Loading…
Loading…
Describes the client that automatically fetches an assigned license from the central platform for an unlicensed deployment, eliminating manual license
The Automatic License Acquisition Client is a component within the admin-api service responsible for automatically fetching a product license from the central platform. It is designed for deployments that have been registered with the platform but do not yet have a full license installed, such as those running on a temporary bootstrap license.
This client solves the problem of manual license installation by enabling a "zero operator steps" flow. Once a deployment is registered and a license is assigned to it on the platform, this client can automatically pull and install it without any user intervention.
The client is the outbound part of the license acquisition flow. It is invoked by a polling service (SpecariaLicenseAcquisitionService), which determines when to attempt a fetch. If the client successfully retrieves a license JWT, that JWT is then passed to a validator (LicenseValidator) for cryptographic verification and activation. The client itself does not persist the license.
This feature is enabled only when the deployment has a platform-assigned deployment ID and the platform's base URL is configured.
The client's primary function, fetchIssuedLicense, orchestrates the process of retrieving a license. The entire process is designed to be "fail-open," meaning any error during the fetch operation will be logged, but will not throw an exception or crash the service. This ensures that a failure to acquire a new license does not disrupt the running deployment.
sequenceDiagram
participant Poller as License Polling Service
participant Client as License Acquisition Client
participant Platform as Platform API
Poller->>Client: Invoques fetchIssuedLicense()
Client->>Client: Resolves Deployment ID
Note right of Client: 1. Checks DB table s2r_specaria_deployment<br/>2. Falls back to S2R_SPECARIA_DEPLOYMENT_ID env var
alt ID is missing or invalid
Client-->>Poller: Returns empty (disabled)
else ID is valid
Client->>Platform: GET .../self-id-license<br/>(with mTLS client cert)
Platform-->>Client: Responds with HTTP Status & Body
alt 200 OK with valid JWT
Client->>Client: Parses {"license_jwt": "..."}
Client->>Client: Verifies license is bound to this deployment
Note right of Client: Checks 'deployment_id' and 'aud' claims in JWT payload.
Client-->>Poller: Returns Optional containing license JWT
else Any other response (404, 409, error)
Client->>Client: Logs status/error
Client-->>Poller: Returns empty
end
endThe operational sequence is as follows:
s2r_specaria_deployment database table. If the ID is not found in the database, it falls back to the S2R_SPECARIA_DEPLOYMENT_ID environment variable. If no ID can be resolved, the feature is considered disabled for this polling cycle.123e4567-e89b-12d3-a456-426614174000). The platform rejects non-compliant IDs, so the client skips the request if the ID is malformed.GET <base_url>/v1/products/<product_id>/deployments/<deployment_id>/self-id-licenseAuthorization bearer token is sent.User-Agent and an Accept: application/json header.license_jwt. It then performs a crucial pre-validation check to ensure the JWT is "bound" to the current deployment. It decodes the JWT payload and verifies that either the deployment_id claim or a specially formatted aud (audience) claim matches the deployment's own ID. If the binding is incorrect or the JWT is missing, the license is ignored.IMPORTANT
Secret Hygiene: The license JWT and the full API response body are considered sensitive and are never written to the logs. Only the HTTP status and a brief summary of the outcome are logged.
The license acquisition client is configured via environment variables and corresponding application properties.
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
s2r.specaria.deployment-id | String | — | No | The platform-issued deployment ID. Can also be set via the S2R_SPECARIA_DEPLOYMENT_ID environment variable. The database is the primary source; this is a fallback. |
S2R_SPECARIA_DEPLOYMENT_ID | String | — | No | Environment variable for the platform-issued deployment ID. Used as a fallback if the ID is not in the database. |
s2r.specaria.product-id | String | s2r | No | The product slug used in the API endpoint path. Can also be set via the SPECARIA_PRODUCT_ID environment variable. |
SPECARIA_PRODUCT_ID | String | s2r | No | Environment variable for the product slug. Overridden by the s2r.specaria.product-id property if set. |
S2R_SPECARIA_HTTP_TIMEOUT_SECONDS | Long | 60 | No | The timeout in seconds for the HTTP request to the platform license API. Minimum value is 1. |
NOTE
The base URL for the platform API is configured separately via SpecariaEndpoints and is a prerequisite for this client to be enabled. The source does not specify the exact configuration key for the base URL.
The client exposes a Java method for internal use by the SpecariaLicenseAcquisitionService. It also interacts with a specific re<customer>e platform API endpoint.
Optional<String> fetchIssuedLicense()Attempts to fetch this deployment's assigned license from the platform.
Optional<String> containing the raw license JWT if one is successfully fetched and passes the initial binding check. Returns an empty Optional if the feature is disabled, no license is available, or any error occurs during the process.Optional.The client calls the following re<customer>e endpoint.
Method: GET
Path: /v1/products/<product_id>/deployments/<deployment_id>/self-id-license
Authentication: Per-product mTLS client certificate.
Successful Response (200 OK): A JSON object containing the license.
{
"license_jwt": "<base64-encoded-jwt>",
"...": "..."
}
Key Status Codes:
200 OK: A license is available. The response body should contain the license_jwt.401 Unauthorized: The provided mTLS client certificate was not accepted.403 Forbidden: The deployment is revoked or the client certificate does not have permission.404 Not Found: The specified deployment_id is not registered with the platform.409 Conflict: The deployment is registered, but a license has not yet been assigned to it. This is considered a normal pending state.The client is designed for fail-open behavior, logging issues instead of throwing errors. Check the admin-api service logs for messages prefixed with S2R-LIC to diagnose problems.
| Log Message | Meaning & Action |
|---|---|
S2R-LIC license-acquire skipped — deployment id is not a canonical UUIDv4 | The deployment ID found in the database or environment variable is not a valid UUIDv4. The platform would reject it, so the client does not send the request. Correct the deployment ID. |
S2R-LIC license-acquire 200 without license_jwt | The platform responded successfully but did not include a license JWT in the response body. This may be a transient platform issue. |
S2R-LIC license-acquire 200 but the license is not bound to this deployment id | A critical security check failed. The platform returned a license, but its internal claims (deployment_id or aud) do not match this deployment's ID. The license is ignored to prevent incorrect installation. This could indicate a platform-side misconfiguration. |
S2R-LIC license-acquire: deployment not assigned yet (409) | This is a normal, non-error state. The platform has registered the deployment but an operator has not yet assigned a license to it. The client will try again on the next polling interval. |
S2R-LIC license-acquire: deployment not registered with the platform yet (404) | The platform does not recognize the deployment ID. This can happen if the deployment has not completed its registration process. |
S2R-LIC license-acquire: deployment revoked or client cert mismatch (403) | The platform rejected the request due to permissions. This could mean the deployment has been explicitly revoked or there is a problem with the mTLS client certificate. |
S2R-LIC license-acquire io/tls error... | A network-level error occurred, such as a connection failure, TLS handshake error, or a timeout. Check network connectivity between the deployment and the platform API. The log message includes the configured timeout. |
S2R-LIC license-acquire unexpected error... | A catch-all for an unexpected Java exception during the process. This indicates a potential bug in the client itself, but the fail-open design prevents it from crashing the service. |
SpecariaLicenseAcquisitionService is the component that contains the polling logic and periodically calls this client to check for a new license.LicenseValidator component, which performs full cryptographic signature verification and activates the license.