From 793c86472ce97a8eae75d4ec94cd2db6901d70b1 Mon Sep 17 00:00:00 2001 From: Nelson Wang Date: Mon, 24 Feb 2020 12:57:50 -0800 Subject: [PATCH 1/3] Fixing uid/gid on UF images; adding tests --- tests/test_docker_splunk.py | 112 ++++++++++++++++++++++++++++++++++++ uf/common-files/Dockerfile | 10 +++- 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/tests/test_docker_splunk.py b/tests/test_docker_splunk.py index 7e657647..f2f7dc5a 100644 --- a/tests/test_docker_splunk.py +++ b/tests/test_docker_splunk.py @@ -396,6 +396,28 @@ def test_splunk_entrypoint_no_provision(self): if cid: self.client.remove_container(cid, v=True, force=True) + def test_splunk_uid_gid(self): + cid = None + try: + # Run container + cid = self.client.create_container(self.SPLUNK_IMAGE_NAME, tty=True, command="no-provision") + cid = cid.get("Id") + self.client.start(cid) + # Wait a bit + time.sleep(5) + # If the container is still running, we should be able to exec inside + # Check that the git SHA exists in /opt/ansible + exec_command = self.client.exec_create(cid, "id", user="splunk") + std_out = self.client.exec_start(exec_command) + assert "uid=41812" in std_out + assert "gid=41812" 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) + def test_uf_entrypoint_help(self): # Run container cid = self.client.create_container(self.UF_IMAGE_NAME, tty=True, command="help") @@ -452,6 +474,28 @@ def test_uf_entrypoint_no_provision(self): if cid: self.client.remove_container(cid, v=True, force=True) + def test_uf_uid_gid(self): + cid = None + try: + # Run container + cid = self.client.create_container(self.UF_IMAGE_NAME, tty=True, command="no-provision") + cid = cid.get("Id") + self.client.start(cid) + # Wait a bit + time.sleep(5) + # If the container is still running, we should be able to exec inside + # Check that the git SHA exists in /opt/ansible + exec_command = self.client.exec_create(cid, "id", user="splunk") + std_out = self.client.exec_start(exec_command) + assert "uid=41812" in std_out + assert "gid=41812" 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) + def test_adhoc_1so_using_default_yml(self): # Generate default.yml cid = self.client.create_container(self.SPLUNK_IMAGE_NAME, tty=True, command="create-defaults") @@ -811,6 +855,74 @@ def test_adhoc_1uf_change_tailed_files(self): if cid: self.client.remove_container(cid, v=True, force=True) + def test_adhoc_1so_password_from_file(self): + # Create a splunk container + cid = None + # From fixtures/pwfile + filePW = "changeme123" + try: + splunk_container_name = generate_random_string() + cid = self.client.create_container(self.SPLUNK_IMAGE_NAME, tty=True, ports=[8089], + volumes=["/var/secrets/pwfile"], name=splunk_container_name, + environment={ + "DEBUG": "true", + "SPLUNK_START_ARGS": "--accept-license", + "SPLUNK_PASSWORD": "/var/secrets/pwfile" + }, + host_config=self.client.create_host_config(binds=[FIXTURES_DIR + "/pwfile:/var/secrets/pwfile"], + port_bindings={8089: ("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 + splunkd_port = self.client.port(cid, 8089)[0]["HostPort"] + url = "https://localhost:{}/services/server/info".format(splunkd_port) + kwargs = {"auth": ("admin", filePW), "verify": False} + status, content = self.handle_request_retry("GET", url, kwargs) + assert status == 200 + except Exception as e: + self.logger.error(e) + raise e + finally: + if cid: + self.client.remove_container(cid, v=True, force=True) + + def test_adhoc_1uf_password_from_file(self): + # Create a splunk container + cid = None + # From fixtures/pwfile + filePW = "changeme123" + try: + splunk_container_name = generate_random_string() + cid = self.client.create_container(self.UF_IMAGE_NAME, tty=True, ports=[8089], + volumes=["/var/secrets/pwfile"], name=splunk_container_name, + environment={ + "DEBUG": "true", + "SPLUNK_START_ARGS": "--accept-license", + "SPLUNK_PASSWORD": "/var/secrets/pwfile" + }, + host_config=self.client.create_host_config(binds=[FIXTURES_DIR + "/pwfile:/var/secrets/pwfile"], + port_bindings={8089: ("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 + splunkd_port = self.client.port(cid, 8089)[0]["HostPort"] + url = "https://localhost:{}/services/server/info".format(splunkd_port) + kwargs = {"auth": ("admin", filePW), "verify": False} + status, content = self.handle_request_retry("GET", url, kwargs) + assert status == 200 + except Exception as e: + self.logger.error(e) + raise e + finally: + if cid: + self.client.remove_container(cid, v=True, force=True) + def test_adhoc_1so_splunk_secret_env(self): # Create a splunk container cid = None diff --git a/uf/common-files/Dockerfile b/uf/common-files/Dockerfile index 5bbab1f5..3ebadf3a 100644 --- a/uf/common-files/Dockerfile +++ b/uf/common-files/Dockerfile @@ -36,6 +36,12 @@ COPY uf/common-files/apps ${SPLUNK_HOME}-etc/apps/ FROM ${SPLUNK_BASE_IMAGE}:latest as bare LABEL maintainer="support@splunk.com" +# Currently kubernetes only accepts UID and not USER field to +# start a container as a particular user. So we create Splunk +# user with pre-determined UID. +ARG UID=41812 +ARG GID=41812 + ENV SPLUNK_HOME=/opt/splunkforwarder \ SPLUNK_GROUP=splunk \ SPLUNK_USER=splunk @@ -44,8 +50,8 @@ ENV SPLUNK_HOME=/opt/splunkforwarder \ COPY [ "splunk/common-files/updateetc.sh", "/sbin/"] # Setup users and groups -RUN groupadd -r ${SPLUNK_GROUP} \ - && useradd -r -m -g ${SPLUNK_GROUP} ${SPLUNK_USER} \ +RUN groupadd -r -g ${GID} ${SPLUNK_GROUP} \ + && useradd -r -m -u ${UID} -g ${GID} ${SPLUNK_USER} \ && chmod 755 /sbin/updateetc.sh # Copy files from package From bf1e310a1e1ae673f8f28d01487d770bd74193d6 Mon Sep 17 00:00:00 2001 From: Nelson Wang Date: Mon, 24 Feb 2020 13:44:21 -0800 Subject: [PATCH 2/3] Adding more tests --- tests/test_docker_splunk.py | 118 ++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/tests/test_docker_splunk.py b/tests/test_docker_splunk.py index f2f7dc5a..3e9d62e6 100644 --- a/tests/test_docker_splunk.py +++ b/tests/test_docker_splunk.py @@ -923,6 +923,44 @@ def test_adhoc_1uf_password_from_file(self): if cid: self.client.remove_container(cid, v=True, force=True) + def test_adhoc_1so_splunk_pass4symmkey(self): + # Create a splunk container + cid = None + try: + splunk_container_name = generate_random_string() + cid = self.client.create_container(self.SPLUNK_IMAGE_NAME, tty=True, ports=[8089], name=splunk_container_name, + environment={ + "DEBUG": "true", + "SPLUNK_START_ARGS": "--accept-license", + "SPLUNK_PASSWORD": self.password, + "SPLUNK_PASS4SYMMKEY": "wubbalubbadubdub" + }, + host_config=self.client.create_host_config(port_bindings={8089: ("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 + splunkd_port = self.client.port(cid, 8089)[0]["HostPort"] + url = "https://localhost:{}/services/server/info".format(splunkd_port) + kwargs = {"auth": ("admin", self.password), "verify": False} + status, content = self.handle_request_retry("GET", url, kwargs) + assert status == 200 + # Check the decrypted pass4SymmKey + exec_command = self.client.exec_create(cid, "cat /opt/splunk/etc/system/local/server.conf", user="splunk") + std_out = self.client.exec_start(exec_command) + pass4SymmKey = re.search(r'\[general\].*?pass4SymmKey = (.*?)\n', std_out, flags=re.MULTILINE|re.DOTALL).group(1).strip() + exec_command = self.client.exec_create(cid, "/opt/splunk/bin/splunk show-decrypted --value '{}'".format(pass4SymmKey), user="splunk") + std_out = self.client.exec_start(exec_command) + assert "wubbalubbadubdub" 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) + def test_adhoc_1so_splunk_secret_env(self): # Create a splunk container cid = None @@ -957,6 +995,44 @@ def test_adhoc_1so_splunk_secret_env(self): finally: if cid: self.client.remove_container(cid, v=True, force=True) + + def test_adhoc_1uf_splunk_pass4symmkey(self): + # Create a splunk container + cid = None + try: + splunk_container_name = generate_random_string() + cid = self.client.create_container(self.UF_IMAGE_NAME, tty=True, ports=[8089], name=splunk_container_name, + environment={ + "DEBUG": "true", + "SPLUNK_START_ARGS": "--accept-license", + "SPLUNK_PASSWORD": self.password, + "SPLUNK_PASS4SYMMKEY": "wubbalubbadubdub" + }, + host_config=self.client.create_host_config(port_bindings={8089: ("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 + splunkd_port = self.client.port(cid, 8089)[0]["HostPort"] + url = "https://localhost:{}/services/server/info".format(splunkd_port) + kwargs = {"auth": ("admin", self.password), "verify": False} + status, content = self.handle_request_retry("GET", url, kwargs) + assert status == 200 + # Check the decrypted pass4SymmKey + exec_command = self.client.exec_create(cid, "cat /opt/splunkforwarder/etc/system/local/server.conf", user="splunk") + std_out = self.client.exec_start(exec_command) + pass4SymmKey = re.search(r'\[general\].*?pass4SymmKey = (.*?)\n', std_out, flags=re.MULTILINE|re.DOTALL).group(1).strip() + exec_command = self.client.exec_create(cid, "/opt/splunkforwarder/bin/splunk show-decrypted --value '{}'".format(pass4SymmKey), user="splunk") + std_out = self.client.exec_start(exec_command) + assert "wubbalubbadubdub" 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) def test_adhoc_1uf_splunk_secret_env(self): # Create a uf container @@ -2485,6 +2561,48 @@ def test_compose_3idx1cm_custom_repl_factor(self): os.remove(os.path.join(SCENARIOS_DIR, "defaults", "default.yml")) except OSError as e: pass + + def test_adhoc_1cm_idxc_pass4symmkey(self): + # Create the container + cid = None + try: + splunk_container_name = generate_random_string() + cid = self.client.create_container(self.SPLUNK_IMAGE_NAME, tty=True, ports=[8089], name=splunk_container_name, + environment={ + "DEBUG": "true", + "SPLUNK_START_ARGS": "--accept-license", + "SPLUNK_PASSWORD": self.password, + "SPLUNK_ROLE": "splunk_cluster_master", + "SPLUNK_INDEXER_URL": "idx1", + "SPLUNK_IDXC_PASS4SYMMKEY": "keepsummerbeingliketotallystokedaboutlikethegeneralvibeandstuff", + "SPLUNK_IDXC_LABEL": "keepsummersafe", + }, + host_config=self.client.create_host_config(port_bindings={8089: ("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 + splunkd_port = self.client.port(cid, 8089)[0]["HostPort"] + url = "https://localhost:{}/services/server/info".format(splunkd_port) + kwargs = {"auth": ("admin", self.password), "verify": False} + status, content = self.handle_request_retry("GET", url, kwargs) + assert status == 200 + # Check if the cluster label and pass4SymmKey line up + exec_command = self.client.exec_create(cid, "cat /opt/splunk/etc/system/local/server.conf", user="splunk") + std_out = self.client.exec_start(exec_command) + assert "cluster_label = keepsummersafe" in std_out + pass4SymmKey = re.search(r'\[clustering\].*?pass4SymmKey = (.*?)\n', std_out, flags=re.MULTILINE|re.DOTALL).group(1).strip() + exec_command = self.client.exec_create(cid, "/opt/splunk/bin/splunk show-decrypted --value '{}'".format(pass4SymmKey), user="splunk") + std_out = self.client.exec_start(exec_command) + assert "keepsummerbeingliketotallystokedaboutlikethegeneralvibeandstuff" 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) def test_compose_1cm_smartstore(self): # Generate default.yml From 507b5ec1b516dde7c63a91a1ce72f9200beaf8a7 Mon Sep 17 00:00:00 2001 From: Nelson Wang Date: Mon, 24 Feb 2020 15:06:28 -0800 Subject: [PATCH 3/3] Forgot to add new test fixture --- tests/fixtures/pwfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/fixtures/pwfile diff --git a/tests/fixtures/pwfile b/tests/fixtures/pwfile new file mode 100644 index 00000000..17329a5a --- /dev/null +++ b/tests/fixtures/pwfile @@ -0,0 +1 @@ +changeme123