pynamodb / PynamoDB

A pythonic interface to Amazon's DynamoDB
http://pynamodb.readthedocs.io
MIT License
2.45k stars 427 forks source link

AccessDeniedException in AWS Lambda #448

Open vatsalshah1990 opened 6 years ago

vatsalshah1990 commented 6 years ago

I'm successfully able to connect with DynamoDB from my local and through the policy simulator. However, pynamodb gives this error when connecting through the AWS Lambda function.

IAM Policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CloudWatchLogging",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Sid": "DynamoDBAccess",
            "Effect": "Allow",
            "Action": [
                "dynamodb:CreateTable",
                "dynamodb:BatchGetItem",
                "dynamodb:BatchWriteItem",
                "dynamodb:PutItem",
                "dynamodb:DescribeTable",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:Scan",
                "dynamodb:Query",
                "dynamodb:UpdateItem",
                "dynamodb:DeleteTable",
                "dynamodb:UpdateTable"
            ],
            "Resource": [
                "arn:aws:dynamodb:ap-south-1:*:table/lmk_staging_comments",
                "arn:aws:dynamodb:ap-south-1:*:table/lmk_staging_groups",
                "arn:aws:dynamodb:ap-south-1:*:table/lmk_staging_posts",
                "arn:aws:dynamodb:ap-south-1:*:table/lmk_staging_user_profile"
            ]
        }
    ]
}

Error Logs:

An error occurred (AccessDeniedException) on request (SQ60ECK3UMM6LLEBC2K04S6HE7VV4KQNSO5AEMVJF66Q9ASUAAJG) on table (lmk_staging_posts) when calling the DescribeTable operation:
2018-02-26 00:11:18.723000 3ca1b0 [DEBUG]       2018-02-25T18:41:18.722Z                Calling DescribeTable with arguments {'TableName': 'lmk_staging_posts'}
2018-02-26 00:19:16.045000 5e175a [DEBUG]       2018-02-25T18:49:16.45Z         Calling DescribeTable with arguments {'TableName': 'lmk_staging_posts'}
2018-02-26 00:19:16.110000 5e175a [DEBUG]       2018-02-25T18:49:16.110Z                Calling DescribeTable with arguments {'TableName': 'lmk_staging_comments'}
2018-02-26 00:19:16.157000 5e175a [DEBUG]       2018-02-25T18:49:16.157Z                Calling DescribeTable with arguments {'TableName': 'lmk_staging_groups'}
2018-02-26 00:19:16.200000 5e175a [DEBUG]       2018-02-25T18:49:16.199Z                Calling DescribeTable with arguments {'TableName': 'lmk_staging_user_profile'}
grvhi commented 5 years ago

@vatsalshah1990 - did you ever find the solution to this problem? I am currently trying to work out a solution to the same problem; it feels to me like pynamoDB / botocore is not using the Lambda function's role....

chekan-o commented 5 years ago

Hi guys,

I've faced same problem recently. I was getting same exception. My problem have happened because I didn't specify the region at model Meta. It appears that in this case pynamodb connects to default region and is not using AWS_REGION environment variable if it is set. My lambda function was deployed at non-default region eu-central-1 and DynamoDB table was also created at eu-central-1. IAM policy was also granting access to the table only at eu-central-1.

pynamodb was trying connect to us-east-1 and was getting AccessDeniedException, but table wasn't even created there. Once I specify region at meta everything went smoothly.

I would recommend to consider using AWS_REGION environment variable if it is set in cases when region is not defined at Meta because it is quite odd if lambda function from one region will connect to DynamoDB at another region. In majority of the use cases they will share same region. Also it would be useful to have information about region where pynamo was trying to connect at logs.

skytreader commented 5 years ago

@chekan-o's solution is correct but might not be complete. In my case I also had to specify the aws_access_key_id and aws_secret_access_key Meta fields.

class Robots(Model):
    class Meta:
        table_name = os.environ.get("ROBOTS_TBL", "robots-dev")
        region = "eu-west-1"
        aws_access_key_id = "**bleeped**"
        aws_secret_access_key = "**bleeped**"

My problem might've been with serverless, though, which is what I used to deploy my service. Notably, this only happened to me when I attempted to provision my DynamoDB tables from the serverless.yml specification. When I had the tables manually provisioned there were no such problems.

It seems that specifying --aws-profile to sls deploy does not make said profile propagate to the deployment. But I'm not yet sure enough to raise this problem on serverless' side.

chekan-o commented 5 years ago

@skytreader the reason why you nee secret key is because you haven’t provided your lambda with IAM policy that allows connection to the DynamoDB. You just need to add/modify IAM policy in your sls yaml template.