Back to Checks
aws

IAM Roles Anywhere trust anchors are backed by a post-quantum (ML-DSA) PKI

rolesanywhere_trust_anchor_pqc_pki
Service: rolesanywhereSeverity: low
OfficialBuilt-inVerified
Categories:encryption
Resource Type:AwsRolesAnywhereTrustAnchor

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 Cloud
Run
prowler aws --checks rolesanywhere_trust_anchor_pqc_pki

Recommendation

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>}' --enabled

Terraform

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 algorithm

Other

1Create a new AWS Private CA with a post-quantum KeyAlgorithm (ML_DSA_44/65/87)
2Create a new Roles Anywhere trust anchor with sourceType=AWS_ACM_PCA pointing to the new CA
3Rotate end-entity certificates issued from the new CA
4Delete the legacy trust anchor once workloads have rotated

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