CloudFormation, S3 bucket access to cross-acccount IAM role - amazon-web-services

I have 2 accounts, s3_buck_acct and iam_acct. I want to provision IAM role from iam_acct to certain actions on the S3 bucket from s3_buck_acct.
Here is the CloudFormation template I came up with that ends up with error:
Resources:
S3BucketTest:
Type: AWS::S3::Bucket
Properties:
BucketName: "cross-acct-permission-demo"
LifecycleConfiguration:
Rules:
- Id: LifecycleExpRule
ExpirationInDays: '3650'
Status: Enabled
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
S3CURBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket:
!Ref S3BucketTest
PolicyDocument:
Statement:
- Action:
- 's3:ListBucket'
- 's3:ListBucketMultipartUploads'
- 's3:PutObject'
- 's3:GetObject'
Effect: "Allow"
Resource:
- "arn:aws:s3:::cross-acct-perm-demo"
- "arn:aws:s3:::cross-acct-perm-demo/*"
Principal: "arn:aws:iam::1234567890:role/service-role/test-role-20190828T130835"
- Action: "*"
Resource: !Join [ '', ["arn:aws:s3:::", !Ref S3BucketTest, '/*']]
Principal: '*'
Effect: Deny
Condition:
Bool:
'aws:SecureTransport':
- 'false'
Error message:
Invalid policy syntax. (Service: Amazon S3; Status Code: 400; Error Code: MalformedPolicy; Request ID: 91BF8921047D9D3B; S3 Extended Request ID: ZOVOzmFZYN6yB1btOqMqgJjOpzfiUpP86c2XiVylzYkg37fGga8/eYDL7C4WzwhmcDGU7NJkL68=)
Not sure where I got this wrong. Can I provision S3 bucket access to cross-account IAM? From the console permissions section, I was able to do it.

Your bucket is called cross-acct-permission-demo but your policy specifies cross-acct-perm-demo. Also your indentation is not correct for the first Action (though it should not cause this issue). Also not sure if the service-role principle is correct in this context.

If you want IAM users in account A to be able to access resources in account B then you create an IAM role in account B that gives access to the relevant resources in account B, then you define account A as a trusted entity for the IAM role, then you permit access to that role to the relevant users in account A. Those users in account A can now assume the (cross-account) role in account B, and gain access to resources in account B.
See Tutorial: Delegate Access Across AWS Accounts Using IAM Roles

Related

aws lambda permission to IAM usergroup using cloudformation

I need create a way for execute especific lambdas for specific IAM users, then i am doing:
I am creating a Usergroup in cloudformation:
Resources:
XXXGroup:
Type: AWS::IAM::Group
And after I am creating a policy and add the policy to my UserGroup
UsersXPolicies:
Type: AWS::IAM::Policy
Properties:
Groups:
- !Ref XXXGroup
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "lambda:*"
Resource:
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:MyFunction
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:MyFunction2
PolicyName: xxx-access-policy
I try first only with "lambda:InvokeFunction" but it not works, then I try with lambda:* but it not works
After I am creating a user:
XXUser:
Type: AWS::IAM::User
Properties:
UserName: xxx.user
LoginProfile:
Password: l98GaTc9xzT9
PasswordResetRequired: true
Path: /
And finally i am adding the user to my usergroup:
USerAdditionX:
Type: AWS::IAM::UserToGroupAddition
Properties:
GroupName: !Ref XXXGroup
Users:
- !Ref XXUser
But after login with my new user i am getting the following error when i go to lambda service:
User: arn:aws:iam::xxxxxxxxx:user/xx.user is not authorized to perform: lambda:GetAccountSettings on resource: * because no identity-based policy allows the lambda:GetAccountSettings action
Access to specific lambdas from my new user
The problem is that lambda get its permission from a role.Policies are attached to role.
You need to attach your policies to a role and then attach a role to lambda.
Please read about lambda execution role over here
You can't limit the visibility for the list of all the Lambda Functions (there is also the same "problem" on EC2 Instances and S3 Buckets permissions policy), so your user cannot interact with the Lambda because the policy that you provided have the condition on the specific resource, but he need the full read-only capability even to see the function.
You should add at least an Allow statement on lambda:ListFunctions and lambda:GetAccountSettings for Resource "*" (so on every Lambda of your account), as stated here.
You could also, as documented here, add the standard AWSLambda_ReadOnlyAccess policy to your group.

Possible to create a policy and share the policy to role across multiple accounts

