AWS CLI: create EC2 instance and attach instance profile (unauthorized) - amazon-web-services

From an ec2 instance "A", I'd like to launch another ec2 instance "B" and assign it an instance profile.
I am able to create the new instance "B" without an instance profile:
aws ec2 run-instances --image-id ami-<redacted> --count 1 --instance-type t2.micro --key-name <redacted> --security-group-ids sg-<redacted> --subnet-id subnet-<redacted>
However, when I add the --iam-instance-profile Name="<redacted>" flag to attach the instance profile, I receive an error:
An error occurred (UnauthorizedOperation) when calling the RunInstances operation:
You are not authorized to perform this operation. Encoded authorization failure message: <redacted>
It guess the instance profile that is attached to instance "A" (and used to create instance "B") is lacking some resource permissions, but I cannot come up with the solution.
I decoded the failure message (aws sts decode-authorization-message --encoded-message <message>), but I still don't get the point:
{
"DecodedMessage":
"{\"allowed\":false,\"explicitDeny\":false,\"matchedStatements\":{\"items\":[]},\"failures\":{\"items\":[]},\"context\":{\"principal\":{\"id\":\"<redacted>\",\"arn\":\"arn:aws:sts::<redacted>:assumed-role/<redacted>/<redacted>\"},\"action\":\"iam:PassRole\",\"resource\":\"arn:aws:iam::<redacted>:role/<redacted>\",\"conditions\":{\"items\":[{\"key\":\"aws:Region\",\"values\":{\"items\":[{\"value\":\"eu-central-1\"}]}},{\"key\":\"aws:Service\",\"values\":{\"items\":[{\"value\":\"ec2\"}]}},{\"key\":\"aws:Resource\",\"values\":{\"items\":[{\"value\":\"role/<redacted>\"}]}},{\"key\":\"iam:RoleName\",\"values\":{\"items\":[{\"value\":\"<redacted>\"}]}},{\"key\":\"aws:Type\",\"values\":{\"items\":[{\"value\":\"role\"}]}},{\"key\":\"aws:Account\",\"values\":{\"items\":[{\"value\":\"<redacted>\"}]}},{\"key\":\"aws:ARN\",\"values\":{\"items\":[{\"value\":\"arn:aws:iam::<redacted>:role/<redacted>\"}]}}]}}}"
}
What am I missing?

The IAM principal (typically an IAM role) associated with instance A needs permission to pass the IAM role associated with your chosen profile to the AWS EC2 service so that instance B can be launched with that chosen profile/role.
The reason that this permission is required is to prevent one role from launching compute with another role that confers elevated permissions (this is called 'privilege escalation').
Add something like the following to the policies associated with the IAM role that instance A was launched with:
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:::your-account:role/your-role"
}

Related

How to solve this? AWS updateAutoScalingGroup - error: AccessDenied: You are not authorized to use launch template

