Appearance
The Auth Model
Keel has two operator paths. IAM team members use MFA-protected role assumption and short-lived STS sessions. Federated operators hold no general-purpose AWS key: they sign in through Cognito and the control plane evaluates per-capability grants. The IAM path remains the bootstrap and break-glass path.
Access levels
Keel enforces three access levels via IAM roles with least-privilege policies:
| Level | IAM Role | Permissions |
|---|---|---|
| Admin | keel-admin | Provision, destroy, manage team, require MFA. Not IAM bootstrap — see below |
| Developer | keel-developer | Deploy, exec, scale, config vars, logs, CodeBuild |
| Viewer | keel-viewer | Read-only: status, logs, dashboard, apps list |
Commands check access levels at the start of execution: keel up and keel destroy require Admin, keel deploy requires Developer, keel logs works for all roles including Viewer.
These three levels govern IAM sessions. A federated operator is not promoted to one of them; their authorization grid independently grants read, logs, exec, scale, and the other capability kinds per scope.
One-time setup
An account administrator runs keel auth setup once. The guided flow:
- Accepts AWS credentials that can create IAM users, roles, and policies. Keel holds them in memory for the duration of setup.
- Creates the three roles, their least-privilege policies and assume policies, and the team table.
- Creates an IAM user under
/keel/that can assumekeel-admin. - Enrolls an MFA device for the new user.
- Verifies the new identity and switches Keel to it.
- Requires MFA for all Keel role assumptions.
The elevated credentials are used only for setup. Keel retains the restricted IAM user credentials, which require an MFA code to assume a Keel role.
Keep your original AWS credentials safe
They are the way back in if you lose your MFA device — the first admin has nobody else who can reset it for them.
bash
keel auth setup # admin, one time; needs a terminal for the MFA step
keel auth setup --dry-run # preview every policy document without touching AWS
keel auth login # start a session — prompts for a one-time code
keel auth whoami # check identity and access levelRe-run keel auth setup after upgrading Keel to publish new versions of its policies. The command preserves MFA enforcement and existing device enrollment. It requires elevated credentials because keel-admin cannot modify Keel's own policies.
Credential handling
Keel stores two credentials per app+environment in ~/.keel/contexts/<app>/:
| File | What it is | Lifetime |
|---|---|---|
base_credentials | A long-lived IAM user access key, stored in plaintext at 0600 | Until rotated or the user is revoked |
credentials | An STS session from assuming a Keel role | 8 hours |
The base key can assume one keel-* role and read its own MFA device. Once MFA is enforced, role assumption also requires a one-time code, so the base key alone cannot access your infrastructure.
- Sessions do not refresh automatically. Run
keel auth loginagain after a session expires. - Keel generates the MFA secret on the member's machine, displays it once, and does not transmit it or write it to the debug log.
keel auth logoutclears the session;--purgealso removes the base key.- OpenTofu receives credentials through environment variables.
- Application containers use rotating ECS task-role credentials instead of IAM user keys.
- Every service has its own runtime IAM role and security group.
How access is enforced
| Layer | Role |
|---|---|
| IAM assume policy on the member's user | The enforcement point — grants exactly one keel-* role |
| MFA condition on the role's trust policy | Makes the access key insufficient on its own |
keel-mfa-enroll-policy | Held only between team add and team activate, never alongside an assume policy |
keel-team DynamoDB table | Roster and audit trail (who added whom, when, current status) |
| Cached STS credentials | What Keel's access check inspects on every privileged command |
| Operator IdP + roster binding | Verifies a Cognito subject and maps it to an opaque principal |
| Authorization grid | Allows or denies one operator capability and scope |
| Control-plane decision log | Records allowed and denied federated requests |
Because the assume policy allows a single role, a member cannot escalate by editing their local config or passing a different --role. Admins can only ever attach one of the three Keel assume policies, or the MFA enrollment policy, to a Keel-managed user — the keel-admin policy constrains iam:AttachUserPolicy with an iam:PolicyARN condition, so keel auth team cannot be used to grant arbitrary permissions.
keel-admin also cannot rewrite Keel's own IAM. It holds read-only access over role/keel-* and policy/keel-* — since policy/keel-* includes keel-admin-policy itself, write access there would let an admin session publish a new version of its own policy granting everything. Changing those documents is a bootstrap act, done by keel auth setup with elevated credentials. The one exception is iam:UpdateAssumeRolePolicy, which keel auth mfa enforce needs; it cannot grant permissions, only change who may assume.
The authorization grid governs federated operators only. It cannot narrow an IAM caller, who already holds direct AWS permissions; that is deliberate so a broken control plane cannot take away the repair path. See The Keel Control Plane for served reads and brokered credentials.
What this does not protect against
MFA makes an exfiltrated key useless — a copy in a backup, a chat message, or terminal scrollback. It does not protect a machine that is already compromised: something running as you can wait for a legitimate login and take the session from credentials, which is plaintext on disk for the life of the session.
keel-admin can create infrastructure roles, attach AWS-managed policies to them, and pass those roles to ECS tasks. Code deployed through Keel can therefore use permissions beyond those granted directly to the admin session. The model prevents direct escalation from a Keel admin session to account administrator; it does not remove the authority needed to deploy infrastructure.