I am trying to create a policy in one AWS account and need to share that policy to a role in multiple accounts (Prod, Dev, Sandbox).
And I can add the AWS accounts number manually and assign AWS Managed Policy to roles and needs to create multiple roles as well.
How can we achieve this?
Here is the code I wrote
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Create a role that authorizes access to users in another account'
Metadata:
Version: 0.7
Parameters:
RoleName:
Type: String
Default: R_EC2-Describe-Instance
MainAccountId:
Type: String
Description: >-
Include the Managed Services Account ID(the account ID where the Main VPC is registered)
Default: 111111111111
MaxLength: 12
MinLength: 12
Resources:
AssumeRole:
Type: AWS::IAM::Policy
Properties:
RoleName: !Ref RoleName
Policies:
-
PolicyName: "CoreSVC-Describe-EC2"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- 'sts:AssumeRole'
Resource: !Join [ "", [ "arn:aws:iam::", !Ref MainAccountId, ":role/R_EC2-Describe-Instance" ] ]
AssumeRolePolicyDocument:
Version: '2012-10-17'
ManagedPolicyName:
- "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAcess"
Statement:
- Effect: Allow
Principal:
"AWS": !Join [ "", [ "arn:aws:iam::", !Ref MainAccountId, ":root" ] ]
Action:
- sts:AssumeRole
Condition: {}
You can't share an IAM Policy with other accounts, as it doesn't have a resource policy to allow it.
The code sample you've shared is sharing the IAM Role with multiple accounts, which is possible via the role's resource/trust policy.
If you want to share the same policy across multiple accounts, then you should probably use CloudFormation StackSets (as mentioned by #ervin-szilagyi), or some other infrastructure-as-code approach.
If you want to share the role with other accounts, then you've already done it. All that's missing is role in those accounts with access to the sts:AssumeRole action so that it can assume the role you've shared in your code.

How to reference AWS managed policy arn in cloudformation?

I am going to create an IAM user with cloudformation and need to attach an AWS managed policy AWSAppSyncInvokeFullAccess. I think I should use the managed policy like below code:
Resources:
publisherUser:
Type: AWS::IAM::User
Properties:
UserName: userName
ManagedPolicyArns:
- !Ref AWSAppSyncInvokeFullAccess
- !Ref AWSLambdaBasicExecutionRole
but it doesn't work since AWSAppSyncInvokeFullAccess is from AWS not from this template. What is the correct way to reference the policies?
These are existing AWS-managed policies. So you should use their full ARN, which you can get from IAM console:
Resources:
publisherUser:
Type: AWS::IAM::User
Properties:
UserName: userName
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSAppSyncInvokeFullAccess
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Update
Or to make it partition independent:
Resources:
publisherUser:
Type: AWS::IAM::User
Properties:
UserName: userName
ManagedPolicyArns:
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AWSAppSyncInvokeFullAccess"
- !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
Just in case anyone was wondering you can find the ARNs of all IAM policies by clicking on the name of the policy on the Policies page.

AWS Cloudformation Role is not authorized to perform AssumeRole on Role

I am trying to execute a cloudformation stack which contains the following resources:
Codebuild project
Codepipeline pipeline
Roles needed
While trying to execute the stack, it fails with the following error:
arn:aws:iam::ACCOUNT_ID:role/CodePipelineRole is not authorized to perform AssumeRole on role arn:aws:iam::ACCOUNT_ID:role/CodePipelineRole (Service: AWSCodePipeline; Status Code: 400; Error Code: InvalidStructureException; Request ID: 7de2b1c6-a432-47e6-8208-2c0072ebaf4b)
I created the role using a managed policy, but I have already tried with a normal policy and it does not work neither.
This is the Role Policy:
CodePipelinePolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Description: 'This policy grants permissions to a service role to enable Codepipeline to use multiple AWS Resources on the users behalf'
Path: "/"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Resource: "*"
Effect: "Allow"
Condition: {}
Action:
- autoscaling:*
- cloudwatch:*
- cloudtrail:*
- cloudformation:*
- codebuild:*
- codecommit:*
- codedeploy:*
- codepipeline:*
- ec2:*
- ecs:*
- ecr:*
- elasticbeanstalk:*
- elasticloadbalancing:*
- iam:*
- lambda:*
- logs:*
- rds:*
- s3:*
- sns:*
- ssm:*
- sqs:*
- kms:*
This is the Role
CodePipelineRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: !Sub ${EnvironmentName}-CodePipelineRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- 'sts:AssumeRole'
Effect: Allow
Principal:
Service:
- codepipeline.amazonaws.com
Path: /
ManagedPolicyArns:
- !Ref CodePipelinePolicy
What intrigues me the most is that it seems like CodePipelineRole is trying to AssumeRole to itself. I'm not understanding what can be happening here.
And when I set the policy's action to *, it works! I don't know what permissions could be missing.
Thanks
It is to do with the trust relationship for the role you have created i.e. CodePipelineRole
Go to the Role in IAM
Select the Trust Relationships tab ...
Then Edit Trust Relationship to include codepipeline
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"codepipeline.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}```
It seems like, behind the scenes, AWS services keep some kind of role cache. If you try to make a role, attach a policy and create a new CodeBuild project sequentially, CodeBuild will give an unauthorized error because it can't find the role. It's similar to getting a forbidden access error on a non-existing bucket (instead of a 404). If you separate the stack in two other stacks: first you create the roles and then you create the CodeBuild, it works. I don't understand why the CLI command works instantly though.
try adding sts:AssumeRole to the list of Actions.
https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_roles.html
Cheers
I had a similar issue with EKS for some reason code build role could not assume role. I solved it by creating a user with sufficient access and by setting:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
env vars as default env vars from environment section in cloud build:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html
I bet you specified RoleArn on your Source action of the CodePipeline. Try to remove it.
CodePipelinePipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
...
Stages:
- Name: "Source"
Actions:
- Name: "Source"
#RoleArn: !GetAtt CodePipelineRole.Arn
The last line was the reason for the very same error in my case.

Edit AWS Cognito Identity Pool using serverless.yml

I am configuring an AWS Cognito Identity Pool using the severless framework, and I am editing a file in the yml configuration to add an unauthenticated role for users to upload an image to an s3 bucket.
The code was previously deployed without an unauthenticated role being specified, and the deployment went fine and was stable. After I went looking for a way to control the permissions regarding accessing the S3 bucket, I discovered that the only way to give write, but not read, permissions on an S3 bucket is to specify it in a user policy, so I have to add an unathenticated role to the identity pool. However, when I deploy the code, I get an error stating:
Serverless Error ---------------------------------------
An error occurred: CognitoIdentityPoolRoles - Resource cannot be updated.
I have managed to get around the problem in the dev environment but it required totally deleting the stack and rebuilding it from scratch.
I also do not want to go in and adjust the resources manually in the AWS console since resources should be managed in cloudformation or in the console, but doing it both ways leads to chaos.
So, at the moment, the options I see are to delete the entire stack and rebuild it with the new roles, or find a way to update through cloudformation.
Does anyone have a way to avoid the first option and allow me to update the stack without attaching the role in the console?
Relevant section of serverless.yml is below...
Resources:
# The federated identity for our user pool to auth with
CognitoIdentityPool:
Type: AWS::Cognito::IdentityPool
Properties:
# Generate a name based on the stage
IdentityPoolName: ${self:custom.stage}MyIdentityPool
# Allow unathenticated users
AllowUnauthenticatedIdentities: true
# Link to our User Pool
CognitoIdentityProviders:
- ClientId:
Ref: CognitoUserPoolClient
ProviderName:
Fn::GetAtt: [ "CognitoUserPool", "ProviderName" ]
# IAM roles
CognitoIdentityPoolRoles:
Type: AWS::Cognito::IdentityPoolRoleAttachment
Properties:
IdentityPoolId:
Ref: CognitoIdentityPool
Roles:
authenticated:
Fn::GetAtt: [CognitoAuthRole, Arn]
# Next two lines are the 2 lines of code which break everything
unauthenticated:
Fn::GetAtt: [CognitoUnAuthRole, Arn]
# IAM role for UN-authenticated users
CognitoUnAuthRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Principal:
Federated: 'cognito-identity.amazonaws.com'
Action:
- 'sts:AssumeRoleWithWebIdentity'
Condition:
StringEquals:
'cognito-identity.amazonaws.com:aud':
Ref: CognitoIdentityPool
'ForAnyValue:StringLike':
'cognito-identity.amazonaws.com:amr': unauthenticated
Policies:
- PolicyName: 'CognitoUnAuthorizedPolicy'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Action:
- 'mobileanalytics:PutEvents'
- 'cognito-sync:*'
- 'cognito-identity:*'
Resource: '*'
# Allow users to upload attachments to their
# folder inside our S3 bucket
- Effect: 'Allow'
Action:
- 's3:PutObject'
Resource:
- Fn::Join:
- ''
-
- Fn::GetAtt: [MediafilesBucket, Arn]
- '/submissions/'
Fixed.
I commented out the sections of serverless.yml related to the identity pool deployed (destroyed), then uncommented that section, redeployed, and restored from backup.
It seems to be a bit of a hack, but it worked.
I also feel like there should be a way to edit identity pool roles through cloudformation...