Permissions
How Alien manages access control across AWS, GCP, and Azure using permission profiles.
Alien derives three layers of permissions from your stack definition:
- Provisioning — Creates resources during initial setup. The customer's admin runs this once. Alien never holds these.
- Management — What Alien uses to manage deployments. Controlled by frozen and live. Management permissions avoid sensitive customer payload access by default — Alien can update your worker's code and read resource metadata, but it can't read storage objects, KV rows, or user-declared vault payloads unless you explicitly extend management permissions.
- Application runtime — What your deployed code can access. Controlled by permission profiles. This page covers this layer.
Resources are isolated by default. A worker can't read from storage, write to a queue, or access a vault unless you explicitly grant it access. This is enforced at the cloud level — IAM policies on AWS, service account bindings on GCP, role assignments on Azure.
Permission Profiles
A permission profile defines what a worker can access. Define them in your stack:
export default new alien.Stack("my-app")
.add(data, "frozen")
.add(cache, "frozen")
.add(api, "live")
.permissions({
profiles: {
execution: {
data: ["storage/data-read", "storage/data-write"],
cache: ["kv/data-read", "kv/data-write"],
},
},
})
.build()Then assign it to a worker:
const api = new alien.Worker("api")
.permissions("execution")
.build()Under the hood, each profile becomes a cloud identity:
- AWS: IAM Role
- GCP: Service Account
- Azure: User-assigned Managed Identity
Scopes
The keys inside a profile control the scope:
profiles: {
execution: {
"*": ["storage/data-read"], // all storage in the stack
"logs-storage": ["storage/data-write"] // only this specific bucket
}
}"*"— stack-level: applies to all resources of that type with the stack prefix"resource-name"— resource-scoped: applies to only that specific resource
Permission Sets
Permission sets are named bundles of cloud permissions that work across all platforms:
| Resource | Available Sets |
|---|---|
| Storage | data-read, data-write |
| KV | data-read, data-write |
| Queue | data-read, data-write |
| Vault | data-read, data-write |
| Worker | execute, invoke |
Each set maps to specific cloud actions. For example, storage/data-read translates to:
- AWS:
s3:GetObject,s3:GetObjectVersion,s3:ListBucket - GCP:
storage.objects.get,storage.objects.list,storage.buckets.get - Azure:
Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read
You don't need to know the cloud-specific actions — Alien handles the translation.
How It Works
When you deploy, Alien:
- Creates a cloud identity for each profile (IAM Role, Service Account, Managed Identity)
- Generates a permission policy from the declared permission sets
- Attaches the policy to the identity
- Configures workers to run with that identity
For resource-scoped permissions, each resource controller applies additional policies after the resource is created — scoped to the exact resource ARN, GCS bucket, or Azure resource ID.
Least-Privilege by Default
Nothing is granted unless declared. A worker with the execution profile can only do what the profile explicitly allows. If you don't grant storage/data-write, writes will fail with a permission error at runtime.
This matters especially when deploying to customer environments. The customer's security team can audit exactly what your software is allowed to do — and verify it matches what you've declared.
The same least-privilege principle applies to management permissions. Alien auto-derives the minimum management access from the frozen/live choice — frozen resources get health checks, live resources get update permissions. Those permissions may include metadata/configuration reads and cleanup operations, but they should not expose sensitive payload contents such as objects, blobs, KV entities, queue messages, or secret values.
Build management can read build metadata such as build status and history. Log and artifact access is modeled separately through explicit build log/artifact permissions.
Sensitive management access must be explicit. Some grants are written by preflights: Alien creates one internal vault named secrets for deployment secret environment variables, and the secrets preflight adds vault/data-read / vault/data-write on that concrete vault so deployment secrets can be synced. When commands are enabled, the commands preflight adds worker/dispatch-command on the concrete worker. User-declared vaults remain customer-managed unless you opt in:
.permissions({
management: {
extend: {
"customer-secrets": ["vault/data-write"],
},
},
})Grant vault/data-read only when the management identity must read secret values. Grant vault/data-write only when it must write secret values. On GCP, Alien generates custom IAM roles from the exact permissions declared in the permission sets, so the resulting roles and any IAM Conditions are visible in the reviewed role plan.
Custom Permission Sets
For edge cases not covered by built-in sets, define inline permission sets:
const assumeAnyRole: PermissionSet = {
id: "assume-any-role",
platforms: {
aws: [{
grant: { actions: ["sts:AssumeRole"] },
binding: {
stack: {
resources: ["*"],
condition: { StringEquals: { "sts:ExternalId": "my-ext-id" } }
}
}
}]
}
}
.permissions({
profiles: {
execution: {
"*": ["storage/data-read", assumeAnyRole],
}
}
})Platform Differences
| Aspect | AWS | GCP | Azure |
|---|---|---|---|
| Identity | IAM Role | Service Account | Managed Identity |
| Stack scope | ARN wildcards | Resource-level IAM | Resource group scope |
| Resource scope | Specific ARN | setIamPolicy on resource | Role assignment on resource |
| Cross-account | AssumeRole | Service account impersonation | OIDC via Federated Identity |