
Quantum-resistant signing on AWS, Part 2: Enforce your ML-DSA algorithm policy with SCPs and IAM
Explains how to turn a cryptographic algorithm policy (approve ML-DSA-65/87, exclude ML-DSA-44) into enforceable AWS controls using SCPs, IAM policies, permission boundaries and KMS key policies. The key lever is the kms:KeySpec condition key (kms:SigningAlgorithm can't distinguish variants, since all use ML_DSA_SHAKE_256), applied to CreateKey, ReplicateKey, Sign, Verify and GetPublicKey. It also covers surfaces without algorithm condition keys (AWS Private CA, ACM import, IAM server certificate upload, ELB TLS) via provisioning pipelines plus CloudTrail and AWS Config drift detection, and the default-allow risk of deny-lists.
What it is
AWS's worked example of enforcing a PQC algorithm policy: ML-DSA-65 and ML-DSA-87 approved, ML-DSA-44 excluded. The post says the exclusion is a standardization choice, not a security judgment. The mechanics work for any allow/deny split. The policy JSON did not survive in the fetched text, so the exact statements must be taken from the original post.
How it works
- KMS exposes three key specs (
ML_DSA_44,ML_DSA_65,ML_DSA_87) that all sign withML_DSA_SHAKE_256. Onlykms:KeySpeccan tell them apart. kms:KeySpecis evaluated onCreateKey,ReplicateKey,Sign,VerifyandGetPublicKey. The post says testing confirmed it on all three usage actions.- The condition value uses underscores:
ML_DSA_44, notML-DSA-44. - The most robust single control is blocking creation. With no ML-DSA-44 KMS key, none can sign or become a certificate subject key.
flowchart TD
A[Need to block ML-DSA-44] --> B{Surface}
B -->|KMS keys| C[kms:KeySpec deny: SCP / IAM / boundary / key policy]
B -->|Private CA| D[No condition key]
B -->|ACM import, IAM upload| E[Not algorithm-aware]
D --> F[Restrict who creates CAs, pin algorithm in pipeline]
E --> G[Deny import/upload unless required]
F --> H[CloudTrail + Config drift detection]
G --> HPreconditions / Affected
- SCPs do not apply to the management account, so keep ML-DSA-44-capable workloads out of it.
- These controls only cover AWS service APIs (KMS, Private CA, ACM). They cannot govern OpenSSL or application signing on EC2, containers or Lambda. They also cannot govern OpenSSH's
ssh-mldsa44-ed25519. - CloudFront, API Gateway and IAM Roles Anywhere are not covered.
What to do
- KMS creation and use: attach a
kms:KeySpecdeny at the org root or an OU as an SCP. Includekms:ReplicateKeyin the creation deny for multi-Region keys. - Usage deny: limit it to
kms:Sign,kms:Verifyandkms:GetPublicKey. Do not usekms:*. It would also blockDescribeKey,DisableKeyandScheduleKeyDeletion, locking you out of cleaning up the keys. - Per-account flexibility: use permission boundaries. They only bind principals that carry them, so enforce attachment with an SCP.
- Deny
iam:CreateRole,iam:CreateUser,iam:PutRolePermissionsBoundaryandiam:PutUserPermissionsBoundaryunlessiam:PermissionsBoundarymatches the approved boundary. - Deny
iam:DeleteRolePermissionsBoundaryandiam:DeleteUserPermissionsBoundaryoutright. - Periodically probe for non-conforming principals.
- Key policy backstop: the same deny works in a key policy, but it needs a
Principalelement, for example"Principal": {"AWS": "*"}. - Private CA:
acm-pca:CreateCertificateAuthorityhas no algorithm condition key. Deny it via SCP except for a trusted pipeline role.- Hard-code the algorithm in that pipeline. Set
KeyAlgorithmandSigningAlgorithmto the same value, such asML_DSA_65. Private CA rejectsML_DSA_SHAKE_256. - Pin the CSR key algorithm in the same pipeline. Private CA copies the CSR subject key without validating its algorithm.
- Don't rely on older AWS CLI help for valid values.
- Import and upload: deny
acm:ImportCertificateandiam:UploadServerCertificatewhere not needed. AWS saysiam:UploadServerCertificateis meant only for Regions or partitions without ACM. - ACM leaf certificates:
acm:KeyAlgorithmonacm:RequestCertificatecan allow-list algorithms. UseStringNotEqualsIfExiststo deny only requests that specify a bad algorithm. PlainStringNotEqualsalso denies requests that omit the key. - ELB: listener APIs reference certificates only by ARN, so no SCP can inspect the algorithm. Control the certificate material instead.
elasticloadbalancing:SecurityPolicycan constrain TLS policies. - Detection:
- CloudTrail logs the
KeySpeconkms:CreateKeyand the signing algorithm onCreateCertificateAuthority. - Listener events do not record the certificate's algorithm. Use AWS Config to evaluate bound or imported certificates.
- Finding existing keys: KMS has no server-side key-spec filter. Enumerate with
ListKeysandDescribeKey, or query AWS Config.
Caveats
- Naming the excluded variant is default-allow: a new variant stays usable until you add it to the deny. The alternative is
StringNotEqualsagainst the approved list, which blocks new variants until approved. Part 1's family-level SCP uses that shape, denying any signing key whose spec isn'tML_DSA_*. The post pairs the deny-list with detection and periodic review. - A blanket root SCP has no exception path and can break IaC or tests.
- Before disabling or deleting existing keys, confirm they signed nothing you still need to verify. Deletion makes verification impossible.
- ACM and ELB do not accept ML-DSA certificates at the time of writing, so those controls are forward-looking. The post tells you to validate them before relying on them.
- The policies are illustrative. Test them outside production.
Organisations named here
- FIPS 204
- kms:KeySpec
- ML-DSA
- ML_DSA_SHAKE_256
Technologies named here
- AWS Key Management Service
- AWS Private Certificate Authority
- AWS Private CA
- AWS Certificate Manager
- Service control policies
- AWS IAM policies
- Elastic Load Balancing
- IAM permission boundaries
- AWS KMS key policies
- AWS CLI / AWS SDKs
- AWS
- AWS KMS
- AWS IAM
- AWS CloudTrail
- AWS Config
- NIST
Techniques named here
- Drift detection with CloudTrail and AWS Config
Related in Cloud & Infra


Orca Security: GenAI Risks in Cloud Environments
.png)
Google API keys keep working after you delete them
