Permissions
A permission profile is the access one workload's code gets, declared in alien.ts and as narrow as the code needs. Each profile becomes a cloud identity in the customer's account, so the cloud itself enforces it.
In the running example, the processor reads documents, writes the index, and only reads policies:
const processor = new alien.Worker("processor")
.code({ type: "source", src: "./processor", toolchain: { type: "typescript" } })
.link(documents)
.link(index)
.link(policies)
.permissions("processor")
.build()
export default new alien.Stack("acme-docs")
// .add(...) each resource
.permissions({
profiles: {
processor: {
documents: ["storage/data-read"],
index: ["kv/data-write"],
policies: ["kv/data-read"],
},
},
})
.build()Profiles
Each key in a profile is a resource id, or "*" for every resource of that type in the stack. Each value is a list of permission sets, named bundles of cloud actions such as storage/data-read.
Alien translates each set into IAM policies on AWS, IAM roles on Google Cloud, and role assignments on Azure.
| Profile becomes | AWS | Google Cloud | Azure |
|---|---|---|---|
| Identity | IAM role | Service account | User-assigned managed identity |
| Resource-scoped grant | Policy on the exact ARN | IAM binding on the resource | Role assignment on the resource |
Permission layers
A deployment has separate permissions for initial setup, ongoing management, and your application:
| Layer | Who holds it | What it covers | Where it comes from |
|---|---|---|---|
| Initial setup | The customer's admin | Creating frozen resources, identities, and the management identity (the identity Alien manages the deployment with), once | The admin's own credentials. Alien never holds them |
| Ongoing management | Alien | Rolling out releases, managing live resources, health checks | Derived from the stack. No access to the data in your resources |
| Application | Your code | Reading and writing the resources it uses | Permission profiles, this page |
Permission profiles are the application layer, and they are the part of alien.ts a customer's security team reads most closely. The management layer follows from your frozen and live choices; see Frozen and live resources.
Name every linked resource
Linking a resource to a workload grants default access when the profile doesn't name that resource:
| Linked resource | Default grant |
|---|---|
| Storage | storage/data-write (read and write) |
| KV | kv/data-write (read and write) |
| Queue | queue/data-read and queue/data-write |
| Vault | vault/data-read and vault/data-write |
| Sandbox | sandbox/execute only. Creating and terminating sandboxes (sandbox/management) must be granted explicitly. |
Triggers grant defaults the same way: a queue trigger adds queue/data-read on the queue, and a storage trigger adds storage/data-write on the bucket. A set the profile already grants under "*" isn't added again.
The defaults are broad. Name every linked resource in the profile so the grant is explicit and as narrow as the code needs. An entry you write always replaces the default.
storage/data-write and kv/data-write include read access. For Queue and Vault, grant the read set too if the code reads.
Permission sets
Common sets:
| Resource | Sets |
|---|---|
| Storage | storage/data-read, storage/data-write |
| KV | kv/data-read, kv/data-write |
| Queue | queue/data-read, queue/data-write, queue/publish |
| Vault | vault/data-read, vault/data-write |
| Postgres | postgres/data-access |
| AI | ai/invoke |
The full list, with the cloud actions behind each set, is in the permissions reference.
How grants are applied
At deploy time, Alien:
- Creates one cloud identity per profile.
- Generates a policy from its permission sets.
- Runs each workload as its profile's identity.
A grant on a named resource is applied after the resource exists, scoped to its exact ARN, bucket, or Azure resource ID. A call the profile doesn't allow fails at runtime with the cloud's permission error.
- Google Cloud. Alien generates custom IAM roles from the exact permissions in each set, so the roles and any IAM Conditions appear in the setup plan the customer reviews.
- Azure. Initial setup creates every custom role up front, and the management identity can assign only those roles to the deployment's own identities. A release that needs a new Azure role waits for initial setup.
See Management access.
The boundary in each cloud
Everything a deployment creates sits inside one boundary the customer's security team can see and revoke:
| Cloud | Boundary | How grants are scoped |
|---|---|---|
| AWS | A resource name prefix that Alien generates per deployment | Every resource is named <prefix>-<id>, and stack-wide policies use ARN wildcards on the prefix. Hundreds of deployments can share one account. |
| Google Cloud | A project the customer creates for the deployment | Project-level IAM with custom roles, plus resource-level bindings and IAM Conditions where Google Cloud supports them |
| Azure | A resource group the customer creates for the deployment | Role assignments on the resource group or on single resources |
AWS has no project or resource group, so the prefix is the boundary. Prefix-based ARNs work for S3, Lambda, SQS, and the other services Alien uses, where tag-based access control doesn't.
On AWS, initial setup also creates an IAM permissions boundary, and every role the management identity writes must carry it. It caps those roles at the deployment's own resources. See Permissions boundary.
In Terraform, the customer can set a stable prefix with the resource_prefix variable (3 to 40 lowercase letters, digits, and hyphens). The customer removes access by deleting the IAM role, the project's grants, or the resource group.
Custom permission sets
When no built-in set fits, define one inline. This one lets an exporter assume a role the customer created for reporting:
const assumeReportingRole: alien.PermissionSet = {
id: "assume-reporting-role",
description: "Assume the customer's reporting role",
platforms: {
aws: [
{
grant: { actions: ["sts:AssumeRole"] },
binding: { stack: { resources: ["arn:aws:iam::*:role/acme-reporting"] } },
},
],
},
}Use it in a profile like a built-in set: exporter: { "*": [assumeReportingRole] }. Custom sets are visible to the customer in the setup template, so keep them as narrow as the built-in ones.
Changing permissions
Initial setup creates the identities, so any change to a profile, including removing a grant, needs the customer's admin to run initial setup again. A release with a profile change stops before it changes anything and reports DEPLOYMENT_SETUP_REQUIRED.
Get profiles right before your first customer deploys. See Changes that need initial setup again.
Review what the customer will see
Render the setup template to read the exact policies your stack produces:
alien render --format cloudformation --stack .Use --format terraform --target aws|gcp|azure for Terraform, or --format helm for Kubernetes. Share the output with a customer's security team before their admin runs initial setup.
Next
- Commands: send commands from your backend to code in a deployment
- Remote bindings: read and write one resource from your backend with scoped credentials
- Permissions reference
Inputs and secrets
Declare the values each deployment needs, say whether you or the customer's admin provides them, and keep customer secrets out of Alien.
Networking and endpoints
Expose a Worker or Container over HTTPS, keep services private inside the stack, and know which network choices belong to initial setup.