22

Is it possible to create a policy with multiple statements when using a CloudFront custom policy for signed cookies (not signed URLs)?

I have read the documentation, and although all the examples just have one statement, I cannot see an explicit rule regarding the number of statements allowed.

If it's not possible to have multiple policy statements, it will be difficult to give a particular user signed-cookie access to say, five random files using only the CloudFront security. Any tips on how to do that would be appreciated.

This question is cross-posted here: https://forums.aws.amazon.com/thread.jspa?threadID=223440&tstart=0

atp
  • 30,132
  • 47
  • 125
  • 187
  • Do you use Python? A scripted solution might be possible. – Rodrigo Murillo Jan 13 '16 at 17:25
  • @RodrigoM I'm not sure how that question is relevant. A programming language could get around the problem, but I'm more interested in if I can do it through CloudFront policy statements. – atp Jan 13 '16 at 21:25
  • 1
    You are limited to one statement per policy. There may be a way to structure that policy to allow some automated method of signing arbitrary URL, as a way of overcoming the limitation. – Rodrigo Murillo Jan 13 '16 at 21:28
  • Well, I _might_ be limited to one statement per policy -- that's the question. If I were, though, can you provide an example of what you mean in overcoming the limitation? I don't understand. – atp Jan 13 '16 at 22:32
  • The documentation (now) explicitly states: ["You can include only one statement."](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-custom-policy.html#private-content-custom-policy-statement-cookies) – Chris Martin Apr 05 '18 at 03:48

5 Answers5

8

FYI

I have faced with the same problem, and contacted with the official AWS support team.

 Hello, thanks for offering us a great service. 
I am an software engineer from Japan. 

Can we have multiple custom policies, like below syntax? 

{ 
  "Statement": [ 
    { ... }, 
    { ... }, 
    { ... }, 
  ] 
} 

I have searched on the web, and found ones who are trying to 
do the same thing and forums/Q&A as well. 

However we found no answer from AWS official support teams 
nor documents saying about that. 

JSON syntax is array, so it seems to work with 
multiple statements but do not work. 

So, if it does not work, would you add a sentence 
about that on the official document?

And then, I got the answer yesterday:

I just heard back this morning. 

You're correct, adding more than one statement 
to a custom policy is not supported. 

I'm updating the documentation now.

So, I think in few days the documentation will be updated that you can not set multiple policy statements for CF Custom Policy for Pre-Signed Cookies.

kenju
  • 5,866
  • 1
  • 41
  • 41
4

It's upsetting there is nothing in the docs that says you can only have one item in the Statement array, but that's AWS docs for ya!

Anyways, a way around this limitation, is to set multiple cookies at different path levels. You'll need to generate a signed cookie for each path you want and set each cookie in whatever app you are using. You can imagine an endpoint in your api that generates all of the necessary cookies, sets them all in the header, and your front end then sets all of those cookies.

More specifically you'll want to create one CloudFront-Key-Pair-Id cookie with your cloudfront access key id, and scope that cookie path to the highest level that you're policies will be set to. Use the AWS CloudFront SDK to sign a cookie for each Resource. Create a pair of CloudFront-Policy and CloudFront-Signature cookie for each path that corresponds to the Resource path.

Say I have the following two Resources and want to give access to both of them: https://cfsub.cloudfront.net/animals/dogs/* https://cfsub.cloudfront.net/animals/cats/*

I'd create:

  • 1 CloudFront-Key-Pair-Id cookie with a path of /animals
  • 1 CloudFront-Policy cookie with the base64 policy generated from running the dogs custom policy through the cloudfront signer. This cookie should have a path of /animals/dogs.
  • 1 CloudFront-Policy same thing for cats
  • 1 CloudFront-Signature cookie with the signature generated from running the dogs custom policy through the cloudfront signer. This cookie should have a path of /animals/cats
  • 1 CloudFront-Signature same thing for cats

All of these cookies should have a domain set to your cloudfront domain cfsub.cloudfront.net

Send all those up to your web app or mobile app.

duhseekoh
  • 1,263
  • 10
  • 13
  • have you tested this against cloudfront? – scagbackbone Feb 27 '18 at 10:47
  • yup, did limited testing, but held up on ios and android apps at the time. ended up going with security by obscurity though :) also, its worth checking out the new lambda @ edge. allows you to throw lambdas in front of cloudfront requests, so if your permissions can be looked up quickly in realtime, you can control the gate there. – duhseekoh Mar 07 '18 at 23:10
1

I can't give definite information on this subject, it is an explicit question which someone at Amazon can give relevant information on.

That said, I believe CloudFront policies may include multiple statements. Their schema is similar to IAM policies but I don't think it'll work exactly how you're expecting.

With IAM policies, you're able to attach multiple statements to one policy but they are OR'd across the statements:

Generally, each statement in a policy includes information about a single permission. If your policy includes multiple statements, a logical OR is applied across the statements at evaluation time. Similarly, if multiple policies are applicable to a request, a logical OR is applied across the policies at evaluation time... IAM Policy Documentation

In the documentation you linked to, the Statement key's value is an array which you can include multiple statements in but they'll be OR'd across them. There is further information on how the policies are evaluated which will help in limiting access to the files you're working on.

Giving access to five random files will be a challenge which I do not believe is accomplishable with CloudFront access policies alone. The conditions available aren't designed with this use case in mind.

As Rodrigo M pointed out, using the AWS API from a script can accomplish what you're attempting to do. Unfortunately that is the only route I can imagine which will accomplish what you're attempting.

If you find a way to accomplish this task using only CloudFront policies (without other AWS services), I'll be quite interested in the solution. It'd be a creative policy and quite useful.

Community
  • 1
  • 1
erik-e
  • 3,721
  • 1
  • 21
  • 19
  • Thanks for the answer. Although that makes total sense for IAM policies, I don't believe it is possible at this time to have multiple `Statements` in a CloudFront policy. I will wait for AWS to confirm this and provide a source. – atp Jan 18 '16 at 04:48
  • The way I would work around this is using URL-rewriting on the content I serve, generating a unique CloudFront signed URL for each individual protected CloudFront resource. – atp Jan 18 '16 at 04:49
0

I have similar requirement and tested AWS CloudFront with canned policy include multiple resources to restrict access to different urls. The policy is a valid json object, it looks like below:

{  
  "Statement":[  
    {  
      "Resource":"https://qssnkgp0nnr9vo.cloudfront.net/foo/*",
      "Condition":{  
        "DateLessThan":{  
          "AWS:EpochTime":1492666203
        }
      }
    },
    {  
      "Resource":"https://qssnkgp0nnr9vo.cloudfront.net/bar/*",
      "Condition":{  
        "DateLessThan":{  
          "AWS:EpochTime":1492666203
        }
      }
    }
  ]
}

After I signed policy and send request to CloudFront it turned out AWS CloudFront does not support it. It got a 403 response said it was a Malformed Policy.

HTTP/1.1 403 Forbidden

<?xml version="1.0" encoding="UTF-8"?><Error><Code>MalformedPolicy</Code><Message>Malformed Policy</Message></Error>
Ming C
  • 2,476
  • 2
  • 14
  • 8
0

AWS officially supports only one statement in one singed policy. However, There is a workaround if you need 4 or less statements. For each statement you can create a separate pair of a CloudFront-Policy cookie and a CloudFront-Signature with its own path. The size of this pair of cookies would be around 600-900 bytes. Since the Cookie header has a limit of around 4Kb, you definitely can't use more than 5 pairs. Using 5 pairs has a high change to reach the header limit.