mirror of
https://github.com/hashicorp/vault.git
synced 2025-12-16 15:01:13 +01:00
More porting from rep (#2388)
* More porting from rep * Address review feedback
This commit is contained in:
parent
98c7bd6c03
commit
8acbdefdf2
@ -17,20 +17,10 @@ func Factory(conf *logical.BackendConfig) (logical.Backend, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Backend(conf *logical.BackendConfig) (*framework.Backend, error) {
|
func Backend(conf *logical.BackendConfig) (*framework.Backend, error) {
|
||||||
// Initialize the salt
|
|
||||||
salt, err := salt.NewSalt(conf.StorageView, &salt.Config{
|
|
||||||
HashFunc: salt.SHA1Hash,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var b backend
|
var b backend
|
||||||
b.Salt = salt
|
|
||||||
b.MapAppId = &framework.PolicyMap{
|
b.MapAppId = &framework.PolicyMap{
|
||||||
PathMap: framework.PathMap{
|
PathMap: framework.PathMap{
|
||||||
Name: "app-id",
|
Name: "app-id",
|
||||||
Salt: salt,
|
|
||||||
Schema: map[string]*framework.FieldSchema{
|
Schema: map[string]*framework.FieldSchema{
|
||||||
"display_name": &framework.FieldSchema{
|
"display_name": &framework.FieldSchema{
|
||||||
Type: framework.TypeString,
|
Type: framework.TypeString,
|
||||||
@ -48,7 +38,6 @@ func Backend(conf *logical.BackendConfig) (*framework.Backend, error) {
|
|||||||
|
|
||||||
b.MapUserId = &framework.PathMap{
|
b.MapUserId = &framework.PathMap{
|
||||||
Name: "user-id",
|
Name: "user-id",
|
||||||
Salt: salt,
|
|
||||||
Schema: map[string]*framework.FieldSchema{
|
Schema: map[string]*framework.FieldSchema{
|
||||||
"cidr_block": &framework.FieldSchema{
|
"cidr_block": &framework.FieldSchema{
|
||||||
Type: framework.TypeString,
|
Type: framework.TypeString,
|
||||||
@ -81,17 +70,11 @@ func Backend(conf *logical.BackendConfig) (*framework.Backend, error) {
|
|||||||
),
|
),
|
||||||
|
|
||||||
AuthRenew: b.pathLoginRenew,
|
AuthRenew: b.pathLoginRenew,
|
||||||
|
|
||||||
|
Init: b.initialize,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since the salt is new in 0.2, we need to handle this by migrating
|
b.view = conf.StorageView
|
||||||
// any existing keys to use the salt. We can deprecate this eventually,
|
|
||||||
// but for now we want a smooth upgrade experience by automatically
|
|
||||||
// upgrading to use salting.
|
|
||||||
if salt.DidGenerate() {
|
|
||||||
if err := b.upgradeToSalted(conf.StorageView); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.Backend, nil
|
return b.Backend, nil
|
||||||
}
|
}
|
||||||
@ -100,10 +83,36 @@ type backend struct {
|
|||||||
*framework.Backend
|
*framework.Backend
|
||||||
|
|
||||||
Salt *salt.Salt
|
Salt *salt.Salt
|
||||||
|
view logical.Storage
|
||||||
MapAppId *framework.PolicyMap
|
MapAppId *framework.PolicyMap
|
||||||
MapUserId *framework.PathMap
|
MapUserId *framework.PathMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) initialize() error {
|
||||||
|
salt, err := salt.NewSalt(b.view, &salt.Config{
|
||||||
|
HashFunc: salt.SHA1Hash,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.Salt = salt
|
||||||
|
|
||||||
|
b.MapAppId.Salt = salt
|
||||||
|
b.MapUserId.Salt = salt
|
||||||
|
|
||||||
|
// Since the salt is new in 0.2, we need to handle this by migrating
|
||||||
|
// any existing keys to use the salt. We can deprecate this eventually,
|
||||||
|
// but for now we want a smooth upgrade experience by automatically
|
||||||
|
// upgrading to use salting.
|
||||||
|
if salt.DidGenerate() {
|
||||||
|
if err := b.upgradeToSalted(b.view); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// upgradeToSalted is used to upgrade the non-salted keys prior to
|
// upgradeToSalted is used to upgrade the non-salted keys prior to
|
||||||
// Vault 0.2 to be salted. This is done on mount time and is only
|
// Vault 0.2 to be salted. This is done on mount time and is only
|
||||||
// done once. It can be deprecated eventually, but should be around
|
// done once. It can be deprecated eventually, but should be around
|
||||||
|
|||||||
@ -72,6 +72,10 @@ func TestBackend_upgradeToSalted(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
err = backend.Initialize()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Check the keys have been upgraded
|
// Check the keys have been upgraded
|
||||||
out, err := inm.Get("struct/map/app-id/foo")
|
out, err := inm.Get("struct/map/app-id/foo")
|
||||||
|
|||||||
@ -17,6 +17,9 @@ type backend struct {
|
|||||||
// by this backend.
|
// by this backend.
|
||||||
salt *salt.Salt
|
salt *salt.Salt
|
||||||
|
|
||||||
|
// The view to use when creating the salt
|
||||||
|
view logical.Storage
|
||||||
|
|
||||||
// Guard to clean-up the expired SecretID entries
|
// Guard to clean-up the expired SecretID entries
|
||||||
tidySecretIDCASGuard uint32
|
tidySecretIDCASGuard uint32
|
||||||
|
|
||||||
@ -57,18 +60,9 @@ func Factory(conf *logical.BackendConfig) (logical.Backend, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Backend(conf *logical.BackendConfig) (*backend, error) {
|
func Backend(conf *logical.BackendConfig) (*backend, error) {
|
||||||
// Initialize the salt
|
|
||||||
salt, err := salt.NewSalt(conf.StorageView, &salt.Config{
|
|
||||||
HashFunc: salt.SHA256Hash,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a backend object
|
// Create a backend object
|
||||||
b := &backend{
|
b := &backend{
|
||||||
// Set the salt object for the backend
|
view: conf.StorageView,
|
||||||
salt: salt,
|
|
||||||
|
|
||||||
// Create the map of locks to modify the registered roles
|
// Create the map of locks to modify the registered roles
|
||||||
roleLocksMap: make(map[string]*sync.RWMutex, 257),
|
roleLocksMap: make(map[string]*sync.RWMutex, 257),
|
||||||
@ -83,6 +77,8 @@ func Backend(conf *logical.BackendConfig) (*backend, error) {
|
|||||||
secretIDAccessorLocksMap: make(map[string]*sync.RWMutex, 257),
|
secretIDAccessorLocksMap: make(map[string]*sync.RWMutex, 257),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
// Create 256 locks each for managing RoleID and SecretIDs. This will avoid
|
// Create 256 locks each for managing RoleID and SecretIDs. This will avoid
|
||||||
// a superfluous number of locks directly proportional to the number of RoleID
|
// a superfluous number of locks directly proportional to the number of RoleID
|
||||||
// and SecretIDs. These locks can be accessed by indexing based on the first two
|
// and SecretIDs. These locks can be accessed by indexing based on the first two
|
||||||
@ -129,10 +125,22 @@ func Backend(conf *logical.BackendConfig) (*backend, error) {
|
|||||||
pathTidySecretID(b),
|
pathTidySecretID(b),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
Init: b.initialize,
|
||||||
}
|
}
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) initialize() error {
|
||||||
|
salt, err := salt.NewSalt(b.view, &salt.Config{
|
||||||
|
HashFunc: salt.SHA256Hash,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.salt = salt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// periodicFunc of the backend will be invoked once a minute by the RollbackManager.
|
// periodicFunc of the backend will be invoked once a minute by the RollbackManager.
|
||||||
// RoleRole backend utilizes this function to delete expired SecretID entries.
|
// RoleRole backend utilizes this function to delete expired SecretID entries.
|
||||||
// This could mean that the SecretID may live in the backend upto 1 min after its
|
// This could mean that the SecretID may live in the backend upto 1 min after its
|
||||||
|
|||||||
@ -21,5 +21,9 @@ func createBackendWithStorage(t *testing.T) (*backend, logical.Storage) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
err = b.Initialize()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
return b, config.StorageView
|
return b, config.StorageView
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,9 @@ type backend struct {
|
|||||||
*framework.Backend
|
*framework.Backend
|
||||||
Salt *salt.Salt
|
Salt *salt.Salt
|
||||||
|
|
||||||
|
// Used during initialization to set the salt
|
||||||
|
view logical.Storage
|
||||||
|
|
||||||
// Lock to make changes to any of the backend's configuration endpoints.
|
// Lock to make changes to any of the backend's configuration endpoints.
|
||||||
configMutex sync.RWMutex
|
configMutex sync.RWMutex
|
||||||
|
|
||||||
@ -59,18 +62,11 @@ type backend struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Backend(conf *logical.BackendConfig) (*backend, error) {
|
func Backend(conf *logical.BackendConfig) (*backend, error) {
|
||||||
salt, err := salt.NewSalt(conf.StorageView, &salt.Config{
|
|
||||||
HashFunc: salt.SHA256Hash,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
b := &backend{
|
b := &backend{
|
||||||
// Setting the periodic func to be run once in an hour.
|
// Setting the periodic func to be run once in an hour.
|
||||||
// If there is a real need, this can be made configurable.
|
// If there is a real need, this can be made configurable.
|
||||||
tidyCooldownPeriod: time.Hour,
|
tidyCooldownPeriod: time.Hour,
|
||||||
Salt: salt,
|
view: conf.StorageView,
|
||||||
EC2ClientsMap: make(map[string]map[string]*ec2.EC2),
|
EC2ClientsMap: make(map[string]map[string]*ec2.EC2),
|
||||||
IAMClientsMap: make(map[string]map[string]*iam.IAM),
|
IAMClientsMap: make(map[string]map[string]*iam.IAM),
|
||||||
}
|
}
|
||||||
@ -83,6 +79,9 @@ func Backend(conf *logical.BackendConfig) (*backend, error) {
|
|||||||
Unauthenticated: []string{
|
Unauthenticated: []string{
|
||||||
"login",
|
"login",
|
||||||
},
|
},
|
||||||
|
LocalStorage: []string{
|
||||||
|
"whitelist/identity/",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Paths: []*framework.Path{
|
Paths: []*framework.Path{
|
||||||
pathLogin(b),
|
pathLogin(b),
|
||||||
@ -104,11 +103,26 @@ func Backend(conf *logical.BackendConfig) (*backend, error) {
|
|||||||
pathIdentityWhitelist(b),
|
pathIdentityWhitelist(b),
|
||||||
pathTidyIdentityWhitelist(b),
|
pathTidyIdentityWhitelist(b),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Invalidate: b.invalidate,
|
||||||
|
|
||||||
|
Init: b.initialize,
|
||||||
}
|
}
|
||||||
|
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) initialize() error {
|
||||||
|
salt, err := salt.NewSalt(b.view, &salt.Config{
|
||||||
|
HashFunc: salt.SHA256Hash,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.Salt = salt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// periodicFunc performs the tasks that the backend wishes to do periodically.
|
// periodicFunc performs the tasks that the backend wishes to do periodically.
|
||||||
// Currently this will be triggered once in a minute by the RollbackManager.
|
// Currently this will be triggered once in a minute by the RollbackManager.
|
||||||
//
|
//
|
||||||
@ -169,6 +183,16 @@ func (b *backend) periodicFunc(req *logical.Request) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) invalidate(key string) {
|
||||||
|
switch key {
|
||||||
|
case "config/client":
|
||||||
|
b.configMutex.Lock()
|
||||||
|
defer b.configMutex.Unlock()
|
||||||
|
b.flushCachedEC2Clients()
|
||||||
|
b.flushCachedIAMClients()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const backendHelp = `
|
const backendHelp = `
|
||||||
aws-ec2 auth backend takes in PKCS#7 signature of an AWS EC2 instance and a client
|
aws-ec2 auth backend takes in PKCS#7 signature of an AWS EC2 instance and a client
|
||||||
created nonce to authenticates the EC2 instance with Vault.
|
created nonce to authenticates the EC2 instance with Vault.
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package cert
|
package cert
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
@ -13,7 +14,7 @@ func Factory(conf *logical.BackendConfig) (logical.Backend, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
return b, b.populateCRLs(conf.StorageView)
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Backend() *backend {
|
func Backend() *backend {
|
||||||
@ -36,9 +37,10 @@ func Backend() *backend {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
AuthRenew: b.pathLoginRenew,
|
AuthRenew: b.pathLoginRenew,
|
||||||
|
|
||||||
|
Invalidate: b.invalidate,
|
||||||
}
|
}
|
||||||
|
|
||||||
b.crls = map[string]CRLInfo{}
|
|
||||||
b.crlUpdateMutex = &sync.RWMutex{}
|
b.crlUpdateMutex = &sync.RWMutex{}
|
||||||
|
|
||||||
return &b
|
return &b
|
||||||
@ -52,6 +54,15 @@ type backend struct {
|
|||||||
crlUpdateMutex *sync.RWMutex
|
crlUpdateMutex *sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) invalidate(key string) {
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(key, "crls/"):
|
||||||
|
b.crlUpdateMutex.Lock()
|
||||||
|
defer b.crlUpdateMutex.Unlock()
|
||||||
|
b.crls = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const backendHelp = `
|
const backendHelp = `
|
||||||
The "cert" credential provider allows authentication using
|
The "cert" credential provider allows authentication using
|
||||||
TLS client certificates. A client connects to Vault and uses
|
TLS client certificates. A client connects to Vault and uses
|
||||||
|
|||||||
@ -45,6 +45,12 @@ func (b *backend) populateCRLs(storage logical.Storage) error {
|
|||||||
b.crlUpdateMutex.Lock()
|
b.crlUpdateMutex.Lock()
|
||||||
defer b.crlUpdateMutex.Unlock()
|
defer b.crlUpdateMutex.Unlock()
|
||||||
|
|
||||||
|
if b.crls != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
b.crls = map[string]CRLInfo{}
|
||||||
|
|
||||||
keys, err := storage.List("crls/")
|
keys, err := storage.List("crls/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error listing CRLs: %v", err)
|
return fmt.Errorf("error listing CRLs: %v", err)
|
||||||
@ -56,6 +62,7 @@ func (b *backend) populateCRLs(storage logical.Storage) error {
|
|||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
entry, err := storage.Get("crls/" + key)
|
entry, err := storage.Get("crls/" + key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
b.crls = nil
|
||||||
return fmt.Errorf("error loading CRL %s: %v", key, err)
|
return fmt.Errorf("error loading CRL %s: %v", key, err)
|
||||||
}
|
}
|
||||||
if entry == nil {
|
if entry == nil {
|
||||||
@ -64,6 +71,7 @@ func (b *backend) populateCRLs(storage logical.Storage) error {
|
|||||||
var crlInfo CRLInfo
|
var crlInfo CRLInfo
|
||||||
err = entry.DecodeJSON(&crlInfo)
|
err = entry.DecodeJSON(&crlInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
b.crls = nil
|
||||||
return fmt.Errorf("error decoding CRL %s: %v", key, err)
|
return fmt.Errorf("error decoding CRL %s: %v", key, err)
|
||||||
}
|
}
|
||||||
b.crls[key] = crlInfo
|
b.crls[key] = crlInfo
|
||||||
@ -121,6 +129,10 @@ func (b *backend) pathCRLDelete(
|
|||||||
return logical.ErrorResponse(`"name" parameter cannot be empty`), nil
|
return logical.ErrorResponse(`"name" parameter cannot be empty`), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := b.populateCRLs(req.Storage); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
b.crlUpdateMutex.Lock()
|
b.crlUpdateMutex.Lock()
|
||||||
defer b.crlUpdateMutex.Unlock()
|
defer b.crlUpdateMutex.Unlock()
|
||||||
|
|
||||||
@ -131,8 +143,7 @@ func (b *backend) pathCRLDelete(
|
|||||||
)), nil
|
)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err := req.Storage.Delete("crls/" + name)
|
if err := req.Storage.Delete("crls/" + name); err != nil {
|
||||||
if err != nil {
|
|
||||||
return logical.ErrorResponse(fmt.Sprintf(
|
return logical.ErrorResponse(fmt.Sprintf(
|
||||||
"error deleting crl %s: %v", name, err),
|
"error deleting crl %s: %v", name, err),
|
||||||
), nil
|
), nil
|
||||||
@ -150,6 +161,10 @@ func (b *backend) pathCRLRead(
|
|||||||
return logical.ErrorResponse(`"name" parameter must be set`), nil
|
return logical.ErrorResponse(`"name" parameter must be set`), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := b.populateCRLs(req.Storage); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
b.crlUpdateMutex.RLock()
|
b.crlUpdateMutex.RLock()
|
||||||
defer b.crlUpdateMutex.RUnlock()
|
defer b.crlUpdateMutex.RUnlock()
|
||||||
|
|
||||||
@ -185,6 +200,10 @@ func (b *backend) pathCRLWrite(
|
|||||||
return logical.ErrorResponse("parsed CRL is nil"), nil
|
return logical.ErrorResponse("parsed CRL is nil"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := b.populateCRLs(req.Storage); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
b.crlUpdateMutex.Lock()
|
b.crlUpdateMutex.Lock()
|
||||||
defer b.crlUpdateMutex.Unlock()
|
defer b.crlUpdateMutex.Unlock()
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,12 @@ func Backend() *backend {
|
|||||||
b.Backend = &framework.Backend{
|
b.Backend = &framework.Backend{
|
||||||
Help: strings.TrimSpace(backendHelp),
|
Help: strings.TrimSpace(backendHelp),
|
||||||
|
|
||||||
|
PathsSpecial: &logical.Paths{
|
||||||
|
LocalStorage: []string{
|
||||||
|
framework.WALPrefix,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
Paths: []*framework.Path{
|
Paths: []*framework.Path{
|
||||||
pathConfigRoot(),
|
pathConfigRoot(),
|
||||||
pathConfigLease(&b),
|
pathConfigLease(&b),
|
||||||
|
|||||||
@ -31,6 +31,8 @@ func Backend() *backend {
|
|||||||
secretCreds(&b),
|
secretCreds(&b),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Invalidate: b.invalidate,
|
||||||
|
|
||||||
Clean: func() {
|
Clean: func() {
|
||||||
b.ResetDB(nil)
|
b.ResetDB(nil)
|
||||||
},
|
},
|
||||||
@ -107,6 +109,13 @@ func (b *backend) ResetDB(newSession *gocql.Session) {
|
|||||||
b.session = newSession
|
b.session = newSession
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) invalidate(key string) {
|
||||||
|
switch key {
|
||||||
|
case "config/connection":
|
||||||
|
b.ResetDB(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const backendHelp = `
|
const backendHelp = `
|
||||||
The Cassandra backend dynamically generates database users.
|
The Cassandra backend dynamically generates database users.
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,8 @@ func Backend() *framework.Backend {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Clean: b.ResetSession,
|
Clean: b.ResetSession,
|
||||||
|
|
||||||
|
Invalidate: b.invalidate,
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.Backend
|
return b.Backend
|
||||||
@ -97,6 +99,13 @@ func (b *backend) ResetSession() {
|
|||||||
b.session = nil
|
b.session = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) invalidate(key string) {
|
||||||
|
switch key {
|
||||||
|
case "config/connection":
|
||||||
|
b.ResetSession()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LeaseConfig returns the lease configuration
|
// LeaseConfig returns the lease configuration
|
||||||
func (b *backend) LeaseConfig(s logical.Storage) (*configLease, error) {
|
func (b *backend) LeaseConfig(s logical.Storage) (*configLease, error) {
|
||||||
entry, err := s.Get("config/lease")
|
entry, err := s.Get("config/lease")
|
||||||
|
|||||||
@ -32,6 +32,8 @@ func Backend() *backend {
|
|||||||
secretCreds(&b),
|
secretCreds(&b),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Invalidate: b.invalidate,
|
||||||
|
|
||||||
Clean: b.ResetDB,
|
Clean: b.ResetDB,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +114,13 @@ func (b *backend) ResetDB() {
|
|||||||
b.db = nil
|
b.db = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) invalidate(key string) {
|
||||||
|
switch key {
|
||||||
|
case "config/connection":
|
||||||
|
b.ResetDB()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LeaseConfig returns the lease configuration
|
// LeaseConfig returns the lease configuration
|
||||||
func (b *backend) LeaseConfig(s logical.Storage) (*configLease, error) {
|
func (b *backend) LeaseConfig(s logical.Storage) (*configLease, error) {
|
||||||
entry, err := s.Get("config/lease")
|
entry, err := s.Get("config/lease")
|
||||||
|
|||||||
@ -32,6 +32,8 @@ func Backend() *backend {
|
|||||||
secretCreds(&b),
|
secretCreds(&b),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Invalidate: b.invalidate,
|
||||||
|
|
||||||
Clean: b.ResetDB,
|
Clean: b.ResetDB,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +107,13 @@ func (b *backend) ResetDB() {
|
|||||||
b.db = nil
|
b.db = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) invalidate(key string) {
|
||||||
|
switch key {
|
||||||
|
case "config/connection":
|
||||||
|
b.ResetDB()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Lease returns the lease information
|
// Lease returns the lease information
|
||||||
func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
||||||
entry, err := s.Get("config/lease")
|
entry, err := s.Get("config/lease")
|
||||||
|
|||||||
@ -29,6 +29,12 @@ func Backend() *backend {
|
|||||||
"crl/pem",
|
"crl/pem",
|
||||||
"crl",
|
"crl",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
LocalStorage: []string{
|
||||||
|
"revoked/",
|
||||||
|
"crl",
|
||||||
|
"certs/",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Paths: []*framework.Path{
|
Paths: []*framework.Path{
|
||||||
|
|||||||
@ -34,6 +34,8 @@ func Backend(conf *logical.BackendConfig) *backend {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Clean: b.ResetDB,
|
Clean: b.ResetDB,
|
||||||
|
|
||||||
|
Invalidate: b.invalidate,
|
||||||
}
|
}
|
||||||
|
|
||||||
b.logger = conf.Logger
|
b.logger = conf.Logger
|
||||||
@ -126,6 +128,13 @@ func (b *backend) ResetDB() {
|
|||||||
b.db = nil
|
b.db = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) invalidate(key string) {
|
||||||
|
switch key {
|
||||||
|
case "config/connection":
|
||||||
|
b.ResetDB()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Lease returns the lease information
|
// Lease returns the lease information
|
||||||
func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
||||||
entry, err := s.Get("config/lease")
|
entry, err := s.Get("config/lease")
|
||||||
|
|||||||
@ -35,6 +35,8 @@ func Backend() *backend {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Clean: b.resetClient,
|
Clean: b.resetClient,
|
||||||
|
|
||||||
|
Invalidate: b.invalidate,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &b
|
return &b
|
||||||
@ -99,6 +101,13 @@ func (b *backend) resetClient() {
|
|||||||
b.client = nil
|
b.client = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) invalidate(key string) {
|
||||||
|
switch key {
|
||||||
|
case "config/connection":
|
||||||
|
b.resetClient()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Lease returns the lease information
|
// Lease returns the lease information
|
||||||
func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
func (b *backend) Lease(s logical.Storage) (*configLease, error) {
|
||||||
entry, err := s.Get("config/lease")
|
entry, err := s.Get("config/lease")
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
type backend struct {
|
type backend struct {
|
||||||
*framework.Backend
|
*framework.Backend
|
||||||
|
view logical.Storage
|
||||||
salt *salt.Salt
|
salt *salt.Salt
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,15 +23,8 @@ func Factory(conf *logical.BackendConfig) (logical.Backend, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Backend(conf *logical.BackendConfig) (*backend, error) {
|
func Backend(conf *logical.BackendConfig) (*backend, error) {
|
||||||
salt, err := salt.NewSalt(conf.StorageView, &salt.Config{
|
|
||||||
HashFunc: salt.SHA256Hash,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var b backend
|
var b backend
|
||||||
b.salt = salt
|
b.view = conf.StorageView
|
||||||
b.Backend = &framework.Backend{
|
b.Backend = &framework.Backend{
|
||||||
Help: strings.TrimSpace(backendHelp),
|
Help: strings.TrimSpace(backendHelp),
|
||||||
|
|
||||||
@ -38,6 +32,10 @@ func Backend(conf *logical.BackendConfig) (*backend, error) {
|
|||||||
Unauthenticated: []string{
|
Unauthenticated: []string{
|
||||||
"verify",
|
"verify",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
LocalStorage: []string{
|
||||||
|
"otp/",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Paths: []*framework.Path{
|
Paths: []*framework.Path{
|
||||||
@ -54,10 +52,23 @@ func Backend(conf *logical.BackendConfig) (*backend, error) {
|
|||||||
secretDynamicKey(&b),
|
secretDynamicKey(&b),
|
||||||
secretOTP(&b),
|
secretOTP(&b),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Init: b.Initialize,
|
||||||
}
|
}
|
||||||
return &b, nil
|
return &b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) Initialize() error {
|
||||||
|
salt, err := salt.NewSalt(b.view, &salt.Config{
|
||||||
|
HashFunc: salt.SHA256Hash,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.salt = salt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
const backendHelp = `
|
const backendHelp = `
|
||||||
The SSH backend generates credentials allowing clients to establish SSH
|
The SSH backend generates credentials allowing clients to establish SSH
|
||||||
connections to remote hosts.
|
connections to remote hosts.
|
||||||
|
|||||||
@ -73,6 +73,10 @@ func TestBackend_allowed_users(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
err = b.Initialize()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
roleData := map[string]interface{}{
|
roleData := map[string]interface{}{
|
||||||
"key_type": "otp",
|
"key_type": "otp",
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package transit
|
package transit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/helper/keysutil"
|
"github.com/hashicorp/vault/helper/keysutil"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/framework"
|
"github.com/hashicorp/vault/logical/framework"
|
||||||
@ -39,6 +41,8 @@ func Backend(conf *logical.BackendConfig) *backend {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Secrets: []*framework.Secret{},
|
Secrets: []*framework.Secret{},
|
||||||
|
|
||||||
|
Invalidate: b.invalidate,
|
||||||
}
|
}
|
||||||
|
|
||||||
b.lm = keysutil.NewLockManager(conf.System.CachingDisabled())
|
b.lm = keysutil.NewLockManager(conf.System.CachingDisabled())
|
||||||
@ -50,3 +54,14 @@ type backend struct {
|
|||||||
*framework.Backend
|
*framework.Backend
|
||||||
lm *keysutil.LockManager
|
lm *keysutil.LockManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) invalidate(key string) {
|
||||||
|
if b.Logger().IsTrace() {
|
||||||
|
b.Logger().Trace("transit: invalidating key", "key", key)
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(key, "policy/"):
|
||||||
|
name := strings.TrimPrefix(key, "policy/")
|
||||||
|
b.lm.InvalidatePolicy(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -15,11 +15,13 @@ type MountCommand struct {
|
|||||||
|
|
||||||
func (c *MountCommand) Run(args []string) int {
|
func (c *MountCommand) Run(args []string) int {
|
||||||
var description, path, defaultLeaseTTL, maxLeaseTTL string
|
var description, path, defaultLeaseTTL, maxLeaseTTL string
|
||||||
|
var local bool
|
||||||
flags := c.Meta.FlagSet("mount", meta.FlagSetDefault)
|
flags := c.Meta.FlagSet("mount", meta.FlagSetDefault)
|
||||||
flags.StringVar(&description, "description", "", "")
|
flags.StringVar(&description, "description", "", "")
|
||||||
flags.StringVar(&path, "path", "", "")
|
flags.StringVar(&path, "path", "", "")
|
||||||
flags.StringVar(&defaultLeaseTTL, "default-lease-ttl", "", "")
|
flags.StringVar(&defaultLeaseTTL, "default-lease-ttl", "", "")
|
||||||
flags.StringVar(&maxLeaseTTL, "max-lease-ttl", "", "")
|
flags.StringVar(&maxLeaseTTL, "max-lease-ttl", "", "")
|
||||||
|
flags.BoolVar(&local, "local", false, "")
|
||||||
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||||
if err := flags.Parse(args); err != nil {
|
if err := flags.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
@ -54,6 +56,7 @@ func (c *MountCommand) Run(args []string) int {
|
|||||||
DefaultLeaseTTL: defaultLeaseTTL,
|
DefaultLeaseTTL: defaultLeaseTTL,
|
||||||
MaxLeaseTTL: maxLeaseTTL,
|
MaxLeaseTTL: maxLeaseTTL,
|
||||||
},
|
},
|
||||||
|
Local: local,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.Sys().Mount(path, mountInfo); err != nil {
|
if err := client.Sys().Mount(path, mountInfo); err != nil {
|
||||||
@ -102,6 +105,10 @@ Mount Options:
|
|||||||
the previously set value. Set to '0' to
|
the previously set value. Set to '0' to
|
||||||
explicitly set it to use the global default.
|
explicitly set it to use the global default.
|
||||||
|
|
||||||
|
-local Mark the mount as a local mount. Local mounts
|
||||||
|
are not replicated nor (if a secondary)
|
||||||
|
removed by replication.
|
||||||
|
|
||||||
`
|
`
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,7 +42,7 @@ func (c *MountsCommand) Run(args []string) int {
|
|||||||
}
|
}
|
||||||
sort.Strings(paths)
|
sort.Strings(paths)
|
||||||
|
|
||||||
columns := []string{"Path | Type | Default TTL | Max TTL | Description"}
|
columns := []string{"Path | Type | Default TTL | Max TTL | Replication Behavior | Description"}
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
mount := mounts[path]
|
mount := mounts[path]
|
||||||
defTTL := "system"
|
defTTL := "system"
|
||||||
@ -63,8 +63,12 @@ func (c *MountsCommand) Run(args []string) int {
|
|||||||
case mount.Config.MaxLeaseTTL != 0:
|
case mount.Config.MaxLeaseTTL != 0:
|
||||||
maxTTL = strconv.Itoa(mount.Config.MaxLeaseTTL)
|
maxTTL = strconv.Itoa(mount.Config.MaxLeaseTTL)
|
||||||
}
|
}
|
||||||
|
replicatedBehavior := "replicated"
|
||||||
|
if mount.Local {
|
||||||
|
replicatedBehavior = "local"
|
||||||
|
}
|
||||||
columns = append(columns, fmt.Sprintf(
|
columns = append(columns, fmt.Sprintf(
|
||||||
"%s | %s | %s | %s | %s", path, mount.Type, defTTL, maxTTL, mount.Description))
|
"%s | %s | %s | %s | %s | %s", path, mount.Type, defTTL, maxTTL, replicatedBehavior, mount.Description))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Ui.Output(columnize.SimpleFormat(columns))
|
c.Ui.Output(columnize.SimpleFormat(columns))
|
||||||
|
|||||||
@ -61,7 +61,7 @@ type ServerCommand struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ServerCommand) Run(args []string) int {
|
func (c *ServerCommand) Run(args []string) int {
|
||||||
var dev, verifyOnly, devHA bool
|
var dev, verifyOnly, devHA, devTransactional bool
|
||||||
var configPath []string
|
var configPath []string
|
||||||
var logLevel, devRootTokenID, devListenAddress string
|
var logLevel, devRootTokenID, devListenAddress string
|
||||||
flags := c.Meta.FlagSet("server", meta.FlagSetDefault)
|
flags := c.Meta.FlagSet("server", meta.FlagSetDefault)
|
||||||
@ -70,7 +70,8 @@ func (c *ServerCommand) Run(args []string) int {
|
|||||||
flags.StringVar(&devListenAddress, "dev-listen-address", "", "")
|
flags.StringVar(&devListenAddress, "dev-listen-address", "", "")
|
||||||
flags.StringVar(&logLevel, "log-level", "info", "")
|
flags.StringVar(&logLevel, "log-level", "info", "")
|
||||||
flags.BoolVar(&verifyOnly, "verify-only", false, "")
|
flags.BoolVar(&verifyOnly, "verify-only", false, "")
|
||||||
flags.BoolVar(&devHA, "dev-ha", false, "")
|
flags.BoolVar(&devHA, "ha", false, "")
|
||||||
|
flags.BoolVar(&devTransactional, "transactional", false, "")
|
||||||
flags.Usage = func() { c.Ui.Output(c.Help()) }
|
flags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||||
flags.Var((*sliceflag.StringFlag)(&configPath), "config", "config")
|
flags.Var((*sliceflag.StringFlag)(&configPath), "config", "config")
|
||||||
if err := flags.Parse(args); err != nil {
|
if err := flags.Parse(args); err != nil {
|
||||||
@ -122,7 +123,7 @@ func (c *ServerCommand) Run(args []string) int {
|
|||||||
devListenAddress = os.Getenv("VAULT_DEV_LISTEN_ADDRESS")
|
devListenAddress = os.Getenv("VAULT_DEV_LISTEN_ADDRESS")
|
||||||
}
|
}
|
||||||
|
|
||||||
if devHA {
|
if devHA || devTransactional {
|
||||||
dev = true
|
dev = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +144,7 @@ func (c *ServerCommand) Run(args []string) int {
|
|||||||
// Load the configuration
|
// Load the configuration
|
||||||
var config *server.Config
|
var config *server.Config
|
||||||
if dev {
|
if dev {
|
||||||
config = server.DevConfig(devHA)
|
config = server.DevConfig(devHA, devTransactional)
|
||||||
if devListenAddress != "" {
|
if devListenAddress != "" {
|
||||||
config.Listeners[0].Config["address"] = devListenAddress
|
config.Listeners[0].Config["address"] = devListenAddress
|
||||||
}
|
}
|
||||||
@ -235,6 +236,9 @@ func (c *ServerCommand) Run(args []string) int {
|
|||||||
ClusterName: config.ClusterName,
|
ClusterName: config.ClusterName,
|
||||||
CacheSize: config.CacheSize,
|
CacheSize: config.CacheSize,
|
||||||
}
|
}
|
||||||
|
if dev {
|
||||||
|
coreConfig.DevToken = devRootTokenID
|
||||||
|
}
|
||||||
|
|
||||||
var disableClustering bool
|
var disableClustering bool
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DevConfig is a Config that is used for dev mode of Vault.
|
// DevConfig is a Config that is used for dev mode of Vault.
|
||||||
func DevConfig(ha bool) *Config {
|
func DevConfig(ha, transactional bool) *Config {
|
||||||
ret := &Config{
|
ret := &Config{
|
||||||
DisableCache: false,
|
DisableCache: false,
|
||||||
DisableMlock: true,
|
DisableMlock: true,
|
||||||
@ -63,7 +63,12 @@ func DevConfig(ha bool) *Config {
|
|||||||
DefaultLeaseTTL: 32 * 24 * time.Hour,
|
DefaultLeaseTTL: 32 * 24 * time.Hour,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ha {
|
switch {
|
||||||
|
case ha && transactional:
|
||||||
|
ret.Backend.Type = "inmem_transactional_ha"
|
||||||
|
case !ha && transactional:
|
||||||
|
ret.Backend.Type = "inmem_transactional"
|
||||||
|
case ha && !transactional:
|
||||||
ret.Backend.Type = "inmem_ha"
|
ret.Backend.Type = "inmem_ha"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@ func TestServer_CommonHA(t *testing.T) {
|
|||||||
args := []string{"-config", tmpfile.Name(), "-verify-only", "true"}
|
args := []string{"-config", tmpfile.Name(), "-verify-only", "true"}
|
||||||
|
|
||||||
if code := c.Run(args); code != 0 {
|
if code := c.Run(args); code != 0 {
|
||||||
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
t.Fatalf("bad: %d\n\n%s\n\n%s", code, ui.ErrorWriter.String(), ui.OutputWriter.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(ui.OutputWriter.String(), "(HA available)") {
|
if !strings.Contains(ui.OutputWriter.String(), "(HA available)") {
|
||||||
@ -61,7 +61,7 @@ func TestServer_GoodSeparateHA(t *testing.T) {
|
|||||||
args := []string{"-config", tmpfile.Name(), "-verify-only", "true"}
|
args := []string{"-config", tmpfile.Name(), "-verify-only", "true"}
|
||||||
|
|
||||||
if code := c.Run(args); code != 0 {
|
if code := c.Run(args); code != 0 {
|
||||||
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
t.Fatalf("bad: %d\n\n%s\n\n%s", code, ui.ErrorWriter.String(), ui.OutputWriter.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(ui.OutputWriter.String(), "HA Backend:") {
|
if !strings.Contains(ui.OutputWriter.String(), "HA Backend:") {
|
||||||
|
|||||||
@ -71,6 +71,15 @@ func (lm *LockManager) CacheActive() bool {
|
|||||||
return lm.cache != nil
|
return lm.cache != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lm *LockManager) InvalidatePolicy(name string) {
|
||||||
|
// Check if it's in our cache. If so, return right away.
|
||||||
|
if lm.CacheActive() {
|
||||||
|
lm.cacheMutex.Lock()
|
||||||
|
defer lm.cacheMutex.Unlock()
|
||||||
|
delete(lm.cache, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (lm *LockManager) policyLock(name string, lockType bool) *sync.RWMutex {
|
func (lm *LockManager) policyLock(name string, lockType bool) *sync.RWMutex {
|
||||||
lm.locksMutex.RLock()
|
lm.locksMutex.RLock()
|
||||||
lock := lm.locks[name]
|
lock := lm.locks[name]
|
||||||
|
|||||||
@ -16,6 +16,12 @@ func CubbyholeBackendFactory(conf *logical.BackendConfig) (logical.Backend, erro
|
|||||||
b.Backend = &framework.Backend{
|
b.Backend = &framework.Backend{
|
||||||
Help: strings.TrimSpace(cubbyholeHelp),
|
Help: strings.TrimSpace(cubbyholeHelp),
|
||||||
|
|
||||||
|
PathsSpecial: &logical.Paths{
|
||||||
|
LocalStorage: []string{
|
||||||
|
"*",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
Paths: []*framework.Path{
|
Paths: []*framework.Path{
|
||||||
&framework.Path{
|
&framework.Path{
|
||||||
Pattern: ".*",
|
Pattern: ".*",
|
||||||
|
|||||||
@ -12,9 +12,13 @@ import (
|
|||||||
|
|
||||||
func TestCubbyholeBackend_RootPaths(t *testing.T) {
|
func TestCubbyholeBackend_RootPaths(t *testing.T) {
|
||||||
b := testCubbyholeBackend()
|
b := testCubbyholeBackend()
|
||||||
root := b.SpecialPaths()
|
expected := []string{
|
||||||
if root != nil {
|
"*",
|
||||||
t.Fatalf("unexpected: %v", root)
|
}
|
||||||
|
|
||||||
|
actual := b.SpecialPaths().LocalStorage
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Fatalf("bad: %#v", actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/duration"
|
"github.com/hashicorp/vault/helper/duration"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/framework"
|
"github.com/hashicorp/vault/logical/framework"
|
||||||
@ -39,12 +40,14 @@ func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backen
|
|||||||
"audit",
|
"audit",
|
||||||
"audit/*",
|
"audit/*",
|
||||||
"raw/*",
|
"raw/*",
|
||||||
|
"replication/primary/secondary-token",
|
||||||
"rotate",
|
"rotate",
|
||||||
"config/auditing/*",
|
"config/auditing/*",
|
||||||
},
|
},
|
||||||
|
|
||||||
Unauthenticated: []string{
|
Unauthenticated: []string{
|
||||||
"wrapping/pubkey",
|
"wrapping/pubkey",
|
||||||
|
"replication/status",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -226,6 +229,11 @@ func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backen
|
|||||||
Type: framework.TypeMap,
|
Type: framework.TypeMap,
|
||||||
Description: strings.TrimSpace(sysHelp["mount_config"][0]),
|
Description: strings.TrimSpace(sysHelp["mount_config"][0]),
|
||||||
},
|
},
|
||||||
|
"local": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeBool,
|
||||||
|
Default: false,
|
||||||
|
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||||
@ -377,6 +385,11 @@ func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backen
|
|||||||
Type: framework.TypeString,
|
Type: framework.TypeString,
|
||||||
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
|
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
|
||||||
},
|
},
|
||||||
|
"local": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeBool,
|
||||||
|
Default: false,
|
||||||
|
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||||
@ -495,6 +508,11 @@ func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backen
|
|||||||
Type: framework.TypeMap,
|
Type: framework.TypeMap,
|
||||||
Description: strings.TrimSpace(sysHelp["audit_opts"][0]),
|
Description: strings.TrimSpace(sysHelp["audit_opts"][0]),
|
||||||
},
|
},
|
||||||
|
"local": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeBool,
|
||||||
|
Default: false,
|
||||||
|
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||||
@ -657,6 +675,10 @@ func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backen
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.Backend.Paths = append(b.Backend.Paths, b.replicationPaths()...)
|
||||||
|
|
||||||
|
b.Backend.Invalidate = b.invalidate
|
||||||
|
|
||||||
return b.Backend.Setup(config)
|
return b.Backend.Setup(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -668,6 +690,20 @@ type SystemBackend struct {
|
|||||||
Backend *framework.Backend
|
Backend *framework.Backend
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *SystemBackend) invalidate(key string) {
|
||||||
|
if b.Core.logger.IsTrace() {
|
||||||
|
b.Core.logger.Trace("sys: invaliding key", "key", key)
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(key, policySubPath):
|
||||||
|
b.Core.stateLock.RLock()
|
||||||
|
defer b.Core.stateLock.RUnlock()
|
||||||
|
if b.Core.policyStore != nil {
|
||||||
|
b.Core.policyStore.invalidate(strings.TrimPrefix(key, policySubPath))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// handleAuditedHeaderUpdate creates or overwrites a header entry
|
// handleAuditedHeaderUpdate creates or overwrites a header entry
|
||||||
func (b *SystemBackend) handleAuditedHeaderUpdate(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *SystemBackend) handleAuditedHeaderUpdate(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
header := d.Get("header").(string)
|
header := d.Get("header").(string)
|
||||||
@ -869,6 +905,7 @@ func (b *SystemBackend) handleMountTable(
|
|||||||
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
||||||
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
||||||
},
|
},
|
||||||
|
"local": entry.Local,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Data[entry.Path] = info
|
resp.Data[entry.Path] = info
|
||||||
@ -880,6 +917,15 @@ func (b *SystemBackend) handleMountTable(
|
|||||||
// handleMount is used to mount a new path
|
// handleMount is used to mount a new path
|
||||||
func (b *SystemBackend) handleMount(
|
func (b *SystemBackend) handleMount(
|
||||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||||
|
b.Core.clusterParamsLock.RLock()
|
||||||
|
repState := b.Core.replicationState
|
||||||
|
b.Core.clusterParamsLock.RUnlock()
|
||||||
|
|
||||||
|
local := data.Get("local").(bool)
|
||||||
|
if !local && repState == consts.ReplicationSecondary {
|
||||||
|
return logical.ErrorResponse("cannot add a non-local mount to a replication secondary"), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get all the options
|
// Get all the options
|
||||||
path := data.Get("path").(string)
|
path := data.Get("path").(string)
|
||||||
logicalType := data.Get("type").(string)
|
logicalType := data.Get("type").(string)
|
||||||
@ -954,6 +1000,7 @@ func (b *SystemBackend) handleMount(
|
|||||||
Type: logicalType,
|
Type: logicalType,
|
||||||
Description: description,
|
Description: description,
|
||||||
Config: config,
|
Config: config,
|
||||||
|
Local: local,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt mount
|
// Attempt mount
|
||||||
@ -979,6 +1026,10 @@ func handleError(
|
|||||||
// handleUnmount is used to unmount a path
|
// handleUnmount is used to unmount a path
|
||||||
func (b *SystemBackend) handleUnmount(
|
func (b *SystemBackend) handleUnmount(
|
||||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||||
|
b.Core.clusterParamsLock.RLock()
|
||||||
|
repState := b.Core.replicationState
|
||||||
|
b.Core.clusterParamsLock.RUnlock()
|
||||||
|
|
||||||
suffix := strings.TrimPrefix(req.Path, "mounts/")
|
suffix := strings.TrimPrefix(req.Path, "mounts/")
|
||||||
if len(suffix) == 0 {
|
if len(suffix) == 0 {
|
||||||
return logical.ErrorResponse("path cannot be blank"), logical.ErrInvalidRequest
|
return logical.ErrorResponse("path cannot be blank"), logical.ErrInvalidRequest
|
||||||
@ -986,6 +1037,11 @@ func (b *SystemBackend) handleUnmount(
|
|||||||
|
|
||||||
suffix = sanitizeMountPath(suffix)
|
suffix = sanitizeMountPath(suffix)
|
||||||
|
|
||||||
|
entry := b.Core.router.MatchingMountEntry(suffix)
|
||||||
|
if entry != nil && !entry.Local && repState == consts.ReplicationSecondary {
|
||||||
|
return logical.ErrorResponse("cannot unmount a non-local mount on a replication secondary"), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt unmount
|
// Attempt unmount
|
||||||
if existed, err := b.Core.unmount(suffix); existed && err != nil {
|
if existed, err := b.Core.unmount(suffix); existed && err != nil {
|
||||||
b.Backend.Logger().Error("sys: unmount failed", "path", suffix, "error", err)
|
b.Backend.Logger().Error("sys: unmount failed", "path", suffix, "error", err)
|
||||||
@ -998,6 +1054,10 @@ func (b *SystemBackend) handleUnmount(
|
|||||||
// handleRemount is used to remount a path
|
// handleRemount is used to remount a path
|
||||||
func (b *SystemBackend) handleRemount(
|
func (b *SystemBackend) handleRemount(
|
||||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||||
|
b.Core.clusterParamsLock.RLock()
|
||||||
|
repState := b.Core.replicationState
|
||||||
|
b.Core.clusterParamsLock.RUnlock()
|
||||||
|
|
||||||
// Get the paths
|
// Get the paths
|
||||||
fromPath := data.Get("from").(string)
|
fromPath := data.Get("from").(string)
|
||||||
toPath := data.Get("to").(string)
|
toPath := data.Get("to").(string)
|
||||||
@ -1010,6 +1070,11 @@ func (b *SystemBackend) handleRemount(
|
|||||||
fromPath = sanitizeMountPath(fromPath)
|
fromPath = sanitizeMountPath(fromPath)
|
||||||
toPath = sanitizeMountPath(toPath)
|
toPath = sanitizeMountPath(toPath)
|
||||||
|
|
||||||
|
entry := b.Core.router.MatchingMountEntry(fromPath)
|
||||||
|
if entry != nil && !entry.Local && repState == consts.ReplicationSecondary {
|
||||||
|
return logical.ErrorResponse("cannot remount a non-local mount on a replication secondary"), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt remount
|
// Attempt remount
|
||||||
if err := b.Core.remount(fromPath, toPath); err != nil {
|
if err := b.Core.remount(fromPath, toPath); err != nil {
|
||||||
b.Backend.Logger().Error("sys: remount failed", "from_path", fromPath, "to_path", toPath, "error", err)
|
b.Backend.Logger().Error("sys: remount failed", "from_path", fromPath, "to_path", toPath, "error", err)
|
||||||
@ -1095,6 +1160,10 @@ func (b *SystemBackend) handleMountTuneWrite(
|
|||||||
// handleTuneWriteCommon is used to set config settings on a path
|
// handleTuneWriteCommon is used to set config settings on a path
|
||||||
func (b *SystemBackend) handleTuneWriteCommon(
|
func (b *SystemBackend) handleTuneWriteCommon(
|
||||||
path string, data *framework.FieldData) (*logical.Response, error) {
|
path string, data *framework.FieldData) (*logical.Response, error) {
|
||||||
|
b.Core.clusterParamsLock.RLock()
|
||||||
|
repState := b.Core.replicationState
|
||||||
|
b.Core.clusterParamsLock.RUnlock()
|
||||||
|
|
||||||
path = sanitizeMountPath(path)
|
path = sanitizeMountPath(path)
|
||||||
|
|
||||||
// Prevent protected paths from being changed
|
// Prevent protected paths from being changed
|
||||||
@ -1110,6 +1179,9 @@ func (b *SystemBackend) handleTuneWriteCommon(
|
|||||||
b.Backend.Logger().Error("sys: tune failed: no mount entry found", "path", path)
|
b.Backend.Logger().Error("sys: tune failed: no mount entry found", "path", path)
|
||||||
return handleError(fmt.Errorf("sys: tune of path '%s' failed: no mount entry found", path))
|
return handleError(fmt.Errorf("sys: tune of path '%s' failed: no mount entry found", path))
|
||||||
}
|
}
|
||||||
|
if mountEntry != nil && !mountEntry.Local && repState == consts.ReplicationSecondary {
|
||||||
|
return logical.ErrorResponse("cannot tune a non-local mount on a replication secondary"), nil
|
||||||
|
}
|
||||||
|
|
||||||
var lock *sync.RWMutex
|
var lock *sync.RWMutex
|
||||||
switch {
|
switch {
|
||||||
@ -1249,6 +1321,7 @@ func (b *SystemBackend) handleAuthTable(
|
|||||||
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
||||||
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
||||||
},
|
},
|
||||||
|
"local": entry.Local,
|
||||||
}
|
}
|
||||||
resp.Data[entry.Path] = info
|
resp.Data[entry.Path] = info
|
||||||
}
|
}
|
||||||
@ -1258,6 +1331,15 @@ func (b *SystemBackend) handleAuthTable(
|
|||||||
// handleEnableAuth is used to enable a new credential backend
|
// handleEnableAuth is used to enable a new credential backend
|
||||||
func (b *SystemBackend) handleEnableAuth(
|
func (b *SystemBackend) handleEnableAuth(
|
||||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||||
|
b.Core.clusterParamsLock.RLock()
|
||||||
|
repState := b.Core.replicationState
|
||||||
|
b.Core.clusterParamsLock.RUnlock()
|
||||||
|
|
||||||
|
local := data.Get("local").(bool)
|
||||||
|
if !local && repState == consts.ReplicationSecondary {
|
||||||
|
return logical.ErrorResponse("cannot add a non-local mount to a replication secondary"), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get all the options
|
// Get all the options
|
||||||
path := data.Get("path").(string)
|
path := data.Get("path").(string)
|
||||||
logicalType := data.Get("type").(string)
|
logicalType := data.Get("type").(string)
|
||||||
@ -1277,6 +1359,7 @@ func (b *SystemBackend) handleEnableAuth(
|
|||||||
Path: path,
|
Path: path,
|
||||||
Type: logicalType,
|
Type: logicalType,
|
||||||
Description: description,
|
Description: description,
|
||||||
|
Local: local,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt enabling
|
// Attempt enabling
|
||||||
@ -1391,6 +1474,7 @@ func (b *SystemBackend) handleAuditTable(
|
|||||||
"type": entry.Type,
|
"type": entry.Type,
|
||||||
"description": entry.Description,
|
"description": entry.Description,
|
||||||
"options": entry.Options,
|
"options": entry.Options,
|
||||||
|
"local": entry.Local,
|
||||||
}
|
}
|
||||||
resp.Data[entry.Path] = info
|
resp.Data[entry.Path] = info
|
||||||
}
|
}
|
||||||
@ -1424,6 +1508,15 @@ func (b *SystemBackend) handleAuditHash(
|
|||||||
// handleEnableAudit is used to enable a new audit backend
|
// handleEnableAudit is used to enable a new audit backend
|
||||||
func (b *SystemBackend) handleEnableAudit(
|
func (b *SystemBackend) handleEnableAudit(
|
||||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||||
|
b.Core.clusterParamsLock.RLock()
|
||||||
|
repState := b.Core.replicationState
|
||||||
|
b.Core.clusterParamsLock.RUnlock()
|
||||||
|
|
||||||
|
local := data.Get("local").(bool)
|
||||||
|
if !local && repState == consts.ReplicationSecondary {
|
||||||
|
return logical.ErrorResponse("cannot add a non-local mount to a replication secondary"), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get all the options
|
// Get all the options
|
||||||
path := data.Get("path").(string)
|
path := data.Get("path").(string)
|
||||||
backendType := data.Get("type").(string)
|
backendType := data.Get("type").(string)
|
||||||
@ -1447,6 +1540,7 @@ func (b *SystemBackend) handleEnableAudit(
|
|||||||
Type: backendType,
|
Type: backendType,
|
||||||
Description: description,
|
Description: description,
|
||||||
Options: optionMap,
|
Options: optionMap,
|
||||||
|
Local: local,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt enabling
|
// Attempt enabling
|
||||||
@ -1562,6 +1656,13 @@ func (b *SystemBackend) handleKeyStatus(
|
|||||||
// handleRotate is used to trigger a key rotation
|
// handleRotate is used to trigger a key rotation
|
||||||
func (b *SystemBackend) handleRotate(
|
func (b *SystemBackend) handleRotate(
|
||||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||||
|
b.Core.clusterParamsLock.RLock()
|
||||||
|
repState := b.Core.replicationState
|
||||||
|
b.Core.clusterParamsLock.RUnlock()
|
||||||
|
if repState == consts.ReplicationSecondary {
|
||||||
|
return logical.ErrorResponse("cannot rotate on a replication secondary"), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Rotate to the new term
|
// Rotate to the new term
|
||||||
newTerm, err := b.Core.barrier.Rotate()
|
newTerm, err := b.Core.barrier.Rotate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1584,6 +1685,17 @@ func (b *SystemBackend) handleRotate(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write to the canary path, which will force a synchronous truing during
|
||||||
|
// replication
|
||||||
|
if err := b.Core.barrier.Put(&Entry{
|
||||||
|
Key: coreKeyringCanaryPath,
|
||||||
|
Value: []byte(fmt.Sprintf("new-rotation-term-%d", newTerm)),
|
||||||
|
}); err != nil {
|
||||||
|
b.Core.logger.Error("core: error saving keyring canary", "error", err)
|
||||||
|
return nil, fmt.Errorf("failed to save keyring canary: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1950,6 +2062,11 @@ west coast.
|
|||||||
and max_lease_ttl.`,
|
and max_lease_ttl.`,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"mount_local": {
|
||||||
|
`Mark the mount as a local mount, which is not replicated
|
||||||
|
and is unaffected by replication.`,
|
||||||
|
},
|
||||||
|
|
||||||
"tune_default_lease_ttl": {
|
"tune_default_lease_ttl": {
|
||||||
`The default lease TTL for this mount.`,
|
`The default lease TTL for this mount.`,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -21,6 +21,7 @@ func TestSystemBackend_RootPaths(t *testing.T) {
|
|||||||
"audit",
|
"audit",
|
||||||
"audit/*",
|
"audit/*",
|
||||||
"raw/*",
|
"raw/*",
|
||||||
|
"replication/*",
|
||||||
"rotate",
|
"rotate",
|
||||||
"config/auditing/*",
|
"config/auditing/*",
|
||||||
}
|
}
|
||||||
@ -50,6 +51,7 @@ func TestSystemBackend_mounts(t *testing.T) {
|
|||||||
"default_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
},
|
},
|
||||||
|
"local": false,
|
||||||
},
|
},
|
||||||
"sys/": map[string]interface{}{
|
"sys/": map[string]interface{}{
|
||||||
"type": "system",
|
"type": "system",
|
||||||
@ -58,6 +60,7 @@ func TestSystemBackend_mounts(t *testing.T) {
|
|||||||
"default_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
},
|
},
|
||||||
|
"local": false,
|
||||||
},
|
},
|
||||||
"cubbyhole/": map[string]interface{}{
|
"cubbyhole/": map[string]interface{}{
|
||||||
"description": "per-token private secret storage",
|
"description": "per-token private secret storage",
|
||||||
@ -66,6 +69,7 @@ func TestSystemBackend_mounts(t *testing.T) {
|
|||||||
"default_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
"default_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
|
||||||
"max_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
"max_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
|
||||||
},
|
},
|
||||||
|
"local": false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(resp.Data, exp) {
|
if !reflect.DeepEqual(resp.Data, exp) {
|
||||||
@ -580,6 +584,7 @@ func TestSystemBackend_authTable(t *testing.T) {
|
|||||||
"default_lease_ttl": int64(0),
|
"default_lease_ttl": int64(0),
|
||||||
"max_lease_ttl": int64(0),
|
"max_lease_ttl": int64(0),
|
||||||
},
|
},
|
||||||
|
"local": false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(resp.Data, exp) {
|
if !reflect.DeepEqual(resp.Data, exp) {
|
||||||
@ -843,6 +848,7 @@ func TestSystemBackend_auditTable(t *testing.T) {
|
|||||||
req.Data["options"] = map[string]interface{}{
|
req.Data["options"] = map[string]interface{}{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
}
|
}
|
||||||
|
req.Data["local"] = true
|
||||||
b.HandleRequest(req)
|
b.HandleRequest(req)
|
||||||
|
|
||||||
req = logical.TestRequest(t, logical.ReadOperation, "audit")
|
req = logical.TestRequest(t, logical.ReadOperation, "audit")
|
||||||
@ -859,6 +865,7 @@ func TestSystemBackend_auditTable(t *testing.T) {
|
|||||||
"options": map[string]string{
|
"options": map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
},
|
},
|
||||||
|
"local": true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(resp.Data, exp) {
|
if !reflect.DeepEqual(resp.Data, exp) {
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
<li<%= sidebar_current("docs-internals-architecture") %>>
|
<li<%= sidebar_current("docs-internals-architecture") %>>
|
||||||
<a href="/docs/internals/architecture.html">Architecture</a>
|
<a href="/docs/internals/architecture.html">Architecture</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-internals-ha") %>>
|
<li<%= sidebar_current("docs-internals-ha") %>>
|
||||||
<a href="/docs/internals/high-availability.html">High Availability</a>
|
<a href="/docs/internals/high-availability.html">High Availability</a>
|
||||||
@ -19,15 +19,15 @@
|
|||||||
|
|
||||||
<li<%= sidebar_current("docs-internals-security") %>>
|
<li<%= sidebar_current("docs-internals-security") %>>
|
||||||
<a href="/docs/internals/security.html">Security Model</a>
|
<a href="/docs/internals/security.html">Security Model</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-internals-telemetry") %>>
|
<li<%= sidebar_current("docs-internals-telemetry") %>>
|
||||||
<a href="/docs/internals/telemetry.html">Telemetry</a>
|
<a href="/docs/internals/telemetry.html">Telemetry</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-internals-token") %>>
|
<li<%= sidebar_current("docs-internals-token") %>>
|
||||||
<a href="/docs/internals/token.html">Token Authentication</a>
|
<a href="/docs/internals/token.html">Token Authentication</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-internals-rotation") %>>
|
<li<%= sidebar_current("docs-internals-rotation") %>>
|
||||||
<a href="/docs/internals/rotation.html">Key Rotation</a>
|
<a href="/docs/internals/rotation.html">Key Rotation</a>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user