should I test SSL / HTTPS routes locally in a rails app? - ruby-on-rails

I'm wondering what the best practice is concerning test that certain urls use certain protocols. Do I have to set up an SSL cert locally?

You don't need to set up an SSL cert locally. You can fake an HTTPS request in your tests with something like:
request.env['HTTPS'] = 'on'

If your concern is specifically about HTTPS connections testing, I would suggest setting up your own test CA and issuing certificates for your machine. Then, import the CA certificate into your test clients. This will be far more realistic than tests where you would just bypass the certificate verification.
Avoid certificates issued to IP addresses, give names to your servers. Even if you don't have a DNS server, set the machine names in the hosts files of the client machines.
There are a number of tools that can help you set up a small CA. TinyCA is one of them, for example.

Related

Is it possible to create the self-signed ssl certificate which will avoid the "challenge" in the application code?

Background
I have a third-party framework that does some network requests to the URL which I provide to it.
The format of requests is:
https://10.0.2.2:8000/api/....
Since the schema is https I constantly receive the error message from the third party lib:
The certificate for this server is invalid. You might be connecting to a server that is pretending to be “10.0.2.2” which could put your confidential information at risk.
The server is a Django application started with
python3 manage.py runserver_plus 10.0.2.2:8000 --cert-file _my_cert.crt
I've tried a lot of ways to generate and install the self-signed certificate to the simulator and run the server, however, none of them have helped to avoid the error in the third party lib.
The Question
So I'm wondering if this makes sense at all.
Is it possible to generate and install self-signed certificate into iOS simulator which will avoid solving the challenging as is described here:
https://developer.apple.com/documentation/foundation/url_loading_system/handling_an_authentication_challenge/performing_manual_server_trust_authentication?language=objc
Please, provide proofs for any kind of answer whether yes or no.
You can get free SSL Certificate from https://letsencrypt.org
Just try it once.
For developing/testing purposes, I think the easiest way to go is to use a tunneling service like serveo. Execute the next command on the application server and this will keep the connection open:
ssh -o ServerAliveInterval=60 -R 80:localhost:8000 serveo.net
You can check for more config options on serveo. For example, you could set up a custom domain name like custom_domain.serveo.net.
You also have alternatives like ngrok.

Port 443 Exact use and description

I had studied on many sites but got confused about port 443
Anyone please provide me complete information on Port no 443.
Thanks for your response.
Is it only for http or also used for ssl or any other
A port can be used for basically anything that is to be exposed on the network, 443 is no different from any other port really. But, I'm guessing you don't want info about how ports work, but rather what port 443 is used for by most often.
Port 443 is the default port for secure HTTP aka https, that is, http with Transport Layer Security (earlier called Secure Sockets Layer). Just as with http, it's a port that web servers uses but unlike standard http enforces the usage of secure certificates, most often created by a Certificate Authority that is known by the web browsers as a secure authority.
So when connecting to a page via https instead of http, using a certificate which the browser (or computer) have either added as a safe certificate or have not. If not, it will tell you so and show an exception or warning (at least most browsers will do that).
TLS requires the certificates, and the reason is that the server encrypts the data that it sends to the client, and then the client decrypt it making the whole stream of data less easy to catch for someone whom should not have the data, i.e., a hacker or similar.
If you are running a webpage, you should make sure that you have valid certificates. Both Chrome and Firefox marks pages without TLS as unsafe and if you have any type of data transfer from page to server (say a form with data for the user to add for example) TLS is pretty much a must to make the data transfer safe.
TLS certificates used to be quite costly, but now a days there are services such as Let's Encrypt and Cloudflare which provides safe and free certificates, either as one you install on the server, or a shared certificate as in the "free" version from Cloudflare.
Personally I find it worth to create a self signed certificate (a certificate from my own Certificate Authority, not a big one which is validated by the browsers) for local development too and add it to the certificate storage so that even my localhost uses TLS, but that might be overkill in some cases.
TLDR;
The port 443 is often used for HTTPS (http with TLS), it's good. Use it.

