mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-05 04:16:31 +02:00
Merge remote-tracking branch 'remotes/from/ce/main'
This commit is contained in:
commit
407557ce87
@ -57,6 +57,14 @@ var sudoPaths = map[string]*regexp.Regexp{
|
||||
"/sys/storage/raft/snapshot-auto/config": regexp.MustCompile(`^/sys/storage/raft/snapshot-auto/config/?$`),
|
||||
"/sys/storage/raft/snapshot-auto/config/{name}": regexp.MustCompile(`^/sys/storage/raft/snapshot-auto/config/[^/]+$`),
|
||||
"/sys/reporting/scan": regexp.MustCompile(`^/sys/reporting/scan$`),
|
||||
|
||||
// activation-flags paths requiring sudo
|
||||
"/sys/activation-flags/oauth-resource-server/activate": regexp.MustCompile(`^/sys/activation-flags/oauth-resource-server/activate$`),
|
||||
"/sys/activation-flags/oauth-resource-server/deactivate": regexp.MustCompile(`^/sys/activation-flags/oauth-resource-server/deactivate$`),
|
||||
|
||||
// OAuth resource server profile paths requiring sudo
|
||||
"/sys/config/oauth-resource-server/{name}": regexp.MustCompile(`^/sys/config/oauth-resource-server/[^/]+$`),
|
||||
"/sys/config/oauth-resource-server": regexp.MustCompile(`^/sys/config/oauth-resource-server$`),
|
||||
}
|
||||
|
||||
func SudoPaths() map[string]*regexp.Regexp {
|
||||
|
||||
2
go.mod
2
go.mod
@ -41,6 +41,8 @@ require (
|
||||
github.com/Azure/azure-storage-blob-go v0.15.0
|
||||
github.com/Azure/go-autorest/autorest v0.11.29
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.24
|
||||
github.com/MicahParks/jwkset v0.11.0
|
||||
github.com/MicahParks/keyfunc/v3 v3.7.0
|
||||
github.com/ProtonMail/go-crypto v1.3.0
|
||||
github.com/ProtonMail/gopenpgp/v3 v3.2.1
|
||||
github.com/SAP/go-hdb v1.10.1
|
||||
|
||||
4
go.sum
4
go.sum
@ -147,6 +147,10 @@ github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1
|
||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
|
||||
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
|
||||
github.com/MicahParks/jwkset v0.11.0 h1:yc0zG+jCvZpWgFDFmvs8/8jqqVBG9oyIbmBtmjOhoyQ=
|
||||
github.com/MicahParks/jwkset v0.11.0/go.mod h1:U2oRhRaLgDCLjtpGL2GseNKGmZtLs/3O7p+OZaL5vo0=
|
||||
github.com/MicahParks/keyfunc/v3 v3.7.0 h1:pdafUNyq+p3ZlvjJX1HWFP7MA3+cLpDtg69U3kITJGM=
|
||||
github.com/MicahParks/keyfunc/v3 v3.7.0/go.mod h1:z66bkCviwqfg2YUp+Jcc/xRE9IXLcMq6DrgV/+Htru0=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
|
||||
@ -1094,7 +1094,7 @@ func (m *ExpirationManager) revokeCommon(ctx context.Context, leaseID string, fo
|
||||
// Delete the secondary index, but only if it's a leased secret (not auth)
|
||||
if le.Secret != nil {
|
||||
var indexToken string
|
||||
// Maintain secondary index by token, except for orphan batch tokens
|
||||
// Maintain secondary index by token, except for orphan batch tokens and ent tokens
|
||||
switch le.ClientTokenType {
|
||||
case logical.TokenTypeBatch:
|
||||
te, err := m.tokenStore.lookupBatchTokenInternal(ctx, le.ClientToken)
|
||||
@ -1108,6 +1108,9 @@ func (m *ExpirationManager) revokeCommon(ctx context.Context, leaseID string, fo
|
||||
// parent
|
||||
indexToken = te.Parent
|
||||
}
|
||||
case logical.TokenTypeEnt:
|
||||
// ent tokens don't maintain parent relationships; just use the token itself
|
||||
indexToken = le.ClientToken
|
||||
default:
|
||||
indexToken = le.ClientToken
|
||||
}
|
||||
@ -1656,6 +1659,15 @@ func (m *ExpirationManager) Register(ctx context.Context, req *logical.Request,
|
||||
}
|
||||
}
|
||||
|
||||
// If the token is an ent token, derive TTL from the ent token
|
||||
if te.Type == logical.TokenTypeEnt {
|
||||
entTokenExpireTime := deriveExpireTimeFromEntToken(te)
|
||||
if !entTokenExpireTime.IsZero() && le.ExpireTime.After(entTokenExpireTime) {
|
||||
// Use the ent token's expiration time for the lease
|
||||
le.ExpireTime = entTokenExpireTime
|
||||
}
|
||||
}
|
||||
|
||||
// Acquire the lock here so persistEntry and updatePending are atomic,
|
||||
// although it is *very unlikely* that anybody could grab the lease ID
|
||||
// before this function returns. (They could find it in an index, or
|
||||
@ -1714,6 +1726,14 @@ func (m *ExpirationManager) RegisterAuth(ctx context.Context, te *logical.TokenE
|
||||
|
||||
authExpirationTime := auth.ExpirationTime()
|
||||
|
||||
// For ent tokens, derive expiration from ent token
|
||||
if te.Type == logical.TokenTypeEnt {
|
||||
entTokenExpireTime := deriveExpireTimeFromEntToken(te)
|
||||
if !entTokenExpireTime.IsZero() {
|
||||
authExpirationTime = entTokenExpireTime
|
||||
}
|
||||
}
|
||||
|
||||
if te.TTL == 0 && authExpirationTime.IsZero() && (len(te.Policies) != 1 || te.Policies[0] != "root") {
|
||||
return errors.New("refusing to register a lease for a non-root token with no TTL")
|
||||
}
|
||||
@ -1815,6 +1835,19 @@ func (m *ExpirationManager) FetchLeaseTimesByToken(ctx context.Context, te *logi
|
||||
}, nil
|
||||
}
|
||||
|
||||
if te.Type == logical.TokenTypeEnt {
|
||||
entTokenExpireTime := deriveExpireTimeFromEntToken(te)
|
||||
if !entTokenExpireTime.IsZero() {
|
||||
issueTime := time.Unix(te.CreationTime, 0)
|
||||
return &leaseEntry{
|
||||
IssueTime: issueTime,
|
||||
ExpireTime: entTokenExpireTime,
|
||||
ClientTokenType: logical.TokenTypeEnt,
|
||||
}, nil
|
||||
}
|
||||
return nil, errors.New("enterprise token has no valid expiration time")
|
||||
}
|
||||
|
||||
tokenNS, err := NamespaceByID(ctx, te.NamespaceID, m.core)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -2109,6 +2142,11 @@ func (m *ExpirationManager) revokeEntry(ctx context.Context, le *leaseEntry) err
|
||||
return errors.New("batch tokens cannot be revoked")
|
||||
}
|
||||
|
||||
// ent tokens are managed by external IdPs and should not be revoked through Vault backends
|
||||
if le.ClientTokenType == logical.TokenTypeEnt {
|
||||
return errors.New("enterprise tokens are managed by external IdPs and cannot be revoked by Vault")
|
||||
}
|
||||
|
||||
if err := m.tokenStore.revokeTree(ctx, le); err != nil {
|
||||
return fmt.Errorf("failed to revoke token: %w", err)
|
||||
}
|
||||
@ -2159,6 +2197,10 @@ func (m *ExpirationManager) renewAuthEntry(ctx context.Context, req *logical.Req
|
||||
return logical.ErrorResponse("batch tokens cannot be renewed"), nil
|
||||
}
|
||||
|
||||
if le.ClientTokenType == logical.TokenTypeEnt {
|
||||
return logical.ErrorResponse("enterprise tokens cannot be renewed"), nil
|
||||
}
|
||||
|
||||
auth := *le.Auth
|
||||
auth.IssueTime = le.IssueTime
|
||||
auth.Increment = increment
|
||||
@ -2297,28 +2339,31 @@ func (m *ExpirationManager) deleteEntry(ctx context.Context, le *leaseEntry) err
|
||||
|
||||
// createIndexByToken creates a secondary index from the token to a lease entry
|
||||
func (m *ExpirationManager) createIndexByToken(ctx context.Context, le *leaseEntry, token string) error {
|
||||
tokenNS := namespace.RootNamespace
|
||||
saltCtx := namespace.ContextWithNamespace(ctx, namespace.RootNamespace)
|
||||
_, nsID := namespace.SplitIDFromString(token)
|
||||
if nsID != "" && !IsEnterpriseToken(token) {
|
||||
var err error
|
||||
tokenNS, err = NamespaceByID(ctx, nsID, m.core)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tokenNS != nil {
|
||||
saltCtx = namespace.ContextWithNamespace(ctx, tokenNS)
|
||||
}
|
||||
}
|
||||
var tokenNS *namespace.Namespace
|
||||
var saltCtx context.Context
|
||||
var err error
|
||||
|
||||
// If it's an enterprise token, we cannot get the ID from the token,
|
||||
// so let's get it from the lease.
|
||||
if IsEnterpriseToken(token) {
|
||||
ns, err := m.getNamespaceFromLeaseID(ctx, le.LeaseID)
|
||||
// fetch the namespace from the lease rather than the req context to allow for cross namespace access
|
||||
tokenNS, err = m.getNamespaceFromLeaseID(ctx, le.LeaseID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tokenNS = ns
|
||||
saltCtx = namespace.ContextWithNamespace(ctx, tokenNS)
|
||||
} else {
|
||||
tokenNS = namespace.RootNamespace
|
||||
saltCtx = namespace.ContextWithNamespace(ctx, namespace.RootNamespace)
|
||||
_, nsID := namespace.SplitIDFromString(token)
|
||||
if nsID != "" {
|
||||
var err error
|
||||
tokenNS, err = NamespaceByID(ctx, nsID, m.core)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tokenNS != nil {
|
||||
saltCtx = namespace.ContextWithNamespace(ctx, tokenNS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
saltedID, err := m.tokenStore.SaltID(saltCtx, token)
|
||||
@ -2379,26 +2424,39 @@ func (m *ExpirationManager) indexByToken(ctx context.Context, le *leaseEntry) (*
|
||||
|
||||
// removeIndexByToken removes the secondary index from the token to a lease entry
|
||||
func (m *ExpirationManager) removeIndexByToken(ctx context.Context, le *leaseEntry, token string) error {
|
||||
tokenNS := namespace.RootNamespace
|
||||
saltCtx := namespace.ContextWithNamespace(ctx, namespace.RootNamespace)
|
||||
_, nsID := namespace.SplitIDFromString(token)
|
||||
if nsID != "" {
|
||||
var err error
|
||||
tokenNS, err = NamespaceByID(ctx, nsID, m.core)
|
||||
var tokenNS *namespace.Namespace
|
||||
var saltCtx context.Context
|
||||
var err error
|
||||
|
||||
if IsEnterpriseToken(token) {
|
||||
tokenNS, err = namespace.FromContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tokenNS != nil {
|
||||
saltCtx = namespace.ContextWithNamespace(ctx, tokenNS)
|
||||
}
|
||||
|
||||
// Downgrade logic for old-style (V0) namespace leases that had its
|
||||
// secondary index live in the root namespace. This reverts to the old
|
||||
// behavior of looking for the secondary index on these leases in the
|
||||
// root namespace to be cleaned up properly. We set it here because the
|
||||
// old behavior used the namespace's token store salt for its saltCtx.
|
||||
if le.Version < 1 {
|
||||
tokenNS = namespace.RootNamespace
|
||||
saltCtx = namespace.ContextWithNamespace(ctx, tokenNS)
|
||||
} else {
|
||||
tokenNS = namespace.RootNamespace
|
||||
saltCtx = namespace.ContextWithNamespace(ctx, namespace.RootNamespace)
|
||||
_, nsID := namespace.SplitIDFromString(token)
|
||||
if nsID != "" {
|
||||
var err error
|
||||
tokenNS, err = NamespaceByID(ctx, nsID, m.core)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tokenNS != nil {
|
||||
saltCtx = namespace.ContextWithNamespace(ctx, tokenNS)
|
||||
}
|
||||
|
||||
// Downgrade logic for old-style (V0) namespace leases that had its
|
||||
// secondary index live in the root namespace. This reverts to the old
|
||||
// behavior of looking for the secondary index on these leases in the
|
||||
// root namespace to be cleaned up properly. We set it here because the
|
||||
// old behavior used the namespace's token store salt for its saltCtx.
|
||||
if le.Version < 1 {
|
||||
tokenNS = namespace.RootNamespace
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2984,6 +3042,9 @@ func (le *leaseEntry) renewable() (bool, error) {
|
||||
case le.ClientTokenType == logical.TokenTypeBatch:
|
||||
return false, nil
|
||||
|
||||
case le.ClientTokenType == logical.TokenTypeEnt:
|
||||
return false, fmt.Errorf("enterprise tokens cannot be renewed")
|
||||
|
||||
// Determine if the lease is expired
|
||||
case le.ExpireTime.Before(time.Now()):
|
||||
return false, fmt.Errorf("lease expired")
|
||||
|
||||
@ -7,6 +7,7 @@ package vault
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
@ -35,3 +36,7 @@ func (m *ExpirationManager) collectLeases() (map[*namespace.Namespace][]string,
|
||||
func (m *ExpirationManager) removeIrrevocableLeasesEnabled(c *Core) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func deriveExpireTimeFromEntToken(_ *logical.TokenEntry) time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
@ -199,6 +199,9 @@ func NewSystemBackend(core *Core, logger log.Logger, config *logical.BackendConf
|
||||
// to declare them here so that the generated OpenAPI spec gets their sudo status correct.
|
||||
"seal",
|
||||
"step-down",
|
||||
"activation-flags/oauth-resource-server/activate",
|
||||
"activation-flags/oauth-resource-server/deactivate",
|
||||
"config/oauth-resource-server/*",
|
||||
},
|
||||
|
||||
Unauthenticated: unauthenticatedPaths,
|
||||
|
||||
@ -134,6 +134,13 @@ var (
|
||||
"config/group-policy-application$": {operations: []logical.Operation{logical.ReadOperation, logical.UpdateOperation}},
|
||||
})...)
|
||||
|
||||
paths = append(paths, buildEnterpriseOnlyPaths(map[string]enterprisePathStub{
|
||||
"activation-flags/oauth-resource-server/activate": {operations: []logical.Operation{logical.UpdateOperation}},
|
||||
"activation-flags/oauth-resource-server/deactivate": {operations: []logical.Operation{logical.UpdateOperation}},
|
||||
"config/oauth-resource-server/": {operations: []logical.Operation{logical.ListOperation}},
|
||||
"config/oauth-resource-server/" + framework.GenericNameRegex("name"): {parameters: []string{"name"}, operations: []logical.Operation{logical.DeleteOperation, logical.ReadOperation, logical.UpdateOperation}},
|
||||
})...)
|
||||
|
||||
// reporting paths
|
||||
paths = append(paths, buildEnterpriseOnlyPaths(map[string]enterprisePathStub{
|
||||
"reporting/scan$": {operations: []logical.Operation{logical.UpdateOperation}},
|
||||
|
||||
@ -2707,7 +2707,11 @@ func (c *Core) RegisterAuth(ctx context.Context, tokenTTL time.Duration, path st
|
||||
return err
|
||||
}
|
||||
}
|
||||
case logical.TokenTypeEnt:
|
||||
// Ensure it's not marked renewable since enterprise tokens are not renewable
|
||||
auth.Renewable = false
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,10 @@ func (c *Core) createAndStoreEnterpriseTokenEntry(ctx context.Context, req *logi
|
||||
return nil
|
||||
}
|
||||
|
||||
func isActivationFlagEnabledForEnterpriseToken(c *Core) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func getEnterpriseTokenMetadata(_ map[string]interface{}) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user