Loading…
Loading…
Documents the LicenseWatermarkFilter, which adds the X-S2R-License header and a customer_id log context value to Admin API requests.
The LicenseWatermarkFilter is a servlet filter that intercepts every incoming request to the Admin API. Its primary function is to apply a "watermark" that identifies the active license associated with the request. This watermarking serves two purposes:
customer_id into the Mapped Diagnostic Context (MDC) for logging. This allows all log entries generated during the processing of a request to be tagged with the customer identifier from the active license, simplifying log analysis and troubleshooting.X-S2R-License HTTP header to the response. This header provides a quick, non-secret way to identify the license state of the instance that handled the request.The filter runs after authentication and authorization have been completed but before the core business logic of the API endpoint is executed. This ensures that the watermarking information is available to all subsequent processing steps and is included in the final response.
The LicenseWatermarkFilter processes requests in a sequence of steps designed to be both efficient and safe for the application's stability.
sequenceDiagram
participant C as API Consumer
participant A as Admin API
participant F as LicenseWatermarkFilter
participant V as License Validator
participant L as Logging Context (MDC)
C->>A: Sends API Request
A->>F: Invokes filter
alt Request path starts with /actuator/
F-->>A: Skips filtering
else Request path is processed
F->>V: currentState()
V-->>F: Returns LicenseState
F->>F: Resolves customer_id from state
F->>L: MDC.put("customer_id", ...)
F->>F: Resolves header value from state
F->>A: setHeader("X-S2R-License", ...)
F->>A: Passes request to next filter
A-->>C: Returns Response (with header)
Note right of F: In 'finally' block
F->>L: MDC.remove("customer_id")
endFor every request that does not target an /actuator/ endpoint, the filter performs the following actions:
LicenseValidator to retrieve the current LicenseState. This operation is wrapped in an exception handler; if it fails, the state is considered null, and the filter proceeds gracefully.customer_id based on the license state and adds it to the MDC using the key customer_id. This value will be automatically included in relevant log messages.X-S2R-License response header. The header is omitted if a license state cannot be determined.finally block, it removes the customer_id from the MDC. This is a critical step to prevent the customer ID from "leaking" and being associated with logs from a different request, which might be processed by the same thread.The LicenseWatermarkFilter is configured to run at a specific point in the request processing chain:
IdpAuthFilter, AdminAuthorizationFilter). This ensures that its logic only executes for authenticated requests and that the logging context it sets is available to authorized controllers.X-S2R-License header is added to the response before it is committed and sent back to the API consumer.IMPORTANT
The LicenseWatermarkFilter intentionally skips all requests to paths starting with /actuator/. This is a critical design choice to protect the stability of the platform. Health check endpoints like /actuator/health/liveness are called frequently by automated probers on a strict deadline. Because resolving the license state can involve database access, including the filter in this path would make the health check dependent on the database. A slow license lookup could cause the liveness probe to fail, triggering an unnecessary and disruptive restart of the service instance.
The filter generates two distinct pieces of information based on the current license state.
X-S2R-License Response HeaderThis HTTP header is added to all successful Admin API responses (except for /actuator/ endpoints).
| License State | X-S2R-License Header Value |
|---|---|
| Full License | The first 16 hexadecimal characters of the SHA-256 hash of the license's installation ID (licenseId). |
| Bootstrap / Activation Grace | The literal string bootstrap. |
| Unlicensed / State Unavailable | The header is omitted from the response. |
customer_id Logging Context (MDC)This key is added to the logging context for the duration of a single request.
| License State | customer_id MDC Value |
|---|---|
| Full License | The customer ID string from the license. If the ID is missing or blank, it falls back to unlicensed. |
| Bootstrap / Activation Grace | The literal string bootstrap. |
| Unlicensed / State Unavailable | The literal string unlicensed. |
For a full, active license, the X-S2R-License header value is derived from the license's installation ID.
Start with the License Installation ID (UUID):
Assume the licenseId is 123e4567-e89b-12d3-a456-426614174000.
Convert to String and Hash: The filter converts the UUID to its string representation and computes its SHA-256 digest.
Truncate the Hash: The filter takes the first 8 bytes of the resulting digest, which corresponds to the first 16 characters of the hexadecimal representation.
f33a8b2a8d7373336295b9588969352e435914620f3cce9868755f7324c7e2a1f33a8b2a8d737333Set the HTTP Header: The resulting response will include the following header:
X-S2R-License: f33a8b2a8d737333
If the LicenseValidator fails to retrieve the current license state (e.g., due to a database connection issue), the LicenseWatermarkFilter handles this gracefully:
S2R-LICENSE watermark — license state unavailable: ...).customer_id in the MDC is set to unlicensed.X-S2R-License header is omitted from the response.The request will proceed, but it will be watermarked as unlicensed.