Hi all, I am having some issues setting permissio...
# help
f
Hi all, I am having some issues setting permissions for a function that clears a dynamodb table (this function is only used for testing, so I am ok with letting it wipe the entries in a table): I define the function as follows:
Copy code
const clearDynamodbTableFunction = new Function(this, 'ClearDynamodbTableFunction', {
        srcPath: "src/helpers/clear_table",
        handler: 'index.handler',
        timeout: 30,
        environment: env,
        permissions: ["ssm", skillsTable, usersTable]
      });
skillsTable
and
usersTable
are tables I create earlier. I put this function behind an API:
Copy code
api.addRoutes(this, {
        "DELETE /clear-table/{table-name}": clearDynamodbTableFunction,
      });
However, upon hitting this API endpoint, I get the following message:
Copy code
botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the DescribeTable operation: User: arn:aws:sts::123:assumed-role/dev-sst-integration-my-st-ClearDynamodbTableFuncti-1T3MU86FI83FK/dev-sst-integration-my-st-ClearDynamodbTableFuncti-eQz66VCa26mn is not authorized to perform: dynamodb:DescribeTable on resource: arn:aws:dynamodb:us-east-1:table/UsersTable
Anyone got any ideas why this happens? I thought I was giving my function full access to the table.
t
Interesting, can you see if rewriting this as
Copy code
const func = new sst.Function(...)
skillsTable.grantReadWrite(func)
usersTable.grantReadWrite(func)
Fixes it
Also curious if you go into IAM and find this role
dev-sst-integration-my-st-ClearDynamodbTableFuncti-1T3MU86FI83FK/dev-sst-integration-my-st-ClearDynamodbTableFuncti-eQz66VCa26mn
what the policy is
f
Thanks @thdxr, I could not do
skillsTable.grantReadWrite(func)
I get the error
Property 'grantReadWrite' does not exist on type 'Table'.ts(2339)
My table definition:
Copy code
const skillsTable = new Table(this, "SkillsTable", {
      fields: {
        skill_id: TableFieldType.STRING,
      },
      primaryIndex: { partitionKey: "skill_id" },
    });
t
Ah sorry I meant
skillsTable.dynamodbTable.grantReadWriteData(func)
f
Thanks @thdxr, I used
usersTable.dynamodbTable.grantFullAccess(clearDynamodbTableFunction)
but that still does not seem to work. The actual lambda function is as follows (perhaps there is something in there that is not captured by the permissions):
Copy code
import boto3
dynamo = boto3.resource('dynamodb')

def truncateTable(tableName):
    table = dynamo.Table(tableName)
    
    #get the table keys
    tableKeyNames = [key.get("AttributeName") for key in table.key_schema]

    #Only retrieve the keys for each item in the table (minimize data transfer)
    projectionExpression = ", ".join('#' + key for key in tableKeyNames)
    expressionAttrNames = {'#'+key: key for key in tableKeyNames}
    
    counter = 0
    page = table.scan(ProjectionExpression=projectionExpression, ExpressionAttributeNames=expressionAttrNames)
    with table.batch_writer() as batch:
        while page["Count"] > 0:
            counter += page["Count"]
            # Delete items in batches
            for itemKeys in page["Items"]:
                batch.delete_item(Key=itemKeys)
            # Fetch the next page
            if 'LastEvaluatedKey' in page:
                page = table.scan(
                    ProjectionExpression=projectionExpression, ExpressionAttributeNames=expressionAttrNames,
                    ExclusiveStartKey=page['LastEvaluatedKey'])
            else:
                break
    print(f"Deleted {counter}")
            
truncateTable("YOUR_TABLE_NAME")
https://stackoverflow.com/a/61641766/16433984
t
Can you go into the iam console and find that role in the error message and show me the policy?
f
@thdxr yes sure - I will do that as soon as I can
@thdxr These are the policies attached to that IAM role:
t
can you show it as json and copy paste it in here
f
*Full*: Tagging *Limited*: Read, Write
Copy code
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "xray:PutTraceSegments",
        "xray:PutTelemetryRecords"
      ],
      "Resource": "*",
      "Effect": "Allow"
    },
    {
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::dev-sst-integration-debug-stack-bucket0000-0000",
        "arn:aws:s3:::dev-sst-integration-debug-stack-bucket0000-0000/*"
      ],
      "Effect": "Allow"
    },
    {
      "Action": "ssm:*",
      "Resource": "*",
      "Effect": "Allow"
    },
    {
      "Action": "dynamodb:*",
      "Resource": [
        "arn:aws:dynamodb:us-east-1:0000-0000:table/dev-sst-integration-UsersTable"
      ],
      "Effect": "Allow"
    },
    {
      "Action": "dynamodb:*",
      "Resource": [
        "arn:aws:dynamodb:us-east-1:0000-0000:table/dev-sst-integration-SkillsTable"
      ],
      "Effect": "Allow"
    }
  ]
}
@thdxr, hope I did that right, but JSON is above
t
Hmm I wonder what those
0000-0000
in there are
if you delete those and try to run your lambda does it work
"arnawsdynamodbus east 1table/dev-sst-integration-SkillsTable"
f
Ah apologies, I put those
0000
in case they were sensitive
They were actually digits
(a bit new to the AWS side of things)
I will delete these roles and redeploy
t
they're not sensitive but this gives me an idea
for
def truncateTable(tableName):
what are you passing in as tableName?
Your error shows
Copy code
dynamodb:DescribeTable on resource: arn:aws:dynamodb:us-east-1:table/UsersTable
f
I pass in
UsersTable
or
SkillsTable
t
It needs the full ARN I believe
f
I pass these to my lambda function through the environment:
Copy code
env["USERS_TABLE_NAME"] = usersTable.tableName
env["SKILLS_TABLE_NAME"] = skillsTable.tableName
t
Ah ok
I think the issue is that the actual table id is table/dev-sst-integration-SkillsTable
f
Ah I will double check - I think it was working for some other lambda functions that merely scan the tables. In that instance it works completely fine. The issue is when I use the Truncate function
t
and it's looking for table/SkillsTable
Actually this is what I'm doing as well so probably not the issue
Can you see if this function can insert a simple entry in?
f
Yes I have another lambda that does a
put
into the table as follows:
Copy code
table = dynamodb.Table(os.getenv("SKILLS_TABLE_NAME"))
table.put_item(Item=payload)
I pass in
SKILLS_TABLE_NAME
into the function environment. This works completely ok.
From my stack trace it seems the issue is this call in the
truncateTable
function:
key.get("AttributeName") _for_ key _in_
_table_.key_schema
t
Assuming that role is the right one for that function from what I can see it has the right permissions
can you try adding "dynamodb" to the permissions array for the function?
f
Yes sure - just redeploying now
Ok it's all working now. I think you were right when you made the distinction between
UsersTable
and
dev-sst-integration-UsersTable
The incorrect naming was indeed causing the error to say access denied.
Thanks a lot @thdxr - that was a lot of help
t
np glad we figured it out!