From d403d5ac8c6f2d832eeb3eb89bb4ef26bdb6cdc7 Mon Sep 17 00:00:00 2001
From: Josh Black <raskchanky@users.noreply.github.com>
Date: Tue, 26 Apr 2022 09:13:45 -0700
Subject: [PATCH 1/2] When tainting a route during setup, pre-calculate the
 namespace specific path (#15067)

---
 changelog/15067.txt           |  3 +++
 helper/namespace/namespace.go |  5 +++++
 vault/auth.go                 | 10 +++++++---
 vault/rollback_test.go        |  3 +--
 vault/router.go               | 15 +++++++++------
 vault/router_test.go          |  2 +-
 6 files changed, 26 insertions(+), 12 deletions(-)
 create mode 100644 changelog/15067.txt

diff --git a/changelog/15067.txt b/changelog/15067.txt
new file mode 100644
index 000000000000..4adee8fb6a49
--- /dev/null
+++ b/changelog/15067.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+core: pre-calculate namespace specific paths when tainting a route during postUnseal
+```
diff --git a/helper/namespace/namespace.go b/helper/namespace/namespace.go
index 1b59495cab84..6e042f84689c 100644
--- a/helper/namespace/namespace.go
+++ b/helper/namespace/namespace.go
@@ -3,6 +3,7 @@ package namespace
 import (
 	"context"
 	"errors"
+	"fmt"
 	"strings"
 )
 
@@ -13,6 +14,10 @@ type Namespace struct {
 	Path string `json:"path"`
 }
 
+func (n *Namespace) String() string {
+	return fmt.Sprintf("ID: %s. Path: %s", n.ID, n.Path)
+}
+
 const (
 	RootNamespaceID = "root"
 )
diff --git a/vault/auth.go b/vault/auth.go
index 74b6a3391052..c7ffe57a27ad 100644
--- a/vault/auth.go
+++ b/vault/auth.go
@@ -6,7 +6,8 @@ import (
 	"fmt"
 	"strings"
 
-	uuid "github.com/hashicorp/go-uuid"
+	"github.com/hashicorp/go-secure-stdlib/strutil"
+	"github.com/hashicorp/go-uuid"
 	"github.com/hashicorp/vault/builtin/plugin"
 	"github.com/hashicorp/vault/helper/namespace"
 	"github.com/hashicorp/vault/sdk/helper/consts"
@@ -723,16 +724,19 @@ func (c *Core) setupCredentials(ctx context.Context) error {
 		path := credentialRoutePrefix + entry.Path
 		err = c.router.Mount(backend, path, entry, view)
 		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
 		}
 
 		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
 		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)
 		}
 
diff --git a/vault/rollback_test.go b/vault/rollback_test.go
index 4308d70e1c2e..681101217a30 100644
--- a/vault/rollback_test.go
+++ b/vault/rollback_test.go
@@ -7,8 +7,7 @@ import (
 	"time"
 
 	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/sdk/helper/logging"
 )
diff --git a/vault/router.go b/vault/router.go
index be067f78a28e..85e3d9b9bc74 100644
--- a/vault/router.go
+++ b/vault/router.go
@@ -8,9 +8,10 @@ import (
 	"sync/atomic"
 	"time"
 
-	metrics "github.com/armon/go-metrics"
-	radix "github.com/armon/go-radix"
-	hclog "github.com/hashicorp/go-hclog"
+	"github.com/armon/go-metrics"
+	"github.com/armon/go-radix"
+	"github.com/hashicorp/go-hclog"
+	"github.com/hashicorp/go-secure-stdlib/strutil"
 	"github.com/hashicorp/vault/helper/namespace"
 	"github.com/hashicorp/vault/sdk/helper/consts"
 	"github.com/hashicorp/vault/sdk/helper/salt"
@@ -43,6 +44,8 @@ func NewRouter() *Router {
 		storagePrefix:      radix.New(),
 		mountUUIDCache:     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
 }
@@ -509,7 +512,7 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc
 	}
 	r.l.RUnlock()
 	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
 	defer metrics.MeasureSince([]string{
@@ -530,7 +533,7 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc
 
 	// Filtered mounts will have a nil backend
 	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
@@ -539,7 +542,7 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc
 		switch req.Operation {
 		case logical.RevokeOperation, logical.RollbackOperation:
 		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
 		}
 	}
 
diff --git a/vault/router_test.go b/vault/router_test.go
index b20b69894fe4..2663cd203f61 100644
--- a/vault/router_test.go
+++ b/vault/router_test.go
@@ -5,7 +5,7 @@ import (
 	"strings"
 	"testing"
 
-	uuid "github.com/hashicorp/go-uuid"
+	"github.com/hashicorp/go-uuid"
 	"github.com/hashicorp/vault/helper/namespace"
 	"github.com/hashicorp/vault/sdk/logical"
 )

From 06f5a329a425b5095491d1cac1d2b34b57124956 Mon Sep 17 00:00:00 2001
From: Josh Black <raskchanky@gmail.com>
Date: Wed, 27 Apr 2022 11:40:54 -0700
Subject: [PATCH 2/2] remove the stdlib dep

---
 vault/auth.go   | 1 -
 vault/router.go | 1 -
 2 files changed, 2 deletions(-)

diff --git a/vault/auth.go b/vault/auth.go
index c7ffe57a27ad..def7bf3648a6 100644
--- a/vault/auth.go
+++ b/vault/auth.go
@@ -6,7 +6,6 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/hashicorp/go-secure-stdlib/strutil"
 	"github.com/hashicorp/go-uuid"
 	"github.com/hashicorp/vault/builtin/plugin"
 	"github.com/hashicorp/vault/helper/namespace"
diff --git a/vault/router.go b/vault/router.go
index 85e3d9b9bc74..367d8be162bf 100644
--- a/vault/router.go
+++ b/vault/router.go
@@ -11,7 +11,6 @@ import (
 	"github.com/armon/go-metrics"
 	"github.com/armon/go-radix"
 	"github.com/hashicorp/go-hclog"
-	"github.com/hashicorp/go-secure-stdlib/strutil"
 	"github.com/hashicorp/vault/helper/namespace"
 	"github.com/hashicorp/vault/sdk/helper/consts"
 	"github.com/hashicorp/vault/sdk/helper/salt"