SCP to deny all resources except certain resources in AWS Organization - amazon-web-services

I want to block all resources except EC2, RDS and global services in AWS Organization. Below is my SCP Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyAllOutsideEU",
"Effect": "Deny",
"NotAction": [
"iam:*",
"cloudfront:*",
"route53:*",
"route53domains:*",
"s3:GetAccountPublic*",
"s3:ListAllMyBuckets",
"s3:PutAccountPublic*",
"shield:*",
"sts:*",
"support:*",
"trustedadvisor:*",
"waf-regional:*",
"waf:*",
"wafv2:*",
"wellarchitected:*"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestedRegion": [
"ap-south-1"
]
},
"ArnNotLike": {
"aws:PrincipalARN": [
"arn:aws:iam::*:role/Role1AllowedToBypassThisSCP",
"arn:aws:iam::*:role/Role2AllowedToBypassThisSCP"
]
}
}
}
]
}
Using this policy, I'm not able to get full access to WAF. Below is WAF service access denied error screen shot.
Can any one please help me to achieve this?

What you are missing is ec2:DescribeRegions.
You already have all the access you want. If you try through aws cli you can do whatever you have allowed in the policy. However Web ACLs page in AWS console has a dropdown to load all AWS regions which uses the ec2:DescribeRegions api call and if you don't have it you can't open the page.
You have two options. Either add the missing permission to your policy. Or if you don't want to add that you can add region=ap-south-1 to your URL in the browser every time you navigate to WAF page.
Also I suggest you to look into arn:aws:iam::aws:policy/AWSWAFConsoleFullAccess. There are other permissions you might need. For example if you want to associate a web-acl to a Load Balancer you will need elasticloadbalancing:DescribeLoadBalancers and elasticloadbalancing:SetWebACL.

Related

Why does restricting `ssm:sendCommand` to a specific document via an IAM policy show access denied?

I'm trying to have an IAM user who can only use SSM Run Command with a specific Document.
If I have the following policy attached to the user, that user can indeed only successfully execute AWS-RunShellScript (which is an AWS managed) document on EC2 instances.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:DescribeDocument",
"ssm:DescribeDocumentParameters",
"ssm:DescribeDocumentPermission",
"ssm:GetCommandInvocation",
"ssm:GetDocument",
"ssm:ListCommandInvocations",
"ssm:ListCommands",
"ssm:ListDocumentMetadataHistory",
"ssm:ListDocuments",
"ssm:ListDocumentVersions"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ssm:SendCommand",
"Resource": "arn:aws:ssm:us-west-2:999999999999:document/AWS-RunShellScript"
}
]
}
However, if I replace the resource item in the policy with a custom document ARN that I created (e.g. arn:aws:ssm:us-west-2:999999999999:document/CustomDocument), I get "Access Denied"
It's not really clear in the documentation but to limit ssm:SendCommand, you must use the Resource field to specify both what document(s) the IAM user is allowed to run and what instance(s) you allow commands to be run on.
The user would see all instances when trying to run a command but will only be able to execute commands for the EC2 instance IDs specified in the IAM policy.
You can specify the policy to allow any instance like below if needs be or specify a limited list of instance IDs in line with the standard security advice of granting least privilege in IAM policies.
As to why the AWS managed document works, it's probably some internal magic 🤷‍♂️
This should work:
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Action":"ssm:SendCommand",
"Resource":[
"arn:aws:ec2:us-west-2:999999999999:instance/*",
"arn:aws:ssm:us-west-2:999999999999:document/AWS-RunShellScript"
]
}
]
}
Slightly similar unexpected behaviour (not really clear in the documentation either): if you define 2 blocks for the same action, they are considered by AWS as just one, eg:
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Action":"ssm:SendCommand",
"Resource":[
"arn:aws:ec2:us-west-2:999999999999:instance/i-1",
"arn:aws:ssm:us-west-2:999999999999:document/AWS-RunShellScript"
]
},
{
"Effect":"Allow",
"Action":"ssm:SendCommand",
"Resource":[
"arn:aws:ec2:us-west-2:999999999999:instance/i-2",
"arn:aws:ssm:us-west-2:999999999999:document/AWS-SecondDoc"
]
}
]
}
will allow you to connect to i-1 with both "AWS-RunShellScript" and "AWS-SecondDoc" (and same for i-2).

Hardening S3 bucket

We store RPMs required for our deployment in a S3 bucket, we are hosting a yum repo on the bucket to make it easier for updating RPMS.
Currently, our bucket is accessible publicly over the S3 endpoint (s3.amazonaws.com) and open to the world for access as we currently can’t pull down yum packages from a private S3 repo.
We need to harden the security of the Repo bucket to enable authentication based access to S3 over s3.amazonaws.com endpoint. Any suggestion towards it ? Thanks !
`{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Allow Access From QA, dev",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::XXXXXXX:root"
]
},
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::test-repo",
"arn:aws:s3:::test-repo/*"
],
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"X.X.X.X/32"
]
},
"StringNotEquals": {
"aws:sourceVpce": "vpce-xxxxxxx"
}
}
}
]
}
`
Rather than trying to specifically add an authentication layer take a look at adding a VPC endpoint to the VPC(s) that you want to be able to access your S3 bucket.
Once you have this in place (and added to the route tables) then you can update the bucket policy for your S3 bucket to add a condition to Deny all traffic not from the source VPC endpoint (aws:sourceVpce).
The advantage to this approach is that you will not need to make any changes to the servers themselves.
More documentation available here.

AWS IAM Policy grant permissions for some EC2 instances

