balanced / balanced-dashboard

The Balanced dashboard.
https://dashboard.balancedpayments.com/
Other
2.28k stars 385 forks source link

Investigate optimising static file serving #827

Open mjallday opened 10 years ago

mjallday commented 10 years ago

From a tweet from wyattanderson:

if it’s for static assets like CSS and JS why not just use Cloudfront and the randomly-generated CF name?

I did not know this existed as an option, from what I read you have to manually version the file name.

Currently, we suffix the file name with a hash of the file to create a unique file name and then upload this to S3 and reference it in the index.html root doc. Is there a better way?

wyattanderson commented 10 years ago

So, for voxy.com, we use a Cloudfront distribution that's actually backed by our webservers, not S3 (for now), but I think this approach would still work for you since you're throwing a unique hash in the filename. For example, one script we load has the following src (we drop the _HASH from the filename at the origin server):

//d1t5bup2xhhy7o.cloudfront.net/static_0b06faacd5a3a192c0cc8d7b88e53027/assets/js/require.js

It doesn't help you with the SSL problem for your base URL (since there're numerous things your users might want to see: a familiar domain name, a green SSL verification icon, whatever), but you can serve static assets this way and still get the benefits of CDN (we have lots of global users) without paying the $600 for SSL certs.

mjallday commented 10 years ago

We used to do the same before we hosted the content directly on S3; uploaded it to a server and then had an nginx rewrite that looked like rewrite "^/(.+)(\.\w{32})\.(css|js)$" /$1.$3 last;.

That allowed us to reference any file name via cloudfront along with any 32 character hash suffix and it would still point to the same file.

I don't think there was a huge decision about which way was best to do this, the only difference in my eyes is that means we have a copy of every version of the file sitting on S3 (is that a good thing??).

Since we only need a friendly SSL cert domain name for the index.html this has worked pretty well for us so far. Glad to see other people are doing something similar, that means we're either doing the right thing or we've got company while we do the wrong thing ;)

wyattanderson commented 10 years ago

Yeah, for us it's worth having static assets closer to users. RTT to the US from Brazil can be very, very long, especially with SSL handshake overhead. But, I certainly don't mean to suggest that you don't know what you're doing. Merely trying to validate my own approach through discussion, I guess. Thanks for your time!

mjallday commented 10 years ago

Good point about keeping the file close to the user. I'm going to reopen this so we can serve via CF to make life easy on those people who aren't so lucky as to be living here in CA next door to our servers.

TODO:

tarunc commented 10 years ago

We should serve the dashboard with a Content Security Policy to mitigate potential XSS attacks. (http://www.html5rocks.com/en/tutorials/security/content-security-policy/) (https://www.owasp.org/index.php/Content_Security_Policy)

We should also employ defense against Clickjacking (https://www.owasp.org/index.php/Clickjacking) (https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet)

tarunc commented 10 years ago

If we do ever make a checkout flow similar to Google Checkout or PayPal, we should look into p3p headers too.

mjallday commented 10 years ago

@tarunc can you come up with a summary of changes needed to implement your security recommendations above?

tarunc commented 10 years ago

Content-Security-Policy Pass the dashboard index.html file with a Content-Security-Policy header. You will have to formulate the header value that this should have but I would think it should be something where the only script code that should be able to run is from (api | auth | js).balancedpayments.com and cloudfront.net and cdn.mxpnl.com and cdn.ravenjs.com. The only style code is cloudfront.net. No iframe code should be able to run etc.

Clickjacking Passing the dashboard index.html file with a X-Frame-Options header with the value DENY since we don't want the dashboard to be able to be iframed.

I don't think we need to have p3p headers. We aren't there yet.

tarunc commented 10 years ago

Word of caution: This is from a cursory glance. I briefly researched the security of ecommerce platforms for a professor while at Berkeley so thats how I know this stuff but it has been 3 years since that.