I am creating a role using the CDK and I need to add sts:SetSourceIdentity to the AssumeRolePolicyDocument.
My code looks like this currently:
new Role(this, 'MyRole', {
assumedBy: new AccountPrincipal(Stack.of(this).account),
...
});
This results in an AssumeRolePolicyDocument that looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::0123456789012:root"
},
"Action": "sts:AssumeRole"
}
]
}
I need it to look like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::0123456789012:root"
},
"Action": ["sts:AssumeRole", "sts:SetSourceIdentity"]
}
]
}
The generate CloudFormation from the CDK code above ends up like this:
"MyRoleCF2E104D": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::0123456789012:root"
]
]
}
}
}
],
"Version": "2012-10-17"
},
...
},
I can't figure out how to get the sts:SetSourceIdentity added to the Action in the CloudFormation. Any ideas? Do I need to eject to the L1 construct?
addStatements adds new actions to the role's assume role policy document:
role.assumeRolePolicy?.addStatements(
new iam.PolicyStatement({
actions: ['sts:SetSourceIdentity'],
principals: [new iam.AccountPrincipal(this.account)],
})
);
Related
I want to add source_account in lambda resource-based policy condition. So I am executing below terraform code.
data "aws_caller_identity" "current" {
# Retrieves information about the AWS account corresponding to the
# access key being used to run Terraform, which we need to populate
# the "source_account" on the permission resource.
}
resource "aws_lambda_permission" "example" {
statement_id = "AllowExecutionFromS3Bucket"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.example.arn}"
principal = "s3.amazonaws.com"
source_account = "${data.aws_caller_identity.current.account_id}"
source_arn = "${aws_s3_bucket.example.arn}"
}
after applying terraform changes and doing plan I am unable to get (this is desired but not getting for S3)
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "lambda-8433be2d-00f7-48dc-9296-7c432662f91e",
"Effect": "Allow",
"Principal": {
"Service": "logs.us-east-1.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:xxxxxxxxxxxx:function:yyyyyyyyyyyy",
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "xxxxxxxxxxxx"
},
"ArnLike": {
"AWS:SourceArn": "arn:aws:logs:us-east-1:xxxxxxxxxxxx:log-group:/aws/lambda/lambda_handler:*"
}
}
}
]
}
I have tried many ways I am not getting any clue.
afer doing terraform plan i am getting below output :
module.environment.aws_lambda_permission.xxxxxxxxxxxx: Creating...
action: "" => "lambda:InvokeFunction"
function_name: "" => "arn:aws:lambda:us-east-1:yyyyyyyyyyyyyy:function:xxxxxxxxxxxx"
principal: "" => "s3.amazonaws.com"
source_arn: "" => "arn:aws:s3:::xxxxxxxxxxxx"
statement_id: "" => "AllowExecutionFromS3Bucket"
I am getting like this :
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "AllowExecutionFromS3Bucket",
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:yyyyyyyyyy:function:xxxxxxxxxx",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:s3:::xxxxxxxxxx"
}
}
}
]
}
I am able to add conditions using AWS CLI .
I am not using the root account. Someone please help me.
You just need to add source_account
resource "aws_lambda_permission" "allow_bucket" {
statement_id = "AllowExecutionFromS3Bucket"
action = "lambda:InvokeFunction"
function_name = "arn:aws:lambda:us-east-1:123456789123:function:mylambda"
principal = "s3.amazonaws.com"
source_account = "123456789123"
source_arn = "arn:aws:s3:::my-bucket"
}
will create
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "AllowExecutionFromS3Bucket",
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:123456789123:function:mylambda",
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "123456789123"
},
"ArnLike": {
"AWS:SourceArn": "arn:aws:s3:::my-bucket"
}
}
}
]
}
I'm having issues with calling a lambda in account B from a different lambda in account A.
Account A's role arn is arn:aws:iam::ACCOUNT_A:role/DeviceApiStack-simServiceRole427DA44E-1WS2T3INIV6IP
Account A's role name is DeviceApiStack-simServiceRole427DA44E-1WS2T3INIV6IP
Account B's role name is Chris-APIStack1-Q6AJ1PZ8V-LambdaCrossAccountExecut-1N3JU88L5AON1
Account B's role arn is arn:aws:lambda:us-east-1:462087996972:function:GetActiveDeviceIdsLambdaChris
For account A my lambda role has the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::ACCOUNT_B:role/Chris-APIStack1-Q6AJ1PZ8V-LambdaCrossAccountExecut-1N3JU88L5AON1",
"Effect": "Allow"
},
{
"Action": "lambda:InvokeFunction",
"Resource": "*",
"Effect": "Allow"
},
{
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:iam::ACCOUNT_B:role/Chris-APIStack1-Q6AJ1PZ8V-LambdaCrossAccountExecut-1N3JU88L5AON1",
"Effect": "Allow"
}
]
}
My lambda in account B has the following role as defined using cloudformation:
"CrossAccountExecutionRoleDemo": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:sts::ACCOUNT_A:role/DeviceApiStack-simServiceRole427DA44E-1WS2T3INIV6IP"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": { "Service": ["lambda.amazonaws.com"] },
"Action": ["sts:AssumeRole"]
}
]
}
}
},
"CrossAccountExecutionPolicyDemo": {
"Type": "AWS::IAM::ManagedPolicy",
"Properties": {
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": { "Fn::GetAtt": ["GetActiveDeviceIdsLambdaDemo", "Arn"] }
}
]
},
"Roles": [
{
"Ref": "CrossAccountExecutionRoleDemo"
}
]
}
}
When I make the following request I get an error
let roleArn = 'arn:aws:iam::ACCOUNT_B:role/Chris-APIStack1-Q6AJ1PZ8V-CrossAccountExecutionRol-1ANKXFZ6YS23'
sts.assumeRole(
{
RoleArn: roleArn,
RoleSessionName: 'NightlySimService',
}, function(err, res){ ... }
Error:
'
AccessDenied: User: arn:aws:sts::ACCOUNT_A:assumed-role/DeviceApiStack-simServiceRole427DA44E-1WS2T3INIV6IP/DeviceApiStack-nightlySimServiceLambdaA51B2AFE-JSUFU8F5BZGC is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::ACCOUNT_B:role/Chris-APIStack1-Q6AJ1PZ8V-CrossAccountExecutionRol-1ANKXFZ6YS23F
'
I can spot two apparent issues in the roles, which could be the cause of your errors.
First. Incorrect principle:
"Principal": {
"AWS": "arn:aws:sts::ACCOUNT_A:role/DeviceApiStack-simServiceRole427DA44E-1WS2T3INIV6IP"
},
As you wrote the role arn is arn:aws:iam::ACCOUNT_A:role/DeviceApiStack-simServiceRole427DA44E-1WS2T3INIV6IP, which does not match of what you provided in the Principal.
Second. Incorrect resource:
{
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:iam::ACCOUNT_B:role/Chris-APIStack1-Q6AJ1PZ8V-LambdaCrossAccountExecut-1N3JU88L5AON1",
"Effect": "Allow"
}
The action lambda:InvokeFunction applies to lambda functions, not IAM roles. Thus, the Resource should be ARN of the lambda.
There could be more issues, which are not that obvious at present.
I need to give permission for all logged users on my application.
This is my code:
this.amplifyService.auth().currentUserCredentials().then(credentials => {
const lambda = new Lambda({
credentials: this.amplifyService.auth().essentialCredentials(credentials)
});
lambda.invoke({
FunctionName: 'my-function',
}, res => {
console.log(res);
});
});
And this is the return:
authRole/CognitoIdentityCredentials is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-2:function:my-function
I already try to create a IAM role manually:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:us-east-2:XXXXXXXXX:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:us-east-2:XXXXX:log-group:/aws/lambda/my-function:*"
]
},
{
"Effect": "Allow",
"Action": [
"lambda:*"
],
"Resource": [
"arn:aws:lambda:us-east-2:XXXXXXXXX:function:my-function"
]
}
]
}
But doesn't work yet.
I am trying to create an CFT which has
1. 3 different roles with Managed policy
2. INline policy which should be added to three roles which are created in CFT.
But i could not do as this is throwing me error saying atleast one resource must be defined.
Please help me in achieving this.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"EMRDefaultRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "EMR_DefaultRole",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "elasticmapreduce.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceRole"
]
}
},
"EMREC2DefaultRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "EMR_EC2_DefaultRole",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforEC2Role"
]
}
},
"EMRAutoScalingDefaultRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "EMR_AutoScaling_DefaultRole",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": [ "elasticmapreduce.amazonaws.com",
"application-autoscaling.amazonaws.com"]
},
"Action": "sts:AssumeRole"
}]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforAutoScalingRole"
]
}
},
"EMRS3Policies": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyName": "Moodys-IAM-EMR-S3-Access-Policy",
"PolicyDocument": {
"Statement": [{
"Effect": "Allow",
"Action": [
"s3:HeadBucket",
"s3:GetObject"
],
"Resource": {
"Fn::Join": ["", ["arn:aws:s3:::mit-", {
"Ref": "AWS::AccountId"
}, "-emr-files/*"]]
}
}
]
},
"Roles": [{
"Ref": "EMRDefaultRole"},
{"Ref": "EMREC2DefaultRole"},
{"Ref": "EMRAutoScalingDefaultRole"
}]
}
}
}
}
Like i am expecting three Role where an managed policy and inline policy are attached.
You are missing resource attribute in your role statements.
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": [ "elasticmapreduce.amazonaws.com",
"application-autoscaling.amazonaws.com"]
},
"Action": "sts:AssumeRole"
}]
This should be (it holds for all of the statements)
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": [ "elasticmapreduce.amazonaws.com",
"application-autoscaling.amazonaws.com"]
},
"Action": "sts:AssumeRole",
"Resource": [
"arn-of-your-resource-or-wildcard"
]
}]
I'm creating an ec2 instance with a role that provides access to kinesis streams and Dynamodb offset Tables. I am using aws cloudformation for that.
Problem I'm having is while creating the Streaming Access IAM Role itself.
So, I will have following structure,
has
StreamingAccessRole ----------> RolePolicy1(kinesis:*), RolePolicy2(dynamodb:*)
The template to create the AWS IAM role with two policies, one for kinesis and the other for dynamodb :
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"teamIdentifier": {
"Type": "String",
"Default": "a28",
"Description": "Identifier for the team"
}
},
"Resources": {
"StreamingAccessRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/a28/",
"Policies": [
{
"PolicyName": "Stream-ConsumerOffset-RW-AccessPolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "kinesis:*",
"Resource": "arn:aws:kinesis:us-west-2:*:stream/a28-*"
},
{
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": "arn:aws:dynamodb:us-west-2:*:table/a28-*"
}
]
}
}
]
}
}
}
}
It creates the Access Role but without role-policies.
$ aws iam get-role --role-name a28-streaming-access-role-st-StreamingAccessRole-14QHMTIOIRN5X --region us-west-2 --profile aws-federated
{
"Role": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
}
}
]
},
"RoleId": "AROAIFD6X2CJXTKLVQNLE",
"CreateDate": "2017-04-07T18:54:59Z",
"RoleName": "a28-streaming-access-role-st-StreamingAccessRole-14QHMTIOIRN5X",
"Path": "/a28/",
"Arn": "arn:aws:iam::500238854089:role/a28/a28-streaming-access-role-st-StreamingAccessRole-14QHMTIOIRN5X"
}
}
Listing the role-policies
$ aws iam list-role-policies --role-name a28-streaming-access-role-st-StreamingAccessRole-14QHMTIOIRN5X --region us-west-2 --profile aws-federated
{
"PolicyNames": []
}
which means it did not even create any policies,
aws iam list-policies --region us-west-2 --profile aws-federated | grep Stream-ConsumerOffset-RW-AccessPolicy
But if I supplied only kinesis:* statement in above example, it creates a policy, but not with dynamodb:* alone.
So, my question is how am supposed to provide multiple RolePolicies using one cloudformation AWS::IAM::Role template, or is this specific to dynamodb?
There's an intermittent race condition when you create the Policy in the Role. Create the Policy separately with AWS::IAM::Policy and set the Roles property to the Role. The problem will go away.
Your template worked perfectly fine for me.
I ran your template and then:
$ aws iam get-role --role-name stack1-StreamingAccessRole-1KDUTVG1OLLQM
{
"Role": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
}
}
]
},
"RoleId": "AROAJADV75HTIM6C62YXQ",
"CreateDate": "2017-04-08T22:22:21Z",
"RoleName": "stack1-StreamingAccessRole-1KDUTVG1OLLQM",
"Path": "/a28/",
"Arn": "arn:aws:iam::123456789012:role/a28/stack1-StreamingAccessRole-1KDUTVG1OLLQM"
}
}
Listing the role-policies:
$ aws iam list-role-policies --role-name stack1-StreamingAccessRole-1KDUTVG1OLLQM
{
"PolicyNames": [
"Stream-ConsumerOffset-RW-AccessPolicy"
]
}
The policy is attached as an inline policy, so it will not appear in list-policies. Rather, use get-role-policy to view it:
$ aws iam get-role-policy --role-name stack1-StreamingAccessRole-1KDUTVG1OLLQM --policy-name Stream-ConsumerOffset-RW-AccessPolicy
{
"RoleName": "stack1-StreamingAccessRole-1KDUTVG1OLLQM",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "kinesis:*",
"Resource": "arn:aws:kinesis:us-west-2:*:stream/a28-*",
"Effect": "Allow"
},
{
"Action": "dynamodb:*",
"Resource": "arn:aws:dynamodb:us-west-2:*:table/a28-*",
"Effect": "Allow"
}
]
},
"PolicyName": "Stream-ConsumerOffset-RW-AccessPolicy"
}
The reason could be race condition as already answered in this answer by Tim Bassett, I simply wanted to add final solution that worked, and how to add AWS::IAM::Policy to cloudformation.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Some Streaming api devops",
"Parameters": {
"environment": {
"Type": "String",
"Default": "staging",
"Description": "environment"
}
},
"Resources": {
"StreamingAccessRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "StreamingAccessRole",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/a28/"
}
},
"StreamConsumerOffsetRWAccessPolicy": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudwatch:*"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": "kinesis:*",
"Resource": "arn:aws:kinesis:us-west-2:051620159240:stream/a28-*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:BatchGetItem",
"dynamodb:BatchWriteItem",
"dynamodb:CreateTable",
"dynamodb:DeleteItem",
"dynamodb:DeleteTable",
"dynamodb:DescribeLimits",
"dynamodb:DescribeReservedCapacity",
"dynamodb:DescribeReservedCapacityOfferings",
"dynamodb:DescribeStream",
"dynamodb:DescribeTable",
"dynamodb:GetItem",
"dynamodb:GetRecords",
"dynamodb:GetShardIterator",
"dynamodb:ListStreams",
"dynamodb:ListTables",
"dynamodb:PutItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:UpdateItem",
"dynamodb:UpdateTable"
],
"Resource": "arn:aws:dynamodb:us-west-2:051620159240:table/a28-*"
},
{
"Action": [
"sns:*Permission",
"sns:Create*",
"sns:Delete*",
"sns:Publish",
"sns:ReceiveMessage",
"sns:Set*"
],
"Resource": [
"arn:aws:sns:us-west-2:051620159240:a28-*"
],
"Effect": "Allow"
}
]
},
"PolicyName": "StreamConsumerOffsetRWAccessPolicy",
"Roles": [
{
"Ref": "StreamingAccessRole"
}
]
}
}
}
}