amazon-web-servicesamazon-dynamodbamazon-iamwhitelist

Deny DynamoDB Access if IP address not on allow list


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

Solution

  • 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.