Sharing AWS Secrets Manager with another account is not working - amazon-web-services

I need to share an AWS Secrets Manager secret with multiple accounts.
For this public post, I've scrubbed the account numbers and replaced them with dummy values.
For this example, the account holding the secret is 987654 and it needs to be accessed by account 123456
The account that will "read" the secret (123456) should be able to read from "ANY ROLE" within the account.
Note: I tried using a wildcard in the principal (ex: "arn:aws:iam::123456:role/*") but I got a malformed policy error. So I'm using conditionals.
The secret is using a KMS key with the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::987654:role/Admin1",
"arn:aws:iam::987654:role/Terraform"
]
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:CallerAccount": [
"987654",
"123456"
]
}
}
}
]
}
The secret policy:
{
"Version" : "2012-10-17",
"Statement" : [ {
"Sid" : "",
"Effect" : "Allow",
"Principal" : {
"AWS" : "*"
},
"Action" : "secretsmanager:GetSecretValue",
"Resource" : "*",
"Condition" : {
"StringEquals" : {
"aws:SourceAccount" : [ "987654", "123456" ]
}
}
} ]
}
When reading the key from account 987654 it works fine. When I try to read the secret from role in account 123456 I get AccessDeniedException:
An error occurred (AccessDeniedException) when calling the GetSecretValue operation: User: arn:aws:sts::123456:assumed-role/Admin/sessionfoo is not authorized to perform: secretsmanager:GetSecretValue on resource: arn:aws:secretsmanager:us-east-1:987654:secret:test because no resource-based policy allows the secretsmanager:GetSecretValue action
I am testing with:
aws secretsmanager get-secret-value --secret-id 'arn:aws:secretsmanager:us-east-1:987654:secret:test'
What's wrong with my policies? Thanks!

Related

AWS IAM. How allow all resources with some tag?

I need to write policy to allow see all Secrets with some tag. But when I use condition, user with this policy loses all access. What am I doing wrong?
Here is my policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret",
"secretsmanager:ListSecrets"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/ProjectName": "Test"
}
}
}
]
}
Here is my Secret
But in result I have this message: You don't have permission to view or select from existing secrets in your account. Contact your administrator to obtain ListSecrets access.

Assume a role to an external account to access a specific instance of my account as Session Manager

I am a beginner studying AWS.
I'd like to give a role external account B so that It can access my account A.
I want to use Session Manager(System Manager) to record commands for external accounts.
My Account ID : A
External Account ID : B
So, In my Account A, I made ssm-accoutB-role.
connected policy is:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:StartSession"
],
"Resource": [
"arn:aws:ec2:REGION:ACCOUNT-ID_A:instance/*"
],
"Condition": {
"StringLike": {
"ssm:resourceTag/ssm": [
"true"
]
}
}
},
{
"Effect": "Allow",
"Action": [
"ssm:TerminateSession",
"ssm:ResumeSession"
],
"Resource": [
"arn:aws:ssm:*:*:session/${aws:username}-*"
]
},
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"*"
]
}
]
}
and set the trust relationship with AccountB
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT-ID_B:user/IAM-USER"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
and I attached Role for AmazonSSMManagedInstanceCore policy with Instance.
Using AWS-CLI, I send commands aws sts get-caller-identity, and export AWS_ACCESS_KEY_ID and so on...
success to assume Role.
and aws ssm start-session \ --target instance-id
// This instance in private subnet connected NAT Gateway
It appears error "An error occurred (AccessDeniedException) when calling the TerminateSession operation: User~~"
How to set the IAM ROLE for ssm...
Please help me!

aws secrets manger and multiple accounts

