Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRILL-8503: Add Configuration Option to Skip Host Validation for Splunk #2927

Merged
merged 2 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading