Environment identity and secrets #
Actions of the org-environment controller that manage an environment's Keycloak realm, its first administrator, its transactional-email key and the credentials its applications read from Kubernetes secrets. The rest of the controller is described in Environments.
Base HTTP route:
/_/organizations/:organizationId/projects/:projectId/environmentsCreate a Keycloak realm #
Provisions a Keycloak realm for an existing environment.
const environment = await kuzzle.query({
controller: 'org-environment',
action: 'createKeycloakRealm',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
environmentId: 'production'
});HTTP route:
POST /_/organizations/:organizationId/projects/:projectId/environments/:environmentId/_keycloakCreate the realm administrator #
Creates the first administrator of an environment's Keycloak realm: a user holding the kuzzleprofile-admin role, which the application maps to the Kuzzle admin profile at first login. The username defaults to admin-kuzzle-<projectId>.
No password is generated nor returned. Keycloak emails email a link to choose one, valid 72 hours. That email is also the first real send through the environment's SMTP key: if it cannot be sent, the action fails.
Running it again keeps the existing user, grants the role if it is missing and sends the link again, which is how an expired link is renewed. It refuses a username already bound to another email. Requires an owner or admin role.
const admin = await kuzzle.query({
controller: 'org-environment',
action: 'createRealmAdmin',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
environmentId: 'production',
email: 'ops@my-company.com'
// username: 'admin-kuzzle-my-project' (optional)
});
// { realmName, username, email, roleName, userId, created, roleGranted, linkLifespanSeconds }HTTP route:
POST /_/organizations/:organizationId/projects/:projectId/environments/:environmentId/keycloak/adminRotate the Scaleway SMTP API key #
Rotates the transactional-email credential of an environment. Every environment owns its own Scaleway SMTP API key, created with its Keycloak realm; this action mints a new one and pushes it everywhere it is used — the environment's Keycloak realm, its Kubernetes secret and the deployed applications, whose rendered values are rewritten so they read the credential by reference — then revokes the previous key.
Rewriting the applications changes their pod template, so they restart and pick the new key up on their own. That rewrite is not cosmetic: nothing else re-renders an application that is already deployed, so without it the pods would never receive the SMTP variables, however many times they are redeployed. Their sending fails for the few seconds the restart takes.
Use it when a key has been corrupted or revoked outside the console. The secret key is returned once and never again.
const apiKey = await kuzzle.query({
controller: 'org-environment',
action: 'createScalewaySmtpApiKey',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
environmentId: 'production'
});
// { access_key, secret_key, secretName, keycloakUpdated, rewrittenApplications }HTTP route:
POST /_/organizations/:organizationId/projects/:projectId/environments/:environmentId/scaleway/smtp-api-keyRotate the Keycloak client secret #
Regenerates the OIDC client secret of an environment's Keycloak realm, publishes it in the environment's Kubernetes secret, and rewrites the deployed applications so they read it by reference instead of carrying its value. That rewrite changes the pod template, so the applications restart and pick up the new secret on their own.
Use it when the secret's value may have been read by a third party: regenerating is what makes the copies already taken useless. The previous secret stops authenticating immediately, so the applications are unauthenticated for the few seconds separating the regeneration from their restart.
Nothing secret is returned: the value never transits through the caller.
const rotation = await kuzzle.query({
controller: 'org-environment',
action: 'rotateKeycloakClientSecret',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
environmentId: 'production'
});
// { realmName, secretName, rewrittenApplications }HTTP route:
POST /_/organizations/:organizationId/projects/:projectId/environments/:environmentId/keycloak/client-secretSeal the platform credentials #
Moves the two platform credentials of the environment's Kuzzle applications — the log-shipping (Loki) push token and the snapshot S3 key pair — out of their rendered values and into the environment's Kubernetes secret, which the applications then read by reference. Rewriting the values rolls the applications' pods.
This is a repair action for environments deployed before the platform stored these credentials by reference. It is idempotent: replaying it refreshes the secret and only reports the applications it actually had to rewrite. Requires an owner or admin role.
const result = await kuzzle.query({
controller: 'org-environment',
action: 'applyPlatformSecrets',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
environmentId: 'production'
});HTTP route:
POST /_/organizations/:organizationId/projects/:projectId/environments/:environmentId/platform-secretsApply the application encryption keys #
Gives every Kuzzle application of the environment its own encryption key, which IoT Platform v4 uses to encrypt the secrets it stores in its database (network provider credentials, tenant mail accounts) and requires at startup.
The key is generated once, from a cryptographic random source, and kept in a Kubernetes secret of the project (crypto-<application>-<environment>). It is never regenerated: replacing it would make the data it encrypted unreadable. The application reads it by reference (application.crypto.keys), so it never appears in the application values, in the deployment manifests or in any API response. Deleting an application keeps its key, since its data may survive it in a backup.
New applications receive their key when they are created. This action is the repair for applications deployed before: it creates the missing keys, wires them, and restarts the Kuzzle pods of the applications it changes (the database is not restarted). It is idempotent, and refuses an environment where an application already sets the variable in clear. Requires an owner or admin role.
const result = await kuzzle.query({
controller: 'org-environment',
action: 'applyCryptoKeys',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
environmentId: 'production'
});
// { rewrittenApplications, skippedApplications, secrets: [{ applicationId, secretName, created, rederived }] }HTTP route:
POST /_/organizations/:organizationId/projects/:projectId/environments/:environmentId/crypto-keysApply the metrics collection #
Lets the platform collect the application metrics of every Kuzzle application of the environment. The backend imports a prometheus-scraper user with a password the platform generates once and keeps in the project secret metrics-<application>-<environment>, never regenerated (the backend only sets it at its first start). Once the backend answers, the platform creates the scraper's API key, stores it in the same secret and turns the collection on. Neither appears in any value or API response.
New applications get this on their own. This action repairs older ones and retries a backend that was not ready; wiring a password restarts the Kuzzle pods (not the database). Idempotent; owner or admin only. States: collected, rolling-out and backend-unavailable (the platform finishes in the background), login-refused (the version does not import the user: deploy a newer one, then rerun), unsupported-chart, skipped.
const result = await kuzzle.query({
controller: 'org-environment',
action: 'applyMetricsScraper',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
environmentId: 'production'
});
// { applications: [{ applicationId, secretName, passwordCreated, apiKey, state }] }HTTP route:
POST /_/organizations/:organizationId/projects/:projectId/environments/:environmentId/metrics-scraper