Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport of VAULT-8337 OSS changes into release/1.13.x #19622

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions vault/request_handling.go
Original file line number Diff line number Diff line change
Expand Up @@ -2199,8 +2199,9 @@ func (c *Core) PopulateTokenEntry(ctx context.Context, req *logical.Request) err
token := req.ClientToken
var err error
req.InboundSSCToken = token
decodedToken := token
if IsSSCToken(token) {
token, err = c.CheckSSCToken(ctx, token, c.isLoginRequest(ctx, req), c.perfStandby)
decodedToken, err = c.CheckSSCToken(ctx, token, c.isLoginRequest(ctx, req), c.perfStandby)
// If we receive an error from CheckSSCToken, we can assume the token is bad somehow, and the client
// should receive a 403 bad token error like they do for all other invalid tokens, unless the error
// specifies that we should forward the request or retry the request.
Expand All @@ -2211,12 +2212,18 @@ func (c *Core) PopulateTokenEntry(ctx context.Context, req *logical.Request) err
return logical.ErrPermissionDenied
}
}
req.ClientToken = token
req.ClientToken = decodedToken
// We ignore the token returned from CheckSSCToken here as Lookup also decodes the SSCT, and
// it may need the original SSCT to check state.
te, err := c.LookupToken(ctx, token)
if err != nil {
// If we're missing required state, return that error as-is to the client
if errors.Is(err, logical.ErrPerfStandbyPleaseForward) || errors.Is(err, logical.ErrMissingRequiredState) {
return err
}
// If we have two dots but the second char is a dot it's a vault
// token of the form s.SOMETHING.nsid, not a JWT
if !IsJWT(token) {
if !IsJWT(decodedToken) {
return fmt.Errorf("error performing token check: %w", err)
}
}
Expand Down
15 changes: 15 additions & 0 deletions vault/token_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -1557,6 +1557,10 @@ func (ts *TokenStore) lookupInternal(ctx context.Context, id string, salted, tai
return ts.lookupBatchToken(ctx, id)
}

// Before we check to see if this is an SSCT, keep the old value in case
// we need to check the full SSCT flow later.
originalToken := id

// lookupInternal is called internally with tokens that oftentimes come from request
// parameters that we cannot really guess. Most notably, these calls come from either
// validateWrappedToken and/or lookupTokenTainted, used in the wrapping token logic.
Expand Down Expand Up @@ -1700,6 +1704,17 @@ func (ts *TokenStore) lookupInternal(ctx context.Context, id string, salted, tai
// It's any kind of expiring token with no lease, immediately delete it
case le == nil:
if ts.core.perfStandby {
// If we're a perf standby with a token but without the lease entry, then
// we have the WALs for the token but not the lease entry. We should check
// the SSCToken again to validate our state. We will receive a 412 if we
// don't have the requisite state.
// We set unauth to 'false' here as we want to validate the full SSCT flow
// and if we're at this point in the method, we have reason to need the token.
_, err = ts.core.CheckSSCToken(ctx, originalToken, false, ts.core.perfStandby)
if err != nil {
return nil, err
}
// If we don't have a state error, and we're still here, return a 500.
return nil, fmt.Errorf("no lease entry found for token that ought to have one, possible eventual consistency issue")
}

Expand Down