Vault SSH: Website page for SSH backend

This commit is contained in:
vishalnayak
2015-08-14 12:41:26 -07:00
parent 52d4c0be9c
commit a98b3befd9
8 changed files with 566 additions and 81 deletions

View File

@@ -19,11 +19,11 @@ func pathConfigLease(b *backend) *framework.Path {
Fields: map[string]*framework.FieldSchema{
"lease": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Default lease for roles.",
Description: "[Required] Default lease for roles.",
},
"lease_max": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Maximum time a credential is valid for.",
Description: "[Required] Maximum time a credential is valid for.",
},
},

View File

@@ -22,15 +22,15 @@ func pathCredsCreate(b *backend) *framework.Path {
Fields: map[string]*framework.FieldSchema{
"role": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Name of the role",
Description: "[Required] Name of the role",
},
"username": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Username in target",
Description: "[Optional] Username in remote host",
},
"ip": &framework.FieldSchema{
Type: framework.TypeString,
Description: "IP of the target machine",
Description: "[Required] IP of the remote host",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{

View File

@@ -19,11 +19,11 @@ func pathKeys(b *backend) *framework.Path {
Fields: map[string]*framework.FieldSchema{
"key_name": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Name of the key",
Description: "[Required] Name of the key",
},
"key": &framework.FieldSchema{
Type: framework.TypeString,
Description: "SSH private key with root privileges for host",
Description: "[Required] SSH private key with super user privileges in host",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
@@ -80,6 +80,10 @@ func (b *backend) pathKeysDelete(req *logical.Request, d *framework.FieldData) (
func (b *backend) pathKeysWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
keyName := d.Get("key_name").(string)
if keyName == "" {
return logical.ErrorResponse("Missing key_name"), nil
}
keyString := d.Get("key").(string)
signer, err := ssh.ParsePrivateKey([]byte(keyString))

View File

@@ -14,7 +14,7 @@ func pathLookup(b *backend) *framework.Path {
Fields: map[string]*framework.FieldSchema{
"ip": &framework.FieldSchema{
Type: framework.TypeString,
Description: "IP address of target",
Description: "[Required] IP address of remote host",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{

View File

@@ -96,7 +96,7 @@ func pathRoles(b *backend) *framework.Path {
[Optional for dynamic type][Not-applicable for otp type]
Script used to install and uninstall public keys in the target machine.
The inbuilt default install script will be for Linux hosts. For sample
script, refer the project's documentation website.`,
script, refer the project documentation website.`,
},
"allowed_users": &framework.FieldSchema{
Type: framework.TypeString,

View File

@@ -12,7 +12,7 @@ func pathVerify(b *backend) *framework.Path {
Fields: map[string]*framework.FieldSchema{
"otp": &framework.FieldSchema{
Type: framework.TypeString,
Description: "One-time-key for SSH session",
Description: "[Required] One-Time-Key that needs to be validated",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{

View File

@@ -144,7 +144,7 @@ func (c *SSHCommand) Run(args []string) int {
}
return 0
}
c.Ui.Output("OTP for the session is" + string(keySecret.Data["key"].(string)))
c.Ui.Output("OTP for the session is " + string(keySecret.Data["key"].(string)))
c.Ui.Output("[Note: Install 'sshpass' to automate typing in OTP]")
}
sshCmdArgs = append(sshCmdArgs, []string{"-p", port}...)

View File

@@ -10,28 +10,44 @@ description: |-
Name: `ssh`
The SSH secret backend for Vault generates SSH credentials dynamically. This solves
the problem of managing private keys of the infrastructure. There are 2 options
available with this backend.
1) Dynamic Type: Registering private keys (having root privileges) with Vault. Vault then issues
leased dynamic credentials to Vault authenticated users. Vault uses the registered
private key to install a new key for the user in the target host. This key will
be a long lived key and gets deleted only after the lease is expired. After the
user receiving the dynamic keys, Vault will have no control on the sessions created
with that key and hence the sessions will not be audited. Which brings us to option 2.
The SSH secret backend for Vault generates SSH credentials dynamically. This backend
increases the security and solves the problem of management and distribution of keys
belonging to remote hosts. This backend provides two ways of credential creation.
Both of them addresses the problem in different ways. Understand both of them and
choose the one which best suits your needs.
2) One-Time-Password (OTP) Type: Installing Vault-SSH agent in the target machines
and enabling challenge response mechanism for client authentication. Vault server
issues a OTP upon user request. During authentication, agent acts as a PAM module
and validates the password with Vault server. Since Vault server is contacted for
every SSH session establishment, they all get audited.
----------------------------------------------------
## I. Dynamic Type
## Quick Start
Register the shared secret key (having super user privileges) with Vault and let
Vault take care of issuing a dynamic secret key every time a client wants to SSH
into the remote host.
When a Vault authenticated client requests for a credential, Vault server creates
a key-pair, uses the previously shared secret key to login to the remote host and
appends the newly generated public key to ~/.ssh/authorized_keys file of the desired
username. Vault uses a install script (configurable) to achieve this.
To run the script without prompts, password requests for sudoers should be disabled at
remote hosts.
File: `/etc/sudoers`
```hcl
%sudo ALL=(ALL)NOPASSWD: ALL
```
The private key returned to the user will be leased and can be renewed if desired.
Once the key is given to the user, Vault has no control on how and when the keys
will be used. Therefore, Vault **WILL NOT** and cannot audit the SSH session establishments.
OTP type audits every SSH request (see below).
### Mounting SSH
`ssh` backend is not mounted by default. So, the first step in using the SSH backend
is to mount it.
```text
```shell
$ vault mount ssh
Successfully mounted 'ssh' at 'ssh'!
```
@@ -39,22 +55,40 @@ Successfully mounted 'ssh' at 'ssh'!
Next, we must register infrastructures with Vault. This is done by writing the role
information. The type of credentials created are determined by the key_type option.
### Dynamic key type
### Registering shared secret key
Create a named key, say "dev_key", in Vault which represents a registered shared key.
Create a named key, say `dev_key`, which represents a registered shared private key.
```text
```shell
$ vault write ssh/keys/dev_key key=@dev_shared_key.pem
```
Assuming that the target machine is hosted on Linux, create a script "key-linux-install.sh"
that can install the given public key in the authorized keys file.
### Create a Role
```text
Create a role, say `dynamic_key_role`. All the machines represented by CIDR block
should be accessible through `dev_key` with root privileges.
```shell
$ vault write ssh/roles/dynamic_key_role key_type=dynamic key=dev_key admin_user=username default_user=username cidr_list=x.x.x.x/y
Success! Data written to: ssh/roles/dynamic_key_role
```
Use the `install_script` option to provide an install script if hosts does not
resemble typical Linux machine. The default script is very straight forward and
is shown below. The script takes three arguments which are explained in the comments.
```shell
# This script file installs or uninstalls an RSA public key to/from authoried_keys
# file in a typical linux machine. This script should be registered with vault
# server while creating a role for key type 'dynamic'.
# $1: "install" or "uninstall"
#
# $2: File name containing public key to be installed. Vault server uses UUID
# as file name to avoid collisions with public keys generated for requests.
#
# $3: Absolute path of the authorized_keys file.
if [ $1 != "install" && $1 != "uninstall" ]; then
exit 1
fi
@@ -64,85 +98,532 @@ fi
grep -vFf $2 $3 > temp_$2
# Contents of temporary file will be the contents of authorized_keys file.
cat temp_$2 > $3
cat temp_$2 | sudo tee $3
if [ $1 == "install" ]; then
# New public key is appended to authorized_keys file
cat $2 >> $3
cat $2 | sudo tee --append $3
fi
# Auxiliary files are deleted
rm -f $2 temp_$2
```
Create a role "dynamic_key_role". All the machines represented by CIDR block
should be accessible through "dev_key" with root privileges.
### Create a credential
```text
$ vault write ssh/roles/dynamic_key_role key_type=dynamic key=dev_key admin_user=foo default_user=bar cidr=x.x.x.x/y install_script=@key-linux-install.sh
```
Create a dynamic key for an IP that belongs to `dynamic_key_role`.
Create a dynamic key for an IP that belongs to the "dynamic_key_role".
```text
```shell
$ vault write ssh/creds/dynamic_key_role ip=x.x.x.x
Key Value
lease_id ssh/creds/dynamic_key_role/862d55c9-e54e-917c-4c8f-f6e1a54b2e51
lease_id ssh/creds/dynamic_key_role/8c4d2042-23bc-d6a8-42c2-6ff01cb83cf8
lease_duration 600
lease_renewable true
key_type dynamic
ip x.x.x.x
key -----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
key_type dynamic
port 22
username username
```
Save the key to a file, say "dyn_key.pem", and then use it to establish an SSH session.
### Establish an SSH session
```text
Save the key to a file, say `dyn_key.pem`, and then use it to establish an SSH session.
```shell
$ ssh -i dyn_key.pem username@ip
username@ip:~$
```
Creating new keys, saving it in a file and establishing an SSH session will all be done
### Automate it!
Creation of new key, saving it in a file and establishing an SSH session will all be done
via a single Vault CLI.
```text
```shell
$ vault ssh -role dynamic_key_role username@ip
username@ip:~$
```
----------------------------------------------------
## II. One-Time-Password (OTP) Type
### OTP key type
Install Vault SSH Agent in remote hosts and let Vault server issue an OTP every time
a client wants to SSH into remote hosts.
Create a role "otp_key_role" of key type "otp". All the machines represented by CIDR
block should have Vault SSH agent installed and challenge response mechanism enabled
as detailed in https://github.com/hashicorp/vault-ssh-agent.
Vault authenticated clients request for a credential from Vault server and get an OTP
issued. When clients try to establish SSH connection with the remote host, OTP typed
in at the password prompt will be received by the Vault agent and gets validated
by the Vault server. Vault server deletes the OTP after validating it once (hence one-time).
```text
$ vault write ssh/roles/otp_key_role key_type=otp default_user=bar cidr=x.x.x.x/y
Since Vault server is contacted for every successful connection establishment, unlike
Dynamic type, every login attempt **WILL** be audited.
Agent in remote hosts act as a client authentication PAM module. See [Vault-SSH-Agent]
(https://github.com/hashicorp/vault-ssh-agent) for configuring agent.
### Mounting SSH
`ssh` backend is not mounted by default and needs to be explicitly mounted. This is
a common step for both OTP and Dynamic types.
```shell
$ vault mount ssh
Successfully mounted 'ssh' at 'ssh'!
```
Create an OTP
### Creating a Role
Create a role, say `otp_key_role` for key type `otp`. All the machines represented
by CIDR block should have agent installed in them and have their SSH configuration
modified to support Vault SSH Agent client authentication.
```shell
$ vault write ssh/roles/otp_key_role key_type=otp default_user=username cidr_list=x.x.x.x/y,m.m.m.m/n
Success! Data written to: ssh/roles/otp_key_role
```
### Create a Credential
Create an OTP credential for an IP that belongs to `otp_key_role`.
```shell
$ vault write ssh/creds/otp_key_role ip=x.x.x.x
Key Value
lease_id ssh/creds/otp_key_role/73bbf513-9606-4bec-816c-5a2f009765a5
lease_duration 600
lease_renewable false
port 22
username username
ip x.x.x.x
key 2f7e25a2-24c9-4b7b-0d35-27d5e5203a5c
key_type otp
```
### Establish an SSH session
```shell
$ ssh username@localhost
Password: <Enter OTP>
username@ip:~$
```
### Automate it!
Creation of new OTP and running SSH command can be done via a single CLI.
```shell
$ vault ssh -role otp_key_role username@x.x.x.x
OTP for the session is `b4d47e1b-4879-5f4e-ce5c-7988d7986f37`
[Note: Install `sshpass` to automate typing in OTP]
Password: <Enter OTP>
```
OTP will be typed in using `sshpass` if it is installed.
```shell
$ vault ssh -role otp_key_role username@x.x.x.x
username@ip:~$
```
----------------------------------------------------
## API
### /ssh/config/lease
#### POST
<dl class="api">
<dt>Description</dt>
<dd>
Configures the lease settings for generated credentials.
This is a root protected endpoint.
</dd>
<dt>Method</dt>
<dd>POST</dd>
<dt>URL</dt>
<dd>`/ssh/config/lease`</dd>
<dt>Parameters</dt>
<dd>
<ul>
<li>
<span class="param">lease</span>
<span class="param-flags">required</span>
(String) The lease value provided as a duration
with time suffix. Hour is the largest suffix.
</li>
<li>
<span class="param">lease_max</span>
<span class="param-flags">required</span>
(String) The maximum lease value provided as a duration
with time suffix. Hour is the largest suffix.
</li>
</ul>
</dd>
<dt>Returns</dt>
<dd>
A `204` response code.
</dd>
</dl>
### /ssh/keys/
#### POST
<dl class="api">
<dt>Description</dt>
<dd>
Creates or updates a named key. This is a root protected endpoint.
</dd>
<dt>Method</dt>
<dd>POST</dd>
<dt>URL</dt>
<dd>`/ssh/keys/<key name>`</dd>
<dt>Parameters</dt>
<dd>
<ul>
<li>
<span class="param">key</span>
<span class="param-flags">required</span>
(String) SSH private key with super user privileges in host
</li>
</ul>
</dd>
<dt>Returns</dt>
<dd>
A `204` response code.
</dd>
#### GET
<dl class="api">
<dt>Description</dt>
<dd>
Queries a named key. This is a root protected endpoint.
</dd>
<dt>Method</dt>
<dd>GET</dd>
<dt>URL</dt>
<dd>`/ssh/keys/<key name>`</dd>
<dt>Parameters</dt>
<dd>None</dd>
<dt>Returns</dt>
<dd>
```javascript
{
"key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAvYvoRcWRxqOim5VZnuM6wHCbLUeiND0yaM1tvOl+Fsrz55DG\nA0OZp4RGAu1Fgr46E1mzxFz1+zY4UbcEExg+u21fpa8YH8sytSWW1FyuD8ICib0A\n/l8slmDMw4BkkGOtSlEqgscpkpv/TWZD1NxJWkPcULk8z6c7TOETn2/H9mL+v2RE\nmbE6NDEwJKfD3MvlpIqCP7idR+86rNBAODjGOGgyUbtFLT+K01XmDRALkV3V/nh+\nGltyjL4c6RU4zG2iRyV5RHlJtkml+UzUMkzr4IQnkCC32CC/wmtoo/IsAprpcHVe\nnkBn3eFQ7uND70p5n6GhN/KOh2j519JFHJyokwIDAQABAoIBAHX7VOvBC3kCN9/x\n+aPdup84OE7Z7MvpX6w+WlUhXVugnmsAAVDczhKoUc/WktLLx2huCGhsmKvyVuH+\nMioUiE+vx75gm3qGx5xbtmOfALVMRLopjCnJYf6EaFA0ZeQ+NwowNW7Lu0PHmAU8\nZ3JiX8IwxTz14DU82buDyewO7v+cEr97AnERe3PUcSTDoUXNaoNxjNpEJkKREY6h\n4hAY676RT/GsRcQ8tqe/rnCqPHNd7JGqL+207FK4tJw7daoBjQyijWuB7K5chSal\noPInylM6b13ASXuOAOT/2uSUBWmFVCZPDCmnZxy2SdnJGbsJAMl7Ma3MUlaGvVI+\nTfh1aQkCgYEA4JlNOabTb3z42wz6mz+Nz3JRwbawD+PJXOk5JsSnV7DtPtfgkK9y\n6FTQdhnozGWShAvJvc+C4QAihs9AlHXoaBY5bEU7R/8UK/pSqwzam+MmxmhVDV7G\nIMQPV0FteoXTaJSikhZ88mETTegI2mik+zleBpVxvfdhE5TR+lq8Br0CgYEA2AwJ\nCUD5CYUSj09PluR0HHqamWOrJkKPFPwa+5eiTTCzfBBxImYZh7nXnWuoviXC0sg2\nAuvCW+uZ48ygv/D8gcz3j1JfbErKZJuV+TotK9rRtNIF5Ub7qysP7UjyI7zCssVM\nkuDd9LfRXaB/qGAHNkcDA8NxmHW3gpln4CFdSY8CgYANs4xwfercHEWaJ1qKagAe\nrZyrMpffAEhicJ/Z65lB0jtG4CiE6w8ZeUMWUVJQVcnwYD+4YpZbX4S7sJ0B8Ydy\nAhkSr86D/92dKTIt2STk6aCN7gNyQ1vW198PtaAWH1/cO2UHgHOy3ZUt5X/Uwxl9\ncex4flln+1Viumts2GgsCQKBgCJH7psgSyPekK5auFdKEr5+Gc/jB8I/Z3K9+g4X\n5nH3G1PBTCJYLw7hRzw8W/8oALzvddqKzEFHphiGXK94Lqjt/A4q1OdbCrhiE68D\nMy21P/dAKB1UYRSs9Y8CNyHCjuZM9jSMJ8vv6vG/SOJPsnVDWVAckAbQDvlTHC9t\nO98zAoGAcbW6uFDkrv0XMCpB9Su3KaNXOR0wzag+WIFQRXCcoTvxVi9iYfUReQPi\noOyBJU/HMVvBfv4g+OVFLVgSwwm6owwsouZ0+D/LasbuHqYyqYqdyPJQYzWA2Y+F\n+B6f4RoPdSXj24JHPg/ioRxjaj094UXJxua2yfkcecGNEuBQHSs=\n-----END RSA PRIVATE KEY-----\n"
}
```
</dd>
#### DELETE
<dl class="api">
<dt>Description</dt>
<dd>
Deletes a named key. This is a root protected endpoint.
</dd>
<dt>Method</dt>
<dd>DELETE</dd>
<dt>URL</dt>
<dd>`/ssh/keys/<key name>`</dd>
<dt>Parameters</dt>
<dd>None</dd>
<dt>Returns</dt>
<dd>
A `204` response code.
</dd>
### /ssh/roles/
#### POST
<dl class="api">
<dt>Description</dt>
<dd>
Creates or updates a named role.
</dd>
<dt>Method</dt>
<dd>POST</dd>
<dt>URL</dt>
<dd>`/ssh/roles/<role name>`</dd>
<dt>Parameters</dt>
<dd>
<ul>
<li>
<span class="param">key</span>
<span class="param-flags">required for dynamic type, NA for otp type</span>
Name of the registered key in Vault. Before creating the role, use the `keys/`
endpoint to create a named key.
</li>
<li>
<span class="param">admin_user</span>
<span class="param-flags">required for dynamic type, NA for otp type</span>
Admin user at remote host. The shared key being registered should be
for this user and should have root privileges. Everytime a dynamic
credential is being generated for other users, Vault uses this admin
username to login to remote host and install the generated credential
for the other user.
</li>
<li>
<span class="param">default_user</span>
<span class="param-flags">required for both types</span>
Default username for which a credential will be generated.
When the endpoint 'creds/' is used without a username, this
value will be used as default username.
</li>
<li>
<span class="param">cidr_list</span>
<span class="param-flags">required for both types</span>
Comma separated list of CIDR blocks for which the role is applicable for.
CIDR blocks can belong to more than one role.
</li>
<li>
<span class="param">port</span>
<span class="param-flags">optional for both types</span>
Port number for SSH connection. Default is '22'. Port number does not
play any role in creation of OTP. For 'otp' type, this is just a way
to inform client about the port number to use. Port number will be
returned to client by Vault server along with OTP.
</li>
<li>
<span class="param">key_type</span>
<span class="param-flags">required for both types</span>
Type of key used to login to hosts. It can be either `otp` or `dynamic`.
`otp` type requires agent to be installed in remote hosts.
</li>
<li>
<span class="param">key_bits</span>
<span class="param-flags">optional for dynamic type, NA for otp type</span>
Length of the RSA dynamic key in bits. It can be one of 1024, 2048 or 4096.
</li>
<li>
<span class="param">install_script</span>
<span class="param-flags">optional for dynamic type, NA for otp type</span>
Script used to install and uninstall public keys in the target machine.
The inbuilt default install script will be for Linux hosts.
</li>
<li>
<span class="param">allowed_users</span>
<span class="param-flags">optional for both types</span>
If this option is not specified, client can request for a credential for
any valid user at the remote host, including the admin user. If only certain
usernames are to be allowed, then this list enforces it. If this field is
set, then credentials can only be created for default_user and usernames
present in this list.
</li>
</ul>
</dd>
<dt>Returns</dt>
<dd>
A `204` response code.
</dd>
#### GET
<dl class="api">
<dt>Description</dt>
<dd>
Queries a named role.
</dd>
<dt>Method</dt>
<dd>GET</dd>
<dt>URL</dt>
<dd>`/ssh/roles/<role name>`</dd>
<dt>Parameters</dt>
<dd>None</dd>
<dt>Returns</dt>
<dd>For dynamic role:
```json
{
"admin_user": "username",
"cidr_list": "x.x.x.x/y",
"default_user": "username",
"key": "<key name>",
"key_type": "dynamic",
"port": 22
}
```
</dd>
<dd>For OTP role:
```json
{
"cidr_list": "x.x.x.x/y",
"default_user": "username",
"key_type": "otp",
"port": 22
}
```
</dd>
#### DELETE
<dl class="api">
<dt>Description</dt>
<dd>
Deletes a named role.
</dd>
<dt>Method</dt>
<dd>DELETE</dd>
<dt>URL</dt>
<dd>`/ssh/roles/<role name>`</dd>
<dt>Parameters</dt>
<dd>None</dd>
<dt>Returns</dt>
<dd>
A `204` response code.
</dd>
### /ssh/creds/
#### POST
<dl class="api">
<dt>Description</dt>
<dd>
Creates a credential for a specific username and IP under the given role.
</dd>
<dt>Method</dt>
<dd>POST</dd>
<dt>URL</dt>
<dd>`/ssh/creds/<role name>`</dd>
<dt>Parameters</dt>
<dd>
<ul>
<li>
<span class="param">username</span>
<span class="param-flags">optional</span>
Username in remote host.
</li>
<li>
<span class="param">ip</span>
<span class="param-flags">required</span>
IP of the remote host.
</li>
</ul>
</dd>
<dt>Returns</dt>
<dd>
A `204` response code.
</dd>
### /ssh/lookup
#### POST
<dl class="api">
<dt>Description</dt>
<dd>
Lists all the roles given IP is associated with.
</dd>
<dt>Method</dt>
<dd>POST</dd>
<dt>URL</dt>
<dd>`/ssh/lookup`</dd>
<dt>Parameters</dt>
<dd>
<ul>
<li>
<span class="param">ip</span>
<span class="param-flags">required</span>
IP of the remote host.
</li>
</ul>
</dd>
<dt>Returns</dt>
<dd>
A `204` response code.
</dd>
### /ssh/verify
#### POST
<dl class="api">
<dt>Description</dt>
<dd>
Verifies if the given OTP is valid. This is an unauthenticated endpoint.
</dd>
<dt>Method</dt>
<dd>POST</dd>
<dt>URL</dt>
<dd>`/ssh/verify`</dd>
<dt>Parameters</dt>
<dd>
<ul>
<li>
<span class="param">otp</span>
<span class="param-flags">required</span>
One-Time-Key that needs to be validated.
</li>
</ul>
</dd>
<dt>Returns</dt>
<dd>
A `204` response code.
</dd>