(Solved)
I missed this mention on the aws user guide You can use the AmazonEC2FullAccess policy to give users complete access to work with Amazon EC2 Auto Scaling resources, launch templates, and other EC2 resources in their AWS account
Now I added permissions as same as on the AmazonEC2FullAccess policy on my custom policy, and the lambda is working well.
The AmazonEC2FullAccess has full permissions of CloudWatch, EC2, EC2 Auto Scaling, ELB, ELB v2, and limited IAM write permission.
#Marcin _ Thanks! your comment made me check this part.
I'm trying to update the ASG with 'updateAutoScalingGroup' API on lambda.
But this error "AccessDenied: You are not authorized to use launch template" is blocking me...
At the first time, I applied only related permissions on the IAM policy depend on the document, but now I allowed full permissions of EC2 and Autoscaling on the policy to solve this issue.
But no lucks.
On google, I saw some posts that saying this is just an error, or issue from AMI existence.
But my AMI for the launch template is in the same account, same region...
Could you give me some hint or reference to solve this?
Thanks
const AWS = require('aws-sdk')
exports.handler = (event) => {
const autoscaling = new AWS.AutoScaling()
const { asgName, templateName, version } = event
const params = {
AutoScalingGroupName: asgName,
LaunchTemplate: {
LaunchTemplateName: templateName,
Version: version
},
MaxSize: 4,
MinSize: 1,
DesiredCapacity: 1
}
autoscaling.updateAutoScalingGroup(params, async (err, data)=> {
if(err) console.log("err---", err)
else console.log("data---", data)
})
};
Below was added after the comments from Marcin, John Rotenstein, samtoddler
Now the policy has full permission for EC2, EC2 Auto Scaling, EC2 Image Builder, Auto Scaling, and some permissions on CloudWatch Logs. But no lucks yet.
The AMI is in the same account, same region. And I added the account number on the 'Modify Image Permissions' on it. (I don't know well on this but just tried.)
describeLaunchTemplates() shows the launchTemplate which I want to use.
CloudTrail shows 'RunInstances' and 'UpdateAutoScalingGroup' events. 'RunInstances' returned "errorCode": "Client.UnauthorizedOperation", and 'UpdateAutoScalingGroup' returned "errorCode": "AccessDenied", "errorMessage": "An unknown error occurred"
Without LaunchTemplate part, API is working well. (I tried update the min and max count only, and it succeed.)
Even I changed AMI as public, it's not working for this.
Now I'm trying to search about launch template and AMI related configuration..
Unfortunately, the errors provided by AWS in some cases are very unclear and could mislead.
Besides checking that you have the proper rights, this error is also returned when you are trying to create an autoscaling group with an invalid AMI or one that doesn't exist.
Actually, problem is your EC2 instance is having an IAM Role which you are not authorised to use it. Add below policy to lambda or whatever role or IAM user you using to pass the role that is attached to EC2 instance. Once that is done it will start working.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"iam:GetRole",
"iam:PassRole"
],
"Resource": "arn:aws:iam::account-id:role/EC2-roles-for-XYZ-*"
}]
}

How to use instance profile credentials available on running ec2 instance?

I want to create tags from within the running ec2 instance, for that I need credentials and I wanted to use the credentials available at curl -s http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance. I set access key, secret key and session token as env variables from the above url . Now I tried
aws ec2 create-tags --resources i-instanceid --tags Key=Test,Value=Testing --region us-east-1
its giving me the following error
An error occurred (UnauthorizedOperation) when calling the CreateTags
operation: You are not authorized to perform this operation. Encoded
authorization failure message
You can use these credentials by invoking aws cli without any parameters related to credentials, it will try to pick up the creds from the instance profile. Your problem is not that you do not have the credentials but that you do not have permission to invoke CreateTags operation. As the error message says it is an authorization problem not an authentication one. You need to change the instance profile policy and include the capability to change instance tags.
More here:
https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html
Check if your role allows you to create, list, delete tags on EC2 or if you require a custom policy attached with this role to allow these actions.
In summary, you should have:
{
"Effect": "Allow",
"Action": [
"ec2:CreateTags",
"ec2:DeleteTags"
]
}

Find role being used on server from AWS CLI

