AWS SCPs and how to block access to certain resources - amazon-web-services

I want to block access to certain resources that I create as a base set up in new AWS account in my Organization. I want to do this for all users except Admins. The access only for admin part is solved with this design:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"ArnNotEquals": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/myadminrole",
"arn:aws:iam::*:role/aws-reserved/sso.amazonaws.com/sso-region/AWSReservedSSO_myrolename"
]
}
}
}
]
}
As you can see in the above role everything is denied for everyone except the admins, this not i want to do I want to block access to certain resources. The simplest way to do so is just to list the resources I want to block access to under "Resource". But this will resolve in manual work to keep this SCP up to date and this is something I try to avoid. So my second idea was to use tags and base the deny of access on them with a condition like this:
"Condition": {"ForAllValues:StringEquals": {"aws:TagKeys": ["mytagkey"]}}
But when I ran into this issue where some AWS services don't support authorisation based on tags, see link:
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html#:~:text=Yes-,AWS%20Lambda,Partial%C2%B2,-Amazon%20Lightsail
Does anyone know a good way to solve my issue? Or does I just have yo accept that I have to manually update my SCP?

After investigation both from me and AWS support this is not possible at the moment. So the answer is that you need to manually update your SCPs.

Related

IAM Policy to give readonly access to a specific DBCluster

I am trying to create an IAM Managed Policy to assign to QA users that will give them readonly access to a specific DBCluster, the QA cluster.
So far I haven't been able to limit the access to the specific cluster, I can only get it to work if the Resource tag is set to all
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"rds:Describe*",
"rds:ListTagsForResource"
],
"Resource": "*",
"Effect": "Allow",
"Sid": "DescribeQADatabase"
}
]
}
I've tried changing the Resource tag to my specific DBCluster ARN, but when I do that nothing shows in the RDS page in the AWS Console
Side question, if I look at the AWS Provided AmazonRDSReadOnlyAccess I see that it gives access to a bunch of other AWS Resources like ec2 instances. Is there a document/resource I can use that will basically tell me all the dependencies I will need if I want to give access to a specific resource?

S3 policy - listing only specific bucket for user [duplicate]

