Cross account access to SSM parameters - amazon-iam

I followed the instructions mentioned in an AWS developer forum post (now no longer available).
Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ssm:GetParametersByPath",
"ssm:GetParameters",
"ssm:GetParameter"
],
"Resource": "arn:aws:ssm:eu-central-1:XXXXXXXXXX:parameter/some-root/*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "ssm:DescribeParameters",
"Resource": "*"
}
]
}
I attached the policy to the target account in a role
When I get the parameters from the source account it works, however I can't access them from the target account.
C:\Users\my-home>aws ssm get-parameters-by-path --path "/some-root/" --profile aws-acc-src
{
"Parameters": [
{
"Name": "/some-root/dev",
"Type": "SecureString",
"Value": "AQICAHh5z4qygT6rbxBnR/PmJn811vO30kBJNB+JrB1tdKNBeAEHFLSQDpTMsRMc1l0D8lXYAAAAYTBfBgkqhkiG9w0BBwagUjBQAgEAMEsGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM+Qmz5FoNcESEXabnAgEQgB6MdOlb545EPN61QqA50w7rH3sghmNWvxsLPPneHEA=",
"Version": 1,
"LastModifiedDate": "2020-10-06T16:03:32.637000+03:00",
"ARN": "arn:aws:ssm:eu-central-1:XXXXXXXX:parameter/some-root/dev"
}
]
}
aws ssm get-parameters-by-path --path "/some-root/" --with-decryption --profile aws-acc-src
{
"Parameters": [
{
"Name": "/some-root/dev",
"Type": "SecureString",
"Value": "foo",
"Version": 1,
"LastModifiedDate": "2020-10-06T16:03:32.637000+03:00",
"ARN": "arn:aws:ssm:eu-central-1:XXXXXXXX:parameter/some-root/dev"
}
]
}
aws ssm get-parameters-by-path --path "/some-root/" --with-decryption --profile aws-acc-target
{
"Parameters": []
}

It looks like, the parameter store doesn't support cross account access. Alternatively you can use secrets manager to share secrets between different AWS accounts.
https://medium.com/awesome-cloud/aws-difference-between-secrets-manager-and-parameter-store-systems-manager-f02686604eae

Related

AWS Role with a PolicyDocument assuming itself

I am trying to understand code written by coworker that has left.
Can anyone tell me why we have a Policy that assume the role it's attached too, what is it suppose to do?
{
"Role1": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
}
}
]
},
"ManagedPolicyArns": [],
"Policies": []
},
"AssumeRolePermissions": {
"Type": "AWS::IAM::Policy",
"DependsOn": "Role1",
"Properties": {
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": { "Fn::GetAtt": [ "Role1", "Arn" ] }
}
]
},
"PolicyName": "Assume_Role",
"Roles": [{ "Ref": "Role1" }]
}
}
}
}
I know a trust policy is useful in the case I want Role2 to assume Role1's permissions.
From the new update (https://aws.amazon.com/blogs/security/announcing-an-update-to-iam-role-trust-policy-behavior/) if seems in that case I need both of them in the trust policy but what if I don't do that, is there a use case for assuming its own role?
Thanks
"Role1": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"AWS": { "Fn::GetAtt": [ "Role1", "Arn" ] }
}
}
]
},
"ManagedPolicyArns": [],
"Policies": []
}
Thanks to #JohnRotenstein and AWS support:
A role assuming itself is a rare use case that while valid isn't an AWS best practice, with AWS recommending using multiple roles instead.
Some of these use cases involve self-assuming in conjunction with a 'scoped-down' policy to obtain a different privilege level, or using a single role and policy throughout the development => build => test => production environment, or can be used to rotate the access/secret keys used by the role since when you role chain the session only last one hour.
All that being said in the majority of cases a self assuming role is a step that depends on use case.

Custom resource name for IAM role defined in user-pool-group-precedence.json Amplify

