This is an automated email from the ASF dual-hosted git repository.

epugh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new 5bee23c9dea SOLR-17137 - Add configuration for SSL between Solr and 
Prometheus exporter. (#2232)
5bee23c9dea is described below

commit 5bee23c9dea32f9262a6d8cf279a03b141636ee1
Author: Eivind Bergstøl <[email protected]>
AuthorDate: Fri May 31 20:34:23 2024 +0200

    SOLR-17137 - Add configuration for SSL between Solr and Prometheus 
exporter. (#2232)
    
    When running Solr with mTLS the exporter also needs to use mTLS to be
    able to talk to Solr api.
    
    This commit also adds a bats test that verifies that solr exporter actually 
scrape the running
    solr instance by verifying information about a newly made core is present.
---
 solr/CHANGES.txt                                   |  2 +
 solr/packaging/build.gradle                        |  1 +
 solr/packaging/test/bats_helper.bash               |  7 +++-
 solr/packaging/test/test_prometheus.bats           | 49 ++++++++++++++++++++++
 solr/prometheus-exporter/bin/solr-exporter         |  8 ++++
 solr/prometheus-exporter/bin/solr-exporter.cmd     |  2 +
 .../prometheus/exporter/SolrClientFactory.java     | 11 +++++
 .../solr/prometheus/exporter/SolrExporter.java     | 30 +++++++++++++
 .../exporter/SolrScrapeConfiguration.java          | 39 +++++++++++++++++
 .../monitoring-with-prometheus-and-grafana.adoc    | 11 +++++
 10 files changed, 159 insertions(+), 1 deletion(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index e9b495d449c..0b9cefd275b 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -113,6 +113,8 @@ New Features
 
 Improvements
 ---------------------
+* SOLR-17137: Enable Prometheus exporter to communicate with SSL protected 
Solr. (Eivind Bergstøl via Eric Pugh)
+
 * SOLR-16921: use -solrUrl to derive the zk host connection for bin/solr zk 
subcommands (Eric Pugh)
 
 * SOLR-14115: Add linkconfig, cluster, and updateacls as commands to SolrCLI.  
Allow bin/solr commands to have parity with zkcli.sh commands. (Eric Pugh)
diff --git a/solr/packaging/build.gradle b/solr/packaging/build.gradle
index cc48294880a..bf816677a02 100644
--- a/solr/packaging/build.gradle
+++ b/solr/packaging/build.gradle
@@ -267,6 +267,7 @@ task integrationTests(type: BatsTask) {
   environment SOLR2_PORT: solrPort + 1
   environment SOLR3_PORT: solrPort + 2
   environment ZK_PORT: solrPort + 1000
+  environment SOLR_EXPORTER_PORT: solrPort + 100
   environment SOLR_LOGS_DIR: "$solrHome/logs"
   environment TEST_OUTPUT_DIR: integrationTestOutput
   environment TEST_FAILURE_DIR: solrTestFailuresDir
diff --git a/solr/packaging/test/bats_helper.bash 
b/solr/packaging/test/bats_helper.bash
index 56c743c8fb2..ccc2aabf2c9 100644
--- a/solr/packaging/test/bats_helper.bash
+++ b/solr/packaging/test/bats_helper.bash
@@ -33,7 +33,7 @@ common_setup() {
     load "${BATS_LIB_PREFIX}/bats-assert/load.bash"
     load "${BATS_LIB_PREFIX}/bats-file/load.bash"
 
-    PATH="${SOLR_TIP:-.}/bin:$PATH"
+    PATH="${SOLR_TIP:-.}/bin:${SOLR_TIP:-.}/prometheus-exporter/bin:$PATH"
     export SOLR_ULIMIT_CHECKS=false
 }
 
@@ -62,6 +62,11 @@ shutdown_all() {
   solr stop -all >/dev/null 2>&1
 }
 
+shutdown_exporter(){
+  EXPORTER_PID=$(ps auxww | grep 
org.apache.solr.prometheus.exporter.SolrExporter | awk "/-classpath/"' {print 
$2}' | sort -r)
+  kill -9 $EXPORTER_PID
+}
+
 delete_all_collections() {
   local collection_list="$(solr zk ls /collections -z localhost:${ZK_PORT})"
   for collection in $collection_list; do
diff --git a/solr/packaging/test/test_prometheus.bats 
b/solr/packaging/test/test_prometheus.bats
new file mode 100644
index 00000000000..25353a7e0ab
--- /dev/null
+++ b/solr/packaging/test/test_prometheus.bats
@@ -0,0 +1,49 @@
+#!/usr/bin/env bats
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load bats_helper
+
+setup() {
+  common_clean_setup
+}
+
+teardown() {
+  # save a snapshot of SOLR_HOME for failed tests
+  save_home_on_failure
+
+  solr stop -all >/dev/null 2>&1
+  
+  shutdown_exporter
+}
+
+@test "should start solr prometheus exporter that scrapes solr for metrics" {
+  solr start
+  solr assert --started http://localhost:${SOLR_PORT}/solr --timeout 5000
+  
+  run solr create -c COLL_NAME
+  assert_output --partial "Created new core 'COLL_NAME'"
+ 
+  echo "# starting solr-exporter on ${SOLR_EXPORTER_PORT}" >&3
+  run solr-exporter -p $SOLR_EXPORTER_PORT -b 
http://localhost:${SOLR_PORT}/solr >&3 &
+
+  sleep 5
+
+  run curl "http:/localhost:$SOLR_EXPORTER_PORT/"
+  
+  assert_output --partial 'solr_metrics_core_query_requests_total'
+  assert_output --partial 'core="COLL_NAME"'
+}
diff --git a/solr/prometheus-exporter/bin/solr-exporter 
b/solr/prometheus-exporter/bin/solr-exporter
index 06504457431..b15f7ff9339 100755
--- a/solr/prometheus-exporter/bin/solr-exporter
+++ b/solr/prometheus-exporter/bin/solr-exporter
@@ -129,6 +129,14 @@ if [[ -n "$CLUSTER_ID" ]]; then
   EXPORTER_ARGS+=(-i "$CLUSTER_ID")
 fi
 
+if [[ -n "$CREDENTIALS" ]]; then
+  EXPORTER_ARGS+=(-u "$CREDENTIALS")
+fi
+
+if [[ -n "$SSL_ENABLED" ]]; then
+  EXPORTER_ARGS+=(-ssl "$SSL_ENABLED")
+fi
+
 exec "$JAVACMD" \
   $JAVA_MEM_OPTS \
   $GC_TUNE \
diff --git a/solr/prometheus-exporter/bin/solr-exporter.cmd 
b/solr/prometheus-exporter/bin/solr-exporter.cmd
index e89b4042ae2..568f4f8b71d 100644
--- a/solr/prometheus-exporter/bin/solr-exporter.cmd
+++ b/solr/prometheus-exporter/bin/solr-exporter.cmd
@@ -83,6 +83,8 @@ IF NOT "%NUM_THREADS%"=="" set EXPORTER_ARGS=%EXPORTER_ARGS% 
-n %NUM_THREADS%
 IF NOT "%ZK_HOST%"=="" set EXPORTER_ARGS=%EXPORTER_ARGS% -z %ZK_HOST%
 IF NOT "%SOLR_URL%"=="" set EXPORTER_ARGS=%EXPORTER_ARGS% -b %SOLR_URL%
 IF NOT "%CLUSTER_ID%"=="" set EXPORTER_ARGS=%EXPORTER_ARGS% -i "%CLUSTER_ID%"
+IF NOT "%CREDENTIALS%"=="" set EXPORTER_ARGS=%EXPORTER_ARGS% -u "%CREDENTIALS%"
+IF NOT "%SSL_ENABLED%"=="" set EXPORTER_ARGS=%EXPORTER_ARGS% -ssl 
"%SSL_ENABLED%"
 goto endInit
 
 @REM Reaching here means variables are defined and arguments have been captured
diff --git 
a/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrClientFactory.java
 
b/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrClientFactory.java
index c1c4a891593..ede2495c452 100644
--- 
a/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrClientFactory.java
+++ 
b/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrClientFactory.java
@@ -21,6 +21,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
+import org.apache.solr.client.solrj.embedded.SSLConfig;
 import org.apache.solr.client.solrj.impl.CloudHttp2SolrClient;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.impl.Http2SolrClient;
@@ -49,6 +50,16 @@ public class SolrClientFactory {
       builder.withBasicAuthCredentials(
           configuration.getBasicAuthUser(), configuration.getBasicAuthPwd());
     }
+    if (configuration.isSSLEnabled()) {
+      builder.withSSLConfig(
+          new SSLConfig(
+              true,
+              true,
+              configuration.getSslConfiguration().keystorePath.toString(),
+              configuration.getSslConfiguration().keystorePassword,
+              configuration.getSslConfiguration().trustStorePath.toString(),
+              configuration.getSslConfiguration().trustStorePassword));
+    }
     return builder;
   }
 
diff --git 
a/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrExporter.java
 
b/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrExporter.java
index 946df18cd78..57b5c52e6e9 100644
--- 
a/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrExporter.java
+++ 
b/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrExporter.java
@@ -21,6 +21,7 @@ import io.prometheus.client.exporter.HTTPServer;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.net.InetSocketAddress;
+import java.nio.file.Paths;
 import java.util.concurrent.ExecutorService;
 import net.sourceforge.argparse4j.ArgumentParsers;
 import net.sourceforge.argparse4j.inf.ArgumentParser;
@@ -103,6 +104,13 @@ public class SolrExporter {
   private static final String ARG_CREDENTIALS_HELP =
       "Specify the credentials in the format username:password. Example: 
--credentials solr:SolrRocks";
 
+  private static final String[] ARG_SSL_FLAGS = {"-ssl", "--ssl-enabled"};
+  private static final String ARG_SSL_METAVAR = "SSL_ENABLED";
+  private static final String ARG_SSL_DEST = "ssl_enabled";
+  private static final boolean ARG_SSL_DEFAULT = false;
+  private static final String ARG_SSL_HELP =
+      "Enable TLS connection to Solr. Expects following env variables: 
SOLR_SSL_KEY_STORE, SOLR_SSL_KEY_STORE_PASSWORD, SOLR_SSL_TRUST_STORE, 
SOLR_SSL_TRUST_STORE_PASSWORD. Example: --ssl-enabled";
+
   public static final CollectorRegistry defaultRegistry = new 
CollectorRegistry();
 
   private final int port;
@@ -257,6 +265,14 @@ public class SolrExporter {
         .setDefault(ARG_CREDENTIALS_DEFAULT)
         .help(ARG_CREDENTIALS_HELP);
 
+    parser
+        .addArgument(ARG_SSL_FLAGS)
+        .metavar(ARG_SSL_METAVAR)
+        .dest(ARG_SSL_DEST)
+        .type(Boolean.class)
+        .setDefault(ARG_SSL_DEFAULT)
+        .help(ARG_SSL_HELP);
+
     try {
       Namespace res = parser.parseArgs(args);
 
@@ -289,6 +305,16 @@ public class SolrExporter {
         }
       }
 
+      if (Boolean.TRUE.equals(res.getBoolean(ARG_SSL_DEST))) {
+        log.info("SSL ENABLED");
+
+        scrapeConfiguration.withSslConfiguration(
+            Paths.get(getSystemVariable("SOLR_SSL_KEY_STORE")),
+            getSystemVariable("SOLR_SSL_KEY_STORE_PASSWORD"),
+            Paths.get(getSystemVariable("SOLR_SSL_TRUST_STORE")),
+            getSystemVariable("SOLR_SSL_TRUST_STORE_PASSWORD"));
+      }
+
       SolrExporter solrExporter =
           new SolrExporter(
               port,
@@ -329,4 +355,8 @@ public class SolrExporter {
       throw new RuntimeException(e);
     }
   }
+
+  private static String getSystemVariable(String name) {
+    return System.getProperty(name, System.getenv(name));
+  }
 }
diff --git 
a/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrScrapeConfiguration.java
 
b/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrScrapeConfiguration.java
index f61447b810d..e0550ddc9c4 100644
--- 
a/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrScrapeConfiguration.java
+++ 
b/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/exporter/SolrScrapeConfiguration.java
@@ -17,6 +17,7 @@
 
 package org.apache.solr.prometheus.exporter;
 
+import java.nio.file.Path;
 import java.util.Optional;
 
 public class SolrScrapeConfiguration {
@@ -26,12 +27,34 @@ public class SolrScrapeConfiguration {
     STANDALONE
   }
 
+  public static class SslConfiguration {
+
+    public final Path keystorePath;
+    public final String keystorePassword;
+    public final Path trustStorePath;
+    public final String trustStorePassword;
+
+    public SslConfiguration(
+        Path keystorePath,
+        String keystorePassword,
+        Path trustStorePath,
+        String trustStorePassword) {
+      this.keystorePath = keystorePath;
+      this.keystorePassword = keystorePassword;
+      this.trustStorePath = trustStorePath;
+      this.trustStorePassword = trustStorePassword;
+    }
+  }
+
   private final ConnectionType type;
   private final String zookeeperConnectionString;
   private final String solrHost;
   private String basicAuthUser;
   private String basicAuthPwd;
 
+  private boolean sslEnabled = false;
+  private SslConfiguration sslConfiguration;
+
   private SolrScrapeConfiguration(
       ConnectionType type, String zookeeperConnectionString, String solrHost) {
     this.type = type;
@@ -73,6 +96,22 @@ public class SolrScrapeConfiguration {
     return basicAuthPwd;
   }
 
+  public SolrScrapeConfiguration withSslConfiguration(
+      Path keystorePath, String keystorePassword, Path trustStorePath, String 
trustStorePassword) {
+    this.sslEnabled = true;
+    this.sslConfiguration =
+        new SslConfiguration(keystorePath, keystorePassword, trustStorePath, 
trustStorePassword);
+    return this;
+  }
+
+  public boolean isSSLEnabled() {
+    return this.sslEnabled;
+  }
+
+  public SslConfiguration getSslConfiguration() {
+    return sslConfiguration;
+  }
+
   @Override
   public String toString() {
     if (type == ConnectionType.CLOUD) {
diff --git 
a/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc
 
b/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc
index 04dcc731ff8..3ed5b081cda 100644
--- 
a/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc
+++ 
b/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc
@@ -183,6 +183,17 @@ A unique ID for the cluster to monitor. This ID will be 
added to all metrics as
 Specify the credentials in the format `username:password`. Example: 
`--credentials solr:SolrRocks`.
 
 
+`-ssl`, `--ssl-enabled`, `$SSL_ENABLED`::
++
+[%autowidth,frame=none]
+|===
+|Optional |Default: false
+|===
++
+
+Enable mTLS connection to Solr. Expects following env variables: 
SOLR_SSL_KEY_STORE, SOLR_SSL_KEY_STORE_PASSWORD, SOLR_SSL_TRUST_STORE, 
SOLR_SSL_TRUST_STORE_PASSWORD. Example: `--ssl-enabled`
+The environment variables are the same that Solr uses to enable mTLS.
+
 === Environment Variable Options
 
 The `./bin` scripts provided with the Prometheus Exporter support the use of 
custom java options through the following environment variables:

Reply via email to