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>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
Christian Heimes 2017-11-08 15:15:30 +01:00 committed by Tomas Krizek
parent 49c77d7781
commit 8bbeedc93f
No known key found for this signature in database
GPG Key ID: 22A2A94B5E49415A
6 changed files with 43 additions and 12 deletions

View File

@ -16,7 +16,7 @@ header = GSS_NAME
handler = ipaserver.secrets.kem.IPAKEMKeys handler = ipaserver.secrets.kem.IPAKEMKeys
paths = /keys paths = /keys
store = ipa store = ipa
server_keys = $IPA_CUSTODIA_CONF_DIR/server.keys server_keys = $IPA_CUSTODIA_KEYS
[store:ipa] [store:ipa]
handler = ipaserver.secrets.store.IPASecStore handler = ipaserver.secrets.store.IPASecStore

View File

@ -347,6 +347,7 @@ class BasePathNamespace(object):
NETWORK_MANAGER_CONFIG_DIR = '/etc/NetworkManager/conf.d' NETWORK_MANAGER_CONFIG_DIR = '/etc/NetworkManager/conf.d'
IPA_CUSTODIA_CONF_DIR = '/etc/ipa/custodia' IPA_CUSTODIA_CONF_DIR = '/etc/ipa/custodia'
IPA_CUSTODIA_CONF = '/etc/ipa/custodia/custodia.conf' 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_SOCKET = '/run/httpd/ipa-custodia.sock'
IPA_CUSTODIA_AUDIT_LOG = '/var/log/ipa-custodia.audit.log' IPA_CUSTODIA_AUDIT_LOG = '/var/log/ipa-custodia.audit.log'
IPA_GETKEYTAB = '/usr/sbin/ipa-getkeytab' IPA_GETKEYTAB = '/usr/sbin/ipa-getkeytab'

View File

@ -326,6 +326,25 @@ def write_tmp_file(txt):
return fd 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): def shell_quote(string):
if isinstance(string, str): if isinstance(string, str):
return "'" + string.replace("'", "'\\''") + "'" return "'" + string.replace("'", "'\\''") + "'"

View File

@ -30,8 +30,7 @@ class CustodiaInstance(SimpleServiceInstance):
def __init__(self, host_name=None, realm=None): def __init__(self, host_name=None, realm=None):
super(CustodiaInstance, self).__init__("ipa-custodia") super(CustodiaInstance, self).__init__("ipa-custodia")
self.config_file = paths.IPA_CUSTODIA_CONF self.config_file = paths.IPA_CUSTODIA_CONF
self.server_keys = os.path.join(paths.IPA_CUSTODIA_CONF_DIR, self.server_keys = paths.IPA_CUSTODIA_KEYS
'server.keys')
self.ldap_uri = None self.ldap_uri = None
self.fqdn = host_name self.fqdn = host_name
self.realm = realm self.realm = realm
@ -40,16 +39,19 @@ class CustodiaInstance(SimpleServiceInstance):
template_file = os.path.basename(self.config_file) + '.template' template_file = os.path.basename(self.config_file) + '.template'
template = os.path.join(paths.USR_SHARE_IPA_DIR, template_file) template = os.path.join(paths.USR_SHARE_IPA_DIR, template_file)
httpd_info = pwd.getpwnam(constants.HTTPD_USER) httpd_info = pwd.getpwnam(constants.HTTPD_USER)
sub_dict = dict(IPA_CUSTODIA_CONF_DIR=paths.IPA_CUSTODIA_CONF_DIR, sub_dict = dict(
IPA_CUSTODIA_SOCKET=paths.IPA_CUSTODIA_SOCKET, IPA_CUSTODIA_CONF_DIR=paths.IPA_CUSTODIA_CONF_DIR,
IPA_CUSTODIA_AUDIT_LOG=paths.IPA_CUSTODIA_AUDIT_LOG, IPA_CUSTODIA_KEYS=paths.IPA_CUSTODIA_KEYS,
LDAP_URI=installutils.realm_to_ldapi_uri(self.realm), IPA_CUSTODIA_SOCKET=paths.IPA_CUSTODIA_SOCKET,
UID=httpd_info.pw_uid, GID=httpd_info.pw_gid) 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) conf = ipautil.template_file(template, sub_dict)
fd = open(self.config_file, "w+") with open(self.config_file, "w") as f:
fd.write(conf) f.write(conf)
fd.flush() ipautil.flush_sync(f)
fd.close()
def create_instance(self): def create_instance(self):
suffix = ipautil.realm_to_suffix(self.realm) suffix = ipautil.realm_to_suffix(self.realm)

View File

@ -189,6 +189,8 @@ class Backup(admintool.AdminTool):
paths.DNSSEC_SOFTHSM_PIN_SO, paths.DNSSEC_SOFTHSM_PIN_SO,
paths.IPA_ODS_EXPORTER_KEYTAB, paths.IPA_ODS_EXPORTER_KEYTAB,
paths.IPA_DNSKEYSYNCD_KEYTAB, paths.IPA_DNSKEYSYNCD_KEYTAB,
paths.IPA_CUSTODIA_KEYS,
paths.IPA_CUSTODIA_CONF,
paths.HOSTS, paths.HOSTS,
) + tuple( ) + tuple(
os.path.join(paths.IPA_NSSDB_DIR, file) os.path.join(paths.IPA_NSSDB_DIR, file)

View File

@ -25,6 +25,7 @@ Test the `ipapython/ipautil.py` module.
import nose import nose
import pytest import pytest
import six import six
import tempfile
from ipapython import ipautil from ipapython import ipautil
@ -470,3 +471,9 @@ def test_backcompat():
assert rc is result.returncode assert rc is result.returncode
assert out is result.output assert out is result.output
assert err is result.error_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)