/usr/lib/ipa/ipa-dnskeysync-replica is in freeipa-server 4.7.0~pre1+git20180411-2ubuntu2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | #!/usr/bin/python
#
# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
#
"""
Download keys from LDAP to local HSM.
This program should be run only on replicas, not on DNSSEC masters.
"""
from gssapi.exceptions import GSSError
import logging
import os
import sys
import ipalib
from ipalib.constants import SOFTHSM_DNSSEC_TOKEN_LABEL
from ipalib.install.kinit import kinit_keytab
from ipapython.dn import DN
from ipapython.ipa_log_manager import standard_logging_setup
from ipapython import ipaldap
from ipaplatform.paths import paths
from ipaserver.dnssec.abshsm import (sync_pkcs11_metadata,
ldap2p11helper_api_params,
wrappingmech_name2id)
from ipaserver.dnssec.ldapkeydb import LdapKeyDB, str_hexlify
from ipaserver.dnssec.localhsm import LocalHSM
logger = logging.getLogger(os.path.basename(__file__))
DAEMONNAME = 'ipa-dnskeysyncd'
PRINCIPAL = None # not initialized yet
WORKDIR = '/tmp'
def hex_set(s):
out = set()
for i in s:
out.add("0x%s" % str_hexlify(i))
return out
def update_metadata_set(source_set, target_set):
"""sync metadata from source key set to target key set
Keys not present in both sets are left intact."""
name = 'sync_metadata'
matching_keys = set(source_set.keys()).intersection(set(target_set.keys()))
logger.info("%s: keys in local HSM & LDAP: %s",
name, hex_set(matching_keys))
for key_id in matching_keys:
sync_pkcs11_metadata(name, source_set[key_id], target_set[key_id])
def find_unwrapping_key(localhsm, wrapping_key_uri):
wrap_keys = localhsm.find_keys(uri=wrapping_key_uri)
# find usable unwrapping key with matching ID
for key_id in wrap_keys.keys():
unwrap_keys = localhsm.find_keys(id=key_id, cka_unwrap=True)
if len(unwrap_keys) > 0:
return unwrap_keys.popitem()[1]
def ldap2replica_master_keys_sync(ldapkeydb, localhsm):
## LDAP -> replica master key synchronization
# import new master keys from LDAP
new_keys = set(ldapkeydb.master_keys.keys()) \
- set(localhsm.master_keys.keys())
logger.debug("master keys in local HSM: %s",
hex_set(localhsm.master_keys.keys()))
logger.debug("master keys in LDAP HSM: %s",
hex_set(ldapkeydb.master_keys.keys()))
logger.debug("new master keys in LDAP HSM: %s",
hex_set(new_keys))
for mkey_id in new_keys:
mkey_ldap = ldapkeydb.master_keys[mkey_id]
if not mkey_ldap.wrapped_entries:
raise ValueError(
"Master key 0x%s in LDAP is missing key material "
"referenced by ipaSecretKeyRefObject attribute" %
str_hexlify(mkey_id)
)
for wrapped_ldap in mkey_ldap.wrapped_entries:
unwrapping_key = find_unwrapping_key(
localhsm, wrapped_ldap.single_value['ipaWrappingKey'])
if unwrapping_key:
break
# TODO: Could it happen in normal cases?
if unwrapping_key is None:
raise ValueError(
"Local HSM does not contain suitable unwrapping key "
"for master key 0x%s" % str_hexlify(mkey_id)
)
params = ldap2p11helper_api_params(mkey_ldap)
params['data'] = wrapped_ldap.single_value['ipaSecretKey']
params['unwrapping_key'] = unwrapping_key.handle
params['wrapping_mech'] = wrappingmech_name2id[wrapped_ldap.single_value['ipaWrappingMech']]
logger.debug('Importing new master key: 0x%s %s',
str_hexlify(mkey_id), params)
localhsm.p11.import_wrapped_secret_key(**params)
# synchronize metadata about master keys in LDAP
update_metadata_set(ldapkeydb.master_keys, localhsm.master_keys)
def ldap2replica_zone_keys_sync(ldapkeydb, localhsm):
## LDAP -> replica zone key synchronization
# import new zone keys from LDAP
new_keys = set(ldapkeydb.zone_keypairs.keys()) \
- set(localhsm.zone_privkeys.keys())
logger.debug("zone keys in local HSM: %s",
hex_set(localhsm.master_keys.keys()))
logger.debug("zone keys in LDAP HSM: %s",
hex_set(ldapkeydb.master_keys.keys()))
logger.debug("new zone keys in LDAP HSM: %s",
hex_set(new_keys))
for zkey_id in new_keys:
zkey_ldap = ldapkeydb.zone_keypairs[zkey_id]
logger.debug('Looking for unwrapping key "%s" for zone key 0x%s',
zkey_ldap['ipaWrappingKey'], str_hexlify(zkey_id))
unwrapping_key = find_unwrapping_key(
localhsm, zkey_ldap['ipaWrappingKey'])
if unwrapping_key is None:
raise ValueError(
"Local HSM does not contain suitable unwrapping key for "
"zone key 0x%s" % str_hexlify(zkey_id)
)
logger.debug('Importing zone key pair 0x%s', str_hexlify(zkey_id))
localhsm.import_private_key(zkey_ldap, zkey_ldap['ipaPrivateKey'],
unwrapping_key)
localhsm.import_public_key(zkey_ldap, zkey_ldap['ipaPublicKey'])
# synchronize metadata about zone keys in LDAP & local HSM
update_metadata_set(ldapkeydb.master_keys, localhsm.master_keys)
# delete keys removed from LDAP
deleted_keys = set(localhsm.zone_privkeys.keys()) \
- set(ldapkeydb.zone_keypairs.keys())
for zkey_id in deleted_keys:
localhsm.p11.delete_key(localhsm.zone_pubkeys[zkey_id].handle)
localhsm.p11.delete_key(localhsm.zone_privkeys[zkey_id].handle)
# IPA framework initialization
standard_logging_setup(verbose=True, debug=True)
ipalib.api.bootstrap(context='dns', confdir=paths.ETC_IPA, in_server=True)
ipalib.api.finalize()
# Kerberos initialization
PRINCIPAL = str('%s/%s' % (DAEMONNAME, ipalib.api.env.host))
logger.debug('Kerberos principal: %s', PRINCIPAL)
ccache_filename = os.path.join(WORKDIR, 'ipa-dnskeysync-replica.ccache')
try:
kinit_keytab(PRINCIPAL, paths.IPA_DNSKEYSYNCD_KEYTAB, ccache_filename,
attempts=5)
except GSSError as e:
logger.critical('Kerberos authentication failed: %s', e)
sys.exit(1)
os.environ['KRB5CCNAME'] = ccache_filename
logger.debug('Got TGT')
# LDAP initialization
ldap = ipaldap.LDAPClient(ipalib.api.env.ldap_uri)
logger.debug('Connecting to LDAP')
ldap.gssapi_bind()
logger.debug('Connected')
### DNSSEC master: key synchronization
ldapkeydb = LdapKeyDB(ldap, DN(('cn', 'keys'),
('cn', 'sec'),
ipalib.api.env.container_dns,
ipalib.api.env.basedn))
localhsm = LocalHSM(paths.LIBSOFTHSM2_SO, SOFTHSM_DNSSEC_TOKEN_LABEL,
open(paths.DNSSEC_SOFTHSM_PIN).read())
ldap2replica_master_keys_sync(ldapkeydb, localhsm)
ldap2replica_zone_keys_sync(ldapkeydb, localhsm)
sys.exit(0)
|