From ec1244868cf4e1dbe62a0f981f850f1946281880 Mon Sep 17 00:00:00 2001 From: Violet Hynes Date: Wed, 2 Jul 2025 15:00:36 -0400 Subject: [PATCH] VAULT-36903 CE Changes (#31180) * VAULT-36903 CE Changes * test fixture * fix stub --- command/server/config.go | 5 +++ command/server/config_test.go | 34 ++++++++++++++++++ .../test-fixtures/observations_allow_deny.hcl | 9 +++++ vault/core.go | 7 +++- vault/observations/observations.go | 22 ++++++++++++ vault/observations/observations_ce.go | 3 +- vault/observations/observations_consts.go | 36 ++++++++++++------- 7 files changed, 100 insertions(+), 16 deletions(-) create mode 100644 command/server/test-fixtures/observations_allow_deny.hcl diff --git a/command/server/config.go b/command/server/config.go index 7f9fd64c09..a0ca7f4a3a 100644 --- a/command/server/config.go +++ b/command/server/config.go @@ -439,6 +439,11 @@ func (c *Config) Merge(c2 *Config) *Config { if c2.Observations.LedgerPath != "" { result.Observations.LedgerPath = c2.Observations.LedgerPath } + result.Observations.TypePrefixDenylist = append(c.Observations.TypePrefixDenylist, c2.Observations.TypePrefixDenylist...) + result.Observations.TypePrefixAllowlist = append(c.Observations.TypePrefixAllowlist, c2.Observations.TypePrefixAllowlist...) + if c2.Observations.FileMode != "" { + result.Observations.FileMode = c2.Observations.FileMode + } } result.ImpreciseLeaseRoleTracking = c.ImpreciseLeaseRoleTracking diff --git a/command/server/config_test.go b/command/server/config_test.go index 427be6aa1f..a3d7205b31 100644 --- a/command/server/config_test.go +++ b/command/server/config_test.go @@ -103,6 +103,40 @@ func Test_ObservationSystemConfig(t *testing.T) { require.NotNil(t, config) require.NotNil(t, config.Observations) require.Equal(t, "/var/ledger.log", config.Observations.LedgerPath) + require.Empty(t, config.Observations.TypePrefixAllowlist) + require.Empty(t, config.Observations.TypePrefixDenylist) +} + +// Test_ObservationSystemConfigAllowDenyList makes sure that the observation system config +// is properly loaded with an allowlist and denylist. +func Test_ObservationSystemConfigAllowDenyList(t *testing.T) { + config, err := LoadConfigFile("./test-fixtures/observations_allow_deny.hcl") + require.NoError(t, err) + require.NotNil(t, config) + require.NotNil(t, config.Observations) + require.Equal(t, "/var/ledger.log", config.Observations.LedgerPath) + require.Equal(t, []string{"deny1", "deny2"}, config.Observations.TypePrefixDenylist) + require.Equal(t, []string{"allow1", "allow2", "allow3"}, config.Observations.TypePrefixAllowlist) + require.Equal(t, "0777", config.Observations.FileMode) +} + +// Test_ObservationSystemConfigMerge checks merge for observation system config +func Test_ObservationSystemConfigMerge(t *testing.T) { + config, err := LoadConfigFile("./test-fixtures/observations.hcl") + require.NoError(t, err) + require.NotNil(t, config) + + config2, err := LoadConfigFile("./test-fixtures/observations_allow_deny.hcl") + require.NoError(t, err) + require.NotNil(t, config2) + + merged := config.Merge(config2) + require.NotNil(t, merged) + require.NotNil(t, merged.Observations) + require.Equal(t, "/var/ledger.log", merged.Observations.LedgerPath) + require.Equal(t, []string{"deny1", "deny2"}, merged.Observations.TypePrefixDenylist) + require.Equal(t, []string{"allow1", "allow2", "allow3"}, merged.Observations.TypePrefixAllowlist) + require.Equal(t, "0777", merged.Observations.FileMode) } // TestDuplicateKeyValidationHcl checks that the server command displays a warning when the HCL config file contains duplicate keys. diff --git a/command/server/test-fixtures/observations_allow_deny.hcl b/command/server/test-fixtures/observations_allow_deny.hcl new file mode 100644 index 0000000000..147b84138a --- /dev/null +++ b/command/server/test-fixtures/observations_allow_deny.hcl @@ -0,0 +1,9 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +observations { + ledger_path = "/var/ledger.log" + type_prefix_denylist = ["deny1", "deny2"] + type_prefix_allowlist = ["allow1", "allow2", "allow3"] + file_mode = "0777" +} diff --git a/vault/core.go b/vault/core.go index cee5cc0ba4..c954576dc2 100644 --- a/vault/core.go +++ b/vault/core.go @@ -1382,7 +1382,12 @@ func NewCore(conf *CoreConfig) (*Core, error) { observationSystemConfig := conf.ObservationSystemConfig if observationSystemConfig != nil { if observationSystemConfig.LedgerPath != "" { - observations, err := observations.NewObservationSystem(nodeID, observationSystemConfig.LedgerPath, observationsLogger) + config := &observations.NewObservationSystemConfig{ + ObservationSystemConfig: observationSystemConfig, + LocalNodeId: nodeID, + Logger: observationsLogger, + } + observations, err := observations.NewObservationSystem(config) if err != nil { return nil, err } diff --git a/vault/observations/observations.go b/vault/observations/observations.go index 32e60d049a..ca3faf1556 100644 --- a/vault/observations/observations.go +++ b/vault/observations/observations.go @@ -3,9 +3,31 @@ package observations +import "github.com/hashicorp/go-hclog" + // ObservationSystemConfig serves as a definition of what an observation // system needs from the Vault config file to start. type ObservationSystemConfig struct { // LedgerPath is the path to the observation system's ledger. LedgerPath string `json:"ledger_path" hcl:"ledger_path"` + + // TypePrefixDenylist will deny any observations with types with matching prefixes + // to be emitted to the ledger. + TypePrefixDenylist []string `json:"type_prefix_denylist" hcl:"type_prefix_denylist"` + + // TypePrefixAllowlist will only allow observations with types with matching prefixes + // to be emitted to the ledger. + TypePrefixAllowlist []string `json:"type_prefix_allowlist" hcl:"type_prefix_allowlist"` + + // FileMode will attempt to open the ledger at the ledger path with the following + // file mode. Specified as a string, but parsed as an octal, e.g. "0755". + FileMode string `json:"file_mode" hcl:"file_mode"` +} + +// NewObservationSystemConfig is the config for a new Observation System, provided +// to NewObservationSystem +type NewObservationSystemConfig struct { + *ObservationSystemConfig + LocalNodeId string + Logger hclog.Logger } diff --git a/vault/observations/observations_ce.go b/vault/observations/observations_ce.go index 11d97742b3..65164de00e 100644 --- a/vault/observations/observations_ce.go +++ b/vault/observations/observations_ce.go @@ -8,7 +8,6 @@ package observations import ( "context" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/vault/helper/namespace" "github.com/hashicorp/vault/sdk/logical" ) @@ -32,6 +31,6 @@ func (observations *ObservationSystem) RecordObservationToLedger(_ context.Conte return nil } -func NewObservationSystem(_ string, _ string, _ hclog.Logger) (*ObservationSystem, error) { +func NewObservationSystem(_ *NewObservationSystemConfig) (*ObservationSystem, error) { return &ObservationSystem{}, nil } diff --git a/vault/observations/observations_consts.go b/vault/observations/observations_consts.go index 1f625bdfca..1aef8b0079 100644 --- a/vault/observations/observations_consts.go +++ b/vault/observations/observations_consts.go @@ -4,25 +4,35 @@ package observations const ( - // lease - ObservationTypeLeaseCreationAuth = "lease/create/auth" + // ObservationTypeLeaseCreationAuth is emitted when a lease connected to auth is created + ObservationTypeLeaseCreationAuth = "lease/create/auth" + // ObservationTypeLeaseCreationNonAuth is emitted when a lease NOT connected to auth is created ObservationTypeLeaseCreationNonAuth = "lease/create/non-auth" - ObservationTypeLeaseRenewAuth = "lease/renew/auth" - ObservationTypeLeaseRenewNonAuth = "lease/renew/non-auth" - ObservationTypeLeaseLazyRevoke = "lease/lazy-revoke" - ObservationTypeLeaseRevocation = "lease/revoke" + // ObservationTypeLeaseRenewAuth is emitted when a lease connected to auth is renewed + ObservationTypeLeaseRenewAuth = "lease/renew/auth" + // ObservationTypeLeaseRenewNonAuth is emitted when a lease NOT connected to auth is renewed + ObservationTypeLeaseRenewNonAuth = "lease/renew/non-auth" + // ObservationTypeLeaseLazyRevoke is emitted when a lease is lazy-revoked + ObservationTypeLeaseLazyRevoke = "lease/lazy-revoke" + // ObservationTypeLeaseRevocation is emitted when a lease is revoked + ObservationTypeLeaseRevocation = "lease/revoke" - // policy + // ObservationTypePolicyACLEvaluation is emitted when an ACL policy is evaluated ObservationTypePolicyACLEvaluation = "policy/acl/evaluation" - // mount - ObservationTypeMountAuthEnable = "mount/auth/enable" - ObservationTypeMountAuthDisable = "mount/auth/disable" - ObservationTypeMountSecretsEnable = "mount/secrets/enable" + // ObservationTypeMountAuthEnable is emitted when an auth mount is enabled + ObservationTypeMountAuthEnable = "mount/auth/enable" + // ObservationTypeMountAuthDisable is emitted when an auth mount is disabled + ObservationTypeMountAuthDisable = "mount/auth/disable" + // ObservationTypeMountSecretsEnable is emitted when a secret mount is enabled + ObservationTypeMountSecretsEnable = "mount/secrets/enable" + // ObservationTypeMountSecretsDisable is emitted when a secret mount is disabled ObservationTypeMountSecretsDisable = "mount/secrets/disable" - // namespace + // ObservationTypeNamespaceCreate is emitted when a namespace is created ObservationTypeNamespaceCreate = "namespace/create" - ObservationTypeNamespacePatch = "namespace/patch" + // ObservationTypeNamespacePatch is emitted when a namespace is patched + ObservationTypeNamespacePatch = "namespace/patch" + // ObservationTypeNamespaceDelete is emitted when a namespace is deleted ObservationTypeNamespaceDelete = "namespace/delete" )