Skip to content

Commit

Permalink
Add ability to disable an entity (#4353)
Browse files Browse the repository at this point in the history
  • Loading branch information
jefferai authored Apr 14, 2018
1 parent 12fbbaa commit b65832d
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 59 deletions.
89 changes: 50 additions & 39 deletions helper/identity/types.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions helper/identity/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ message Entity {
// MFASecrets holds the MFA secrets indexed by the identifier of the MFA
// method configuration.
//map<string, mfa.Secret> mfa_secrets = 10;

// Disabled indicates whether tokens associated with the account should not
// be able to be used
bool disabled = 11;
}

// Alias represents the alias that gets stored inside of the
Expand Down
4 changes: 4 additions & 0 deletions logical/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,10 @@ var (
// ErrPermissionDenied is returned if the client is not authorized
ErrPermissionDenied = errors.New("permission denied")

// ErrDisabledEntity is returned if the entity tied to a token is marked as
// disabled
ErrEntityDisabled = errors.New("entity associated with token is disabled")

// ErrMultiAuthzPending is returned if the the request needs more
// authorizations
ErrMultiAuthzPending = errors.New("request needs further approval")
Expand Down
59 changes: 40 additions & 19 deletions vault/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,10 @@ func (c *Core) checkToken(ctx context.Context, req *logical.Request, unauth bool
}
}

if entity != nil && entity.Disabled {
return nil, te, logical.ErrEntityDisabled
}

// Check if this is a root protected path
rootPath := c.router.RootPath(req.Path)

Expand Down Expand Up @@ -1319,20 +1323,21 @@ func (c *Core) sealInitCommon(ctx context.Context, req *logical.Request) (retErr
return retErr
}

// Since there is no token store in standby nodes, sealing cannot be done.
// Ideally, the request has to be forwarded to leader node for validation
// and the operation should be performed. But for now, just returning with
// an error and recommending a vault restart, which essentially does the
// same thing.
if c.standby {
c.logger.Error("vault cannot seal when in standby mode; please restart instead")
retErr = multierror.Append(retErr, errors.New("vault cannot seal when in standby mode; please restart instead"))
c.stateLock.RUnlock()
return retErr
}

// Validate the token is a root token
acl, te, entity, err := c.fetchACLTokenEntryAndEntity(req.ClientToken)
if err != nil {
// Since there is no token store in standby nodes, sealing cannot
// be done. Ideally, the request has to be forwarded to leader node
// for validation and the operation should be performed. But for now,
// just returning with an error and recommending a vault restart, which
// essentially does the same thing.
if c.standby {
c.logger.Error("vault cannot seal when in standby mode; please restart instead")
retErr = multierror.Append(retErr, errors.New("vault cannot seal when in standby mode; please restart instead"))
c.stateLock.RUnlock()
return retErr
}
retErr = multierror.Append(retErr, err)
c.stateLock.RUnlock()
return retErr
Expand All @@ -1341,10 +1346,12 @@ func (c *Core) sealInitCommon(ctx context.Context, req *logical.Request) (retErr
// Audit-log the request before going any further
auth := &logical.Auth{
ClientToken: req.ClientToken,
Policies: te.Policies,
Metadata: te.Meta,
DisplayName: te.DisplayName,
EntityID: te.EntityID,
}
if te != nil {
auth.Policies = te.Policies
auth.Metadata = te.Meta
auth.DisplayName = te.DisplayName
auth.EntityID = te.EntityID
}

logInput := &audit.LogInput{
Expand All @@ -1358,6 +1365,12 @@ func (c *Core) sealInitCommon(ctx context.Context, req *logical.Request) (retErr
return retErr
}

if entity != nil && entity.Disabled {
retErr = multierror.Append(retErr, logical.ErrEntityDisabled)
c.stateLock.RUnlock()
return retErr
}

// Attempt to use the token (decrement num_uses)
// On error bail out; if the token has been revoked, bail out too
if te != nil {
Expand Down Expand Up @@ -1450,10 +1463,12 @@ func (c *Core) StepDown(req *logical.Request) (retErr error) {
// Audit-log the request before going any further
auth := &logical.Auth{
ClientToken: req.ClientToken,
Policies: te.Policies,
Metadata: te.Meta,
DisplayName: te.DisplayName,
EntityID: te.EntityID,
}
if te != nil {
auth.Policies = te.Policies
auth.Metadata = te.Meta
auth.DisplayName = te.DisplayName
auth.EntityID = te.EntityID
}

logInput := &audit.LogInput{
Expand All @@ -1466,6 +1481,12 @@ func (c *Core) StepDown(req *logical.Request) (retErr error) {
return retErr
}

if entity != nil && entity.Disabled {
retErr = multierror.Append(retErr, logical.ErrEntityDisabled)
c.stateLock.RUnlock()
return retErr
}

// Attempt to use the token (decrement num_uses)
if te != nil {
te, err = c.tokenStore.UseToken(ctx, te)
Expand Down
14 changes: 14 additions & 0 deletions vault/identity_store_entities.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ vault <command> <path> metadata=key1=value1 metadata=key2=value2
Type: framework.TypeCommaStringSlice,
Description: "Policies to be tied to the entity.",
},
"disabled": {
Type: framework.TypeBool,
Description: "If set true, tokens tied to this identity will not be able to be used (but will not be revoked).",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.UpdateOperation: i.pathEntityRegister(),
Expand Down Expand Up @@ -76,6 +80,10 @@ vault <command> <path> metadata=key1=value1 metadata=key2=value2
Type: framework.TypeCommaStringSlice,
Description: "Policies to be tied to the entity.",
},
"disabled": {
Type: framework.TypeBool,
Description: "If set true, tokens tied to this identity will not be able to be used (but will not be revoked).",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.UpdateOperation: i.pathEntityIDUpdate(),
Expand Down Expand Up @@ -354,6 +362,11 @@ func (i *IdentityStore) handleEntityUpdateCommon(req *logical.Request, d *framew
entity.Policies = entityPoliciesRaw.([]string)
}

disabledRaw, ok := d.GetOk("disabled")
if ok {
entity.Disabled = disabledRaw.(bool)
}

// Get the name
entityName := d.Get("name").(string)
if entityName != "" {
Expand Down Expand Up @@ -434,6 +447,7 @@ func (i *IdentityStore) handleEntityReadCommon(entity *identity.Entity) (*logica
respData["metadata"] = entity.Metadata
respData["merged_entity_ids"] = entity.MergedEntityIDs
respData["policies"] = entity.Policies
respData["disabled"] = entity.Disabled

// Convert protobuf timestamp into RFC3339 format
respData["creation_time"] = ptypes.TimestampString(entity.CreationTime)
Expand Down
Loading

0 comments on commit b65832d

Please sign in to comment.