Enable peer verification of remote RabbitMq server

By checking the received certificate and fail to make a connection
if the verification fail.

Solves: Jira GER-1791
Change-Id: Ibb38a84b48039b62077939592425007cb23335bd
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/config/RabbitMqConfig.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/config/RabbitMqConfig.java
index 353cc21..e52fcff 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/config/RabbitMqConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/config/RabbitMqConfig.java
@@ -23,12 +23,17 @@
 import com.google.inject.Singleton;
 import com.rabbitmq.client.AMQP;
 import com.rabbitmq.client.ConnectionFactory;
+import java.io.FileInputStream;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
 import java.security.KeyManagementException;
+import java.security.KeyStore;
 import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateFactory;
 import java.util.Date;
 import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
 import org.eclipse.jgit.lib.Config;
 
 @Singleton
@@ -45,6 +50,7 @@
     private static final String VIRTUAL_HOST = "virtualHost";
     private static final String WAIT_FOR_CONFIRM = "waitForConfirm";
     private static final String MAX_BATCH_SIZE = "maxBatchSize";
+    private static final String CERTIFICATE = "certificate";
     private static final boolean DEFAULT_PERSISTENT_DELIVERY = true;
     private static final long DEFAULT_WAIT_FOR_CONFIRM = 5000;
     private static final int DEFAULT_MAX_BATCH_SIZE = 1;
@@ -64,6 +70,7 @@
               cfg.getBoolean(RABBIT_MQ, null, PERSISTENT_DELIVERY, DEFAULT_PERSISTENT_DELIVERY),
               cfg.getString(RABBIT_MQ, null, ROUTING_KEY_TAG),
               cfg.getString(RABBIT_MQ, null, APP_ID),
+              cfg.getString(RABBIT_MQ, null, CERTIFICATE),
               ConfigUtil.getTimeUnit(
                   cfg,
                   RABBIT_MQ,
@@ -105,6 +112,7 @@
       boolean persistentDelivery,
       String routingKey,
       String appId,
+      String certificatePath,
       long waitForConfirms,
       int maxBatchSize) {
     this.exchange = exchange;
@@ -119,7 +127,38 @@
       this.connectionFactory = null;
       return;
     }
+
     ConnectionFactory cf = new ConnectionFactory();
+
+    if (certificatePath != null) {
+      try {
+        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+
+        KeyStore tks = KeyStore.getInstance("JKS");
+        tks.load(null);
+        tks.setCertificateEntry(
+            "server_certificate",
+            certificateFactory.generateCertificate(new FileInputStream(certificatePath)));
+
+        TrustManagerFactory tmf =
+            TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        tmf.init(tks);
+
+        SSLContext c = SSLContext.getInstance("TLSv1.3");
+        c.init(null, tmf.getTrustManagers(), null);
+
+        cf.useSslProtocol(c);
+        cf.enableHostnameVerification();
+      } catch (Exception e) {
+        logger.atSevere().withCause(e).log(
+            "Failed to setup certificate for peer-verification of RabbitMQ-server");
+        this.connectionFactory = null;
+        return;
+      }
+    } else {
+      logger.atInfo().log("No certificate provided, continuing without peer verification.");
+    }
+
     try {
       cf.setUri(uri);
     } catch (KeyManagementException | NoSuchAlgorithmException | URISyntaxException e) {
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index b3fa201..e68d8ba 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -12,6 +12,7 @@
       password = secret
       waitForConfirms = 7 seconds
       maxBatchSize = 100
+      certificate = /path/to/certificate.crt
     [EiffelRepoClient]
       graphQlUrl = https://eiffel.company.com/graphql
       goRestUrl = https://eiffel.company.com/rest/
@@ -76,6 +77,10 @@
   If confirms are disabled this option has no real effect.
   (Default: _1_.)
 
+certificate
+: The certificate used for peer verification of server. If no certificate is set
+we will trust anyone.
+
 ## Section "EiffelRepoClient" ##
 
 Configuration for connecting to the