Machine Installation id based Oauth 2
This commit is contained in:
98
cygnus-cloud-service/README.md
Normal file
98
cygnus-cloud-service/README.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# 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 `client_id`,
|
||||
`installation_id`, and the approved scope. The identity endpoint requires the
|
||||
`identity.login` scope and verifies the same machine 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
|
||||
```
|
||||
|
||||
Configure clients in an external Spring YAML file rather than the packaged
|
||||
`application.yml`:
|
||||
|
||||
```yaml
|
||||
cygnus:
|
||||
security:
|
||||
enabled: true
|
||||
issuer-uri: https://cloud.example.com
|
||||
audience: cygnus-cloud-api
|
||||
token-audience: https://cloud.example.com/oauth2/token
|
||||
clients:
|
||||
customer-a:
|
||||
enabled: true
|
||||
installation-id: site-01
|
||||
assertion-public-key: file:/secure/clients/customer-a/public.pem
|
||||
scopes:
|
||||
- identity.login
|
||||
```
|
||||
|
||||
Start with that protected file using
|
||||
`--spring.config.additional-location=file:/secure/cygnus/clients.yml`.
|
||||
Never place cloud private keys, customer assertions, or installation private
|
||||
keys in the repository or container image.
|
||||
Reference in New Issue
Block a user