Reconstruct the authorization chain
At a fictional bank, an APS role in the application account needs a symmetric key from the security account. Having kms:Decrypt in the role’s IAM policy is insufficient if the key does not authorize that access. In a cross-account policy design, check authorization at the key and delegation at the identity, without ignoring explicit denies, conditions, and applicable boundaries. Permission for the service storing the object is a separate check. Identify the effective session principal, operation, full key ARN, and Region. Within an account, a key policy can directly authorize a principal or enable IAM delegation; do not turn the cross-account pattern into a universal two-independent-permission rule for every request.
Constrain use without confusing context with a secret
kms:ViaService can restrict key use to requests made by an integrated service on the principal’s behalf through forward access sessions. A direct KMS call does not establish that the service path is authorized, nor does it automatically satisfy the condition. For symmetric operations, encryption context adds authenticated pairs that must be reproduced for decryption. It is not a secret store: it can appear in plaintext in logs. Use nonsensitive operational identifiers, never customer names or secrets. In the original exercise, Workload=nav-batch and Stage=prod identify the context. Changing prod to Prod or losing a pair can invalidate the request. Record required context alongside process metadata, protecting integrity and compatibility across application versions.
Give each grant a purpose and an exit
A grant allows specified operations on one key; it does not introduce a deny. It has one grantee and one-key scope. Creation, revocation, and retirement are eventually consistent; a grant token can allow newly granted permission to be used before normal propagation. This does not make revocation instantaneous or replace other access rules. For context, Equals requires an exact pair match; Subset allows additional pairs while retaining every required pair. Pair order does not matter, but capitalization and values do. This lesson’s Python model checks only those comparisons, not IAM or cryptography. In automation, a stable name with identical parameters helps avoid duplicate grants on retries. Define an owner, purpose, constraints, and retirement procedure when work ends.
Distinguish rotation from data migration
Rotating material in an eligible key retains the logical key identity and allows older data to remain decryptable. It does not rewrite objects or rotate data keys already used. If a plaintext data key was compromised, rotating the KMS key alone does not resolve that exposure. Envelope encryption uses a data key for the data and protects that data key with KMS. GenerateDataKey can return plaintext and encrypted copies of the data key; the application should avoid persisting the plaintext copy and remove it from memory when no longer needed. GenerateDataKeyWithoutPlaintext does not provide the plaintext copy for immediate encryption. Retargeting an alias changes future resolutions of that alias but does not automatically migrate historical ciphertext to the new key.
Rehearse recovery using the Region’s own policies
Related multi-Region keys share material and key identity, but policies, grants, aliases, and enabled/disabled state are independent. Copying architecture into another Region without reviewing these properties can leave the application unable to decrypt during recovery. The rehearsal should use the actual destination role and correct regional ARN. Do not assume every service exploits multi-Region interoperability: S3 treats these keys as regional in its server-side encryption mechanism. A private endpoint policy does not itself grant KMS authorization either. Collect evidence by operation and path. For cross-account calls, CloudTrail records in both caller and key-owner accounts help correlate who requested access, which key was used, and the result.
Treat key retirement as a recovery dependency
A PendingDeletion key stops accepting cryptographic operations, although an application might continue temporarily using cached data keys. No immediate incident does not prove disuse. Retirement review must cover historical copies, object versions, rare cycles, and restores, with identified owners. Canceling scheduled deletion leaves the key Disabled; an authorized re-enablement decision and service validation are needed. After a KMS-generated key is deleted, recreating an alias with the same name does not recover the old material. Keep planning separate from execution and use read/restore tests before approving exit. The decision should explain which data still depends on the key and for how long, rather than relying only on recent traffic.
required = {'Workload': 'nav-batch', 'Stage': 'prod'}
request = {'Stage': 'prod', 'Workload': 'nav-batch', 'Run': 'r14'}
exact_match = request == required # False: additional pair
subset_match = all(request.get(k) == v for k, v in required.items) # True
wrong_case = {**request, 'Stage': 'Prod'}
wrong_case_matches = all(wrong_case.get(k) == v for k, v in required.items) # False
# Local pair-comparison model only; not KMS encryption or IAM evaluation.In a fictional recovery rehearsal, the related multi-Region identifier exists at the destination, but the recovery role is not authorized in its regional policy. APS identifies the call and missing condition before proposing a scoped change.
Common pitfalls
Confusing IAM Allow with effective access; treating context as secret; expecting instant revocation; treating rotation as re-encryption; deleting keys because recent traffic is absent.
Related topics: S3: access, encryption, and retention
Access and recovery depend on the correct key, identity, context, operation, Region, and lifecycle together.
Reference: KMS key policies · SAP-C02