CloudFlare SSL compatibility with ASP.NET MVC RequireHttps

I am hosting an ASP.NET MVC 4 site on AppHarbor (which uses Amazon EC2), and I'm using CloudFlare for Flexible SSL. I'm having a problem with redirect loops (310) when trying to use RequireHttps. The problem is that, like EC2, CloudFlare terminates the SSL before forwarding the request onto the server. However, whereas Amazon sets the X-Forwarded-Proto header so that you can handle the request with a custom filter, CloudFlare does not appear to. Or if they do, I don't know how they are doing it, since I can't intercept traffic at that level. I've tried the solutions for Amazon EC2, but they don't seem to help with CloudFlare.
Has anyone experienced this issue, or know enough about CloudFlare to help?
The X-Forwarded-Proto header is intentionally overridden by AppHarbor's load balancers to the actual scheme of the request.
Note that while CloudFlare's flexible SSL option may add slightly more security, there is still unencrypted traffic travelling over the public internet from CloudFlare to AppHarbor. This arguably defies the purpose of SSL for anything else than appearances and reducing the number of attack vectors (like packet sniffing on the user's local network) - i.e. it may look "professional" to your users, but it actually is still insecure.
That's less than ideal particularly since AppHarbor supports both installing your own certificates and includes piggyback SSL out of the box. CloudFlare also recommends using "Full SSL" for scenarios where the origin servers/service support SSL. So you have a couple of options:
Continue to use the insecure "Flexible SSL" option, but instead of inspecting the X-Forwarded-Proto header in your custom RequireHttps filter, you should inspect the scheme attribute of the CF-Visitor header. There are more details in this discussion.
Use "Full SSL" and point CloudFlare to your *.apphb.com hostname. This way you can use the complimentary piggyback SSL that is enabled by default with your AppHarbor app. You'll have to override the Host header on CloudFlare to make this work and here's a blog post on how to do that. This will of course make requests to your app appear like they were made to your *.apphb.com domain - so if for instance you automatically redirect requests to a "canonical" URL or generate absolute URLs you'll likely have to take this into consideration.
Upload your certificate and add a custom hostname to AppHarbor. Then turn on "Full SSL" on CloudFlare. This way the host header will remain the same and your application will continue to work without any modifications. You can read more about the SSL options offered by AppHarbor in this knowledge base article.
This is interesting.
Just I recently had a discussion with one of our clients, who asked me about "flexible" SSL and suggested that we (Incapsula) also offer such option.
After some discussion we both came to the conclusion that such a feature would be misleading, since it will provide the end-user with a false sense of security while also exposing the site owner to liability claims.
Simply put, the visitor on one of "flexible" SSL connection may feel absolutely safe behind the encryption and will be willing provide sensitive data, not knowing that the 'server to cloud' route is not encrypted at all and can be intercepted (i.e. by backdoor shells).
It was interesting to visit here and see others reach the same conclusion. +1
Please know that as website owner you may be liable for any unwanted exposure such setup may cause.
My suggestion is to do the responsible thing and to invest in SSL certificate or even create a self signed one (to use for encryption of 'cloud to server' route).
Or you could just get a free one year SSL cert signed by StartCom and upload that to AppHarbor.
Then you can call it a day and pat yourself on the back! That is until future you one year from now has to purchase a cert =).

Use an NSURLProtectionSpace or SecTrustSetAnchorCertificates() for HTTPS server validation?

I want to confirm the identity of the server my client is communicating with over a HTTPS connection.
There would appear to be two options, however I've not been able to find anything describing what the advantages/disadvantages of one method over the over is. Which of these is more secure and why?
1) Create a self-signed certificate which is used by the server and added to the application bundle and set as an anchor certificate using SecTrustSetAnchorCertificates()
2) Create an NSURLProtectionSpace and set its realm, host, port, and protocol, then compare it with the NSURLProtectionSpace in the NSURLAuthenticationChallenge passed into willSendRequestForAuthenticationChallenge:.
Does it make much difference which of these authentication mechanisms is used to verify the server?
TIA
Technical Note 2232: HTTPS Server Trust Evaluation describes best practices for evaluating trust over SSL/TLS.
It's not clear from the question wether you're interested in only self signed certificates or evaluating trust in general. In general, avoid using self signed certificates in production environments. If you must use a self signed server certificate, you should be rigorous in verifying that the credentials are what you expect. At the very least you should check the public key the server provides against a known value (SSL public key pinning). An example to get you started is here.