I have a secret in one account that I want to share in another account. In the other account we have a lambda function that will need this secret. I followed this and it works great.
AWS share secrets between accounts
Now we want to see if instead of granting access to every user that invokes this lambda is there a way to grant access to a group or a role in the other account access to the secret. I tried using the role that invokes the function but I got denied in the response for the lambda. Then next I tried a group in the other account but it wouldn't let me save it. I just kept telling the principal was not correct. Thanks.
So here is what I used for policies.
Policy on the Customer Managed Key
{
"Sid": "Permissions for external users",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::external-acct:role/Cross-Account-KMS-Role"
},
"Action": [
"kms:Decrypt",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "secretsmanager.us-east-1.amazonaws.com"
},
"StringLike": {
"kms:EncryptionContext:SecretARN": "arn:aws:secretsmanager:us-east-1:central-acct:secret:my-secret"
}
}
}
Now on the secret itself we set this policy up.
{
"Version" : "2012-10-17",
"Statement" : [ {
"Effect" : "Allow",
"Principal" : {
"AWS" : "arn:aws:iam::external-acct:role/Cross-Account-KMS-Role"
},
"Action" : "secretsmanager:GetSecretValue",
"Resource" : "*",
"Condition" : {
"ForAnyValue:StringEquals" : {
"secretsmanager:VersionStage" : "AWSCURRENT"
}
}}
Then on the external account we created this policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:us-east-1:central-acct:secret:my-secret"
},
{
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "arn:aws:kms:us-east-1:central-acct:key/customer-key-1"
}
]
}
then we atached the policy to the Role above. Now when i did this for my own account instead of the role I can use aws cli and pull the secret. Now of course i wasn't using the role but my account.
Ok, So I figured it out. It seems that the resource policy on the CMK was wrong. I had used one like this
arn:aws:kms:us-east-1:my_acct:key/my_policy
When I needed one like this.
arn:aws:kms:us-east-1:my_acct:key/my_policy_id

AWS secret manager access deny issue

I have a secret key (USRFTP) stored in ACCOUNT A, I want to access this key from EC2 box with role ASHISHROLE in ACCOUNT B. I am running python code to get secret key as given below, Using resource policy in secret key as given below, KMS policy is as given below, But still getting this issue
botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the GetSecretValue operation: User: arn:aws:sts::ACCOUNTB:assumed-role/ASHISHROLE /i-*********is not authorized to perform: secretsmanager:GetSecretValue on resource: arn:aws:secretsmanager:us-east-2:ACCOUNTA:secret:USRFTP-KJHJH
import boto3
import base64
from botocore.exceptions import ClientError
def get_secret():
secret_name = "arn:aws:secretsmanager:us-east-2:ACCOUNTA:secret:USRFTP"
region_name = "us-east-2"
# Create a Secrets Manager client
session = boto3.session.Session()
client = session.client(
service_name='secretsmanager',
region_name=region_name
)
print("here")
get_secret_value_response = client.get_secret_value(
SecretId=secret_name
)
if 'SecretString' in get_secret_value_response:
return get_secret_value_response['SecretString']
else:
return base64.b64decode(get_secret_value_response['SecretBinary'])
print(get_secret())
SECRET KEY RESOURCE POLICY
{
"Version" : "2012-10-17",
"Statement" : [ {
"Effect" : "Allow",
"Principal" : {
"AWS" : "arn:aws:iam::ACCOUNTB:role/ASHISHROLE"
},
"Action" : "secretsmanager:GetSecretValue",
"Resource" : "*"
} ]
}
KMS POLICY
{
"Id": "key-consolepolicy-3",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNTA:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNTA:role/OKin"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNTB:root"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNTB:root"
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": "true"
}
}
}
]
}
The most difficult concept with cross-account permissions is that it requires granting permission from both directions.
In your situation, you have:
Secrets Manager in Account-A
EC2 instance in Account-B
An IAM Role (Role-B) in Account-B
This requires permissions from A to B:
The Secret in Account-A needs a "Secret Key Resource Policy" that permits access from Role-B (You have already done this)
And it also requires permissions from B to A:
Role-B must be given permission to access the Secret in Account-A
This might seem strange, but I like to think of it like this:
By default, an IAM User / IAM Role has no permission
To use the Secrets Manager (even in the same account), the IAM Role must be given permission such as secretsmanager:GetSecretValue -- otherwise it isn't permitted to do anything
By default, an AWS Account cannot be accessed from another AWS Account (eg I cannot access your account)
If an AWS Account is willing to have another account access it, then it must grant access. This can be done at the resource-level in services such as S3, SNS, SQS, KMS and Secrets Manager because they have the ability to create policies on resources. Services without this capability cannot grant cross-account access and must be used by assuming a role in the same account.
The configuration in your question appears to be missing the permissions that need to be granted to Role-B to access the Secrets Manager, such as:
{
"Version" : "2012-10-17",
"Statement" : [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:us-east-2:ACCOUNTA:secret:USRFTP"
}
]
}
Thank you John for your answer, but I wanted to piggyback off of you because I also had this same issue. One thing I also noticed is that the "Principal" key is required when setting up these permissions. So here is something similar to what I had to do, just replaced my Principal value with a wildcard:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "ALLOW",
"Action": "secretsmanager:GetSecretValue",
"Principal": "*",
"Resource": "**Your:resource:name:here**"
}
]
}
So just make sure the Principal key is included at minimum and you should be good.

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.