DynamoDB + IAM Policies: Preventing Accidental Public Access
0 reputation · 01 May 2025, 15:25 UTC
0 reputation · 01 May 2025, 15:25 UTC
When a table is shared via an IAM policy that uses a wildcard resource ARN, any principal with permission to the broader resource can read or write the table, even if the intention was to restrict access to a specific account or service. A VPC interface endpoint can keep traffic inside a VPC, but it does not override a permissive IAM policy. Adding a customer‑managed CMK introduces another layer: the KMS key policy must grant the DynamoDB service principal and any cross‑account principals that need to access the table. The documentation does not explicitly state whether the KMS key policy must also allow a cross‑account principal when the table is shared through a resource‑based policy, leading to inconsistent access outcomes.
Given these overlapping controls, what is the safest combination of IAM, VPC endpoint, and KMS key policies that guarantees a table cannot be accessed by unintended principals?
1. Does a VPC endpoint automatically deny access for principals that are not explicitly allowed in the endpoint policy?
2. When a table is shared cross‑account via a resource‑based policy, must the KMS key policy also grant the cross‑account principal access to the CMK?
3. If a customer‑managed CMK is used, what is the minimal set of permissions required on the KMS key policy to allow DynamoDB to read and write the table while preventing other principals from doing so?
32275 reputation · 01 May 2025, 19:48 UTC
IAM policies can explicitly deny DynamoDB actions when the request does not come from an allowed source using condition keys such as aws:SourceVpce, aws:SourceIp or aws:VpcSourceIp. A VPC endpoint does not automatically deny traffic; the endpoint policy must contain an explicit deny for any action not permitted. When a table is encrypted with a customer‑managed CMK, the KMS key policy must grant the DynamoDB service principal (dynamodb.amazonaws.com) permission to use the key for encrypt/decrypt operations. If the table is shared cross‑account via a resource‑based policy, the external account’s principal must also be allowed in the KMS key policy to use the CMK.
Accidental exposure usually occurs when a broad IAM policy (e.g., AdministratorAccess) or a missing resource‑level condition allows any AWS credential holder to call DynamoDB APIs. Even if a VPC endpoint is used, a permissive IAM policy or an overly permissive endpoint policy can still let unintended principals reach the table.
arn:aws:dynamodb:us-east-1:123456789012:table/MyTable).{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "dynamodb:*",
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable",
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": "vpce-0abcd1234efgh5678"
}
}
}
]
}
If your traffic comes from the public internet, replace the condition with aws:SourceIp and list your allowed CIDR blocks.
AmazonDynamoDBFullAccess) from those principals.{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem",
"dynamodb:Query",
"dynamodb:Scan"
],
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable"
},
{
"Effect": "Deny",
"Principal": "*",
"Action": "dynamodb:*",
"Resource": "*"
}
]
}
{
"Version": "2012-10-17",
"Id": "key-dynamodb-policy",
"Statement": [
{
"Sid": "Allow DynamoDB service use",
"Effect": "Allow",
"Principal": {
"Service": "dynamodb.amazonaws.com"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
}
]
}
If the table is shared cross‑account via a resource‑based policy, add another statement that allows the external account’s role or user (or the account root) the same KMS actions:To finalize the condition in the IAM deny policy, please confirm whether your application accesses DynamoDB from within a VPC (use aws:SourceVpce) or from the public internet (use aws:SourceIp). This determines which condition key to use and does not change the overall approach otherwise.
Use comments to ask for clarification. Post a solution as an answer.
4,550 reputation · 01 May 2025, 23:26 UTC
Under current AWS behavior, VPC endpoint policies are allow-only resource policies. You do not need an explicit Deny statement for unwanted principals or actions. If a request is not matched by an Allow in the endpoint policy, it is implicitly denied at the endpoint. A principal with broad IAM permissions still cannot reach the table through the interface endpoint unless the endpoint policy explicitly allows that principal and the required DynamoDB actions.
For the CMK side, DynamoDB needs kms:Decrypt and kms:GenerateDataKey* for the service principal. The wildcard on GenerateDataKey is necessary because DynamoDB uses both GenerateDataKey and GenerateDataKeyWithoutPlaintext. Cross-account principals in a table resource-based policy must be granted those same permissions directly in the KMS key policy; cross-account IAM delegation from the key owner is not sufficient.