From 8dd45a3d0f0a3b8f8818203cb189e833cdb9c4d7 Mon Sep 17 00:00:00 2001 From: Leonardo Mendes Date: Thu, 9 May 2024 10:34:03 -0300 Subject: [PATCH] Store IPSec cert and keys in LUKS filesystem This commit updated ipsec-client to store certs and keys in LUKS filesystem. The encrypted filesystem take some time to mount and decrypted, so a script was created to check if the filesystem is ready before start ipsec. Test Plan: PASS: Bootstrap, install and unlock a DX system with a worker. Wait until system reboots and verify unlocked enable available status. Then, observe IPSec is enabled, SAs are established and the symbolic links were created in the directories /etc/swanctl/x509 and /etc/swanctl/private pointing to file in the directory /var/luks/stx/luks_fs/ipsec/{certs,keys}. Story: 2010940 Task: 50086 Change-Id: Ifccd747bd1db8f565d4744d99d94a61a22d5890e Signed-off-by: Leonardo Mendes --- sysinv/sysinv/debian/deb_folder/rules | 2 ++ .../sysinv/debian/deb_folder/sysinv.install | 1 + .../sysinv/scripts/check-ipsec-luks-dir.sh | 14 +++++++++++ .../sysinv/sysinv/sysinv/cmd/ipsec_client.py | 5 ++-- .../sysinv/sysinv/ipsec_auth/client/client.py | 23 ++++++++++++------- .../sysinv/ipsec_auth/common/constants.py | 13 ++++++----- .../sysinv/sysinv/ipsec_auth/common/utils.py | 14 +++++++++++ ...rkerconfig-standalone.workerconfig.service | 1 + .../workerconfig/workerconfig.service | 1 + 9 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 sysinv/sysinv/sysinv/scripts/check-ipsec-luks-dir.sh diff --git a/sysinv/sysinv/debian/deb_folder/rules b/sysinv/sysinv/debian/deb_folder/rules index c5cd8ef353..6f2198207a 100755 --- a/sysinv/sysinv/debian/deb_folder/rules +++ b/sysinv/sysinv/debian/deb_folder/rules @@ -27,6 +27,7 @@ override_dh_install: install -p -D -m 700 $(CURDIR)/scripts/kube-cert-rotation.sh $(CURDIR)/debian/tmp/usr/bin/kube-cert-rotation.sh install -p -D -m 700 $(CURDIR)/scripts/ipsec-cert-renew.sh $(CURDIR)/debian/tmp/usr/bin/ipsec-cert-renew.sh install -p -D -m 700 $(CURDIR)/scripts/ipsec-swap-certificates.py $(CURDIR)/debian/tmp/usr/bin/ipsec-swap-certificates + install -p -D -m 700 $(CURDIR)/scripts/check-ipsec-luks-dir.sh $(CURDIR)/debian/tmp/usr/bin/check-ipsec-luks-dir.sh dh_install override_dh_python3: @@ -39,3 +40,4 @@ override_dh_installsystemd: override_dh_fixperms: dh_fixperms -Xkube-cert-rotation.sh dh_fixperms -Xipsec-cert-renew.sh + dh_fixperms -Xcheck-ipsec-luks-dir.sh diff --git a/sysinv/sysinv/debian/deb_folder/sysinv.install b/sysinv/sysinv/debian/deb_folder/sysinv.install index 1b6508b546..82d7504298 100644 --- a/sysinv/sysinv/debian/deb_folder/sysinv.install +++ b/sysinv/sysinv/debian/deb_folder/sysinv.install @@ -15,6 +15,7 @@ etc/sysinv/upgrades/delete_load.sh etc/update-motd.d/10-system usr/bin/cert-alarm usr/bin/cert-mon +usr/bin/check-ipsec-luks-dir.sh usr/bin/ipsec-server usr/bin/ipsec-client usr/bin/kube-cert-rotation.sh diff --git a/sysinv/sysinv/sysinv/scripts/check-ipsec-luks-dir.sh b/sysinv/sysinv/sysinv/scripts/check-ipsec-luks-dir.sh new file mode 100644 index 0000000000..22c8f598bc --- /dev/null +++ b/sysinv/sysinv/sysinv/scripts/check-ipsec-luks-dir.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +FIRST_BOOT="/etc/platform/.first_boot" +LUKS_DIR="/var/luks/stx/luks_fs/ipsec" + +if [ -e ${FIRST_BOOT} ]; then + exit 0 +fi + +test -d $LUKS_DIR +while [ $? != 0 ]; do + sleep 1 + test -d $LUKS_DIR +done diff --git a/sysinv/sysinv/sysinv/sysinv/cmd/ipsec_client.py b/sysinv/sysinv/sysinv/sysinv/cmd/ipsec_client.py index 8862580c7a..70aa5ee0b0 100644 --- a/sysinv/sysinv/sysinv/sysinv/cmd/ipsec_client.py +++ b/sysinv/sysinv/sysinv/sysinv/cmd/ipsec_client.py @@ -80,8 +80,9 @@ def main(): logging.setup(CONF, 'ipsec-client') - if not os.path.exists(constants.TMP_DIR_IPSEC_KEYS): - os.makedirs(constants.TMP_DIR_IPSEC_KEYS) + if not os.path.exists(constants.LUKS_DIR_IPSEC_KEYS): + os.makedirs(constants.LUKS_DIR_IPSEC_KEYS) + os.makedirs(constants.LUKS_DIR_IPSEC_CERTS) client = Client(host, port, opcode, force_reload) client.run() diff --git a/sysinv/sysinv/sysinv/sysinv/ipsec_auth/client/client.py b/sysinv/sysinv/sysinv/sysinv/ipsec_auth/client/client.py index 8891c175fc..10e566a70f 100644 --- a/sysinv/sysinv/sysinv/sysinv/ipsec_auth/client/client.py +++ b/sysinv/sysinv/sysinv/sysinv/ipsec_auth/client/client.py @@ -69,11 +69,14 @@ class Client(object): encryption_algorithm=serialization.NoEncryption() ) - # TODO: Save PRK2 in LUKS Filesystem prk2_file = constants.CERT_NAME_PREFIX + \ self.hostname[constants.UNIT_HOSTNAME] + '.key' + + prk2_luks_path = constants.LUKS_DIR_IPSEC_KEYS + prk2_file prk2_path = constants.CERT_SYSTEM_LOCAL_PRIVATE_DIR + prk2_file - utils.save_data(prk2_path, prk2_bytes) + + utils.save_data(prk2_luks_path, prk2_bytes) + utils.create_symlink(prk2_luks_path, prk2_path) return prk2 @@ -81,8 +84,8 @@ class Client(object): def _generate_ak1(self, puk1_data): ak1 = os.urandom(32) - # TODO: Save AK1 in LUKS Filesystem - utils.save_data(constants.TMP_AK1_FILE, ak1) + # Save AK1 in LUKS Filesystem + utils.save_data(constants.LUKS_AK1_FILE, ak1) return ak1 @@ -101,7 +104,7 @@ class Client(object): def _generate_message_3(self): message = {} - puk1_data = utils.load_data(constants.TMP_PUK1_FILE) + puk1_data = utils.load_data(constants.LUKS_PUK1_FILE) puc_data = utils.load_data(constants.TRUSTED_CA_CERT_1_PATH) LOG.info("Generate RSA Private Key (PRK2).") @@ -177,8 +180,9 @@ class Client(object): LOG.exception("%s" % msg) return False - utils.save_data(constants.TMP_PUK1_FILE, key) - + utils.save_data(constants.LUKS_PUK1_FILE, key) + utils.save_data(constants.TRUSTED_ROOT_CA_CERT_1_PATH, root_ca_cert) + utils.save_data(constants.TRUSTED_CA_CERT_1_PATH, ca_cert) if self.op_code == constants.OP_CODE_INITIAL_AUTH: utils.save_data(constants.TRUSTED_ROOT_CA_CERT_0_PATH, root_ca_cert) utils.save_cert_bundle(ca_cert, constants.TRUSTED_CA_CERT_0_PREFIX) @@ -211,8 +215,11 @@ class Client(object): cert_file = constants.CERT_NAME_PREFIX + \ self.hostname[constants.UNIT_HOSTNAME] + '.crt' + cert_luks_path = constants.LUKS_DIR_IPSEC_CERTS + cert_file cert_path = constants.CERT_SYSTEM_LOCAL_DIR + cert_file - utils.save_data(cert_path, cert) + + utils.save_data(cert_luks_path, cert) + utils.create_symlink(cert_luks_path, cert_path) if self.op_code == constants.OP_CODE_INITIAL_AUTH: if self.personality == constants.CONTROLLER: diff --git a/sysinv/sysinv/sysinv/sysinv/ipsec_auth/common/constants.py b/sysinv/sysinv/sysinv/sysinv/ipsec_auth/common/constants.py index c34c9bbff5..d71976c7e4 100644 --- a/sysinv/sysinv/sysinv/sysinv/ipsec_auth/common/constants.py +++ b/sysinv/sysinv/sysinv/sysinv/ipsec_auth/common/constants.py @@ -45,12 +45,13 @@ CERT_SYSTEM_LOCAL_DIR = '/etc/swanctl/x509/' CERT_SYSTEM_LOCAL_PRIVATE_DIR = '/etc/swanctl/private/' CERT_NAME_PREFIX = 'system-ipsec-certificate-' -TMP_DIR_IPSEC = '/tmp/ipsec/' -TMP_DIR_IPSEC_KEYS = TMP_DIR_IPSEC + 'keys/' -TMP_FILE_IPSEC_PUK1 = 'puk1.crt' -TMP_FILE_IPSEC_AK1_KEY = 'ak1.key' -TMP_PUK1_FILE = TMP_DIR_IPSEC + TMP_FILE_IPSEC_PUK1 -TMP_AK1_FILE = TMP_DIR_IPSEC_KEYS + TMP_FILE_IPSEC_AK1_KEY +LUKS_DIR_IPSEC = '/var/luks/stx/luks_fs/ipsec/' +LUKS_DIR_IPSEC_KEYS = LUKS_DIR_IPSEC + 'keys/' +LUKS_DIR_IPSEC_CERTS = LUKS_DIR_IPSEC + 'certs/' +LUKS_FILE_IPSEC_PUK1 = 'puk1.key' +LUKS_FILE_IPSEC_AK1_KEY = 'ak1.key' +LUKS_PUK1_FILE = LUKS_DIR_IPSEC_KEYS + LUKS_FILE_IPSEC_PUK1 +LUKS_AK1_FILE = LUKS_DIR_IPSEC_KEYS + LUKS_FILE_IPSEC_AK1_KEY UNIT_HOSTNAME = 'unit_hostname' FLOATING_UNIT_HOSTNAME = 'floating_unit_hostname' diff --git a/sysinv/sysinv/sysinv/sysinv/ipsec_auth/common/utils.py b/sysinv/sysinv/sysinv/sysinv/ipsec_auth/common/utils.py index 91454442b0..a7cc581344 100644 --- a/sysinv/sysinv/sysinv/sysinv/ipsec_auth/common/utils.py +++ b/sysinv/sysinv/sysinv/sysinv/ipsec_auth/common/utils.py @@ -351,3 +351,17 @@ def save_cert_bundle(cert_data, cert_prefix): cert_path = get_ca_certificate_path(cert_prefix, index) save_data(cert_path, cert.public_bytes(encoding=serialization.Encoding.PEM)) index += 1 + + +def create_symlink(src, dst): + if not os.path.exists(src): + return False + + if os.path.exists(dst): + if src == dst: + return False + os.unlink(dst) + + os.symlink(src, dst) + + return os.path.exists(dst) diff --git a/workerconfig/debian/deb_folder/workerconfig-standalone.workerconfig.service b/workerconfig/debian/deb_folder/workerconfig-standalone.workerconfig.service index 97e6a1af38..afb6682827 100644 --- a/workerconfig/debian/deb_folder/workerconfig-standalone.workerconfig.service +++ b/workerconfig/debian/deb_folder/workerconfig-standalone.workerconfig.service @@ -6,6 +6,7 @@ After=affine-platform.sh.service After=opt-platform.service After=sysinv-agent.service After=network-online.target +After=ipsec.service Before=config.service worker-config-gate.service Before=goenabled.service diff --git a/workerconfig/workerconfig/workerconfig.service b/workerconfig/workerconfig/workerconfig.service index 97e6a1af38..afb6682827 100644 --- a/workerconfig/workerconfig/workerconfig.service +++ b/workerconfig/workerconfig/workerconfig.service @@ -6,6 +6,7 @@ After=affine-platform.sh.service After=opt-platform.service After=sysinv-agent.service After=network-online.target +After=ipsec.service Before=config.service worker-config-gate.service Before=goenabled.service