I'm on an EC2 instance that has an IAM role attached to it, and would like to be able to verify that I am indeed using this role from the AWS CLI.
I'm imagining being able to call something like this (but can't find anything like it in the CLI docs):
$ aws get-current-role-details
Does this functionality exist?
Use the AWS STS command get-caller-identity.
Returns details about the IAM identity whose credentials are used to call the API.
$ aws sts get-caller-identity
{
"UserId": "AIDAxxx",
"Account": "xxx",
"Arn": "arn:aws:iam::xxx:user/Tyrone321"
}
You can then take the role name, and query IAM for the role details using both iam list-role-policies for inline policies and iam-list-attached-role-policies for attached managed policies (thanks to #Dimitry K for the callout).
$ aws iam list-attached-role-policies --role-name Tyrone321
{
"AttachedPolicies": [
{
"PolicyName": "SomePolicy",
"PolicyArn": "arn:aws:iam::aws:policy/xxx"
},
{
"PolicyName": "AnotherPolicy",
"PolicyArn": "arn:aws:iam::aws:policy/xxx"
} ]
}
To get the actual IAM permissions, use aws iam get-policy to get the default policy version ID, and then aws iam get-policy-version with the version ID to retrieve the actual policy statements.
If the IAM principal is a user, the commands are aws iam list-attached-user-policies and aws iam get-user-policy.
See the AWS IAM CLI reference for more information.
There is a more simple and elegant way to get the current role details.
$ curl http://169.254.169.254/latest/meta-data/iam/info
{
"Code" : "Success",
"LastUpdated" : "2019-05-08T13:15:52Z",
"InstanceProfileArn" : "arn:aws:iam::xxxxxxxxxxxx:instance-profile/rolename",
"InstanceProfileId" : "AIPAIFNV5UU4JJLAXXXXX"
}
In InstanceProfileArn you can see your role name
Unfortunately, there is not a simple way to get that information. You'll need to get there through the following path:
Step 1. Get the current EC2 instance ID from the instance metadata.
curl -s http://169.254.169.254/latest/meta-data/instance-id
You may need the current region as well.
curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone/ | sed 's/\(.*\)[a-z]/\1/'
Step 2. Get the ID of the IAM Instance Profile attached to your EC2 instance.
aws ec2 describe-instances \
--region us-east-1 \
--instance-id i-12345678 \
--query 'Reservations[0].Instances[0].IamInstanceProfile.Id'
Remember to substitute the EC2 instance ID and region as required.
Step 3. Get the IAM instance profile roles.
aws iam list-instance-profiles \
--query "InstanceProfiles[?InstanceProfileId=='ABCDEFG'].Roles"
Remember to substitute the IAM instance profile ID.
Notes:
An IAM instance profile may have more than one IAM role associated with it. Usually it will be only one, but it could have more.

How to give ec2 instance access to s3 using boto3

By googling, I found this tutorial on accessing S3 from EC2 instance without credential file. I followed its instructions and got the desired instance. The aws web console page looks like
However, I don't want to do it manually using the web console every time. How can I create such EC2 instances using boto3?
I tried
s = boto3.Session(profile_name='dev', region_name='us-east-1')
ec2 = s.resource('ec2')
rc = ec2.create_instances(ImageId='ami-0e297018',
InstanceType='t2.nano',
MinCount=1,
MaxCount=1,
KeyName='my-key',
IamInstanceProfile={'Name': 'harness-worker'},
)
where harness-worker is the IAM role with access to S3, but nothing else.
It is also used in the first approach with the aws web console tutorial.
Then I got error saying
ClientError: An error occurred (UnauthorizedOperation) when calling
the RunInstances operation: You are not authorized to perform this
operation.
Did I do something obviously wrong?
The dev profile has AmazonEC2FullAccess. Without the line IamInstanceProfile={'Name': 'harness-worker'},, create_instances is able to create instance.
To assign an IAMProfile to an instance, AmazonEC2FullAccess is not sufficient. In addition, you need the following privilege to pass the role to the instance.
See: Granting an IAM User Permission to Pass an IAM Role to an Instance
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*"
}
First you can give full IAM access to your dev profile and see it works. Then remove full IAM access and give only iam:PassRole and try again.
This has nothing to do with the role you are trying to assign the new EC2 instance. The Python script you are running doesn't have the RunInstances permission.

Cloudwatch permissions to running instance with no IAM role

I've been reading up on configuring cloudwatch log service, however the docs say that you must attatch a permission to the IAM role of your instance. If I already have an instance running that doesn't have an IAM role attached, what options do I have as far as configuring this service?
You can clone your current instance into a new EC2 instance that has an IAM instance profile (role) assigned.
Stop your EC2 instance.
Create an AMI image of your EC2 instance.
Launch a new EC2 instance from your AMI image, this time assigning an IAM role.
If the instance was not launched without an IAM role, then:
Create a policy (not an inline policy) as specified in the document
Add a test IAM user and attach the policy to the test_user
From the IAM dashboard, download or copy the test_user security credentials (key and secret)
On your instance, use aws configure and configure the credentials by using the key and secret
It may look complicated but it is not.