Cloudfront bucket policy for video on demand - amazon-web-services

I am creating a video on demand platform similar to netflix. I want the users that have purchased the subscription to view my videos to be able to watch them (not download them). I also do not want the users to be able to copy the source of the video url, and access it through a new tab (this is working for now, it says access denied).
So what I have done for now is this, I have copied the official code from amazon's documentation, which allegedly only allows the content (in my case the video) to be played on the website that I specify. This is the policy:
{
"Version": "2008-10-17",
"Id": "Policy1408118342443",
"Statement": [
{
"Sid": "Stmt1408118336209",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"https://mywebsite/*",
"https://mywebsite/*"
]
}
}
}
]
So what hapenned was, I was not able to play the video on my site and I was not able to access the video by direct URL. I have tried selecting the video file, and allowing "Read object" for public access, but that only made my video be direcctly accessable by URL, which I don't want.
My "Block public access" permissions are all currently off, because if they are On I cannot edit the bucket policy (it says "Access denied" when I hit save).
My question is, how do I protect my video content from bandwith theft? I don't want a person to buy my membership, then send the direct video link to his friends so everyone can see. Allegedly to amazon this is possible, but what seems to be the problem?
Also I am planning to use Cloudfront after I solve this issue, so hopefully that won't interfere.

Related

Items in my Amazon S3 bucket are publicly accessible. How do I restrict access so that the Bucket link is only accessible from within my app?

