Loading…
Loading…
Manage system-wide configuration settings. Provides an interface to read, write, and validate settings, with support for tenant-specific overrides and
## Overview
The System Settings Repository provides a centralized, database-backed interface for managing platform-wide operational configuration. It allows operators to read and modify system behavior without requiring a code change or redeployment.
This component solves the problem of hard-coding configuration values by storing them in the `s2r_system_setting` database table. It provides typed accessors for retrieving settings and a transactional update mechanism with validation. It is a core part of the admin service, used by various other components to fetch configuration for tasks like generating OpenAPI specifications, managing update channels, and tuning runtime performance.
Key capabilities include:
* **Persistent Configuration**: Settings are stored in the database, surviving application restarts.
* **Tenant-Specific Overlays**: The system supports multi-tenancy by allowing tenant-specific settings to override platform-wide defaults.
* **Secret Management**: Sensitive values, such as passwords and tokens, are automatically encrypted at rest and masked in API responses.
* **Dynamic Updates**: Most settings can be changed at runtime through an API.
* **Type-Safe Access**: Provides methods to retrieve settings as specific data types (e.g., integer, boolean, string).
* **Configuration Fallbacks**: For certain critical settings like the public URL and localization, it implements a resolution chain that falls back from the database to environment variables and finally to sensible defaults.
## How it Works
The `SystemSettingRepository` manages settings stored in the `s2r_system_setting` table. Its logic is designed to be robust, secure, and compatible with multi-tenant deployments.
### Tenant Setting Overlays
The system is designed to support multiple tenants. Settings can exist at two levels:
1. **Platform-wide**: A default value stored under a special `__platform__` tenant ID.
2. **Tenant-specific**: An override value stored with a specific tenant's ID.
When a setting is requested, the repository first searches for a value specific to the currently bound tenant. If one is found, it is used. If not, the repository falls back to the platform-wide default. This "shadowing" mechanism allows each tenant to have customized configuration while sharing a common baseline. The SQL query `FIND_ALL_EFFECTIVE_SQL` explicitly orders results to ensure tenant-specific values take precedence.
### Secret Management
A subset of setting keys, defined in `SECRET_KEYS`, are treated as sensitive credentials.
* **Encryption at Rest**: When a secret setting is updated via the `patch` method, its value is encrypted using the `CredentialsCipher` service before being stored in the database. The stored value is a JSON envelope containing the encrypted data and algorithm details.
* **Masking on Read**: When settings are retrieved in bulk (e.g., via `findEffectiveMap`), the actual secret values are never returned. Instead, for each secret key like `f5_password`, a boolean flag named `f5_password_set` is returned, indicating whether a value has been stored.
* **Decryption**: To retrieve the actual plaintext secret, components must call the `getSecret(String key)` method, which fetches the encrypted value and decrypts it. Access to this method is restricted.
* **Legacy Encryption**: The `encryptLegacyPlaintextSecrets` method provides a way to find and encrypt any secrets that were stored in plaintext before the encryption-at-rest feature was introduced.
The following keys are managed as secrets:
* `f5_password`
* `alert_smtp_password`
* `f5_ingest_token`
### Configuration Resolution Chains
For certain essential, deployment-specific settings, the repository uses a multi-tiered resolution chain to determine the effective value. This provides flexibility for operators to configure the system via environment variables or the database.
A typical resolution order is:
1. **Database Setting**: The value from the `s2r_system_setting` table for the specific key (respecting the tenant overlay).
2. **Environment Variable**: If the database setting is not present, the system checks for a corresponding environment variable.
3. **Default Value**: If neither of the above is set, a hard-coded default value is used.
This pattern is used for `public_base_url`, locale settings (`openapi.primary_locale`, `openapi.supported_locales`), and the local timezone (`local.timezone`).
The diagram below illustrates the resolution flow for the `public_base_url` setting.
```mermaid
flowchart TD
subgraph resolvePublicBaseUrl
A[Start] --> B{DB setting 'public_base_url' set?};
B -- Yes --> C[Use DB value];
B -- No --> D{Env var 'S2R_PUBLIC_BASE_URL' set?};
D -- Yes --> E[Use Env var value];
D -- No --> F[Use empty string];
C --> G[Strip trailing slashes];
E --> G;
F --> H[End];
G --> H;
end
Settings are updated via the patch method, which accepts a map of key-value pairs. The process is as follows:
MUTABLE_KEYS allow-list.install_profile and update_channel, it performs strict validation against a set of allowed values. Numeric ranges are also checked for keys like update_check_interval_hours.INSERT ... ON CONFLICT DO UPDATE (upsert) statement, which creates the setting if it doesn't exist or updates it if it does. This operation is atomic per key.The SystemSettingRepository class exposes the following public methods for interacting with system settings.
| Method | Description |
|---|---|
findEffectiveMap() | Returns a Map<String, Object> of all effective settings for the current tenant. Secret values are masked, replaced by a boolean <key>_set flag. |
patch(Map<String, Object> updates, String actor) | Atomically updates one or more settings. Validates keys and values. Encrypts secrets. Throws IllegalArgumentException on validation failure. |
getString(String key, String defaultValue) | Retrieves a setting as a String. Returns defaultValue if the setting is not found or is blank. |
getInt(String key, int defaultValue) | Retrieves a setting as an int. Returns defaultValue if the setting is not found or cannot be parsed as an integer. |
getLong(String key, long defaultValue) | Retrieves a setting as a long. Returns defaultValue if the setting is not found or cannot be parsed as a long. |
getBoolean(String key, boolean defaultValue) | Retrieves a setting as a boolean. Recognizes "true", "1", "false", "0". Returns defaultValue if not found or unrecognized. |
getSecret(String key) | Retrieves and decrypts a secret setting value. Throws IllegalArgumentException if the key is not a designated secret key. Returns null if the secret is not set. |
resolvePublicBaseUrl() | Resolves the public base URL of the platform using the DB -> Env Var -> Default resolution chain. |
resolveOpenApiPrimaryLocale() | Resolves the primary locale (e.g., en-US) for OpenAPI specifications using a DB -> Env Var -> Default (en-US) chain. |
resolveOpenApiSupportedLocales() | Resolves the list of supported locales using a DB -> Env Var -> Default (primary locale) chain. |
resolveLocalZone() | Resolves the local IANA time zone ID (e.g., UTC) using a DB -> Env Var -> Default (UTC) chain. |
encryptLegacyPlaintextSecrets() | Scans for and encrypts any secret settings stored in plaintext. Returns the number of values migrated. |
The following system settings are mutable at runtime by an operator. They can be modified via the settings API.
WARNING
The keys specaria_read_only_after_days, specaria_hard_stop_after_days, and specaria_latency_injection_ms were previously mutable system settings. They have been removed and are now managed through code defaults, environment variables, or the product license. Do not attempt to set them as system settings.
IMPORTANT
The setting branding_logo_left is intentionally immutable and locked to the platform brand logo. Only branding_logo_right is available for a tenant-specific logo.
CAUTION
Changes to scheduler delay settings (e.g., f5_agg_refresh_delay_ms) only take effect after a service restart.
| Name | Type | Default | Description - |
|---|---|---|---|
max_sync_payload_mb | Integer | — | Maximum size in megabytes for a sync payload. - |
default_timeout_ms | Integer | — | Default timeout in milliseconds for operations. - |
default_retry_count | Integer | — | Default number of retries for operations. - |default_retention_days | Integer | — | Default retention period in days for audit and runtime structured data. See raw_log_* settings for raw payload retention. - |raw_log_storage_mode | String | — | Governs storage for raw log payloads. - |raw_log_db_retention_days | Integer | — | Retention period in days for raw logs stored in the database. - |raw_log_gcs_retention_days | Integer | — | Retention period in days for raw logs stored in GCS. - |aggregation_retention_days | Integer | — | Retention period in days for aggregation tables. - |dashboard_freshness_stale_minutes | Integer | 60 | The threshold in minutes after which a traffic source is marked as "STALE" on the Operations Dashboard if its data has not been refreshed. - |public_base_url | String | — | Public base URL where the platform is reachable. Used to generate absolute URLs in OpenAPI specs. Resolved via DB -> S2R_PUBLIC_BASE_URL env var -> empty string. - |install_profile | String | — | Sets the installation profile. Must be one of f5_modernization, generic_soap_to_rest, or both. This gates F5-related features in the UI and API. - |request_validation_default_mode | String | — | Default request validation mode for newly created services. Must be one of off, monitor, or enforce. The alias shadow is accepted on write and mapped to monitor. - |response_validation_default_mode | String | — | Default response validation mode for newly created services. Must be one of off, monitor, or enforce. - |runtime_route_cache_ttl_seconds | Integer | 15 | Time-to-live in seconds for the runtime route cache. The runtime refreshes this value from the DB every 60 seconds. Precedence: DB > env var > code default. - |runtime_cb_failure_threshold | Integer | 5 | The number of consecutive failures required to trip a circuit breaker to the open state. Precedence: DB > env var > code default. - |runtime_cb_open_seconds | Integer | 30 | The duration in seconds that a circuit breaker remains open after tripping. Precedence: DB > env var > code default. - |runtime_no_contract_flatten_heuristic | Boolean | false | Opt-in heuristic to flatten single-child SOAP wrapper elements for services without a formal contract. - |f5_agg_refresh_delay_ms | Long | 1,