Related
I am attaching the following resource policy to an SM secret
{
"Version" : "2012-10-17",
"Id" : "AllowAccessToSecretValue",
"Statement" : [ {
"Sid" : "AllowLambdaAccess",
"Effect" : "Allow",
"Principal" : {
"Service" : "lambda.amazonaws.com"
},
"Action" : [ "secretsmanager:GetSecretValue", "secretsmanager:UpdateSecret" ],
"Resource" : "arn:aws:secretsmanager:us-east-1:123456789:secret:my-secret-xkxkxk",
"Condition" : {
"ArnLike" : {
"aws:SourceArn" : "arn:aws:lambda:us-east-1:123456789:function:foo*"
}
}
} ]
}
Then I am trying to access it from a lambda that has the following code:
secret_name = "my-secret"
def lambda_handler(event, context):
# Calling SecretsManager
get_secret_value_response = client.get_secret_value(
SecretId=secret_name
)
#Raw Response
#Extracting the key/value from the secret
secret = get_secret_value_response['SecretString']
print(secret)
put_secret_value_response = client.update_secret(
SecretId=secret_name,
SecretString='fofo'
)
secret = get_secret_value_response['SecretString']
print(secret)
The arn of the function is
arn:aws:lambda:us-east-1:123456789:function:foo-lala
The execution fails:
"errorMessage": "An error occurred (AccessDeniedException) when calling the GetSecretValue operation: User: arn:aws:sts::123456789:assumed-role/my-secret/foo-lala is not authorized to perform: secretsmanager:GetSecretValue on resource: my-secret because no identity-based policy allows the secretsmanager:GetSecretValue action",
Why is that?
update
Removing the Condition clause entirely does not seem to work either
{
"Version" : "2012-10-17",
"Id" : "AllowAccessToSecretValue",
"Statement" : [ {
"Sid" : "AllowLambdaAccess",
"Effect" : "Allow",
"Principal" : {
"Service" : "lambda.amazonaws.com"
},
"Action" : [ "secretsmanager:GetSecretValue", "secretsmanager:UpdateSecret" ],
"Resource" : "*"
} ]
}
Resource is "arn:aws:secretsmanager:us-east-1:123456789:secret:my-secret-xkxkxk" but you are trying to access my-secret!
Update:
{
"Version" : "2012-10-17",
"Id" : "AllowAccessToSecretValue",
"Statement" : [ {
"Sid" : "AllowLambdaAccess",
"Effect" : "Allow",
"Principal" : {
"AWS" : "arn:aws:iam::359524702761:role/service-role/foo-lala-role-16s42m8h"
},
"Action" : [ "secretsmanager:GetSecretValue", "secretsmanager:UpdateSecret" ],
"Resource" : "arn:aws:secretsmanager:us-east-1:359524702761:secret:my-secret-dNl6kV"
} ]
}
Your resource policy fails to grant the expected privileges because the Lambda service is not the caller. Rather, the Lambda service assumes the Lambda's execution role and the *role* makes the call to Secrets Manager.
Set the Lambda role as the Principal and remove the condition:
{
"Version": "2012-10-17",
"Id": "AllowAccessToSecretValue",
"Statement": [
{
"Sid": "AllowLambdaAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam:us-east-1:123456789:role/MyLambdaRole"
},
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:UpdateSecret"
],
"Resource": "arn:aws:secretsmanager:us-east-1:123456789:secret:my-secret-xkxkxk"
}
]
}
You can match multiple roles with a pattern. Use the "Any" Principal with an ArnLike Condition with a wildcard pattern on aws:PrincipalArn. This will match whatever role names match the pattern.
{
"Version": "2012-10-17",
"Id": "AllowAccessToSecretValue",
"Statement": [
{
"Sid": "AllowLambdaAccess",
"Effect": "Allow",
"Principal": { "AWS": "*" },
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:UpdateSecret"
],
"Resource": "arn:aws:secretsmanager:us-east-1:123456789:secret:my-secret-xkxkxk",
"Condition": {
"ArnLike": {
"aws:PrincipalArn": "arn:aws:iam:us-east-1:123456789:role/*RolePattern*"
}
}
}
]
}
I am trying to create the cross account log data sharing as per the mentioned link using cloudformation
When I delete the destination Part, everything is being created as normal.
https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CreateFirehoseStream.html
"Resources": {
"KdsDataStream01BCE77D": {
"Type": "AWS::Kinesis::Stream",
"Properties": {
"Name": "RecipientStream",
"ShardCount": 1,
"RetentionPeriodHours": 24
}
},
"CWLtoKinesisRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {
"Service": "logs.amazonaws.com"
},
"Condition": {
"StringLike": {
"aws:SourceArn": [
{
"Ref" : "SourceAccountId",
"Ref" : "RecipientAccountId"
}
]
}
},
"Action": "sts:AssumeRole"
}
},
"Policies": [
{
"PolicyName": "Permissions-Policy-For-CWL",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "kinesis:PutRecords",
"Resource": [
{
"Fn::GetAtt": [
"KdsDataStream01BCE77D",
"Arn"
]
}
]
}
]
}
}
]
}
},
"ServiceRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"firehose.amazonaws.com",
"logs.amazonaws.com",
"lambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
},
"Policies": [
{
"PolicyName": "kinesis-access",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kinesis:PutRecords",
"kinesis:GetRecords",
"kinesis:SubscribeToShard",
"kinesis:ListShards",
"kinesis:ListStreams",
"kinesis:DescribeStreamSummary",
"kinesis:DescribeLimits",
"kinesis:DescribeStream",
"kinesis:ListStreamConsumers",
"kinesis:DescribeStreamConsumer",
"kinesis:GetShardIterator",
"kinesis:ListTagsForStream",
"Lambda:InvokeFunction"
],
"Resource": "*"
}
]
}
},
{
"PolicyName": "firehose-access",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"firehose:DescribeDeliveryStream",
"firehose:ListDeliveryStreams",
"firehose:ListTagsForDeliveryStream"
],
"Resource": "*"
}
]
}
},
{
"PolicyName": "s3-access",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*Object",
"s3:ListBucket",
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Resource": "*"
}
]
}
},
{
"PolicyName": "cloudwatch-access",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"cloudwatch:*",
"logs:Describe*",
"logs:Delete*",
"logs:Get*",
"logs:Put*"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "arn:aws:iam::*:role/aws-service-role/events.amazonaws.com/AWSServiceRoleForCloudWatchEvents*",
"Condition": {
"StringLike": {
"iam:AWSServiceName": "events.amazonaws.com"
}
}
}
]
}
},
{
"PolicyDocument": {
"Statement": [
{
"Action": [
"kinesis:DescribeStream",
"kinesis:DescribeStreamSummary",
"kinesis:GetShardIterator",
"kinesis:GetRecords",
"kinesis:ListShards",
"kinesis:SubscribeToShard"
],
"Effect": "Allow",
"Resource": [
{
"Fn::GetAtt": [
"KdsDataStream01BCE77D",
"Arn"
]
}
]
}
],
"Version": "2012-10-17"
},
"PolicyName": "ReadSource"
}
],
"RoleName": "ServiceRole"
}
},
"DestinationWithName" : {
"Type" : "AWS::Logs::Destination",
"Properties" : {
"DestinationName": "TestDestination",
"RoleArn": {
"Fn::GetAtt": [
"CWLtoKinesisRole",
"Arn"
]
},
"TargetArn": {
"Fn::GetAtt": [
"KdsDataStream01BCE77D",
"Arn"
]
},
"DestinationPolicy": "{\"Version\" : \"2012-10-17\",\"Statement\" : [{\"Effect\" : \"Allow\", \"Principal\" : {\"AWS\" : \"*\"},\"Action\" : \"logs:PutSubscriptionFilter\", \"Resource\" : \"arn:aws:logs:us-east-1:763475694844:destination:TestDestination\"}]}"
}
},
SourceAccountID and RecipientAccountID are passed during runtime.
Problem that I am facing is , it shows the error as
When creating a Cross Account Log Destination deploy fails with "Could not deliver test message to specified destination". (Invalid Parameter Exception)
How can I resolve this issue
Hello I recently made a CFT for my lambda and sqs (both on the same account/region) but I noticed that when I go to the aws console, it shows the SQS resource both on the "input side" and the "output side" of my lambda. Is this intentional? or did I just do my CFTs incorrectly. Below is the relevant JSON code.
"MyLambdaFunctionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "root",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes"
],
"Resource": {
"Fn::Sub": "arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:test-${Environment}-my-queue"
}
}
]
}
}
]
}
},
"OutputRouterEventSource": {
"Type": "AWS::Lambda::EventSourceMapping",
"Properties": {
"BatchSize": 10,
"Enabled" : true,
"EventSourceArn": {
"Fn::Sub": "arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:test-${Environment}-my-queue"
},
"FunctionName": {
"Fn::GetAtt": [
"MyLambdaFunction",
"Arn"
]
}
}
},
"OutputRouterLambdaInvokePermission": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"Action": "lambda:InvokeFunction",
"Principal": "sns.amazonaws.com",
"SourceArn": {
"Fn::Sub": "arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:test-${Environment}-my-queue"
},
"FunctionName": {
"Fn::Sub": "test-${Environment}-my-lambda"
}
}
}
It is normal to have SQS on both side in this case: SQS triggers your Lambda function (left side) and your Lambda function's role must have the permission to receive and delete messages from the queue (right side).
(I think your are mixing services in your OutputRouterLambdaInvokePermission resource where the principal is SNS and the source references the arn of a SQS queue, you can drop this resource as it is not needed for SQS triggers)
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"
}
]
}
}
}
}
Following cloudformation template gives error on line 9 :
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Policy to allow send receive message from SQS Queue",
"Resources" : {
"MyPolicy" : {
"Type" : "AWS::IAM::Policy",
"Properties" : {
"PolicyName" : "CFUsers",
"Roles": [ { "arn:aws:iam::710161973367:role/Cognito_CFIAuth_Role" } ],
"PolicyDocument" : {
"Version" : "2012-10-17",
"Statement": [
{
"Sid": "Sid1482400105445",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::710161973367:role/Cognito_CFIAuth_Role"
},
"Action": [
"SQS:SendMessage",
"SQS:ReceiveMessage",
"SQS:DeleteMessage",
"SQS:GetQueueUrl"
],
"Resource": "arn:aws:sqs:ap-south-1:710161973367:CFI-Trace"
}
]
}
}
}
}
I want role Cognito_CFIAuth_Role to have message send/read/delete previleges on SQS queue CFI-Trace. How do I attach SQS operation privileges to IAM Role ?
First, Line 9 contains a JSON syntax error, the brackets {} around your Role string should be removed:
"Roles": [ "arn:aws:iam::710161973367:role/Cognito_CFIAuth_Role" ],
Second, AWS::IAM::Policy's Roles property accepts "The names of AWS::IAM::Roles to attach to this policy", not full ARNs, so your line should be:
"Roles": [ "Cognito_CFIAuth_Role" ],
You also need a missing closing bracket } at the end of your example.
With the AWS::IAM::Policy resource, you're creating an inline policy. http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html explains that this takes a list of "The names of AWS::IAM::Roles, which I take to be the logical name of role resources defined within the same stack.
If you want to attach the policy to a preexisting role, you should use the ManagedPolicy type instead. http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html#cfn-iam-managedpolicy-roles takes the name of the preexisting role(s).
Cloudformation type IAM::Policy is for Users and Groups. Roles and instance profiles are for ec2. You have conflated both ideas. If you have the role predefined in a different CFN then you use just an Instance Profile for your EC2 instance, if not you can create it too and then ref it
"RootInstanceProfile": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"Path": "/",
"Roles": [ {
"arn:aws:iam::710161973367:role/Cognito_CFIAuth_Role"
} ]
}
}
or
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"SQSRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "root",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"SQS:SendMessage",
"SQS:ReceiveMessage",
"SQS:DeleteMessage",
"SQS:GetQueueUrl"
],
"Resource": "arn:aws:sqs:ap-south-1:710161973367:CFI-Trace"
}
]
}
}
]
}
},
"RootInstanceProfile": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"Path": "/",
"Roles": [
{
"Ref": "SQSRole"
}
]
}
}
}
}
IAM Policy
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-policy.html
IAM role
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html
Now there is also SQS Policy
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-policy.html
You can also attach ManagedPolicyArns to CloudFormation resource type AWS::IAM::Role https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-managepolicyarns