I have my video files stored in s3 bucket.
My files are downloadable using a plugin called Video DownloadHelper. It has two option download Using Browser and download Using Companion App.
I'm restricting S3 files access by setting bucket policy with specific http referrer.
After adding this policy now it is not possible to download Using Browser but able to download Using Companion App.
How can I restrict downloading files using the second method as well? The bucket policy I have set is given below. Any help would be appreciated. Thanks.
{
"Version": "2012-10-17",
"Id": "http referer policy example",
"Statement": [
{
"Sid": "Allow get requests referred by www.example.com and example.com.",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::examplebucket/*",
"Condition": {
"StringLike": {"aws:Referer": ["http://www.example.com/*","http://example.com/*"]}
}
},
{
"Sid": "Explicit deny to ensure requests are allowed only from specific referer.",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::examplebucket/*",
"Condition": {
"StringNotLike": {"aws:Referer": ["http://www.example.com/*","http://example.com/*"]}
}
}
]
}
Once your file is loaded in the browser, It can be downloaded. what you can do is to generate a signed URL for the images, which is valid for a short time.
set the src for the images to an API which redirects to a signed URL generated by the backend, so while inspecting the browser it will show the signed URL as SRC but that URL can't be reused. But this will only prevent the reuse of the image URLs or if the download-helper is using the URL to download the image. Here whenever the user refreshes the page a new URL will be generated and send to browser.
Eg:
<img src=https://api-url/image/image-id>
and in your backend do something similar to
response.redirect(signed-url)
Related
I am in serious trouble. I have been uploading to the s3 bucket using aws-sdk javascript, downloading it through object link. Using s3 to store images/assets to be used for the nextjs website. I have set the bucket to the read only for everyone. I just realize that this is serious problem, as anyone will be able to download from my bucket unilimited time, and the cost will be through the roof. How can I secure the download to be only from my website through presigned link(I haven't configured the presigned link on my side)? Please help me. I will provide more details below:
current bucket policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::bucketname/*"
}
]
}
CORS:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"PUT",
"POST",
"DELETE",
"GET",
"HEAD"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [
"x-amz-server-side-encryption",
"x-amz-request-id",
"x-amz-id-2"
],
"MaxAgeSeconds": 3000
}
]
You can restrict access to objects based on the 'referring' website.
From Bucket policy examples - Amazon Simple Storage Service:
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Principal":"*",
"Action": "s3:GetObject",
"Resource":"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
"Condition":{
"StringLike":{"aws:Referer":["http://www.example.com/*","http://example.com/*"]}
}
}
]
}
However, restricting access with referer is not secure since it is easy to fake this information.
The more secure method would be to use Amazon S3 pre-signed URLs, which provide time-limited access to private objects in Amazon S3. These URLs must be generated by your back-end, typically after a user has authenticated to your website. This is ideal for serving private/confidential content.
However, if you are simply serving content for a normal website that does not require authentication, then referer is more appropriate.
I have uploaded my file to amazon s3 bucket.
on clicking the uploaded file in s3 it gives me the properties of the uploaded file and the link for the uploaded file.When i copy paste the link in a browzer the file gets downloaded.
my bucket policy is as below.
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket-name/*"
}
]
}
But i donot want my audio/video/image files to get downloaded when we copy paste the link in a browzer..Instead the audio/video/image file to be displayed only through my website.
To achieve this i have used ,
npm aws-cloudfront-sign
cfUtil = require(aws-cloudfront-sign )
i have created a signed url using the above npm module:
var cfKeypairId = 'AJDS2LD3KSD5SJSDKJSA(sample key pair)';
var cfURL = 'http://my_domain_name'+file_path;
//my domain name is something that starts with smb...cloudfront.net
var signedUrl = cfUtil.getSignedUrl(cfURL, {
keypairId: cfKeypairId,
expireTime: Date.now() + 60000,
privateKeyString: ???
});
what should i give in private key string????
what should be my bucket policy?
what should i do with CName's?
can somebody tell this in brief?
You can obtain your CloudFront Key Pair ID and Private Key using the Security Credentials Section(Login Using Root Account) in AWS Web Console.
In your S3 bucket policy you can deny public access and only allow Origin Access Identity in AWS CloudFront to access S3.
If you plan to customize your Domain Name(URL) where you server the files, you can use CName mapping for it using AWS Route53 or using any other DNS provider.
I am using nodejs npm-multer s3 to upload my video/audio/image files to amazon s3 bucket.
I am using the below policy to enable permission for viewing my files through my mobile application
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowPublicRead",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my bucket/*"
}
]
}
But the problem is whenever i copy the link of my s3 files in a browser and paste it, my files are getting downloaded(or shown).
how can i prevent this?
i dont want my files to get downloaded or shown when the link is given in the addressbar.
my files should only be shown or streamed through my mobile and web application.
How can i achieve this?
You might want to consider serving your content through CloudFront in this case using either Signed URLs or Signed Cookies and use an Origin Access Identity to restrict access to your Amazon S3 content.
This way, only CloudFront can access your S3 content and only clients with valid signed URL/cookies can access your CloudFront distribution.
After you setup your Origin Access Identity in CloudFront, your bucket policy should be something like:
{
"Version": "2012-10-17",
"Id": "Policy1476619044274",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <Your Origin Access Identity ID>"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
The format for specifying the Origin Access Identity in a Principal statement is:
"Principal":{
"CanonicalUser":"<Your Origin Access Identity Canonical User ID>"
}
or
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <Your Origin Access Identity ID>"
}
See: Serving Private Content through CloudFront.
This is the first time I use Amazon S3. I've read questions and answers. They all seem similar to this problem but none of the answers fixed it for me.
I can successfully upload pictures but I can get them to display them (403 forbidden status).
This is the bucket's policy:
{
"Version": "2012-10-17",
"Id": "Policy1475848347662",
"Statement": [
{
"Sid": "Stmt1475848335256",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::235314345576:user/userx"
},
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3:::bucketdev/*"
}
]}
This is the CORS config:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
This is the user's policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:GetObject",
"s3:ListBucketMultipartUploads"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]}
Using this component: https://www.npmjs.com/package/react-dropzone-s3-uploader.
Can anyone help?
Thanks.
There are two things to note:
Where to assign permissions for access to Amazon S3
Which permissions to assign
Where to assign permissions for access to Amazon S3
Objects in Amazon S3 are private by default. There are three ways to assign permission to access objects:
Object ACLs (Access Control Lists): These are permissions on the objects themselves
Bucket Policies: This is a set of rules applied to the bucket as a whole, but it can also specify permissions related to a subset of a bucket (eg a particular path within the bucket)
IAM Policies that are applied to IAM Users, Groups or Roles: These permissions apply specifically to those entities
If your intention is to keep the content of the S3 bucket private but allow access to a specific user, then you should assign permissions to the IAM User (as you have done). It also means that you do not require a Bucket Policy since granting access via any one of the above methods is sufficient.
See documentation: Guidelines for Using the Available Access Policy Options
Also a CORS Policy is only required if a HTML page served from one domain is referring to content from another domain. It is quite possible that you do not require the CORS Policy -- do some testing to confirm whether this is the case.
Which permissions to assign
This is always confusing... Some permissions are associated with the Bucket, while some permissions are associated with the contents of the Bucket.
The following permissions from your policy should be at the Bucket level (arn:aws:s3:::MyBucket):
s3:CreateBucket
s3:DeleteBucket
s3:DeleteBucketPolicy
s3:GetBucketPolicy
s3:GetLifecycleConfiguration
s3:ListBucket
s3:ListBucketMultipartUploads
s3:PutBucketPolicy
s3:PutLifecycleConfiguration
Other API calls (eg GetObject) should be at the object-level (eg arn:aws:s3:::MyBucket/*).
See: Specifying Permissions in a Policy
Therefore, the policy associated with your IAM User should look more like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1",
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:ListMultipartUploadParts"
],
"Resource": [
"arn:aws:s3:::MY-BUCKET"
]
},
{
"Sid": "Stmt2",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::MY-BUCKET/*"
]
}
]
}
This grants GetObject permission to objects within the bucket, rather than on the bucket itself.
Just if some body will face with the same problem - be sure that all files was uploaded to bucket, because if you use "Add files" button it does not upload nested folders. Better use "drag and drop".
I have set up a bucket in AWS S3. I granted access to the bucket for my IAM user with an ALLOW policy (Using the Bucket Policy Editor). I was able to save files to the bucket with the user. I have been working with the bucket for media serving before, so it seems the default action is to give public permission to view the files (images), which is fine for most web sites.
In my new project I want to be able to access the S3 bucket with an IAM user but want to deny all other access. No public read access, no access whatsoever besides the IAM user who should have full access save/delete whatever.
What seems like I should do, I was reading about here. It says to create a Deny policy using the NotPrincipal attribute, and that way it will still allow that user, but deny everyone else. For good measure I also added an Allow policy just for the user I want:
{
"Version": "2012-10-17",
"Id": "Policy**********",
"Statement": [
{
"Sid": "Stmt**********",
"Effect": "Deny",
"NotPrincipal": {
"AWS": "arn:aws:iam::*********:user/my_user"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::my_bucket/*"
},
{
"Sid": "Stmt*************",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::**********:user/my_user"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::my_bucket/*"
}
]
}
But this is denying access to everyone even my_user. Again I can confirm that I had access when I just used the Allow portion of the policy above, but then the public also has read access, which I am trying to turn off.
How can I set up my bucket policy to give full access to only the unique IAM user and deny all access to any other user?
Thanks.
It's quite simple:
By default, buckets have no public access
Do NOT add a Bucket Policy, since you do not want to grant access public access
Instead, add a policy to the IAM User granting them access
The main thing to realise is that the IAM User cannot access content via unauthenticated URLS (eg s3.amazonaws.com/bucket/file.jpg) because S3 doesn't know who they are. When the IAM User accesses the content, they will need to use authenticated access so that S3 knows who they are, such as:
Accessing via the AWS Management Console using a Username + Password
Accessing via the AWS Command-Line Interface (CLI) using an Access Key + Secret Key
The policy on the IAM User would look something like:
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my_bucket",
"arn:aws:s3:::my_bucket/*"
]
}
If I understand correctly, allow access to buket only for 1 IAM user. We can use the bucket policy. I got this in netApp documnetation.
{
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::95390887230002558202:federated-user/Bob"
},
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::examplebucket",
"arn:aws:s3:::examplebucket/*"
]
},
{
"Effect": "Deny",
"NotPrincipal": {
"AWS": "arn:aws:iam::95390887230002558202:federated-user/Bob"
},
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::examplebucket",
"arn:aws:s3:::examplebucket/*"
]
}
]
}