Free SSL security certificate on Heroku? - ruby-on-rails

I pushed a Spree Rails app to Heroku and I see it's using ssl withhttps:// and has a yellow padlock in the browser. Clicking on this shows "Identity verified" and the Certificate Information says Issued To: *.herokuapp.com
This is great. With no configuration or expense at the Heroku end, my app is using SSL with a valid looking certificate. Ok it's a yellow rather than green padlock but hey, not bad for free.
I'm sure this is a stupid question..but how can I run another Rails app on Heroku with a verified certificate without paying for the SSL add-on and purchasing my own certificate?

The TLS/SSL connection your browser is establishing is due to the fact the you are connecting to your app via appname.herokuapp.com. This is standard and will automatically work for any app you create out of the box. Heroku provides SSL encryption as you may be sending sensitive information to the server and it is better practice to encrypt data that you may not necessarily deem sensitive, but your client may. All reputable providers (SAS, Web Hosts, Email Providers) will have a wildcard SSL certificate installed to the base domain (*.herokuapp.com) as it is a single certificate that is relatively inexpensive and will secure all the sub-domains automatically.
That being said Apps are SSL-enabled already and can be accessed simply by using https, e.g., https://appname.herokuapp.com, but you would want to go with the SSL endpoint option when you want to establish the trusted relationship with your clients. Both ways are as secure as the other, but with the wildcard SSL (also referred to as a shared SSL certificate) the trust is established between the client via their browser and Heroku not your App/Site. With the SSL signed to your domain.com the clients can connect to your domain and not the Heroku sub-domain and see your site's information in the connection information on the browser. If your site is needing disambiguation from Heroku then is when you will want to proceed with an SSL setup outside the default.
As for what SSL type and issuer to use I would not recommend https://www.startssl.com/ as they do not offer SSLs with high browser ubiquity as they are not fully signed by an external root authority. Comodo and the consumer standard Rapid/GeoTrust are the best choices as far as assurance, recognition, and easy of use and concerned. You only need a DV (domain validated) SSL and they can be had for a few domains a month.
More on this and the Heroku SSL configuration can be found here

I recently spent some time setting this up. It can be done using CloudFront and a proxy to Heroku. This is probably best used for small projects but seems to be working great so far! See my post here:
http://ksylvest.com/posts/2014-05-06/setup-free-ish-ssl-tls-on-heroku-for-ruby-on-rails-or-any-other-framework

A few things have changed since this question was first answered, notably the advent of Let's Encrypt and new Heroku SSL endpoints, which together make it possible to add SSL for free. I've created a gem to generate and add certificates automatically: https://github.com/KMarshland/heroku-ssl. Once you've added heroku_ssl to your gemfile, you can simply run:
rake heroku_ssl:update_certs
Alternatively, if you don't want to use the gem, you can do these tasks manually:
1. Generate the SSL Certificate
Follow the instructions in https://github.com/unixcharles/acme-client to generate your certificates. You'll need to register your email, authorize the domain, and then finally get your certificates. When authorizing the domain, if you only have one server running, you can simply stick the authorization file in your public folder; if not, you'll either have to set up a dedicated controller and route or add a text record to your DNS zone file.
2. Add the certificate to Heroku
After downloading your certificates, you can either use Heroku's web interface or just run
heroku certs:update fullchain.pem privkey.pem
3. Configure your DNS
You need to set a CNAME record in your DNS zone file that points to [yourdomain].herokudns.com. The DNS zone file specifies what urls get mapped to what servers on the domain name you own. If your site is already pointed to your Heroku app, there will already be a CNAME record; you just need to change where it points to. If not, you'll need to add a new line:
[subdomain] [TTL] IN CNAME [yourdomain].herokudns.com.

Related

Apex domains on heroku

