mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-29 09:42:25 +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
|
||||
}
|
||||
|
||||
opts, err := getOpts(opt...)
|
||||
var tokenPresent bool
|
||||
token := r.Header.Get(consts.AuthHeaderName)
|
||||
|
||||
if opts.withRedactVersion {
|
||||
body.Version = opts.withRedactionValue
|
||||
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(r.Context(), token)
|
||||
lock.Unlock()
|
||||
tokenPresent = err == nil && tokenEntry != nil
|
||||
}
|
||||
opts, _ := getOpts(opt...)
|
||||
|
||||
if opts.withRedactClusterName {
|
||||
body.ClusterName = opts.withRedactionValue
|
||||
if !tokenPresent {
|
||||
if opts.withRedactVersion {
|
||||
body.Version = opts.withRedactionValue
|
||||
}
|
||||
|
||||
if opts.withRedactClusterName {
|
||||
body.ClusterName = opts.withRedactionValue
|
||||
}
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"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) {
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
handleSysLeaderGet(core, w, opt...)
|
||||
handleSysLeaderGet(core, w, r, opt...)
|
||||
default:
|
||||
respondError(w, http.StatusMethodNotAllowed, nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func handleSysLeaderGet(core *vault.Core, w http.ResponseWriter, opt ...ListenerConfigOption) {
|
||||
ctx := context.Background()
|
||||
func handleSysLeaderGet(core *vault.Core, w http.ResponseWriter, r *http.Request, opt ...ListenerConfigOption) {
|
||||
var tokenPresent bool
|
||||
token := r.Header.Get(consts.AuthHeaderName)
|
||||
ctx := r.Context()
|
||||
|
||||
opts, _ := getOpts(opt...)
|
||||
if opts.withRedactAddresses {
|
||||
ctx = logical.CreateContextRedactionSettings(ctx, false, true, false)
|
||||
if token != "" {
|
||||
// We don't care about the error, we just want to know if token exists
|
||||
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)
|
||||
|
||||
@@ -98,7 +98,7 @@ func handleSysUnseal(core *vault.Core) http.Handler {
|
||||
return
|
||||
}
|
||||
core.ResetUnsealProcess()
|
||||
handleSysSealStatusRaw(core, w)
|
||||
handleSysSealStatusRaw(core, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ func handleSysUnseal(core *vault.Core) http.Handler {
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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) {
|
||||
ctx := context.Background()
|
||||
func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, r *http.Request, opt ...ListenerConfigOption) {
|
||||
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)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -203,7 +208,6 @@ func handleSysSealBackendStatusRaw(core *vault.Core, w http.ResponseWriter, r *h
|
||||
respondError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
respondOk(w, status)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,11 +15,18 @@ import (
|
||||
"testing"
|
||||
|
||||
"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/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/vault"
|
||||
"github.com/hashicorp/vault/vault/seal"
|
||||
"github.com/hashicorp/vault/version"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSysSealStatus(t *testing.T) {
|
||||
@@ -556,3 +563,64 @@ func TestSysStepDown(t *testing.T) {
|
||||
resp := testHttpPut(t, token, addr+"/v1/sys/step-down", nil)
|
||||
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["address"] = fmt.Sprintf("%s:%d", "0.0.0.0", config.Port)
|
||||
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)
|
||||
portStr := fmt.Sprintf("%d/tcp", config.Port)
|
||||
if strutil.StrListContains(ports, portStr) {
|
||||
|
||||
@@ -105,8 +105,11 @@ type ClusterOptions struct {
|
||||
}
|
||||
|
||||
type VaultNodeListenerConfig struct {
|
||||
Port int
|
||||
ChrootNamespace string
|
||||
Port int
|
||||
ChrootNamespace string
|
||||
RedactAddresses bool
|
||||
RedactClusterName bool
|
||||
RedactVersion bool
|
||||
}
|
||||
|
||||
type CA struct {
|
||||
|
||||
@@ -743,6 +743,10 @@ func (c *Core) HAStateWithLock() consts.HAState {
|
||||
return c.HAState()
|
||||
}
|
||||
|
||||
func (c *Core) HALock() sync.Locker {
|
||||
return c.stateLock.RLocker()
|
||||
}
|
||||
|
||||
// CoreConfig is used to parameterize a core
|
||||
type CoreConfig struct {
|
||||
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) {
|
||||
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)
|
||||
if err != nil {
|
||||
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) {
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user