Skip to content

Commit

Permalink
DRILL-8503: Add Configuration Option to Skip Host Validation for Splu…
Browse files Browse the repository at this point in the history
…nk (#2927)
  • Loading branch information
cgivre committed Jul 24, 2024
1 parent c0c2605 commit ac98f34
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 26 deletions.
31 changes: 16 additions & 15 deletions contrib/storage-splunk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@ This plugin enables Drill to query Splunk.

## Configuration

| Option | Default | Description | Since |
| -------------------- | --------- | --------------------------------------------------------------- | ----- |
| type | (none) | Set to "splunk" to use this plugin | 1.19 |
| username | null | Splunk username to be used by Drill | 1.19 |
| password | null | Splunk password to be used by Drill | 1.19 |
| scheme | https | The scheme with which to access the Splunk host | 2.0 |
| hostname | localhost | Splunk host to be queried by Drill | 1.19 |
| port | 8089 | TCP port over which Drill will connect to Splunk | 1.19 |
| earliestTime | null | Global earliest record timestamp default | 1.19 |
| latestTime | null | Global latest record timestamp default | 1.19 |
| app | null | The application context of the service[^1] | 2.0 |
| owner | null | The owner context of the service[^1] | 2.0 |
| token | null | A Splunk authentication token to use for the session[^2] | 2.0 |
| cookie | null | A valid login cookie | 2.0 |
| validateCertificates | true | Whether the Splunk client will validates the server's SSL cert | 2.0 |
| Option | Default | Description | Since |
|-----------------------| --------- | --------------------------------------------------------------- | ----- |
| type | (none) | Set to "splunk" to use this plugin | 1.19 |
| username | null | Splunk username to be used by Drill | 1.19 |
| password | null | Splunk password to be used by Drill | 1.19 |
| scheme | https | The scheme with which to access the Splunk host | 2.0 |
| hostname | localhost | Splunk host to be queried by Drill | 1.19 |
| port | 8089 | TCP port over which Drill will connect to Splunk | 1.19 |
| earliestTime | null | Global earliest record timestamp default | 1.19 |
| latestTime | null | Global latest record timestamp default | 1.19 |
| app | null | The application context of the service[^1] | 2.0 |
| owner | null | The owner context of the service[^1] | 2.0 |
| token | null | A Splunk authentication token to use for the session[^2] | 2.0 |
| cookie | null | A valid login cookie | 2.0 |
| validateCertificates | true | Whether the Splunk client will validates the server's SSL cert | 2.0 |
| validateHostname | true | Whether the Splunk client will validate the server's host name | 1.22 |

[^1]: See [this Splunk documentation](https://docs.splunk.com/Documentation/Splunk/latest/Admin/Apparchitectureandobjectownership) for more information.
[^2]: See [this Splunk documentation](https://docs.splunk.com/Documentation/Splunk/latest/Security/CreateAuthTokens) for more information.
Expand Down
2 changes: 1 addition & 1 deletion contrib/storage-splunk/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<dependency>
<groupId>com.splunk</groupId>
<artifactId>splunk</artifactId>
<version>1.9.3</version>
<version>1.9.5</version>
<exclusions>
<exclusion>
<groupId>org.apache.maven.plugins</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,17 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
* This class wraps the functionality of the Splunk connection for Drill.
Expand All @@ -54,6 +55,10 @@ public class SplunkConnection {
private final Integer port;
// Whether the Splunk client will validate the server's SSL cert.
private final boolean validateCertificates;

// Whether or not to validate the server's hostname.
private final boolean validateHostnames;

// The application context of the service.
private final String app;
// The owner context of the service.
Expand All @@ -80,6 +85,7 @@ public SplunkConnection(SplunkPluginConfig config, String queryUserName) {
this.token = config.getToken();
this.cookie = config.getCookie();
this.validateCertificates = config.getValidateCertificates();
this.validateHostnames = config.getValidateHostname();
this.connectionAttempts = config.getReconnectRetries();
service = connect();
}
Expand All @@ -101,6 +107,7 @@ public SplunkConnection(SplunkPluginConfig config, Service service, String query
this.token = config.getToken();
this.cookie = config.getCookie();
this.validateCertificates = config.getValidateCertificates();
this.validateHostnames = config.getValidateHostname();
this.service = service;
}

Expand All @@ -109,8 +116,9 @@ public SplunkConnection(SplunkPluginConfig config, Service service, String query
* @return an active Splunk {@link Service} connection.
*/
public Service connect() {
HttpService.setSslSecurityProtocol(SSLSecurityProtocol.TLSv1_2);
HttpService.setValidateCertificates(validateCertificates);
HttpService.setSslSecurityProtocol(SSLSecurityProtocol.TLSv1_2);

if (! validateCertificates) {
try {
HttpService.setSSLSocketFactory(createAllTrustingSSLFactory());
Expand All @@ -121,6 +129,16 @@ public Service connect() {
}
}

if (! this.validateHostnames) {
// Disable hostname verification
// This verification does not work with Splunk self-signed certificates
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
return true;
}
});
}

ServiceArgs loginArgs = new ServiceArgs();
if (scheme != null) {
// Fall back to the Splunk SDK default if our value is null by not setting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
import org.apache.drill.common.PlanStringBuilder;
Expand Down Expand Up @@ -49,6 +51,7 @@ public class SplunkPluginConfig extends StoragePluginConfig {
private final String token;
private final String cookie;
private final boolean validateCertificates;
private final boolean validateHostname;
private final Integer reconnectRetries;
private final boolean writable;
private final Integer writerBatchSize;
Expand All @@ -64,6 +67,7 @@ public SplunkPluginConfig(@JsonProperty("username") String username,
@JsonProperty("token") String token,
@JsonProperty("cookie") String cookie,
@JsonProperty("validateCertificates") boolean validateCertificates,
@JsonProperty("validateHostname") boolean validateHostname,
@JsonProperty("earliestTime") String earliestTime,
@JsonProperty("latestTime") String latestTime,
@JsonProperty("credentialsProvider") CredentialsProvider credentialsProvider,
Expand All @@ -82,6 +86,7 @@ public SplunkPluginConfig(@JsonProperty("username") String username,
this.cookie = cookie;
this.writable = writable;
this.validateCertificates = validateCertificates;
this.validateHostname = validateHostname;
this.earliestTime = earliestTime;
this.latestTime = latestTime == null ? "now" : latestTime;
this.reconnectRetries = reconnectRetries;
Expand All @@ -99,6 +104,7 @@ private SplunkPluginConfig(SplunkPluginConfig that, CredentialsProvider credenti
this.writable = that.writable;
this.cookie = that.cookie;
this.validateCertificates = that.validateCertificates;
this.validateHostname = that.validateHostname;
this.earliestTime = that.earliestTime;
this.latestTime = that.latestTime;
this.reconnectRetries = that.reconnectRetries;
Expand Down Expand Up @@ -188,10 +194,17 @@ public String getCookie() {
}

@JsonProperty("validateCertificates")
@JsonInclude(Include.NON_DEFAULT)
public boolean getValidateCertificates() {
return validateCertificates;
}

@JsonProperty("validateHostname")
@JsonInclude(Include.NON_DEFAULT)
public boolean getValidateHostname() {
return validateHostname;
}

@JsonProperty("earliestTime")
public String getEarliestTime() {
return earliestTime;
Expand Down Expand Up @@ -234,6 +247,7 @@ public boolean equals(Object that) {
Objects.equals(token, thatConfig.token) &&
Objects.equals(cookie, thatConfig.cookie) &&
Objects.equals(validateCertificates, thatConfig.validateCertificates) &&
Objects.equals(validateHostname, thatConfig.validateHostname) &&
Objects.equals(earliestTime, thatConfig.earliestTime) &&
Objects.equals(latestTime, thatConfig.latestTime) &&
Objects.equals(authMode, thatConfig.authMode);
Expand All @@ -252,6 +266,7 @@ public int hashCode() {
cookie,
writable,
validateCertificates,
validateHostname,
earliestTime,
latestTime,
authMode
Expand All @@ -271,6 +286,7 @@ public String toString() {
.field("token", token)
.field("cookie", cookie)
.field("validateCertificates", validateCertificates)
.field("validateHostname", validateHostname)
.field("earliestTime", earliestTime)
.field("latestTime", latestTime)
.field("Authentication Mode", authMode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@

package org.apache.drill.exec.store.splunk;

import java.util.Arrays;

public class SplunkUtils {
/**
* These are special fields that alter the queries sent to Splunk.
Expand Down Expand Up @@ -54,9 +52,13 @@ public enum SPECIAL_FIELDS {
* @param unknownField The field to be pushed down
* @return true if the field is a special field, false if not.
*/
public static boolean includes(String field) {
return Arrays.stream(SplunkUtils.SPECIAL_FIELDS.values())
.anyMatch(special -> field.equals(special.name()));
public static boolean includes(String unknownField) {
for (SPECIAL_FIELDS field : SPECIAL_FIELDS.values()) {
if (field.field.equals(unknownField)) {
return true;
}
}
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public void testConnectionFail() {
SPLUNK_STORAGE_PLUGIN_CONFIG.getToken(),
SPLUNK_STORAGE_PLUGIN_CONFIG.getCookie(),
SPLUNK_STORAGE_PLUGIN_CONFIG.getValidateCertificates(),
SPLUNK_STORAGE_PLUGIN_CONFIG.getValidateHostname(),
SPLUNK_STORAGE_PLUGIN_CONFIG.getEarliestTime(),
SPLUNK_STORAGE_PLUGIN_CONFIG.getLatestTime(),
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public static void initSplunk() throws Exception {
SPLUNK_STORAGE_PLUGIN_CONFIG = new SplunkPluginConfig(
SPLUNK_LOGIN, SPLUNK_PASS,
"http", hostname, port,
null, null, null, null, false, // app, owner, token, cookie, validateCertificates
null, null, null, null, false, true, // app, owner, token, cookie, validateCertificates
"1", "now",
null,
4,
Expand All @@ -116,7 +116,7 @@ public static void initSplunk() throws Exception {
SPLUNK_STORAGE_PLUGIN_CONFIG_WITH_USER_TRANSLATION = new SplunkPluginConfig(
null, null, // username, password
"http", hostname, port,
null, null, null, null, false, // app, owner, token, cookie, validateCertificates
null, null, null, null, false, false, // app, owner, token, cookie, validateCertificates
"1", "now",
credentialsProvider,
4,
Expand Down

0 comments on commit ac98f34

Please sign in to comment.