Skip to content

IAM actions

What each role must be granted, verified against the API calls the code makes.

The two roles

The design splits reading from certifying, because they are different jobs with different blast radii. A reader can open reports and cannot mint a certificate; a certifier can mint a certificate and cannot read anything.

Reader

Used by whoever is on the security rota, to open an encrypted report.

Action Resource Why
kms:GetPublicKey encryption key Read the curve and validate the key at construction
kms:DeriveSharedSecret encryption key The ECDH agreement — the one secret operation

Must not have kms:Sign on the certification key. That refusal is the property the split exists to provide, and it is worth testing for rather than assuming: a reader that can also certify is a reader that can issue a certificate in your name.

Certifier

Used once per certificate, to assemble and publish one.

Action Resource Why
kms:GetPublicKey both keys The primary's modulus and the subkey's point both go into the certificate
kms:Sign certification key Two signatures: the identity self-certification and the subkey binding

The easiest grant to get wrong is GetPublicKey on the encryption key. A certifier that cannot read it has no subkey packet to emit, so there is nothing to bind and the certificate is useless — and the failure arrives as an AccessDeniedException on a key the operator was not thinking about.

Key specifications

Purpose KeyUsage KeySpec
Encryption subkey KEY_AGREEMENT ECC_NIST_P256 (P-384 and P-521 also work)
Certification primary SIGN_VERIFY RSA_4096

Both usages are checked at construction. NewDeriverForKey rejects a key that is not KEY_AGREEMENT and does not advertise ECDH; NewSigner rejects one that is not SIGN_VERIFY or whose public half is not RSA. Pointing at the wrong key of the right type otherwise wires up cleanly and fails later, per operation, inside whatever was using it.

Human operation

These roles are intended to carry an MFA condition and no OIDC trust. Nothing in this module assumes a CI identity, and the operations are infrequent — one assembly per certificate, one derivation per report.

Errors you will actually see

Sentinel Means
ErrKeyUnusable The key exists and cannot do the job — wrong usage, or not RSA
ErrKeyRotated The alias now points at a different key than at construction
ErrCurveMismatch The peer point is on a different curve from the KMS key
ErrNoSharedSecret KMS returned success with an empty secret
ErrNotConfigured No client or no key id was supplied

Treat an AccessDeniedException during first use as a likely gap in the key policy rather than a limitation of KMS. Policy templates are validated for shape and over-broad grants; a missing grant is not something a linter can see.