mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 11:38:02 +00:00
Enhance SSH backend documentation; remove getting of stored keys and have TTLs honor backends systemview values
This commit is contained in:
@@ -23,7 +23,7 @@ func Factory(conf *logical.BackendConfig) (logical.Backend, error) {
|
||||
|
||||
func Backend(conf *logical.BackendConfig) (*framework.Backend, error) {
|
||||
salt, err := salt.NewSalt(conf.StorageView, &salt.Config{
|
||||
HashFunc: salt.SHA1Hash,
|
||||
HashFunc: salt.SHA256Hash,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -45,7 +45,6 @@ func Backend(conf *logical.BackendConfig) (*framework.Backend, error) {
|
||||
},
|
||||
|
||||
Paths: []*framework.Path{
|
||||
pathConfigLease(&b),
|
||||
pathConfigZeroAddress(&b),
|
||||
pathKeys(&b),
|
||||
pathRoles(&b),
|
||||
@@ -63,30 +62,18 @@ func Backend(conf *logical.BackendConfig) (*framework.Backend, error) {
|
||||
}
|
||||
|
||||
const backendHelp = `
|
||||
The SSH backend generates credentials to establish SSH connection with remote hosts.
|
||||
There are two types of credentials that could be generated: Dynamic and OTP. The
|
||||
desired way of key creation should be chosen by using 'key_type' parameter of 'roles/'
|
||||
endpoint. When a credential is requested for a particular role, Vault will generate
|
||||
a credential accordingly and issue it.
|
||||
The SSH backend generates credentials allowing clients to establish SSH
|
||||
connections to remote hosts.
|
||||
|
||||
Dynamic Key: is a RSA private key which can be used to establish SSH session using
|
||||
publickey authentication. When the client receives a key and uses it to establish
|
||||
connections with hosts, Vault server will have no way to know when and how many
|
||||
times the key will be used. So, these login attempts will not be audited by Vault.
|
||||
To create a dynamic credential, Vault will use the shared private key registered
|
||||
with the role. Named key should be created using 'keys/' endpoint and used with
|
||||
'roles/' endpoint for Vault to know the shared key to use for installing the newly
|
||||
generated key. Since Vault uses the shared key to install keys for other usernames,
|
||||
shared key should have sudoer privileges in remote hosts and password prompts for
|
||||
sudoers should be disabled. Also, dynamic keys are leased keys and gets revoked
|
||||
in remote hosts by Vault after the expiry.
|
||||
There are two variants of the backend, which generate different types of
|
||||
credentials: dynamic keys and One-Time Passwords (OTPs). The desired behavior
|
||||
is role-specific and chosen at role creation time with the 'key_type'
|
||||
parameter.
|
||||
|
||||
OTP Key: is a UUID which can be used to login using keyboard-interactive authentication.
|
||||
All the hosts that intend to support OTP should have Vault SSH Agent installed in
|
||||
them. This agent will receive the OTP from client and get it validated by Vault server.
|
||||
And since Vault server has a role to play for each successful connection, all the
|
||||
events will be audited. Vault server validates a key only once, hence it is a OTP.
|
||||
Please see the backend documentation for a thorough description of both
|
||||
types. The Vault team strongly recommends the OTP type.
|
||||
|
||||
After mounting this backend, before generating the keys, configure the lease using
|
||||
'congig/lease' endpoint and create roles using 'roles/' endpoint.
|
||||
After mounting this backend, before generating credentials, configure the
|
||||
backend's lease behavior using the 'config/lease' endpoint and create roles
|
||||
using the 'roles/' endpoint.
|
||||
`
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
@@ -54,6 +55,19 @@ oOyBJU/HMVvBfv4g+OVFLVgSwwm6owwsouZ0+D/LasbuHqYyqYqdyPJQYzWA2Y+F
|
||||
`
|
||||
)
|
||||
|
||||
func testingFactory(conf *logical.BackendConfig) (logical.Backend, error) {
|
||||
defaultLeaseTTLVal := 2 * time.Minute
|
||||
maxLeaseTTLVal := 10 * time.Minute
|
||||
return Factory(&logical.BackendConfig{
|
||||
Logger: nil,
|
||||
StorageView: &logical.InmemStorage{},
|
||||
System: &logical.StaticSystemView{
|
||||
DefaultLeaseTTLVal: defaultLeaseTTLVal,
|
||||
MaxLeaseTTLVal: maxLeaseTTLVal,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
var testIP string
|
||||
|
||||
var testUserName string
|
||||
@@ -101,7 +115,7 @@ func TestSSHBackend_Lookup(t *testing.T) {
|
||||
resp3 := []string{testDynamicRoleName, testOTPRoleName}
|
||||
resp4 := []string{testDynamicRoleName}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Factory: Factory,
|
||||
Factory: testingFactory,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testLookupRead(t, data, resp1),
|
||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||
@@ -123,7 +137,7 @@ func TestSSHBackend_DynamicKeyCreate(t *testing.T) {
|
||||
"ip": testIP,
|
||||
}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Factory: Factory,
|
||||
Factory: testingFactory,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||
testRoleWrite(t, testDynamicRoleName, testDynamicRoleData),
|
||||
@@ -140,7 +154,7 @@ func TestSSHBackend_OTPRoleCrud(t *testing.T) {
|
||||
"cidr_list": testCIDRList,
|
||||
}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Factory: Factory,
|
||||
Factory: testingFactory,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||
testRoleRead(t, testOTPRoleName, respOTPRoleData),
|
||||
@@ -162,7 +176,7 @@ func TestSSHBackend_DynamicRoleCrud(t *testing.T) {
|
||||
"key_type": testDynamicKeyType,
|
||||
}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Factory: Factory,
|
||||
Factory: testingFactory,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||
testRoleWrite(t, testDynamicRoleName, testDynamicRoleData),
|
||||
@@ -175,11 +189,9 @@ func TestSSHBackend_DynamicRoleCrud(t *testing.T) {
|
||||
|
||||
func TestSSHBackend_NamedKeysCrud(t *testing.T) {
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Factory: Factory,
|
||||
Factory: testingFactory,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testNamedKeysRead(t, ""),
|
||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||
testNamedKeysRead(t, testSharedPrivateKey),
|
||||
testNamedKeysDelete(t),
|
||||
},
|
||||
})
|
||||
@@ -191,7 +203,7 @@ func TestSSHBackend_OTPCreate(t *testing.T) {
|
||||
"ip": testIP,
|
||||
}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Factory: Factory,
|
||||
Factory: testingFactory,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||
testCredsWrite(t, testOTPRoleName, data, false),
|
||||
@@ -207,7 +219,7 @@ func TestSSHBackend_VerifyEcho(t *testing.T) {
|
||||
"message": api.VerifyEchoResponse,
|
||||
}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Factory: Factory,
|
||||
Factory: testingFactory,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testVerifyWrite(t, verifyData, expectedData),
|
||||
},
|
||||
@@ -232,7 +244,7 @@ func TestSSHBackend_ConfigZeroAddressCRUD(t *testing.T) {
|
||||
}
|
||||
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Factory: Factory,
|
||||
Factory: testingFactory,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||
testConfigZeroAddressWrite(t, req1),
|
||||
@@ -272,7 +284,7 @@ func TestSSHBackend_CredsForZeroAddressRoles(t *testing.T) {
|
||||
"roles": fmt.Sprintf("%s,%s", testOTPRoleName, testDynamicRoleName),
|
||||
}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Factory: Factory,
|
||||
Factory: testingFactory,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testRoleWrite(t, testOTPRoleName, otpRoleData),
|
||||
testCredsWrite(t, testOTPRoleName, data, true),
|
||||
@@ -352,31 +364,6 @@ func testVerifyWrite(t *testing.T, data map[string]interface{}, expected map[str
|
||||
}
|
||||
}
|
||||
|
||||
func testNamedKeysRead(t *testing.T, key string) logicaltest.TestStep {
|
||||
return logicaltest.TestStep{
|
||||
Operation: logical.ReadOperation,
|
||||
Path: fmt.Sprintf("keys/%s", testKeyName),
|
||||
Check: func(resp *logical.Response) error {
|
||||
if key != "" {
|
||||
if resp == nil || resp.Data == nil {
|
||||
return fmt.Errorf("Key missing in response")
|
||||
}
|
||||
var d struct {
|
||||
Key string `mapstructure:"key"`
|
||||
}
|
||||
if err := mapstructure.Decode(resp.Data, &d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.Key != key {
|
||||
return fmt.Errorf("Key mismatch")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func testNamedKeysWrite(t *testing.T, name, key string) logicaltest.TestStep {
|
||||
return logicaltest.TestStep{
|
||||
Operation: logical.WriteOperation,
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
)
|
||||
|
||||
type configLease struct {
|
||||
Lease time.Duration
|
||||
LeaseMax time.Duration
|
||||
}
|
||||
|
||||
func pathConfigLease(b *backend) *framework.Path {
|
||||
return &framework.Path{
|
||||
Pattern: "config/lease",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"lease": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: "[Required] Default lease for roles.",
|
||||
},
|
||||
"lease_max": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: "[Required] Maximum time a credential is valid for.",
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.WriteOperation: b.pathConfigLeaseWrite,
|
||||
},
|
||||
|
||||
HelpSynopsis: pathConfigLeaseHelpSyn,
|
||||
HelpDescription: pathConfigLeaseHelpDesc,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *backend) pathConfigLeaseWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
leaseRaw := d.Get("lease").(string)
|
||||
if leaseRaw == "" {
|
||||
return logical.ErrorResponse("Missing lease"), nil
|
||||
}
|
||||
|
||||
leaseMaxRaw := d.Get("lease_max").(string)
|
||||
if leaseMaxRaw == "" {
|
||||
return logical.ErrorResponse("Missing lease_max"), nil
|
||||
}
|
||||
|
||||
lease, err := time.ParseDuration(leaseRaw)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf(
|
||||
"Invalid 'lease': %s", err)), nil
|
||||
}
|
||||
|
||||
leaseMax, err := time.ParseDuration(leaseMaxRaw)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf(
|
||||
"Invalid 'lease_max': %s", err)), nil
|
||||
}
|
||||
|
||||
entry, err := logical.StorageEntryJSON("config/lease", &configLease{
|
||||
Lease: lease,
|
||||
LeaseMax: leaseMax,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create storage entry JSON: %s", err)
|
||||
}
|
||||
|
||||
if err := req.Storage.Put(entry); err != nil {
|
||||
return nil, fmt.Errorf("could not store JSON: %s", err)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
||||
entry, err := s.Get("config/lease")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if entry == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var result configLease
|
||||
if err := entry.DecodeJSON(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
const pathConfigLeaseHelpSyn = `
|
||||
Configure the default lease information for SSH dynamic keys.
|
||||
`
|
||||
|
||||
const pathConfigLeaseHelpDesc = `
|
||||
This configures the default lease information used for SSH keys generated by
|
||||
this backend. The lease specifies the duration that a credential will be valid
|
||||
for, as well as the maximum session for a set of credentials.
|
||||
|
||||
The format for the lease is "1h" or integer and then unit. The longest
|
||||
unit is hour.
|
||||
`
|
||||
@@ -157,20 +157,8 @@ func (b *backend) pathCredsCreateWrite(
|
||||
return nil, fmt.Errorf("key type unknown")
|
||||
}
|
||||
|
||||
// Change the lease information to reflect user's choice
|
||||
lease, _ := b.Lease(req.Storage)
|
||||
|
||||
// If the lease information is set, update it in secret.
|
||||
if lease != nil {
|
||||
result.Secret.TTL = lease.Lease
|
||||
result.Secret.GracePeriod = lease.LeaseMax
|
||||
}
|
||||
|
||||
// If lease information is not set, set it to 10 minutes.
|
||||
if lease == nil {
|
||||
result.Secret.TTL = 10 * time.Minute
|
||||
result.Secret.GracePeriod = 2 * time.Minute
|
||||
}
|
||||
result.Secret.TTL = b.System().DefaultLeaseTTL()
|
||||
result.Secret.GracePeriod = 2 * time.Minute
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ func pathKeys(b *backend) *framework.Path {
|
||||
},
|
||||
},
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.ReadOperation: b.pathKeysRead,
|
||||
logical.WriteOperation: b.pathKeysWrite,
|
||||
logical.DeleteOperation: b.pathKeysDelete,
|
||||
},
|
||||
@@ -52,22 +51,6 @@ func (b *backend) getKey(s logical.Storage, n string) (*sshHostKey, error) {
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (b *backend) pathKeysRead(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
key, err := b.getKey(req.Storage, d.Get("key_name").(string))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if key == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"key": key.Key,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *backend) pathKeysDelete(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
keyName := d.Get("key_name").(string)
|
||||
keyPath := fmt.Sprintf("keys/%s", keyName)
|
||||
@@ -120,7 +103,7 @@ Vault uses this key to install and uninstall dynamic keys in remote hosts. This
|
||||
key should have sudoer privileges in remote hosts. This enables installing keys
|
||||
for unprivileged usernames.
|
||||
|
||||
If this backend is mounted as "ssh", then the endpoint for registering shared key
|
||||
is "ssh/keys/webrack", if "webrack" is the user coined name for the key. The name
|
||||
given here can be associated with any number of roles via the endpoint "ssh/roles/".
|
||||
If this backend is mounted as "ssh", then the endpoint for registering shared
|
||||
key is "ssh/keys/<name>". The name given here can be associated with any number
|
||||
of roles via the endpoint "ssh/roles/".
|
||||
`
|
||||
|
||||
@@ -23,7 +23,7 @@ func secretDynamicKey(b *backend) *framework.Secret {
|
||||
Description: "IP address of host",
|
||||
},
|
||||
},
|
||||
DefaultDuration: 10 * time.Minute,
|
||||
DefaultDuration: 0, // this will use sysview's value
|
||||
DefaultGracePeriod: 2 * time.Minute,
|
||||
Renew: b.secretDynamicKeyRenew,
|
||||
Revoke: b.secretDynamicKeyRevoke,
|
||||
@@ -31,14 +31,7 @@ func secretDynamicKey(b *backend) *framework.Secret {
|
||||
}
|
||||
|
||||
func (b *backend) secretDynamicKeyRenew(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
lease, err := b.Lease(req.Storage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if lease == nil {
|
||||
lease = &configLease{Lease: 1 * time.Hour}
|
||||
}
|
||||
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, false)
|
||||
f := framework.LeaseExtend(b.System().DefaultLeaseTTL(), b.System().MaxLeaseTTL(), false)
|
||||
return f(req, d)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ func secretOTP(b *backend) *framework.Secret {
|
||||
Description: "One time password",
|
||||
},
|
||||
},
|
||||
DefaultDuration: 10 * time.Minute,
|
||||
DefaultDuration: 0, // this will use sysview's value
|
||||
DefaultGracePeriod: 2 * time.Minute,
|
||||
Revoke: b.secretOTPRevoke,
|
||||
}
|
||||
|
||||
@@ -61,10 +61,37 @@ employees actively contribute to Vault.
|
||||
<a href="https://www.serfdom.io">Serf</a>,
|
||||
<a href="https://www.terraform.io">Terraform</a>,
|
||||
<a href="https://github.com/armon/statsite">Statsite</a>, and
|
||||
<a href="https://github.com/armon/bloomd">Bloomd</a>.
|
||||
</p>
|
||||
<a href="https://github.com/armon/bloomd">Bloomd</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="person">
|
||||
<img class="pull-left" src="https://s.gravatar.com/avatar/b32bf8e58ce1929d2d676a353c88f539.png?s=125">
|
||||
<div class="bio">
|
||||
<h3>Jeff Mitchell (<a href="https://github.com/jefferai">@jefferai</a>)</h3>
|
||||
<p>
|
||||
Jeff Mitchell is a core contributor to Vault. He works on all layers of
|
||||
Vault, from the core to backends. Jeff is an employee of HashiCorp and
|
||||
has also contributed to
|
||||
<a href="https://www.consul.io">Consul</a> and
|
||||
<a href="https://www.terraform.io">Terraform</a>,
|
||||
as well as many other open-source projects.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="person">
|
||||
<img class="pull-left" src="https://s.gravatar.com/avatar/824b1038ad73d555cf26ef6096bd46ce.png?s=125">
|
||||
<div class="bio">
|
||||
<h3>Vishal Nayak (<a href="https://github.com/vishalnayak">@vishalnayak</a>)</h3>
|
||||
<p>
|
||||
Vishal Nayak is a contributor to Vault. He works on all layers of Vault,
|
||||
from the core to backends. Vishal is currently finishing his Master's
|
||||
degree, after which he will be joining full-time.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="person">
|
||||
<img class="pull-left" src="http://www.gravatar.com/avatar/2acc31dd6370a54b18f6755cd0710ce6.png?s=125">
|
||||
@@ -81,7 +108,7 @@ employees actively contribute to Vault.
|
||||
<a href="https://www.terraform.io">Terraform</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
@@ -3,128 +3,214 @@ layout: "docs"
|
||||
page_title: "Secret Backend: SSH"
|
||||
sidebar_current: "docs-secrets-ssh"
|
||||
description: |-
|
||||
The SSH secret backend for Vault generates dynamic SSH keys or One-Time-Passwords.
|
||||
The SSH secret backend for Vault generates dynamic SSH keys or One-Time-Passwords.
|
||||
---
|
||||
|
||||
# SSH Secret Backend
|
||||
|
||||
Name: `ssh`
|
||||
|
||||
Vault SSH backend generates SSH credentials for remote hosts dynamically. This
|
||||
backend increases the security by removing the need to share the private key to
|
||||
everyone who needs access to infrastructures. It also solves the problem of
|
||||
management and distribution of keys belonging to remote hosts.
|
||||
Vault SSH backend dynamically generates SSH credentials for remote hosts. This
|
||||
increases security by removing the need to share private keys with all users
|
||||
needing access to infrastructure. It also solves the problem of management and distribution of keys belonging to remote hosts.
|
||||
|
||||
This backend supports two types of credential creation: Dynamic and OTP. Both of
|
||||
them addresses the problems in different ways.
|
||||
This backend supports two types of credential creation: Dynamic Key and
|
||||
One-Time Password (OTP), which address these problems in different ways.
|
||||
|
||||
Read and carefully understand both of them and choose the one which best suits
|
||||
your needs.
|
||||
Read and carefully understand both of them before choosing the one which best
|
||||
suits your needs. The Vault team strongly recommends the OTP type whenever
|
||||
possible, and the drawbacks to the dynamic key type should be carefully considered
|
||||
before choosing it.
|
||||
|
||||
This page will show a quick start for this backend. For detailed documentation
|
||||
on every path, use `vault path-help` after mounting the backend.
|
||||
|
||||
----------------------------------------------------
|
||||
## I. Dynamic Type
|
||||
|
||||
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 dynamic 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 for
|
||||
the desired username. Vault uses an install script (configurable) to achieve this.
|
||||
To run this script in super user mode without password prompts, `NOPASSWD` option
|
||||
for sudoers should be enabled at all 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 will not know when it gets used or how many
|
||||
time it gets used. Therefore, Vault **WILL NOT** and cannot audit the SSH session
|
||||
establishments. An alternative is to use OTP type, which 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.
|
||||
The `ssh` backend is not mounted by default and needs to be explicitly mounted.
|
||||
This is a common step for both OTP and Dynamic Key types.
|
||||
|
||||
```shell
|
||||
$ vault mount ssh
|
||||
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.
|
||||
To do this, first create a named key and then create a role.
|
||||
----------------------------------------------------
|
||||
## I. One-Time-Password (OTP) Type
|
||||
|
||||
### Registering shared secret key
|
||||
This backend type allows a Vault server to issue an OTP every time a client
|
||||
wants to SSH into a remote host, using a helper command on the remote host to
|
||||
perform verification through a helper command.
|
||||
|
||||
Create a named key, say `dev_key`, which represents a registered shared private key.
|
||||
Remember that this key should be of admin user with super user privileges.
|
||||
An authenticated client requests credentials from the Vault server and, if
|
||||
authorized, is issued an OTP. When the client establishes an SSH connection
|
||||
to the desired remote host, the OTP used during SSH authentication is received
|
||||
by the Vault helper, which then validates the OTP with the Vault server. The
|
||||
Vault server then deletes this OTP, ensuring that it is only used once.
|
||||
|
||||
Since the Vault server is contacted during SSH connection establishment, every
|
||||
login attempt and the correlating Vault lease information is logged to the
|
||||
audit backend.
|
||||
|
||||
See [Vault-SSH-Helper](https://github.com/hashicorp/vault-ssh-helper) for
|
||||
details on the helper.
|
||||
|
||||
### Drawbacks
|
||||
|
||||
The main concern with the OTP backend type is the remote host's connection to
|
||||
Vault; if compromised, an attacker could spoof the Vault server returning
|
||||
a successful request. This risk can be mitigated by using TLS for the
|
||||
connection to Vault and checking certificate validity; future enhancements to
|
||||
this backend may address this problem in a more concrete way.
|
||||
|
||||
### Creating a Role
|
||||
|
||||
Create a role with the `key_type` parameter set to `otp`. All of the machines
|
||||
represented by the role's CIDR list should have helper properly installed and
|
||||
configured.
|
||||
|
||||
```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!
|
||||
|
||||
A single CLI command can be used to create a new OTP and invoke SSH with the
|
||||
correct paramters to connect to the host.
|
||||
|
||||
```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>
|
||||
```
|
||||
|
||||
The OTP will be entered automatically using `sshpass` if it is installed.
|
||||
|
||||
```shell
|
||||
$ vault ssh -role otp_key_role username@x.x.x.x
|
||||
username@ip:~$
|
||||
```
|
||||
|
||||
----------------------------------------------------
|
||||
## II. Dynamic Key Type
|
||||
|
||||
When using this type, the administrator registers a secret key with appropriate
|
||||
`sudo` privileges on the remote machines; for every authorized credential
|
||||
request, Vault creates a new SSH key pair and appends the newly-generated
|
||||
public key to the `authorized_keys` file for the configured username on the
|
||||
remote host. Vault uses a configurable install script to achieve this.
|
||||
|
||||
The backend does not prompt for `sudo` passwords; the `NOPASSWD` option
|
||||
for sudoers should be enabled at all remote hosts for the Vault administrative
|
||||
user.
|
||||
|
||||
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 will not know when it gets
|
||||
used or how many time it gets used. Therefore, Vault **WILL NOT** and cannot
|
||||
audit the SSH session establishments.
|
||||
|
||||
When the credential lease expires, Vault removes the secret key from the remote
|
||||
machine.
|
||||
|
||||
### Drawbacks
|
||||
|
||||
The dynamic key type has several serious drawbacks:
|
||||
|
||||
1. _Audit logs are unreliable_: Vault can only log when users request
|
||||
credentials, not when they use the given keys. If user A and user B both
|
||||
request access to a machine, and are given a lease valid for five minutes,
|
||||
it is impossible to know whether two accesses to that user account on the
|
||||
remote machine were A, A; A, B; B, A; or B, B.
|
||||
2. _Generating dynamic keys consumes entropy_: Unless equipped with a hardware
|
||||
entropy generating device, a machine can quickly run out of entropy when
|
||||
generating SSH keys. This will cause further requests for various Vault
|
||||
operations to stall until more entropy is available, which could take a
|
||||
significant amount of time, after which the next request for a new SSH key
|
||||
will use the generated entropy and cause stalling again.
|
||||
|
||||
Because of these drawbacks, the Vault team recommends use of the OTP type
|
||||
whenever possible. Care should be taken with respect to the above issues with
|
||||
any deployments using the dynamic key type.
|
||||
|
||||
### sudo
|
||||
|
||||
In order to adjust the `authorized_keys` file for the desired user, Vault
|
||||
connects via SSH to the remote machine as a separate user, and uses `sudo` to
|
||||
gain the privileges required. An example `sudoers` file is shown below.
|
||||
|
||||
File: `/etc/sudoers`
|
||||
|
||||
```hcl
|
||||
# This is a sample sudoers statement; you should modify it
|
||||
# as appropriate to satisfy your security needs.
|
||||
vaultadmin ALL=(ALL)NOPASSWD: ALL
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
Next, infrastructure configuration must be registered with Vault via roles.
|
||||
First, however, the shared secret key must be specified.
|
||||
|
||||
#### Registering the shared secret key
|
||||
|
||||
Register a key with a name; this key must have administrative capabilities
|
||||
on the remote hosts.
|
||||
|
||||
```shell
|
||||
$ vault write ssh/keys/dev_key key=@dev_shared_key.pem
|
||||
```
|
||||
|
||||
### Create a Role
|
||||
#### Create a Role
|
||||
|
||||
Create a role, say `dynamic_key_role`. All the machines represented by CIDR block
|
||||
should be accessible through `dev_key` with root privileges.
|
||||
Next, create a role. All of the machines contained within this CIDR block list
|
||||
should be accessible using the registered shared secret key.
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
Option `cidr_list` is optional and defaults to zero-address (0.0.0.0/0).
|
||||
`cidr_list` is optional and defaults to the zero address (0.0.0.0/0), e.g. all
|
||||
hosts.
|
||||
|
||||
Use the `install_script` option to provide an install script if hosts does not
|
||||
resemble typical Linux machine. The default script is compiled into the binary.
|
||||
It is straight forward and is shown below. The script takes three arguments which
|
||||
are explained in the comments.
|
||||
Use the `install_script` option to provide an install script if the remote
|
||||
hosts do not resemble a typical Linux machine. The default script is compiled
|
||||
into the Vault binary, but it is straight forward to specify an alternate.
|
||||
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
|
||||
|
||||
# If the key being installed is already present in the authorized_keys file, it is
|
||||
# removed and the result is stored in a temporary file.
|
||||
grep -vFf $2 $3 > temp_$2
|
||||
|
||||
# Contents of temporary file will be the contents of authorized_keys file.
|
||||
cat temp_$2 | sudo tee $3
|
||||
|
||||
if [ $1 == "install" ]; then
|
||||
# New public key is appended to authorized_keys file
|
||||
cat $2 | sudo tee --append $3
|
||||
fi
|
||||
|
||||
# Auxiliary files are deleted
|
||||
rm -f $2 temp_$2
|
||||
```
|
||||
To see the default, see [linux_install_script.go](https://github.com/hashicorp/vault/blob/master/builtin/logical/ssh/linux_install_script.go)
|
||||
|
||||
### Create a credential
|
||||
|
||||
Create a dynamic key for an IP that belongs to `dynamic_key_role`.
|
||||
Create a dynamic key for an IP that is covered by `dynamic_key_role`'s CIDR
|
||||
list.
|
||||
|
||||
```shell
|
||||
$ vault write ssh/creds/dynamic_key_role ip=x.x.x.x
|
||||
@@ -167,7 +253,8 @@ username username
|
||||
|
||||
### Establish an SSH session
|
||||
|
||||
Save the key to a file, say `dyn_key.pem`, and then use it to establish an SSH session.
|
||||
Save the key to a file (e.g. `dyn_key.pem`) and then use it to establish an
|
||||
SSH session.
|
||||
|
||||
```shell
|
||||
$ ssh -i dyn_key.pem username@ip
|
||||
@@ -176,139 +263,17 @@ username@ip:~$
|
||||
|
||||
### 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.
|
||||
Creation of new key, saving to a file, and using it to establish an SSH session
|
||||
can all be done with a single Vault CLI command.
|
||||
|
||||
```shell
|
||||
$ vault ssh -role dynamic_key_role username@ip
|
||||
username@ip:~$
|
||||
```
|
||||
|
||||
----------------------------------------------------
|
||||
## II. One-Time-Password (OTP) 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.
|
||||
|
||||
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).
|
||||
|
||||
Since Vault server is contacted for every successful connection establishment, unlike
|
||||
Dynamic type, every login attempt **WILL** be audited.
|
||||
|
||||
See [Vault-SSH-Agent](https://github.com/hashicorp/vault-ssh-agent) for details
|
||||
on how to configure the 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'!
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
@@ -331,7 +296,7 @@ username@ip:~$
|
||||
<span class="param">key</span>
|
||||
<span class="param-flags">required</span>
|
||||
(String)
|
||||
SSH private key with super user privileges in host
|
||||
SSH private key with appropriate privileges on remote hosts.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
@@ -341,35 +306,7 @@ username@ip:~$
|
||||
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
|
||||
#### DELETE
|
||||
|
||||
<dl class="api">
|
||||
<dt>Description</dt>
|
||||
@@ -411,90 +348,95 @@ username@ip:~$
|
||||
<ul>
|
||||
<li>
|
||||
<span class="param">key</span>
|
||||
<span class="param-flags">required for Dynamic type, NA for OTP type</span>
|
||||
(String)
|
||||
<span class="param-flags">required for Dynamic Key type, N/A for
|
||||
OTP type</span>
|
||||
(String)
|
||||
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>
|
||||
(String)
|
||||
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.
|
||||
<span class="param-flags">required for Dynamic Key type, N/A for OTP
|
||||
type</span>
|
||||
(String)
|
||||
Admin user at remote host. The shared key being registered should
|
||||
be for this user and should have root or sudo privileges. Every
|
||||
time a dynamic credential is generated for a client,
|
||||
Vault uses this admin username to login to remote host and install
|
||||
the generated credential.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">default_user</span>
|
||||
<span class="param-flags">required for both types</span>
|
||||
(String)
|
||||
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.
|
||||
(String)
|
||||
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">optional for both types</span>
|
||||
(String)
|
||||
Comma separated list of CIDR blocks for which the role is applicable for.
|
||||
CIDR blocks can belong to more than one role. Defaults to zero-address (0.0.0.0/0).
|
||||
(String)
|
||||
Comma separated list of CIDR blocks for which the role is
|
||||
applicable for. CIDR blocks can belong to more than one role.
|
||||
Defaults to the zero address (0.0.0.0/0).
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">exclude_cidr_list</span>
|
||||
<span class="param-flags">optional for both types</span>
|
||||
(String)
|
||||
Comma separated list of CIDR blocks. IP addresses belonging to these blocks are not
|
||||
accepted by the role. This is particularly useful when big CIDR blocks are being used
|
||||
by the role and certain parts of it needs to be kept out.
|
||||
(String)
|
||||
Comma-separated list of CIDR blocks. IP addresses belonging to
|
||||
these blocks are not accepted by the role. This is particularly
|
||||
useful when big CIDR blocks are being used by the role and certain
|
||||
parts need to be kept out.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">port</span>
|
||||
<span class="param-flags">optional for both types</span>
|
||||
(Integer)
|
||||
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.
|
||||
(Integer)
|
||||
Port number for SSH connection. The default is '22'. Port number
|
||||
does not play any role in OTP generation. For the 'otp' backend
|
||||
type, this is just a way to inform the client about the port number
|
||||
to use. The port number will be returned to the client by Vault
|
||||
along with the OTP.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">key_type</span>
|
||||
<span class="param-flags">required for both types</span>
|
||||
(String)
|
||||
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.
|
||||
(String)
|
||||
Type of credentials generated by this role. Can be either `otp` or
|
||||
`dynamic`.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">key_bits</span>
|
||||
<span class="param-flags">optional for Dynamic type, NA for OTP type</span>
|
||||
(Integer)
|
||||
Length of the RSA dynamic key in bits. It is 1024 by default or it can be 2048.
|
||||
<span class="param-flags">optional for Dynamic Key type, N/A for OTP type</span>
|
||||
(Integer)
|
||||
Length of the RSA dynamic key in bits; can be either 1024 or 2048.
|
||||
1024 the default.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">install_script</span>
|
||||
<span class="param-flags">optional for Dynamic type, NA for OTP type</span>
|
||||
(String)
|
||||
Script used to install and uninstall public keys in the target machine.
|
||||
The inbuilt default install script will be for Linux hosts.
|
||||
<span class="param-flags">optional for Dynamic Key type, N/A for OTP type</span>
|
||||
(String)
|
||||
Script used to install and uninstall public keys in the target
|
||||
machine. Defaults to the built-in script.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">allowed_users</span>
|
||||
<span class="param-flags">optional for both types</span>
|
||||
(String)
|
||||
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.
|
||||
(String)
|
||||
If this option is not specified, a client can request credentials
|
||||
to log into any valid user at the remote host, including the admin
|
||||
user. If this field is set, credentials can only be created for
|
||||
the values in this list and the value of the `default_user` field.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">key_option_specs</span>
|
||||
<span class="param-flags">optional for Dynamic type, NA for OTP type</span>
|
||||
(String)
|
||||
Comma separated option specifications which will be prefixed to RSA key in
|
||||
authorized_keys file. Options should be valid and comply with authorized_keys
|
||||
file format and should not contain spaces.
|
||||
<span class="param-flags">optional for Dynamic Key type, N/A for OTP type</span>
|
||||
(String)
|
||||
Comma separated option specification which will be prefixed to RSA
|
||||
keys in the remote host's authorized_keys file. N.B.: Vault does
|
||||
not check this string for validity.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
@@ -504,7 +446,7 @@ username@ip:~$
|
||||
A `204` response code.
|
||||
</dd>
|
||||
|
||||
#### GET
|
||||
#### GET
|
||||
|
||||
<dl class="api">
|
||||
<dt>Description</dt>
|
||||
@@ -520,9 +462,9 @@ username@ip:~$
|
||||
|
||||
<dt>Parameters</dt>
|
||||
<dd>None</dd>
|
||||
|
||||
|
||||
<dt>Returns</dt>
|
||||
<dd>For dynamic role:
|
||||
<dd>For a dynamic key role:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -536,7 +478,7 @@ username@ip:~$
|
||||
```
|
||||
</dd>
|
||||
|
||||
<dd>For OTP role:
|
||||
<dd>For an OTP role:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -549,7 +491,7 @@ username@ip:~$
|
||||
</dd>
|
||||
|
||||
|
||||
#### DELETE
|
||||
#### DELETE
|
||||
|
||||
<dl class="api">
|
||||
<dt>Description</dt>
|
||||
@@ -576,7 +518,8 @@ username@ip:~$
|
||||
<dl class="api">
|
||||
<dt>Description</dt>
|
||||
<dd>
|
||||
Creates a credential for a specific username and IP under the given role.
|
||||
Creates credentials for a specific username and IP with the
|
||||
parameters defined in the given role.
|
||||
</dd>
|
||||
|
||||
<dt>Method</dt>
|
||||
@@ -591,18 +534,18 @@ username@ip:~$
|
||||
<li>
|
||||
<span class="param">username</span>
|
||||
<span class="param-flags">optional</span>
|
||||
(String)
|
||||
Username in remote host.
|
||||
(String)
|
||||
Username on the remote host.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">ip</span>
|
||||
<span class="param-flags">required</span>
|
||||
(String)
|
||||
(String)
|
||||
IP of the remote host.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
|
||||
<dt>Returns</dt>
|
||||
<dd>
|
||||
A `204` response code.
|
||||
@@ -614,7 +557,7 @@ username@ip:~$
|
||||
<dl class="api">
|
||||
<dt>Description</dt>
|
||||
<dd>
|
||||
Lists all the roles given IP is associated with.
|
||||
Lists all of the roles with which the given IP is associated.
|
||||
</dd>
|
||||
|
||||
<dt>Method</dt>
|
||||
@@ -629,7 +572,7 @@ username@ip:~$
|
||||
<li>
|
||||
<span class="param">ip</span>
|
||||
<span class="param-flags">required</span>
|
||||
(String)
|
||||
(String)
|
||||
IP of the remote host.
|
||||
</li>
|
||||
</ul>
|
||||
@@ -646,7 +589,8 @@ username@ip:~$
|
||||
<dl class="api">
|
||||
<dt>Description</dt>
|
||||
<dd>
|
||||
Verifies if the given OTP is valid. This is an unauthenticated endpoint.
|
||||
Verifies if the given OTP is valid. This is an unauthenticated
|
||||
endpoint.
|
||||
</dd>
|
||||
|
||||
<dt>Method</dt>
|
||||
@@ -661,7 +605,7 @@ username@ip:~$
|
||||
<li>
|
||||
<span class="param">otp</span>
|
||||
<span class="param-flags">required</span>
|
||||
(String)
|
||||
(String)
|
||||
One-Time-Key that needs to be validated.
|
||||
</li>
|
||||
</ul>
|
||||
@@ -671,4 +615,3 @@ username@ip:~$
|
||||
<dd>
|
||||
A `204` response code.
|
||||
</dd>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user