Using SSL in Azure VM in cloudapp.azure.com domains with ZeroSSL

Michel Fernandes
BeyondLabsEY
Published in
5 min readFeb 16, 2018

The VM from Azure, when is setup to use domain names comes with cloudapp domain, which may vary, but essentially is <your server name>.cloudapp.com.

Since we are not owner from cloudapp.com is not possible to use Let's Encrypt or other kind of SSLs providers due to DNS check. But, here comes ZeroSSL.

ZeroSSL, is a provider from Let's Encrypt. It makes easier the process to get a certificate. The easy part is ZeroSSL allows checking using a file name serving in the website, not only with DNS entry, more common in SSL providers, including Let's Encrpyt.

My goal was to setup a SSL connection of my JIRA and Confluence applications, so let’s configure with this use case.

Step 1: Filling the forms

Access the Certificate Wizard from ZeroSSL using this link. You may try accessing directly from ZeroSSL site as well, using the URL https://zerossl.com.

Make sure you have accepted the Terms of Services both from ZeroSSL and Let's Encrypt.

Important: mark HTTP verification.

Step 2: download the certificate and key

Click Next.

Will be asked about "Include www-prefixed version too?". For Azure VMs there is no www prefix, so select No.

Now, download the Domain CSR file, and click Next for key generation.

As previously, download the Account Key.

Step 3: HTTP verification

This step is the verification.

You need to create the folder ".well-known/acme-challenge" inside your webroot folder. Then, create a file with the name provided (green arrow). Open it, then paste the content of yellow arrow. It’s pretty straightforward.

If you run a own web application, with freedom to create addition folders and files, just create them.

In my case I use the JIRA, so it would be very difficult to change these configurations just to make this checking. To accomplish that, we can use the SimpleHTTPServer from Python.

First, let's create the files, in Linux systems, we can do as follows:

mkdir -p .well-known/acme-challenge/
nano .well-known/acme-challenge/<file_name_provided>

Then just paste the provided content. (Yes, I hate vim 😝)

Now, let's start the SimpelHTTPServer.

The files served by the web server will be the same in the directory when it is running.

As I have Jira running, let's stop for while.

sudo service jira stop

Now, let's start our temporary web server.

python -m SimpleHTTPServer 8080

Ok, now we can click Next to procede with verification.

And… voilà!

Now, save your Account ID.

And the Certificate and Key.

The next steps is for Jira and Confluence configuration, if you know how to use your certificate and key, you are ready to go 😁.

Step 4: Jira/Confluence configuration

Now, to use our certificate in Jira/Confluence webserver, it is necessary to convert the CRT file in JKS format. Seems difficult, but is pretty easy.

The conversion requires two steps: first convert the CRT file in PKCS12, then secondly, PKCS12 to JKS.

Let's convert first our files to PKCS12 format, using openssl. Will be asked for a password, pick one.

openssl pkcs12 -export -in host.crt -inkey host.key > host.p12

The conversion to JKS format requires the keytool. This application usually resides in bin folder of JRE installed. In Jira/Confluence environment is located inside the application folder, in "/opt/atlassian/jira or confluence/jre/bin".

Will be prompted to choose a password, pick one with at least 6 characters, and save it.

Let's give a try.

/opt/atlassian/jira/jre/bin/keytool -importkeystore -srckeystore host.p12 -destkeystore host.jks -srcstoretype pkcs12

As result we have the host.jks.

Let's copy to Jira/Confluence application root.

sudo cp host.jks /opt/atlassian/jira/

With the JKS file and password, now we need to update that in configuration files.

First let's edit the file located at /opt/atlassian/jira or confluence/conf/server.xml.

Here, we need to change the redirect port to 443, when user try to access using port 80.

<Connector port="8080"maxThreads="150"minSpareThreads="25"connectionTimeout="20000"enableLookups="false"maxHttpHeaderSize="8192"protocol="HTTP/1.1"useBodyEncodingForURI="true"redirectPort="443"acceptCount="100"disableUploadTimeout="true"bindOnInit="false"/>

Why 443 and not 8443?

Simple, the web application is not running under root access. I use the iptables to redirect request from 8080 to 80. If we keep the redirect port 8443, when user try to access using port 80, will be redirect to 8443, not 443.

Finally, change the keystore file and include the password.

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"maxHttpHeaderSize="8192" SSLEnabled="true"maxHttpHeaderSize="8192" SSLEnabled="true"maxThreads="150" minSpareThreads="25"enableLookups="false" disableUploadTimeout="true"acceptCount="100" scheme="https" secure="true"clientAuth="false" sslProtocol="TLS" useBodyEncodingForURI="true"keystoreFile="host.jks" keystorePass="your_password"/>

Last, edit the web.xml file in /opt/atlassian/jira or confluence/atlassian_jira or confluence/WEB_INF/web.xml and put, before </web-app> tag:

<security-constraint>
<web-resource-collection>
<web-resource-name>Restricted URLs</web-resource-name>
<url-pattern>/</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>

Restart the services, and you ready to have a more secured web application 😎.

The certificates will last 90 days, keep it checking to renew properly.

--

--

Michel Fernandes
BeyondLabsEY

Solution Architect at EY and Teacher at FIAP. Helping everyone in journey to the cloud and practice of machine learning and visual computing.