mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-24 16:10:02 -06:00
cdfc86364e
The database storing the keys with OpenDNSSEC 2.1 has a different schema from OpenDNSSEC 1.4, and the keytype (ZSK, KSK) is stored in a different table column: "role" instead of "keytype". With OpenDNSSEC 1.4, keytype can be 256 (ZSK) or 257 (KSK), while with OpenDNSSEC 2.1, role can be 1 (KSK) or 2 (ZSK). The schema migration can be seen in opendnssec source code: enforcer/utils/1.4-2.0_db_convert/sqlite_convert.sql INSERT INTO hsmKey SELECT DISTINCT REMOTE.keypairs.id, 1, REMOTE.keypairs.policy_id, REMOTE.keypairs.HSMkey_id, 2, REMOTE.keypairs.size, REMOTE.keypairs.algorithm, (~(REMOTE.dnsseckeys.keytype)&1)+1, CASE WHEN REMOTE.keypairs.generate IS NOT NULL THEN strftime('%s', REMOTE.keypairs.generate) ELSE strftime("%s", "now") END, 0, 1, --only RSA supported REMOTE.securitymodules.name, 0 --assume no backup FROM REMOTE.keypairs JOIN REMOTE.dnsseckeys ON REMOTE.keypairs.id = REMOTE.dnsseckeys.keypair_id JOIN REMOTE.securitymodules ON REMOTE.securitymodules.id = REMOTE.keypairs.securitymodule_id; and the schema for the table is defined in enforcer/src/db/kasp.sqlite: CREATE TABLE HsmKey ( locator VARCHAR(255) NOT NULL, candidate_for_sharing TINYINT UNSIGNED DEFAULT 0, bits INT UNSIGNED DEFAULT 2048, policy VARCHAR(255) DEFAULT 'default', algorithm INT UNSIGNED DEFAULT 1, role VARCHAR(3) DEFAULT 'ZSK', inception INT UNSIGNED, isrevoked TINYINT UNSIGNED DEFAULT 0, key_type VARCHAR(255), repository VARCHAR(255), backmeup TINYINT UNSIGNED DEFAULT 0, backedup TINYINT UNSIGNED DEFAULT 0, requirebackup TINYINT UNSIGNED DEFAULT 0, id INTEGER PRIMARY KEY AUTOINCREMENT ); Fixes: https://pagure.io/freeipa/issue/8647 Reviewed-By: Rob Crittenden <rcritten@redhat.com>
118 lines
3.8 KiB
Python
118 lines
3.8 KiB
Python
#
|
|
# Copyright (C) 2020 FreeIPA Contributors see COPYING for license
|
|
#
|
|
|
|
import os
|
|
|
|
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']
|
|
key['generate'] = ipautil.datetime_from_utctimestamp(
|
|
row['inception'],
|
|
units=1).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)
|