Enforcing HTTPS on Routes

About HTTPS Routes

When you map an HTTP route to an application, both HTTP and HTTPS endpoints are opened on the Apcera cluster's router (assuming that HTTPS is enabled on your Apcera cluster's HTTP router). By default, clients can access routes using either http or https protocols. For example, the HTTP route my-app.example.com can be reached using http://my-app.example.com or https://my-app.example.com.

You can optionally enforce that requests that arrive over a non-secure connection are redirected to the route's secure endpoint. There are two ways to do this:

  • Have the Apcera router automatically redirect requests over http to the route's https address. See Enforcing HTTPS on the router.
  • Have your application redirect to HTTPS based on the value of HTTP headers set by the Apcera router on incoming requests before routing to the job instance. This approach requires that your application include a HTTP routing component, such as NGinx or Apache, to handle the redirect. See Enforcing HTTPS on the job.

Note that SSL connections are terminated at the HTTP router in your Apcera cluster; jobs do not receive HTTPS traffic.

Enforcing HTTPS on the router

The easiest way to enforce HTTPS on a route is to include the --https-only flag when creating the route. For example, the following creates an HTTPS-only route for the app myapp on the specified port:

apc route add www.example.com --port 1234 --app myapp --http --https-only

The following curl command (with --verbose flag) demonstrates the effect of adding the --http-only flag. Note that the request uses http and the response code is 301 Moved Permanently and the Location header is the route with https protocol:

curl --verbose http://www.example.com
> GET / HTTP/1.1
> Host: www.example.com

< HTTP/1.1 301 Moved Permanently
< Location: https://www.example.com/

You can use the same flag when creating an application with the apc app create, apc docker run, or apc app from package commands. Auto-generated routes and any routes added via the --routes parameter are marked as HTTPS-only. For example, the following marks the routes http://app1.example.com and http://app2.example.com as HTTPS-only.

apc app create my-app --routes http://app1.example.com,http://app2.example.com --https-only

In the Web Console, check the Only allow HTTPS option when creating the route (see Managing routes and ports).

In a multi-resource manifest you can add https_only: true to a route definition to enforce HTTPS on the route.

Note that once a route has been created with an HTTPS-only route it cannot be changed to a non-HTTPS-route, and vice-versa. For example, suppose you create an app and assign it an HTTPS-only route:

apc app create app1 -p ~/my-app --routes app.example.com --https-only
...
Success!

If you then tried to add the same route endpoint to another app without the --https-only flag then a https-only flag conflict error is generated:

apc app create app2 -p ~/my-app --routes app.example.com
...
Creating app "app2"... error
Error: error creating job: Route app.example.com https-only flag conflict

Enforcing HTTPS on a job

To enforce HTTPS on a job (rather than on the Apcera router) your job can examine the value of the Apcera-HTTPS request header. This header is injected by the Apcera router before it forwards the request to the job instance. If the original request to the router was made over HTTPS then this header is set to on. If the request was not made over HTTPS then the value of Apcera-HTTPS is an empty string and your application can redirect the request to the route's HTTPS endpoint.

For example, suppose you have an Apcera job that uses NGINX as a front-end. The following NGINX configuration redirects the request if the Apcera-HTTPS request header value is empty:

server {
  listen $PORT;
  root  www;

  if ($http_apcera_https != "on") {
    return 301 https://$host$request_uri;
  }

  location / {
    try_files $uri /index.html?$args;
  }
}

If your job uses Apache as the front-end then the following configuration will accomplish the same thing:

RewriteEngine On
Rewritecond %{HTTP:apcera-https} == "on"
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Note that HTTPS connections are terminated at the Apcera router; jobs receive HTTP traffic, only.

If the Apcera-HTTPS request header is set to "on" then the following additional request headers are added that provide details about the SSL connection:

  • Apcera-SSL-Cipher – Specifies the cipher used in the SSL connection between the router and client.
  • Apcera-SSL-Protocol – Specifies the SSL protocol used in the connection.
  • Apcera-SSL-Session-Id – Session identifier for the SSL connection.
  • Apcera-SSL-Session-Reused – Contains "r" if the SSL session was reused; otherwise contains ".".
  • Apcera-SSL-Server-Name – The hostname that was contacted by the client at the beginning of the SSL handshake process.