I've got a site that was originally running on a non-heroku server that I moved to heroku. The site was using a bare domain before (example.com). Heroku requires non-bare domains (www.example.com) as per this article: https://devcenter.heroku.com/articles/apex-domains
My question is: I have a bunch of links out there currently like this: https://example.com which throw a browser error now that I am using non-bare domains.
This excerpt from heroku confirms the error is widespread.
SSL
Traffic routed over SSL behaves, at the DNS level, identical to unencrypted traffic and suffers from the same naked domain limitations.
However, applications requiring SSL encryption should use the ALIAS/ANAME configuration on the root domain. Subdomain redirection will cause a browser error when the root domain is requested over SSL (i.e. https://example.com).
How can I redirect people to the right domain without them experiencing a browser error?
EDIT:
I emailed heroku and this was their response:
I'm afraid only the ALIAS/ANAME style records will be able to reference an SSL endpoint at the apex and from my understanding Namecheap do not support those record types. We have a few examples for various providers here. But if your domain provider doesn't support ALIAS/ANAME we can only recommend you switch to another provider that does. A URL redirector doesn't work for SSL, the CNAME type breaks email, and raw A records can break after only a few minutes.
So I moved providers from Namecheap to Cloudflare, CNAME'd instead of redirected, and everything now works as expected.
If you don't have an SSL endpoint provisioned then your visitors will get a 'certificate mismatch' error as Heroku will serve their default herokuapp.com certificate. You can't redirect https without a valid certificate as browsers first check the validity of the certificate. If you're moving to Heroku and want to respond to those requests you will need a valid certificate, SSL endpoint provisioned and a DNS provider that supports using CNAMEs on Apex records.

I need to purchase an SSL certificate to use through a heroku server and iOS app. What exactly do I need?

I have created an iOS app, and rails server, that communicate with each other back and forth. I am using login capabilities, so I want SSL.
It appears an SSL endpoint on heroku is $20/mo. Adding that seems simple. heroku addons:create ssl:endpoint.
Now, I need to purchase an SSL certificate.
1) Where's the cheapest place I can get an SSL certificate for my needs? There seems to be varying degrees of options. Do I just require the most basic?
2) What exactly do I receive with my purchase? A private key, and the certificate? I'm not too sure exactly what happens though. Is it like this... When the iOS client hits my server, and hits any https link, my server will return the certificate. The iOS app receives the certificate, and send it to a Certificate Authority(CA). The CA will return the certificate along with the public key to the iOS app. The iOS app will then encrypt the data with the public key, and send it back to the server. The server will then use the private key to decrypt the data.
3) Where exactly do I store the private key on my rails server? In my db? In a .secrets file? In the heroku config?
#1: The SSL certificate you need depends on how many domains you want to secure. If it's jus www.yourdomain.com and yourdomain.com most certs (i.e. a Comodo PositiveSSL) will do the trick.
In addition:
DNSimple, who won't be the absolute cheapest, can do a lot of the work for you (key generation, CSR generation, and generating the certificate)
I (currently) use Namecheap for single-domain PositiveSSL and/or multi-domain PositiveSSL certs. Relatively cheap, two-factor authentication on their login, their UI is "usable" if not great.
#2: Heroku has an article on how to set up the endpoint once you have a cert: https://devcenter.heroku.com/articles/ssl-endpoint - which shows how to add the signed certificate and private key via heroku certs:add yourcert.crt yourkey.key
#3: Your iOS app should use the NSURLSession method to make calls to your Heroku application remotely. This handles the TLS (SSL) handshake and you don't have to worry about the particulars.
As an additional tip, you can also pin the certificate of your Heroku application in your iOS app. Your iOS app effectively matches its' hardcoded signature against the signature in the certificate of your Heroku app so that it knows it's not just talking to some other HTTPS server.
Hopefully that's clear.
Added IRT comment
Note that when you add the SSL addon, you will get an SSL endpoint - e.g. sushi-bento-2141.herokussl.com - which already has SSL through Heroku's wildcard certificate. Your app can listen to requests on the non-SSL endpoint morning-evergreen-9385.herokuapp.com and re-direct them (301 permanent). You don't need to buy your own cert for this.
However, it's typically much nicer to have your own domain name (more recognisable for users!), for which you do have to buy a certificate for (as per my answers above).

Rails: Automatically Create & Provision SSL Certificate via API

