| --- |
| title: HTTPS Configuration |
| layout: website-normal |
| --- |
| |
| ## Getting the Certificate |
| To enable HTTPS web access, you will need a server certificate in a java keystore. To create a self-signed certificate, |
| for testing and non-production use, you can use the tool `keytool` from your Java distribution. (A self-signed |
| certificate will cause a warning to be displayed by a browser when viewing the page. The various browsers each have |
| ways to import the certificate as a trusted one, for test purposes.) |
| |
| The following command creates a self-signed certificate and adds it to a keystore, `keystore.jks`: |
| |
| {% highlight bash %} |
| % keytool -genkey -keyalg RSA -alias brooklyn \ |
| -keystore <path-to-keystore-directory>/keystore.jks -storepass "mypassword" \ |
| -validity 365 -keysize 2048 -keypass "password" \ |
| -ext "SAN=dns:<your-server-hostname>" |
| {% endhighlight %} |
| |
| The passwords above should be changed to your own values. Omit those arguments above for the tool to prompt you for the values. |
| Replace `<your-server-hostname>` with the hostname clients use to reach the server (and set the same value when |
| prompted for the certificate's first and last name / CN). This matters because the certificate served is chosen by |
| matching the client's requested hostname against each certificate's CN and Subject Alternative Names — see |
| [Which certificate gets served (SNI)](#which-certificate-gets-served-sni) below. |
| |
| You will then be prompted to enter your name and organization details. This will use (or create, if it does not exist) |
| a keystore with the password `mypassword` - you should use your own secure password, which will be the same password |
| used in your `brooklyn.cfg` (below). You will also need to replace `<path-to-keystore-directory>` with the full |
| path of the folder where you wish to store your keystore. The keystore will contain the newly generated key, |
| with alias `brooklyn` and password `password`. |
| |
| For production servers, a valid signed certificate from a trusted certifying authority should be used instead. |
| Typically keys from a certifying authority are not provided in Java keystore format. To create a Java keystore from |
| existing certificates (CA certificate, and public and private keys), you must first create a PKCS12 keystore from them, |
| for example with `openssl`; this can then be converted into a Java keystore with `keytool`. For example, with |
| a CA certificate `ca.pem`, and public and private keys `cert.pem` and `key.pem`, create the PKCS12 store `server.p12`, |
| and then convert it into a keystore `keystore.jks` as follows: |
| |
| {% highlight bash %} |
| % openssl pkcs12 -export -in cert.pem -inkey key.pem \ |
| -out server.p12 -name "brooklyn" \ |
| -CAfile ca.pem -caname root -chain -passout pass:"password" |
| |
| % keytool -importkeystore \ |
| -deststorepass "password" -destkeypass "password" -destkeystore keystore.jks \ |
| -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass "password" \ |
| -alias "brooklyn" |
| {% endhighlight %} |
| |
| |
| ## HTTPS Configuration |
| |
| In [`org.ops4j.pax.web.cfg`](/guide/ops/paths.md) in the Brooklyn distribution root, un-comment the settings: |
| |
| {% highlight properties %} |
| org.osgi.service.http.port.secure=8443 |
| org.osgi.service.http.secure.enabled=true |
| org.ops4j.pax.web.ssl.keystore=${karaf.home}/etc/keystores/keystore.jks |
| org.ops4j.pax.web.ssl.password=password |
| org.ops4j.pax.web.ssl.keypassword=password |
| org.ops4j.pax.web.ssl.key.alias=brooklyn |
| org.ops4j.pax.web.ssl.clientauthwanted=false |
| org.ops4j.pax.web.ssl.clientauthneeded=false |
| {% endhighlight %} |
| |
| replacing the passwords with appropriate values, and restart the server. Note the keystore location is relative to |
| the installation root, but a fully qualified path can also be given, if it is desired to use some separate pre-existing |
| store. |
| |
| ### Which certificate gets served (SNI) |
| |
| When a client opens an HTTPS connection it normally sends the hostname it is trying to reach as a TLS |
| *Server Name Indication* (SNI) extension. The server matches that hostname against the CN and Subject |
| Alternative Names of every certificate in the keystore and presents the one that matches. **This hostname |
| matching takes precedence over `org.ops4j.pax.web.ssl.key.alias`.** The alias property only chooses the |
| certificate for clients that send no SNI, or whose hostname matches no certificate in the keystore. |
| |
| In practice this means: |
| |
| * Make sure your certificate's CN — and ideally a Subject Alternative Name — matches the hostname your |
| users actually use, for example by creating it with `-ext SAN=dns:brooklyn.example.com`. Browsers always |
| send SNI, so they are then served your certificate automatically, regardless of the alias setting. |
| * A keystore may contain a default self-signed certificate, either shipped with a distribution or created |
| when the server first started. As long as that default does not claim the same hostname as yours it never |
| shadows your certificate — it is only used as the SNI fallback. A well-chosen default uses a name that |
| cannot match a real host, such as `CN=default`. If a default certificate *does* claim your hostname — for |
| example one with `CN=localhost` when your users reach the server as `localhost` — remove or replace it. |
| * `org.ops4j.pax.web.ssl.key.alias` is still worth setting — it selects which certificate is served as the |
| fallback to clients that send no SNI — but on its own it does **not** override SNI hostname matching. |
| |
| After restarting, you can verify which certificate is actually being served. Pass the real hostname as the SNI |
| name with `-servername`, because that is what browsers send; testing with a hostname that happens to match a |
| different certificate (such as `localhost` against a default `CN=localhost` certificate) is misleading: |
| |
| {% highlight bash %} |
| % openssl s_client -connect <host>:8443 -servername <host> </dev/null 2>/dev/null \ |
| | openssl x509 -noout -subject -issuer -serial -dates |
| {% endhighlight %} |
| |
| To enable HTTPS _only_, i.e. to disable HTTP, add the following line to this file: |
| |
| {% highlight properties %} |
| org.osgi.service.http.enabled=false |
| {% endhighlight %} |
| |