mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 18:17:55 +00:00
On lease deletion, also delete non-orphan batch token parent index (#11377)
This commit is contained in:
3
changelog/11377.txt
Normal file
3
changelog/11377.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:bug
|
||||||
|
core: Fix storage entry leak when revoking leases created with non-orphan batch tokens.
|
||||||
|
```
|
||||||
@@ -915,8 +915,24 @@ func (m *ExpirationManager) revokeCommon(ctx context.Context, leaseID string, fo
|
|||||||
|
|
||||||
// Delete the secondary index, but only if it's a leased secret (not auth)
|
// Delete the secondary index, but only if it's a leased secret (not auth)
|
||||||
if le.Secret != nil {
|
if le.Secret != nil {
|
||||||
if err := m.removeIndexByToken(ctx, le); err != nil {
|
var indexToken string
|
||||||
return err
|
// Maintain secondary index by token, except for orphan batch tokens
|
||||||
|
switch le.ClientTokenType {
|
||||||
|
case logical.TokenTypeBatch:
|
||||||
|
te, err := m.tokenStore.lookupBatchTokenInternal(ctx, le.ClientToken)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// If it's a non-orphan batch token, assign the secondary index to its
|
||||||
|
// parent
|
||||||
|
indexToken = te.Parent
|
||||||
|
default:
|
||||||
|
indexToken = le.ClientToken
|
||||||
|
}
|
||||||
|
if indexToken != "" {
|
||||||
|
if err := m.removeIndexByToken(ctx, le, indexToken); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1364,6 +1380,17 @@ func (m *ExpirationManager) Register(ctx context.Context, req *logical.Request,
|
|||||||
Version: 1,
|
Version: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var indexToken string
|
||||||
|
// Maintain secondary index by token, except for orphan batch tokens
|
||||||
|
switch {
|
||||||
|
case te.Type != logical.TokenTypeBatch:
|
||||||
|
indexToken = le.ClientToken
|
||||||
|
case te.Parent != "":
|
||||||
|
// If it's a non-orphan batch token, assign the secondary index to its
|
||||||
|
// parent
|
||||||
|
indexToken = te.Parent
|
||||||
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
// If there is an error we want to rollback as much as possible (note
|
// If there is an error we want to rollback as much as possible (note
|
||||||
// that errors here are ignored to do as much cleanup as we can). We
|
// that errors here are ignored to do as much cleanup as we can). We
|
||||||
@@ -1382,7 +1409,7 @@ func (m *ExpirationManager) Register(ctx context.Context, req *logical.Request,
|
|||||||
retErr = multierror.Append(retErr, errwrap.Wrapf("an additional error was encountered deleting any lease associated with the newly-generated secret: {{err}}", err))
|
retErr = multierror.Append(retErr, errwrap.Wrapf("an additional error was encountered deleting any lease associated with the newly-generated secret: {{err}}", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.removeIndexByToken(ctx, le); err != nil {
|
if err := m.removeIndexByToken(ctx, le, indexToken); err != nil {
|
||||||
retErr = multierror.Append(retErr, errwrap.Wrapf("an additional error was encountered removing lease indexes associated with the newly-generated secret: {{err}}", err))
|
retErr = multierror.Append(retErr, errwrap.Wrapf("an additional error was encountered removing lease indexes associated with the newly-generated secret: {{err}}", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1408,16 +1435,8 @@ func (m *ExpirationManager) Register(ctx context.Context, req *logical.Request,
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maintain secondary index by token, except for orphan batch tokens
|
if indexToken != "" {
|
||||||
switch {
|
if err := m.createIndexByToken(ctx, le, indexToken); err != nil {
|
||||||
case te.Type != logical.TokenTypeBatch:
|
|
||||||
if err := m.createIndexByToken(ctx, le, le.ClientToken); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
case te.Parent != "":
|
|
||||||
// If it's a non-orphan batch token, assign the secondary index to its
|
|
||||||
// parent
|
|
||||||
if err := m.createIndexByToken(ctx, le, te.Parent); err != nil {
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1966,10 +1985,10 @@ func (m *ExpirationManager) indexByToken(ctx context.Context, le *leaseEntry) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// removeIndexByToken removes the secondary index from the token to a lease entry
|
// removeIndexByToken removes the secondary index from the token to a lease entry
|
||||||
func (m *ExpirationManager) removeIndexByToken(ctx context.Context, le *leaseEntry) error {
|
func (m *ExpirationManager) removeIndexByToken(ctx context.Context, le *leaseEntry, token string) error {
|
||||||
tokenNS := namespace.RootNamespace
|
tokenNS := namespace.RootNamespace
|
||||||
saltCtx := namespace.ContextWithNamespace(ctx, namespace.RootNamespace)
|
saltCtx := namespace.ContextWithNamespace(ctx, namespace.RootNamespace)
|
||||||
_, nsID := namespace.SplitIDFromString(le.ClientToken)
|
_, nsID := namespace.SplitIDFromString(token)
|
||||||
if nsID != "" {
|
if nsID != "" {
|
||||||
var err error
|
var err error
|
||||||
tokenNS, err = NamespaceByID(ctx, nsID, m.core)
|
tokenNS, err = NamespaceByID(ctx, nsID, m.core)
|
||||||
@@ -1990,7 +2009,7 @@ func (m *ExpirationManager) removeIndexByToken(ctx context.Context, le *leaseEnt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saltedID, err := m.tokenStore.SaltID(saltCtx, le.ClientToken)
|
saltedID, err := m.tokenStore.SaltID(saltCtx, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -677,7 +677,8 @@ func TestExpiration_Register(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestExpiration_Register_BatchToken(t *testing.T) {
|
func TestExpiration_Register_BatchToken(t *testing.T) {
|
||||||
exp := mockExpiration(t)
|
c, _, rootToken := TestCoreUnsealed(t)
|
||||||
|
exp := c.expiration
|
||||||
noop := &NoopBackend{
|
noop := &NoopBackend{
|
||||||
RequestHandler: func(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
RequestHandler: func(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
||||||
resp := &logical.Response{Secret: req.Secret}
|
resp := &logical.Response{Secret: req.Secret}
|
||||||
@@ -685,15 +686,17 @@ func TestExpiration_Register_BatchToken(t *testing.T) {
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, barrier, _ := mockBarrier(t)
|
{
|
||||||
view := NewBarrierView(barrier, "logical/")
|
_, barrier, _ := mockBarrier(t)
|
||||||
meUUID, err := uuid.GenerateUUID()
|
view := NewBarrierView(barrier, "logical/")
|
||||||
if err != nil {
|
meUUID, err := uuid.GenerateUUID()
|
||||||
t.Fatal(err)
|
if err != nil {
|
||||||
}
|
t.Fatal(err)
|
||||||
err = exp.router.Mount(noop, "prod/aws/", &MountEntry{Path: "prod/aws/", Type: "noop", UUID: meUUID, Accessor: "noop-accessor", namespace: namespace.RootNamespace}, view)
|
}
|
||||||
if err != nil {
|
err = exp.router.Mount(noop, "prod/aws/", &MountEntry{Path: "prod/aws/", Type: "noop", UUID: meUUID, Accessor: "noop-accessor", namespace: namespace.RootNamespace}, view)
|
||||||
t.Fatal(err)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
te := &logical.TokenEntry{
|
te := &logical.TokenEntry{
|
||||||
@@ -701,9 +704,10 @@ func TestExpiration_Register_BatchToken(t *testing.T) {
|
|||||||
TTL: 1 * time.Second,
|
TTL: 1 * time.Second,
|
||||||
NamespaceID: "root",
|
NamespaceID: "root",
|
||||||
CreationTime: time.Now().Unix(),
|
CreationTime: time.Now().Unix(),
|
||||||
|
Parent: rootToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = exp.tokenStore.create(context.Background(), te)
|
err := exp.tokenStore.create(context.Background(), te)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -760,6 +764,13 @@ func TestExpiration_Register_BatchToken(t *testing.T) {
|
|||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
idEnts, err := exp.tokenView.List(context.Background(), "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(idEnts) != 0 {
|
||||||
|
t.Fatalf("expected no entries in sys/expire/token, got: %v", idEnts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExpiration_RegisterAuth(t *testing.T) {
|
func TestExpiration_RegisterAuth(t *testing.T) {
|
||||||
|
|||||||
@@ -1122,7 +1122,7 @@ func (ts *TokenStore) lookupTainted(ctx context.Context, id string) (*logical.To
|
|||||||
return ts.lookupInternal(ctx, id, false, true)
|
return ts.lookupInternal(ctx, id, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ts *TokenStore) lookupBatchToken(ctx context.Context, id string) (*logical.TokenEntry, error) {
|
func (ts *TokenStore) lookupBatchTokenInternal(ctx context.Context, id string) (*logical.TokenEntry, error) {
|
||||||
// Strip the b. from the front and namespace ID from the back
|
// Strip the b. from the front and namespace ID from the back
|
||||||
bEntry, _ := namespace.SplitIDFromString(id[2:])
|
bEntry, _ := namespace.SplitIDFromString(id[2:])
|
||||||
|
|
||||||
@@ -1146,6 +1146,16 @@ func (ts *TokenStore) lookupBatchToken(ctx context.Context, id string) (*logical
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
te.ID = id
|
||||||
|
return te, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts *TokenStore) lookupBatchToken(ctx context.Context, id string) (*logical.TokenEntry, error) {
|
||||||
|
te, err := ts.lookupBatchTokenInternal(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if time.Now().After(time.Unix(te.CreationTime, 0).Add(te.TTL)) {
|
if time.Now().After(time.Unix(te.CreationTime, 0).Add(te.TTL)) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -1160,7 +1170,6 @@ func (ts *TokenStore) lookupBatchToken(ctx context.Context, id string) (*logical
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
te.ID = id
|
|
||||||
return te, nil
|
return te, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user