Defining two statements for the action on an IAM role - amazon-web-services

Is it possible, to have two statements for the same action in an IAM role?
For different actions, it works fine, but when creating a new statement for the same actions it's not working.
Example:
IamDeploymentRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: "iam-deployment"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
AWS:
- !Sub "arn:aws:iam::${ManagementAccountID}:root"
Action:
- "sts:AssumeRole"
Condition:
IpAddress:
X
- Effect: "Allow"
Principal:
Service:
- "some service"
Action:
- "sts:AssumeRole"
I'm trying to do it, but it's like the second item on the statement is being ignored. I don't know how exactly this filter works.
For instance, when a statement matches the action but not the condition, does it moves on? or in the first know no it stops?
I tried a lot of documentation, but couldn't find an answer.
Condition:
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html
Condition Operator:
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_ARN
Condition Key:
https://docs.aws.amazon.com/IAM/latest/UserGuide/list_awscloudformation.html#awscloudformation-aws_ResourceTag___TagKey_
Global condition key:
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-principalarn
Polices and Permissions: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html

It appears that you are defining AssumeRolePolicyDocument, which is the Trust Policy for an IAM Role.
I tested this by creating an IAM Role with a Trust Policy that trusted both Amazon EC2 and AWS Lambda:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
I then assigned Amazon S3 permissions to the role.
Testing:
EC2: I attempted to launch an Amazon EC2 instance with this role, but the role did not appear in the drop-down list.
Lambda: I was able to successfully attach the role to an AWS Lambda function and access Amazon S3.
I then swapped the order of the trust relationships:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
This had no impact — Lambda worked fine, but EC2 would not recognize the role.
I then removed Lambda from the Trust Relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
This caused the role to disappear from the Lambda console and, strangely, it also did not appear for use in the EC2 console.
I then created an identical role (with just EC2 as the trusted entity) and it worked fine.
Bottom line: The services do seem to get confused when there are multiple services in the Trust Policy. It is almost as if it "remembers" the first service and ignores the others, even when the trust policy is modified. Therefore, it seems that you can only specify one service in a Trust Policy.

It looks like you have an indentation issue. The second item in the array needs to be indented.

Related

CloudFormation API Gateway Lambda integration request not getting right permissions?

I have a CloudFormation stack template that creates an API Gateway resource where the method is of Type: LAMBDA_PROXY. It initially works fine for accessing the root domain, for example https://28af295f439b5f0aef7c7805864ba3981f282e1e.guacchain.com/ - but when I try accessing https://28af295f439b5f0aef7c7805864ba3981f282e1e.guacchain.com/about the network request gives back status code 500 and response {"message": "Internal server error"}
The generated Lambda function has this as its Resource-based Policy:
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "stack-28af295f439b5f0aef7c7805864ba3981f282e1e-lambdaApiGatewayInvoke-128TRSSUE8WDQ",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:378688096774:function:lambda-28af295f439b5f0aef7c7805864ba3981f282e1e",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:us-east-1:378688096774:bccwb0kvvd/*/*/*"
}
}
}
]
}
When going to the API Gateway Integration Request page and simply editing the Lambda Function field (cutting the existing value then pasting it back, then hitting the checkmark), I get this "Add permission" popup:
After clicking OK and then refreshing the Lambda console page, its Resource-base Policy updates to include two seemingly duplicate statements (only difference being the Sid field):
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "stack-28af295f439b5f0aef7c7805864ba3981f282e1e-lambdaApiGatewayInvoke-128TRSSUE8WDQ",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:378688096774:function:lambda-28af295f439b5f0aef7c7805864ba3981f282e1e",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:us-east-1:378688096774:bccwb0kvvd/*/*/*"
}
}
},
{
"Sid": "d6d795d4-8461-4774-bd6e-ae8d8ea3bcee",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:378688096774:function:lambda-28af295f439b5f0aef7c7805864ba3981f282e1e",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:us-east-1:378688096774:bccwb0kvvd/*/*/*"
}
}
}
]
}
After deploying the API Gateway and waiting about a minute, https://28af295f439b5f0aef7c7805864ba3981f282e1e.guacchain.com/about finally becomes accessible. So my question is, what's inadequate with the original Lambda Resource-based Policy that prevents all requests except for the / one to be accessed on the domain?
One subtle note I want to point out is that after cutting the Lambda function name and pasting it on the Integration Request page, it doesn't show as an autocomplete option, while others do.
This is the lambdaIAMRole I have defined in the CloudFormation stack:
lambdaIAMRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 'sts:AssumeRole'
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Policies:
- PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 'logs:CreateLogGroup'
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
Effect: Allow
Resource:
- !Sub >-
arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${lambdaFunctionName}:*
PolicyName: lambda
And the Lambda function resource has Role: !GetAtt lambdaIAMRole.Arn as part of its Properties field.
Based on the comments and inspection of the CloudFormation template, it was found that the issue was caused by the incorrect setup of IntegrationHttpMethod in apiGatewayLambdaResourceMethod.
Instead of
IntegrationHttpMethod: GET
it should be
IntegrationHttpMethod: POST
This is because AWS_PROXY for lambda requires POST method, not GET.

