AWS S3 Replication Fails Due to Bucket Policy - amazon-web-services

We've been using a template for bucket policies that worked well until we tried to enable replication. The first thing in the policy is a deny statement that has exceptions for a specific vpce, and three IP network ranges. The deny statement is followed by some allow statements. This worked well. When we tried to configure replication, we get replication failed status for any object added or updated. So we added the IAM role created for this replication to the deny exceptions and also to the allow statements as a principal. This still cause replication failure. We know the issue is the policy because removing the policy results in replication completing normally. Here's the format of the deny statement...
"Statement": [
{
"Sid": "Stmt1587152999999",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"<Bucket ARN>",
"<Bucket ARN>/*"
],
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"x.x.x.x/xx",
"x.x.x.x/xx",
"x.x.x.x/xx"
]
},
"StringNotEquals": {
"aws:SourceVpce": "<VPCE ID>"
},
"ArnNotEquals": {
"aws:SourceArn": "<IAM role created for replication>"
}
}
},
Is the source arn of the IAM role used for replication the correct way to exclude it from the deny statement? Is there another approach to limit access while still allowing replication?

Deny statements are always difficult. They often end up denying more than expected.
I think the above statement is saying:
Access to this S3 bucket is denied if:
You aren't coming from one of these IP addresses, AND
You aren't coming through that VPC Endpoint, AND
You aren't using that IAM Role
This should effectively be saying "Don't deny if any of the above are True" (that is, they are using one of the IPs, OR the VPC Endpoint OR the IAM Role).
See: Creating a condition with multiple keys or values - AWS Identity and Access Management
This means that your statement should be correct, but you report having problems. I can't see an immediate problem with what you are doing, but try starting by only having the IAM Role condition, test whether it is working correctly, then add the other conditions one-at-a-time to identify the cause of the conflict.

The issue with my policy was in the Role ARN.
I used "aws:SourceArn" but should have used " "aws:PrincipalArn"
I'm pretty sure I got SourceArn from the policy generator. I ended up opening a case and after a few iterations with support I got the "aws:PrincipalArn". That worked!

Related

AWS policy StringNotLike not working as expected

I am trying to set up a policy using StringNotLike, to prevent access to a particular bucket (named secbucket) and allows all other buckets. However whatever I put in the condition, it still allows access for all buckets.
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": "arn:aws:s3:::*",
"Condition": {
"StringNotLike": {
"s3:prefix": [
"secbucket",
"secbucket/home",
"secbucket/home/*"
]
}
}
}
To clarify if I understand the StringNotLike with the Resource condition: If the s3:prefix does not match the conditions, it will allow access.
I am not sure what wrong with this policy. Please let me know what is wrong with this policy. Many thanks.
The Bucket name is not part of the S3 prefix.
If you wish to create a policy that references the bucket name, you will need to do it as part of the ARN, eg:
"Resource": "arn:aws:s3:::secbucket"
It appears your desire is to grant access to ALL buckets except secbucket. This can be done in two steps:
Grant access to all buckets by using an Allow statement
Deny access to secbucket by using a Deny statement
If you wish to secure secbucket from most of your users, an alternative method is to put secbucket in a different AWS Account and then use a Bucket Policy to only grant access to specific IAM entities. This is sometimes easier than denying access to lots of entities.

AWS IAM policy permissions clash issue

I have tried to create a policy that will prevent the deregistration of AMIs, unless the AMIs have the appropriate "delete this" tag. When I run the IAM policy simulator, the policy doesn't seem to work and the AMIs are allowed to be deregistered, because users already are associated with policies that are more permissive than my new policy.
Is it possible to make my custom policy take priority over other policies? Or do I have to create new policies that explicitly do not have the Deregister AMI permission?
The following IAM policy will deny deregistration of an AMI (just replace with your concrete resource ARN) when said AMI does not have the "delete" tag or that tag's value is not "yes". This works regardless of any possible Allow permissions that the calling identity might have.
This is because permission statements with "Deny" action always take precedence over any Allow permissions.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "ec2:DeregisterImage",
"Resource": "arn:aws:ec2:*::image/*",
"Condition": {
"StringNotEquals": {
"aws:ResourceTag/delete": "yes"
}
}
}
]
}
Read this page for the detailed algorithm IAM uses to evaluate permissions: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html

What is the purpose of 'resource' in an AWS resource policy?

As per title, what is the purpose of having the resource field when defining a resource policy when the resource policy is already going to be applied to a particular resource.
For example, in this aws tutorial, the following policy is defined an attached to a queue. What is the purpose of the resource field?
{
"Version": "2008-10-17",
"Id": "example-ID",
"Statement": [
{
"Sid": "example-statement-ID",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"SQS:SendMessage"
],
"Resource": "arn:aws:sqs:REGION:ACCOUNT-ID:QUEUENAMEHERE",
"Condition": {
"ArnLike": { "aws:SourceArn": "arn:aws:s3:*:*:bucket-name" }
}
}
]
}
S3 is a good example of where you need to include the resource statement in the policy. Let's say you want to have a upload location on S3 bucket.
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"Upload",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:PutObject"],
"Resource":["arn:aws:s3:::examplebucket/uploads/*"]
}
]
}
In these cases you really don't want to default the Resource to the bucket as it could accidentally cause global access. It is better to make sure the user clearly understands what access is being allowed or denied.
But why make it required for resource policies where it isn't need like SQS? For this let's dive into how resource policies are used.
You can grant access to a resources 2 ways:
Identity based policies for IAM principals (users and roles).
Resource based policies
The important part to understand is how are resource polices used? Resource policies are actually used by IAM in the policy evaluation logic for authorization. To put it another way, resources are not responsible for the actual authorization that is left to IAM (Identity and Access Management).
Since IAM requires that every policy statement have a Resource or NotResource this means the service would need to add the resource when sending it to IAM if it was missing. So let us look at the implications from a design perspective of having the service add the resource if it is missing.
The service no longer would need to just verify the policy is correct.
If the resource is missing from the statement the service would need to update the policy before sending it to IAM.
There is now the potential for two different versions of a resource policy. The one the user created for editing and the one sent to IAM.
It increases the potential for user error and accidentally opening up access by attaching a policy to the wrong resource. If we modify the policy statement in the question drop the resource and condition statement we have a pretty open policy. This could easily be attached to the wrong resource especially from the CLI or terraform.
{
"Sid": "example-statement-ID",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"*"
]
}
Note I answered this from a general design perspective based on my understanding of how AWS implements access management. How AWS implemented the system might be a little different but I doubt it because policy evaluation logic really needs to be optimized for performance so it's better do to that in in one service, IAM, instead of in each service.
Hope that helps.
Extra reading if you are interested in the details of the Policy Evaluation Logic.
You can deny access 6 ways:
Identity Policy
Resource policies
Organizational Polices if your account is part of an organization
IAM permission boundaries if set
Session Assumed Policy if used
Implicitly if there was no allow policy
Here is the complete IAM policy evaluation logic workflow.
There is a Policy as you defined.
Policy applied resource : A, I don't know where you will apply this.
The resource in the policy : B, arn:aws:sqs:REGION:ACCOUNT-ID:QUEUENAMEHERE
Once you apply the polity to some service like ec2 instance that is A, then the instance only can do SQS:SendMessage through the resource B. A and B are totally different.
If you want to restrict the permission for the resource A that shouldn't access to other resources but can only access to the defined resources, then you have to define the resource such as B in the policy.
Your policy is only valid for that resource B and this is not the resource what you applied A.

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/*).

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/*