I'm building a Rails-based website builder as an experiment and am wondering if there's an API for purchasing and provisioning an SSL certificate automatically for a new website via an API. I believe I have a way to set up the domain and unique IP (although still working through that), but not seeing a great way to set up the SSL certificate.
I found some sort of SSL API -- anyone used it? http://doc.rpc.gandi.net/cert/usage.html

IIS Passing client certificate to rails

I have an application written in Rails that must be ran behind a IIS server due to restrictions by the client, the government. We have to have SSL authentication. So what I can't figure out in my hours of searching Google is how to get IIS to pass the client certificate to the rails server (thin).
I've seen tutorials on Apache that use:
SSLOptions +ExportCertData
Which then make it available to the request object. Any ideas on how to configure IIS to do the same?
At least in the way that you ask the question IIS cannot provide a client certificate as the client cert would be issued by a third party. So you need to get the x509 cert that your application and then the cert is authenticated as part of the initial connection request with iis.
As to the apache function to provide the ssl cert from the server to the client, this functionality is not exposed by iis.
That's why you were not able to find anything on google
The main reason companies want to run Rails(or Other) applications behind an IIS server is for SSO apart from protecting the resources.
See if this helps.
We have been running our Rails app behind IIS at quite a few customer locations. We run our Rails app in JRuby inside Tomcat.
The steps to install the JK ISAPI redirector plugin are here
http://tomcat.apache.org/connectors-doc/webserver_howto/iis.html
All Rails contexts are protected in IIS using standard IIS authentication schemes, Integrated Windows Authentication ( Negotiate, NTLM).
Within the Rails app one can get the logged in user's information.
request.env['java.servlet_request'].get_remote_user
The Rails app also connects to Microsoft AD for additional user information like email, department etc.,
Since the Rails is blindly trusting the IIS server for authenticaiton it needs to be prevented from direct access.
1. Disable HTTP ports in Tomcat
2. Enable only the AJP port
3. Add an IP restriction so that it accepts connection only from the IIS server(s)
==
I do not think it is possible for IIS to pass on the certificate details. We tried to extract the Kerboros tokens ( for kerboros authentication delegation ) without much success and realized it is not possible.
After being told this may be impossible. I've finally figured it out! Here are the steps that I took.
Using OpenSSL create your own CA certificate.
Using the generated CA certficate create and sign other certificates with Open SSL.
Open Internet Information Service Manager click on the server, then click on server certificates.
Click Import under the Actions column
After importing click on your site.
In the Actions column click bindings...
Click add, scroll to https, and select the CA certificate that you imported
Click on your site again to get to the menu and click on SSL settings
Check require SSL and then click the radio buttion, require
Click your site again then click on the configuration editor (installed in IIS 7.5 can add-in in 7.0)
Go to system.webServer/security/authentication/iisClientCertificateMappingAuthentication
Set enabled to true
Set manyToOneCertificateMappings to true
Click on the ... box on the far right-end of manyToOneMappings
Click add under actions column, under collections
Add the username and password of the user you created (can be on local machine)
Now, go to the main server and restart.
You should be able to see the certificate using request.headers hash.
Variables for the hash include:
CERT_SERIALNUMBER
CERT_SUBJECT
CERT_ISSUER
HTTPS_SERVER_ISSUER
HTTPS_SERVER_SUBJECT
If you cannot find something you may have to install a module (for like authentication). I don't remember which ones I installed.

Custom domains in a Rails App

I want users of my service to be able to add their own custom domains. For example, www.[their domain].com should be able to access their application's index and show pages. My service is implemented in Rails 3.
I've seen apps like Tumblr offer this functionality for their front facing blogs. Although I have seen apps for Rails that implement sub domains in the way that Basecamp does, I have not found a resource for fully custom domains.
They'll need to create an A record in their DNS to point to your app servers IP. You'll need to know what domain they have pointed to your server and log it against their account, and also set your web servers config in such a way as to channel the requests from other domains to your app. You can then use the request object to look up their account in your application_controller.
I just answered a similar question so I decided to chime in here too.
#Codebeef gave a good answer but this won't work anymore in the world where HTTPS is a must in most modern browsers.
This is the full picture of how to handle custom domains for your app.
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.
If you need more detail you can DM me on Twitter #dragocrnjac

Resources