Hot questions for Using Azure in ssl

Question:

I need to use Azure Redis Cluster, with password, with SSL, with pipelining support.

I was using Jedis until now but it lacks support for cluster+ssl+password+pipelining combo.

I tried lettuce (https://github.com/mp911de/lettuce/releases/tag/4.1.2.Final) and currently hit a connection issue I am not able to solve on my own.

Connecting to an Azure Redis Cluster (2 * P4) works without SSL but not with. Also I can connect to a single node with SSL but without cluster support. Problem is when combining cluster+ssl, the auth call times out (the command is sent over the wire but times out).

The cluster without SSL working code looks like this:

RedisURI redisURI = RedisURI.Builder.redis(host, 6379)
  .withPassword(password)
  .build();
RedisClusterClient client = RedisClusterClient.create(redisURI);
RedisAdvancedClusterCommands<String, String> connection = client.connect().sync();
connection.set("a", "1");
System.out.println(connection.get("a"));

Output is 1

Enabling SSL:

RedisURI redisURI = RedisURI.Builder.redis(host, 6380)
  .withPassword(password)
  .withSsl(true)
  .build();
RedisClusterClient client = RedisClusterClient.create(redisURI);
RedisAdvancedClusterCommands<String, String> connection = client.connect().sync();
connection.set("a", "1");
System.out.println(connection.get("a"));

It hangs during 1 minute and log4j logs looks like this:

2016-05-26 14:25:17,110 | TRACE | lettuce-nioEventLoop-3-1 | CommandEncoder | [/{CLIENT} -> {HOST}/{IP}:6380] Sent: *2
$4
AUTH
$44
{PASSWORD}
2016-05-26 14:26:17,134 | WARN  | main | ClusterTopologyRefresh | Cannot connect to RedisURI [host='***', port=6380]
com.lambdaworks.redis.RedisCommandTimeoutException: Command timed out
    at com.lambdaworks.redis.LettuceFutures.await(LettuceFutures.java:95)
    at com.lambdaworks.redis.LettuceFutures.awaitOrCancel(LettuceFutures.java:74)
    at com.lambdaworks.redis.AbstractRedisAsyncCommands.auth(AbstractRedisAsyncCommands.java:64)
    at com.lambdaworks.redis.cluster.RedisClusterClient.connectToNode(RedisClusterClient.java:342)
    at com.lambdaworks.redis.cluster.RedisClusterClient.connectToNode(RedisClusterClient.java:301)
    at com.lambdaworks.redis.cluster.ClusterTopologyRefresh.getConnections(ClusterTopologyRefresh.java:240)
    at com.lambdaworks.redis.cluster.ClusterTopologyRefresh.loadViews(ClusterTopologyRefresh.java:132)
    at com.lambdaworks.redis.cluster.RedisClusterClient.loadPartitions(RedisClusterClient.java:468)
    at com.lambdaworks.redis.cluster.RedisClusterClient.initializePartitions(RedisClusterClient.java:445)
    at com.lambdaworks.redis.cluster.RedisClusterClient.connectClusterImpl(RedisClusterClient.java:359)
    at com.lambdaworks.redis.cluster.RedisClusterClient.connect(RedisClusterClient.java:244)
    at com.lambdaworks.redis.cluster.RedisClusterClient.connect(RedisClusterClient.java:231)
    at com.ubikod.ermin.reach.tools.Test.main(Test.java:20)
Exception in thread "main" com.lambdaworks.redis.RedisException: Cannot retrieve initial cluster partitions from initial URIs [RedisURI [host='***', port=6380]]
    at com.lambdaworks.redis.cluster.RedisClusterClient.loadPartitions(RedisClusterClient.java:471)
    at com.lambdaworks.redis.cluster.RedisClusterClient.initializePartitions(RedisClusterClient.java:445)
    at com.lambdaworks.redis.cluster.RedisClusterClient.connectClusterImpl(RedisClusterClient.java:359)
    at com.lambdaworks.redis.cluster.RedisClusterClient.connect(RedisClusterClient.java:244)
    at com.lambdaworks.redis.cluster.RedisClusterClient.connect(RedisClusterClient.java:231)
    at com.ubikod.ermin.reach.tools.Test.main(Test.java:20)

Keeping SSL and disabling cluster works:

RedisURI redisURI = RedisURI.Builder.redis(host, 6380)
  .withPassword(password)
  .withSsl(true)
  .build();
RedisClient client = RedisClient.create(redisURI);
RedisCommands<String, String> connection = client.connect().sync();
connection.set("a", "1");
System.out.println(connection.get("a"));

So that's not just an SSL issue, its a SSL + cluster combo issue. I tried to use withStartTls, disabling peer verification, raising the timeout, any combination of those without luck.

Any idea if it's a library bug or an Azure Redis bug?


Answer:

I inspected the wiki page of lettuce, and I noticed the issue was not caused by a library bug or an Azure Redis bug, unfortunately, just only the lettuce not support Redis Cluster with SSL, please see the content below from the subsection Connecting to Redis using String RedisURI of the wiki page.

lettuce supports SSL only on regular Redis connections. Master resolution using Redis Sentinel or Redis Cluster are not supported since both strategies provide Redis addresses to the native port. Redis Sentinel and Redis Cluster cannot provide the SSL ports.

Question:

I am currently working on a Java 8 app with Vaadin and Hibernate which I am trying to migrate to Azure for testing purposes. Everything worked out so far except for one thing: When I activate the require SSL option in The MariaDB on Azure, I can't connect anymore:

Caused by: java.sql.SQLException: SSL connection is required. Please specify SSL options and retry.

Unfortunately I didn't write this app myself and I am not too familiar with neither Vaadin nor Hibernate or even Java in general and how to establish ssl or db connections with those.So I need some help:

This is the JDBC Connection string in the Servlet.java file, where for my understanding the db init happens:

Connection con = DriverManager.getConnection("jdbc:mysql://<username>.mariadb.database.azure.com:3306/<db>?autoReconnect=true", "<username>", "<password>");

which I changed by just adding this to the URL: &useSSL=true&requireSSL=true&verifyServerCertificate=true

Now the app doesn't stop at the DB init anymore but still crashes before the page is fully rendered, with the same error message.

I found a hibernate.cfg.xml with the following content (I removed the mappings to keep it shorter):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <!-- Hibernate -->
        <property name="hibernate.use_sql_comments">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="hibernate.show_sql">false</property>
        <property name="hibernate.connection.autocommit">true</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>

        <!-- Hikari -->
        <property name="hibernate.connection.provider_class">com.zaxxer.hikari.hibernate.HikariConnectionProvider</property>
        <property name="hibernate.hikari.dataSourceClassName">com.mysql.jdbc.jdbc2.optional.MysqlDataSource</property>
        <property name="hibernate.hikari.dataSource.url">jdbc:mysql://dbname.mariadb.database.azure.com:3306/db</property>
        <property name="hibernate.hikari.dataSource.user">username</property>
        <property name="hibernate.hikari.dataSource.password">password</property>
        <property name="hibernate.hikari.dataSource.cachePrepStmts">true</property>
        <property name="hibernate.hikari.dataSource.prepStmtCacheSize">250</property>
        <property name="hibernate.hikari.dataSource.prepStmtCacheSqlLimit">2048</property>
        <property name="hibernate.hikari.dataSource.useServerPrepStmts">true</property>
    </session-factory>

</hibernate-configuration>

What do I have to change there to make use of SSL for the connection?


Answer:

You may try:

<property name="hibernate.hikari.dataSource.url">jdbc:mysql://dbname.mariadb.database.azure.com:3306/db?useSSL=true</property>

Per my understanding, the properties in hibernate.cfg.xml will finally be used to generate a whole connection string. So, if there is no direct property for useSSL, you may add it to the url manually.

Question:

I am trying to enforce https on an Azure java web app running on tomcat 1.7. (The application wa created using the portal) I have added the below web.config to the site/wwwroot directory. This is correctly redirecting the non http calls via https, but inside the application the request appears to have a http rather than https.

<configuration>
<system.webServer>
<handlers>
  <add name="httpPlatformHandler" path="*"
       verb="*" modules="httpPlatformHandler"
       resourceType="Unspecified" />
</handlers>

<httpPlatform processPath="%AZURE_TOMCAT7_HOME%\bin\startup.bat">
</httpPlatform>
<rewrite>
  <rules>
    <rule name="Force HTTPS" enabled="true" stopProcessing="true">
      <match url="(.*)" ignoreCase="false" />
      <conditions>
        <add input="{HTTPS}" pattern="off" />
      </conditions>
      <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
    </rule>
  </rules>
</rewrite>
</system.webServer>
</configuration>

I think it might be standard behavior for the application to be showing http rather than https, but i was certainly expecting the below to render true

HttpServletRequest request
request.isSecure()  //this should be true
request.getScheme() //Ideally should be https but is http

Is there anything I need to add to my web.config file?

not sure if it makes much difference but I am using CA signed wild card certificate which I have also uploaded through portal. This is definately working becasue before I couldnt make https calls on my web app and after the certificate upload I was able to make the calls.

Thanks in advance for your help.


Answer:

Just to answer the problem domain of editing configuration, there are 3 methods of using Java with Azure App Service:

1) enable through the portal. This method is great when uploading a war file but you cannot change configuration for the web container.

