From 1d3458b33b433a2cd2f8216ccad0feef70f3c92b Mon Sep 17 00:00:00 2001 From: Nelson Wang Date: Tue, 17 Dec 2019 00:22:04 -0800 Subject: [PATCH 1/2] Adding tests for splunktcp-ssl --- tests/test_docker_splunk.py | 157 ++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/tests/test_docker_splunk.py b/tests/test_docker_splunk.py index bc9ba9ee..d894e94f 100644 --- a/tests/test_docker_splunk.py +++ b/tests/test_docker_splunk.py @@ -102,6 +102,15 @@ def teardown_method(self, method): self.compose_file_name, self.project_name = None, None self._clean_docker_env() + def cleanup_files(self, files): + try: + for file in files: + os.remove(file) + except OSError as e: + pass + except Exception as e: + raise e + def _clean_docker_env(self): # Remove anything spun up by docker-compose containers = self.client.containers(filters={"label": "com.docker.compose.version"}) @@ -1224,6 +1233,154 @@ def test_adhoc_1uf_hec_ssl_disabled(self): except OSError: pass + def test_adhoc_1so_splunktcp_ssl(self): + # Generate default.yml + cid = self.client.create_container(self.SPLUNK_IMAGE_NAME, tty=True, command="create-defaults") + self.client.start(cid.get("Id")) + output = self.get_container_logs(cid.get("Id")) + self.client.remove_container(cid.get("Id"), v=True, force=True) + # Get the password + password = re.search(" password: (.*)", output).group(1).strip() + assert password + # Commands to generate self-signed certificates for Splunk here: https://docs.splunk.com/Documentation/Splunk/latest/Security/ConfigureSplunkforwardingtousesignedcertificates + passphrase = "abcd1234" + cmds = [ + "openssl genrsa -aes256 -passout pass:{pw} -out {path}/ca.key 2048".format(pw=passphrase, path=FIXTURES_DIR), + "openssl req -new -key {path}/ca.key -passin pass:{pw} -out {path}/ca.csr -subj /CN=localhost".format(pw=passphrase, path=FIXTURES_DIR), + "openssl x509 -req -in {path}/ca.csr -sha512 -passin pass:{pw} -signkey {path}/ca.key -CAcreateserial -out {path}/ca.pem -days 3".format(pw=passphrase, path=FIXTURES_DIR), + "openssl genrsa -aes256 -passout pass:{pw} -out {path}/server.key 2048".format(pw=passphrase, path=FIXTURES_DIR), + "openssl req -new -passin pass:{pw} -key {path}/server.key -out {path}/server.csr -subj /CN=localhost".format(pw=passphrase, path=FIXTURES_DIR), + "openssl x509 -req -passin pass:{pw} -in {path}/server.csr -SHA256 -CA {path}/ca.pem -CAkey {path}/ca.key -CAcreateserial -out {path}/server.pem -days 3".format(pw=passphrase, path=FIXTURES_DIR), + "cat {path}/server.pem {path}/server.key {path}/ca.pem > {path}/cert.pem".format(path=FIXTURES_DIR) + ] + for cmd in cmds: + execute_cmd = subprocess.check_output(["/bin/sh", "-c", cmd]) + # Update s2s ssl settings + output = re.sub(r''' s2s:.*?ssl: false''', r''' s2s: + ca: /tmp/defaults/ca.pem + cert: /tmp/defaults/cert.pem + enable: true + password: {} + port: 9997 + ssl: true'''.format(passphrase), output, flags=re.DOTALL) + # Write the default.yml to a file + with open(os.path.join(FIXTURES_DIR, "default.yml"), "w") as f: + f.write(output) + # Create the container and mount the default.yml + cid = None + try: + splunk_container_name = generate_random_string() + cid = self.client.create_container(self.SPLUNK_IMAGE_NAME, tty=True, ports=[8000, 8089], + volumes=["/tmp/defaults/"], name=splunk_container_name, + environment={"DEBUG": "true", + "SPLUNK_START_ARGS": "--accept-license", + "SPLUNK_PASSWORD": password}, + host_config=self.client.create_host_config(binds=[FIXTURES_DIR + ":/tmp/defaults/"], + port_bindings={8089: ("0.0.0.0",), 8000: ("0.0.0.0",)}) + ) + cid = cid.get("Id") + self.client.start(cid) + # Poll for the container to be ready + assert self.wait_for_containers(1, name=splunk_container_name) + # Check splunkd + assert self.check_splunkd("admin", password) + # Check if the created file exists + exec_command = self.client.exec_create(cid, "cat /opt/splunk/etc/system/local/inputs.conf", user="splunk") + std_out = self.client.exec_start(exec_command) + assert "[splunktcp-ssl:9997]" in std_out + assert "serverCert = /tmp/defaults/cert.pem" in std_out + except Exception as e: + self.logger.error(e) + raise e + finally: + if cid: + self.client.remove_container(cid, v=True, force=True) + files = [ + os.path.join(FIXTURES_DIR, "ca.key"), + os.path.join(FIXTURES_DIR, "ca.csr"), + os.path.join(FIXTURES_DIR, "ca.pem"), + os.path.join(FIXTURES_DIR, "server.key"), + os.path.join(FIXTURES_DIR, "server.csr"), + os.path.join(FIXTURES_DIR, "server.pem"), + os.path.join(FIXTURES_DIR, "cert.pem"), + os.path.join(FIXTURES_DIR, "default.yml") + ] + self.cleanup_files(files) + + def test_adhoc_1uf_splunktcp_ssl(self): + # Generate default.yml + cid = self.client.create_container(self.UF_IMAGE_NAME, tty=True, command="create-defaults") + self.client.start(cid.get("Id")) + output = self.get_container_logs(cid.get("Id")) + self.client.remove_container(cid.get("Id"), v=True, force=True) + # Get the password + password = re.search(" password: (.*)", output).group(1).strip() + assert password + # Commands to generate self-signed certificates for Splunk here: https://docs.splunk.com/Documentation/Splunk/latest/Security/ConfigureSplunkforwardingtousesignedcertificates + passphrase = "abcd1234" + cmds = [ + "openssl genrsa -aes256 -passout pass:{pw} -out {path}/ca.key 2048".format(pw=passphrase, path=FIXTURES_DIR), + "openssl req -new -key {path}/ca.key -passin pass:{pw} -out {path}/ca.csr -subj /CN=localhost".format(pw=passphrase, path=FIXTURES_DIR), + "openssl x509 -req -in {path}/ca.csr -sha512 -passin pass:{pw} -signkey {path}/ca.key -CAcreateserial -out {path}/ca.pem -days 3".format(pw=passphrase, path=FIXTURES_DIR), + "openssl genrsa -aes256 -passout pass:{pw} -out {path}/server.key 2048".format(pw=passphrase, path=FIXTURES_DIR), + "openssl req -new -passin pass:{pw} -key {path}/server.key -out {path}/server.csr -subj /CN=localhost".format(pw=passphrase, path=FIXTURES_DIR), + "openssl x509 -req -passin pass:{pw} -in {path}/server.csr -SHA256 -CA {path}/ca.pem -CAkey {path}/ca.key -CAcreateserial -out {path}/server.pem -days 3".format(pw=passphrase, path=FIXTURES_DIR), + "cat {path}/server.pem {path}/server.key {path}/ca.pem > {path}/cert.pem".format(path=FIXTURES_DIR) + ] + for cmd in cmds: + execute_cmd = subprocess.check_output(["/bin/sh", "-c", cmd]) + # Update s2s ssl settings + output = re.sub(r''' s2s:.*?ssl: false''', r''' s2s: + ca: /tmp/defaults/ca.pem + cert: /tmp/defaults/cert.pem + enable: true + password: {} + port: 9997 + ssl: true'''.format(passphrase), output, flags=re.DOTALL) + # Write the default.yml to a file + with open(os.path.join(FIXTURES_DIR, "default.yml"), "w") as f: + f.write(output) + # Create the container and mount the default.yml + cid = None + try: + splunk_container_name = generate_random_string() + cid = self.client.create_container(self.UF_IMAGE_NAME, tty=True, ports=[8000, 8089], + volumes=["/tmp/defaults/"], name=splunk_container_name, + environment={"DEBUG": "true", + "SPLUNK_START_ARGS": "--accept-license", + "SPLUNK_PASSWORD": password}, + host_config=self.client.create_host_config(binds=[FIXTURES_DIR + ":/tmp/defaults/"], + port_bindings={8089: ("0.0.0.0",), 8000: ("0.0.0.0",)}) + ) + cid = cid.get("Id") + self.client.start(cid) + # Poll for the container to be ready + assert self.wait_for_containers(1, name=splunk_container_name) + # Check splunkd + assert self.check_splunkd("admin", password) + # Check if the created file exists + exec_command = self.client.exec_create(cid, "cat /opt/splunkforwarder/etc/system/local/inputs.conf", user="splunk") + std_out = self.client.exec_start(exec_command) + assert "[splunktcp-ssl:9997]" in std_out + assert "serverCert = /tmp/defaults/cert.pem" in std_out + except Exception as e: + self.logger.error(e) + raise e + finally: + if cid: + self.client.remove_container(cid, v=True, force=True) + files = [ + os.path.join(FIXTURES_DIR, "ca.key"), + os.path.join(FIXTURES_DIR, "ca.csr"), + os.path.join(FIXTURES_DIR, "ca.pem"), + os.path.join(FIXTURES_DIR, "server.key"), + os.path.join(FIXTURES_DIR, "server.csr"), + os.path.join(FIXTURES_DIR, "server.pem"), + os.path.join(FIXTURES_DIR, "cert.pem"), + os.path.join(FIXTURES_DIR, "default.yml") + ] + self.cleanup_files(files) + def test_adhoc_1so_web_ssl(self): # Generate a password password = generate_random_string() From 17050208565cd4c842b150b9b27e79dfb6836b01 Mon Sep 17 00:00:00 2001 From: Nelson Wang Date: Tue, 17 Dec 2019 16:38:09 -0800 Subject: [PATCH 2/2] Adding docs for splunktcp-ssl --- docs/ADVANCED.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/ADVANCED.md b/docs/ADVANCED.md index 5d774602..3103daef 100644 --- a/docs/ADVANCED.md +++ b/docs/ADVANCED.md @@ -18,6 +18,7 @@ Let's dive into the nitty-gritty on how to tweak the setup of your containerized * [Enable SmartStore](#enable-smartstore) * [Using deployment servers](#using-deployment-servers) * [Deploy distributed topology](#deploy-distributed-topology) +* [Enable SSL internal communication](#enable-ssl-internal-communication) * [Build from source](#build-from-source) * [base-debian-9](#base-debian-9) * [splunk-debian-9](#splunk-debian-9) @@ -248,6 +249,25 @@ While running a standalone Splunk instance may be fine for testing and developme See the [instructions on standing up a distributed environment](advanced/DISTRIBUTED_TOPOLOGY.md) to understand how to get started. +## Enable SSL Internal Communication +For users looking to secure the network traffic from one Splunk instance to another Splunk instance (ex: forwarders to indexers), you can enable forwarding and receiving to use SSL certificates. + +If you wish to enable SSL on one tier of your Splunk topology, it's very likely all instances will need it. To achieve this, we recommend you generate your server and CA certificates and add them to the `default.yml` which gets shared across all Splunk docker containers. Use this example `default.yml` snippet for the configuration of Splunk TCP with SSL. +``` +splunk: + ... + s2s: + ca: /mnt/certs/ca.pem + cert: /mnt/certs/cert.pem + enable: true + password: abcd1234 + port: 9997 + ssl: true + ... +``` + +For more instructions on how to bring your own certificates, please see: https://docs.splunk.com/Documentation/Splunk/latest/Security/ConfigureSplunkforwardingtousesignedcertificates + ## Build from source While we don't support or recommend you building your own images from source, it is entirely possible. This can be useful if you want to incorporate very experimental features, test new features, and if you have your own registry for persistent images.