AWS IAM Policy applying restrictions to managed instances -- invalid ARN? - amazon-web-services

I'm facing some very weird issues when it comes to policies and managed instances. For example, one of my users is getting this error:
User: arn:aws:iam::708332864XX:user/XXXX is not authorized to perform: ssm:StartSession on resource: arn:aws:ssm:us-east-2:708332864XX:managed-instance/mi-055c2be5596fXXXXX
However, when looking at the policies, I don't have the ability to select a managed-instance as a resource:
If I try to just simply replace instance with managed-instance, then it says the ARN is invalid:
How would I give a user ssm:StartSession permission on managed instances then in this case? The following policy does nothing:
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"ssm:TerminateSession",
"ssm:StartSession"
],
"Resource": [
"arn:aws:ssm:us-east-2:708332864587:managed-instance/*"
]
}
Apparently this doesn't do anything:

Notice how the managed instance ARN is for the arn:aws:ssm namespace:
arn:aws:ssm:us-east-2:708332864XX:managed-instance/mi-055c2be5596fXXXXX
You are trying to add permission for the arn:aws:ec2 namespace, which is why it isn't working.

TLDR; I would suggest to use the instance ARN instead. I would also verify that your role have access to all documents or at least to SSM-SessionManagerRunShell.
The long explanation:
If you read about StartSession in https://docs.aws.amazon.com/service-authorization/latest/reference/list_awssystemsmanager.html you can learn that
for StartSession you have in the Resrouce column three different Resource types
Actions
Description
Access Level
Resource
StartSession
Grants permission to initiate a connection to a specified target for a Session Manager session
write
document instance task
Each of them has a different ARN structure:
document - arn:${Partition}:ssm:${Region}:${Account}:document/${DocumentName}
instance - arn:${Partition}:ec2:${Region}:${Account}:instance/${InstanceId}
task - arn:${Partition}:ecs:${Region}:${Account}:task/${TaskId}
You can put any other ARNs in the rule, but they will have no effect. But in one they or other the user need access to all the required resources.
For example (mentioned in the other answer as well): In your question you have
aws:arn:ec2:.....:managed-instance with quote: "If I try to just simply replace instance with managed-instance, then it says the ARN is invalid". Yes, because it is. You cannot just combine the parts of ARNs randomly. Valid ARNs are only the documented ones: https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html
When you describe your "managed instance" you should see in it an id of an EC2 instance. This is the only instance which does exist. The ssm "managed instance" is a structure which stores only the ssm-related data for that particular EC2 instance.
`
If you read the example policy in the AWS documentation for StartSession you see there:
https://docs.aws.amazon.com/systems-manager/latest/userguide/getting-started-restrict-access-quickstart.html
So you you need to figure out how to get the ec2 instance id from the managed instance id like for example with
https://docs.aws.amazon.com/cli/latest/reference/ssm/describe-instance-information.html
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:StartSession"
],
"Resource": [
"arn:aws:ec2:region:987654321098:instance/i-02573cafcfEXAMPLE",
"arn:aws:ssm:region:account-id:document/SSM-SessionManagerRunShell"
],
"Condition": {
"BoolIfExists": {
"ssm:SessionDocumentAccessCheck": "true"
}
}
},
--cut--
Keep in mind that in AWS you may not be able to limit access per resource level for all services. That's especially for newer services. Or you may not be able to do it easily. For example you can create a lambda function which will start your ec2 instance and will create a policy for it (I don't say that you should do it that way, but it is possible).
Sometimes you can use conditions or you can use PassRole/AssumeRole mechanism to allow access to the resource by a mechanism which is outside of the IAM service. You may need to be creative and/or sometimes compromise.

Related

AWS IAM: How does the condition context key "aws:RequestTag" work?

I have an EC2 instance with a role attached to it. My goal is to provide full access to AWS service (Lambda for example) but only on certain resources (Tag based). I found that aws:RequestTag was the way to do it.
Below is the IAM policy attached to the role.
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1614664562621",
"Action": "lambda:*",
"Effect": "Allow",
"Resource": "*",
"Condition": {
"StringLike": {
"aws:ResourceTag/app": "prod"
}
}
}
]
}
I added the tags app:prod on the required lambda functions but however when I try to list the lambda I get an AccessDeniedException error. Below is the error message
An error occurred (AccessDeniedException) when calling the
ListFunctions operation: User:
arn:aws:sts::123456789:assumed-role/iam-role-name/i-01abcd456abcd is
not authorized to perform: lambda:ListFunctions on resource: *
How to make the aws:RequestTag work? Where am I going wrong?
Similar question below: (That solution didn't work for me)
aws:RequestTag on s3 bucket is not working (while assuming a role)
You probably want to use aws:ResourceTag instead in your condition and tag the resources (i.e. Lambda functions) that this policy should permit access to.
aws:RequestTag is used to control which tags can be carried in an AWS API call such as for adding/editing/removing a resource tag on a resource or adding session tags on a session (via an sts:TagSession call). They are not meant to protect access to resources having a specific tag.
Also, adding the tag on your role does not mean that any caller identity (i.e. assumed session role) will then have this tag as a request/session tag. And consequently, it will not control any authorization/access to resources with that tag. The IAM role that you tagged simply is another AWS resource with a resource tag applied to it now.
Additionally, you couldn't even control session tags when EC2 assumes your role in the EC2 instance, so you cannot control session/request tags for your EC2 instance.
EDIT: In your particular example with lambda:ListFunctions, though, which is not a resource-specific action, you cannot control/filter the list by Lambda functions having a specific resource tag allowed by the policy of the API caller.
When working with multiple environments/stages, having multiple AWS accounts (one per environment/stage) is actually best practice. You can then even use AWS Organizations for consolidated billing, etc. if you don't already use multiple AWS accounts.

Use AWS EC2 tag to determine S3 access policy

I have multiple AWS EC2 instances that have unique name tags of the form ***-manager (three unique characters then -manager).
I have several S3 buckets (and sub-folders in them) with similar 3-character id's in their names that I need to restrict access to depending on which EC2 is asking.
How could I write a single AWS policy to attach to every EC2 that would do the following:
The bucket docker.***.mysite.com should only be accessible by the EC2 whose name tag has value ***-manager. Action is anything, i.e. *.
The folder downloads.mysite.com/***/ should only be accessible by the EC2 whose name tag has value ***-manager. The action is ListBucket and GetObject with a prefix restriction.
The folder downloads.mysite.com/common/ should be accessible by any EC2
No EC2 should have access to the root downloads.mysite.com/ or know anything about it (i.e., can't do any S3 action outside of the common and its *** subfolder.
NOTE: If it's not easy/possible to extract the 3-letter id from the EC2 name tag to "pass" to the Resource part of the policy I can easily add a new tag to each EC2 that just has the *** as its value - but still have to "pass" that somehow to the Resource in the policy definition.
I don't think it will be possible to create one policy for multiple situations.
The closest method would be to use IAM Policy Elements: Variables - AWS Identity and Access Management, but that does not allow use of an arbitrary value nor can it be used to retrieve a tag from an EC2 instance.
I think you'll need to create separate Roles for each EC2 instance that refer to the specific S3 buckets.
There seems to be no way how to do this because IAM S3 policies can't look back for the "caller tags".
What can be done though is lookup the tags of the IAM role assigned to the EC2 instance. Unfortunately the relevant condition on GetObject action is s3:ExistingObjectTag/<key>, which works on the S3 object rather than on the S3 bucket itself.
A simplified policy using the above would look like:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowListBucket",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::<S3_BUCKET_NAME>"
]
},
{
"Sid": "AllowROcheckTag",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::<S3_BUCKET_NAME>/*",
"Condition": {
"StringEquals": {
"s3:ExistingObjectTag/<TAG_ON_S3_OBJECT>": "aws:RequestTag/<TAG_ON_IAM_ROLE_ASSIGNED_TO_EC2>}"
}
}
}
]
}
In the above case it would be the IAM role assigned to the EC2 instance and its tags driving the access to the objects in the S3 bucket.
Details about allowed conditions for specific S3 action is here

IAM Policy using Condition ec2:ResourceTag not working

I have n x EC2 instances that I wish to limit ec2 actions to instances with the same key/value tag (I.E. platform=dev).
I'm looking at doing this using an IAM Policy attached to the group their default IAM user is in.
Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:ResourceTag/tag:platform": "dev"
}
}
}
]}
I set this up as per the online AWS docs: Example Policies for Working With the AWS CLI or an AWS SDK
I check it in the Policy Simulator and it works as expected (pass in a dev and it's allowed, otherwise denied).
Then on one of the servers with the tag key/pair of platform=dev, I run aws ec2 describe-instances I get the response:
An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.
but if I remove the Condition it works. I don't understand what I'm doing wrong. Any help would be gratefully received!
The problem is that not every API Action & Resource will accept the ec2:ResourceTag/tag in the condition.
I think you're probably granting overly-broad permissions (Action: ec2:*), so figure out what actions your instances will need do, and then decide how to restrict them.
The list of actions, resources and conditions keys can be found at Supported Resource-Level Permissions for Amazon EC2 API Actions.
I have ran into this issue before, it had something to do with combining wildcards and conditions. What solved it for us was being more explicit on the action (e.g ["ec2:DescribeInstances"]), and on the resource as well (arn:aws:ec2:region:accountid:instance/*).

OpsWorks Role to Start Instance

I am not able to start an OpsWorks instance after I have created the Instance within an OpsWorks Layer, which is part of an OpsWorks Stack. The error that I get after attempting to start the 24/7 instance is the following:
An error occurred while starting the instance java-app1
OpsWorks failed to obtain the necessary credentials to start the instance on your behalf. Please try again after waiting a minute. If this error persists, please check the permissions of the stack IAM role.
The error indicates that I don't have my permissions set correctly for the IAM Role of my Stack. I have created an OpsWorks Stack that contains a reference to a Role ARN that has the AWSOpsWorksFullAccess and AWSOpsWorksRole policies set for the Role's permissions. I would have thought one of those two policies would be enough.
I can create a OpsWorks Layer within that Stack, and create an OpsWorks instance as well. The created instance uses the DefaultInstanceProfileArn of the Stack. In my case, that ARN references a Role that contains the following policies:
AmazonEC2FullAccess
AWSOpsWorksFullAccess
AWSOpsWorksRole
AmazonS3FullAccess
I know that the policies that I have applied are very broad, but at this point I'm just trying to get an OpsWorks instance to start. What policy needs to be applied in order for OpsWorks to have the correct permissions to start an instance within my Stack?
This is a bit late :-)
I had that issue recently.
The roles that are attached are:
AmazonEC2FullAccess
AWSOpsWorksFullAccess
AWSOpsWorksCMServiceRole
This gives me create, start, stop and delete.
This confused me the most. Passing this mountant brings a lot of sights.
Open stack-setting, you will find your current IAM ROLE
Follow the document below to attach an inline policy.
https://docs.aws.amazon.com/opsworks/latest/userguide/opsworks-security-servicerole.html
If you create a custom service role, you must ensure that it grants all the permissions that AWS OpsWorks Stacks needs to manage your stack. The following JSON sample is the policy statement for the standard service role; a custom service role should include at least the following permissions in its policy statement.
{
"Version": "2008-10-17",
"Statement": [
{
"Action": [
"ec2:*",
"iam:PassRole",
"cloudwatch:GetMetricStatistics",
"cloudwatch:DescribeAlarms",
"ecs:*",
"elasticloadbalancing:*",
"rds:*"
],
"Effect": "Allow",
"Resource": [
"*"
],
"Condition": {
"StringEquals": {
"iam:PassedToService": "ec2.amazonaws.com"
}
}
}
]
}
A bit late, but the easiest way to solve this if you are just trying out opsworks is to create a service role with EC2 full access.
This should allow for the creation of the stack

IAM Policy isn't allowing EC2 access

I have a policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1429817158000",
"Effect": "Allow",
"Action": [
"ec2:*"
],
"Resource": [
"arn:aws:ec2:*"
]
}
]
}
That is attached to a group. That group has one user. When I log in to myloginthing.signin.aws.amazon.com with that user's credentials I can't do anything related to EC2. It gives me messages such as "You are not authorized to describe Running Instances" for every action on the page.
the IAM Policy Simulator tells me any action is denied because
Implicitly denied (no matching statements found).
What am I missing?
This actually took me a while to figure out.
It turns out that you have to match each action (in your example, ec2:*) with a set of allowable resources (in your example, arn:aws:ec2:*).
The problem is that not every action has the same set of allowable resources - so while you can use a number of different resources for RunInstances, DescribeInstances ONLY supports *.
The whole list is available here
(Note: Link is posted because a) the list is very large, and b) it will probably change significantly over time.
It's actually fine to use ec2:* as Allow Action, but "arn:aws:ec2:*" is an invalid Amazon Resource Name.
Replace "arn:aws:ec2:*" with "arn:aws:ec2:::*" or just "*" should work.
See Amazon Resource Names (ARNs) and AWS Service Namespaces
You have to fill out all Resources:
arn:aws:ec2:*::image/*
arn:aws:ec2:*::snapshot/*
arn:aws:ec2:*:*:subnet/*
arn:aws:ec2:*:*:network-interface/*
arn:aws:ec2:*:*:security-group/*
arn:aws:ec2:*:*:volume/*
arn:aws:ec2:*:*:instance/*
arn:aws:ec2:*:*:network-interface/*
arn:aws:ec2:*:*:key-pair/*