When tainting a route during setup, pre-calculate the namespace specific path (#15067)

This commit is contained in:
Josh Black 2022-04-26 09:13:45 -07:00 committed by GitHub
parent d6933e9ef4
commit a4593e8913
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 24 additions and 12 deletions

3
changelog/15067.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
core: pre-calculate namespace specific paths when tainting a route during postUnseal
```

View File

@ -3,6 +3,7 @@ package namespace
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"strings" "strings"
"github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/helper/consts"
@ -15,6 +16,10 @@ type Namespace struct {
Path string `json:"path"` Path string `json:"path"`
} }
func (n *Namespace) String() string {
return fmt.Sprintf("ID: %s. Path: %s", n.ID, n.Path)
}
const ( const (
RootNamespaceID = "root" RootNamespaceID = "root"
) )

View File

@ -7,7 +7,7 @@ import (
"strings" "strings"
"github.com/hashicorp/go-secure-stdlib/strutil" "github.com/hashicorp/go-secure-stdlib/strutil"
uuid "github.com/hashicorp/go-uuid" "github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/builtin/plugin" "github.com/hashicorp/vault/builtin/plugin"
"github.com/hashicorp/vault/helper/namespace" "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/helper/consts"
@ -825,16 +825,19 @@ func (c *Core) setupCredentials(ctx context.Context) error {
path := credentialRoutePrefix + entry.Path path := credentialRoutePrefix + entry.Path
err = c.router.Mount(backend, path, entry, view) err = c.router.Mount(backend, path, entry, view)
if err != nil { if err != nil {
c.logger.Error("failed to mount auth entry", "path", entry.Path, "error", err) c.logger.Error("failed to mount auth entry", "path", entry.Path, "namespace", entry.Namespace(), "error", err)
return errLoadAuthFailed return errLoadAuthFailed
} }
if c.logger.IsInfo() { if c.logger.IsInfo() {
c.logger.Info("successfully enabled credential backend", "type", entry.Type, "path", entry.Path) c.logger.Info("successfully enabled credential backend", "type", entry.Type, "path", entry.Path, "namespace", entry.Namespace())
} }
// Ensure the path is tainted if set in the mount table // Ensure the path is tainted if set in the mount table
if entry.Tainted { if entry.Tainted {
// Calculate any namespace prefixes here, because when Taint() is called, there won't be
// a namespace to pull from the context. This is similar to what we do above in c.router.Mount().
path = entry.Namespace().Path + path
c.router.Taint(ctx, path) c.router.Taint(ctx, path)
} }

View File

@ -7,8 +7,7 @@ import (
"time" "time"
log "github.com/hashicorp/go-hclog" log "github.com/hashicorp/go-hclog"
uuid "github.com/hashicorp/go-uuid" "github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/helper/namespace" "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/helper/logging" "github.com/hashicorp/vault/sdk/helper/logging"
) )

View File

@ -9,9 +9,9 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
metrics "github.com/armon/go-metrics" "github.com/armon/go-metrics"
radix "github.com/armon/go-radix" "github.com/armon/go-radix"
hclog "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-secure-stdlib/strutil" "github.com/hashicorp/go-secure-stdlib/strutil"
"github.com/hashicorp/vault/helper/namespace" "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/helper/consts"
@ -47,6 +47,8 @@ func NewRouter() *Router {
storagePrefix: radix.New(), storagePrefix: radix.New(),
mountUUIDCache: radix.New(), mountUUIDCache: radix.New(),
mountAccessorCache: radix.New(), mountAccessorCache: radix.New(),
// this will get replaced in production with a real logger but it's useful to have a default in place for tests
logger: hclog.NewNullLogger(),
} }
return r return r
} }
@ -530,7 +532,7 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc
} }
r.l.RUnlock() r.l.RUnlock()
if !ok { if !ok {
return logical.ErrorResponse(fmt.Sprintf("no handler for route '%s'", req.Path)), false, false, logical.ErrUnsupportedPath return logical.ErrorResponse(fmt.Sprintf("no handler for route %q. route entry not found.", req.Path)), false, false, logical.ErrUnsupportedPath
} }
req.Path = adjustedPath req.Path = adjustedPath
defer metrics.MeasureSince([]string{ defer metrics.MeasureSince([]string{
@ -551,7 +553,7 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc
// Filtered mounts will have a nil backend // Filtered mounts will have a nil backend
if re.backend == nil { if re.backend == nil {
return logical.ErrorResponse(fmt.Sprintf("no handler for route '%s'", req.Path)), false, false, logical.ErrUnsupportedPath return logical.ErrorResponse(fmt.Sprintf("no handler for route %q. route entry found, but backend is nil.", req.Path)), false, false, logical.ErrUnsupportedPath
} }
// If the path is tainted, we reject any operation except for // If the path is tainted, we reject any operation except for
@ -560,7 +562,7 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc
switch req.Operation { switch req.Operation {
case logical.RevokeOperation, logical.RollbackOperation: case logical.RevokeOperation, logical.RollbackOperation:
default: default:
return logical.ErrorResponse(fmt.Sprintf("no handler for route '%s'", req.Path)), false, false, logical.ErrUnsupportedPath return logical.ErrorResponse(fmt.Sprintf("no handler for route %q. route entry is tainted.", req.Path)), false, false, logical.ErrUnsupportedPath
} }
} }

View File

@ -5,7 +5,7 @@ import (
"strings" "strings"
"testing" "testing"
uuid "github.com/hashicorp/go-uuid" "github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/helper/namespace" "github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/logical"
) )