Message isn't sent to SQS when I specify Principal in access policy

I have an infrastructure where SNS topic sends messages to SQS (using SNS subscription of course). When I setup the following access policy it works.
{
"Version": "2012-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "SendMessagePolicy",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "SQS:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:312226948869:mr-sandbox-loyalty",
"Condition": {
"ArnEquals": {
"AWS:SourceArn": "arn:aws:sns:us-east-1:312226948869:mr-sandbox-transaction-created"
}
}
}
]
}
BUT when instead of * I setting up arn:aws:iam::312226948869:root messages aren't sent to queue. The account number which I used is 312226948869. Any ideas?
Thanks.
UPDATE
In web console, when I'm trying to set Principal: 312226949769 it's overrided as Principal: arn:aws:iam::312226949769:root
I managed to fix the issue. I added IAM ARN to ArnEquals condition.
{
"Version": "2012-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "SendersPolicy",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:%account_id%:mr-prod-loyalty-program",
"Condition": {
"ArnEquals": {
"AWS:SourceArn": [
"arn:aws:iam::%account_id%:role/boss-mr-prod-sqs-dashboard",
"arn:aws:iam::%account_id%:role/IDT-PSF-Instance-Profile"
]
}
}
}
]
}
My solution ended up not using my specific account as principal but instead service of SNS. This should be fine since I have the condition of specific sns topic arn
Resources:
Policy:
Type: AWS::SQS::QueuePolicy
Properties:
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- sns.amazonaws.com
Action:
- sqs:SendMessage
Resource: !GetAtt MySQS.Arn
Condition:
ArnEquals:
aws:SourceArn: !Ref MyTopic
Queues:
- !Ref MySQS

AWS Cloudwatch can not publish to SNS Topic with SSE

I have a Route53 health check, which submits its metrics into Cloudwatch, and finally Cloudwatch specifies thresholds and should send alerts through SNS.
However, I would like my SNS Topic to be encrypted. When I turn on SNS Topic encryption using the alias/aws/sns key I receive these messages in the Cloudwatch message history:
{
"actionState": "Failed",
"stateUpdateTimestamp": 123456778899,
"notificationResource": "arn:aws:sns:xx-region-y:zzzzzzzzzz:topic_name",
"publishedMessage": null,
"error": "null (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: ccccccccccccccccccc)"
}
This appears to not be an IAM issue with Cloudwatch, but with SNS itself being unauthorized to use the KMS resources.
I enjoy using the IAM Policy Simulator for IAM users to identify where their permissions are lacking, but there doesn't seem to be a way to validate a Service's access to other services. Is that a thing I can manage?
https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_testing-policies.html
I have also tried this with a CMK with the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Action": [
"kms:GenerateDataKey*",
"kms:Decrypt"
],
"Resource": "*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "route53.amazonaws.com"
},
"Action": [
"kms:GenerateDataKey*",
"kms:Decrypt"
],
"Resource": "*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": [
"kms:GenerateDataKey*",
"kms:Decrypt"
],
"Resource": "*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::XXXXXXXX:role/OrganizationAccountAccessRole"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
I'm pretty much throwing darts at a wall with the principals, but I think there's validation for sns.amazonaws.comfor SNS and events.amazonaws.com for Cloudwatch.
I received the exact same error, "null (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: ccccccccccccccccccc)", when using a CMK in this manner as well. I can understand my CMK not working properly, but the Amazon managed key I think should just work out of the box.
I've tried using a CMK which grants sns.amazonaws.com and events.amazonaws.com with kms:* permissions. Same error.
Just summarizing the correct answer here because the accepted answer seems to be outdated:.
You cannot use the Amazon managed CMK alias/aws/sns because in order to connect cloudwatch with an SNS topic encrypted with a KMS CMK, you need to set a resource-policy/access-policy on the CMK so that cloudwatch service can perform kms:GenerateDataKey* and kms:Decrypt actions on the key and the access-policy on amazon managed keys cannot be edited.
For your case, you would need to create a customer managed symmetric CMK, and edit the access-policy to allow cloudwatch service principal to access that CMK. The access-policy will look like:
"Version": "2012-10-17",
"Id": "key-policies",
"Statement": [
{
"Sid": "Enable IAM User Permissions for administration of this key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxxxxxx:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow cloudwatch metric to use this key",
"Effect": "Allow",
"Principal": {
"Service": "cloudwatch.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey*"
],
"Resource": "*"
}
]
}
Update: It's likely this information is out of date. Please try the other answers and let everyone know if they work for you.
Apparently, CloudWatch can't send messages to encrypted SNS topics according to Protecting Amazon SNS Data Using Server-Side Encryption (SSE) and AWS KMS:
Currently, CloudWatch alarms don't work with Amazon SNS encrypted topics. For information about publishing alarms to unencrypted topics, see Using Amazon CloudWatch Alarms in the Amazon CloudWatch User Guide.
However, the blog post Encrypting messages published to Amazon SNS with AWS KMS seems to indicate you can...
🤦
The service is not "events.amazonaws.com", it is "cloudwatch.amazonaws.com". You should get the SNS notifications once you change this in the key policy.
See https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html for more information.
While some AWS services use an IAM Role in your account, others use a specific principal to be granted access instead. See https://aws.amazon.com/blogs/compute/encrypting-messages-published-to-amazon-sns-with-aws-kms/.
I think in your case you need to allow the cloudwatch principal, events.amazonaws.com, to be allowed to use the KMS key you specified, in the key's policy. See the section "Enabling compatibility between encrypted topics and event sources" in the above link.
Note that as the document says, "Several AWS services publish events to Amazon SNS topics. To allow these event sources to work with encrypted topics, you must first create a customer-managed CMK and then add the following statement to the policy of the CMK." This only works with customer managed keys.
Adding just the below events.amazon.com permissions to the KMS key's resource policy did the trick for me, specifically to allow AWS::Events::Rule that had encrypted SNS topics registered as Targets for 'FAILED' CodeBuild and CodePipeline states.
{
"Sid": "Allow Events use of key (for publishing to CMK encrypted SNS topics)",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey*"
],
"Resource": "*"
}
Hope this saves someone else some of the frustration and time this had caused me.
I ran into the same issue today! I see there are suggestions for granting the CMK to cloudwatch.amazonaws.com and also to events.amazonaws.com. For me, I needed to grant to both for that to work. Here is the entirety of my Cloudformation definition for the CMK.
InternalSNSKey:
Type: AWS::KMS::Key
Properties:
Description: IA-Internal-SNS Encryption Key
KeyPolicy:
Version: 2012-10-17
Id: allow-root-access-to-key
Statement:
- Sid: allow-root-to-delegate-actions
Effect: Allow
Principal:
AWS: !Sub arn:aws:iam::${AWS::AccountId}:root
Action:
- kms:*
Resource: '*'
- Sid: allow-cloudwatch-to-use-key
Effect: Allow
Principal:
Service: cloudwatch.amazonaws.com
Action:
- kms:Decrypt
- kms:GenerateDataKey*
Resource: '*'
- Sid: allow-events-to-use-key
Effect: Allow
Principal:
Service: events.amazonaws.com
Action:
- kms:Decrypt
- kms:GenerateDataKey*
Resource: '*'