I want to restrict access for a specific user to see just few EC2 instances. I created a new user in IAM Roles and I attached a new Policy to it. The content of that Policy is attached below. I tried to look over documentation and to do it myself like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": [
"arn:aws:ec2:eu-west-1:ACCOUNT_ID:instance/i-INSTANCE_ID1",
"arn:aws:ec2:eu-west-1:ACCOUNT_ID:instance/i-INSTANCE_ID2"
]
}
]
}
I placed my region,ACCOUNT_ID(the owner id, not of the new user created) and instance-id, but when I connect with that user and I go to list all Instances I got this An error occurred fetching instance data: You are not authorized to perform this operation..
After I placed the code in JSON editor, in Policy Review step I got this message:
This policy defines some actions, resources, or conditions that do not
provide permissions. To grant access, policies must have an action
that has an applicable resource or condition. For details, choose Show
remaining Learn more
The AWS documentation mention exactly the same configuration or these examples.
I assume you connect as that user in the console (but it would be the same with CLI) Here is what I think is happening:
To list all the instances, the console most probably calls the DescribeInstances API. As per the list of action/resources/tags that can be used in IAM policy, this API does not support the resource filter in IAM.
This means your user has no authorization to list instances and they will not be shown in the console. You can validate this theory by using the CLI to request the details of a specific instance id, if my hypothesis is correct, it will be authorized.
As DescribeInstances can not be restricted by resource or tags, I don't think it is possible to filter the instance list for a user.
To have the console working, you'll need to add the following statement in your IAM policy
"Statement": [
{ your existing statement },
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*"
}
]
Please report if I was right :-) The example you mentioned in your question shows exactly that : Resources = * on DescribeInstances and Resources specific InstanceId on other operations.
The previous answer is wrong, you can Conditionally allow access to ec2:DescribeInstances by tag names. It's an AWS best practice as well. Also explicitly deny access to the ec2:CreateTags and ec2:DeleteTags actions to prevent users from creating or deleting tags to take control of the instance.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:ResourceTag/UserName": "${aws:username}"
}
}
},
{
"Effect": "Deny",
"Action": [
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Resource": "*"
}
]
}
DescribeInstances action does not support condition.
https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html

AWS IAM grant user read access to specific VPC only

I have tried to limit access to a VPC without success. Maybe approaching the issue from the other side is a better idea, but I can't get that to work either.
I have tried:
Limit by tags as shown here:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:Describe*",
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:ResourceTag/client": "<client>"
}
}
}
]
}
Limit by VPC as suggested here:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1508450090000",
"Effect": "Allow",
"Action": [
"ec2:Describe*"
],
"Resource": [
"arn:aws:ec2:<region>:<account>:subnet/*"
],
"Condition": {
"StringEquals": {
"ec2:Vpc": "arn:aws:ec2:<region>:<account>:vpc/<vpc_id>"
}
}
}
]
}
Both policies result in not even listing any instances, see screenshot.
This seems to be a very obvious and commonly needed policy to me.
Any help is appreciated.
According to the documentation: http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_IAM.html#readonlyvpciam
The following policy grants users permission to list your VPCs and
their components. They can't create, update, or delete them.
{
"Version": "2012-10-17",
"Statement":[{
"Effect":"Allow",
"Action":["ec2:DescribeVpcs",
"ec2:DescribeSubnets",
"ec2:DescribeInternetGateways",
"ec2:DescribeEgressOnlyInternetGateways",
"ec2:DescribeVpcEndpoints",
"ec2:DescribeNatGateways",
"ec2:DescribeCustomerGateways",
"ec2:DescribeVpnGateways",
"ec2:DescribeVpnConnections",
"ec2:DescribeRouteTables",
"ec2:DescribeAddresses",
"ec2:DescribeSecurityGroups",
"ec2:DescribeNetworkAcls",
"ec2:DescribeDhcpOptions",
"ec2:DescribeTags",
"ec2:DescribeInstances"],
"Resource":"*"
}
]
}
Further, if you have multiple VPCs that you do not want them to even see, perhaps you should consider creating a sub-account with only the portion of your network that they should have visibility across:
Setup Consolidated Billing
As a first step, log into your AWS account and click the "Sign up for Consolidated Billing" button.
Create a new account
From a non-logged in browser, you will then want to sign up again to AWS again like this:
Give this new account the appropriate name for your client. Note the email address you signed up with.
Link the accounts
In your main account, head back to ConsolidatedBilling and click the Send a Request button. Provide the email address for your new sub-account.
You should receive an email to the email address for your new sub-account. Copy the activation link and paste it into your browser logged in to the sub-account.
Your accounts are now linked!
Create your clients VPC and enable the services that the client requires.
Next, you can create the VPC & services the client requires, and restrict their access via the policy above.
You cannot restrict Describe* calls in the manner you want.
Calls that create resources can be restricted (eg give permission to launch an instance in a particular VPC), but calls that list resources cannot be restricted.
If you require the ability to prevent certain users from listing resources, then you'll either need to build your own front-end that filters the information before presenting it to users, or use multiple AWS accounts since they are fully isolated from each other.

How to allow an EC2 instance access to its own tags from the OS

I need to create an IAM managed policy that allows a given EC2 instance to see its own tags from the OS (Linux). I've been able to do this by setting the policy as:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1473154086000",
"Effect": "Allow",
"Action": [
"ec2:DescribeTags"
],
"Resource": [
"*"
]
}
]
}
The above lets me run ec2-describe-tags from the instance just fine but sees all tags from all resources. I want to restrict it to only seeing its own tags. I've tried to use the EC2 instance ARN as the resource but that did not work. I've also tried using a condition of the IP of the instance; no luck. I'd really like to lock this down if possible; any help would be appreciated.
The action ec2:DescribeTags is not a "resource-level", so, you cannot limit at specific resource.
See: http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ec2-api-permissions.html#ec2-api-unsupported-resource-permissions