mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
DNSSEC: Accept ipa-ods-exporter commands from command line.
Previously only systemd socket activation was supported. Ability to call the command directly is handy in special cases, e.g. for debugging or moving key master role from one server to another. https://fedorahosted.org/freeipa/ticket/4657 Reviewed-By: Martin Basti <mbasti@redhat.com>
This commit is contained in:
@@ -9,6 +9,9 @@ This program uses the same socket and protocol as original signerd and should
|
||||
be activated via systemd socket activation using "ods-signer" command line
|
||||
utility.
|
||||
|
||||
Alternativelly, it can be called directly and a command can be supplied as
|
||||
first command line argument.
|
||||
|
||||
Purpose of this replacement is to upload keys generated by OpenDNSSEC to LDAP.
|
||||
"""
|
||||
|
||||
@@ -334,7 +337,7 @@ def hex_set(s):
|
||||
out.add("0x%s" % hexlify(i))
|
||||
return out
|
||||
|
||||
def receive_zone_name(log):
|
||||
def receive_systemd_command(log):
|
||||
fds = systemd.daemon.listen_fds()
|
||||
if len(fds) != 1:
|
||||
raise KeyError('Exactly one socket is expected.')
|
||||
@@ -345,36 +348,40 @@ def receive_zone_name(log):
|
||||
log.debug('accepted new connection %s', repr(conn))
|
||||
|
||||
# this implements cmdhandler_handle_cmd() logic
|
||||
cmd = conn.recv(ODS_SE_MAXLINE)
|
||||
cmd = cmd.strip()
|
||||
cmd = conn.recv(ODS_SE_MAXLINE).strip()
|
||||
log.debug('received command "%s" from systemd socket', cmd)
|
||||
return (cmd, conn)
|
||||
|
||||
try:
|
||||
if cmd == 'ipa-hsm-update':
|
||||
msg = 'HSM synchronization finished, exiting.'
|
||||
conn.send('%s\n' % msg)
|
||||
log.info(msg)
|
||||
sys.exit(0)
|
||||
def parse_command(cmd):
|
||||
"""Parse command to (exit code, message, zone_name) tuple.
|
||||
|
||||
elif not cmd.startswith('update '):
|
||||
conn.send('Command "%s" is not supported by IPA; ' \
|
||||
'HSM synchronization was finished and the command ' \
|
||||
'will be ignored.\n' % cmd)
|
||||
log.info('Ignoring unsupported command "%s".', cmd)
|
||||
sys.exit(0)
|
||||
Exit code None means that execution should continue.
|
||||
"""
|
||||
if cmd == 'ipa-hsm-update':
|
||||
return (0,
|
||||
'HSM synchronization finished, exiting.',
|
||||
None)
|
||||
|
||||
else:
|
||||
zone_name = cmd2ods_zone_name(cmd)
|
||||
conn.send('Update request for zone "%s" queued.\n' % zone_name)
|
||||
log.info('Processing command: "%s"', cmd)
|
||||
elif not cmd.startswith('update '):
|
||||
return (0,
|
||||
'Command "%s" is not supported by IPA; '
|
||||
'HSM synchronization was finished and the command '
|
||||
'will be ignored.\n' % cmd,
|
||||
None)
|
||||
|
||||
finally:
|
||||
else:
|
||||
zone_name = cmd2ods_zone_name(cmd)
|
||||
return (None,
|
||||
'Update request for zone "%s" queued.\n' % zone_name,
|
||||
zone_name)
|
||||
|
||||
def send_systemd_reply(conn, reply):
|
||||
# Reply & close connection early.
|
||||
# This is necessary to let Enforcer to unlock the ODS DB.
|
||||
conn.send(reply + '\n')
|
||||
conn.shutdown(socket.SHUT_RDWR)
|
||||
conn.close()
|
||||
|
||||
return zone_name
|
||||
|
||||
def cmd2ods_zone_name(cmd):
|
||||
# ODS stores zone name without trailing period
|
||||
zone_name = cmd[7:].strip()
|
||||
@@ -384,13 +391,17 @@ def cmd2ods_zone_name(cmd):
|
||||
return zone_name
|
||||
|
||||
log = logging.getLogger('root')
|
||||
# this service is socket-activated
|
||||
# this service is usually socket-activated
|
||||
log.addHandler(systemd.journal.JournalHandler())
|
||||
log.setLevel(level=logging.DEBUG)
|
||||
|
||||
if len(sys.argv) != 1:
|
||||
if len(sys.argv) > 2:
|
||||
print __doc__
|
||||
sys.exit(1)
|
||||
# program was likely invoked from console, log to it
|
||||
elif len(sys.argv) == 2:
|
||||
console = logging.StreamHandler()
|
||||
log.addHandler(console)
|
||||
|
||||
# IPA framework initialization
|
||||
ipalib.api.bootstrap(in_server=True, log=None) # no logging to file
|
||||
@@ -429,16 +440,29 @@ master2ldap_zone_keys_sync(log, ldapkeydb, localhsm)
|
||||
# command receive is delayed so the command will stay in socket queue until
|
||||
# the problem with LDAP server or HSM is fixed
|
||||
try:
|
||||
zone_name = receive_zone_name(log)
|
||||
|
||||
cmd, conn = receive_systemd_command(log)
|
||||
if len(sys.argv) != 1:
|
||||
log.critical('No additional parameters are accepted when '
|
||||
'socket activation is used.')
|
||||
sys.exit(1)
|
||||
# Handle cases where somebody ran the program without systemd.
|
||||
except KeyError as e:
|
||||
print 'HSM (key material) sychronization is finished but ' \
|
||||
'this program should be socket-activated by OpenDNSSEC.'
|
||||
print 'Use "ods-signer" command line utility to synchronize ' \
|
||||
'DNS zone keys and metadata.'
|
||||
print 'Error: %s' % e
|
||||
sys.exit(0)
|
||||
if len(sys.argv) != 2:
|
||||
print(__doc__)
|
||||
print('ERROR: Exactly one parameter or socket activation is required.')
|
||||
sys.exit(1)
|
||||
conn = None
|
||||
cmd = sys.argv[1]
|
||||
|
||||
exitcode, msg, zone_name = parse_command(cmd)
|
||||
|
||||
if conn:
|
||||
send_systemd_reply(conn, msg)
|
||||
if exitcode is not None:
|
||||
log.info(msg)
|
||||
sys.exit(exitcode)
|
||||
else:
|
||||
log.debug(msg)
|
||||
|
||||
ods_keys = get_ods_keys(zone_name)
|
||||
ods_keys_id = set(ods_keys.keys())
|
||||
|
||||
Reference in New Issue
Block a user