Reputation: 5818
I note that the role
property of a CDK Lambda Function is of type iam.IRole | undefined
. This is surprising to me - how is it possible for a Lambda Function to exist without a Role to act as?
In practice, this is frustrating because it means that, instead of:
const dynamoTable = new Table(...);
const func = new Function(...);
dynamoTable.grantReadWriteData(func.role);
, I have to instead do
[...]
if (typeof func.role !== 'undefined') {
dynamoTable.grantReadWriteData(func.role);
}
(Though I am at least impressed that TypeScript can determine that the property is defined within that if
block if, instead, I extract const funcRole = func.role
)
Is there a more idiomatic way to do this?
EDIT: Balu's answer, which points out that the Function
itself is IGrantable
, addresses how to update the RolePolicy for the auto-created Role - but (I believe?) we still need a concrete Role in order to update Resource Policies (e.g. on Queues) by calling resource.addToRolePolicy(new PolicyStatement({...}))
with appropriate principals
. Some resources like Dynamo Tables have "helper" methods that can accept the Function itself - but for those that don't, the Role (or, more accurately, a Principal
) is required.
Upvotes: 4
Views: 2903
Reputation: 10333
CDK code, if we don't pass a role, it creates a role with default permissions AWSLambdaBasicExecutionRole
and AWSLambdaVPCAccessExecutionRole
From documentation:
Lambda functions assume an IAM role during execution. In CDK by default, Lambda functions will use an autogenerated Role if one is not provided.
The autogenerated Role is automatically given permissions to execute the Lambda function.
We can always add additional permissions by calling addToRolePolicy
on the function. OR by calling grant permissions on other resources like dynamoDb or loggroup, etc.
Lets say our lambda is created like this
const myFun = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_10_X,
handler: 'index.handler',
code: ...})
We can add permissions like this:
myFun.role.addToRolePolicy(
new iam.PolicyStatement({
resources: ['*'],
actions: [...],
})
);
OR Lets say we want to grant access to write to log group, we can do this, which appends additional inline policy to lambda role.
const logGroup = new awsLogs.LogGroup(this, `my-fun`, {
retention: 30,
logGroupName: `/aws/lambda/${functionName}`,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
logGroup.grantWrite(this.myFun);
Similarly in case of DynamoDB,for dynamoTable.grantReadWriteData method, we need to pass function itself, not the role. so,
Instead of
dynamoTable.grantReadWriteData(myFun.role);
We should do
dynamoTable.grantReadWriteData(myFun);
Upvotes: 3