I have an Amplify project and want to have a custom resource string per environment. For example I have the below defined in my user-pool-group-precedence.json file:
[{
"groupName": "example",
"precedence": 1,
"customPolicies": [
{
"PolicyName": "example-policy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Policy01",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::s3bucket-*/"],
"Effect": "Allow"
}
]
}
]
}]
I have multiple s3 buckets (1 per environment). For example s3bucket-dev and s3bucket-qa. Currently the above policy grants access to all my s3 buckets in different environments. How do I go about defining a single bucket per environment? Ideally I want something like
arn:aws:s3:::s3bucket-${aws:env}/
I looked at using conditions but was unsure how to implement them in order to achieve my goal.
Since this policy will be added to the amplify cloudformation template, Amplify already provides the parameter env in that target template. I suppose you will just have to reference it in your policy like this to make it dynamic as per your environment (Fn::Join does what you need):
[{
"groupName": "example",
"precedence": 1,
"customPolicies": [
{
"PolicyName": "example-policy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Policy01",
"Action": ["s3:GetObject"],
"Resource": {
"Fn::Join": [
"",
[
"arn:aws:s3:::s3bucket-",
{
"Ref": "env"
},
"/"
]
]
},
"Effect": "Allow"
}
]
}
]
}]

Cannot set S3 trigger for Lambda function in AWS

I've been all over the internet looking for a solution to this. I have been trying to setup an AWS Lambda function to send a message to SNS every time a file is uploaded to a particular S3 bucket, according to this tutorial. At this point, I have the function setup and I can invoke it successfully. However, when I attempt to connect the function to S3, I get an error stating An error occurred (InvalidArgument) when calling the PutBucketNotification operation: Unable to validate the following destination configurations. According to this article, I should be able to add a permission that will let S3 invoke the Lambda function, like this:
aws lambda add-permission \
--function-name my-file-upload \
--principal s3.amazonaws.com \
--statement-id AcceptFromImport \
--action "lambda:InvokeFunction" \
--source-arn arn:aws:s3:::file-import \
--source-account my_account_id
I did this, and noticed that the policy associated with the Lambda function updated and appeared to be correct. However, the error persists. I've looked at a similar question, here, but none of the solutions here worked.
Execution Role ARN: arn:aws:iam::my_account_id:role/lambda-upload-stream
Execution Role (lambda-upload-stream) trust relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Execution Role policy (my-file-upload):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AccessObject",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::file-import/*"
},
{
"Sid": "SendUpdate",
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:ap-northeast-1:my_account_id:comm-in"
}
]
}
Lambda function ARN: arn:aws:lambda:ap-northeast-1:my_account_id:function:my-file-upload
Lambda function role document
{
"roleName": "lambda-upload-stream",
"policies": [
{
"name": "my-file-upload",
"id": "AWS_ACCESS_KEY_ID",
"type": "managed",
"arn": "arn:aws:iam::my_account_id:policy/my-file-upload",
"document": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AccessObject",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::file-import/*"
},
{
"Sid": "SendUpdate",
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:ap-northeast-1:my_account_id:comm-in"
}
]
}
}
],
"resources": {
"s3": {
"service": {
"name": "Amazon S3",
"icon": "data:image/svg+xml;base64,very_long_base64_string1"
},
"statements": [
{
"resource": "arn:aws:s3:::file-import/*",
"service": "s3",
"effect": "Allow",
"action": "s3:GetObject",
"source": {
"index": "AccessObject",
"policyName": "my-file-upload",
"policyType": "managed"
}
}
]
},
"sns": {
"service": {
"name": "Amazon SNS",
"icon": "data:image/svg+xml;base64,very_long_base64_string2"
},
"statements": [
{
"resource": "arn:aws:sns:ap-northeast-1:my_account_id:comm-in",
"service": "sns",
"effect": "Allow",
"action": "sns:Publish",
"source": {
"index": "SendUpdate",
"policyName": "my-file-upload",
"policyType": "managed"
}
}
]
}
},
"trustedEntities": [
"lambda.amazonaws.com"
]
}
Lambda function resource policy:
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:ap-northeast-1:my_account_id:function:my-file-upload",
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "my_account_id"
},
"ArnLike": {
"AWS:SourceArn": "arn:aws:s3:::file-import"
}
}
}
]
}
My question is: what am I doing wrong here and how do I fix it?
The thing you need to create is called a "Resource-based policy", and is what should be created by aws lambda add-permission.
A Resource-based policy gives S3 permission to invoke your lambda. This is a property on your lambda itself, and is not part of your lambda's IAM role (Your lambda's IAM role controls what your lambda can do, a Resource-based policy controls who can do what to your lambda. You can view this resource in the UI on the aws console by going to your lambda, clicking "Permissions" and scrolling down to "Resource-based policy". The keyword you want to look out for is lambda:InvokeFunction, which is what gives other things permission to call your lambda, including other AWS accounts, and other AWS services on your account (like s3).
That being said, the command you ran should have created this policy. Did you make sure to replace my_account_id with your actual account id when you ran the command?
In addition, make sure you replace --source-arn arn:aws:s3:::file-import with the actual ARN of your bucket (I assume you had to create a bucket with a different name because s3 buckets must have globally unique names, and file-import is almost surely already taken)
I figured out what the problem was. My initial command was:
aws s3api put-bucket-notification --bucket azure-erp-import \
--notification-configuration "CloudFunctionConfiguration={Id=file-uploaded,Events=[],Event=s3:ObjectCreated:*,CloudFunction=arn:aws:lambda:ap-northeast-1:my_account_id:function:my-file-upload,InvocationRole=arn:aws:iam::my_account_id:role/lambda-upload-stream}"
This failed because the arn:aws:iam::my_account_id:role/lambda-upload-stream role doesn't have permissions to call lambda:InvokeFunction on the lambda function. Removing this value fixed the error.

