This is an AWS credential_process
credential provider that
sources credentials from AWS Systems Manager's Default Host Management Configuration.
It allows an EC2 instance to assume a role without an associated instance profile.
This project is just a PoC. It uses a lot of code copy-pasted directly from the Amazon SSM agent GitHub repo. Don't use this for anything beyond education.
Usage
-
Follow the AWS docs on setting up DHMC in your account. Note that it is a region-specific setting.
-
Launch an EC2 instance without an associated instance profile (IAM role)
-
Install
awsaccountcreds
-
Write the following to
~/.aws/config
:[default] credential_process = /home/ec2-user/awsaccountcreds # or wherever you placed the executable
-
Run something in the AWS CLI, like
aws sts get-caller-identity
or (if the DHMC role has S3 permissions)aws s3 ls
.
How it works
See the following sequence diagram. The CLI retrieves (from the instance metadata
service) "instance identity" SigV4 credentials. Prior to DHMC, these were only used for
EC2 Instance Connect (as far as I know). Calling sts:GetCallerIdentity
with these credentials reveal they have an interesting ARN format: arn:aws:sts::607481581596:assumed-role/aws:ec2-instance/i-0ab9ac31d8ff41296
.
Next an RSA keypair is generated. The key pair's public key is sent to SSM using
the undocumented ssm:RegisterManagedInstance
API. This API call is signed using
the above credentials (C_0
in the diagram).
Finally, ssm:RequestManagedInstanceRoleToken
(also undocumented) is invoked.
This is also signed using C_0
credentials and has an additional SSM-AsymmetricKeyAuthorization
request header. This request header is an RSA signature over the Authorization
SigV4 header. This API returns credentials (C_1
in the diagram) for a role
session for the DHMC role with the instance ID as the role session name.
It seems only one RSA keypair can be registered for a given instance ID. This
keypair can then be used to retrieve credentials multiple times. I haven't yet
looked into how the RSA keypair gets refreshed, but it seems to be a thing (the
API has a boolean UpdateKeyPair
response field)
sequenceDiagram
participant CLI as AWS CLI
participant C as awsaccountcreds
participant I as EC2 IMDS
participant SSM as Systems Manager
participant STS as AWS STS
CLI->>C: Retrieve credentials
C->>I: Get EC2 instance identity credentials<br>from /identity-credentials/ec2<br>/security-credentials/ec2-instance
I->>C: Temporary AWS credentials C_0
note over C: CLI generates RSA keypair
C->>SSM: RegisterManagedInstance(rsa keypair) using instance identity credentials
SSM->>C: 200 OK
C->>SSM: RequestManagedInstanceRoleToken() using instance identity credentials <br> and SSM-AsymmetricKeyAuthorization header from RSA keypair
SSM->>STS: AssumeRole(RoleArn=DHMC role)
STS->>SSM: Temporary AWS credentials C_1
SSM->>C: Temporary AWS credentials for DHMC role C_1
C->>CLI: Temporary credentials C_1