IAM Roles Anywhere with post-quantum cryptography
AWS announced post-quantum cryptography support for IAM Roles Anywhere in March 2026.
This step-by-step guide details how to set up IAM Roles Anywhere with ML-DSA (Module-Lattice Digital Signature Algorithm) certificates, issued by our open-source serverless CA.
Create Post-quantum cryptography Serverless CA
Begin by following the instructions in Open-source Post-quantum Cryptography Serverless CA to create a ML-DSA CA.
In my case, I updated the example Cloud CA with an additional ML-DSA CA operating alongside my existing ECDSA CA. Following deployment, I downloaded my new root and issuing ML-DSA CA certs from:
Root PQC CA: https://certs.cloud-ca.com/pqc-root-ca-dev.crt
Issuing PQC CA: https://certs.cloud-ca.com/pqc-issuing-ca-dev.crt
You’ll be able to download your own CA certificates from the equivalent domain and URL for your own serverless CA.
Configure IAM Roles Anywhere
Download the CA bundle from the public endpoint, in my case: https://certs.cloud-ca.com/pqc-ca-bundle-dev.pem. If you opted to keep your CA information private, the equivalent file can be downloaded from the S3 bucket with external in the name.
We’ll be taking a similar approach to that described in my post AWS IAM Roles Anywhere with open-source private CA.
Create Trust Anchor
- log in to your Application AWS account
- Select IAM, Roles
- Scroll down to Roles Anywhere, Manage
- Create a trust anchor
- Choose your region
- Set a name for the trust anchor, e.g.
pqc-ca - Select External certificate bundle
- Paste in the CA certs bundle certs from your clipboard
- Leave notification defaults
- Add tags if desired
- Press Create Trust Anchor
In my case, the ML-DSA trust anchor is set up in the same account and region as my already existing ECDSA trust anchor.
Next set up the IAM role, trust policy, and optional session policy profile, following instructions in my post AWS IAM Roles Anywhere with open-source private CA.
Get Paul Schwarzenberger’s stories in your inbox
Join Medium for free to get updates from this writer.
In my case, as I’d already done that previously for ECDSA testing with IAM Roles Anywhere, I didn’t need to repeat it.
Download AWS IAM Roles Anywhere Credential Helper
- Download the AWS IAM Roles Anywhere Credential Helper v1.85 or later for your operating system
- Copy the binary into your home directory
- Alternatively copy to another location, e.g.
usr/bin/localand set directory in yourPATH - if using MacOS, remove file name extended attribute:
xattr -c aws_signing_helper - set as executable:
chmod 755 aws_signing_helper
Obtain ML-DSA client certificate
Issue a fully post-quantum client certificate from your ML-DSA CA, with AWS credentials for your CA AWS account:
git clone https://github.com/serverless-ca/terraform-aws-ca.git
cd terraform-aws-ca
pip install -r utils/requirements.txt
python utils/client-cert.py --profile <your-aws-profile> --keyalgo ml-dsa-44 --project pqc- ML-DSA-44 key pair is generated locally
- CSR is signed with the local ML-DSA key and submitted to the tls-cert Lambda function, which issues the certificate signed by the ML-DSA issuing CA
— project pqctargets the ML-DSA deployment when more than one CA shares the AWS account, as in the example deployment — omit for an account with a single CA- certificate, private key (PKCS8) and CA bundle are written to your local
~/certsdirectory
Install OpenSSL version 4, make sure it’s the default version in PATH, and run:
openssl verify -CAfile ~/certs/ca-bundle.pem ~/certs/client-cert.crt
openssl x509 -in ~/certs/client-cert.crt -text -nooutConvert ML-DSA private key format
The AWS IAM Roles Anywhere Credential Helper version 1.8.5 only supports one of the three ML-DSA private key formats allowed by RFC 9881, and this is not the version used by Python Cryptography. Details are in this GitHub Issue which I raised on 1 November 2026.
To ensure compatibility, using OpenSSL version 4, convert the private key format:
openssl pkey -in ~/certs/client-key.pem -provparam ml-dsa.output_formats=seed-priv -out ~/certs/client-key-seedpriv.pem
openssl asn1parse -in ~/certs/client-key-seedpriv.pem -strparse 20 | cut -c1-60 # expect SEQUENCE, OCTET STRING l=32, OCTET STRING l=2560Set AWS CLI profile
Using a text editor such as vi edit ~/.aws/config and insert:
[profile pqc]
credential_process = ./aws_signing_helper credential-process --certificate certs/client-cert.crt --private-key certs/client-key-seedpriv.pem --trust-anchor-arn arn:aws:rolesanywhere:REGION:ACCOUNT_ID:trust-anchor/TRUST_ANCHOR_ID --profile-arn arn:aws:rolesanywhere:REGION:ACCOUNT_ID:profile/PROFILE_ID --role-arn arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME- for example:
[profile pqc]
credential_process = ./aws_signing_helper credential-process --certificate certs/client-cert.crt --private-key certs/client-key-seedpriv.pem --trust-anchor-arn "arn:aws:rolesanywhere:eu-west-2:992382525818:trust-anchor/3b909a8c-091f-4367-b0bc-2198ca133449" --profile-arn "arn:aws:rolesanywhere:eu-west-2:992382525818:profile/86227258-a142-433d-a4bc-6015c99b39b9" --role-arn "arn:aws:iam::992382525818:role/roles-anywhere-s3-full-access"- substitute your ARNs
- save changes
Test access
- check AWS identity:
aws sts get-caller-identity --profile pqc- you should get a response like this:
{
"UserId": "AROA6ODU3UF5DTDLJCYVE:401f1972253b0bb86bd62ac8285ad6236cc8f45a",
"Account": "992382525818",
"Arn": "arn:aws:sts::992382525818:assumed-role/roles-anywhere-s3-full-access/401f1972253b0bb86bd62ac8285ad6236cc8f45a"
}- list all S3 buckets, this should fail as access is only allowed to a single bucket
aws s3 ls --profile pqc
An error occurred (AccessDenied) when calling the ListBuckets operation: User: arn:aws:sts::992382525818:assumed-role/roles-anywhere-s3-full-access/401f1972253b0bb86bd62ac8285ad6236cc8f45a is not authorized to perform: s3:ListAllMyBuckets because no session policy allows the s3:ListAllMyBuckets action- download a file from the designated S3 bucket, this should succeed
- replace the example below with your own S3 bucket and object
aws s3 cp s3://cloud-apps-confidential/confidential.png confidential.png --profile pqc
download: s3://cloud-apps-confidential/confidential.png to ./confidential.pngOptionally you can set this AWS CLI profile as your default, in which case you don’t need to include the profile argument.
8. View connection details
- At IAM, Roles, Roles Anywhere, navigate to your region
- Select Subject Activity
- A record of connections can be seen
- Click on the link to view the certificate used to authenticate
- In CloudTrail, search for the
CreateSessionevent from therolesanywhere.amazonaws.comevent source
Details of the client, role and trust anchor can be viewed in the JSON event.
👏 🎉 🎊 Congratulations, you’ve set up and tested AWS IAM Roles Anywhere with post-quantum cryptography, using the open-source private CA 🎆 🌟 🎇









