diff --git a/vault/activity_log.go b/vault/activity_log.go index 461daae920e6..fdfb07857430 100644 --- a/vault/activity_log.go +++ b/vault/activity_log.go @@ -12,6 +12,7 @@ import ( "io" "net/http" "os" + "path" "sort" "strconv" "strings" @@ -87,6 +88,16 @@ const ( entityActivityType = "entity" secretSyncActivityType = "secret-sync" + // ActivityLogMinimumRetentionMonths sets the default minimum retention_months + // to enforce when reporting is enabled. Note that this value is also statically + // defined in the UI. Any updates here should also be made to + // ui/app/models/clients/config.js. + ActivityLogMinimumRetentionMonths = 48 + + // activityLogMaximumRetentionMonths sets the default maximum retention_months + // to enforce when reporting is enabled. + activityLogMaximumRetentionMonths = 60 + // FeatureSecretSyncBilling will always be false FeatureSecretSyncBilling = license.FeatureNone ) @@ -260,7 +271,7 @@ func NewActivityLog(core *Core, logger log.Logger, view *BarrierView, metrics me precomputedQueryWritten: make(chan struct{}), } - config, err := a.loadConfigOrDefault(core.activeContext) + config, err := a.loadConfigOrDefault(core.activeContext, core.ManualLicenseReportingEnabled()) if err != nil { return nil, err } @@ -1895,12 +1906,12 @@ type activityConfig struct { func defaultActivityConfig() activityConfig { return activityConfig{ DefaultReportMonths: 12, - RetentionMonths: 24, + RetentionMonths: ActivityLogMinimumRetentionMonths, Enabled: "default", } } -func (a *ActivityLog) loadConfigOrDefault(ctx context.Context) (activityConfig, error) { +func (a *ActivityLog) loadConfigOrDefault(ctx context.Context, isReportingEnabled bool) (activityConfig, error) { // Load from storage var config activityConfig configRaw, err := a.view.Get(ctx, activityConfigKey) @@ -1915,9 +1926,36 @@ func (a *ActivityLog) loadConfigOrDefault(ctx context.Context) (activityConfig, return config, err } + // check if the retention time is lesser than the default when reporting is enabled + if (config.RetentionMonths < ActivityLogMinimumRetentionMonths) && isReportingEnabled { + updatedConfig, err := a.setDefaultRetentionMonthsInConfig(ctx, config) + if err != nil { + return config, err + } + return updatedConfig, nil + } return config, nil } +// setDefaultRetentionMonthsInConfig sets the retention months in activity config with default value. +// This supports upgrades from versions prior to set the new default ActivityLogMinimumRetentionMonths. +func (a *ActivityLog) setDefaultRetentionMonthsInConfig(ctx context.Context, inputConfig activityConfig) (activityConfig, error) { + inputConfig.RetentionMonths = ActivityLogMinimumRetentionMonths + + // Store the config + entry, err := logical.StorageEntryJSON(path.Join(activitySubPath, activityConfigKey), inputConfig) + if err != nil { + return inputConfig, err + } + if err := a.view.Put(ctx, entry); err != nil { + return inputConfig, err + } + + // Set the new config on the activity log + a.SetConfig(ctx, inputConfig) + return inputConfig, nil +} + // HandleTokenUsage adds the TokenEntry to the current fragment of the activity log // This currently occurs on token usage only. func (a *ActivityLog) HandleTokenUsage(ctx context.Context, entry *logical.TokenEntry, clientID string, isTWE bool) error { diff --git a/vault/activity_log_test.go b/vault/activity_log_test.go index dc02fed1c8ee..5280795534dc 100644 --- a/vault/activity_log_test.go +++ b/vault/activity_log_test.go @@ -860,7 +860,7 @@ func TestActivityLog_API_ConfigCRUD_Census(t *testing.T) { if err == nil { t.Fatal("expected error") } - if resp.Data["error"] != `retention_months must be at least 24 while Reporting is enabled` { + if resp.Data["error"] != `retention_months must be at least 48 while Reporting is enabled` { t.Fatalf("bad: %v", resp) } } else { @@ -871,7 +871,7 @@ func TestActivityLog_API_ConfigCRUD_Census(t *testing.T) { req = logical.TestRequest(t, logical.UpdateOperation, "internal/counters/config") req.Storage = view - req.Data["retention_months"] = 26 + req.Data["retention_months"] = 56 resp, err = b.HandleRequest(namespace.RootContext(nil), req) if err != nil { t.Fatalf("err: %v", err) @@ -917,9 +917,10 @@ func TestActivityLog_API_ConfigCRUD_Census(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } + expected := map[string]interface{}{ "default_report_months": 12, - "retention_months": 26, + "retention_months": 56, "enabled": "enable", "queries_available": false, "reporting_enabled": core.AutomatedLicenseReportingEnabled(), diff --git a/vault/activity_log_testing_util.go b/vault/activity_log_testing_util.go index 600da787c053..bbaae9551191 100644 --- a/vault/activity_log_testing_util.go +++ b/vault/activity_log_testing_util.go @@ -115,7 +115,7 @@ func (a *ActivityLog) SetStandbyEnable(ctx context.Context, enabled bool) { // TODO only patch enabled? a.SetConfigStandby(ctx, activityConfig{ DefaultReportMonths: 12, - RetentionMonths: 24, + RetentionMonths: ActivityLogMinimumRetentionMonths, Enabled: enableStr, }) } diff --git a/vault/logical_system_activity.go b/vault/logical_system_activity.go index cf0d6a273f82..bd98c084950f 100644 --- a/vault/logical_system_activity.go +++ b/vault/logical_system_activity.go @@ -18,6 +18,9 @@ import ( "github.com/hashicorp/vault/sdk/logical" ) +// defaultToRetentionMonthsMaxWarning is a warning message for setting the max retention_months value when retention_months value is more than activityLogMaximumRetentionMonths +var defaultToRetentionMonthsMaxWarning = fmt.Sprintf("retention_months cannot be greater than %d; capped to %d.", activityLogMaximumRetentionMonths, activityLogMaximumRetentionMonths) + // activityQueryPath is available in every namespace func (b *SystemBackend) activityQueryPath() *framework.Path { return &framework.Path{ @@ -109,7 +112,7 @@ func (b *SystemBackend) rootActivityPaths() []*framework.Path { }, "retention_months": { Type: framework.TypeInt, - Default: 24, + Default: ActivityLogMinimumRetentionMonths, Description: "Number of months of client data to retain. Setting to 0 will clear all existing data.", }, "enabled": { @@ -308,7 +311,7 @@ func (b *SystemBackend) handleActivityConfigRead(ctx context.Context, req *logic return logical.ErrorResponse("no activity log present"), nil } - config, err := a.loadConfigOrDefault(ctx) + config, err := a.loadConfigOrDefault(ctx, b.Core.ManualLicenseReportingEnabled()) if err != nil { return nil, err } @@ -345,7 +348,7 @@ func (b *SystemBackend) handleActivityConfigUpdate(ctx context.Context, req *log warnings := make([]string, 0) - config, err := a.loadConfigOrDefault(ctx) + config, err := a.loadConfigOrDefault(ctx, b.Core.ManualLicenseReportingEnabled()) if err != nil { return nil, err } @@ -363,6 +366,8 @@ func (b *SystemBackend) handleActivityConfigUpdate(ctx context.Context, req *log { // Parse the retention months + // For CE, this value can be between 0 and 60 + // When reporting is enabled, this value can be between 48 and 60 if retentionMonthsRaw, ok := d.GetOk("retention_months"); ok { config.RetentionMonths = retentionMonthsRaw.(int) } @@ -371,9 +376,9 @@ func (b *SystemBackend) handleActivityConfigUpdate(ctx context.Context, req *log return logical.ErrorResponse("retention_months must be greater than or equal to 0"), logical.ErrInvalidRequest } - if config.RetentionMonths > 36 { - config.RetentionMonths = 36 - warnings = append(warnings, "retention_months cannot be greater than 36; capped to 36.") + if config.RetentionMonths > activityLogMaximumRetentionMonths { + config.RetentionMonths = activityLogMaximumRetentionMonths + warnings = append(warnings, defaultToRetentionMonthsMaxWarning) } } @@ -416,7 +421,7 @@ func (b *SystemBackend) handleActivityConfigUpdate(ctx context.Context, req *log return logical.ErrorResponse("retention_months cannot be 0 while enabled"), logical.ErrInvalidRequest } - // if manual license reporting is enabled, retention months must at least be 24 months + // if manual license reporting is enabled, retention months must at least be 48 months if a.core.ManualLicenseReportingEnabled() && config.RetentionMonths < minimumRetentionMonths { return logical.ErrorResponse("retention_months must be at least %d while Reporting is enabled", minimumRetentionMonths), logical.ErrInvalidRequest }