summaryrefslogtreecommitdiffstats
path: root/ipaserver/install/opendnssecinstance.py
diff options
context:
space:
mode:
Diffstat (limited to 'ipaserver/install/opendnssecinstance.py')
-rw-r--r--ipaserver/install/opendnssecinstance.py299
1 files changed, 299 insertions, 0 deletions
diff --git a/ipaserver/install/opendnssecinstance.py b/ipaserver/install/opendnssecinstance.py
new file mode 100644
index 000000000..0d2fb009e
--- /dev/null
+++ b/ipaserver/install/opendnssecinstance.py
@@ -0,0 +1,299 @@
+#
+# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
+#
+
+import random
+
+import service
+import os
+import pwd
+import grp
+import stat
+
+import _ipap11helper
+
+import installutils
+from ipapython.ipa_log_manager import *
+from ipapython.dn import DN
+from ipapython import sysrestore, ipautil, ipaldap, p11helper
+from ipaplatform import services
+from ipaplatform.paths import paths
+from ipalib import errors, api
+from ipaserver.install import dnskeysyncinstance
+
+KEYMASTER = u'dnssecKeyMaster'
+softhsm_slot = 0
+
+
+def get_dnssec_key_masters(conn):
+ """
+ :return: list of active dnssec key masters
+ """
+ assert conn is not None
+
+ dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
+
+ filter_attrs = {
+ u'cn': u'DNSSEC',
+ u'objectclass': u'ipaConfigObject',
+ u'ipaConfigString': [KEYMASTER, u'enabledService'],
+ }
+ only_masters_f = conn.make_filter(filter_attrs, rules=conn.MATCH_ALL)
+
+ try:
+ entries = conn.find_entries(filter=only_masters_f, base_dn=dn)
+ except errors.NotFound:
+ return []
+
+ keymasters_list = []
+ for entry in entries[0]:
+ keymasters_list.append(str(entry.dn[1].value))
+
+ return keymasters_list
+
+
+def check_inst():
+ if not os.path.exists(paths.ODS_KSMUTIL):
+ print ("Please install the 'opendnssec' package and start "
+ "the installation again")
+ return False
+ return True
+
+
+class OpenDNSSECInstance(service.Service):
+ def __init__(self, fstore=None, dm_password=None):
+ service.Service.__init__(
+ self, "ods-enforcerd",
+ service_desc="OpenDNSSEC enforcer daemon",
+ dm_password=dm_password,
+ ldapi=False,
+ autobind=ipaldap.AUTOBIND_DISABLED
+ )
+ self.dm_password = dm_password
+ self.ods_uid = None
+ self.ods_gid = None
+ self.conf_file_dict = {
+ 'SOFTHSM_LIB': paths.LIBSOFTHSM2_SO,
+ 'TOKEN_LABEL': dnskeysyncinstance.softhsm_token_label,
+ 'KASP_DB': paths.OPENDNSSEC_KASP_DB,
+ }
+ self.kasp_file_dict = {}
+ self.extra_config = [KEYMASTER]
+
+ if fstore:
+ self.fstore = fstore
+ else:
+ self.fstore = sysrestore.FileStore(paths.SYSRESTORE)
+
+ suffix = ipautil.dn_attribute_property('_suffix')
+
+ def get_masters(self):
+ if not self.admin_conn:
+ self.ldap_connect()
+ return get_dnssec_key_masters(self.admin_conn)
+
+ def create_instance(self, fqdn, realm_name, generate_master_key=True):
+ self.backup_state("enabled", self.is_enabled())
+ self.backup_state("running", self.is_running())
+ self.fqdn = fqdn
+ self.realm = realm_name
+ self.suffix = ipautil.realm_to_suffix(self.realm)
+
+ try:
+ self.stop()
+ except Exception:
+ pass
+
+ # get a connection to the DS
+ if not self.admin_conn:
+ self.ldap_connect()
+ # checking status must be first
+ self.step("checking status", self.__check_dnssec_status)
+ self.step("setting up configuration files", self.__setup_conf_files)
+ self.step("setting up ownership and file mode bits", self.__setup_ownership_file_modes)
+ if generate_master_key:
+ self.step("generating master key", self.__generate_master_key)
+ self.step("setting up OpenDNSSEC", self.__setup_dnssec)
+ self.step("setting up ipa-dnskeysyncd", self.__setup_dnskeysyncd)
+ self.step("starting OpenDNSSEC enforcer", self.__start)
+ self.step("configuring OpenDNSSEC enforcer to start on boot", self.__enable)
+ self.start_creation()
+
+ def __check_dnssec_status(self):
+ named = services.knownservices.named
+ ods_enforcerd = services.knownservices.ods_enforcerd
+
+ try:
+ self.named_uid = pwd.getpwnam(named.get_user_name()).pw_uid
+ except KeyError:
+ raise RuntimeError("Named UID not found")
+
+ try:
+ self.named_gid = grp.getgrnam(named.get_group_name()).gr_gid
+ except KeyError:
+ raise RuntimeError("Named GID not found")
+
+ try:
+ self.ods_uid = pwd.getpwnam(ods_enforcerd.get_user_name()).pw_uid
+ except KeyError:
+ raise RuntimeError("OpenDNSSEC UID not found")
+
+ try:
+ self.ods_gid = grp.getgrnam(ods_enforcerd.get_group_name()).gr_gid
+ except KeyError:
+ raise RuntimeError("OpenDNSSEC GID not found")
+
+ def __enable(self):
+ try:
+ self.ldap_enable('DNSSEC', self.fqdn, self.dm_password,
+ self.suffix, self.extra_config)
+ except errors.DuplicateEntry:
+ root_logger.error("DNSSEC service already exists")
+ self.enable()
+
+ def __setup_conf_files(self):
+ if not self.fstore.has_file(paths.OPENDNSSEC_CONF_FILE):
+ self.fstore.backup_file(paths.OPENDNSSEC_CONF_FILE)
+
+ if not self.fstore.has_file(paths.OPENDNSSEC_KASP_FILE):
+ self.fstore.backup_file(paths.OPENDNSSEC_KASP_FILE)
+
+ pin_fd = open(paths.DNSSEC_SOFTHSM_PIN, "r")
+ pin = pin_fd.read()
+ pin_fd.close()
+
+ # add pin to template
+ sub_conf_dict = self.conf_file_dict
+ sub_conf_dict['PIN'] = pin
+
+ ods_conf_txt = ipautil.template_file(
+ ipautil.SHARE_DIR + "opendnssec_conf.template", sub_conf_dict)
+ ods_conf_fd = open(paths.OPENDNSSEC_CONF_FILE, 'w')
+ ods_conf_fd.seek(0)
+ ods_conf_fd.truncate(0)
+ ods_conf_fd.write(ods_conf_txt)
+ ods_conf_fd.close()
+
+ ods_kasp_txt = ipautil.template_file(
+ ipautil.SHARE_DIR + "opendnssec_kasp.template", self.kasp_file_dict)
+ ods_kasp_fd = open(paths.OPENDNSSEC_KASP_FILE, 'w')
+ ods_kasp_fd.seek(0)
+ ods_kasp_fd.truncate(0)
+ ods_kasp_fd.write(ods_kasp_txt)
+ ods_kasp_fd.close()
+
+ if not self.fstore.has_file(paths.SYSCONFIG_ODS):
+ self.fstore.backup_file(paths.SYSCONFIG_ODS)
+
+ installutils.set_directive(paths.SYSCONFIG_ODS,
+ 'SOFTHSM2_CONF',
+ paths.DNSSEC_SOFTHSM2_CONF,
+ quotes=False, separator='=')
+
+ def __setup_ownership_file_modes(self):
+ assert self.ods_uid is not None
+ assert self.ods_gid is not None
+
+ # workarounds for packaging bugs in opendnssec-1.4.5-2.fc20.x86_64
+ # https://bugzilla.redhat.com/show_bug.cgi?id=1098188
+ for (root, dirs, files) in os.walk(paths.ETC_OPENDNSSEC_DIR):
+ for directory in dirs:
+ dir_path = os.path.join(root, directory)
+ os.chmod(dir_path, 0770)
+ # chown to root:ods
+ os.chown(dir_path, 0, self.ods_gid)
+ for filename in files:
+ file_path = os.path.join(root, filename)
+ os.chmod(file_path, 0660)
+ # chown to root:ods
+ os.chown(file_path, 0, self.ods_gid)
+
+ for (root, dirs, files) in os.walk(paths.VAR_OPENDNSSEC_DIR):
+ for directory in dirs:
+ dir_path = os.path.join(root, directory)
+ os.chmod(dir_path, 0770)
+ # chown to ods:ods
+ os.chown(dir_path, self.ods_uid, self.ods_gid)
+ for filename in files:
+ file_path = os.path.join(root, filename)
+ os.chmod(file_path, 0660)
+ # chown to ods:ods
+ os.chown(file_path, self.ods_uid, self.ods_gid)
+
+ def __generate_master_key(self):
+
+ with open(paths.DNSSEC_SOFTHSM_PIN, "r") as f:
+ pin = f.read()
+
+ os.environ["SOFTHSM2_CONF"] = paths.DNSSEC_SOFTHSM2_CONF
+ p11 = _ipap11helper.P11_Helper(softhsm_slot, pin, paths.LIBSOFTHSM2_SO)
+ try:
+ # generate master key
+ root_logger.debug("Creating master key")
+ p11helper.generate_master_key(p11)
+
+ # change tokens mod/owner
+ root_logger.debug("Changing ownership of token files")
+ for (root, dirs, files) in os.walk(paths.DNSSEC_TOKENS_DIR):
+ for directory in dirs:
+ dir_path = os.path.join(root, directory)
+ os.chmod(dir_path, 0770 | stat.S_ISGID)
+ os.chown(dir_path, self.ods_uid, self.named_gid) # chown to ods:named
+ for filename in files:
+ file_path = os.path.join(root, filename)
+ os.chmod(file_path, 0770 | stat.S_ISGID)
+ os.chown(file_path, self.ods_uid, self.named_gid) # chown to ods:named
+
+ finally:
+ p11.finalize()
+
+ def __setup_dnssec(self):
+ # run once only
+ if self.get_state("KASP_DB_configured"):
+ root_logger.debug("Already configured, skipping step")
+
+ self.backup_state("KASP_DB_configured", True)
+
+ if not self.fstore.has_file(paths.OPENDNSSEC_KASP_DB):
+ self.fstore.backup_file(paths.OPENDNSSEC_KASP_DB)
+
+ command = [
+ paths.ODS_KSMUTIL,
+ 'setup'
+ ]
+
+ ods_enforcerd = services.knownservices.ods_enforcerd
+ ipautil.run(command, stdin="y", runas=ods_enforcerd.get_user_name())
+
+ def __setup_dnskeysyncd(self):
+ # set up dnskeysyncd this is DNSSEC master
+ installutils.set_directive(paths.SYSCONFIG_IPA_DNSKEYSYNCD,
+ 'ISMASTER',
+ '1',
+ quotes=False, separator='=')
+
+ def __start(self):
+ self.restart() # needed to reload conf files
+
+ def uninstall(self):
+ if not self.is_configured():
+ return
+
+ self.print_msg("Unconfiguring %s" % self.service_name)
+
+ running = self.restore_state("running")
+ enabled = self.restore_state("enabled")
+
+ for f in [paths.OPENDNSSEC_CONF_FILE, paths.OPENDNSSEC_KASP_FILE,
+ paths.OPENDNSSEC_KASP_DB, paths.SYSCONFIG_ODS]:
+ try:
+ self.fstore.restore_file(f)
+ except ValueError, error:
+ root_logger.debug(error)
+ pass
+
+ if enabled is not None and not enabled:
+ self.disable()
+
+ if running is not None and running:
+ self.start()
OSZAR »