From 20088377ba995fd34f6f1423d3af3ea7532d4202 Mon Sep 17 00:00:00 2001 From: Raymond Laubert Date: Wed, 25 Feb 2026 11:34:05 -0500 Subject: [PATCH 1/6] feat: Added 'API Token Expiration' to the Parameter table. BED-7448 --- cmd/api/src/database/migration/migrations/v8.7.0.sql | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cmd/api/src/database/migration/migrations/v8.7.0.sql b/cmd/api/src/database/migration/migrations/v8.7.0.sql index d1b033af4d5..94f608e57c1 100644 --- a/cmd/api/src/database/migration/migrations/v8.7.0.sql +++ b/cmd/api/src/database/migration/migrations/v8.7.0.sql @@ -146,3 +146,13 @@ CREATE TABLE IF NOT EXISTS schema_list_findings ( CREATE INDEX IF NOT EXISTS idx_schema_list_findings_extension_id ON schema_list_findings (schema_extension_id); CREATE INDEX IF NOT EXISTS idx_schema_list_findings_environment_id ON schema_list_findings(environment_id); + +-- Add API Tokens Expiration Parameter +INSERT INTO parameter (key, name, description, value, created_at, updated_at) +VALUES ('auth.api_token_expiration', + 'API Token Expiration', + 'This configuration parameter enables/disables created API tokens to expire after the set number of days.', + '{"enabled":true}', + current_timestamp, + current_timestamp) +ON CONFLICT DO NOTHING; From 3503cf7ff5c5a3e553352157b22724db8e1a2ebf Mon Sep 17 00:00:00 2001 From: Raymond Laubert Date: Wed, 25 Feb 2026 13:20:16 -0500 Subject: [PATCH 2/6] feat: Added the Expiration Period to the APITokenExpiration Parameter Column, made Methods for the APITokenExpiration Parameter in the parameter file, and created unit test for the APITokenExpiration Parameter. BED-7448 --- .../database/migration/migrations/v8.7.0.sql | 2 +- cmd/api/src/database/parameters_test.go | 22 +++++++++++++++++ cmd/api/src/model/appcfg/parameter.go | 24 ++++++++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/cmd/api/src/database/migration/migrations/v8.7.0.sql b/cmd/api/src/database/migration/migrations/v8.7.0.sql index 94f608e57c1..3e4786b388d 100644 --- a/cmd/api/src/database/migration/migrations/v8.7.0.sql +++ b/cmd/api/src/database/migration/migrations/v8.7.0.sql @@ -152,7 +152,7 @@ INSERT INTO parameter (key, name, description, value, created_at, updated_at) VALUES ('auth.api_token_expiration', 'API Token Expiration', 'This configuration parameter enables/disables created API tokens to expire after the set number of days.', - '{"enabled":true}', + '{"enabled":true, "expiration_period":30}', current_timestamp, current_timestamp) ON CONFLICT DO NOTHING; diff --git a/cmd/api/src/database/parameters_test.go b/cmd/api/src/database/parameters_test.go index b8a8c971900..3ef71b91061 100644 --- a/cmd/api/src/database/parameters_test.go +++ b/cmd/api/src/database/parameters_test.go @@ -213,3 +213,25 @@ func TestParameters_GetAPITokensParameter(t *testing.T) { require.Equal(t, enableApiKeys, appcfg.GetAPITokensParameter(testCtx, db)) } + +func TestParameters_GetAPITokenExpirationParameter(t *testing.T) { + var ( + db = integration.SetupDB(t) + testCtx = context.Background() + apiKeyExpiration = true + expirationPeriod = 30 + ) + + newVal, err := types.NewJSONBObject(map[string]any{"enabled": apiKeyExpiration, "expiration_period": expirationPeriod}) + require.Nil(t, err) + + require.Nil(t, db.SetConfigurationParameter(testCtx, appcfg.Parameter{ + Key: appcfg.APITokenExpiration, + Value: newVal, + })) + + valObtained = appcfg.GetAPITokenExpirationParameter(testCtx, db) + + require.Equal(t, apiKeyExpiration, valObtained.Enabled) + require.Equal(t, expirationPeriod, valObtained.ExpirationPeriod) +} diff --git a/cmd/api/src/model/appcfg/parameter.go b/cmd/api/src/model/appcfg/parameter.go index 1201de99b8a..83be540cec9 100644 --- a/cmd/api/src/model/appcfg/parameter.go +++ b/cmd/api/src/model/appcfg/parameter.go @@ -43,6 +43,7 @@ const ( PruneTTL ParameterKey = "prune.ttl" ReconciliationKey ParameterKey = "analysis.reconciliation" ScheduledAnalysis ParameterKey = "analysis.scheduled" + APITokenExpiration ParameterKey = "auth.api_token_expiration" // The below keys are not intended to be user updatable, so should not be added to IsValidKey TrustedProxiesConfig ParameterKey = "http.trusted_proxies" @@ -90,7 +91,7 @@ func (s *Parameter) Map(value any) error { func (s *Parameter) IsValidKey(parameterKey ParameterKey) bool { switch parameterKey { - case PasswordExpirationWindow, Neo4jConfigs, PruneTTL, CitrixRDPSupportKey, ReconciliationKey, ScheduledAnalysis: + case PasswordExpirationWindow, Neo4jConfigs, PruneTTL, CitrixRDPSupportKey, ReconciliationKey, ScheduledAnalysis, APITokenExpiration: return true default: return false @@ -151,6 +152,8 @@ func (s *Parameter) Validate() utils.Errors { v = &TimeoutLimitParameter{} case EnvironmentTargetedAccessControlKey: v = &EnvironmentTargetedAccessControlParameters{} + case APITokenExpiration: + v = &APITokenExpirationParameter{} default: return utils.Errors{errors.New("invalid key")} } @@ -577,3 +580,22 @@ func GetEnvironmentTargetedAccessControlParameters(ctx context.Context, service return result } + +type APITokenExpirationParameter struct { + Enabled bool `json:"enabled"` + ExpirationPeriod int `json:"expiration_period"` +} + +func GetAPITokenExpirationParameter(ctx context.Context, service ParameterService) APITokenExpirationParameter { + result := APITokenExpirationParameter{Enabled: true} + + if cfg, err := service.GetConfigurationParameter(ctx, APITokenExpiration); err != nil { + slog.WarnContext(ctx, "Failed to fetch API tokens expiration configuration; returning default values.") + } else if err := cfg.Map(&result); err != nil { + slog.WarnContext(ctx, "Invalid API tokens expiration configuration supplied, returning default values.", + slog.String("invalid_configuration", err.Error()), + slog.String("parameter_key", string(APITokenExpiration))) + } + + return result +} From 0652e544f219bd58bc3c74db140a9920b00d9f3a Mon Sep 17 00:00:00 2001 From: Raymond Laubert Date: Wed, 25 Feb 2026 13:23:07 -0500 Subject: [PATCH 3/6] feat: Updated the Default Value for the ExpirationPeriod. BED-7448 --- cmd/api/src/database/migration/migrations/v8.7.0.sql | 2 +- cmd/api/src/database/parameters_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/api/src/database/migration/migrations/v8.7.0.sql b/cmd/api/src/database/migration/migrations/v8.7.0.sql index 3e4786b388d..dbaee4fc1f4 100644 --- a/cmd/api/src/database/migration/migrations/v8.7.0.sql +++ b/cmd/api/src/database/migration/migrations/v8.7.0.sql @@ -152,7 +152,7 @@ INSERT INTO parameter (key, name, description, value, created_at, updated_at) VALUES ('auth.api_token_expiration', 'API Token Expiration', 'This configuration parameter enables/disables created API tokens to expire after the set number of days.', - '{"enabled":true, "expiration_period":30}', + '{"enabled":true, "expiration_period":90}', current_timestamp, current_timestamp) ON CONFLICT DO NOTHING; diff --git a/cmd/api/src/database/parameters_test.go b/cmd/api/src/database/parameters_test.go index 3ef71b91061..b51de35b24a 100644 --- a/cmd/api/src/database/parameters_test.go +++ b/cmd/api/src/database/parameters_test.go @@ -219,7 +219,7 @@ func TestParameters_GetAPITokenExpirationParameter(t *testing.T) { db = integration.SetupDB(t) testCtx = context.Background() apiKeyExpiration = true - expirationPeriod = 30 + expirationPeriod = 90 ) newVal, err := types.NewJSONBObject(map[string]any{"enabled": apiKeyExpiration, "expiration_period": expirationPeriod}) From 824bea26fa8dd781c6202cfb5ce8c08059dbb30f Mon Sep 17 00:00:00 2001 From: Raymond Laubert Date: Wed, 25 Feb 2026 13:40:25 -0500 Subject: [PATCH 4/6] feat: Updated the Default Value for APITokenExpiration Enabled. BED-7448 --- cmd/api/src/database/migration/migrations/v8.7.0.sql | 2 +- cmd/api/src/model/appcfg/parameter.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/api/src/database/migration/migrations/v8.7.0.sql b/cmd/api/src/database/migration/migrations/v8.7.0.sql index dbaee4fc1f4..6e69df8ce4f 100644 --- a/cmd/api/src/database/migration/migrations/v8.7.0.sql +++ b/cmd/api/src/database/migration/migrations/v8.7.0.sql @@ -152,7 +152,7 @@ INSERT INTO parameter (key, name, description, value, created_at, updated_at) VALUES ('auth.api_token_expiration', 'API Token Expiration', 'This configuration parameter enables/disables created API tokens to expire after the set number of days.', - '{"enabled":true, "expiration_period":90}', + '{"enabled":false, "expiration_period":90}', current_timestamp, current_timestamp) ON CONFLICT DO NOTHING; diff --git a/cmd/api/src/model/appcfg/parameter.go b/cmd/api/src/model/appcfg/parameter.go index 83be540cec9..6912e3da5ba 100644 --- a/cmd/api/src/model/appcfg/parameter.go +++ b/cmd/api/src/model/appcfg/parameter.go @@ -587,7 +587,7 @@ type APITokenExpirationParameter struct { } func GetAPITokenExpirationParameter(ctx context.Context, service ParameterService) APITokenExpirationParameter { - result := APITokenExpirationParameter{Enabled: true} + result := APITokenExpirationParameter{Enabled: false, ExpirationPeriod: 90} if cfg, err := service.GetConfigurationParameter(ctx, APITokenExpiration); err != nil { slog.WarnContext(ctx, "Failed to fetch API tokens expiration configuration; returning default values.") From 50e952b4dd07580358805ba394b6a00441c800f5 Mon Sep 17 00:00:00 2001 From: Raymond Laubert Date: Thu, 26 Feb 2026 10:15:34 -0500 Subject: [PATCH 5/6] feat: Fixed mistake with variable declaration. BED-7448 --- cmd/api/src/database/parameters_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/api/src/database/parameters_test.go b/cmd/api/src/database/parameters_test.go index b51de35b24a..246f5ea1ce1 100644 --- a/cmd/api/src/database/parameters_test.go +++ b/cmd/api/src/database/parameters_test.go @@ -230,7 +230,7 @@ func TestParameters_GetAPITokenExpirationParameter(t *testing.T) { Value: newVal, })) - valObtained = appcfg.GetAPITokenExpirationParameter(testCtx, db) + valObtained := appcfg.GetAPITokenExpirationParameter(testCtx, db) require.Equal(t, apiKeyExpiration, valObtained.Enabled) require.Equal(t, expirationPeriod, valObtained.ExpirationPeriod) From 2cd90e5e4862cc85088d2a7a0b5754138ec3f7a5 Mon Sep 17 00:00:00 2001 From: Raymond Laubert Date: Thu, 26 Feb 2026 10:46:10 -0500 Subject: [PATCH 6/6] feat: Resolved comments regarding APITokenExpiration ExpirationPeriod validation and return. BED-7448 --- cmd/api/src/database/parameters_test.go | 2 +- cmd/api/src/model/appcfg/parameter.go | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd/api/src/database/parameters_test.go b/cmd/api/src/database/parameters_test.go index 246f5ea1ce1..b4a7b75c9ee 100644 --- a/cmd/api/src/database/parameters_test.go +++ b/cmd/api/src/database/parameters_test.go @@ -219,7 +219,7 @@ func TestParameters_GetAPITokenExpirationParameter(t *testing.T) { db = integration.SetupDB(t) testCtx = context.Background() apiKeyExpiration = true - expirationPeriod = 90 + expirationPeriod = 30 ) newVal, err := types.NewJSONBObject(map[string]any{"enabled": apiKeyExpiration, "expiration_period": expirationPeriod}) diff --git a/cmd/api/src/model/appcfg/parameter.go b/cmd/api/src/model/appcfg/parameter.go index 6912e3da5ba..093e0042ddc 100644 --- a/cmd/api/src/model/appcfg/parameter.go +++ b/cmd/api/src/model/appcfg/parameter.go @@ -583,7 +583,7 @@ func GetEnvironmentTargetedAccessControlParameters(ctx context.Context, service type APITokenExpirationParameter struct { Enabled bool `json:"enabled"` - ExpirationPeriod int `json:"expiration_period"` + ExpirationPeriod int `json:"expiration_period" validate:"min=1,max=365"` } func GetAPITokenExpirationParameter(ctx context.Context, service ParameterService) APITokenExpirationParameter { @@ -595,6 +595,11 @@ func GetAPITokenExpirationParameter(ctx context.Context, service ParameterServic slog.WarnContext(ctx, "Invalid API tokens expiration configuration supplied, returning default values.", slog.String("invalid_configuration", err.Error()), slog.String("parameter_key", string(APITokenExpiration))) + } else if result.ExpirationPeriod <= 0 || result.ExpirationPeriod > 365 { + slog.WarnContext(ctx, "Invalid API token expiration period supplied, returning default values.", + slog.Int("invalid_expiration_period", result.ExpirationPeriod), + slog.String("parameter_key", string(APITokenExpiration))) + result.ExpirationPeriod = 90 } return result