2023-03-15 16:00:52 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2015-03-20 16:59:48 +00:00
|
|
|
package aws
|
|
|
|
|
|
|
|
import (
|
2018-01-19 06:44:44 +00:00
|
|
|
"context"
|
2015-04-04 03:36:47 +00:00
|
|
|
"strings"
|
2018-08-16 10:38:13 +00:00
|
|
|
"sync"
|
2015-03-21 10:18:46 +00:00
|
|
|
"time"
|
|
|
|
|
2018-09-18 20:26:06 +00:00
|
|
|
"github.com/aws/aws-sdk-go/service/iam/iamiface"
|
|
|
|
"github.com/aws/aws-sdk-go/service/sts/stsiface"
|
2019-04-12 21:54:35 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/framework"
|
2019-04-13 07:44:06 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/logical"
|
2015-03-20 16:59:48 +00:00
|
|
|
)
|
|
|
|
|
2020-06-11 03:53:48 +00:00
|
|
|
const (
|
|
|
|
rootConfigPath = "config/root"
|
|
|
|
minAwsUserRollbackAge = 5 * time.Minute
|
2023-04-06 15:08:30 +00:00
|
|
|
operationPrefixAWS = "aws"
|
|
|
|
operationPrefixAWSASD = "aws-config"
|
2020-06-11 03:53:48 +00:00
|
|
|
)
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
b := Backend()
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.Setup(ctx, conf); err != nil {
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return b, nil
|
2015-03-20 18:32:18 +00:00
|
|
|
}
|
|
|
|
|
2016-06-10 19:53:02 +00:00
|
|
|
func Backend() *backend {
|
2015-03-20 16:59:48 +00:00
|
|
|
var b backend
|
|
|
|
b.Backend = &framework.Backend{
|
2015-04-04 03:36:47 +00:00
|
|
|
Help: strings.TrimSpace(backendHelp),
|
|
|
|
|
2017-02-16 21:29:30 +00:00
|
|
|
PathsSpecial: &logical.Paths{
|
|
|
|
LocalStorage: []string{
|
|
|
|
framework.WALPrefix,
|
|
|
|
},
|
2017-11-03 15:43:31 +00:00
|
|
|
SealWrapStorage: []string{
|
|
|
|
"config/root",
|
|
|
|
},
|
2017-02-16 21:29:30 +00:00
|
|
|
},
|
|
|
|
|
2015-03-20 16:59:48 +00:00
|
|
|
Paths: []*framework.Path{
|
2018-09-18 20:26:06 +00:00
|
|
|
pathConfigRoot(&b),
|
2018-09-26 14:10:00 +00:00
|
|
|
pathConfigRotateRoot(&b),
|
2015-04-19 05:25:37 +00:00
|
|
|
pathConfigLease(&b),
|
2018-08-16 10:38:13 +00:00
|
|
|
pathRoles(&b),
|
2016-06-20 23:51:04 +00:00
|
|
|
pathListRoles(&b),
|
2015-03-20 16:59:48 +00:00
|
|
|
pathUser(&b),
|
|
|
|
},
|
|
|
|
|
|
|
|
Secrets: []*framework.Secret{
|
2015-04-19 05:25:37 +00:00
|
|
|
secretAccessKeys(&b),
|
2015-03-20 16:59:48 +00:00
|
|
|
},
|
2015-03-21 10:18:46 +00:00
|
|
|
|
2020-06-11 03:53:48 +00:00
|
|
|
Invalidate: b.invalidate,
|
2018-02-03 01:28:25 +00:00
|
|
|
WALRollback: b.walRollback,
|
logical/aws: Harden WAL entry creation (#5202)
* logical/aws: Harden WAL entry creation
If AWS IAM user creation failed in any way, the WAL corresponding to the
IAM user would get left around and Vault would try to roll it back.
However, because the user never existed, the rollback failed. Thus, the
WAL would essentially get "stuck" and Vault would continually attempt to
roll it back, failing every time. A similar situation could arise if the
IAM user that Vault created got deleted out of band, or if Vault deleted
it but was unable to write the lease revocation back to storage (e.g., a
storage failure).
This attempts to harden it in two ways. One is by deleting the WAL log
entry if the IAM user creation fails. However, the WAL deletion could
still fail, and this wouldn't help where the user is deleted out of
band, so second, consider the user rolled back if the user just doesn't
exist, under certain circumstances.
Fixes #5190
* Fix segfault in expiration unit tests
TestExpiration_Tidy was passing in a leaseEntry that had a nil Secret,
which then caused a segfault as the changes to revokeEntry didn't check
whether Secret was nil; this is probably unlikely to occur in real life,
but good to be extra cautious.
* Fix potential segfault
Missed the else...
* Respond to PR feedback
2018-09-27 14:54:59 +00:00
|
|
|
WALRollbackMinAge: minAwsUserRollbackAge,
|
2017-07-28 18:04:46 +00:00
|
|
|
BackendType: logical.TypeLogical,
|
2015-03-20 16:59:48 +00:00
|
|
|
}
|
|
|
|
|
2016-06-10 19:53:02 +00:00
|
|
|
return &b
|
2015-03-20 16:59:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type backend struct {
|
|
|
|
*framework.Backend
|
2018-08-16 10:38:13 +00:00
|
|
|
|
|
|
|
// Mutex to protect access to reading and writing policies
|
|
|
|
roleMutex sync.RWMutex
|
2018-09-18 20:26:06 +00:00
|
|
|
|
2018-09-26 14:10:00 +00:00
|
|
|
// Mutex to protect access to iam/sts clients and client configs
|
2018-09-18 20:26:06 +00:00
|
|
|
clientMutex sync.RWMutex
|
|
|
|
|
|
|
|
// iamClient and stsClient hold configured iam and sts clients for reuse, and
|
|
|
|
// to enable mocking with AWS iface for tests
|
|
|
|
iamClient iamiface.IAMAPI
|
|
|
|
stsClient stsiface.STSAPI
|
2015-03-20 16:59:48 +00:00
|
|
|
}
|
2015-04-04 03:36:47 +00:00
|
|
|
|
|
|
|
const backendHelp = `
|
|
|
|
The AWS backend dynamically generates AWS access keys for a set of
|
|
|
|
IAM policies. The AWS access keys have a configurable lease set and
|
|
|
|
are automatically revoked at the end of the lease.
|
2015-04-04 04:10:54 +00:00
|
|
|
|
|
|
|
After mounting this backend, credentials to generate IAM keys must
|
|
|
|
be configured with the "root" path and policies must be written using
|
2015-04-27 21:20:28 +00:00
|
|
|
the "roles/" endpoints before any access keys can be generated.
|
2015-04-04 03:36:47 +00:00
|
|
|
`
|
2018-09-18 20:26:06 +00:00
|
|
|
|
2020-06-11 03:53:48 +00:00
|
|
|
func (b *backend) invalidate(ctx context.Context, key string) {
|
|
|
|
switch {
|
|
|
|
case key == rootConfigPath:
|
|
|
|
b.clearClients()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// clearClients clears the backend's IAM and STS clients
|
|
|
|
func (b *backend) clearClients() {
|
|
|
|
b.clientMutex.Lock()
|
|
|
|
defer b.clientMutex.Unlock()
|
|
|
|
b.iamClient = nil
|
|
|
|
b.stsClient = nil
|
|
|
|
}
|
|
|
|
|
2018-09-18 20:26:06 +00:00
|
|
|
// clientIAM returns the configured IAM client. If nil, it constructs a new one
|
|
|
|
// and returns it, setting it the internal variable
|
|
|
|
func (b *backend) clientIAM(ctx context.Context, s logical.Storage) (iamiface.IAMAPI, error) {
|
|
|
|
b.clientMutex.RLock()
|
|
|
|
if b.iamClient != nil {
|
|
|
|
b.clientMutex.RUnlock()
|
|
|
|
return b.iamClient, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Upgrade the lock for writing
|
|
|
|
b.clientMutex.RUnlock()
|
|
|
|
b.clientMutex.Lock()
|
|
|
|
defer b.clientMutex.Unlock()
|
|
|
|
|
|
|
|
// check client again, in the event that a client was being created while we
|
|
|
|
// waited for Lock()
|
|
|
|
if b.iamClient != nil {
|
|
|
|
return b.iamClient, nil
|
|
|
|
}
|
|
|
|
|
2020-09-28 21:06:49 +00:00
|
|
|
iamClient, err := nonCachedClientIAM(ctx, s, b.Logger())
|
2018-09-18 20:26:06 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
b.iamClient = iamClient
|
|
|
|
|
|
|
|
return b.iamClient, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *backend) clientSTS(ctx context.Context, s logical.Storage) (stsiface.STSAPI, error) {
|
|
|
|
b.clientMutex.RLock()
|
|
|
|
if b.stsClient != nil {
|
|
|
|
b.clientMutex.RUnlock()
|
|
|
|
return b.stsClient, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Upgrade the lock for writing
|
|
|
|
b.clientMutex.RUnlock()
|
|
|
|
b.clientMutex.Lock()
|
|
|
|
defer b.clientMutex.Unlock()
|
|
|
|
|
|
|
|
// check client again, in the event that a client was being created while we
|
|
|
|
// waited for Lock()
|
|
|
|
if b.stsClient != nil {
|
|
|
|
return b.stsClient, nil
|
|
|
|
}
|
|
|
|
|
2020-09-28 21:06:49 +00:00
|
|
|
stsClient, err := nonCachedClientSTS(ctx, s, b.Logger())
|
2018-09-18 20:26:06 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
b.stsClient = stsClient
|
|
|
|
|
|
|
|
return b.stsClient, nil
|
|
|
|
}
|