Imported Upstream version 4.8.10
This commit is contained in:
46
daemons/dnssec/Makefile.am
Normal file
46
daemons/dnssec/Makefile.am
Normal file
@@ -0,0 +1,46 @@
|
||||
# This file will be processed with automake-1.7 to create Makefile.in
|
||||
#
|
||||
AUTOMAKE_OPTIONS = 1.7
|
||||
|
||||
appdir = $(libexecdir)/ipa/
|
||||
nodist_app_SCRIPTS = \
|
||||
ipa-dnskeysyncd \
|
||||
ipa-dnskeysync-replica \
|
||||
ipa-ods-exporter
|
||||
|
||||
dist_noinst_DATA = \
|
||||
ipa-dnskeysyncd.service.in \
|
||||
ipa-ods-exporter.service.in \
|
||||
ipa-ods-exporter.socket.in \
|
||||
ipa-dnskeysyncd.in \
|
||||
ipa-dnskeysync-replica.in \
|
||||
ipa-ods-exporter.in
|
||||
|
||||
|
||||
systemdsystemunit_DATA = \
|
||||
ipa-dnskeysyncd.service \
|
||||
ipa-ods-exporter.service \
|
||||
ipa-ods-exporter.socket
|
||||
|
||||
CLEANFILES = $(systemdsystemunit_DATA) $(nodist_app_SCRIPTS)
|
||||
|
||||
%: %.in Makefile
|
||||
sed \
|
||||
-e 's|@libexecdir[@]|$(libexecdir)|g' \
|
||||
-e 's|@localstatedir[@]|$(localstatedir)|g' \
|
||||
-e 's|@sysconfenvdir[@]|$(sysconfenvdir)|g' \
|
||||
-e 's|@runstatedir[@]|$(runstatedir)|g' \
|
||||
-e 's|@ODS_USER[@]|$(ODS_USER)|g' \
|
||||
-e 's|@ODS_GROUP[@]|$(ODS_GROUP)|g' \
|
||||
-e 's|@NAMED_GROUP[@]|$(NAMED_GROUP)|g' \
|
||||
'$(srcdir)/$@.in' >$@
|
||||
|
||||
dnssecconfdir = $(IPA_SYSCONF_DIR)/dnssec
|
||||
install-data-hook:
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(dnssecconfdir)
|
||||
|
||||
PYTHON_SHEBANG = \
|
||||
$(nodist_app_SCRIPTS) \
|
||||
$(NULL)
|
||||
|
||||
include $(top_srcdir)/Makefile.pythonscripts.am
|
||||
704
daemons/dnssec/Makefile.in
Normal file
704
daemons/dnssec/Makefile.in
Normal file
@@ -0,0 +1,704 @@
|
||||
# Makefile.in generated by automake 1.16.2 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = daemons/dnssec
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
|
||||
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
|
||||
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
|
||||
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
|
||||
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/VERSION.m4 \
|
||||
$(top_srcdir)/server.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(dist_noinst_DATA) \
|
||||
$(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
am__installdirs = "$(DESTDIR)$(appdir)" \
|
||||
"$(DESTDIR)$(systemdsystemunitdir)"
|
||||
SCRIPTS = $(nodist_app_SCRIPTS)
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
DATA = $(dist_noinst_DATA) $(systemdsystemunit_DATA)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in \
|
||||
$(top_srcdir)/Makefile.pythonscripts.am
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
API_VERSION = @API_VERSION@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
|
||||
CMOCKA_LIBS = @CMOCKA_LIBS@
|
||||
CONFIG_STATUS = @CONFIG_STATUS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CRYPTO_CFLAGS = @CRYPTO_CFLAGS@
|
||||
CRYPTO_LIBS = @CRYPTO_LIBS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DATA_VERSION = @DATA_VERSION@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DIRSRV_CFLAGS = @DIRSRV_CFLAGS@
|
||||
DIRSRV_LIBS = @DIRSRV_LIBS@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GETTEXT_DOMAIN = @GETTEXT_DOMAIN@
|
||||
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
|
||||
GIT_BRANCH = @GIT_BRANCH@
|
||||
GIT_VERSION = @GIT_VERSION@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
GMSGFMT_015 = @GMSGFMT_015@
|
||||
GREP = @GREP@
|
||||
INI_CFLAGS = @INI_CFLAGS@
|
||||
INI_LIBS = @INI_LIBS@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
INTLLIBS = @INTLLIBS@
|
||||
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
|
||||
IPAPLATFORM = @IPAPLATFORM@
|
||||
IPA_DATA_DIR = @IPA_DATA_DIR@
|
||||
IPA_SYSCONF_DIR = @IPA_SYSCONF_DIR@
|
||||
JSLINT = @JSLINT@
|
||||
KRAD_LIBS = @KRAD_LIBS@
|
||||
KRB5KDC_SERVICE = @KRB5KDC_SERVICE@
|
||||
KRB5_CFLAGS = @KRB5_CFLAGS@
|
||||
KRB5_GSSAPI_CFLAGS = @KRB5_GSSAPI_CFLAGS@
|
||||
KRB5_GSSAPI_LIBS = @KRB5_GSSAPI_LIBS@
|
||||
KRB5_LIBS = @KRB5_LIBS@
|
||||
LD = @LD@
|
||||
LDAP_CFLAGS = @LDAP_CFLAGS@
|
||||
LDAP_LIBS = @LDAP_LIBS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBICONV = @LIBICONV@
|
||||
LIBINTL = @LIBINTL@
|
||||
LIBINTL_LIBS = @LIBINTL_LIBS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBPDB_NAME = @LIBPDB_NAME@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBVERTO_CFLAGS = @LIBVERTO_CFLAGS@
|
||||
LIBVERTO_LIBS = @LIBVERTO_LIBS@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBICONV = @LTLIBICONV@
|
||||
LTLIBINTL = @LTLIBINTL@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MK_ASSIGN = @MK_ASSIGN@
|
||||
MK_ELSE = @MK_ELSE@
|
||||
MK_ENDIF = @MK_ENDIF@
|
||||
MK_IFEQ = @MK_IFEQ@
|
||||
MSGATTRIB = @MSGATTRIB@
|
||||
MSGFMT = @MSGFMT@
|
||||
MSGFMT_015 = @MSGFMT_015@
|
||||
MSGMERGE = @MSGMERGE@
|
||||
NAMED_GROUP = @NAMED_GROUP@
|
||||
NDRNBT_CFLAGS = @NDRNBT_CFLAGS@
|
||||
NDRNBT_LIBS = @NDRNBT_LIBS@
|
||||
NDRPAC_CFLAGS = @NDRPAC_CFLAGS@
|
||||
NDRPAC_LIBS = @NDRPAC_LIBS@
|
||||
NDR_CFLAGS = @NDR_CFLAGS@
|
||||
NDR_LIBS = @NDR_LIBS@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
NSPR_CFLAGS = @NSPR_CFLAGS@
|
||||
NSPR_LIBS = @NSPR_LIBS@
|
||||
NUM_VERSION = @NUM_VERSION@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
ODS_GROUP = @ODS_GROUP@
|
||||
ODS_USER = @ODS_USER@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PKG_CONFIG = @PKG_CONFIG@
|
||||
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PLATFORM_PYTHON = @PLATFORM_PYTHON@
|
||||
POPT_CFLAGS = @POPT_CFLAGS@
|
||||
POPT_LIBS = @POPT_LIBS@
|
||||
POSUB = @POSUB@
|
||||
PYLINT = @PYLINT@
|
||||
PYTHON = @PYTHON@
|
||||
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
|
||||
PYTHON_INSTALL_EXTRA_OPTIONS = @PYTHON_INSTALL_EXTRA_OPTIONS@
|
||||
PYTHON_PLATFORM = @PYTHON_PLATFORM@
|
||||
PYTHON_PREFIX = @PYTHON_PREFIX@
|
||||
PYTHON_VERSION = @PYTHON_VERSION@
|
||||
RANLIB = @RANLIB@
|
||||
SAMBA40EXTRA_LIBPATH = @SAMBA40EXTRA_LIBPATH@
|
||||
SAMBAUTIL_CFLAGS = @SAMBAUTIL_CFLAGS@
|
||||
SAMBAUTIL_LIBS = @SAMBAUTIL_LIBS@
|
||||
SASL_CFLAGS = @SASL_CFLAGS@
|
||||
SASL_LIBS = @SASL_LIBS@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSSCERTMAP_CFLAGS = @SSSCERTMAP_CFLAGS@
|
||||
SSSCERTMAP_LIBS = @SSSCERTMAP_LIBS@
|
||||
SSSIDMAP_CFLAGS = @SSSIDMAP_CFLAGS@
|
||||
SSSIDMAP_LIBS = @SSSIDMAP_LIBS@
|
||||
SSSNSSIDMAP_CFLAGS = @SSSNSSIDMAP_CFLAGS@
|
||||
SSSNSSIDMAP_LIBS = @SSSNSSIDMAP_LIBS@
|
||||
STRIP = @STRIP@
|
||||
TALLOC_CFLAGS = @TALLOC_CFLAGS@
|
||||
TALLOC_LIBS = @TALLOC_LIBS@
|
||||
TEVENT_CFLAGS = @TEVENT_CFLAGS@
|
||||
TEVENT_LIBS = @TEVENT_LIBS@
|
||||
UNISTRING_LIBS = @UNISTRING_LIBS@
|
||||
UNLINK = @UNLINK@
|
||||
USE_NLS = @USE_NLS@
|
||||
UUID_CFLAGS = @UUID_CFLAGS@
|
||||
UUID_LIBS = @UUID_LIBS@
|
||||
VENDOR_SUFFIX = @VENDOR_SUFFIX@
|
||||
VERSION = @VERSION@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
XGETTEXT_015 = @XGETTEXT_015@
|
||||
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
|
||||
XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
|
||||
XMLRPC_LIBS = @XMLRPC_LIBS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
i18ntests = @i18ntests@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
krb5rundir = @krb5rundir@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
pkgpyexecdir = @pkgpyexecdir@
|
||||
pkgpythondir = @pkgpythondir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
pyexecdir = @pyexecdir@
|
||||
pythondir = @pythondir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
selinux_makefile = @selinux_makefile@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sysconfenvdir = @sysconfenvdir@
|
||||
systemdsystemunitdir = @systemdsystemunitdir@
|
||||
systemdtmpfilesdir = @systemdtmpfilesdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
# This file will be processed with automake-1.7 to create Makefile.in
|
||||
#
|
||||
AUTOMAKE_OPTIONS = 1.7
|
||||
appdir = $(libexecdir)/ipa/
|
||||
nodist_app_SCRIPTS = \
|
||||
ipa-dnskeysyncd \
|
||||
ipa-dnskeysync-replica \
|
||||
ipa-ods-exporter
|
||||
|
||||
dist_noinst_DATA = \
|
||||
ipa-dnskeysyncd.service.in \
|
||||
ipa-ods-exporter.service.in \
|
||||
ipa-ods-exporter.socket.in \
|
||||
ipa-dnskeysyncd.in \
|
||||
ipa-dnskeysync-replica.in \
|
||||
ipa-ods-exporter.in
|
||||
|
||||
systemdsystemunit_DATA = \
|
||||
ipa-dnskeysyncd.service \
|
||||
ipa-ods-exporter.service \
|
||||
ipa-ods-exporter.socket
|
||||
|
||||
CLEANFILES = $(systemdsystemunit_DATA) $(nodist_app_SCRIPTS)
|
||||
dnssecconfdir = $(IPA_SYSCONF_DIR)/dnssec
|
||||
PYTHON_SHEBANG = \
|
||||
$(nodist_app_SCRIPTS) \
|
||||
$(NULL)
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/Makefile.pythonscripts.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign daemons/dnssec/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign daemons/dnssec/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
|
||||
esac;
|
||||
$(top_srcdir)/Makefile.pythonscripts.am $(am__empty):
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-nodist_appSCRIPTS: $(nodist_app_SCRIPTS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(nodist_app_SCRIPTS)'; test -n "$(appdir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(appdir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(appdir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n' \
|
||||
-e 'h;s|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) { files[d] = files[d] " " $$1; \
|
||||
if (++n[d] == $(am__install_max)) { \
|
||||
print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
|
||||
else { print "f", d "/" $$4, $$1 } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(appdir)$$dir'"; \
|
||||
$(INSTALL_SCRIPT) $$files "$(DESTDIR)$(appdir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-nodist_appSCRIPTS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(nodist_app_SCRIPTS)'; test -n "$(appdir)" || exit 0; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 's,.*/,,;$(transform)'`; \
|
||||
dir='$(DESTDIR)$(appdir)'; $(am__uninstall_files_from_dir)
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
install-systemdsystemunitDATA: $(systemdsystemunit_DATA)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(systemdsystemunitdir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(systemdsystemunitdir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemdsystemunitdir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(systemdsystemunitdir)" || exit $$?; \
|
||||
done
|
||||
|
||||
uninstall-systemdsystemunitDATA:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \
|
||||
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
|
||||
dir='$(DESTDIR)$(systemdsystemunitdir)'; $(am__uninstall_files_from_dir)
|
||||
tags TAGS:
|
||||
|
||||
ctags CTAGS:
|
||||
|
||||
cscope cscopelist:
|
||||
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
distdir-am: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(SCRIPTS) $(DATA)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(appdir)" "$(DESTDIR)$(systemdsystemunitdir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-nodist_appSCRIPTS \
|
||||
install-systemdsystemunitDATA
|
||||
@$(NORMAL_INSTALL)
|
||||
$(MAKE) $(AM_MAKEFLAGS) install-data-hook
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-nodist_appSCRIPTS \
|
||||
uninstall-systemdsystemunitDATA
|
||||
|
||||
.MAKE: install-am install-data-am install-strip
|
||||
|
||||
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
|
||||
cscopelist-am ctags-am distclean distclean-generic \
|
||||
distclean-libtool distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am \
|
||||
install-data-hook install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-nodist_appSCRIPTS \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip install-systemdsystemunitDATA installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
|
||||
uninstall-am uninstall-nodist_appSCRIPTS \
|
||||
uninstall-systemdsystemunitDATA
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
%: %.in Makefile
|
||||
sed \
|
||||
-e 's|@libexecdir[@]|$(libexecdir)|g' \
|
||||
-e 's|@localstatedir[@]|$(localstatedir)|g' \
|
||||
-e 's|@sysconfenvdir[@]|$(sysconfenvdir)|g' \
|
||||
-e 's|@runstatedir[@]|$(runstatedir)|g' \
|
||||
-e 's|@ODS_USER[@]|$(ODS_USER)|g' \
|
||||
-e 's|@ODS_GROUP[@]|$(ODS_GROUP)|g' \
|
||||
-e 's|@NAMED_GROUP[@]|$(NAMED_GROUP)|g' \
|
||||
'$(srcdir)/$@.in' >$@
|
||||
install-data-hook:
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(dnssecconfdir)
|
||||
|
||||
# special handling of Python scripts with auto-generated shebang line
|
||||
$(PYTHON_SHEBANG):%: %.in Makefile
|
||||
$(AM_V_GEN)sed -e 's|^#!/usr/bin/python3.*|#!$(PYTHON) -I|g' $< > $@
|
||||
$(AM_V_GEN)chmod +x $@
|
||||
|
||||
.PHONY: python_scripts_sub
|
||||
python_scripts_sub: $(PYTHON_SHEBANG)
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
196
daemons/dnssec/ipa-dnskeysync-replica.in
Normal file
196
daemons/dnssec/ipa-dnskeysync-replica.in
Normal file
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# 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 import errors
|
||||
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]
|
||||
return None
|
||||
|
||||
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')
|
||||
|
||||
keys_dn = DN(
|
||||
('cn', 'keys'), ('cn', 'sec'),
|
||||
ipalib.api.env.container_dns,
|
||||
ipalib.api.env.basedn
|
||||
)
|
||||
|
||||
with open(paths.DNSSEC_SOFTHSM_PIN) as f:
|
||||
localhsm = LocalHSM(
|
||||
paths.LIBSOFTHSM2_SO,
|
||||
SOFTHSM_DNSSEC_TOKEN_LABEL,
|
||||
f.read()
|
||||
)
|
||||
|
||||
try:
|
||||
# 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, keys_dn)
|
||||
ldap2replica_master_keys_sync(ldapkeydb, localhsm)
|
||||
ldap2replica_zone_keys_sync(ldapkeydb, localhsm)
|
||||
except (errors.NetworkError, errors.DatabaseError) as e:
|
||||
# SERVER_DOWN, CONNECT_ERROR
|
||||
logger.error("LDAP server is down: %s", e)
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.exit(0)
|
||||
120
daemons/dnssec/ipa-dnskeysyncd.in
Normal file
120
daemons/dnssec/ipa-dnskeysyncd.in
Normal file
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import ldap
|
||||
import ldapurl
|
||||
import os
|
||||
import signal
|
||||
import time
|
||||
|
||||
from ipalib import api
|
||||
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.keysyncer import KeySyncer
|
||||
|
||||
logger = logging.getLogger(os.path.basename(__file__))
|
||||
|
||||
|
||||
# IPA framework initialization
|
||||
standard_logging_setup(verbose=True)
|
||||
api.bootstrap(context='dns', confdir=paths.ETC_IPA, in_server=True)
|
||||
api.finalize()
|
||||
if api.env.debug:
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.setLevel(logging.DEBUG)
|
||||
|
||||
# Global state
|
||||
watcher_running = True
|
||||
ldap_connection = False
|
||||
|
||||
DAEMONNAME = 'ipa-dnskeysyncd'
|
||||
PRINCIPAL = None # not initialized yet
|
||||
WORKDIR = '/tmp' # private temp
|
||||
KEYTAB_FB = paths.IPA_DNSKEYSYNCD_KEYTAB
|
||||
|
||||
# Shutdown handler
|
||||
def commenceShutdown(signum, stack):
|
||||
# Declare the needed global variables
|
||||
global watcher_running
|
||||
global ldap_connection # pylint: disable=global-variable-not-assigned
|
||||
|
||||
logger.info('Signal %s received: Shutting down!', signum)
|
||||
|
||||
# We are no longer running
|
||||
watcher_running = False
|
||||
|
||||
# Tear down the server connection
|
||||
if ldap_connection:
|
||||
ldap_connection.close_db()
|
||||
del ldap_connection
|
||||
|
||||
# Shutdown
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
os.umask(0o07)
|
||||
|
||||
# Signal handlers
|
||||
signal.signal(signal.SIGTERM, commenceShutdown)
|
||||
signal.signal(signal.SIGINT, commenceShutdown)
|
||||
|
||||
# Kerberos initialization
|
||||
PRINCIPAL = str('%s/%s' % (DAEMONNAME, api.env.host))
|
||||
logger.debug('Kerberos principal: %s', PRINCIPAL)
|
||||
ccache_filename = os.path.join(WORKDIR, 'ipa-dnskeysyncd.ccache')
|
||||
try:
|
||||
kinit_keytab(PRINCIPAL, KEYTAB_FB, ccache_filename, attempts=5)
|
||||
except Exception as ex:
|
||||
logger.critical("Kerberos authentication failed: %s", ex)
|
||||
# signal failure and let init system to restart the daemon
|
||||
sys.exit(1)
|
||||
os.environ['KRB5CCNAME'] = ccache_filename
|
||||
|
||||
# LDAP initialization
|
||||
basedn = DN(api.env.container_dns, api.env.basedn)
|
||||
ldap_url = ldapurl.LDAPUrl(api.env.ldap_uri)
|
||||
ldap_url.dn = str(basedn)
|
||||
ldap_url.scope = ldapurl.LDAP_SCOPE_SUBTREE
|
||||
ldap_url.filterstr = '(|(objectClass=idnsZone)(objectClass=idnsSecKey)(objectClass=ipk11PublicKey))'
|
||||
logger.debug('LDAP URL: %s', ldap_url.unparse())
|
||||
|
||||
# Real work
|
||||
while watcher_running:
|
||||
# Prepare the LDAP server connection (triggers the connection as well)
|
||||
ldap_connection = KeySyncer(ldap_url.initializeUrl(), ipa_api=api)
|
||||
|
||||
# Now we login to the LDAP server
|
||||
try:
|
||||
logger.info('LDAP bind...')
|
||||
ldap_connection.sasl_interactive_bind_s("", ipaldap.SASL_GSSAPI)
|
||||
except ldap.INVALID_CREDENTIALS as e:
|
||||
logger.exception('Login to LDAP server failed: %s', e)
|
||||
sys.exit(1)
|
||||
except (ldap.SERVER_DOWN, ldap.CONNECT_ERROR) as e:
|
||||
logger.exception('LDAP server is down, going to retry: %s', e)
|
||||
time.sleep(5)
|
||||
continue
|
||||
|
||||
# Commence the syncing
|
||||
logger.info('Commencing sync process')
|
||||
ldap_search = ldap_connection.syncrepl_search(
|
||||
ldap_url.dn,
|
||||
ldap_url.scope,
|
||||
mode='refreshAndPersist',
|
||||
attrlist=ldap_url.attrs,
|
||||
filterstr=ldap_url.filterstr
|
||||
)
|
||||
|
||||
try:
|
||||
while ldap_connection.syncrepl_poll(all=1, msgid=ldap_search):
|
||||
pass
|
||||
except (ldap.SERVER_DOWN, ldap.CONNECT_ERROR) as e:
|
||||
logger.error('syncrepl_poll: LDAP error (%s)', e)
|
||||
sys.exit(1)
|
||||
15
daemons/dnssec/ipa-dnskeysyncd.service.in
Normal file
15
daemons/dnssec/ipa-dnskeysyncd.service.in
Normal file
@@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=IPA key daemon
|
||||
|
||||
[Service]
|
||||
EnvironmentFile=@sysconfenvdir@/ipa-dnskeysyncd
|
||||
ExecStart=@libexecdir@/ipa/ipa-dnskeysyncd
|
||||
User=@ODS_USER@
|
||||
Group=@NAMED_GROUP@
|
||||
SupplementaryGroups=@ODS_USER@
|
||||
PrivateTmp=yes
|
||||
Restart=on-failure
|
||||
RestartSec=60s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
787
daemons/dnssec/ipa-ods-exporter.in
Normal file
787
daemons/dnssec/ipa-ods-exporter.in
Normal file
@@ -0,0 +1,787 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
"""
|
||||
This is FreeIPA's replacement for signerd from OpenDNSSEC suite version 1.4.x.
|
||||
|
||||
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.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
import select
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import dateutil.tz
|
||||
import dns.dnssec
|
||||
from gssapi.exceptions import GSSError
|
||||
import six
|
||||
import systemd.daemon
|
||||
import systemd.journal
|
||||
|
||||
import ipalib
|
||||
from ipalib.constants import SOFTHSM_DNSSEC_TOKEN_LABEL
|
||||
from ipalib.install.kinit import kinit_keytab
|
||||
from ipapython.dn import DN
|
||||
from ipapython import ipaldap
|
||||
from ipaplatform.paths import paths
|
||||
from ipaserver.dnssec.abshsm import sync_pkcs11_metadata, wrappingmech_name2id
|
||||
from ipaserver.dnssec.ldapkeydb import LdapKeyDB, str_hexlify
|
||||
from ipaserver.dnssec.localhsm import LocalHSM
|
||||
|
||||
from ipaserver.dnssec import opendnssec
|
||||
|
||||
logger = logging.getLogger(os.path.basename(__file__))
|
||||
|
||||
DAEMONNAME = 'ipa-ods-exporter'
|
||||
PRINCIPAL = None # not initialized yet
|
||||
WORKDIR = os.path.join(paths.VAR_OPENDNSSEC_DIR ,'tmp')
|
||||
KEYTAB_FB = paths.IPA_ODS_EXPORTER_KEYTAB
|
||||
|
||||
ODS_SE_MAXLINE = 1024 # from ODS common/config.h
|
||||
ODS_DB_LOCK_PATH = "%s%s" % (paths.OPENDNSSEC_KASP_DB, '.our_lock')
|
||||
|
||||
SECRETKEY_WRAPPING_MECH = 'rsaPkcsOaep'
|
||||
PRIVKEY_WRAPPING_MECH = 'aesKeyWrapPad'
|
||||
|
||||
# Constants from OpenDNSSEC's enforcer/ksm/include/ksm/ksm.h
|
||||
KSM_STATE_PUBLISH = 2
|
||||
KSM_STATE_READY = 3
|
||||
KSM_STATE_ACTIVE = 4
|
||||
KSM_STATE_RETIRE = 5
|
||||
KSM_STATE_DEAD = 6
|
||||
KSM_STATE_KEYPUBLISH = 10
|
||||
|
||||
# DNSKEY flag constants
|
||||
dnskey_flag_by_value = {
|
||||
0x0001: 'SEP',
|
||||
0x0080: 'REVOKE',
|
||||
0x0100: 'ZONE'
|
||||
}
|
||||
|
||||
def dnskey_flags_to_text_set(flags):
|
||||
"""Convert a DNSKEY flags value to set texts
|
||||
@rtype: set([string])"""
|
||||
|
||||
flags_set = set()
|
||||
mask = 0x1
|
||||
while mask <= 0x8000:
|
||||
if flags & mask:
|
||||
text = dnskey_flag_by_value.get(mask)
|
||||
if not text:
|
||||
text = hex(mask)
|
||||
flags_set.add(text)
|
||||
mask <<= 1
|
||||
return flags_set
|
||||
|
||||
def datetime2ldap(dt):
|
||||
return dt.strftime(ipalib.constants.LDAP_GENERALIZED_TIME_FORMAT)
|
||||
|
||||
def sql2datetime(sql_time):
|
||||
"""Convert SQL date format from local time zone into UTC."""
|
||||
localtz = dateutil.tz.tzlocal()
|
||||
localtime = datetime.strptime(sql_time, "%Y-%m-%d %H:%M:%S").replace(
|
||||
tzinfo=localtz)
|
||||
utctz = dateutil.tz.gettz('UTC')
|
||||
return localtime.astimezone(utctz)
|
||||
|
||||
def sql2datetimes(row):
|
||||
row2key_map = {'generate': 'idnsSecKeyCreated',
|
||||
'publish': 'idnsSecKeyPublish',
|
||||
'active': 'idnsSecKeyActivate',
|
||||
'retire': 'idnsSecKeyInactive',
|
||||
'dead': 'idnsSecKeyDelete'}
|
||||
times = {}
|
||||
for column, key in row2key_map.items():
|
||||
if row[column] is not None:
|
||||
times[key] = sql2datetime(row[column])
|
||||
return times
|
||||
|
||||
def sql2ldap_algorithm(sql_algorithm):
|
||||
return {"idnsSecAlgorithm": dns.dnssec.algorithm_to_text(sql_algorithm)}
|
||||
|
||||
def sql2ldap_flags(sql_flags):
|
||||
dns_flags = dnskey_flags_to_text_set(sql_flags)
|
||||
ldap_flags = {}
|
||||
for flag in dns_flags:
|
||||
attr = 'idnsSecKey%s' % flag
|
||||
ldap_flags[attr] = 'TRUE'
|
||||
return ldap_flags
|
||||
|
||||
def sql2ldap_keyid(sql_keyid):
|
||||
assert len(sql_keyid) % 2 == 0
|
||||
assert len(sql_keyid) > 0
|
||||
# TODO: this is huge hack. BIND has some problems with % notation in URIs.
|
||||
# Workaround: OpenDNSSEC uses same value for ID also for label (but in hex).
|
||||
uri = "pkcs11:object=%s" % sql_keyid
|
||||
#uri += '%'.join(sql_keyid[i:i+2] for i in range(0, len(sql_keyid), 2))
|
||||
return {"idnsSecKeyRef": uri}
|
||||
|
||||
def ods2bind_timestamps(key_state, key_type, ods_times):
|
||||
"""Transform (timestamps and key states) from ODS to set of BIND timestamps
|
||||
with equivalent meaning. At the same time, remove timestamps
|
||||
for future/planned state transitions to prevent ODS & BIND
|
||||
from desynchronizing.
|
||||
|
||||
OpenDNSSEC database may contain timestamps for state transitions planned
|
||||
in the future, but timestamp itself is not sufficient information because
|
||||
there could be some additional condition which is guaded by OpenDNSSEC
|
||||
itself.
|
||||
|
||||
BIND works directly with timestamps without any additional conditions.
|
||||
This difference causes problem when state transition planned in OpenDNSSEC
|
||||
does not happen as originally planned for some reason.
|
||||
|
||||
At the same time, this difference causes problem when OpenDNSSEC on DNSSEC
|
||||
key master and BIND instances on replicas are not synchronized. This
|
||||
happens when DNSSEC key master is down, or a replication is down. Even
|
||||
a temporary desynchronization could cause DNSSEC validation failures
|
||||
which could have huge impact.
|
||||
|
||||
To prevent this problem, this function removes all timestamps corresponding
|
||||
to future state transitions. As a result, BIND will not do state transition
|
||||
until it happens in OpenDNSSEC first and until the change is replicated.
|
||||
|
||||
Also, timestamp mapping depends on key type and is not 1:1.
|
||||
For detailed description of the mapping please see
|
||||
https://fedorahosted.org/bind-dyndb-ldap/wiki/BIND9/Design/DNSSEC/OpenDNSSEC2BINDKeyStates
|
||||
"""
|
||||
bind_times = {}
|
||||
# idnsSecKeyCreated is equivalent to SQL column 'created'
|
||||
bind_times['idnsSecKeyCreated'] = ods_times['idnsSecKeyCreated']
|
||||
|
||||
# set of key states where publishing in DNS zone is desired is taken from
|
||||
# opendnssec/enforcer/ksm/ksm_request.c:KsmRequestIssueKeys()
|
||||
# TODO: support for RFC 5011, requires OpenDNSSEC v1.4.8+
|
||||
if ('idnsSecKeyPublish' in ods_times and
|
||||
key_state in {KSM_STATE_PUBLISH, KSM_STATE_READY, KSM_STATE_ACTIVE,
|
||||
KSM_STATE_RETIRE, KSM_STATE_KEYPUBLISH}):
|
||||
bind_times['idnsSecKeyPublish'] = ods_times['idnsSecKeyPublish']
|
||||
|
||||
# ZSK and KSK handling differs in enforcerd, see
|
||||
# opendnssec/enforcer/enforcerd/enforcer.c:commKeyConfig()
|
||||
if key_type == 'ZSK':
|
||||
# idnsSecKeyActivate cannot be set before the key reaches ACTIVE state
|
||||
if ('idnsSecKeyActivate' in ods_times and
|
||||
key_state in {KSM_STATE_ACTIVE, KSM_STATE_RETIRE, KSM_STATE_DEAD}):
|
||||
bind_times['idnsSecKeyActivate'] = ods_times['idnsSecKeyActivate']
|
||||
|
||||
# idnsSecKeyInactive cannot be set before the key reaches RETIRE state
|
||||
if ('idnsSecKeyInactive' in ods_times and
|
||||
key_state in {KSM_STATE_RETIRE, KSM_STATE_DEAD}):
|
||||
bind_times['idnsSecKeyInactive'] = ods_times['idnsSecKeyInactive']
|
||||
|
||||
elif key_type == 'KSK':
|
||||
# KSK is special: it is used for signing as long as it is in zone
|
||||
if ('idnsSecKeyPublish' in ods_times and
|
||||
key_state in {KSM_STATE_PUBLISH, KSM_STATE_READY, KSM_STATE_ACTIVE,
|
||||
KSM_STATE_RETIRE, KSM_STATE_KEYPUBLISH}):
|
||||
bind_times['idnsSecKeyActivate'] = ods_times['idnsSecKeyPublish']
|
||||
# idnsSecKeyInactive is ignored for KSK on purpose
|
||||
|
||||
else:
|
||||
raise ValueError("unsupported key type %s" % key_type)
|
||||
|
||||
# idnsSecKeyDelete is relevant only in DEAD state
|
||||
if 'idnsSecKeyDelete' in ods_times and key_state == KSM_STATE_DEAD:
|
||||
bind_times['idnsSecKeyDelete'] = ods_times['idnsSecKeyDelete']
|
||||
|
||||
return bind_times
|
||||
|
||||
def get_ldap_zone(ldap, dns_base, name):
|
||||
zone_names = ["%s." % name, name]
|
||||
|
||||
# find zone object: name can optionally end with period
|
||||
ldap_zone = None
|
||||
for zone_name in zone_names:
|
||||
zone_base = DN("idnsname=%s" % zone_name, dns_base)
|
||||
try:
|
||||
ldap_zone = ldap.get_entry(dn=zone_base,
|
||||
attrs_list=["idnsname"])
|
||||
break
|
||||
except ipalib.errors.NotFound:
|
||||
continue
|
||||
|
||||
if ldap_zone is None:
|
||||
raise ipalib.errors.NotFound(
|
||||
reason='DNS zone "%s" not found in LDAP' % name)
|
||||
|
||||
return ldap_zone
|
||||
|
||||
def get_ldap_keys_dn(zone_dn):
|
||||
"""Container DN"""
|
||||
return DN("cn=keys", zone_dn)
|
||||
|
||||
def get_ldap_keys(ldap, zone_dn):
|
||||
"""Keys objects"""
|
||||
keys_dn = get_ldap_keys_dn(zone_dn)
|
||||
ldap_filter = ldap.make_filter_from_attr('objectClass', 'idnsSecKey')
|
||||
ldap_keys = ldap.get_entries(base_dn=keys_dn, filter=ldap_filter)
|
||||
|
||||
return ldap_keys
|
||||
|
||||
def get_ods_keys(zone_name):
|
||||
# get zone ID
|
||||
rows = db.get_zone_id(zone_name)
|
||||
if len(rows) != 1:
|
||||
raise ValueError("exactly one DNS zone should exist in ODS DB")
|
||||
zone_id = rows[0]
|
||||
|
||||
# get relevant keys for given zone ID:
|
||||
# ignore keys which were generated but not used yet
|
||||
# key state check is using constants from
|
||||
# OpenDNSSEC's enforcer/ksm/include/ksm/ksm.h
|
||||
# WARNING! OpenDNSSEC version 1 and 2 are using different constants!
|
||||
rows = db.get_keys_for_zone(zone_id)
|
||||
keys = {}
|
||||
for row in rows:
|
||||
key_data = sql2ldap_flags(row['keytype'])
|
||||
if key_data.get('idnsSecKeyZONE') != 'TRUE':
|
||||
raise ValueError("unexpected key type 0x%x" % row['keytype'])
|
||||
if key_data.get('idnsSecKeySEP', 'FALSE') == 'TRUE':
|
||||
key_type = 'KSK'
|
||||
else:
|
||||
key_type = 'ZSK'
|
||||
|
||||
# transform key state to timestamps for BIND with equivalent semantics
|
||||
ods_times = sql2datetimes(row)
|
||||
key_data.update(
|
||||
ods2bind_timestamps(row['state'], key_type, ods_times)
|
||||
)
|
||||
|
||||
key_data.update(sql2ldap_algorithm(row['algorithm']))
|
||||
key_id = "%s-%s-%s" % (
|
||||
key_type,
|
||||
datetime2ldap(key_data['idnsSecKeyCreated']),
|
||||
row['HSMkey_id']
|
||||
)
|
||||
|
||||
key_data.update(sql2ldap_keyid(row['HSMkey_id']))
|
||||
keys[key_id] = key_data
|
||||
logger.debug("key %s metadata: %s", key_id, key_data)
|
||||
|
||||
return keys
|
||||
|
||||
def sync_set_metadata_2ldap(name, source_set, target_set):
|
||||
"""sync metadata from source key set to target key set in LDAP
|
||||
|
||||
Keys not present in both sets are left intact."""
|
||||
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 ldap2master_replica_keys_sync(ldapkeydb, localhsm):
|
||||
"""LDAP=>master's local HSM replica key synchronization"""
|
||||
# import new replica keys from LDAP
|
||||
logger.debug("replica pub keys in LDAP: %s",
|
||||
hex_set(ldapkeydb.replica_pubkeys_wrap))
|
||||
logger.debug("replica pub keys in SoftHSM: %s",
|
||||
hex_set(localhsm.replica_pubkeys_wrap))
|
||||
new_replica_keys = set(ldapkeydb.replica_pubkeys_wrap.keys()) \
|
||||
- set(localhsm.replica_pubkeys_wrap.keys())
|
||||
logger.info("new replica keys in LDAP: %s",
|
||||
hex_set(new_replica_keys))
|
||||
for key_id in new_replica_keys:
|
||||
new_key_ldap = ldapkeydb.replica_pubkeys_wrap[key_id]
|
||||
logger.debug('label=%s, id=%s, data=%s',
|
||||
new_key_ldap['ipk11label'],
|
||||
str_hexlify(new_key_ldap['ipk11id']),
|
||||
str_hexlify(new_key_ldap['ipapublickey']))
|
||||
localhsm.import_public_key(new_key_ldap, new_key_ldap['ipapublickey'])
|
||||
|
||||
# set CKA_WRAP = FALSE for all replica keys removed from LDAP
|
||||
removed_replica_keys = set(localhsm.replica_pubkeys_wrap.keys()) \
|
||||
- set(ldapkeydb.replica_pubkeys_wrap.keys())
|
||||
logger.info("obsolete replica keys in local HSM: %s",
|
||||
hex_set(removed_replica_keys))
|
||||
for key_id in removed_replica_keys:
|
||||
localhsm.replica_pubkeys_wrap[key_id]['ipk11wrap'] = False
|
||||
|
||||
# synchronize replica key attributes from LDAP to local HSM
|
||||
sync_set_metadata_2ldap('ldap2master_replica',
|
||||
localhsm.replica_pubkeys_wrap,
|
||||
ldapkeydb.replica_pubkeys_wrap)
|
||||
|
||||
def master2ldap_master_keys_sync(ldapkeydb, localhsm):
|
||||
## master key -> LDAP synchronization
|
||||
# export new master keys to LDAP
|
||||
new_master_keys = set(localhsm.master_keys.keys()) \
|
||||
- set(ldapkeydb.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 local HSM: %s",
|
||||
hex_set(new_master_keys))
|
||||
for mkey_id in new_master_keys:
|
||||
mkey = localhsm.master_keys[mkey_id]
|
||||
ldapkeydb.import_master_key(mkey)
|
||||
|
||||
# re-fill cache with keys we just added
|
||||
ldapkeydb.flush()
|
||||
logger.debug('master keys in LDAP after flush: %s',
|
||||
hex_set(ldapkeydb.master_keys))
|
||||
|
||||
# synchronize master key metadata to LDAP
|
||||
for mkey_id, mkey_local in localhsm.master_keys.items():
|
||||
logger.debug('synchronizing master key metadata: 0x%s',
|
||||
str_hexlify(mkey_id))
|
||||
sync_pkcs11_metadata('master2ldap_master', mkey_local, ldapkeydb.master_keys[mkey_id])
|
||||
|
||||
# re-wrap all master keys in LDAP with new replica keys (as necessary)
|
||||
enabled_replica_key_ids = set(localhsm.replica_pubkeys_wrap.keys())
|
||||
logger.debug('enabled replica key ids: %s',
|
||||
hex_set(enabled_replica_key_ids))
|
||||
|
||||
for mkey_id, mkey_ldap in ldapkeydb.master_keys.items():
|
||||
logger.debug('processing master key data: 0x%s',
|
||||
str_hexlify(mkey_id))
|
||||
|
||||
# check that all active replicas have own copy of master key
|
||||
used_replica_keys = set()
|
||||
for wrapped_entry in mkey_ldap.wrapped_entries:
|
||||
matching_keys = localhsm.find_keys(
|
||||
uri=wrapped_entry.single_value['ipaWrappingKey'])
|
||||
for matching_key in matching_keys.values():
|
||||
label = matching_key['ipk11label']
|
||||
if not label.startswith(u'dnssec-replica:'):
|
||||
raise ValueError(
|
||||
"Wrapped key '%s' refers to PKCS#11 URI '%s' which "
|
||||
"is not a known DNSSEC replica key: label '%s' "
|
||||
"does not start with 'dnssec-replica:' prefix" % (
|
||||
wrapped_entry.dn,
|
||||
wrapped_entry['ipaWrappingKey'],
|
||||
label
|
||||
)
|
||||
)
|
||||
used_replica_keys.add(matching_key['ipk11id'])
|
||||
|
||||
new_replica_keys = enabled_replica_key_ids - used_replica_keys
|
||||
logger.debug('master key 0x%s is not wrapped with replica keys %s',
|
||||
str_hexlify(mkey_id), hex_set(new_replica_keys))
|
||||
|
||||
# wrap master key with new replica keys
|
||||
mkey_local = localhsm.find_keys(id=mkey_id).popitem()[1]
|
||||
for replica_key_id in new_replica_keys:
|
||||
logger.info('adding master key 0x%s wrapped with replica key 0x%s',
|
||||
str_hexlify(mkey_id), str_hexlify(replica_key_id))
|
||||
replica_key = localhsm.replica_pubkeys_wrap[replica_key_id]
|
||||
keydata = localhsm.p11.export_wrapped_key(mkey_local.handle,
|
||||
replica_key.handle,
|
||||
wrappingmech_name2id[SECRETKEY_WRAPPING_MECH])
|
||||
mkey_ldap.add_wrapped_data(keydata, SECRETKEY_WRAPPING_MECH,
|
||||
replica_key_id)
|
||||
|
||||
ldapkeydb.flush()
|
||||
|
||||
def master2ldap_zone_keys_sync(ldapkeydb, localhsm):
|
||||
"""add and update zone key material from local HSM to LDAP
|
||||
|
||||
No key material will be removed, only new keys will be added or updated.
|
||||
Key removal is hanled by master2ldap_zone_keys_purge()."""
|
||||
keypairs_ldap = ldapkeydb.zone_keypairs
|
||||
logger.debug("zone keys in LDAP: %s", hex_set(keypairs_ldap))
|
||||
|
||||
pubkeys_local = localhsm.zone_pubkeys
|
||||
privkeys_local = localhsm.zone_privkeys
|
||||
logger.debug("zone keys in local HSM: %s", hex_set(privkeys_local))
|
||||
|
||||
if set(pubkeys_local) != set(privkeys_local):
|
||||
raise ValueError(
|
||||
"IDs of private and public keys for DNS zones in local HSM does "
|
||||
"not match to key pairs: %s vs. %s" % (
|
||||
hex_set(pubkeys_local), hex_set(privkeys_local)
|
||||
)
|
||||
)
|
||||
|
||||
new_keys = set(pubkeys_local) - set(keypairs_ldap)
|
||||
logger.debug("new zone keys in local HSM: %s", hex_set(new_keys))
|
||||
mkey = localhsm.active_master_key
|
||||
# wrap each new zone key pair with selected master key
|
||||
for zkey_id in new_keys:
|
||||
pubkey = pubkeys_local[zkey_id]
|
||||
pubkey_data = localhsm.p11.export_public_key(pubkey.handle)
|
||||
|
||||
privkey = privkeys_local[zkey_id]
|
||||
privkey_data = localhsm.p11.export_wrapped_key(privkey.handle,
|
||||
wrapping_key=mkey.handle,
|
||||
wrapping_mech=wrappingmech_name2id[PRIVKEY_WRAPPING_MECH])
|
||||
ldapkeydb.import_zone_key(pubkey, pubkey_data, privkey, privkey_data,
|
||||
PRIVKEY_WRAPPING_MECH, mkey['ipk11id'])
|
||||
|
||||
sync_set_metadata_2ldap('master2ldap_zone_keys', pubkeys_local, keypairs_ldap)
|
||||
sync_set_metadata_2ldap('master2ldap_zone_keys', privkeys_local, keypairs_ldap)
|
||||
ldapkeydb.flush()
|
||||
|
||||
def master2ldap_zone_keys_purge(ldapkeydb, localhsm):
|
||||
"""purge removed key material from LDAP (but not metadata)
|
||||
|
||||
Keys which are present in LDAP but not in local HSM will be removed.
|
||||
Key metadata must be removed first so references to removed key material
|
||||
are removed before actually removing the keys."""
|
||||
keypairs_ldap = ldapkeydb.zone_keypairs
|
||||
logger.debug("zone keys in LDAP: %s", hex_set(keypairs_ldap))
|
||||
|
||||
pubkeys_local = localhsm.zone_pubkeys
|
||||
privkeys_local = localhsm.zone_privkeys
|
||||
logger.debug("zone keys in local HSM: %s", hex_set(privkeys_local))
|
||||
if set(pubkeys_local) != set(privkeys_local):
|
||||
raise ValueError(
|
||||
"IDs of private and public keys for DNS zones in local HSM does "
|
||||
"not match to key pairs: %s vs. %s" % (
|
||||
hex_set(pubkeys_local), hex_set(privkeys_local)
|
||||
)
|
||||
)
|
||||
|
||||
deleted_key_ids = set(keypairs_ldap) - set(pubkeys_local)
|
||||
logger.debug("zone keys deleted from local HSM but present in LDAP: %s",
|
||||
hex_set(deleted_key_ids))
|
||||
for zkey_id in deleted_key_ids:
|
||||
keypairs_ldap[zkey_id].schedule_deletion()
|
||||
ldapkeydb.flush()
|
||||
|
||||
def hex_set(s):
|
||||
out = set()
|
||||
for i in s:
|
||||
out.add("0x%s" % str_hexlify(i))
|
||||
return out
|
||||
|
||||
|
||||
def receive_systemd_command():
|
||||
fds = systemd.daemon.listen_fds()
|
||||
if len(fds) != 1:
|
||||
raise KeyError('Exactly one socket is expected.')
|
||||
|
||||
sck = socket.fromfd(fds[0], socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
timeout = 1 # give the socket a bit of time
|
||||
rlist, _wlist, _xlist = select.select([sck], [], [], timeout)
|
||||
if not rlist:
|
||||
logger.critical(
|
||||
'socket activation did not return a readable socket with a '
|
||||
'command.'
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
logger.debug('accepting new connection')
|
||||
conn_tmp, _addr = sck.accept()
|
||||
conn = opendnssec.ODSSignerConn(conn_tmp)
|
||||
logger.debug('accepted new connection %s', repr(conn))
|
||||
|
||||
# this implements cmdhandler_handle_cmd() logic
|
||||
cmd = conn.read_cmd()
|
||||
|
||||
# ODS uses an ASCII protocol, the rest of the code expects str
|
||||
if six.PY3:
|
||||
cmd = cmd.decode('ascii')
|
||||
logger.debug('received command "%s" from systemd socket', cmd)
|
||||
return cmd, conn
|
||||
|
||||
def parse_command(cmd):
|
||||
"""Parse command to (exit code, message, zone_name) tuple.
|
||||
|
||||
Exit code None means that execution should continue.
|
||||
"""
|
||||
if cmd == 'ipa-hsm-update':
|
||||
return (
|
||||
0,
|
||||
'HSM synchronization finished, skipping zone synchronization.',
|
||||
None,
|
||||
cmd
|
||||
)
|
||||
|
||||
elif cmd == 'ipa-full-update':
|
||||
return (
|
||||
None,
|
||||
'Synchronization of all zones was finished.',
|
||||
None,
|
||||
cmd
|
||||
)
|
||||
|
||||
elif cmd.startswith('ldap-cleanup '):
|
||||
zone_name = cmd2ods_zone_name(cmd)
|
||||
return (
|
||||
None,
|
||||
'Zone "%s" metadata will be removed from LDAP.\n' % zone_name,
|
||||
zone_name,
|
||||
'ldap-cleanup'
|
||||
)
|
||||
|
||||
elif cmd.startswith('update '):
|
||||
zone_name = cmd2ods_zone_name(cmd)
|
||||
return (
|
||||
None,
|
||||
'Zone "%s" metadata will be updated in LDAP.\n' % zone_name,
|
||||
zone_name,
|
||||
'update'
|
||||
)
|
||||
|
||||
else:
|
||||
return (
|
||||
0,
|
||||
"Command '%s' is not supported by IPA; HSM synchronization was "
|
||||
"finished and the command will be ignored." % cmd,
|
||||
None,
|
||||
None
|
||||
)
|
||||
|
||||
|
||||
def send_systemd_reply(conn, reply):
|
||||
# Reply & close connection early.
|
||||
# This is necessary to let Enforcer to unlock the ODS DB.
|
||||
if six.PY3:
|
||||
reply = reply.encode('ascii')
|
||||
conn.send_reply_and_close(reply)
|
||||
|
||||
def cmd2ods_zone_name(cmd):
|
||||
# ODS stores zone name without trailing period
|
||||
zone_name = cmd.split(' ', 1)[1].strip()
|
||||
if len(zone_name) > 1 and zone_name[-1] == '.':
|
||||
zone_name = zone_name[:-1]
|
||||
|
||||
return zone_name
|
||||
|
||||
def sync_zone(ldap, dns_dn, zone_name):
|
||||
"""synchronize metadata about zone keys for single DNS zone
|
||||
|
||||
Key material has to be synchronized elsewhere.
|
||||
Keep in mind that keys could be shared among multiple zones!"""
|
||||
logger.debug('%s: synchronizing zone "%s"', zone_name, zone_name)
|
||||
try:
|
||||
ods_keys = get_ods_keys(zone_name)
|
||||
except ValueError as e:
|
||||
logger.error(str(e))
|
||||
return
|
||||
ods_keys_id = set(ods_keys.keys())
|
||||
|
||||
ldap_zone = get_ldap_zone(ldap, dns_dn, zone_name)
|
||||
zone_dn = ldap_zone.dn
|
||||
|
||||
keys_dn = get_ldap_keys_dn(zone_dn)
|
||||
try:
|
||||
ldap_keys = get_ldap_keys(ldap, zone_dn)
|
||||
except ipalib.errors.NotFound:
|
||||
# cn=keys container does not exist, create it
|
||||
ldap_keys = []
|
||||
ldap_keys_container = ldap.make_entry(keys_dn,
|
||||
objectClass=['nsContainer'])
|
||||
try:
|
||||
ldap.add_entry(ldap_keys_container)
|
||||
except ipalib.errors.DuplicateEntry:
|
||||
# ldap.get_entries() does not distinguish non-existent base DN
|
||||
# from empty result set so addition can fail because container
|
||||
# itself exists already
|
||||
pass
|
||||
|
||||
ldap_keys_dict = {}
|
||||
for ldap_key in ldap_keys:
|
||||
cn = ldap_key['cn'][0]
|
||||
ldap_keys_dict[cn] = ldap_key
|
||||
|
||||
ldap_keys = ldap_keys_dict # shorthand
|
||||
ldap_keys_id = set(ldap_keys.keys())
|
||||
|
||||
new_keys_id = ods_keys_id - ldap_keys_id
|
||||
logger.info('%s: new key metadata from ODS: %s', zone_name, new_keys_id)
|
||||
for key_id in new_keys_id:
|
||||
cn = "cn=%s" % key_id
|
||||
key_dn = DN(cn, keys_dn)
|
||||
logger.debug('%s: adding key metadata "%s" to LDAP', zone_name, key_dn)
|
||||
ldap_key = ldap.make_entry(key_dn,
|
||||
objectClass=['idnsSecKey'],
|
||||
**ods_keys[key_id])
|
||||
ldap.add_entry(ldap_key)
|
||||
|
||||
deleted_keys_id = ldap_keys_id - ods_keys_id
|
||||
logger.info('%s: deleted key metadata in LDAP: %s',
|
||||
zone_name, deleted_keys_id)
|
||||
for key_id in deleted_keys_id:
|
||||
cn = "cn=%s" % key_id
|
||||
key_dn = DN(cn, keys_dn)
|
||||
logger.debug('%s: deleting key metadata "%s" from LDAP',
|
||||
zone_name, key_dn)
|
||||
ldap.delete_entry(key_dn)
|
||||
|
||||
update_keys_id = ldap_keys_id.intersection(ods_keys_id)
|
||||
logger.info('%s: key metadata in LDAP & ODS: %s',
|
||||
zone_name, update_keys_id)
|
||||
for key_id in update_keys_id:
|
||||
ldap_key = ldap_keys[key_id]
|
||||
ods_key = ods_keys[key_id]
|
||||
logger.debug('%s: updating key metadata "%s" in LDAP',
|
||||
zone_name, ldap_key.dn)
|
||||
ldap_key.update(ods_key)
|
||||
try:
|
||||
ldap.update_entry(ldap_key)
|
||||
except ipalib.errors.EmptyModlist:
|
||||
continue
|
||||
|
||||
def cleanup_ldap_zone(ldap, dns_dn, zone_name):
|
||||
"""delete all key metadata about zone keys for single DNS zone
|
||||
|
||||
Key material has to be synchronized elsewhere.
|
||||
Keep in mind that keys could be shared among multiple zones!"""
|
||||
logger.debug('%s: cleaning up key metadata from zone "%s"',
|
||||
zone_name, zone_name)
|
||||
|
||||
try:
|
||||
ldap_zone = get_ldap_zone(ldap, dns_dn, zone_name)
|
||||
ldap_keys = get_ldap_keys(ldap, ldap_zone.dn)
|
||||
except ipalib.errors.NotFound as ex:
|
||||
# zone or cn=keys container does not exist, we are done
|
||||
logger.debug('%s: %s', zone_name, str(ex))
|
||||
return
|
||||
|
||||
for ldap_key in ldap_keys:
|
||||
logger.debug('%s: deleting key metadata "%s"', zone_name, ldap_key.dn)
|
||||
ldap.delete_entry(ldap_key)
|
||||
|
||||
|
||||
# this service is usually socket-activated
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.addHandler(systemd.journal.JournalHandler())
|
||||
root_logger.setLevel(level=logging.DEBUG)
|
||||
|
||||
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()
|
||||
root_logger.addHandler(console)
|
||||
|
||||
# IPA framework initialization
|
||||
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_name = paths.IPA_ODS_EXPORTER_CCACHE
|
||||
|
||||
try:
|
||||
kinit_keytab(PRINCIPAL, paths.IPA_ODS_EXPORTER_KEYTAB, ccache_name,
|
||||
attempts=5)
|
||||
except GSSError as e:
|
||||
logger.critical('Kerberos authentication failed: %s', e)
|
||||
sys.exit(1)
|
||||
|
||||
os.environ['KRB5CCNAME'] = ccache_name
|
||||
logger.debug('Got TGT')
|
||||
|
||||
# LDAP initialization
|
||||
dns_dn = DN(ipalib.api.env.container_dns, ipalib.api.env.basedn)
|
||||
ldap = ipaldap.LDAPClient(ipalib.api.env.ldap_uri)
|
||||
logger.debug('Connecting to LDAP')
|
||||
ldap.gssapi_bind()
|
||||
logger.debug('Connected')
|
||||
|
||||
|
||||
### DNSSEC master: key material upload & synchronization (but not deletion)
|
||||
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())
|
||||
|
||||
ldap2master_replica_keys_sync(ldapkeydb, localhsm)
|
||||
master2ldap_master_keys_sync(ldapkeydb, localhsm)
|
||||
master2ldap_zone_keys_sync(ldapkeydb, localhsm)
|
||||
|
||||
|
||||
### DNSSEC master: DNSSEC key metadata upload & synchronization & deletion
|
||||
# command receive is delayed so the command will stay in socket queue until
|
||||
# the problem with LDAP server or HSM is fixed
|
||||
try:
|
||||
cmd, conn = receive_systemd_command()
|
||||
if len(sys.argv) != 1:
|
||||
logger.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:
|
||||
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, cmd = parse_command(cmd)
|
||||
if exitcode:
|
||||
logger.debug("parse_command returned exitcode: %d", exitcode)
|
||||
if msg:
|
||||
logger.debug("parse_command returned msg: %s", msg)
|
||||
if zone_name:
|
||||
logger.debug("parse_command returned zone_name: %s", zone_name)
|
||||
if cmd:
|
||||
logger.debug("parse_command returned cmd: %s", cmd)
|
||||
|
||||
if exitcode is not None:
|
||||
if conn:
|
||||
send_systemd_reply(conn, msg)
|
||||
logger.info("%s", msg)
|
||||
sys.exit(exitcode)
|
||||
else:
|
||||
logger.debug("%s", msg)
|
||||
|
||||
# Open DB directly and read key timestamps etc.
|
||||
db = None
|
||||
try:
|
||||
# LOCK WARNING:
|
||||
# ods-enforcerd is holding kasp.db.our_lock when processing all zones and
|
||||
# the lock is unlocked only after all calls to ods-signer are finished,
|
||||
# i.e. when ods-enforcerd receives reply from each ods-signer call.
|
||||
#
|
||||
# Consequently, ipa-ods-exporter (ods-signerd implementation) must not
|
||||
# request kasp.db.our_lock to prevent deadlocks.
|
||||
# SQLite transaction isolation should suffice.
|
||||
# Beware: Reply can be sent back only after DB is unlocked and closed
|
||||
# otherwise ods-enforcerd will fail.
|
||||
|
||||
db = opendnssec.ODSDBConnection()
|
||||
|
||||
if zone_name is not None:
|
||||
# only one zone should be processed
|
||||
if cmd == 'update':
|
||||
sync_zone(ldap, dns_dn, zone_name)
|
||||
elif cmd == 'ldap-cleanup':
|
||||
cleanup_ldap_zone(ldap, dns_dn, zone_name)
|
||||
else:
|
||||
# process all zones
|
||||
for zone_name in db.get_zones():
|
||||
sync_zone(ldap, dns_dn, zone_name)
|
||||
|
||||
### DNSSEC master: DNSSEC key material purging
|
||||
# references to old key material were removed above in sync_zone()
|
||||
# so now we can purge old key material from LDAP
|
||||
master2ldap_zone_keys_purge(ldapkeydb, localhsm)
|
||||
|
||||
except Exception as ex:
|
||||
msg = "ipa-ods-exporter exception: %s" % traceback.format_exc(ex)
|
||||
logger.exception("%s", ex)
|
||||
raise ex
|
||||
|
||||
finally:
|
||||
try:
|
||||
if db:
|
||||
db.close()
|
||||
finally:
|
||||
if conn:
|
||||
send_systemd_reply(conn, msg)
|
||||
|
||||
logger.debug('Done')
|
||||
16
daemons/dnssec/ipa-ods-exporter.service.in
Normal file
16
daemons/dnssec/ipa-ods-exporter.service.in
Normal file
@@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=IPA OpenDNSSEC Signer replacement
|
||||
Wants=ipa-ods-exporter.socket
|
||||
After=ipa-ods-exporter.socket
|
||||
|
||||
[Service]
|
||||
EnvironmentFile=@sysconfenvdir@/ipa-ods-exporter
|
||||
ExecStart=@libexecdir@/ipa/ipa-ods-exporter
|
||||
User=@ODS_USER@
|
||||
Group=@ODS_GROUP@
|
||||
PrivateTmp=yes
|
||||
Restart=on-failure
|
||||
RestartSec=60s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
7
daemons/dnssec/ipa-ods-exporter.socket.in
Normal file
7
daemons/dnssec/ipa-ods-exporter.socket.in
Normal file
@@ -0,0 +1,7 @@
|
||||
[Socket]
|
||||
ListenStream=@runstatedir@/opendnssec/engine.sock
|
||||
SocketUser=@ODS_USER@
|
||||
SocketGroup=@ODS_GROUP@
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
Reference in New Issue
Block a user