101 lines
3.9 KiB
Markdown
101 lines
3.9 KiB
Markdown
# Cygnus cloud service
|
|
|
|
## Identity login API
|
|
|
|
`POST /api/v1/identity/login` requires a valid machine JWT with the
|
|
`identity.login` scope. The JWT must carry `client_id` and `installation_id`;
|
|
both must equal the values inside the encrypted payload.
|
|
|
|
The request uses a hybrid encrypted envelope:
|
|
|
|
```json
|
|
{
|
|
"keyId": "cygnus-login-2026-01",
|
|
"encryptedKey": "base64 RSA-OAEP-SHA256 encrypted AES key",
|
|
"initializationVector": "base64 12-byte AES-GCM IV",
|
|
"encryptedPayload": "base64 AES-GCM ciphertext and tag"
|
|
}
|
|
```
|
|
|
|
The AES-GCM additional authenticated data is the UTF-8 `keyId`. The decrypted
|
|
JSON is:
|
|
|
|
```json
|
|
{
|
|
"loginId": "user",
|
|
"password": "password",
|
|
"clientId": "client-id-from-jwt",
|
|
"installationId": "installation-id-from-jwt",
|
|
"nonce": "unique-random-value",
|
|
"issuedAt": "2026-07-23T06:30:00Z"
|
|
}
|
|
```
|
|
|
|
Configure the PKCS#8 RSA private key with
|
|
`CYGNUS_LOGIN_PRIVATE_KEY=file:/secure/path/login-private.pem`. Keep this key
|
|
outside the source tree and container image. The corresponding public key is
|
|
distributed to the on-prem gateway.
|
|
|
|
The database bootstrap is
|
|
`src/main/resources/db/identity/001_identity_login_schema.sql`. It is
|
|
transactional and idempotent; it copies login/menu data from `matrix.public`
|
|
to `matrix.identity`. It is intended for initial migration and controlled
|
|
development refreshes. Do not run it after `identity` becomes the production
|
|
system of record because its upserts intentionally refresh rows from `public`.
|
|
|
|
## Machine token endpoint
|
|
|
|
`POST /oauth2/token` implements the client-credentials flow used by the
|
|
on-premises gateway. The client assertion must be:
|
|
|
|
- an inner RS256 JWT signed with the installation private key;
|
|
- encrypted as RSA-OAEP-256 plus AES-256-GCM using the cloud assertion key;
|
|
- bound to the configured client ID, installation ID, and token audience;
|
|
- unexpired and no longer-lived than `CYGNUS_ASSERTION_TTL`.
|
|
|
|
The endpoint returns a short-lived RS256 access token carrying the client,
|
|
installation, tenant, license, security-version, and approved-scope claims.
|
|
The identity endpoint requires the `identity.login` scope and verifies the
|
|
same machine and tenant binding in the encrypted login payload.
|
|
|
|
Generate separate cloud key pairs:
|
|
|
|
```bash
|
|
mkdir -p config/keys
|
|
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 \
|
|
-out config/keys/assertion-decryption-private.pem
|
|
openssl pkey -in config/keys/assertion-decryption-private.pem -pubout \
|
|
-out config/keys/assertion-decryption-public.pem
|
|
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 \
|
|
-out config/keys/access-token-private.pem
|
|
openssl pkey -in config/keys/access-token-private.pem -pubout \
|
|
-out config/keys/access-token-public.pem
|
|
chmod 600 config/keys/*private.pem
|
|
```
|
|
|
|
## Dynamic tenant, installation, and license registration
|
|
|
|
Machine clients are no longer configured in a runtime `clients.yml`. The
|
|
authoritative records are:
|
|
|
|
- `identity.client_account`: tenant identity and status;
|
|
- `identity.client_installation`: machine identity, assertion public key,
|
|
allowed scopes, enabled state, and security version;
|
|
- `identity.client_license`: subscription period, package, type, status, and
|
|
licensed limits.
|
|
|
|
Token issuance resolves the installation and active license through a
|
|
Redis cache-aside service with PostgreSQL fallback. Cache entries have a
|
|
bounded TTL and can be invalidated after administrative changes. Therefore,
|
|
new customers, installations, key rotations, scope changes, and license
|
|
changes do not require restarting the cloud service.
|
|
|
|
The login/menu queries are tenant-scoped. Tenant-owned identity tables carry
|
|
`tenant_id`; `identity.pages` remains the shared feature catalog while
|
|
permissions are assigned per tenant.
|
|
|
|
Use `scripts/setup-local-communication.sh` to create keys, register or update
|
|
the database records, create the initial license, and generate the on-premises
|
|
machine assertion. Never place cloud private keys, customer assertions, or
|
|
installation private keys in the repository or container image.
|