Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions aws-integration-setup/cloudformation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ aws cloudformation create-stack \
--capabilities CAPABILITY_NAMED_IAM
```

IAM ignores alias ARNs for key operations, so the KMS policy grants its actions on the ARN you pass and on `arn:aws:kms:<region>:<account>:key/*` in the same Nullify account and region. Nullify's key policy is the real gate: the role can only use Nullify keys whose key policy allows it. Either form produces a working grant, so an existing stack does not need updating when the configure page changes. The `KMSPolicyResource` stack output lists both resources.
The policy grants its actions on the ARN you pass in one statement, and on `arn:aws:kms:<region>:<account>:key/*` in that ARN's account and region in a second. IAM ignores alias ARNs for key operations, so a Nullify alias ARN needs that wildcard to work at all; a key ARN in your own account does not, and must not reach the rest of your keys. The second statement therefore carries the IAM condition `StringNotEquals` on `aws:PrincipalAccount`, which holds only when the ARN names an account other than the one you deploy into. A Nullify ARN of either form gets the wildcard; an ARN from your own account is granted alone.

The account check runs on every request rather than at deploy time because CloudFormation template `Condition`s accept only `Ref`, `Fn::FindInMap` and other conditions, so `AWS::AccountId` cannot be compared with an account parsed out of a parameter. The effective permissions are the same either way. Nullify's key policy is the real gate: the role can only use Nullify keys whose key policy allows it. Either ARN form produces a working grant, so an existing stack does not need updating when the configure page changes. The `KMSPolicyResource` stack output lists both resources.

Update an existing stack, keeping its current values:

Expand Down Expand Up @@ -224,7 +226,7 @@ On an existing stack, add that line to the `update-stack` command above.
| `RoleArn`, `IAMRoleArn` | ARN of the Nullify read-only role |
| `RoleName` | `AWSIntegration-<CustomerName>-NullifyReadOnlyRole` |
| `KubernetesGroupName` | `nullify-readonly`, the default group for the managed EKS scan |
| `KMSPolicyResource` | Resources of the KMS policy, comma-separated: `NullifyKMSKeyArn` and `key/*` in its account and region (only when `NullifyKMSKeyArn` is set) |
| `KMSPolicyResource` | Resources of the KMS policy, comma-separated: `NullifyKMSKeyArn`, always granted, and `key/*` in its account and region, granted only when that account is not your own (only when `NullifyKMSKeyArn` is set) |

## Managed EKS scan (no in-cluster agent)

Expand Down Expand Up @@ -355,7 +357,7 @@ Other flags: `--role-arn` instead of `--customer-name`, `--authorization rbac|ad
| `401 Unauthorized` | No access entry, an entry for a since-recreated role, or `CONFIG_MAP` authentication mode |
| `403 ... cannot list <resource>` | RBAC missing or incomplete for that resource |
| Timeout connecting to the endpoint | Nullify's IPs are not in `publicAccessCidrs`, or the endpoint is private-only |
| KMS `AccessDenied` on collector upload | `NullifyKMSKeyArn` is empty or not the value shown on the configure page. If it matches, the role already allows `key/*` in that account and region, so the denial comes from Nullify's key policy: contact Nullify support |
| KMS `AccessDenied` on collector upload | `NullifyKMSKeyArn` is empty or not the value shown on the configure page. If it matches a Nullify ARN, the role already allows `key/*` in that account and region, so the denial comes from Nullify's key policy: contact Nullify support. An ARN in your own account is granted alone, and an alias ARN from your own account grants nothing, because IAM never resolves an alias ARN to a key |

### Removal

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
},
"NullifyKMSKeyArn": {
"Type": "String",
"Description": "Optional. The KMS ARN shown on the Nullify configure page. Both forms are accepted: an alias ARN (arn:aws:kms:<region>:<account>:alias/<name>) or a key ARN (arn:aws:kms:<region>:<account>:key/<key-id>, including multi-Region key/mrk-... keys). IAM ignores alias ARNs for key operations, so the policy grants the KMS actions on this ARN and on key/* in the same Nullify account and region. Nullify's key policy is the real gate: this role can only use Nullify keys whose key policy allows it.",
"Description": "Optional. The KMS ARN shown on the Nullify configure page. Both forms are accepted: an alias ARN (arn:aws:kms:<region>:<account>:alias/<name>) or a key ARN (arn:aws:kms:<region>:<account>:key/<key-id>, including multi-Region key/mrk-... keys). IAM ignores alias ARNs for key operations, so the policy grants the KMS actions on this ARN and, in a second statement, on key/* in the ARN's account and region. That second statement carries the IAM condition StringNotEquals aws:PrincipalAccount, so it applies only when the ARN names an account other than the one you deploy into: an ARN from your own account is granted on its own. Nullify's key policy is the real gate: this role can only use Nullify keys whose key policy allows it.",
"Default": "",
"AllowedPattern": "^(arn:aws:kms:[a-z0-9-]+:[0-9]{12}:(key/(mrk-)?[a-f0-9-]+|alias/[A-Za-z0-9/_-]+))?$",
"ConstraintDescription": "Must be empty, a KMS alias ARN (arn:aws:kms:<region>:<account>:alias/<name>) or a KMS key ARN (arn:aws:kms:<region>:<account>:key/<key-id>)."
Expand Down Expand Up @@ -859,7 +859,20 @@
"Resource": [
{
"Ref": "NullifyKMSKeyArn"
},
}
],
"Condition": {}
},
{
"Effect": "Allow",
"Action": [
"kms:DescribeKey",
"kms:GenerateDataKey",
"kms:GenerateDataKeyWithoutPlaintext",
"kms:ReEncryptFrom",
"kms:ReEncryptTo"
],
"Resource": [
{
"Fn::Sub": [
"arn:${KmsPartition}:kms:${KmsRegion}:${KmsAccount}:key/*",
Expand Down Expand Up @@ -931,7 +944,31 @@
]
}
],
"Condition": {}
"Condition": {
"StringNotEquals": {
"aws:PrincipalAccount": {
"Fn::Select": [
4,
{
"Fn::Split": [
":",
{
"Fn::Join": [
"",
[
{
"Ref": "NullifyKMSKeyArn"
},
":::::x"
]
]
}
]
}
]
}
}
}
}
]
}
Expand Down Expand Up @@ -969,7 +1006,7 @@
},
"KMSPolicyResource": {
"Condition": "KMSKeyProvided",
"Description": "Resources of the KMS access policy, comma-separated: NullifyKMSKeyArn and key/* in the same Nullify account and region.",
"Description": "Resources of the KMS access policy, comma-separated: NullifyKMSKeyArn, granted always, and key/* in the ARN's account and region, granted only on requests whose principal account differs from that account.",
"Value": {
"Fn::Join": [
",",
Expand Down
Loading