AWS upgrade role entries (#7025)

* upgrade aws roles

* test upgrade aws roles

* Initialize aws credential backend at mount time

* add a TODO

* create end-to-end test for builtin/credential/aws

* fix bug in initializer

* improve comments

* add Initialize() to logical.Backend

* use Initialize() in Core.enableCredentialInternal()

* use InitializeRequest to call Initialize()

* improve unit testing for framework.Backend

* call logical.Backend.Initialize() from all of the places that it needs to be called.

* implement backend.proto changes for logical.Backend.Initialize()

* persist current role storage version when upgrading aws roles

* format comments correctly

* improve comments

* use postUnseal funcs to initialize backends

* simplify test suite

* improve test suite

* simplify logic in aws role upgrade

* simplify aws credential initialization logic

* simplify logic in aws role upgrade

* use the core's activeContext for initialization

* refactor builtin/plugin/Backend

* use a goroutine to upgrade the aws roles

* misc improvements and cleanup

* do not run AWS role upgrade on DR Secondary

* always call logical.Backend.Initialize() when loading a plugin.

* improve comments

* on standbys and DR secondaries we do not want to run any kind of upgrade logic

* fix awsVersion struct

* clarify aws version upgrade

* make the upgrade logic for aws auth more explicit

* aws upgrade is now called from a switch

* fix fallthrough bug

* simplify logic

* simplify logic

* rename things

* introduce currentAwsVersion const to track aws version

* improve comments

* rearrange things once more

* conglomerate things into one function

* stub out aws auth initialize e2e test

* improve aws auth initialize e2e test

* finish aws auth initialize e2e test

* tinker with aws auth initialize e2e test

* tinker with aws auth initialize e2e test

* tinker with aws auth initialize e2e test

* fix typo in test suite

* simplify logic a tad

* rearrange assignment

* Fix a few lifecycle related issues in #7025 (#7075)

* Fix panic when plugin fails to load
This commit is contained in:
Mike Jarmy
2019-07-05 19:55:40 -04:00
committed by Brian Kassouf
parent 8b9e9ea1ec
commit c48159ea3a
21 changed files with 1135 additions and 342 deletions

View File

@@ -91,13 +91,8 @@ type PluginBackend struct {
loaded bool
}
func (b *PluginBackend) reloadBackend(ctx context.Context) error {
b.Logger().Debug("reloading plugin backend", "plugin", b.config.Config["plugin_name"])
return b.startBackend(ctx)
}
// startBackend starts a plugin backend
func (b *PluginBackend) startBackend(ctx context.Context) error {
func (b *PluginBackend) startBackend(ctx context.Context, storage logical.Storage) error {
pluginName := b.config.Config["plugin_name"]
pluginType, err := consts.ParsePluginType(b.config.Config["plugin_type"])
if err != nil {
@@ -134,11 +129,14 @@ func (b *PluginBackend) startBackend(ctx context.Context) error {
b.Backend = nb
b.loaded = true
return nil
// call Initialize() explicitly here.
return b.Backend.Initialize(ctx, &logical.InitializationRequest{
Storage: storage,
})
}
// HandleRequest is a thin wrapper implementation of HandleRequest that includes automatic plugin reload.
func (b *PluginBackend) HandleRequest(ctx context.Context, req *logical.Request) (*logical.Response, error) {
// lazyLoad lazy-loads the backend before running a method
func (b *PluginBackend) lazyLoadBackend(ctx context.Context, storage logical.Storage, methodWrapper func() error) error {
b.RLock()
canary := b.canary
@@ -149,17 +147,19 @@ func (b *PluginBackend) HandleRequest(ctx context.Context, req *logical.Request)
b.Lock()
// Check once more after lock swap
if !b.loaded {
err := b.startBackend(ctx)
err := b.startBackend(ctx, storage)
if err != nil {
b.Unlock()
return nil, err
return err
}
}
b.Unlock()
b.RLock()
}
resp, err := b.Backend.HandleRequest(ctx, req)
err := methodWrapper()
b.RUnlock()
// Need to compare string value for case were err comes from plugin RPC
// and is returned as plugin.BasicError type.
if err != nil &&
@@ -167,73 +167,60 @@ func (b *PluginBackend) HandleRequest(ctx context.Context, req *logical.Request)
// Reload plugin if it's an rpc.ErrShutdown
b.Lock()
if b.canary == canary {
err := b.reloadBackend(ctx)
b.Logger().Debug("reloading plugin backend", "plugin", b.config.Config["plugin_name"])
err := b.startBackend(ctx, storage)
if err != nil {
b.Unlock()
return nil, err
return err
}
b.canary, err = uuid.GenerateUUID()
if err != nil {
b.Unlock()
return nil, err
return err
}
}
b.Unlock()
// Try request once more
// Try once more
b.RLock()
defer b.RUnlock()
return b.Backend.HandleRequest(ctx, req)
return methodWrapper()
}
return resp, err
return err
}
// HandleExistenceCheck is a thin wrapper implementation of HandleRequest that includes automatic plugin reload.
func (b *PluginBackend) HandleExistenceCheck(ctx context.Context, req *logical.Request) (bool, bool, error) {
b.RLock()
canary := b.canary
// HandleRequest is a thin wrapper implementation of HandleRequest that includes automatic plugin reload.
func (b *PluginBackend) HandleRequest(ctx context.Context, req *logical.Request) (resp *logical.Response, err error) {
// Lazy-load backend
if !b.loaded {
// Upgrade lock
b.RUnlock()
b.Lock()
// Check once more after lock swap
if !b.loaded {
err := b.startBackend(ctx)
if err != nil {
b.Unlock()
return false, false, err
}
}
b.Unlock()
b.RLock()
}
err = b.lazyLoadBackend(ctx, req.Storage, func() error {
var merr error
resp, merr = b.Backend.HandleRequest(ctx, req)
return merr
})
checkFound, exists, err := b.Backend.HandleExistenceCheck(ctx, req)
b.RUnlock()
if err != nil &&
(err.Error() == rpc.ErrShutdown.Error() || err == bplugin.ErrPluginShutdown) {
// Reload plugin if it's an rpc.ErrShutdown
b.Lock()
if b.canary == canary {
err := b.reloadBackend(ctx)
if err != nil {
b.Unlock()
return false, false, err
}
b.canary, err = uuid.GenerateUUID()
if err != nil {
b.Unlock()
return false, false, err
}
}
b.Unlock()
// Try request once more
b.RLock()
defer b.RUnlock()
return b.Backend.HandleExistenceCheck(ctx, req)
}
return checkFound, exists, err
return
}
// HandleExistenceCheck is a thin wrapper implementation of HandleExistenceCheck that includes automatic plugin reload.
func (b *PluginBackend) HandleExistenceCheck(ctx context.Context, req *logical.Request) (checkFound bool, exists bool, err error) {
err = b.lazyLoadBackend(ctx, req.Storage, func() error {
var merr error
checkFound, exists, merr = b.Backend.HandleExistenceCheck(ctx, req)
return merr
})
return
}
// Initialize is a thin wrapper implementation of Initialize that includes automatic plugin reload.
func (b *PluginBackend) Initialize(ctx context.Context, req *logical.InitializationRequest) error {
// This method is only ever called just after mounting, so we know that the
// call to lazyLoadBackend() will call startBackend(). Since
// startBackend() calls Initialize() on the underlying logical.Backend, the
// method wrapper that we pass in here is a no-op
return b.lazyLoadBackend(ctx, req.Storage, func() error {
return nil
})
}