mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 02:02:43 +00:00
Listeners: Redaction only for TCP (#23592)
* redaction should only work for TCP listeners, also fix bug that allowed custom response headers for unix listeners * fix failing test * updates from PR feedback
This commit is contained in:
@@ -141,7 +141,7 @@ func ParseConfig(d string) (*SharedConfig, error) {
|
||||
|
||||
// Track which types of listener were found.
|
||||
for _, l := range result.Listeners {
|
||||
result.found(l.Type, l.Type)
|
||||
result.found(l.Type.String(), l.Type.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,14 @@ import (
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
)
|
||||
|
||||
const (
|
||||
TCP ListenerType = "tcp"
|
||||
Unix ListenerType = "unix"
|
||||
)
|
||||
|
||||
// ListenerType represents the supported types of listener.
|
||||
type ListenerType string
|
||||
|
||||
type ListenerTelemetry struct {
|
||||
UnusedKeys UnusedKeyMap `hcl:",unusedKeyPositions"`
|
||||
UnauthenticatedMetricsAccess bool `hcl:"-"`
|
||||
@@ -45,7 +53,7 @@ type Listener struct {
|
||||
UnusedKeys UnusedKeyMap `hcl:",unusedKeyPositions"`
|
||||
RawConfig map[string]interface{}
|
||||
|
||||
Type string
|
||||
Type ListenerType
|
||||
Purpose []string `hcl:"-"`
|
||||
PurposeRaw interface{} `hcl:"purpose"`
|
||||
Role string `hcl:"role"`
|
||||
@@ -254,6 +262,16 @@ func parseListener(item *ast.ObjectItem) (*Listener, error) {
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// Normalize returns the lower case string version of a listener type.
|
||||
func (t ListenerType) Normalize() ListenerType {
|
||||
return ListenerType(strings.ToLower(string(t)))
|
||||
}
|
||||
|
||||
// String returns the string version of a listener type.
|
||||
func (t ListenerType) String() string {
|
||||
return string(t.Normalize())
|
||||
}
|
||||
|
||||
// parseChrootNamespace attempts to parse the raw listener chroot namespace settings.
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
@@ -286,20 +304,21 @@ func (l *Listener) parseType(fallback string) error {
|
||||
}
|
||||
|
||||
// Use type if available, otherwise fall back.
|
||||
result := l.Type
|
||||
if result == "" {
|
||||
result = fallback
|
||||
rawType := l.Type
|
||||
if rawType == "" {
|
||||
rawType = ListenerType(fallback)
|
||||
}
|
||||
result = strings.ToLower(result)
|
||||
|
||||
parsedType := rawType.Normalize()
|
||||
|
||||
// Sanity check the values
|
||||
switch result {
|
||||
case "tcp", "unix":
|
||||
switch parsedType {
|
||||
case TCP, Unix:
|
||||
default:
|
||||
return fmt.Errorf("unsupported listener type %q", result)
|
||||
return fmt.Errorf("unsupported listener type %q", parsedType)
|
||||
}
|
||||
|
||||
l.Type = result
|
||||
l.Type = parsedType
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -396,6 +415,13 @@ func (l *Listener) parseTLSSettings() error {
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
func (l *Listener) parseHTTPHeaderSettings() error {
|
||||
// Custom response headers are only supported by TCP listeners.
|
||||
// Clear raw data and return early if it was something else.
|
||||
if l.Type != TCP {
|
||||
l.CustomResponseHeadersRaw = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// if CustomResponseHeadersRaw is nil, we still need to set the default headers
|
||||
customHeadersMap, err := ParseCustomResponseHeaders(l.CustomResponseHeadersRaw)
|
||||
if err != nil {
|
||||
@@ -604,6 +630,16 @@ func (l *Listener) parseCORSSettings() error {
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
func (l *Listener) parseRedactionSettings() error {
|
||||
// Redaction is only supported on TCP listeners.
|
||||
// Clear raw data and return early if it was something else.
|
||||
if l.Type != TCP {
|
||||
l.RedactAddressesRaw = nil
|
||||
l.RedactClusterNameRaw = nil
|
||||
l.RedactVersionRaw = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if l.RedactAddressesRaw != nil {
|
||||
|
||||
@@ -159,7 +159,7 @@ func TestListener_parseType(t *testing.T) {
|
||||
tc := tc
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
l := &Listener{Type: tc.inputType}
|
||||
l := &Listener{Type: ListenerType(tc.inputType)}
|
||||
err := l.parseType(tc.inputFallback)
|
||||
switch {
|
||||
case tc.isErrorExpected:
|
||||
@@ -167,7 +167,7 @@ func TestListener_parseType(t *testing.T) {
|
||||
require.ErrorContains(t, err, tc.errorMessage)
|
||||
default:
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expectedValue, l.Type)
|
||||
require.Equal(t, tc.expectedValue, l.Type.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -861,16 +861,19 @@ func TestListener_parseCORSSettings(t *testing.T) {
|
||||
// assign the relevant value on the SharedConfig struct.
|
||||
func TestListener_parseHTTPHeaderSettings(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
listenerType ListenerType
|
||||
rawCustomResponseHeaders []map[string]any
|
||||
expectedNumCustomResponseHeaders int
|
||||
isErrorExpected bool
|
||||
errorMessage string
|
||||
}{
|
||||
"nil": {
|
||||
listenerType: TCP,
|
||||
isErrorExpected: false,
|
||||
expectedNumCustomResponseHeaders: 1, // default: Strict-Transport-Security
|
||||
},
|
||||
"custom-headers-bad": {
|
||||
listenerType: TCP,
|
||||
rawCustomResponseHeaders: []map[string]any{
|
||||
{"juan": false},
|
||||
},
|
||||
@@ -878,6 +881,7 @@ func TestListener_parseHTTPHeaderSettings(t *testing.T) {
|
||||
errorMessage: "failed to parse custom_response_headers",
|
||||
},
|
||||
"custom-headers-good": {
|
||||
listenerType: TCP,
|
||||
rawCustomResponseHeaders: []map[string]any{
|
||||
{
|
||||
"2xx": []map[string]any{
|
||||
@@ -888,6 +892,18 @@ func TestListener_parseHTTPHeaderSettings(t *testing.T) {
|
||||
expectedNumCustomResponseHeaders: 2,
|
||||
isErrorExpected: false,
|
||||
},
|
||||
"unix-no-headers": {
|
||||
listenerType: Unix,
|
||||
rawCustomResponseHeaders: []map[string]any{
|
||||
{
|
||||
"2xx": []map[string]any{
|
||||
{"X-Custom-Header": []any{"Custom Header Value 1", "Custom Header Value 2"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedNumCustomResponseHeaders: 0,
|
||||
isErrorExpected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
@@ -898,6 +914,7 @@ func TestListener_parseHTTPHeaderSettings(t *testing.T) {
|
||||
|
||||
// Configure listener with raw values
|
||||
l := &Listener{
|
||||
Type: tc.listenerType,
|
||||
CustomResponseHeadersRaw: tc.rawCustomResponseHeaders,
|
||||
}
|
||||
|
||||
@@ -978,6 +995,7 @@ func TestListener_parseChrootNamespaceSettings(t *testing.T) {
|
||||
// assign the relevant value on the SharedConfig struct.
|
||||
func TestListener_parseRedactionSettings(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
listenerType ListenerType
|
||||
rawRedactAddresses any
|
||||
expectedRedactAddresses bool
|
||||
rawRedactClusterName any
|
||||
@@ -988,41 +1006,58 @@ func TestListener_parseRedactionSettings(t *testing.T) {
|
||||
errorMessage string
|
||||
}{
|
||||
"missing": {
|
||||
listenerType: TCP,
|
||||
isErrorExpected: false,
|
||||
expectedRedactAddresses: false,
|
||||
expectedRedactClusterName: false,
|
||||
expectedRedactVersion: false,
|
||||
},
|
||||
"redact-addresses-bad": {
|
||||
listenerType: TCP,
|
||||
rawRedactAddresses: "juan",
|
||||
isErrorExpected: true,
|
||||
errorMessage: "invalid value for redact_addresses",
|
||||
},
|
||||
"redact-addresses-good": {
|
||||
listenerType: TCP,
|
||||
rawRedactAddresses: "true",
|
||||
expectedRedactAddresses: true,
|
||||
isErrorExpected: false,
|
||||
},
|
||||
"redact-cluster-name-bad": {
|
||||
listenerType: TCP,
|
||||
rawRedactClusterName: "juan",
|
||||
isErrorExpected: true,
|
||||
errorMessage: "invalid value for redact_cluster_name",
|
||||
},
|
||||
"redact-cluster-name-good": {
|
||||
listenerType: TCP,
|
||||
rawRedactClusterName: "true",
|
||||
expectedRedactClusterName: true,
|
||||
isErrorExpected: false,
|
||||
},
|
||||
"redact-version-bad": {
|
||||
listenerType: TCP,
|
||||
rawRedactVersion: "juan",
|
||||
isErrorExpected: true,
|
||||
errorMessage: "invalid value for redact_version",
|
||||
},
|
||||
"redact-version-good": {
|
||||
listenerType: TCP,
|
||||
rawRedactVersion: "true",
|
||||
expectedRedactVersion: true,
|
||||
isErrorExpected: false,
|
||||
},
|
||||
"redact-unix-na": {
|
||||
listenerType: Unix,
|
||||
rawRedactAddresses: "true",
|
||||
expectedRedactAddresses: false,
|
||||
rawRedactClusterName: "true",
|
||||
expectedRedactClusterName: false,
|
||||
rawRedactVersion: "true",
|
||||
expectedRedactVersion: false,
|
||||
isErrorExpected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
@@ -1033,6 +1068,7 @@ func TestListener_parseRedactionSettings(t *testing.T) {
|
||||
|
||||
// Configure listener with raw values
|
||||
l := &Listener{
|
||||
Type: tc.listenerType,
|
||||
RedactAddressesRaw: tc.rawRedactAddresses,
|
||||
RedactClusterNameRaw: tc.rawRedactClusterName,
|
||||
RedactVersionRaw: tc.rawRedactVersion,
|
||||
|
||||
Reference in New Issue
Block a user