|
28 | 28 | # SA from enumerating key policies of unrelated workloads sharing the |
29 | 29 | # account (account-wide key-policy reconnaissance). Split from the main |
30 | 30 | # policy because the 6144-char limit was reached. |
| 31 | +# |
| 32 | +# - KMSTagOnCreate: kms:TagResource against a key that does NOT exist |
| 33 | +# yet (the CreateKey Tags parameter, per the AWS KMS API reference's |
| 34 | +# "Required permissions" for CreateKey) can never satisfy |
| 35 | +# aws:ResourceTag/Project: there is no resource, so no resource tag, |
| 36 | +# at authorization time. KMSMutateTaggedOnly's tag-on-EXISTING-key |
| 37 | +# grant (policy_compute.tf) therefore denies kms:TagResource during |
| 38 | +# aws_kms_key creation with Terraform's `tags` argument, breaking |
| 39 | +# every `terraform apply` that creates a new CMK (e.g. the OIDC |
| 40 | +# signing key in modules/compute/aws/lambda/signing-key.tf). AWS |
| 41 | +# authorizes tag-on-create via the aws:RequestTag/aws:TagKeys |
| 42 | +# condition keys instead, which inspect the tags being attached in |
| 43 | +# the request rather than tags already on the resource; see |
| 44 | +# "Controlling access during AWS requests" in the IAM user guide. |
| 45 | +# This MUST stay a separate statement: folding aws:RequestTag into |
| 46 | +# KMSMutateTaggedOnly would AND it with that statement's |
| 47 | +# aws:ResourceTag condition, which is exactly the unsatisfiable |
| 48 | +# combination this statement exists to avoid. Kept resource-unscoped |
| 49 | +# (Resource = "*") like KMSCreateAndRead/KMSReadTaggedOnly, since the |
| 50 | +# key ARN isn't known until CreateKey returns; the condition is what |
| 51 | +# limits it to CUDly-tagged create calls. StringEqualsIgnoreCase |
| 52 | +# matches the case-insensitive convention documented on |
| 53 | +# KMSMutateTaggedOnly (policy_compute.tf) for the same Project tag. |
| 54 | +# Added here (rather than policy_compute.tf) because the main policy |
| 55 | +# is within ~60 characters of the 6144-char limit; this statement |
| 56 | +# would not reliably fit. |
| 57 | +# aws:RequestTag alone would be an unintended privilege escalation: |
| 58 | +# it says nothing about the resource's CURRENT tags, so without more |
| 59 | +# it would let a leaked deploy token call kms:TagResource on ANY |
| 60 | +# existing key in the account (not just ones it creates), self-attach |
| 61 | +# Project=CUDly, and then use KMSMutateTaggedOnly to disable, delete, |
| 62 | +# or rewrite the key policy of that now-mistagged key, i.e. hijack a |
| 63 | +# key it never created. The added Null condition on |
| 64 | +# aws:ResourceTag/Project restricts the statement to resources with |
| 65 | +# NO Project tag yet (true for a brand-new key mid-CreateKey, false |
| 66 | +# for anything already tagged, ours or not), so it can only ever |
| 67 | +# perform the initial tag-on-create and can't be used to claim an |
| 68 | +# existing key. |
31 | 69 |
|
32 | 70 | resource "aws_iam_policy" "compute_b" { |
33 | 71 | name = "cudly-deploy-compute-b" |
@@ -97,6 +135,27 @@ resource "aws_iam_policy" "compute_b" { |
97 | 135 | } |
98 | 136 | } |
99 | 137 | }, |
| 138 | + { |
| 139 | + # kms:TagResource for the CreateKey Tags parameter. See the |
| 140 | + # KMSTagOnCreate note in the file header comment above for why |
| 141 | + # this must be a separate, aws:RequestTag-gated statement rather |
| 142 | + # than folded into KMSMutateTaggedOnly's aws:ResourceTag gate, |
| 143 | + # and why the Null condition on aws:ResourceTag/Project is |
| 144 | + # required to stop this from being usable to hijack an existing, |
| 145 | + # unrelated key by self-tagging it. |
| 146 | + Sid = "KMSTagOnCreate" |
| 147 | + Effect = "Allow" |
| 148 | + Action = ["kms:TagResource"] |
| 149 | + Resource = "*" |
| 150 | + Condition = { |
| 151 | + StringEqualsIgnoreCase = { |
| 152 | + "aws:RequestTag/Project" = "CUDly" |
| 153 | + } |
| 154 | + Null = { |
| 155 | + "aws:ResourceTag/Project" = "true" |
| 156 | + } |
| 157 | + } |
| 158 | + }, |
100 | 159 | ] |
101 | 160 | }) |
102 | 161 |
|
|
0 commit comments