IAM Roles Anywhere trust anchors are backed by a post-quantum (ML-DSA) PKI
IAM Roles Anywhere trust anchors are assessed for use of a post-quantum digital signature algorithm (ML-DSA). A trust anchor backed by an AWS Private CA whose KeyAlgorithm is RSA or ECC produces signatures vulnerable to forgery by a future quantum attacker, allowing an unintended actor to issue certificates and obtain unauthorized AWS access.
Risk
Trust anchors are the root of trust for workloads authenticating to AWS via X.509 certificates. If the signing CA uses RSA or ECC, an attacker with quantum capability could forge end-entity certificates and impersonate workloads. Migrating trust anchors to ML-DSA-backed PKI (NIST FIPS 204) protects this control plane in the post-quantum era.
Run this check with Prowler
Run in Prowler Cloudprowler aws --checks rolesanywhere_trust_anchor_pqc_pkiRecommendation
Back IAM Roles Anywhere trust anchors with an AWS Private CA that uses an ML-DSA key algorithm. For trust anchors backed by an external certificate bundle, ensure the certificates were issued by an ML-DSA CA and re-verify periodically as the cryptographic landscape evolves.
Remediation
CLI
aws rolesanywhere create-trust-anchor --name pqc-trust --source 'sourceType=AWS_ACM_PCA,sourceData={acmPcaArn=<ml_dsa_ca_arn>}' --enabledTerraform
resource "aws_rolesanywhere_trust_anchor" "<example_resource_name>" {
name = "pqc-trust"
enabled = true
source {
source_type = "AWS_ACM_PCA"
source_data {
acm_pca_arn = "<ml_dsa_ca_arn>" # FIX: PCA must use ML_DSA key algorithm
}
}
}NativeIaC
Resources:
<example_resource_name>:
Type: AWS::RolesAnywhere::TrustAnchor
Properties:
Name: pqc-trust
Enabled: true
Source:
SourceType: AWS_ACM_PCA
SourceData:
AcmPcaArn: <ml_dsa_ca_arn> # FIX: PCA must use ML_DSA key algorithmOther
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.acmpca.acmpca_client import acmpca_client
from prowler.providers.aws.services.rolesanywhere.rolesanywhere_client import (
rolesanywhere_client,
)
PQC_PCA_KEY_ALGORITHMS_DEFAULT = [
"ML_DSA_44",
"ML_DSA_65",
"ML_DSA_87",
]
class rolesanywhere_trust_anchor_pqc_pki(Check):
"""Verify that IAM Roles Anywhere trust anchors are backed by a post-quantum PKI.
For trust anchors whose source is ``AWS_ACM_PCA``, the linked Private CA's
``KeyAlgorithm`` is checked against the configured ML-DSA allowlist. A CA
that exists but cannot be inspected (cross-account or missing acm-pca
permissions) is a data-availability gap and is reported as MANUAL.
Trust anchors backed by an external ``CERTIFICATE_BUNDLE`` are reported as
FAIL by design: the bundle is user-supplied rather than an AWS-managed CA,
so migrating to an ML-DSA AWS Private CA is the remediation regardless of
the bundle's contents.
"""
def execute(self) -> list[Check_Report_AWS]:
findings = []
pqc_algorithms = rolesanywhere_client.audit_config.get(
"rolesanywhere_pqc_pca_key_algorithms", PQC_PCA_KEY_ALGORITHMS_DEFAULT
)
for trust_anchor in rolesanywhere_client.trust_anchors.values():
report = Check_Report_AWS(metadata=self.metadata(), resource=trust_anchor)
if trust_anchor.source_type == "AWS_ACM_PCA":
linked_ca = acmpca_client.certificate_authorities.get(
trust_anchor.acm_pca_arn
)
if linked_ca and linked_ca.status != "ACTIVE":
report.status = "FAIL"
report.status_extended = (
f"IAM Roles Anywhere trust anchor {trust_anchor.name} is "
f"backed by Private CA {linked_ca.id}, which is in "
f"{linked_ca.status or '<unknown>'} status and cannot be "
"used as an active post-quantum PKI trust root."
)
elif linked_ca and linked_ca.key_algorithm in pqc_algorithms:
report.status = "PASS"
report.status_extended = (
f"IAM Roles Anywhere trust anchor {trust_anchor.name} is "
f"backed by Private CA {linked_ca.id} using post-quantum "
f"key algorithm {linked_ca.key_algorithm}."
)
elif linked_ca:
report.status = "FAIL"
report.status_extended = (
f"IAM Roles Anywhere trust anchor {trust_anchor.name} is "
f"backed by Private CA {linked_ca.id} using key algorithm "
f"{linked_ca.key_algorithm or '<unknown>'}, which is not "
"post-quantum (ML-DSA)."
)
else:
report.status = "MANUAL"
report.status_extended = (
f"IAM Roles Anywhere trust anchor {trust_anchor.name} is "
f"backed by Private CA {trust_anchor.acm_pca_arn}, which "
"could not be inspected (cross-account or missing "
"acm-pca permissions). Verify manually that the CA uses "
"an ML-DSA key algorithm."
)
else:
source = trust_anchor.source_type or "<none>"
report.status = "FAIL"
report.status_extended = (
f"IAM Roles Anywhere trust anchor {trust_anchor.name} uses "
f"source type {source}; the certificate signature algorithm "
"cannot be inspected automatically. Migrate to an AWS Private "
"CA using an ML-DSA key algorithm to enable post-quantum "
"evaluation."
)
findings.append(report)
return findings