aws assume role on shell script does not assume the role

I'm following a tutorial where I assume roles on EC2 instances so it has access to services. I'm following this tutorial (https://medium.com/swlh/aws-iam-assuming-an-iam-role-from-an-ec2-instance-882081386c49), but I'm stuck on the cli part when I start running a "aws s3 ls". Just so I know it works, I gave the AssumedRole all access to s3.
This is my setup:
ImplicitRole // will be attached to EC2
policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::xxx:role/*"
}
]
}
AssumedRole // will be the role assumed once logged in to EC2
policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
What happens is I would run the following on cli
aws sts assume-role --role-arn arn:aws:iam::****:role/AssumedRole --role-session-name test-session
Then I will get the Credentials
{
"Credentials": {
"AccessKeyId": "key",
"SecretAccessKey": "secret",
"SessionToken": "longtoken",
"Expiration": "2020-07-08T07:29:51+00:00"
},
"AssumedRoleUser": {
"AssumedRoleId": "AKDIEEOOKDLKSDJFDJ:test-session",
"Arn": "arn:aws:sts::xxxx:assumed-role/AssumedRole/test-session"
}
}
and then will update the variables eg: set AWS_ACCESS_KEY_ID=XXXX , etc
Once done I run the following but it would give me ListObject AccessDenied
aws s3 ls s3://bucket
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

Allow access to file only from specific Lambda [s3]

A s3 bucket (static web hosting) have a certain policy that deny access to everyone concerning a certain file.
How can I allow only a specific lambda function to access it ? (using only the bucket policy)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Authentication",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"NotResource": "arn:aws:s3:::web/auth.html"
}
]
}
UPDATE : Changing the previous policy with this one gives the desired result
{
"Version": "2012-10-17",
"Id": "Policy1477651215159",
"Statement": [
{
"Sid": "Console administration",
"Effect": "Allow",
"NotPrincipal": {
"AWS": "arn:aws:iam::XXXX:role/role_lambda"
},
"Action": "s3:GetObject",
"NotResource": "arn:aws:s3:::web/auth.html"
}
]
}
Lambda functions run in a Execution Role. You can make a customer IAM Role for your lambda function. See this
Then you can use that IAM Role to grant access to that S3 Object. See this article for steps to follow.
This is a CloudFormation snippet. You can allow your Lambda role access to S3 using the following IAM policy statement:
"LambdaRolePolicy" : {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyName": "Lambda",
"PolicyDocument": {
"Statement" : [ {
"Action" : [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Effect" : "Allow",
"Resource" : {
"Fn::Join": [ "", [
"arn:aws:s3:::",
{ "Ref": "S3Bucket" },
"/*"
] ]
}
} ]
},
"Roles" : [ { "Ref": "RootRole" } ]
}
}
S3Bucket resource is your S3 bucket and RootRole is the Lambda role.