# # Copyright (C) 2020 FreeIPA Contributors see COPYING for license # import os import dateutil.tz from ipaserver.dnssec._odsbase import AbstractODSDBConnection from ipaserver.dnssec._odsbase import AbstractODSSignerConn from ipaserver.dnssec._odsbase import ODS_SE_MAXLINE from ipaplatform.constants import constants from ipaplatform.paths import paths from ipapython import ipautil CLIENT_OPC_STDOUT = 0 CLIENT_OPC_EXIT = 4 class ODSDBConnection(AbstractODSDBConnection): def get_zones(self): cur = self._db.execute("SELECT name from zone") rows = cur.fetchall() return [row['name'] for row in rows] def get_zone_id(self, zone_name): cur = self._db.execute( "SELECT id FROM zone WHERE LOWER(name)=LOWER(?)", (zone_name,)) rows = cur.fetchall() return [row[0] for row in rows] def get_keys_for_zone(self, zone_id): cur = self._db.execute( "SELECT hsmk.locator, hsmk.inception, hsmk.algorithm, " "hsmk.role, hsmk.state " "FROM hsmKey AS hsmk " "JOIN keyData AS kd ON hsmk.id = kd.hsmKeyId " "WHERE kd.zoneId = ?", (zone_id,)) for row in cur: key = dict() key['HSMkey_id'] = row['locator'] # The date is stored in UTC format but OpenDNSSEC 1.4 was # returning a local tz format tz = dateutil.tz.tzlocal() key['generate'] = ipautil.datetime_from_utctimestamp( row['inception'], units=1).astimezone(tz).replace(tzinfo=None).isoformat( sep=' ', timespec='seconds') key['algorithm'] = row['algorithm'] key['publish'] = key['generate'] key['active'] = None key['retire'] = None key['dead'] = None if row['role'] == 2: key['keytype'] = 256 elif row['role'] == 1: key['keytype'] = 257 key['state'] = row['state'] yield key class ODSSignerConn(AbstractODSSignerConn): def read_cmd(self): msg = self._conn.recv(ODS_SE_MAXLINE) _opc = int(msg[0]) msglen = int(msg[1]) << 8 + int(msg[2]) cmd = msg[3:msglen - 1].strip() return cmd def send_reply_and_close(self, reply): prefix = bytearray([CLIENT_OPC_STDOUT, len(reply) >> 8, len(reply) & 255]) self._conn.sendall(prefix + reply) # 2nd message: CLIENT_OPC_EXIT, then len, msg len, exit code prefix = bytearray([CLIENT_OPC_EXIT, 0, 1, 0]) self._conn.sendall(prefix) self._conn.close() class ODSTask(): def run_ods_setup(self): """Initialize a new kasp.db""" cmd = [paths.ODS_ENFORCER_DB_SETUP] return ipautil.run(cmd, stdin="y", runas=constants.ODS_USER) def run_ods_notify(self, **kwargs): """Notify ods-enforcerd to reload its conf.""" cmd = [paths.ODS_ENFORCER, 'flush'] # run commands as ODS user if os.geteuid() == 0: kwargs['runas'] = constants.ODS_USER return ipautil.run(cmd, **kwargs) def run_ods_policy_import(self, **kwargs): """Run OpenDNSSEC manager command to import policy.""" cmd = [paths.ODS_ENFORCER, 'policy', 'import'] # run commands as ODS user if os.geteuid() == 0: kwargs['runas'] = constants.ODS_USER ipautil.run(cmd, **kwargs) def run_ods_manager(self, params, **kwargs): """Run OpenDNSSEC manager command (ksmutil, enforcer) :param params: parameter for ODS command :param kwargs: additional arguments for ipautil.run() :return: result from ipautil.run() """ assert params[0] != 'setup' cmd = [paths.ODS_ENFORCER] cmd.extend(params) # run commands as ODS user if os.geteuid() == 0: kwargs['runas'] = constants.ODS_USER return ipautil.run(cmd, **kwargs)