AWS.Lambda.createFunction returns error message: "Failed to create Lambda function: InvalidParameterValueException: The role defined for the function cannot be assumed by Lambda."
I am trying to create a lambda function to a third party AWS account via IAM Role delegation. https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html?icmpid=docs_iam_console
In the third party account, the IAM Role was created with an external ID. https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html
Role ARN: 'arn:aws:iam::11111111111:role/Third-party'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::000000000000:user/admin"
],
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "abcde"
}
}
}
]
}
Following parameter is used to assume the role. It returns the credentials.
const assumeRoleRequestParam: AWS.STS.AssumeRoleRequest = {
RoleArn: 'arn:aws:iam::11111111111:role/Third-party',
ExternalId: 'abcde',
RoleSessionName: 'DeployLambaFunction'
}
Lambda function is created as follows.
const lambda = new AWS.Lambda({
accessKeyId: accessKeyID,
secretAccessKey: secretAccessKey,
sessionToken: sessionToken
});
const functionParams: AWS.Lambda.CreateFunctionRequest = {
FunctionName: 'deploy-test',
Runtime: 'nodejs14.x',
Handler: 'index.handler',
Role: 'arn:aws:iam::11111111111:role/Third-party',
Code: {
ZipFile: fs.readFileSync("helloworld.js.zip")
},
};
lambda.createFunction(functionParams, (err, data) => {
if (err) {
console.error('Failed to create Lambda function:', err);
} else {
console.log('Lambda function created successfully:', data);
}
});
It returns the error message given above. But it works if I don't use the external ID in the Role.
I expect creating lambda function should work fine when I use external ID in the IAM role, as it works when I do not use external ID. I checked the AWS documentations and the internet for similar issues, but I find none. Am I missing something?
As commented by @luk2302, the issue is because lambda service itself cannot assume the role with the external ID.
Solution is to split the role policy into two statements, one for the manual assume-role with the external ID condition and one for the assume-role from the lambda service without such a condition.
Example:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::000000000000:user/admin"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "abcde"
}
}
},
{
"Sid": "Statement1",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}