Action catalog
Deployed and supported. The fields and commands described here are stable within version v1alpha1.
Each API route checks one action on one resource before responding. This catalog tells you which ones, so you can write policies as tightly as possible: allow ssm:read on secret/app-* without opening ssm:write, let a CI publish a site without being able to delete it.
Example: allow reading logs and restarting apps, nothing else.
{ "Version": "1", "Statement": [
{ "Effect": "Allow", "Actions": ["deploy:list", "deploy:read", "deploy:logs"], "Resources": ["app/*"] },
{ "Effect": "Allow", "Actions": ["deploy:write"], "Resources": ["app/*"] },
{ "Effect": "Deny", "Actions": ["deploy:delete"], "Resources": ["app/*"] } ] }
How to read the tables
- Resource:
type/namedesignates an item;type/*designates the collection (list, create). AnAllowonsecret/*covers the collection; a partialDeny(secret/prod-*) does not block it, the service then filters item by item. - Everything happens in the session's tenant: a policy of another tenant does not count.
- The managed policies
readonlyandreadwriteare recalled in a column:R= covered byreadonly,RW= covered byreadwrite,A=adminonly.
Deployments and applications (deploy)
sng command | Route | Action | Resource | Managed |
|---|---|---|---|---|
sng apply | POST /v1/apply, POST /v1/apply/complete | deploy:write | release/* | RW |
sng apply of a CDNSite | same | additionally cdn:write | cdn/<site> | RW |
sng validate | POST /v1/validate | deploy:read | release/* | R |
sng plan | POST /v1/plan | deploy:read | release/* | R |
sng pull | GET /v1/export, POST /v1/export | deploy:read | resource/* | R |
sng kind list TYPE, sng kind get TYPE | GET /v1/resources/{type} | deploy:list | resource/<type>/* | R |
sng kind get TYPE NAME | GET /v1/resources/{type}/{name} | deploy:read | resource/<type>/<name> | R |
sng kind delete TYPE NAME | DELETE /v1/resources/{type}/{name} | deploy:delete | resource/<type>/<name> | RW |
sng kind delete CDNSite NAME | same | additionally cdn:delete | cdn/<site> | RW |
| — | POST /v1/deployments, POST /v1/deployments/{id}/complete | deploy:write | release/* | RW |
| — | GET /v1/deployments/{id}, GET /v1/operations/{id} | deploy:read | release/* | R |
| — | GET /v1/releases | deploy:list | release/* | R |
| — | POST /v1/releases | deploy:write | release/* | RW |
| — | POST /v1/releases/{version}/restore | deploy:write | release/<version> | RW |
sng app list, sng kind list App | GET /v1/apps | deploy:list | app/* | R |
sng app describe NAME, sng kind get App NAME | GET /v1/apps/{name} | deploy:read | app/<name> | R |
sng app create NAME | POST /v1/apps | deploy:write | app/<name> | RW |
sng app patch NAME, sng app scale NAME N, sng app restart NAME | PATCH /v1/apps/{name}, POST /v1/apps/{name}/scale, POST /v1/apps/{name}/restart | deploy:write | app/<name> | RW |
sng app delete NAME | DELETE /v1/apps/{name} | deploy:delete | app/<name> | RW |
sng app logs NAME | GET /v1/apps/{name}/logs | deploy:logs | app/<name> | R |
The sng app … commands are being enabled gradually; sng apply, sng kind list App and sng kind get App cover the same routes.
Secrets (ssm:*)
sng command | Route | Action | Resource | Managed |
|---|---|---|---|---|
sng secret list | GET /v1/secrets | ssm:list | secret/* | R |
sng secret describe NAME, sng secret versions NAME | GET /v1/secrets/{name}, GET /v1/secrets/{name}/versions | ssm:describe | secret/<name> | R |
sng secret get NAME | GET /v1/secrets/{name}/value | ssm:read | secret/<name> | R |
sng secret set NAME, sng secret restore NAME | PUT /v1/secrets/{name}, POST /v1/secrets/{name}/restore | ssm:write | secret/<name> | RW |
sng secret rotate NAME (reads the current value, then writes the new one) | GET /v1/secrets/{name}/value, PUT /v1/secrets/{name} | ssm:read and ssm:write | secret/<name> | RW |
| API only: immediate rotation and cancelling the scheduled rotation | POST /v1/secrets/{name}/rotate, POST /v1/secrets/{name}/rotate/cancel | ssm:rotate | secret/<name> | RW |
sng secret delete NAME | DELETE /v1/secrets/{name} | ssm:delete | secret/<name> | RW |
sng secret create NAME (SSMSecret manifest) | POST /v1/apply | deploy:write | release/* | RW |
The secrets service checks the same actions when one of your applications calls it directly with a session: read ssm:read, write ssm:write, declaration ssm:declare, rotation ssm:rotate, deletion ssm:delete, always on secret/<name>.
Static sites (cdn)
sng command | Route | Action | Resource | Managed |
|---|---|---|---|---|
sng kind list CDNSite | GET /v1/cdn | cdn:list | cdn/* | R |
| — | POST /v1/cdn | cdn:write | cdn/* then cdn/<site> | RW |
| — | POST /v1/cdn/{site}/enable, POST /v1/cdn/{site}/disable | cdn:write | cdn/<site> | RW |
| — | DELETE /v1/cdn/{site} | cdn:delete | cdn/<site> | RW |
| publishing | POST /v1/cdn/{site}/uploads, POST /v1/cdn/{site}/uploads/complete | cdn:upload | cdn/<site> | RW |
| cache clearing | POST /v1/cdn/{site}/cache/clear | cdn:purge | cdn/<site> | RW |
See Static sites for the corresponding commands.
Environments (env)
sng command | Route | Action | Resource | Managed |
|---|---|---|---|---|
sng env list | GET /v1/env | env:read | env/* | R |
sng env checkout NAME, sng env refresh | POST /v1/env/checkout, POST /v1/env/refresh | env:write | env/* | RW |
sng env restore REF | POST /v1/env/restore | env:admin | env/* | A |
sng env create-tenant NAME | POST /v1/env/create-tenant | env:admin | env/* | A |
Resource tier (tier)
sng command | Route | Action | Resource | Managed |
|---|---|---|---|---|
sng tenant tier list | GET /v1/tiers | tier:list | tier/<tenant> | R |
sng tenant tier show | GET /v1/tier | tier:read | tier/<tenant> | R |
sng tenant tier set TIER | PUT /v1/tier | tier:write | tier/<tenant> | A |
tier:write is not in readwrite: changing the tier requires admin.
Policies and sessions (policy, iam, oidctrust)
sng command | Route | Action | Resource | Managed |
|---|---|---|---|---|
sng tenant use, sng tenant assume | POST /v1/iam/session, POST /v1/iam/session/assume | iam:assumerole | tenant/<tenant> (policy of the target tenant) | A, assume-role |
sng tenant policy list, GET /v1/iam/bindings | GET /v1/iam/policies, GET /v1/iam/bindings | policy:list | policy/* | R |
sng tenant policy get NAME, principals NAME | GET /v1/iam/policies/{name}, …/principals | policy:read | policy/<name> | R |
sng tenant policy create|update|delete NAME | PUT|DELETE /v1/iam/policies/{name} | policy:admin | policy/<name> | A |
sng tenant policy attach|detach NAME | POST /v1/iam/policies/{name}/attach|detach, PUT|DELETE /v1/iam/bindings/{name} | policy:admin | policy/<name> | A |
sng tenant oidc list | GET /v1/iam/oidc-trusts | oidctrust:list | oidctrust/* | R |
sng tenant oidc get NAME | GET /v1/iam/oidc-trusts/{name} | oidctrust:read | oidctrust/<name> | R |
sng tenant oidc create|delete NAME | PUT|DELETE /v1/iam/oidc-trusts/{name} | oidctrust:admin | oidctrust/<name> | A |
Your end users (auth)
/v1/auth/… routes: they always apply to the directory of the session's tenant.
sng command | Route | Action | Resource | Managed |
|---|---|---|---|---|
sng iam user list | GET /v1/auth/users | auth:ListUsers | auth/users/* | R |
sng iam user describe ID | GET /v1/auth/users/{id} | auth:ListUsers | auth/users/<id> | R |
sng iam user disable|enable ID | POST /v1/auth/users/{id}/disable|enable | auth:ManageUsers | auth/users/<id> | A |
sng iam user roles ID | PUT /v1/auth/users/{id}/roles | auth:ManageUsers | auth/users/<id> | A |
sng iam user delete ID | DELETE /v1/auth/users/{id} | auth:ManageUsers | auth/users/<id> | A |
sng iam invitation list | GET /v1/auth/invitations | auth:ListUsers | auth/invitations/* | R |
sng iam user invite EMAIL, sng iam invitation delete ID | POST /v1/auth/invitations, DELETE …/{id} | auth:ManageUsers | auth/invitations/* | A |
sng iam role list|describe | GET /v1/auth/roles[/{name}] | auth:ListUsers | auth/roles/* | R |
sng iam role create|update|delete | PUT|DELETE /v1/auth/roles/{name} | auth:ManageRoles | auth/roles/<name> | A |
sng iam login-page show | GET /v1/auth/settings | auth:ListUsers | auth/settings | R |
sng iam login-page set | PUT /v1/auth/settings | auth:ManageLoginPage | auth/settings | A |
sng iam app credentials NAME | GET /v1/auth/applications/{name}/credentials | auth:ReadCredentials | iamapp/<name> | R |
sng iam app rotate NAME | POST /v1/auth/applications/{name}/rotate | auth:RotateCredentials | iamapp/<name> | A |
auth:ReadCredentials and auth:RotateCredentials are in neither readonly nor readwrite: only the admin policy reads or renews an application's credentials. The sng iam app list\|describe and sng iam provider list\|describe commands read the IAMApplication and IAMProvider objects of the desired state; they read resources like sng get and fall under the read actions of those kinds.
sng tenant destroy NAME: DELETE /v1/tenants/{tenant}, iam:admin, tenant/<tenant>.
Image registry (registry)
The registry checks each docker / sng registry operation with your session. The resource is the repository declared by a RegistryRepository.
| Operation | Action | Resource | Managed |
|---|---|---|---|
docker pull, reading a manifest, vulnerability scan | registry:pull | repository/<repository> | R |
docker push | registry:push | repository/<repository> | RW |
| deleting a manifest | registry:delete | repository/<repository> | RW |
docker login (session check only) | registry:pull | repository/login-probe | R |
sng registry access-key credentials NAME (reading the credentials of an access key) | registry:admin | accesskey/<name> | A |
sng registry access-key rotate NAME (immediate renewal of an access key) | registry:rotate | accesskey/<name> | A |
Registry access keys (RegistryAccessKey) and anonymous pulls of public repositories do not go through policies: a key has exactly the rights declared in its manifest. See OCI registry.
Encryption (kms:*)
The actions kms:wrap, kms:unwrap and kms:rewrap are accepted in a policy, but encryption is reserved for the platform in this version: it encrypts your secrets for you. A kms:* policy in your tenant opens no access.
DNS (dns)
Being rolled out. The interface described here is the one of the next release: it may still change, and may not be enabled on your tenant yet.
Being enabled gradually on tenants, with DNS management.
sng command | Route | Action | Resource |
|---|---|---|---|
sng dns zone list | GET /v1/dns/zones | dns:list | dnszone/* |
sng dns zone create DOMAIN | POST /v1/dns/zones | dns:write | dnszone/* |
sng dns zone describe DOMAIN | GET /v1/dns/zones/{domain} | dns:read | dnszone/<domain> |
sng dns zone delete DOMAIN | DELETE /v1/dns/zones/{domain} | dns:delete | dnszone/<domain> |
sng dns record list | GET /v1/dns/records | dns:list | dnsrecord/* |
sng dns record set NAME | PUT /v1/dns/records | dns:write | dnsrecord/<id> |
sng dns record describe ID | GET /v1/dns/records/{id} | dns:read | dnsrecord/<id> |
sng dns record delete ID | DELETE /v1/dns/records/{id} | dns:delete | dnsrecord/<id> |
sng apply of a DNSRecord / DNSZone | POST /v1/apply | additionally dns:write | dnsrecord/<name> / dnszone/* |
With DNS, readwrite gains dns:write and dns:delete. See DNS and domains.
Monitoring
Monitoring resources (Monitor, NotificationChannel, StatusPage) go through sng apply: these are the deploy:* actions above. No dedicated monitoring:* action exists in this version.
Routes outside policies
A few routes do not check a policy: they carry your identity, not a session.
sng command | Route | Who |
|---|---|---|
sng sso whoami | GET /v1/iam/me | any signed-in user |
sng sso logout | POST /v1/iam/logout | any signed-in user |
sng tenant list | GET /v1/tenants | any signed-in user (lists the tenants where they hold a policy) |
sng tenant create NAME | POST /v1/tenants | any user registered on StackNGO |
sng template list|search|gen | GET /v1/templates[/{kind}] | any signed-in user |
| — | GET /v1/iam/jwks.json | public |