mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 18:17:55 +00:00
Redacted Information With Valid Token (#25735)
This commit is contained in:
@@ -57,14 +57,27 @@ func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
opts, err := getOpts(opt...)
|
var tokenPresent bool
|
||||||
|
token := r.Header.Get(consts.AuthHeaderName)
|
||||||
|
|
||||||
if opts.withRedactVersion {
|
if token != "" {
|
||||||
body.Version = opts.withRedactionValue
|
// We don't care about the error, we just want to know if the token exists
|
||||||
|
lock := core.HALock()
|
||||||
|
lock.Lock()
|
||||||
|
tokenEntry, err := core.LookupToken(r.Context(), token)
|
||||||
|
lock.Unlock()
|
||||||
|
tokenPresent = err == nil && tokenEntry != nil
|
||||||
}
|
}
|
||||||
|
opts, _ := getOpts(opt...)
|
||||||
|
|
||||||
if opts.withRedactClusterName {
|
if !tokenPresent {
|
||||||
body.ClusterName = opts.withRedactionValue
|
if opts.withRedactVersion {
|
||||||
|
body.Version = opts.withRedactionValue
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.withRedactClusterName {
|
||||||
|
body.ClusterName = opts.withRedactionValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||||
"github.com/hashicorp/vault/sdk/logical"
|
"github.com/hashicorp/vault/sdk/logical"
|
||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
)
|
)
|
||||||
@@ -17,19 +17,29 @@ func handleSysLeader(core *vault.Core, opt ...ListenerConfigOption) http.Handler
|
|||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case "GET":
|
case "GET":
|
||||||
handleSysLeaderGet(core, w, opt...)
|
handleSysLeaderGet(core, w, r, opt...)
|
||||||
default:
|
default:
|
||||||
respondError(w, http.StatusMethodNotAllowed, nil)
|
respondError(w, http.StatusMethodNotAllowed, nil)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSysLeaderGet(core *vault.Core, w http.ResponseWriter, opt ...ListenerConfigOption) {
|
func handleSysLeaderGet(core *vault.Core, w http.ResponseWriter, r *http.Request, opt ...ListenerConfigOption) {
|
||||||
ctx := context.Background()
|
var tokenPresent bool
|
||||||
|
token := r.Header.Get(consts.AuthHeaderName)
|
||||||
|
ctx := r.Context()
|
||||||
|
|
||||||
opts, _ := getOpts(opt...)
|
if token != "" {
|
||||||
if opts.withRedactAddresses {
|
// We don't care about the error, we just want to know if token exists
|
||||||
ctx = logical.CreateContextRedactionSettings(ctx, false, true, false)
|
lock := core.HALock()
|
||||||
|
lock.Lock()
|
||||||
|
tokenEntry, err := core.LookupToken(ctx, token)
|
||||||
|
lock.Unlock()
|
||||||
|
tokenPresent = err == nil && tokenEntry != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if tokenPresent {
|
||||||
|
ctx = logical.CreateContextRedactionSettings(r.Context(), false, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := core.GetLeaderStatus(ctx)
|
resp, err := core.GetLeaderStatus(ctx)
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ func handleSysUnseal(core *vault.Core) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
core.ResetUnsealProcess()
|
core.ResetUnsealProcess()
|
||||||
handleSysSealStatusRaw(core, w)
|
handleSysSealStatusRaw(core, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ func handleSysUnseal(core *vault.Core) http.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the seal status
|
// Return the seal status
|
||||||
handleSysSealStatusRaw(core, w)
|
handleSysSealStatusRaw(core, w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ func handleSysSealStatus(core *vault.Core, opt ...ListenerConfigOption) http.Han
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSysSealStatusRaw(core, w, opt...)
|
handleSysSealStatusRaw(core, w, r, opt...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,25 +174,30 @@ func handleSysSealBackendStatus(core *vault.Core) http.Handler {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, opt ...ListenerConfigOption) {
|
func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, r *http.Request, opt ...ListenerConfigOption) {
|
||||||
ctx := context.Background()
|
ctx := r.Context()
|
||||||
|
|
||||||
|
var tokenPresent bool
|
||||||
|
token := r.Header.Get(consts.AuthHeaderName)
|
||||||
|
if token != "" {
|
||||||
|
// We don't care about the error, we just want to know if the token exists
|
||||||
|
lock := core.HALock()
|
||||||
|
lock.Lock()
|
||||||
|
tokenEntry, err := core.LookupToken(ctx, token)
|
||||||
|
lock.Unlock()
|
||||||
|
tokenPresent = err == nil && tokenEntry != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are is no valid token then we will redact the specified values
|
||||||
|
if tokenPresent {
|
||||||
|
ctx = logical.CreateContextRedactionSettings(ctx, false, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
status, err := core.GetSealStatus(ctx, true)
|
status, err := core.GetSealStatus(ctx, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(w, http.StatusInternalServerError, err)
|
respondError(w, http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
opts, err := getOpts(opt...)
|
|
||||||
|
|
||||||
if opts.withRedactVersion {
|
|
||||||
status.Version = opts.withRedactionValue
|
|
||||||
status.BuildDate = opts.withRedactionValue
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.withRedactClusterName {
|
|
||||||
status.ClusterName = opts.withRedactionValue
|
|
||||||
}
|
|
||||||
|
|
||||||
respondOk(w, status)
|
respondOk(w, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +208,6 @@ func handleSysSealBackendStatusRaw(core *vault.Core, w http.ResponseWriter, r *h
|
|||||||
respondError(w, http.StatusInternalServerError, err)
|
respondError(w, http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
respondOk(w, status)
|
respondOk(w, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,18 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-test/deep"
|
"github.com/go-test/deep"
|
||||||
|
"github.com/hashicorp/go-cleanhttp"
|
||||||
|
"github.com/hashicorp/vault/audit"
|
||||||
|
auditFile "github.com/hashicorp/vault/builtin/audit/file"
|
||||||
"github.com/hashicorp/vault/helper/namespace"
|
"github.com/hashicorp/vault/helper/namespace"
|
||||||
|
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
|
||||||
|
"github.com/hashicorp/vault/internalshared/configutil"
|
||||||
|
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||||
"github.com/hashicorp/vault/sdk/logical"
|
"github.com/hashicorp/vault/sdk/logical"
|
||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
"github.com/hashicorp/vault/vault/seal"
|
"github.com/hashicorp/vault/vault/seal"
|
||||||
"github.com/hashicorp/vault/version"
|
"github.com/hashicorp/vault/version"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSysSealStatus(t *testing.T) {
|
func TestSysSealStatus(t *testing.T) {
|
||||||
@@ -556,3 +563,64 @@ func TestSysStepDown(t *testing.T) {
|
|||||||
resp := testHttpPut(t, token, addr+"/v1/sys/step-down", nil)
|
resp := testHttpPut(t, token, addr+"/v1/sys/step-down", nil)
|
||||||
testResponseStatus(t, resp, 204)
|
testResponseStatus(t, resp, 204)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestSysSealStatusRedaction tests that the response from a
|
||||||
|
// a request to sys/seal-status are redacted only if no valid token
|
||||||
|
// is provided with the request
|
||||||
|
func TestSysSealStatusRedaction(t *testing.T) {
|
||||||
|
conf := &vault.CoreConfig{
|
||||||
|
EnableUI: false,
|
||||||
|
EnableRaw: true,
|
||||||
|
BuiltinRegistry: corehelpers.NewMockBuiltinRegistry(),
|
||||||
|
AuditBackends: map[string]audit.Factory{
|
||||||
|
"file": auditFile.Factory,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
core, _, token := vault.TestCoreUnsealedWithConfig(t, conf)
|
||||||
|
|
||||||
|
// Setup new custom listener
|
||||||
|
ln, addr := TestListener(t)
|
||||||
|
props := &vault.HandlerProperties{
|
||||||
|
Core: core,
|
||||||
|
ListenerConfig: &configutil.Listener{
|
||||||
|
RedactVersion: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
TestServerWithListenerAndProperties(t, ln, addr, core, props)
|
||||||
|
defer ln.Close()
|
||||||
|
TestServerAuth(t, addr, token)
|
||||||
|
|
||||||
|
client := cleanhttp.DefaultClient()
|
||||||
|
|
||||||
|
// Check seal-status
|
||||||
|
req, err := http.NewRequest("GET", addr+"/v1/sys/seal-status", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
req.Header.Set(consts.AuthHeaderName, token)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
testResponseStatus(t, resp, 200)
|
||||||
|
|
||||||
|
// Verify that version exists when provided a valid token
|
||||||
|
var actual map[string]interface{}
|
||||||
|
testResponseStatus(t, resp, 200)
|
||||||
|
testResponseBody(t, resp, &actual)
|
||||||
|
assert.NotEmpty(t, actual["version"])
|
||||||
|
|
||||||
|
// Verify that version is redacted when no token is provided
|
||||||
|
req, err = http.NewRequest("GET", addr+"/v1/sys/seal-status", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
req.Header.Set(consts.AuthHeaderName, "")
|
||||||
|
resp, err = client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
testResponseStatus(t, resp, 200)
|
||||||
|
testResponseBody(t, resp, &actual)
|
||||||
|
assert.Empty(t, actual["version"])
|
||||||
|
}
|
||||||
|
|||||||
@@ -640,6 +640,9 @@ func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOption
|
|||||||
listener := cfg["tcp"].(map[string]interface{})
|
listener := cfg["tcp"].(map[string]interface{})
|
||||||
listener["address"] = fmt.Sprintf("%s:%d", "0.0.0.0", config.Port)
|
listener["address"] = fmt.Sprintf("%s:%d", "0.0.0.0", config.Port)
|
||||||
listener["chroot_namespace"] = config.ChrootNamespace
|
listener["chroot_namespace"] = config.ChrootNamespace
|
||||||
|
listener["redact_addresses"] = config.RedactAddresses
|
||||||
|
listener["redact_cluster_name"] = config.RedactClusterName
|
||||||
|
listener["redact_version"] = config.RedactVersion
|
||||||
listenerConfig = append(listenerConfig, cfg)
|
listenerConfig = append(listenerConfig, cfg)
|
||||||
portStr := fmt.Sprintf("%d/tcp", config.Port)
|
portStr := fmt.Sprintf("%d/tcp", config.Port)
|
||||||
if strutil.StrListContains(ports, portStr) {
|
if strutil.StrListContains(ports, portStr) {
|
||||||
|
|||||||
@@ -105,8 +105,11 @@ type ClusterOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type VaultNodeListenerConfig struct {
|
type VaultNodeListenerConfig struct {
|
||||||
Port int
|
Port int
|
||||||
ChrootNamespace string
|
ChrootNamespace string
|
||||||
|
RedactAddresses bool
|
||||||
|
RedactClusterName bool
|
||||||
|
RedactVersion bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type CA struct {
|
type CA struct {
|
||||||
|
|||||||
@@ -743,6 +743,10 @@ func (c *Core) HAStateWithLock() consts.HAState {
|
|||||||
return c.HAState()
|
return c.HAState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Core) HALock() sync.Locker {
|
||||||
|
return c.stateLock.RLocker()
|
||||||
|
}
|
||||||
|
|
||||||
// CoreConfig is used to parameterize a core
|
// CoreConfig is used to parameterize a core
|
||||||
type CoreConfig struct {
|
type CoreConfig struct {
|
||||||
entCoreConfig
|
entCoreConfig
|
||||||
|
|||||||
@@ -5675,6 +5675,17 @@ func (core *Core) GetLeaderStatusLocked(ctx context.Context) (*LeaderResponse, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *SystemBackend) handleSealStatus(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *SystemBackend) handleSealStatus(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
|
var tokenPresent bool
|
||||||
|
token := req.ClientToken
|
||||||
|
if token != "" {
|
||||||
|
// We don't care about the error, we just want to know if the token exists
|
||||||
|
_, tokenEntry, _, _, err := b.Core.fetchACLTokenEntryAndEntity(ctx, req)
|
||||||
|
tokenPresent = err == nil && tokenEntry != nil
|
||||||
|
}
|
||||||
|
// If there is a valid token then we will not redact any values
|
||||||
|
if tokenPresent {
|
||||||
|
ctx = logical.CreateContextRedactionSettings(ctx, false, false, false)
|
||||||
|
}
|
||||||
status, err := b.Core.GetSealStatus(ctx, false)
|
status, err := b.Core.GetSealStatus(ctx, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -5694,6 +5705,18 @@ func (b *SystemBackend) handleSealStatus(ctx context.Context, req *logical.Reque
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *SystemBackend) handleLeaderStatus(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *SystemBackend) handleLeaderStatus(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
|
var tokenPresent bool
|
||||||
|
token := req.ClientToken
|
||||||
|
|
||||||
|
if token != "" {
|
||||||
|
// We don't care about the error, we just want to know if token exists
|
||||||
|
_, tokenEntry, _, _, err := b.Core.fetchACLTokenEntryAndEntity(ctx, req)
|
||||||
|
tokenPresent = err == nil && tokenEntry != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if tokenPresent {
|
||||||
|
ctx = logical.CreateContextRedactionSettings(ctx, false, false, false)
|
||||||
|
}
|
||||||
status, err := b.Core.GetLeaderStatusLocked(ctx)
|
status, err := b.Core.GetLeaderStatusLocked(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
Reference in New Issue
Block a user