How do I access S3 buckets from my EC2 instance? - amazon-web-services

I'm new to AWS and was looking for a bucket policy to enable my ec2 servers access to the S3 buckets on the same account. I tried using this policy which enables the account:
{
"Sid": "AddCannedAcl",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::account-number:root"
},
"Action": "s3:",
"Resource": "arn:aws:s3:::my-bucket/"
} ] }
But I got access denied on the ec2.
I've found this:
http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html
#Principal
"Principal": { "Service": [ "ec2.amazonaws.com", "datapipeline.amazonaws.com" ] }
Which supposed to enable specifically the ec2. But when editing the policy I get "We encountered an internal error. Please try again." Any help is appreciated.

First thing to note is that a Linux user (e.g. root above) is not an IAM/AWS user. An IAM user can be created and authenticated through an ID and private key. (And I assume you'll want to avoid using your root account for any such purposes)
When you go to the S3 manager, you should be able to click on the bucket and then edit the permissions. From there, you should be able to use the AWS policy generator. There are numerous sample policies online as well.
Best practice is to add permissions to a group of users, not just one user. At first, you may find that you are not providing overall permissions that are required, so it is coming back with an error.
You can follow the directions here:
https://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html

Related

Grant access to Amazon S3 bucket only to one IAM User

I wish to have a bucket that only one IAM user could access using the AWS Console, list its content and access object files inside it.
So, I have created the IAM user, the bucket itself, and later:
bucket policy as follow:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "statement1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::0000000:user/dave"
},
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::testbucket1234"
},
{
"Sid": "statement2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::0000000:user/dave"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::testbucket1234/*"
}
]
}
And also a inline policy attached to my user's group, as follow:
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:*Object",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::testbucket1234/*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
}
]
}
Now: I can list my buckets, access the desired bucket, list its content (so far so good). The problem is when I try to open one file object inside the bucket and I get "access denied" error. If I turn the object public, I can access it, but I can also access it using other IAM accounts, and that is not the intention. I want to access the bucket, list its contents and access objects only by usage of this specific IAM account. What am I doing wrong? How can I reach this goal? Thanks in advance.
By default, no IAM User can access any bucket. It is only by granting permissions to users that they can access resources.
However, many people tend to grant Amazon S3 permissions for all buckets, at least for Administrators. This then makes it difficult to remove permissions so that a bucket can only be accessed by one user. While it can be done with Deny policies, such policies are difficult to craft correctly.
For situations where specific data should only be accessed by one user, or a specific group of users (eg HR staff), I would recommend that you create a separate AWS Account and only grant permission to specific IAM Users or IAM Groups via a Bucket Policy (which works fine cross-account). This way, any generic policies that grant access to "all buckets" will not apply to buckets in this separate account.
Update: Accessing private objects
Expanding on what is mentioned in the comments below, a private object in Amazon S3 can be accessed by an authorized user. However, when accessing the object, it is necessary to identify who is accessing the object and their identity must be proved. This can be done in one of several ways:
In the Amazon S3 management console, use the Open command (in the Actions menu). This will open the object using a pre-signed URL that authorizes the access based upon the user who logged into the console. The same method is used for the Download option.
Using the AWS Command-Line Interface (CLI), you can download objects. The AWS CLI needs to be pre-configured with your IAM security credentials to prove your identity.
Programs using an AWS SDK can access S3 objects using their IAM security credentials. In fact, the AWS CLI is simply a Python program that uses the AWS SDK.
If you want to access the object via a URL, an application can generate an Amazon S3 pre-signed URLs. This URL includes the user's identity and a security signature that grants access to a private object for a limited period (eg 5 minutes). This method is commonly used when web applications want to grant access to a private object, such as a document or photo. The S3 management console actually uses this method when a user selects Actions/Open, so that the user can view a private object in their browser.

Cross-account S3 bucket permissions

I'm trying to grant access to S3 bucket to other account using S3 UI:
Permissions -> Access Control List -> Access for other AWS accounts
I know canonical id for account I want to grant permissions. It is 161 char code. When I'm trying to add It I'm getting next error:
I'm pretty sure I'm using the correct ID because it says says Canonical user ID (for Amazon S3)
What is wrong?
If you wish to grant bucket access to another AWS Account, I would recommend using a Bucket Policy. This allows the user(s) in the other account to use their normal credentials to access the bucket.
Here is a sample bucket policy that grants access to a specific user in another AWS account:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
],
"Principal": {
"AWS": [
"arn:aws:iam::ACCOUNT-ID:user/foo"
]
}
}
]
}
You are probably using the wrong id. Please have a look at this document to find out how to retrieve the one that you need here: AWS account identifiers - AWS General Reference
Having that said, in most cases it would be better to not use access control list but access S3 via cross-account roles instead. To learn more, please have a look at: Provide Cross-Account Access to Objects In S3 Buckets

AWS S3 - How to restrict an IAM user to just a single bucket?

I've been struggling with this for hours and cannot figure it out.
I've created a new user, duplicity, and I made a new bucket called bobs-house, and generated the following policy: (any numbers I'm not sure I should share are xxx'd out)
{
"Version": "2012-10-17",
"Id": "Policyxxx",
"Statement": [
{
"Sid": "Stmtxxx",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxx:user/duplicity"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::bobs-house/*"
}
]
}
I go to the policy simulator, and run some tests. Sure enough, it says I can do whatever I want as user duplicity, but only on bobs-house. If duplicity tries to do anything involving other buckets, it's denied. Great!
Now I fire up my FTP client and connect to s3.amazonaws.com (using Transmit's S3 protocol of course, not FTP protocol), using duplicity's IAM access key and secret key. I get "access denied." I can't figure out what I'm doing wrong. Any help would be appreciated!
EDIT:
Got it, thanks to John's answer below. I can use Transmit to connect and view only that bucket's contents, add files, etc. But duplicity (backup software) is complaining:
PermanentRedirect. The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint. bobs-house.s3.amazonaws.com
So I switch the formatting in duplicity's config to:
s3://bops-house.s3.amazonaws.com/test
And then I get this error:
The request signature we calculated does not match the signature you provided. Check your key and signing method.
My access key & secret key are definitely correct.
If you wish to give Amazon S3 permissions to a specific user, it is better to create the policy against the IAM User themselves, rather than the bucket policy.
A bucket policy is good for assigning universal permissions, while a policy in IAM is good for giving permissions to specific Users or Groups of users.
See: User Policy Examples

S3 IAM Policy to access other account

We need to create an IAM user that is allowed to access buckets in our client's S3 accounts (provided that they have allowed us access to those buckets as well).
We have created an IAM user in our account with the following inline policy:
{
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:PutObjectAcl",
"s3:ListMultipartUploadParts",
"s3:PutObject",
"s3:ListBucketMultipartUploads",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::*"
}
]
}
In addition to this, we will request that our clients use the following policy and apply it to their relevant bucket:
{
"Version": "2008-10-17",
"Id": "Policy1416999097026",
"Statement": [
{
"Sid": "Stmt1416998971331",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::229569340673:user/our-iam-user"
},
"Action": [
"s3:AbortMultipartUpload",
"s3:PutObjectAcl",
"s3:ListMultipartUploadParts",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::client-bucket-name/*"
},
{
"Sid": "Stmt1416999025675",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::229569340673:user/our-iam-user"
},
"Action": [
"s3:ListBucketMultipartUploads",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::client-bucket-name"
}
]
}
Whilst this all seems to work fine, the one major issue that we have discovered is our own internal inline policy seems to give full access to our-iam-user to all of our own internal buckets.
Have we mis-configured something, or are we missing something else obvious here?
According to AWS support, this is not the right way to approach the problem:
https://forums.aws.amazon.com/message.jspa?messageID=618606
I am copying the answer from them here.
AWS:
The policy you're using with your IAM user grants access to any Amazon S3 bucket. In this case this will include any S3 bucket in your account and any bucket in any other account, where the account owner has granted your user access. You'll want to be more specific with the policy of your IAM user. For example, the following policy will limit your IAM user access to a single bucket.
You can also grant access to an array of buckets, if the user requires access to more than one.
Me
Unfortunately, we don't know beforehand all of our client's bucket names when we create the inline policy. As we get more and more clients to our service, it would be impractical to keep adding new client bucket names to the inline policy.
I guess another option is to create a new AWS account used solely for the above purpose - i.e. this account will not itself own anything, and will only ever be used for uploading to client buckets.
Is this acceptable, or are there any other alternatives options open to us?
AWS
Having a separate AWS account would provide clear security boundaries. Keep in mind that if you ever create a bucket in that other account, the user would inherit access to any bucket if you grant access to "arn:aws:s3:::*".
Another approach would be to use blacklisting (note whitelisting as suggested above is a better practice).
As you can see, the 2nd statement explicitly denies access to an array of buckets. This will override the allow in the first statment. The disadvantage here is that by default the user will inherit access to any new bucket. Therefore, you'd need to be diligent about adding new buckets to the blacklist. Either approach will require you to maintain changes to the policy. Therefore, I recommend my previous policy (aka whitelisting) where you only grant access to the S3 buckets that the user requires.
Conclusion
For our purposes, the white listing/blacklisting approach is not acceptable because we don't know before all the buckets that will be supplied by our clients. In the end, we went the route of creating a new AWS account with a single user, and that user does not have of its own s3 buckets
The policy you grant to your internal user gives this user access to all S3 bucket for the API listed (the first policy in your question). This is unnecessary as your client's bucket policies will grant your user required privileges to access to client's bucket.
To solve your problem, remove the user policy - or - explicitly your client's bucket in the list of allowed [Resources] instead of using "*"

How can I share Amazon S3 content with MFA protection via IAM?

I like to share my Amazon S3 private content with members. Initially I did that by creating an AWS Identity and Access Management (IAM) user account, but people started to pass these credentials around.
So I found I can hand out a AWS Multi-Factor Authentication (MFA) token/fob to each user account created via IAM. However, testing reveals that I can still download files, S3 will not ask for the 6-digits number generated by the token/fob.
What am I missing here? Or if I went down the wrong path, please suggest a way to detect/prevent members sharing these credentials. Thanks
You need to specifically Configure MFA-Protected API Access for the resource you are trying to protect (i.e. the S3 content in your case), see the introductory blog post about MFA-Protected API Access for an overview how this feature works.
Fortunately there are a few examples for Adding a Bucket Policy to Require MFA Authentication available - please read that section for details, but the first example addresses your use case already (the third one extends it by adding a condition to limit the duration for which the aws:MultiFactorAuthAge key is valid):
{
"Version": "2008-10-17",
"Id": "123",
"Statement": [
{
"Sid": "",
"Effect": "Deny",
"Principal": { "AWS": "*" },
"Action": "s3:**",
"Resource": "arn:aws:s3:::examplebucket/taxdocuments/*",
"Condition": { "Null": { "aws:MultiFactorAuthAge": true }}
}
]
}