forge-cert-yields-federation

Issuing a certificate from a CA that is the trust anchor of a federation lets the issuer mint a matching external identity and federate in.

derived any cloud emits CanFederateAs

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'p': None} CanSignAs {'ca': None} {'anchor': None} TrustsExternalIdentity {'ext': None} {'ext': None} ExternalIdentityMapsTo {'internal': None}

where

node_type(?ca) == SigningKey # a certificate-authority signer (acmpca CA / gcp CAS pool) trust_anchor_of(?anchor -> ?ext) == ?ca # the trust validates certs issued by THIS CA, not merely present in the account node_type(?ext) in [ExternalIdentity, FederatedIdentity] node_type(?internal) in [Role, ServiceAccount, MachineIdentity]

emit

source typeFederatedIdentity
target typeRole
source?ext
target?internal
permissions<CA issue/sign action, e.g. acm-pca:IssueCertificate | privateca certificates.create>
conditionstrust_condition cert_subject_condition
state logicCONDITIONAL(trust_condition) by default: even with CA-issuance, the trust's profile/role condition on the certificate SUBJECT/SAN (RolesAnywhere profile `x509Subject`/SAN mapping, or the role trust `sub` derived from cert fields) must admit a subject the attacker can put in the forged cert. ACTIVE only when that cert-subject condition is ABSENT or BROAD (no subject pin / attacker can choose the SAN) so a freshly-minted cert matches — the X.509 analogue of the unpinned-subject case in rule 1. Inherit weakest with CanSignAs: if the CA issuance is CONDITIONAL (acm-pca TemplateArn restriction, key-policy gate) or BLOCKED, the federation carries that state. Never ACTIVE when the profile pins the cert subject/SAN to a value the attacker cannot present.

Narrative

{p.name} can issue certificates from {ca.name}, which is the trust anchor for {anchor.name}'s federation; it can mint a client certificate whose subject satisfies the trust, presenting an external identity it controls to federate in as {internal.name}.

Raw rule rules/derived/federation-chains.yaml

id: forge-cert-yields-federation
emits: CanFederateAs
description: Issuing a certificate from a CA that is the trust anchor of a federation lets the issuer
  mint a matching external identity and federate in.
applies_to:
- '*'
match:
- - p: null
  - CanSignAs
  - ca: null
- - anchor: null
  - TrustsExternalIdentity
  - ext: null
- - ext: null
  - ExternalIdentityMapsTo
  - internal: null
where:
- 'node_type(?ca) == SigningKey  # a certificate-authority signer (acmpca CA / gcp CAS pool)'
- 'trust_anchor_of(?anchor -> ?ext) == ?ca   # the trust validates certs issued by THIS CA, not merely
  present in the account'
- node_type(?ext) in [ExternalIdentity, FederatedIdentity]
- node_type(?internal) in [Role, ServiceAccount, MachineIdentity]
emit:
  source_type: FederatedIdentity
  target_type: Role
  source: ?ext
  target: ?internal
  permissions:
  - <CA issue/sign action, e.g. acm-pca:IssueCertificate | privateca certificates.create>
  conditions:
  - trust_condition
  - cert_subject_condition
  state_logic: "CONDITIONAL(trust_condition) by default: even with CA-issuance, the trust's profile/role\
    \ condition on the certificate SUBJECT/SAN (RolesAnywhere profile `x509Subject`/SAN mapping, or the\
    \ role trust `sub` derived from cert fields) must admit a subject the attacker can put in the forged\
    \ cert. ACTIVE only when that cert-subject condition is ABSENT or BROAD (no subject pin / attacker\
    \ can choose the SAN) so a freshly-minted cert matches \u2014 the X.509 analogue of the unpinned-subject\
    \ case in rule 1. Inherit weakest with CanSignAs: if the CA issuance is CONDITIONAL (acm-pca TemplateArn\
    \ restriction, key-policy gate) or BLOCKED, the federation carries that state. Never ACTIVE when the\
    \ profile pins the cert subject/SAN to a value the attacker cannot present."
  confidence: min(contributing_confidences) * 0.9
  derived_from:
  - ?p CanSignAs ?ca
  - ?anchor TrustsExternalIdentity ?ext (anchored on ?ca)
  - ?ext ExternalIdentityMapsTo ?internal
  false_positive_note: "Conservative and tight, mirroring credential-chains sign-as-yields-impersonation:\
    \ CA-issuance yields federation ONLY when ?ca is the ACTUAL trust anchor of the federation (trust_anchor_of\
    \ == ?ca), not merely a CA that exists in the account. Honor the certificate-subject condition: AWS\
    \ IAM Roles Anywhere profiles and role trust policies constrain on cert Subject/CN/SAN and issuer\
    \ \u2014 if the profile/role pins a subject the attacker cannot mint (a specific CN, an acm-pca:TemplateArn\
    \ restricting the issued cert), keep CONDITIONAL(trust_condition, cert_subject_condition). Respect\
    \ the CA-issuance gate from Phase-5 acmpca (acm-pca:IssueCertificate scoped by TemplateArn) / gcp\
    \ CAS (privateca.certificates.create on the CA pool with a permitted certificate template) \u2014\
    \ a CanSignAs that is itself CONDITIONAL/BLOCKED does not yield an ACTIVE federation. This does NOT\
    \ model generic cert issuance as compromise \u2014 without a federation consuming the cert it stays\
    \ at CanSignAs (cite credential-chains: signing needs a consuming trust)."
  narrative: '{p.name} can issue certificates from {ca.name}, which is the trust anchor for {anchor.name}''s
    federation; it can mint a client certificate whose subject satisfies the trust, presenting an external
    identity it controls to federate in as {internal.name}.'
move · open · esc close