seal

Using Seal

Markdown

Apps and identities

Grant an app, tell Seal how it proves who it is, and optionally limit where it connects from.

Apps and grants#

An app is a name, like checkout. You choose it when you seal (--app checkout) and when you grant. A grant links the app to an identity, the way a running copy proves who it is. The first grant for a name creates the app.

Each grant is a signed tenant change. The CLI opens the console for your admin key's signature, or you can use the console's Apps page. Adding an identity widens access, so it waits out your pending window.

One app can have several identities, such as a managed identity in production and a GitHub workflow for CI. Each is granted and removed on its own.

Identity types#

Prefer the identity your cloud already gives your app. Its tokens are short-lived and there's nothing to store. Use an app key only on your laptop or machines with no cloud identity.

Azure managed identity
Grant flagsazure --object-id --entra-tenant --audience
What the app needsSEAL_AZURE_AUDIENCE, plus AZURE_CLIENT_ID for a user-assigned identity
AWS IAM role
Grant flagsaws --role-arn --role-id
What the app needsThe usual AWS credentials. Rust crate with --features aws only.
Kubernetes service account
Grant flagsk8s --service-account NS/NAME --issuer --uid
What the app needsA projected token with audience seal:<tenant> and expirationSeconds: 600. The issuer must be HTTPS your replicas can reach.
Google Cloud service account
Grant flagsgcp --email --unique-id
What the app needsNothing. The SDK asks the metadata server.
GitHub Actions workflow
Grant flagsgithub --repo --repository-id --owner-id plus --environment or --ref
What the app needspermissions: id-token: write
App key
Grant flagskey --generate --out FILE, or --public HEX
What the app needsSEAL_APP_KEY set to the file's sealak_ line

Grants use ids that never change, not display names. Something deleted and recreated under the same name doesn't inherit access. Each flag's --help says where to find its id. The SDK reads the Kubernetes token from /var/run/secrets/seal.zone/token, or from SEAL_KUBERNETES_TOKEN_FILE.

Example: Azure managed identity#

Azure issues tokens only for an audience an Entra application owns. Register one per tenant:

Terminal
$az ad app create --display-name seal-acme --query appId -o tsv
$az ad app update --id <APP ID> --identifier-uris api://<APP ID>
$az ad sp create --id <APP ID>

Then grant the identity. az identity show gives its principalId and tenantId.

Terminal
$seal grant app checkout azure --object-id <OID> --entra-tenant <TID> --audience api://<APP ID>

In the app, set SEAL_AZURE_AUDIENCE=api://<APP ID>.

The SDK uses an identity your code passes, or the first one it finds in the table's order. The app key comes last, so a stray SEAL_APP_KEY can't replace a cloud identity.

Network rules#

A network rule limits where an app may start sessions from.

Terminal
$seal grant network checkout 203.0.113.0/24 198.51.100.7/32

The first network applies at once. Later ones widen access and wait. seal revoke network checkout removes the rule. Rules stop a copied identity working from elsewhere. They don't help against whoever runs the replica's host, and on Seal's hosted replica they trust Seal's front door to report the address.

Revoking an app#

Terminal
$seal revoke app checkout azure --object-id <OID> # one identity
$seal revoke app checkout # every identity

Revoking applies once signed, with no wait. Replicas pick it up within about 30 seconds and cut open sessions too. Disabling the identity at your cloud is slower, up to 24 hours for cached Azure tokens. See Rotating and revoking.

The artifact check#

An allow list makes the enclave refuse sessions whose running executable hash isn't on it.

Terminal
$seal settings integrity allow checkout checkout-server=<SHA-256>

Python and Node report the interpreter's hash by default, so report your own with endpoint_reporter. The app reports its own hash, so root on that machine can lie.