API Gateway does not have permission to assume the provided role

I am trying to invoke a lambda function from an API Gateway. I have followed the next tutorial: https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-lambda.html
However, I get the following error when I test it from the web of API Gateway:
Execution failed due to configuration error: API Gateway does not have permission to assume the provided role
I have search in google and I have not been able to solve it (this, for instance).
If I go to the IAM Management Console, I can see that the trust relationship allows API Gateway to assume the rol, and the JSON of the trust relationship is the following:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"apigateway.amazonaws.com",
"lambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
I have tried also with:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com",
"apigateway.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
The policy of the role is the next:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"*"
]
}
]
}
What is wrong here? Thank you
To fix this go to the role in your IAM and select the “Trust Relationships” tab. From here edit the policy and for the Principal Service add in “apigateway.amazonaws.com” as seen below. This will grant the API Gateway the ability to assume roles to run your function in addition to the existing lambda permission.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"apigateway.amazonaws.com",
"lambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
I guess you have not attached the role to the invoking method i.e the api gateway
Attaching the created role to the api gateway is needed for api to execute the lamda.
Under Execution role, choose Choose an existing role.
Enter the role ARN for the lambda_invoke_function_assume_apigw_role
role you created earlier.
Choose Save.
AWS Link

AWS Trust Policy Has prohibited field Principal

I'm trying to create an IAM role and assign it to an EC2 instance according to Attach an AWS IAM Role to an Existing Amazon EC2 Instance by Using the AWS CLI.
The policy looks like below:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
But it gives this error:
This policy contains the following error: Has prohibited field Principal
There is a similar question here but it couldn't fix this issue.
Any help would be appreciated.
Faced the same issue when trying to update the "Trust Relationship" Or same known as "Trust Policy".
"Principal" comes to play only in "Trust Policy". May be by mistake you are updating normal policy falling under the permissions tab. Try updating the policy under "Trust Relationships" tab as below:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com",
"lambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
The easiest way to create a Service Role is:
Go to the IAM Console
Click Roles
Create new Role
Select an Amazon EC2 service role
Then attach your policies
It will create the trust policy for you.
Please note that the Trust Policy is stored in a separate location to the actual Policy (the bit that assigns permissions). Based upon the error message, it seems like you're putting the trust policy in the normal spot, because Roles don't need a principle (but trust policies do).
write a policy inside bucket --> permissions --> bucket policy --> save
Note: don't write policy in iam console and bucket and cloud-watch regions must be same. other region wont work.
use below policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "logs.YOUR-CLOUD-WATCH-REGION.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME"
},
{
"Effect": "Allow",
"Principal": {
"Service": "logs.YOUR-CLOUD-WATCH-REGION.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}