I'm trying to restrict access to the state lock management DynamoDB table. (Terraform) I understand that DynamoDB does not support resource based policies and you have to set it in a role, however I'm not actually 100% sure of that either.
The thing is that, although the policy applies greatly, it is not working. Variable details are perfekt. Important is to say I authenticate to Terraform with Short Term credentials by setting the AWs environments variables you get in the Portal and I have Administrator Access. However, I understand that an explicit deny always overwrites any allows.
I know that it is not working because I change the value of IP variable to something different and I am still able to obtain statelock info when terraform apply.
json (I have tried allow also)
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "dynamodb:*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": <myip>
}
},
"Effect": "Deny",
"Resource":<myarn>
}
]
}
This is how it looks using data iam policy document
resource "aws_iam_role" "role" {
name = "${var.dynamodb_name}-ip-restrict-role"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["dynamodb.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role_policy" "dynamodb_policy" {
name = "${var.dynamodb_name}-ip-restrict-policy"
policy = data.aws_iam_policy_document.dynamodb_policy_document.json
role = aws_iam_role.role.id
}
data "aws_iam_policy_document" "dynamodb_policy_document" {
statement {
resources = [aws_dynamodb_table.dynamodb.arn]
effect = "Deny"
actions = [
"dynamodb:*"
]
condition {
test = "NotIpAddress"
variable = "aws:SourceIp"
values = var.whitelisted_ips_dynamo
}
}
}
Two days after you asked the question, AWS released resource based policies for DynamoDB, you're in luck! It may take a few more days until terraform supports them, but now you're able to create a policy like this and attach it to your table:
{
"Version": "2012-10-17",
"Statement": [
{
"Principal": "*",
"Action": "dynamodb:*Item*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "1.1.1.1"
}
},
"Effect": "Deny",
"Resource": "arn:aws:dynamodb:eu-central-1:123123123123:table/demotable"
}
]
}
Be careful though, you may lock yourself out from managing that table if you use dynamodb:*
in the action, I suggest you use dynamodb:*Item*
, which would still allow you to update the table properties if you're not from a whitelisted IP.
You're correct, that DynamoDB supports no resource-based permissions that would allow you to limit access to certain IP addresses.
I tried your setup with this policy on my IAM User:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "dynamodb:*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "1.1.1.1"
}
},
"Effect": "Deny",
"Resource": "arn:aws:dynamodb:eu-central-1:123123123:table/demotable"
}
]
}
Any I was successfully locked out:
$ aws dynamodb describe-table --table-name demotable
An error occurred (AccessDeniedException) when calling the DescribeTable operation:
User: arn:aws:iam::123123123123:user/myuser is not authorized to perform:
dynamodb:DescribeTable on resource: arn:aws:dynamodb:eu-central-1:123123123123:table/demotable
with an explicit deny in an identity-based policy
Changing the SourceIp
to my actual IP allowed me to describe the table (the user has an admin policy).
$ aws dynamodb describe-table --table-name demotable --output yaml --no-cli-pager
Table:
AttributeDefinitions:
- AttributeName: GSI1PK
AttributeType: S
- AttributeName: GSI1SK
AttributeType: S
- AttributeName: PK
AttributeType: S
- AttributeName: SK
# ...
I suggest you check you double check your IPs and resource ARN, the policy itself looks fine aside from that.