backport of commit cccfdb088f218f5631195e8b653c07a77cfac2b5 (#22596)

Co-authored-by: Ellie <ellie.sterner@hashicorp.com>
This commit is contained in:
hc-github-team-secure-vault-core 2023-08-28 19:16:57 -04:00 committed by GitHub
parent eb7de7129a
commit d13671c155
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 9 deletions

3
changelog/22583.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
core/quotas: Reduce overhead for role calculation when using cloud auth methods.
```

View File

@ -5,6 +5,7 @@ package http
import ( import (
"bytes" "bytes"
"context"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -63,11 +64,16 @@ func rateLimitQuotaWrapping(handler http.Handler, core *vault.Core) http.Handler
} }
r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
role := core.DetermineRoleFromLoginRequestFromBytes(mountPath, bodyBytes, r.Context())
// add an entry to the context to prevent recalculating request role unnecessarily
r = r.WithContext(context.WithValue(r.Context(), logical.CtxKeyRequestRole{}, role))
quotaResp, err := core.ApplyRateLimitQuota(r.Context(), &quotas.Request{ quotaResp, err := core.ApplyRateLimitQuota(r.Context(), &quotas.Request{
Type: quotas.TypeRateLimit, Type: quotas.TypeRateLimit,
Path: path, Path: path,
MountPath: mountPath, MountPath: mountPath,
Role: core.DetermineRoleFromLoginRequestFromBytes(mountPath, bodyBytes, r.Context()), Role: role,
NamespacePath: ns.Path, NamespacePath: ns.Path,
ClientAddress: parseRemoteIPAddress(r), ClientAddress: parseRemoteIPAddress(r),
}) })

View File

@ -447,3 +447,9 @@ type CtxKeyInFlightRequestID struct{}
func (c CtxKeyInFlightRequestID) String() string { func (c CtxKeyInFlightRequestID) String() string {
return "in-flight-request-ID" return "in-flight-request-ID"
} }
type CtxKeyRequestRole struct{}
func (c CtxKeyRequestRole) String() string {
return "request-role"
}

View File

@ -842,12 +842,17 @@ func (c *Core) LoginMFACreateToken(ctx context.Context, reqPath string, cachedAu
return nil, fmt.Errorf("namespace not found: %w", err) return nil, fmt.Errorf("namespace not found: %w", err)
} }
var role string
if reqRole := ctx.Value(logical.CtxKeyRequestRole{}); reqRole != nil {
role = reqRole.(string)
}
// The request successfully authenticated itself. Run the quota checks on // The request successfully authenticated itself. Run the quota checks on
// the original login request path before creating the token. // the original login request path before creating the token.
quotaResp, quotaErr := c.applyLeaseCountQuota(ctx, &quotas.Request{ quotaResp, quotaErr := c.applyLeaseCountQuota(ctx, &quotas.Request{
Path: reqPath, Path: reqPath,
MountPath: strings.TrimPrefix(mountPoint, ns.Path), MountPath: strings.TrimPrefix(mountPoint, ns.Path),
Role: c.DetermineRoleFromLoginRequest(mountPoint, loginRequestData, ctx), Role: role,
NamespacePath: ns.Path, NamespacePath: ns.Path,
}) })
@ -867,7 +872,7 @@ func (c *Core) LoginMFACreateToken(ctx context.Context, reqPath string, cachedAu
// note that we don't need to handle the error for the following function right away. // note that we don't need to handle the error for the following function right away.
// The function takes the response as in input variable and modify it. So, the returned // The function takes the response as in input variable and modify it. So, the returned
// arguments are resp and err. // arguments are resp and err.
leaseGenerated, resp, err := c.LoginCreateToken(ctx, ns, reqPath, mountPoint, resp, loginRequestData) leaseGenerated, resp, err := c.LoginCreateToken(ctx, ns, reqPath, mountPoint, role, resp)
if quotaResp.Access != nil { if quotaResp.Access != nil {
quotaAckErr := c.ackLeaseQuota(quotaResp.Access, leaseGenerated) quotaAckErr := c.ackLeaseQuota(quotaResp.Access, leaseGenerated)

View File

@ -489,6 +489,10 @@ func (c *Core) switchedLockHandleRequest(httpCtx context.Context, req *logical.R
if ok { if ok {
ctx = context.WithValue(ctx, logical.CtxKeyInFlightRequestID{}, inFlightReqID) ctx = context.WithValue(ctx, logical.CtxKeyInFlightRequestID{}, inFlightReqID)
} }
requestRole, ok := httpCtx.Value(logical.CtxKeyRequestRole{}).(string)
if ok {
ctx = context.WithValue(ctx, logical.CtxKeyRequestRole{}, requestRole)
}
resp, err = c.handleCancelableRequest(ctx, req) resp, err = c.handleCancelableRequest(ctx, req)
req.SetTokenEntry(nil) req.SetTokenEntry(nil)
cancel() cancel()
@ -1248,7 +1252,14 @@ func (c *Core) handleRequest(ctx context.Context, req *logical.Request) (retResp
Path: resp.Auth.CreationPath, Path: resp.Auth.CreationPath,
NamespaceID: ns.ID, NamespaceID: ns.ID,
} }
if err := c.expiration.RegisterAuth(ctx, registeredTokenEntry, resp.Auth, c.DetermineRoleFromLoginRequest(req.MountPoint, req.Data, ctx)); err != nil {
// Check for request role
var role string
if reqRole := ctx.Value(logical.CtxKeyRequestRole{}); reqRole != nil {
role = reqRole.(string)
}
if err := c.expiration.RegisterAuth(ctx, registeredTokenEntry, resp.Auth, role); err != nil {
// Best-effort clean up on error, so we log the cleanup error as // Best-effort clean up on error, so we log the cleanup error as
// a warning but still return as internal error. // a warning but still return as internal error.
if err := c.tokenStore.revokeOrphan(ctx, resp.Auth.ClientToken); err != nil { if err := c.tokenStore.revokeOrphan(ctx, resp.Auth.ClientToken); err != nil {
@ -1477,12 +1488,18 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
return return
} }
// Check for request role
var role string
if reqRole := ctx.Value(logical.CtxKeyRequestRole{}); reqRole != nil {
role = reqRole.(string)
}
// The request successfully authenticated itself. Run the quota checks // The request successfully authenticated itself. Run the quota checks
// before creating lease. // before creating lease.
quotaResp, quotaErr := c.applyLeaseCountQuota(ctx, &quotas.Request{ quotaResp, quotaErr := c.applyLeaseCountQuota(ctx, &quotas.Request{
Path: req.Path, Path: req.Path,
MountPath: strings.TrimPrefix(req.MountPoint, ns.Path), MountPath: strings.TrimPrefix(req.MountPoint, ns.Path),
Role: c.DetermineRoleFromLoginRequest(req.MountPoint, req.Data, ctx), Role: role,
NamespacePath: ns.Path, NamespacePath: ns.Path,
}) })
@ -1674,7 +1691,7 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
// Attach the display name, might be used by audit backends // Attach the display name, might be used by audit backends
req.DisplayName = auth.DisplayName req.DisplayName = auth.DisplayName
leaseGen, respTokenCreate, errCreateToken := c.LoginCreateToken(ctx, ns, req.Path, source, resp, req.Data) leaseGen, respTokenCreate, errCreateToken := c.LoginCreateToken(ctx, ns, req.Path, source, role, resp)
leaseGenerated = leaseGen leaseGenerated = leaseGen
if errCreateToken != nil { if errCreateToken != nil {
return respTokenCreate, nil, errCreateToken return respTokenCreate, nil, errCreateToken
@ -1726,9 +1743,8 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
// LoginCreateToken creates a token as a result of a login request. // LoginCreateToken creates a token as a result of a login request.
// If MFA is enforced, mfa/validate endpoint calls this functions // If MFA is enforced, mfa/validate endpoint calls this functions
// after successful MFA validation to generate the token. // after successful MFA validation to generate the token.
func (c *Core) LoginCreateToken(ctx context.Context, ns *namespace.Namespace, reqPath, mountPoint string, resp *logical.Response, loginRequestData map[string]interface{}) (bool, *logical.Response, error) { func (c *Core) LoginCreateToken(ctx context.Context, ns *namespace.Namespace, reqPath, mountPoint, role string, resp *logical.Response) (bool, *logical.Response, error) {
auth := resp.Auth auth := resp.Auth
source := strings.TrimPrefix(mountPoint, credentialRoutePrefix) source := strings.TrimPrefix(mountPoint, credentialRoutePrefix)
source = strings.ReplaceAll(source, "/", "-") source = strings.ReplaceAll(source, "/", "-")
@ -1788,7 +1804,7 @@ func (c *Core) LoginCreateToken(ctx context.Context, ns *namespace.Namespace, re
} }
leaseGenerated := false leaseGenerated := false
err = registerFunc(ctx, tokenTTL, reqPath, auth, c.DetermineRoleFromLoginRequest(mountPoint, loginRequestData, ctx)) err = registerFunc(ctx, tokenTTL, reqPath, auth, role)
switch { switch {
case err == nil: case err == nil:
if auth.TokenType != logical.TokenTypeBatch { if auth.TokenType != logical.TokenTypeBatch {