Deny DynamoDB Access if IP address not on allow list

59 views Asked by At

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
       }
      }
   }
2

There are 2 answers

5
Maurice On BEST ANSWER

Update: 21.03.2024

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.


Outdated answer

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.

0
Leeroy Hannigan On

I would use a VPCe policy for this, if the requests are coming from within AWS (EC2, Lambda, etc...).

Adding a VPCe for DynamoDB adds no additional cost, but forces all of your traffic to go via the endpoint, which allows you to specify its own IAM policy, which treats it almost like a resource based policy, that you don't have to define on each role/user.

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/vpc-endpoints-dynamodb.html