An AWS workload
A server on AWS signs one harmless AWS call with the role it already runs as, and nothing secret leaves the machine.
Not verified yet
Your CI logs in like a person does, with no key to steal. A server on AWS does the same. It signs one harmless AWS call with the role it already runs as and sends the signed request to Penv Cloud. Penv Cloud replays that request to AWS to learn who signed it.
This page is incomplete on purpose. The penv binary signs content-type, host, x-amz-date
and x-amz-security-token, and packages/store/src/aws-iam.ts refuses a request whose signed
headers do not include x-penv-cloud-org carrying the workspace id. Until the binary signs that
header there is no end-to-end command line path to document, so this page describes the mechanism
and the console setup only. Issue a pck_ credential in the console and pass it in PENV_TOKEN
meanwhile.
What the workload proves
The call is sts:GetCallerIdentity, signed with SigV4 using the role the workload already runs as.
The body is byte for byte Action=GetCallerIdentity&Version=2011-06-15, because its hash is part
of the signature. The server reads that body strictly and refuses a parameter it does not know,
because ignoring an extra parameter is how CVE-2022-2385 worked against another AWS authenticator.
Nothing secret leaves the machine. The signature is useless for anything except that one call, against that one endpoint, for a couple of minutes. Penv Cloud never sees the secret access key.
These rules govern the exchange:
- The workspace id travels inside the signature.
x-penv-cloud-orghas to appear inSignedHeaders, and a request where the header is merely present is refused. Presence alone can be fitted onto any captured signature, and nothing else in aGetCallerIdentitysignature says who the request was meant for. - The matcher is the account plus the role's immutable id. A role name can be recreated and a session name is chosen by the caller, so neither is trusted.
- The host is matched whole, against a pattern per partition. The global
sts.amazonaws.compasses and so does a regionalsts.<region>.amazonaws.com, with GovCloud and China on patterns of their own. Nothing here does a substring test, which would acceptamazonaws.com.cn.evil.com. The binary signs a regional host, resolving the region fromAWS_REGION, thenAWS_DEFAULT_REGION, thenus-east-1.
A captured signature cannot be replayed anywhere else, and it cannot be replayed here either: SigV4 carries no nonce, so single use is enforced on the Penv Cloud side by a distributed guard that records the request only once AWS has answered, which leaves a retry after an outage working.
Set up the trust
Open Machine Identities then All Identities, create an identity bound to the project and environment it should read, then add an AWS trust to it. Confirming it is you is required to create the identity.
| Field | What it is |
|---|---|
| Partition | aws, or the partition your account lives in |
| Account ID | The twelve-digit account the role belongs to |
| Role unique ID | The role's immutable id, the AROA... string |
| Expiry | How long the trust itself stays valid |
Read the role's unique id with aws iam get-role --role-name YOUR_ROLE --query Role.RoleId. It is
not the ARN, and it does not survive a delete and recreate, which is the point.
What the machine gets back
The exchange returns a pck_ credential that lasts fifteen minutes, capped by the trust's own
expiry, bound to one project and one environment. A request naming any other environment is
refused with 403 forbidden.
| Answer | What it means |
|---|---|
401 unauthorized | The trust does not name this account and role id |
401 expired | The trust's own expiry has passed |
503 unavailable | Penv Cloud could not reach AWS STS. Retry once |
Where the machine's credentials come from
The binary reads AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN from its own
environment. Every AWS runtime that hands a role to a process sets all three. The session token is
optional to the binary, and it is signed whenever it is there.
Do it in order
- Read the role's unique id:
aws iam get-role --role-name YOUR_ROLE --query Role.RoleId. - Open Machine Identities then All Identities and create an identity for that workload.
- Add an AWS trust to it with the partition, the account id and the role unique id.
- Until the binary signs the workspace header, issue a
pck_credential on the same identity. - Put that credential in
PENV_TOKENon the host and runpenv run -- <your command>. - Open the audit log and confirm the read names the identity you just created.