From 0e1b5a65ed06b2213deebb0ea1e5fb8422223426 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 8 Nov 2017 15:15:30 +0100 Subject: [PATCH] Backup ipa-custodia conf and keys https://pagure.io/freeipa/issue/7247 Signed-off-by: Christian Heimes Reviewed-By: Simo Sorce --- install/share/custodia.conf.template | 2 +- ipaplatform/base/paths.py | 1 + ipapython/ipautil.py | 19 +++++++++++++++++++ ipaserver/install/custodiainstance.py | 24 +++++++++++++----------- ipaserver/install/ipa_backup.py | 2 ++ ipatests/test_ipapython/test_ipautil.py | 7 +++++++ 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/install/share/custodia.conf.template b/install/share/custodia.conf.template index 855a1b3ba206e4ded8de80758b02473040096c7f..ee3c43ca7ec265aa09d250426bf4138bcfdf62b6 100644 --- a/install/share/custodia.conf.template +++ b/install/share/custodia.conf.template @@ -16,7 +16,7 @@ header = GSS_NAME handler = ipaserver.secrets.kem.IPAKEMKeys paths = /keys store = ipa -server_keys = $IPA_CUSTODIA_CONF_DIR/server.keys +server_keys = $IPA_CUSTODIA_KEYS [store:ipa] handler = ipaserver.secrets.store.IPASecStore diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index 804fddee60f787e161947bbe4b1914995257ceb4..42240a71066599ca8b36d10a9e5b23625f868977 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -349,6 +349,7 @@ class BasePathNamespace(object): NETWORK_MANAGER_CONFIG_DIR = '/etc/NetworkManager/conf.d' IPA_CUSTODIA_CONF_DIR = '/etc/ipa/custodia' IPA_CUSTODIA_CONF = '/etc/ipa/custodia/custodia.conf' + IPA_CUSTODIA_KEYS = '/etc/ipa/custodia/server.keys' IPA_CUSTODIA_SOCKET = '/run/httpd/ipa-custodia.sock' IPA_CUSTODIA_AUDIT_LOG = '/var/log/ipa-custodia.audit.log' IPA_GETKEYTAB = '/usr/sbin/ipa-getkeytab' diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py index cc52af6d9235cfbd597679231f63667b81a200b4..426b32ef05ab00dcbf37b1e58b6390accee33cb1 100644 --- a/ipapython/ipautil.py +++ b/ipapython/ipautil.py @@ -307,6 +307,25 @@ def write_tmp_file(txt): return fd + +def flush_sync(f): + """Flush and fsync file to disk + + :param f: a file object with fileno and name + """ + # flush file buffer to file descriptor + f.flush() + # flush Kernel buffer to disk + os.fsync(f.fileno()) + # sync metadata in directory + dirname = os.path.dirname(os.path.abspath(f.name)) + dirfd = os.open(dirname, os.O_RDONLY | os.O_DIRECTORY) + try: + os.fsync(dirfd) + finally: + os.close(dirfd) + + def shell_quote(string): if isinstance(string, str): return "'" + string.replace("'", "'\\''") + "'" diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py index bc3cea7063dff183c85b4f6e8ced7567f691001d..0a90bb3954486b9773e3553e9981d2a8d0d4e44a 100644 --- a/ipaserver/install/custodiainstance.py +++ b/ipaserver/install/custodiainstance.py @@ -25,8 +25,7 @@ class CustodiaInstance(SimpleServiceInstance): def __init__(self, host_name=None, realm=None): super(CustodiaInstance, self).__init__("ipa-custodia") self.config_file = paths.IPA_CUSTODIA_CONF - self.server_keys = os.path.join(paths.IPA_CUSTODIA_CONF_DIR, - 'server.keys') + self.server_keys = paths.IPA_CUSTODIA_KEYS self.ldap_uri = None self.fqdn = host_name self.realm = realm @@ -35,16 +34,19 @@ class CustodiaInstance(SimpleServiceInstance): template_file = os.path.basename(self.config_file) + '.template' template = os.path.join(paths.USR_SHARE_IPA_DIR, template_file) httpd_info = pwd.getpwnam(constants.HTTPD_USER) - sub_dict = dict(IPA_CUSTODIA_CONF_DIR=paths.IPA_CUSTODIA_CONF_DIR, - IPA_CUSTODIA_SOCKET=paths.IPA_CUSTODIA_SOCKET, - IPA_CUSTODIA_AUDIT_LOG=paths.IPA_CUSTODIA_AUDIT_LOG, - LDAP_URI=installutils.realm_to_ldapi_uri(self.realm), - UID=httpd_info.pw_uid, GID=httpd_info.pw_gid) + sub_dict = dict( + IPA_CUSTODIA_CONF_DIR=paths.IPA_CUSTODIA_CONF_DIR, + IPA_CUSTODIA_KEYS=paths.IPA_CUSTODIA_KEYS, + IPA_CUSTODIA_SOCKET=paths.IPA_CUSTODIA_SOCKET, + IPA_CUSTODIA_AUDIT_LOG=paths.IPA_CUSTODIA_AUDIT_LOG, + LDAP_URI=installutils.realm_to_ldapi_uri(self.realm), + UID=httpd_info.pw_uid, + GID=httpd_info.pw_gid + ) conf = ipautil.template_file(template, sub_dict) - fd = open(self.config_file, "w+") - fd.write(conf) - fd.flush() - fd.close() + with open(self.config_file, "w") as f: + f.write(conf) + ipautil.flush_sync(f) def create_instance(self): suffix = ipautil.realm_to_suffix(self.realm) diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py index f8cdd56d26636678279ba5afb423c5eef10c33d0..93b154330d3e6c8700c98860eb0c08f6841774bb 100644 --- a/ipaserver/install/ipa_backup.py +++ b/ipaserver/install/ipa_backup.py @@ -181,6 +181,8 @@ class Backup(admintool.AdminTool): paths.DNSSEC_SOFTHSM_PIN_SO, paths.IPA_ODS_EXPORTER_KEYTAB, paths.IPA_DNSKEYSYNCD_KEYTAB, + paths.IPA_CUSTODIA_KEYS, + paths.IPA_CUSTODIA_CONF, paths.HOSTS, ) + tuple( os.path.join(paths.IPA_NSSDB_DIR, file) diff --git a/ipatests/test_ipapython/test_ipautil.py b/ipatests/test_ipapython/test_ipautil.py index 9c351bd0ed9cd96488ac74deadf97996668a75d2..5e1f58003e9f3cae2f0819ecc348ade2c367548b 100644 --- a/ipatests/test_ipapython/test_ipautil.py +++ b/ipatests/test_ipapython/test_ipautil.py @@ -25,6 +25,7 @@ Test the `ipapython/ipautil.py` module. import nose import pytest import six +import tempfile from ipapython import ipautil @@ -478,3 +479,9 @@ def test_backcompat(): assert rc is result.returncode assert out is result.output assert err is result.error_output + + +def test_flush_sync(): + with tempfile.NamedTemporaryFile('wb+') as f: + f.write(b'data') + ipautil.flush_sync(f) -- 2.13.6