2) deploy Tomcat or Jetty from the Marketplace/gallery. When you do this you get a complete install of Tomcat or Jetty in your space that you can edit or alter to your hearts content

3) upload a custom app including your own jvm if desired. If you go this route there are a few things you need to keep in mind that are described in the Azure documentation.

With respect to SSL, due to the need in App Service to support a multitude of frameworks, SSL is supported upstream of the app. You don't need to enable the HTTPS connector in Tomcat or locally set a trust store or any of those fun things. Use the information here: http://azure.microsoft.com/en-us/documentation/articles/web-sites-configure-ssl-certificate/ to enable HTTPS for your site.

Question:

I want to deploy a Spring Boot Application, generated with JHipster, to Azure App Service and enable HTTPS/SSL. I bought an App Service Certificate and bound it to a custom domain of my app service. How can I use that certificate in a config file of my Spring Application?

I also set the WEBSITE_LOAD_CERTIFICATES variable to my ceritificate's thumbprint.

server:
    port: 443
    ssl:
        key-store: keystore.p12
        key-store-password: <your-password>
        keyStoreType: PKCS12
        keyAlias: <your-application>

I don't know how to access the certificate from here. What is the path to the keystore, and how do I obtain the password and key alias?


Answer:

You just need to configure the SSL certificate to your web app on Azure portal.

Because there is a front tier before your spring boot application. The front tier will handle the security connections (HTTPS) with clients, but communicate with your web app with HTTP.

For more detailed explanation, you may refer to this post: Is current request being made over SSL with Azure deployment