From 0e1b5a65ed06b2213deebb0ea1e5fb8422223426 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
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 <cheimes@redhat.com>
Reviewed-By: Simo Sorce <ssorce@redhat.com>
---
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