From 6e020e38e008f489da5d454eee64d291bdf926f8 Mon Sep 17 00:00:00 2001 From: divyaac Date: Mon, 4 Dec 2023 14:51:44 -0800 Subject: [PATCH] Add_Chroot_Namespace_In_Response (#24355) --- http/handler.go | 22 +++++++++++++--------- http/logical.go | 19 ++++++++++--------- http/logical_test.go | 8 ++++---- http/sys_seal.go | 4 ++-- sdk/logical/request.go | 3 +++ vault/logical_system.go | 2 ++ vault/logical_system_integ_test.go | 3 ++- vault/logical_system_paths.go | 4 ++++ 8 files changed, 40 insertions(+), 25 deletions(-) diff --git a/http/handler.go b/http/handler.go index c3f49d32b6..2e1db26aa0 100644 --- a/http/handler.go +++ b/http/handler.go @@ -151,6 +151,10 @@ func handler(props *vault.HandlerProperties) http.Handler { // Create the muxer to handle the actual endpoints mux := http.NewServeMux() + var chrootNamespace string + if props.ListenerConfig != nil { + chrootNamespace = props.ListenerConfig.ChrootNamespace + } switch { case props.RecoveryMode: @@ -161,8 +165,8 @@ func handler(props *vault.HandlerProperties) http.Handler { mux.Handle("/v1/sys/generate-recovery-token/update", handleSysGenerateRootUpdate(core, strategy)) default: // Handle non-forwarded paths - mux.Handle("/v1/sys/config/state/", handleLogicalNoForward(core)) - mux.Handle("/v1/sys/host-info", handleLogicalNoForward(core)) + mux.Handle("/v1/sys/config/state/", handleLogicalNoForward(core, chrootNamespace)) + mux.Handle("/v1/sys/host-info", handleLogicalNoForward(core, chrootNamespace)) mux.Handle("/v1/sys/init", handleSysInit(core)) mux.Handle("/v1/sys/seal-status", handleSysSealStatus(core, @@ -177,7 +181,7 @@ func handler(props *vault.HandlerProperties) http.Handler { mux.Handle("/v1/sys/health", handleSysHealth(core, WithRedactClusterName(props.ListenerConfig.RedactClusterName), WithRedactVersion(props.ListenerConfig.RedactVersion))) - mux.Handle("/v1/sys/monitor", handleLogicalNoForward(core)) + mux.Handle("/v1/sys/monitor", handleLogicalNoForward(core, chrootNamespace)) mux.Handle("/v1/sys/generate-root/attempt", handleRequestForwarding(core, handleAuditNonLogical(core, handleSysGenerateRootAttempt(core, vault.GenerateStandardRootTokenStrategy)))) mux.Handle("/v1/sys/generate-root/update", handleRequestForwarding(core, @@ -193,10 +197,10 @@ func handler(props *vault.HandlerProperties) http.Handler { mux.Handle("/v1/sys/internal/ui/feature-flags", handleSysInternalFeatureFlags(core)) for _, path := range injectDataIntoTopRoutes { - mux.Handle(path, handleRequestForwarding(core, handleLogicalWithInjector(core))) + mux.Handle(path, handleRequestForwarding(core, handleLogicalWithInjector(core, chrootNamespace))) } - mux.Handle("/v1/sys/", handleRequestForwarding(core, handleLogical(core))) - mux.Handle("/v1/", handleRequestForwarding(core, handleLogical(core))) + mux.Handle("/v1/sys/", handleRequestForwarding(core, handleLogical(core, chrootNamespace))) + mux.Handle("/v1/", handleRequestForwarding(core, handleLogical(core, chrootNamespace))) if core.UIEnabled() { if uiBuiltIn { mux.Handle("/ui/", http.StripPrefix("/ui/", gziphandler.GzipHandler(handleUIHeaders(core, handleUI(http.FileServer(&UIAssetWrapper{FileSystem: assetFS()})))))) @@ -213,7 +217,7 @@ func handler(props *vault.HandlerProperties) http.Handler { if props.ListenerConfig != nil && props.ListenerConfig.Telemetry.UnauthenticatedMetricsAccess { mux.Handle("/v1/sys/metrics", handleMetricsUnauthenticated(core)) } else { - mux.Handle("/v1/sys/metrics", handleLogicalNoForward(core)) + mux.Handle("/v1/sys/metrics", handleLogicalNoForward(core, chrootNamespace)) } if props.ListenerConfig != nil && props.ListenerConfig.Profiling.UnauthenticatedPProfAccess { @@ -226,13 +230,13 @@ func handler(props *vault.HandlerProperties) http.Handler { mux.Handle("/v1/sys/pprof/symbol", http.HandlerFunc(pprof.Symbol)) mux.Handle("/v1/sys/pprof/trace", http.HandlerFunc(pprof.Trace)) } else { - mux.Handle("/v1/sys/pprof/", handleLogicalNoForward(core)) + mux.Handle("/v1/sys/pprof/", handleLogicalNoForward(core, chrootNamespace)) } if props.ListenerConfig != nil && props.ListenerConfig.InFlightRequestLogging.UnauthenticatedInFlightAccess { mux.Handle("/v1/sys/in-flight-req", handleUnAuthenticatedInFlightRequest(core)) } else { - mux.Handle("/v1/sys/in-flight-req", handleLogicalNoForward(core)) + mux.Handle("/v1/sys/in-flight-req", handleLogicalNoForward(core, chrootNamespace)) } entAdditionalRoutes(mux, core) } diff --git a/http/logical.go b/http/logical.go index c76c0462c0..6ef1daa7a6 100644 --- a/http/logical.go +++ b/http/logical.go @@ -257,11 +257,12 @@ func buildLogicalPath(r *http.Request) (string, int, error) { return path, 0, nil } -func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Request) (*logical.Request, io.ReadCloser, int, error) { +func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Request, chrootNamespace string) (*logical.Request, io.ReadCloser, int, error) { req, origBody, status, err := buildLogicalRequestNoAuth(core.PerfStandby(), core.RouterAccess(), w, r) if err != nil || status != 0 { return nil, nil, status, err } + req.ChrootNamespace = chrootNamespace req.SetRequiredState(r.Header.Values(VaultIndexHeaderName)) requestAuth(r, req) @@ -290,22 +291,22 @@ func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Reques // - Perf standby and token with limited use count. // - Perf standby and token re-validation needed (e.g. due to invalid token). // - Perf standby and control group error. -func handleLogical(core *vault.Core) http.Handler { - return handleLogicalInternal(core, false, false) +func handleLogical(core *vault.Core, chrootNamespace string) http.Handler { + return handleLogicalInternal(core, false, false, chrootNamespace) } // handleLogicalWithInjector returns a handler for processing logical requests // that also have their logical response data injected at the top-level payload. // All forwarding behavior remains the same as `handleLogical`. -func handleLogicalWithInjector(core *vault.Core) http.Handler { - return handleLogicalInternal(core, true, false) +func handleLogicalWithInjector(core *vault.Core, chrootNamespace string) http.Handler { + return handleLogicalInternal(core, true, false, chrootNamespace) } // handleLogicalNoForward returns a handler for processing logical local-only // requests. These types of requests never forwarded, and return an // `vault.ErrCannotForwardLocalOnly` error if attempted to do so. -func handleLogicalNoForward(core *vault.Core) http.Handler { - return handleLogicalInternal(core, false, true) +func handleLogicalNoForward(core *vault.Core, chrootNamespace string) http.Handler { + return handleLogicalInternal(core, false, true, chrootNamespace) } func handleLogicalRecovery(raw *vault.RawBackend, token *atomic.String) http.Handler { @@ -338,9 +339,9 @@ func handleLogicalRecovery(raw *vault.RawBackend, token *atomic.String) http.Han // handleLogicalInternal is a common helper that returns a handler for // processing logical requests. The behavior depends on the various boolean // toggles. Refer to usage on functions for possible behaviors. -func handleLogicalInternal(core *vault.Core, injectDataIntoTopLevel bool, noForward bool) http.Handler { +func handleLogicalInternal(core *vault.Core, injectDataIntoTopLevel bool, noForward bool, chrootNamespace string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - req, origBody, statusCode, err := buildLogicalRequest(core, w, r) + req, origBody, statusCode, err := buildLogicalRequest(core, w, r, chrootNamespace) if err != nil || statusCode != 0 { respondError(w, statusCode, err) return diff --git a/http/logical_test.go b/http/logical_test.go index cc85967774..e5b0caf222 100644 --- a/http/logical_test.go +++ b/http/logical_test.go @@ -323,7 +323,7 @@ func TestLogical_ListSuffix(t *testing.T) { req = req.WithContext(namespace.RootContext(nil)) req.Header.Add(consts.AuthHeaderName, rootToken) - lreq, _, status, err := buildLogicalRequest(core, nil, req) + lreq, _, status, err := buildLogicalRequest(core, nil, req, "") if err != nil { t.Fatal(err) } @@ -338,7 +338,7 @@ func TestLogical_ListSuffix(t *testing.T) { req = req.WithContext(namespace.RootContext(nil)) req.Header.Add(consts.AuthHeaderName, rootToken) - lreq, _, status, err = buildLogicalRequest(core, nil, req) + lreq, _, status, err = buildLogicalRequest(core, nil, req, "") if err != nil { t.Fatal(err) } @@ -358,7 +358,7 @@ func TestLogical_ListSuffix(t *testing.T) { t.Fatal(err) } - lreq, _, status, err = buildLogicalRequest(core, nil, req) + lreq, _, status, err = buildLogicalRequest(core, nil, req, "") if err != nil { t.Fatal(err) } @@ -517,7 +517,7 @@ func TestLogical_ListWithQueryParameters(t *testing.T) { req = req.WithContext(namespace.RootContext(nil)) req.Header.Add(consts.AuthHeaderName, rootToken) - lreq, _, status, err := buildLogicalRequest(core, nil, req) + lreq, _, status, err := buildLogicalRequest(core, nil, req, "") if err != nil { t.Fatal(err) } diff --git a/http/sys_seal.go b/http/sys_seal.go index 14bfa41b00..a17c6eb660 100644 --- a/http/sys_seal.go +++ b/http/sys_seal.go @@ -18,7 +18,7 @@ import ( func handleSysSeal(core *vault.Core) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - req, _, statusCode, err := buildLogicalRequest(core, w, r) + req, _, statusCode, err := buildLogicalRequest(core, w, r, "") if err != nil || statusCode != 0 { respondError(w, statusCode, err) return @@ -48,7 +48,7 @@ func handleSysSeal(core *vault.Core) http.Handler { func handleSysStepDown(core *vault.Core) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - req, _, statusCode, err := buildLogicalRequest(core, w, r) + req, _, statusCode, err := buildLogicalRequest(core, w, r, "") if err != nil || statusCode != 0 { respondError(w, statusCode, err) return diff --git a/sdk/logical/request.go b/sdk/logical/request.go index 176b7013a3..4f75bbd6d8 100644 --- a/sdk/logical/request.go +++ b/sdk/logical/request.go @@ -248,6 +248,9 @@ type Request struct { // When a request has been forwarded, contains information of the host the request was forwarded 'from' ForwardedFrom string `json:"forwarded_from,omitempty"` + + // Name of the chroot namespace for the listener that the request was made against + ChrootNamespace string `json:"chroot_namespace,omitempty"` } // Clone returns a deep copy of the request by using copystructure diff --git a/vault/logical_system.go b/vault/logical_system.go index 67b674105d..bd5c93e227 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -4708,6 +4708,8 @@ func (b *SystemBackend) pathInternalUIResultantACL(ctx context.Context, req *log }, } + resp.Data["chroot_namespace"] = req.ChrootNamespace + if acl.root { resp.Data["root"] = true return resp, nil diff --git a/vault/logical_system_integ_test.go b/vault/logical_system_integ_test.go index d1ff71d102..644aaec0a6 100644 --- a/vault/logical_system_integ_test.go +++ b/vault/logical_system_integ_test.go @@ -144,7 +144,8 @@ func TestSystemBackend_InternalUIResultantACL(t *testing.T) { }, }, }, - "root": false, + "root": false, + "chroot_namespace": "", } if diff := deep.Equal(resp.Data, exp); diff != nil { diff --git a/vault/logical_system_paths.go b/vault/logical_system_paths.go index db0b52583e..60e56d3182 100644 --- a/vault/logical_system_paths.go +++ b/vault/logical_system_paths.go @@ -2642,6 +2642,10 @@ func (b *SystemBackend) internalPaths() []*framework.Path { Type: framework.TypeMap, Required: false, }, + "chroot_namespace": { + Type: framework.TypeString, + Required: true, + }, }, }}, },