Multiple domains powered by one rails app

I am creating a blogging-like application where we allow our customers to use their own custom domain names such as domainexample.com, so each different domain serves the same application but with different content.
However I am struggling to figure out how to set this up on a production server. If my production server has a static IP then I can surely just set an a-record on each domain to the ip of the production server.
But what if the production server does not have a static IP. For example if we want to host it on heroku or engineyard? I have seen a few solutions online that require using rewrite rules but they require server restarts and cant really dynamically add and remove new domains as new users sign up. Does anyone know any good solutions to let multiple domains hit one rails app?
Heroku isn't your only option. If you can anticipate your customer's domains, have a look at this. If you can't, Rails routes constraints and a combination of the accepted answer to the question linked above should get you where you need to be going. Sounds like you wouldn't want to restart your server--so no editing of the routes. You might also make domains part of your models, or distinguish at the controller level or use URL rewriting in your web-server layer.
The problem, as I see it, is that Rails breaks its mantra of opinion over configuration here. There are many ways of serving up from multiple domains. That might be an intrinsic complexity, but the Rails Guides could at least document one possible solution.
If your customers just CNAME to your domain or create the A record to your IP and you don't handle TLS termination for these custom domains, your app will not support HTTPS, and without it, your app won't work in modern browsers on these custom domains.
You need to set up a TLS termination reverse proxy in front of your webserver. This proxy can be run on a separate machine but you can run it on the same machine as the webserver.
CNAME vs A record
If your customers want to have your app on their subdomain, e.g. app.customer.com they can create a CNAME app.customer.com pointing to your proxy.
If they want to have your app on their root domain, e.g. customer.com then they'll have to create an A record on customer.com pointing to your proxy's IP. Make sure this IP doesn't change, ever!
How to handle TLS termination?
To make TLS termination work, you'll have to issue TLS certificates for these custom domains. You can use Let's Encrypt for that. Your proxy will see the Host header of the incoming request, e.g. app.customer1.com or customer2.com etc., and then it will decide which TLS certificate to use by checking the SNI.
The proxy can be set up to automatically issue and renew certificates for these custom domains. On the first request from a new custom domain, the proxy will see it doesn't have the appropriate certificate. It will ask Let's Encrypt for a new certificate. Let's Encrypt will first issue a challenge to see if you manage the domain, and since the customer already created a CNAME or A record pointing to your proxy, that tells Let's Encrypt you indeed manage the domain, and it will let you issue a certificate for it.
To issue and renew certificates automatically, I'd recommend using Caddyserver, greenlock.js, OpenResty (Nginx).
tl;dr on what happens here;
Caddyserver listens on 443 and 80, it receives requests, issues, and renews certificates automatically, proxies traffic to your backend.
How to handle it on my backend
Your proxy is terminating TLS and proxying requests to your backend. However, your backend doesn't know who is the original customer behind the request. This is why you need to tell your proxy to include additional headers in proxied requests to identify the customer. Just add X-Serve-For: app.customer.com or X-Serve-For: customer2.com or whatever the Host header is of the original request.
Now when you receive the proxied request on the backend, you can read this custom header and you know who is the customer behind the request. You can implement your logic based on that, show data belonging to this customer, etc.
More
Put a load balancer in front of your fleet of proxies for higher availability. You'll also have to use distributed storage for certificates and Let's Encrypt challenges. Use AWS ECS or EBS for automated recovery if something fails, otherwise, you may be waking up in the middle of the night restarting machines, or your proxy manually.
Alternatively, there have been a few services like this recently that allow you to add custom domains to your app without running the infrastructure yourself.
If you need more detail you can DM me on Twitter #dragocrnjac

Resources