I've been able to generate a user policy that only gives access to a specific bucket, however after trying everything (including this post: Is there an S3 policy for limiting access to only see/access one bucket?).
The problem: I am unable to restrict the listing of the buckets down to just one bucket. For a variety of reasons, I do not want the listing to show any buckets other than the one specified.
I've tried a variety of policies, to no avail. Here's my latest policy JSON which is working as far as restricting operations, but not listing:
{
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Deny",
"Action": [
"s3:ListBucket"
],
"NotResource": [
"arn:aws:s3:::acgbu-acg",
"arn:aws:s3:::acgbu-acg/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::acgbu-acg",
"arn:aws:s3:::acgbu-acg/*"
]
}
]
}
Any help would be greatly appreciated. I'm beginning to wonder if it's even possible.
It is not currently possible to restrict the list of buckets to show only one bucket.
The AWS console relies on the ListAllMyBuckets action to get the list of buckets owned by the user, but the returned list can not be restricted by using an Amazon Resource Name (or ARN; the only ARN that's allowed for ListAllMyBuckets is arn:aws:s3:::*).
This limitation isn't clearly explained in the official AWS docs, but ListAllMyBuckets is a service level API call (it's also called GET Service in the REST API), not a bucket level API call and its associated ARN in the IAM policy refers to the S3 service an not to a specific bucket.
For possible workarounds, see this answer on StackOverflow:
The free "S3 Browser" (this works on my version 3-7-5) allows users with the proper permissions to "Add External Bucket" for the account, all they need to know is the name of the bucket. This allows them to "see" their bucket and the contents (and what ever abilities they've been given inside that bucket), they won't see any of the other buckets.
To make the bucket "play nice" with the S3 Browser behavior, I suggest the following IAM Policy for the User or Group:
{
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:GetBucketAcl"
],
"Resource": "arn:aws:s3:::acgbu-acg"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::acgbu-acg/*"
}
]
}
It's a work around, and it's okay if the user only needs to do it once. But if the buckets your user is accessing are changing around a lot then this work around isn't very practical.
I came here looking for how to restrict access to a bucket to one (or a list of) user(s). Maybe, post title is ambiguous ?
Anyway, it seems to have Google's favor, so let's enrich it a little :
If you need to restrict access to a bucket to some user(s), follow those steps :
First, get the IDs of the user you want to grant rights to.
This can be achieved using the awscli command aws iam list-users
Those IDs look like this : "AIDAIFKYAC9DNJXM2CRD", or "AIDAZ362UEKJCJMFFXCL"
Please, comment if it's available in the web console.
Once you got the ID(s) that must be given access, put a policy on the bucket you want to protect.
To do this with the web console :
-> Open S3 -> Open your bucket -> Select the "properties" tab -> Click on "Edit bucket policy"
To apply the policy using awscli, create a file with the policy's content, and put it on your bucket using this command :
aws s3api put-bucket-policy --bucket NAME_OF_YOUR_BUCKET --policy file:///path/to/policyFile.json
Of course, set YOUR_BUCKET_NAME and the file's path to your values, BUT DON'T remove the file:// prefix before your file's name
Warning : this deny policy will override the default "access to s3" a user could have. This means you can deny access to your OWN user with this. Use with caution !
I'm even afraid you could make a bucket fully innaccessible.
Out of curiosity, I tried accessing with our account's root user, which I didn't grant access to, and effectively couldn't.
Gotta ask this to support, and hopefully update this answer.
Anyway, I'm sure you'll be careful enough, so here's a sample policy.
Just replace the bucket's name with yours and the userId(s) with the one(s) you want to authorize to access.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::your-bucket-name",
"arn:aws:s3:::your-bucket-name/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"AIDAXAXAXAXAXAXAXAXAX",
"AIDAOXOXOXOXOXOOXOXOX",
"AIDAXIXIXIXIXIXIXIXIX"
]
}
}
}
]
}
For something more specific, or if you want to use roles instead of users, see this AWS post explaining in detail how to restrict access to a buckets
Hope this helps
The original poster was asking about a user policy. This would be attached to particular user(s) while others may have more leineint policies (or no policy) applied to them. A typical use case would be where you only want to restrict one user, whose credentials need to be shared outside the highest trust group. User policy is the way to go for that..

limiting aws ec2 users

Is it possible to create a sub-account or sub-user that is limited in what he can see and/or do in AWS based on tags for example?
I have tried using policies, but for instances this wouldn't work, because you can't limit it on a resource level.
This makes it that either they can controll and see everything, or nothing at all.
is there anything that I have missed?
The question scope just too wide. Please study the IAM Guides and play around with IAM policy generator condition.
Even playing around with ARN that allow wildcard, you still need to define some explicit prefix/suffix for those wildcard values. For EC2, you need to understand EC2 resource ARN and possible need to mix with "Condition" to add restriction.
Here is an example of using policy generator for a policies that only allow run,start and stop instance, and it restrict to EC2 with resource tag serverX. When you attach this policy to the user, they can only do the following task. You may need to add further condition to make sure the user doesn't see instances belongs to others, by enforcing the tag name creation yourself.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1462794515000",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:RunInstances",
"ec2:StartInstances",
"ec2:StopInstances"
],
"Condition": {
"StringLike": {
"ec2:ResourceTag/Name": "serverX"
}
},
"Resource": [
"arn:aws:ec2::1234567890:instance/*"
]
}
]
}
You can play around with AWS policy Simulator. Another good reference is AWS inline policies and managed policies

Proper access policy for Amazon Elastic Search Cluster

I've recently started using the new Amazon Elasticsearch Service and I can't seem to figure out the access policy I need so that I can only access the services from my EC2 instances that have a specific IAM role assigned to them.
Here's an example of the access policy I currently have assigned for the ES domain:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::[ACCOUNT_ID]:role/my_es_role",
]
},
"Action": "es:*",
"Resource": "arn:aws:es:us-east-1:[ACCOUNT_ID]:domain/[ES_DOMAIN]/*"
}
]
}
But as I said, this doesn't work. I log into the EC2 instance (which has the my_es_role role attached to it) and attempt to run a simple curl call on the "https://*.es.amazonaws.com" end point, I get the following error:
{"Message":"User: anonymous is not authorized to perform: es:ESHttpGet on resource: arn:aws:es:us-east-1:[ACCOUNT_ID]:domain/[ES_DOMAIN]/“}
Does anyone know what I have to change in the access policy in order for this to work?
You can lock access down to IAM-only, but how will you view Kibana in your browser? You could setup a proxy (see Gist and/or NPM module) or enable both IAM and IP-based access for viewing results.
I was able to get both IAM access IP-restricted access with the following Access Policy. Note the order is important: I could not get it working with the IP-based statement before the IAM statement.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxxxxxx:root"
},
"Action": "es:*",
"Resource": "arn:aws:es:us-west-2:xxxxxxxxxxxx:domain/my-elasticsearch-domain/*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:us-west-2:xxxxxxxxxxxx:domain/my-elasticsearch-domain/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"192.168.1.0",
"192.168.1.1"
]
}
}
}
]
}
My EC2 instance has an instance profile with the
arn:aws:iam::aws:policy/AmazonESFullAccess
policy. Logstash should sign requests using the logstash-output-amazon-es output plugin. Logstash running on my EC2 instance includes an output section like this:
output {
amazon_es {
hosts => ["ELASTICSEARCH_HOST"]
region => "AWS_REGION"
}
# If you need to do some testing & debugging, uncomment this line:
# stdout { codec => rubydebug }
}
I can access Kibana from the two IPs in the access policy (192.168.1.0 and 192.168.1.1).
According to AWS doc and as you (and I) just tested, you cannot restrict access to an AWS ES domain to a role/account/user/... and simply cURL it!
Standard clients, such as curl, cannot perform the request signing that is required of identity-based access policies. You must use an IP address-based access policy that allows anonymous access to successfully perform the instructions for this step.
(http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg-search.html)
So you have basically two solutions:
change your access policy and restrict it to IP(s), I think you cannot use private IP because your ES cluster does not seems to belong to your VPC (default or not). Please use the public IP
sign your request: http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-managedomains.html#es-managedomains-signing-service-requests
Signing your request is probably the best solution if you want to keep your access policy as is (which is more flexible than restricting to an IP), but it seems to be a bit more complex. I haven't tried so far and I cannot find any doc to help.
A bit late to the party, but I was able to deal with the exact same issue by adding signature to my requests.
If you use Python (like I do), you can use the following library to make it particularly easy to implement:
https://github.com/DavidMuller/aws-requests-auth
It worked perfectly for me.
You may either use resource based policy or identity based policy rather than IP based policy which is like hard coding the IP address.
But you need to use Signature version 4 to sign the request
For Java implementation please refer http://mytechbites.blogspot.in/2017/04/secure-amazon-elastic-search-service.html
You just need to full user name in elastic search policy.
In this case, you can get your full user name from the error message itself.
In my case:
"arn:aws:sts::[ACCOUNT_ID]:assumed-role/[LAMBDA_POLICY_NAME]/[LAMBDA_NAME]"
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:sts::xxxxxxxxxxxx:assumed-role/[lambda-role]/[full-lambda-name]"
]
},
"Action": "es:*",
"Resource": "arn:aws:es:[region]:xxxxxxxxxxxxx:domain/[elasticsearch-domain-name]/*"
}
]
}
Role ARN needs to be changed. it will be looks like "arn:aws:iam::[ACCOUNT_ID]:role/service-role/my_es_role"
I'm also trying to do this, and I got it working using the Allow access to the domain from specific IP(s) option with the Elastic IP of my EC2 instance (could also work using the instance's private IP, but I'm not too sure)

Permission to not allow IAM USER instance to create new instance

I want to create a power-user who has all the permission on the existing instance, but he isn't able to create a new instance.
Which permission would manage that that problem.
I am assuming "PowerUser" means all permissions, then you might want to try this permission
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
},
{
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "*"
}
]
}
The first statement gives full permission to your user (please adapt to your definition of "PowerUser"). The second statement explicitly denies to call the EC2 API RunInstances (http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html)
You can learn more about IAM Policies at http://docs.aws.amazon.com/IAM/latest/UserGuide/PoliciesOverview.html
I'm assuming you are discussing EC2 permissions. To prevent creation of new instances, the EC2 policy action associated with this is EC2:RunInstances.
To specify a single instance, I'd suggest using a condition block with a ec2:ResourceTag/. That gives more flexibility than hardcoding it in another manner. However, this will take some thought to prevent privilege escalation.