amazon-web-servicesamazon-dynamodbamazon-cognitofederated-identity

AccessDeniedException while trying to do dynamodb:PutItem action


My AWS Lambda function is trying to write to dynamodb. Users who log in from client app call the AWS API-Gateway endpoint that further calls the AWS Lambda function. These Users are created in AWS Cognito User pool. Login is done using Identity Pool (Federated Identity). Which means, first login using username and password gives Id_token which is exchanged with temporary IAM credentials and session token. User is in a group that has associated a role that allows writing to dynamodb table.

AWS Lambda function looks like this -

def create_profile(event, context):
    profile = json.loads(event["body"])

    session = boto3.Session(region_name='eu-west-2')
    ddb_client = session.client('dynamodb')
    row_id = str(uuid.uuid4())
    item = {
        'RowID': {
            'S': row_id
        },
        'first_name': {
            'S': profile['first_name']
        },
        'last_name': {
            'S': profile['last_name']
        }
    }

    ddb_client.put_item(TableName='Persons', Item=item)

(This is just a test code. so no validations etc. and please ignore that part)

I get this error

[ERROR] ClientError: An error occurred (AccessDeniedException) when calling the PutItem operation: User: arn:aws:sts::<ACCOUNT_ID>:assumed-role/<PREFIX>-CreateProfileFunctionRole-1VOW05TI1WR20/<PREFIX>-CreateProfileFunction-gqmkkzOP1Ro7 **is not authorized to perform:** dynamodb:PutItem on resource: arn:aws:dynamodb:eu-west-2:<ACCOUNT_ID>:table/Persons **because no identity-based policy allows** the dynamodb:PutItem action
    Traceback (most recent call last):
      File "/var/task/app.py", line 23, in create_profile
        ddb_client.put_item(TableName='Persons', Item=item)
      File "/var/runtime/botocore/client.py", line 391, in _api_call
        return self._make_api_call(operation_name, kwargs)
      File "/var/runtime/botocore/client.py", line 719, in _make_api_call
        raise error_class(parsed_response, operation_name)

My question is, why does it say "because no identity-based policy allows" since I have added AdministratorAccess managed policy already. I am thinking that the python code written above is not running under the federated identity to do further operations on more services.

I have checked that the role that the Cognito Group is associated with is "assumed" since the role can be seen in Id_token when seen in jwt.io.

Is there something wrong with my python code? Do I need to do something explicit to run it under the assumed identity to do further calls to more aws services?


Solution

  • I faced a similar issue. I managed to fix this by adding the explicit policy to that the role <PREFIX>-CreateProfileFunctionRole-1VOW05TI1WR20

    On the role add the following policy

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": "dynamodb:PutItem",
                "Resource": "arn:aws:dynamodb:eu-west-2:<ACCOUNT_ID>:table/Persons*"
            }
        ]
    }
    

    For me the problem was resolved. Hope it helps for you.