I have created a lambda function through which I want to launch an ec2 instance using pre-baked AMI along with a bunch of other tags.
Lambda function:
require 'json'
require 'aws-sdk'
def lambda_handler(event:, context:)
client = Aws::EC2::Client.new(region: 'us-west-2')
images = client.describe_images({
filters: [
{
name: "tag:metatag",
values: ["app"],
},
],
owners: ["<owner_id>"],
dry_run: false,
}).images
latest_image_id = images.first.image_id
ec2 = Aws::EC2::Resource.new(region: 'us-west-2')
instance = ec2.create_instances({
image_id: latest_image_id,
min_count: 1,
max_count: 1,
key_name: '<key-name>',
security_group_ids: ['ApplicationSG'],
instance_type: 't3.large',
subnet_id: '<subnet>',
iam_instance_profile: {
arn: '<arn>'
}
})
instance.batch_create_tags({ tags: [
{ key: 'Name', value: 'testapp08' }
]})
{ statusCode: 200, body: JSON.generate("latest_image_id:#{latest_image_id}, instance: #{instance.inspect}") }
end
Created a role with an inline policy to provide required ec2 launch permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:DetachVolume",
"ec2:AttachVolume",
"ec2:RebootInstances",
"ec2:ResetImageAttribute",
"ec2:DeregisterImage",
"ec2:DeleteTags",
"ec2:CreateTags",
"ec2:ResetSnapshotAttribute",
"ec2:RunInstances",
"ec2:StopInstances",
"ec2:CreateVolume",
"ec2:Describe*",
"ec2:ModifySnapshotAttribute",
"ec2:StartInstances"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "logs:*",
"Resource": "arn:aws:logs:*:*:*"
}
]
}
Currently getting the following error while permissions as ec2:RunInstances is enabled
{
"errorMessage": "You are not authorized to perform this operation. Encoded authorization failure message: sGOne-.....",
"errorType": "Function<Aws::EC2::Errors::UnauthorizedOperation>",
"stackTrace": [
"/var/runtime/gems/aws-sdk-core-3.40.0/lib/seahorse/client/plugins/raise_response_errors.rb:15:in `call'",
"/var/runtime/gems/aws-sdk-core-3.40.0/lib/aws-sdk-core/plugins/jsonvalue_converter.rb:20:in `call'",
"/var/runtime/gems/aws-sdk-core-3.40.0/lib/aws-sdk-core/plugins/idempotency_token.rb:17:in `call'",
"/var/runtime/gems/aws-sdk-core-3.40.0/lib/aws-sdk-core/plugins/param_converter.rb:24:in `call'",
"/var/runtime/gems/aws-sdk-core-3.40.0/lib/aws-sdk-core/plugins/response_paging.rb:10:in `call'",
"/var/runtime/gems/aws-sdk-core-3.40.0/lib/seahorse/client/plugins/response_target.rb:23:in `call'",
"/var/runtime/gems/aws-sdk-core-3.40.0/lib/seahorse/client/request.rb:70:in `send_request'",
"/var/runtime/gems/aws-sdk-ec2-1.60.0/lib/aws-sdk-ec2/client.rb:27423:in `run_instances'",
"/var/runtime/gems/aws-sdk-ec2-1.60.0/lib/aws-sdk-ec2/resource.rb:392:in `create_instances'",
"/var/task/lambda_function.rb:21:in `lambda_handler'"
]
}
This property:
iam_instance_profile: {
arn: '<arn>'
}
requires iam:PassRole permission.
This is because a normal user who only has limited permissions might try to launch an EC2 instance with a role that has super-user access. Therefore, they require iam:PassRole permission to be able to launch an instance with a role. The policy that grants this permission can then restrict which roles they are allowed to 'pass'.
Therefore, add iam:PassRole permission to the policy.
Related
First of all I have been searching stackflow and the internet for this but I didn't find exactly where the issue is.
Basically I am trying to add custom cidr ips to a security group via lambda function. I have given all the appropriate permissions (as far as i can tell) [REMOVED]and also tried attaching the vpc (which is non-default) to the lambda function to access the security group[REMOVED].
But I am getting "An error occurred (VPCIdNotSpecified) when calling the AuthorizeSecurityGroupIngress operation: No default VPC for this user"
Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:RevokeSecurityGroupIngress",
"ec2:CreateNetworkInterface",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeVpcs",
"ec2:DeleteNetworkInterface",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"wafv2:GetIPSet",
"logs:CreateLogGroup",
"wafv2:UpdateIPSet"
],
"Resource": [
"arn:aws:logs:us-west-2:xxxx:log-group:xxx:log-stream:*",
"arn:aws:wafv2:us-west-2:xxx:*/ipset/*/*"
]
}
]
}
Lambda function:
#!/usr/bin/python3.9
import boto3
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
response = ec2.authorize_security_group_ingress(
GroupId='sg-xxxxxxx'
IpPermissions=[
{
'FromPort': 443,
'IpProtocol': 'tcp',
'IpRanges': [
{
'CidrIp': '1x.1x.x.1x/32',
'Description': 'adding test cidr using lambda'
},
],
'ToPort': 443
}
],
DryRun=True
)
return response
Could someone point me to the right direction? VPC is non-default. All I need is the add ingress rule to existing security group within non-default vpc
Thanks
Found the solution: Initially it was syntax error but after googling i thought it requires vpc so I added VPC to the Lambda configuration which was not required for this purpose.
For anyone having the same issue (only want to update security group with the cidr): below is the correct function and permissions (function isnt complete as depending on the solution u may want to delete old rules too):
Lambda function:
#!/usr/bin/python3.9
import boto3
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
response = ec2.authorize_security_group_ingress(
DryRun=False,
GroupId='sg-0123456789',
IpPermissions=[
{
'FromPort': 443,
'IpProtocol': 'tcp',
'IpRanges': [
{
'CidrIp': '1x.2x.3x.4x/32',
'Description': 'Security group updated via lambda'
}
],
'ToPort': 443
}
]
)
return response
IAM Policy on lambda execution role:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:ModifySecurityGroupRules",
"ec2:UpdateSecurityGroupRuleDescriptionsIngress"
],
"Resource": "arn or all"
}
]
}
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.
When deploying Spinnaker to EKS via hal deploy apply, Spinnaker Clouddriver pod goes to CrashLoopBackOff with the following error,
Caused by: com.amazonaws.services.securitytoken.model.AWSSecurityTokenServiceException: User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/Spinnaker-k8s-Worker-Node-Role/i-yyyyyyyyyyyyyyy is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::xxxxxxxxxxxx:role/Spinnaker-Managed-Role
My Halyard config is like follows,
currentDeployment: default
deploymentConfigurations:
- name: default
version: 1.17.6
providers:
appengine:
enabled: false
accounts: []
aws:
enabled: true
accounts:
- name: my-account
requiredGroupMembership: []
providerVersion: V1
permissions: {}
accountId: 'xxxxxxxxxxxx' # my account id here
regions:
- name: us-east-1
assumeRole: Spinnaker-Clouddriver-Role
lifecycleHooks: []
primaryAccount: my-account
bakeryDefaults:
baseImages: []
defaultKeyPairTemplate: '{{name}}-keypair'
defaultRegions:
- name: us-east-1
defaults:
iamRole: BaseIAMRole
My Spinnaker-Clouddriver-Role IAM role has PowerUserAccess permissions at the moment and has following as the Trust Relationship
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com",
"ecs.amazonaws.com",
"application-autoscaling.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxxxxx:role/Spinnaker-k8s-Worker-Node-Role"
},
"Action": "sts:AssumeRole"
}
]
}
How can I get this resolved?
The full log can be found on https://gist.github.com/agentmilindu/d9d31ee4287c87fb87e5060e0709989d#file-awssecuritytokenserviceexception-log-L3
Take a look at an AWS IAM policy that works flawlessly.
Refer to Armory AWS IAM set up and EC2 provider set up
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:*",
"cloudformation:*",
"ecr:*"
],
"Resource": [
"*"
]
},
{
"Action": "sts:AssumeRole",
"Resource": [
"arn:aws:iam::123456789012:role/SpinnakerManagedRoleAccount1",
"arn:aws:iam::101121314157:role/SpinnakerManagedRoleAccount2",
"arn:aws:iam::202122232425:role/SpinnakerManagedRoleAccount3"
],
"Effect": "Allow"
}
]
}
I have a cloudformation template that creates a lambda funciton as well as a role for that lambda function. I try assuming the role in the lambda function but keep getting the error :
An error occurred (AccessDenied) when calling the AssumeRole operation: Access denied
Is there a step I'm missing? Not sure why I don't have permission to assume the role. I'm assuming I'm missing some sort of permission if the error I'm getting is access denied as opposed to some execution error.
Cloudformation Snippet :
"LambdaRoleCustomResource": {
"Type": "AWS::IAM::Role",
"Condition": "CreateWebACL",
"DependsOn": "WAFWebACL",
"Properties": {
"RoleName": {
"Fn::Join": ["-", [{
"Ref": "AWS::StackName"
}, "Custom-Resource"]]
},
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": ["lambda.amazonaws.com"]
},
"Action": ["sts:AssumeRole"]
}]
},
"Path": "/",
"Policies": [{
"PolicyName": "S3Access",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"s3:CreateBucket",
"s3:GetBucketLocation",
"s3:GetBucketNotification",
"s3:GetObject",
"s3:ListBucket",
"s3:PutBucketNotification"
],
"Resource": {
"Fn::Join": ["", ["arn:aws:s3:::", {
"Ref": "AccessLogBucket"
}]]
}
}]
}
}
Lambda Function Snippet:
sts_client = boto3.client('sts')
sts_credentials = sts_client.assume_role(RoleArn='arn:aws:iam::XXXXXXXXX:role/portal-cloudfront-waf-Custom-Resource', RoleSessionName='custom-resource-cf-session')
sts_credentials = sts_credentials['Credentials']
cf = boto3.client('cloudformation', aws_access_key_id=sts_credentials['AccessKeyId'], aws_secret_access_key=sts_credentials['SecretAccessKey'], aws_session_token=sts_credentials['SessionToken'])
stack_name = event['ResourceProperties']['StackName']
cf_desc = cf.describe_stacks(StackName=stack_name)
global waf
sts_client = boto3.client('sts')
sts_credentials = sts_client.assume_role(RoleArn='arn:aws:iam::XXXXXXXX:role/portal-cloudfront-waf-Custom-Resource', RoleSessionName='custom-resource-waf-session')
sts_credentials = sts_credentials['Credentials']
s3 = boto3.client('waf', aws_access_key_id=sts_credentials['AccessKeyId'], aws_secret_access_key=sts_credentials['SecretAccessKey'], aws_session_token=sts_credentials['SessionToken'])
waf = boto3.client('waf')
Your Lambda function will automatically use the permissions associated with the Role attached to the function. There is no need to create credentials.
So, just use:
cf = boto3.client('cloudformation')
s3 = boto3.client('waf')
I'm new to aws. I want to generate temporary credentials for aws call. And for that I use example from Making Requests Using IAM User Temporary Credentials - AWS SDK for Java
Where I pass
String clientRegion = "<specific region>";
String roleARN = "<ARN from role>";
String roleSessionName = "Just random string"; //<-- maybe I should pass specific SessionName?
String bucketName = "<specific bucket name>";
And when trying assume role
stsClient.assumeRole(roleRequest);
get an error
com.amazonaws.services.securitytoken.model.AWSSecurityTokenServiceException:
User: arn:aws:iam:::user/ is not authorized to perform:
sts:AssumeRole on resource: arn:aws:iam::<ID>:role/<ROLE_NAME> (Service: AWSSecurityTokenService; Status Code: 403; Error Code:
AccessDenied; Request ID:)
I have a cognito role.
I think the problem in role Trust Relationship settings.
It looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<iam user ID>:user/<USER_NAME>",
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "<user pool ID>"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
and user policy (This user policy is attached to this Role also):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "<sidId1>",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::<path>*"
]
},
{
"Sid": "sidId2",
"Effect": "Allow",
"Action": [
"sts:AssumeRole",
"sts:AssumeRoleWithWebIdentity"
],
"Resource": [
"arn:aws:iam::<ID>:role/<ROLE_NAME>"
]
}
]
}
User policy has two warnings:
What I'm doing wrong?
UPD
I changed role Trust relationship, just delete Condition:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com",
"AWS": "arn:aws:iam::<ID>:user/<USER>"
},
"Action": [
"sts:AssumeRole",
"sts:AssumeRoleWithWebIdentity"
]
}
]
}
and now Access denied error occurred on another line of code:
// Verify that assuming the role worked and the permissions are set correctly
// by getting a set of object keys from the bucket.
ObjectListing objects = s3Client.listObjects(bucketName);
Received error response: com.amazonaws.services.s3.model.AmazonS3Exception: Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: ), S3 Extended Request ID:
To be able to assume to an IAM Role, simply the IAM Role assume role policy or trust relation must explicitly allow the principal assuming role into it, which in this case it didn't. It permitted sts:AssumeRoleWithWebIdentity with some conditions which didn't apply to your case.
About the other error, as mentioned by the #user818510 your role doesn't have permission to s3:ListBucket action.