I have an Amazon S3 bucket that contains items. These are accessible by anyone at the moment with a link. The link includes a UUID so the chances of someone actually accessing it are very low. Nonetheless, with GDPR around the corner, I'm anxious to get it tied down.
I'm not really sure what to google to find an answer, and having searched around I'm not closer to my answer. I wondered if someone else had a solution to this problem? I'd like to only be able to access the resources if I'm clicking on the link from within my app.
According to the S3 documentation, you should be able to restrict access to S3 objects to certain HTTP referrers, with an explicit deny to block access to anyone outside of your app:
{
"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/*"]}
}
}
]
}
The prerequisite for using this setup would be to build an S3 link wrapper service and hosting it at some site for your app.
This is a standard use-case for using a Pre-signed URL.
Basically, when your application generates the HTML page that contains a link, it generates a special URL that includes an expiry time. It then inserts that URL in the HTML link code (eg for an image, you would use: <img src='[PRE-SIGNED URL]'/>
The code to generate the pre-signed URL is quite simple (and is provided in most SDKs).
Keep your Amazon S3 bucket as private so that other people cannot access the content. Then, anyone with a valid pre-signed URL will get the content.

What to write in bucket policy for secure my video

I hosted my video on Amazon S3 for selling online course like Udemy.
Can you guide me about, what bucket policy do I need for secure my video that student can view them but don't download or someone else can't find URL for that video. What should I write in the bucket policy? And which player do I need on my wordpress website to play these videos.Please help me out.
{
"Version": "2008-10-17",
"Id": "Policy1414368633278",
"Statement": [
{
"Sid": "Stmt1414368595009",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOURBUCKETNAME/*",
"Condition": {
"StringLike": {
"aws:Referer": "http://YOURDOMAINNAME.com/*"
}
}
}
]
}
A bucket policy alone is not sufficient to secure your content as you describe.
You will require some application logic to determine whether a user is permitted to access the object. If the application then wishes to grant access, it can create a time-limited pre-signed URL. This allows the object to be accessed for a specific time period, after which access is denied.
Companies like Udemy implement their own form of access control. If you were to supply a video to them, they would host it and control access.
Bottom line: You need an application to control access, which then provides a link that tells Amazon S3 to grant access to the object.

Amazon S3 Permissions by Client code

I've been converting an existing application to an EC2, S3 and RDS model within AWS, so far it's going well but I've got a problem I can't seem to find any info on.
My Web application accesses the S3 box for images and documents, the way this is stored is by client code,
Data/ClientCode1/Images
Data/ClientCode2/Images
Data/ClientABC/Images -- etc
The EC2 hosting the web application also works within a similar structure, so www.programname.com/ClientCode1/Index.aspx as an example, this has working security to prevent cross client access.
Now when www.programname.com/ClientCode1/Index.aspx goes to access the S3 for images, I need to make sure it can only access the ClientCode1 folder on the S3, the goal is to prevent client A seeing the images/documents of client B if you had a tech sort trying.
Is there perhaps a way to get the page referrer, or is there a better approach to this issue?
There is no way to use the URL or referrer to control access to Amazon S3, because that information is presented to your application (not S3).
If all your users are accessing the data in Amazon S3 via the same application, it will be the job of your application to enforce any desired security. This is because the application will be using a single set of credentials to access AWS services, so those credentials will need access to all data that the application might request.
To clarify: Amazon S3 has no idea which page a user is viewing. Only your application knows this. Therefore, your application will need to enforce the security.
I found the solution, seems to work well
{
"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:::clientdata/Clients/Client1/*",
"Condition": {
"StringLike": {"aws:Referer": ["http://www.example.com/Client1/*","http://example.com/Client1/*"]}
}
},
{
"Sid": "Explicit deny to ensure requests are allowed only from specific referer.",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::clientdata/Clients/Client1/*",
"Condition": {
"StringNotLike": {"aws:Referer": ["http://www.example.com/Client1/*","http://example.com/Client1/*"]}
}
}
]
}
This allows you to check the referer to see if the URL is from a given path, in my case I have each client sitting in their own path, the bucket follows the same rule, in the above example only a user coming from Client1 can access the bucket data for Client1, if I log in to Client2 and try force an image to the Client1 bucket I'll get access denied.

aws bucket policy to allow Facebook to show open graph images

I can't seem to get Facebook to have access to the resources I put in my open graph tags in my bucket policy.
This is my current policy, meant to prevent hotlinking but allow Facebook (and ideally other social networks) to access my images (and other resources)
{
"Version": "2012-10-17",
"Id": "idance and social only",
"Statement": [
{
"Sid": "Explicitly only allow only from specific referer.",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::common-resources-idance-net/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"https://example.com/*",
"*facebook*",
"*twitter*",
"*google*"
],
"aws:UserAgent": [
"*facebook*",
"*twitter*",
"*google*"
]
}
}
}
]
}
Here's the Facebook Sharing Debugger link saying that (and presumably why) the scraping for the resources fails.
The error for the inaccessible image is:
could not be downloaded because it exceeded the maximum allowed sized of 8Mb or your server was too slow to respond.
But the image is not large and S3 is not slow. So I imagine that this is a bucket policy issue.
I'm not sure what I'm missing but can anyone shed some light on what I might change to make this work?
Update: I removed the policy entirely, and it seems to not had any effect. Perhaps some special header needs to be sent to Facebook when scraping?

prevent image hotlinking but allow direct access

I use Amazon S3 to store my website's images. I have a bucket policy that stops other websites hotlinking my images.
To get this to work, I have the file permission set to "private" in S3 and then the bucket policy opens access up to my website only.
This works fine, but because the file is "private" I cannot view the image directly in a browser, and this is something I want to allow.
Here is the policy
{
"Version": "2008-10-17",
"Id": "preventHotLinking",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"http://mydomain.com/*",
"http://www.mydomain.com/*"
]
}
}
}
]
}
So, to summarise:
the file itself is set to private
the above policy allows images to be displayed on pages from the domain "mydomain.com" but not on "someoneelsesdomain.com"
This also blocks direct access though, so pasting http://jbtestyt.s3.amazonaws.com/archie.jpg into a browser does not show the image (because it is private).
But I would like the image to display for direct access.
Possibly the solution is to make the file public then deny all referrers apart from ones I list? But I was not sure, and could not find anything like that.
Many thanks in advance.
I am inferring that you are looking for a "native" S3 solution, so here goes. If you really think about it, hotlinking in essence is "directly accessing" the file. Therefore, "the file itself is set to private" will always ensure that (on AWS at least) you cannot directly access it no matter what. This is by design on S3. What you suggest for whitelisting referrers is probably the only straightforward way that you're going to accomplish this using S3 alone.