Skip to content
10 changes: 3 additions & 7 deletions daemons/dnssec/ipa-ods-exporter.in
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ Purpose of this replacement is to upload keys generated by OpenDNSSEC to LDAP.
"""
from __future__ import print_function

from datetime import datetime
from datetime import datetime, timezone
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
Expand Down Expand Up @@ -93,11 +92,8 @@ def datetime2ldap(dt):

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)
localtime = datetime.strptime(sql_time, "%Y-%m-%d %H:%M:%S")
return localtime.astimezone(timezone.utc)

def sql2datetimes(row):
row2key_map = {'generate': 'idnsSecKeyCreated',
Expand Down
11 changes: 5 additions & 6 deletions freeipa.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,6 @@ BuildRequires: keyutils
BuildRequires: python3-augeas
BuildRequires: python3-cffi
BuildRequires: python3-cryptography >= 1.6
BuildRequires: python3-dateutil
BuildRequires: python3-dbus
BuildRequires: python3-dns >= 1.15
BuildRequires: python3-docker
Expand Down Expand Up @@ -975,7 +974,6 @@ Requires: keyutils
Requires: python3-argcomplete
Requires: python3-cffi
Requires: python3-cryptography >= 1.6
Requires: python3-dateutil
Requires: python3-dbus
Requires: python3-dns >= 1.15
Requires: python3-gssapi >= 1.2.0
Expand Down Expand Up @@ -1394,6 +1392,8 @@ fi
%systemd_post ipa-epn.timer

%post client
%tmpfiles_create ipaclient.conf

if [ $1 -gt 1 ] ; then
# Has the client been configured?
restore=0
Expand Down Expand Up @@ -1926,13 +1926,12 @@ fi
%ghost %attr(644,root,root) %config(noreplace) %{_sysconfdir}/ipa/nssdb/pkcs11.txt
%ghost %attr(600,root,root) %config(noreplace) %{_sysconfdir}/ipa/nssdb/pwdfile.txt
%ghost %attr(644,root,root) %config(noreplace) %{_sysconfdir}/pki/ca-trust/source/ipa.p11-kit
%dir %{_localstatedir}/lib/ipa-client
%dir %{_localstatedir}/lib/ipa-client/pki
%dir %{_localstatedir}/lib/ipa-client/sysrestore
%{_mandir}/man5/default.conf.5*
%dir %{_usr}/share/ipa/client
%{_usr}/share/ipa/client/*.template

# NOTE: systemd specific section
%{_tmpfilesdir}/ipaclient.conf
# END

%files python-compat
%doc README.md Contributors.txt
Expand Down
9 changes: 7 additions & 2 deletions init/tmpfilesd/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
dist_noinst_DATA = \
ipa.conf.in \
ipaclient.conf.in \
ipa-dnssec.conf.in

systemdtmpfiles_DATA = \
ipa.conf
ipa.conf \
ipaclient.conf

appdir = $(IPA_DATA_DIR)
dist_app_DATA = \
Expand All @@ -13,5 +15,8 @@ CLEANFILES = $(systemdtmpfiles_DATA) $(app_DATA)

%: %.in Makefile
sed \
-e 's|@HTTPD_GROUP[@]|$(HTTPD_GROUP)|g;s|@ODS_USER[@]|$(ODS_USER)|g;s|@NAMED_GROUP[@]|$(NAMED_GROUP)|g' \
-e 's|@HTTPD_GROUP[@]|$(HTTPD_GROUP)|g' \
-e 's|@ODS_USER[@]|$(ODS_USER)|g' \
-e 's|@NAMED_GROUP[@]|$(NAMED_GROUP)|g' \
-e 's|@localstatedir[@]|$(localstatedir)|g' \
'$(srcdir)/$@.in' >$@
3 changes: 3 additions & 0 deletions init/tmpfilesd/ipaclient.conf.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
d @localstatedir@/lib/ipa-client 0755 root root
d @localstatedir@/lib/ipa-client/pki 0755 root root
d @localstatedir@/lib/ipa-client/sysrestore 0755 root root
3 changes: 3 additions & 0 deletions ipaplatform/fedora/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

from ipaplatform.redhat.paths import RedHatPathNamespace
from ipaplatform.fedora.constants import HAS_NFS_CONF
from ipaplatform.osinfo import osinfo


class FedoraPathNamespace(RedHatPathNamespace):
Expand All @@ -36,6 +37,8 @@ class FedoraPathNamespace(RedHatPathNamespace):
NAMED_CRYPTO_POLICY_FILE = "/etc/crypto-policies/back-ends/bind.config"
if HAS_NFS_CONF:
SYSCONFIG_NFS = '/etc/nfs.conf'
if osinfo.version_number >= (45,):
BIN_TOMCAT = "/usr/share/tomcat/bin/version.sh"


paths = FedoraPathNamespace()
3 changes: 3 additions & 0 deletions ipaplatform/rhel/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@

from ipaplatform.redhat.paths import RedHatPathNamespace
from ipaplatform.rhel.constants import HAS_NFS_CONF
from ipaplatform.osinfo import osinfo


class RHELPathNamespace(RedHatPathNamespace):
NAMED_CRYPTO_POLICY_FILE = "/etc/crypto-policies/back-ends/bind.config"
if HAS_NFS_CONF:
SYSCONFIG_NFS = '/etc/nfs.conf'
if osinfo.version_number >= (11,0):
BIN_TOMCAT = "/usr/share/tomcat/bin/version.sh"


paths = RHELPathNamespace()
5 changes: 1 addition & 4 deletions ipaserver/dnssec/_ods21.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
#

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
Expand Down Expand Up @@ -41,10 +39,9 @@ def get_keys_for_zone(self, zone_id):
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(
units=1).astimezone().replace(tzinfo=None).isoformat(
sep=' ', timespec='seconds')
key['algorithm'] = row['algorithm']
key['publish'] = key['generate']
Expand Down
31 changes: 19 additions & 12 deletions ipaserver/install/cainstance.py
Original file line number Diff line number Diff line change
Expand Up @@ -952,20 +952,27 @@ def __request_ra_certificate(self):
tmpdb.import_pkcs12(
paths.DOGTAG_ADMIN_P12, pkcs12_passwd=self.dm_password)

(_keytype, keysize) = api.env.key_type_size.split(':', 1)
(keytype, keysize) = api.env.key_type_size.split(':', 1)

if keytype == "mldsa":
# convert to the format NSS expects
keysize = f"ML-DSA-{keysize}"

csrfile = os.path.join(tmpdb.secdir, "csr")
ipautil.run(
[paths.CERTUTIL,
"-d", tmpdb.secdir,
"-R", "-s", str(DN(('CN', 'IPA RA'), self.subject_base)),
# eventually use -q curve-name for ECC
"-g", keysize,
"-z", os.path.join(tmpdb.secdir, tmpdb.noise_fname),
"-f", tmpdb.passwd_fname,
"-o", csrfile,
"-a",]
)
cmd = [
paths.CERTUTIL,
"-d", tmpdb.secdir,
"-R", "-s", str(DN(('CN', 'IPA RA'), self.subject_base)),
"-k", keytype,
"-z", os.path.join(tmpdb.secdir, tmpdb.noise_fname),
"-f", tmpdb.passwd_fname,
"-o", csrfile,
"-a",]
if keytype.lower() == 'rsa':
cmd.extend(["-g", keysize])
else:
cmd.extend(["-q", keysize])
ipautil.run(cmd)

tmpdb.pki_issue_ra_certificate(
csrfile=csrfile,
Expand Down
76 changes: 60 additions & 16 deletions ipaserver/install/certs.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
from ipapython.certdb import get_ca_nickname, find_cert_from_txt, NSSDatabase
from ipapython.dn import DN
from ipapython.ipautil import log_level_override
from ipalib import x509, api, constants
from ipalib import x509, api
from ipalib.errors import CertificateOperationError
from ipalib.install import certstore
from ipalib.util import strip_csr_header
Expand Down Expand Up @@ -147,6 +147,42 @@ def is_ipa_issued_cert(api, cert):
return DN(cert.issuer) == cacert_subject


def get_ra_agent_profile(api):
"""This is suitable during installation. I doubt at runtime.

FIXME: This will need a conditional on whether
api.env.key_type_size available or not. If not then
retrieve the value from LDAP.

The caller is expected to handle None.
"""
(keytype, _keysize) = api.env.key_type_size.split(':', 1)
if keytype == "rsa":
return "caSubsystemCert"
elif keytype == "mldsa":
return "caMLDSASubsystemCert"
else:
return None


def get_default_profile(api):
"""This is suitable during installation. I doubt at runtime.

FIXME: This will need a conditional on whether
api.env.key_type_size available or not. If not then
retrieve the value from LDAP.

The caller is expected to handle None.
"""
(keytype, _keysize) = api.env.key_type_size.split(':', 1)
if keytype == "rsa":
return "caIPAserviceCert"
elif keytype == "mldsa":
return "caMLDSAServerCert"
else:
return None


class CertDB:
"""An IPA-server-specific wrapper around NSS

Expand Down Expand Up @@ -779,13 +815,13 @@ def pki_issue_ra_certificate(self, csrfile, certfile, dm_password):
ca_client = pki.ca.CAClient(pki_client)
cert_client = pki.cert.CertClient(ca_client)

profile = get_ra_agent_profile(api)
inputs = dict()
inputs['cert_request_type'] = 'pkcs10'
with open(csrfile, 'r') as f:
inputs['cert_request'] = f.read()
with log_level_override():
result = cert_client.enroll_cert(
constants.RA_AGENT_PROFILE, inputs)[0]
result = cert_client.enroll_cert(profile, inputs)[0]

request_data = result.request
if request_data.request_status != pki.cert.CertRequestStatus.COMPLETE:
Expand All @@ -806,8 +842,14 @@ def pki_issue_certificate(self, service, profile, keyfile, certfile,
"""Use openssl to generate a CSR and submit it using the pki
Python API, using the IPA RA certificate.
"""
(keytype, keysize) = api.env.key_type_size.split(':', 1)

# Generate a private key
if service == 'krbtgt':
principal = api.env.realm
# PKINIT doesn't support ML-DSA yet, force RSA.
keytype = "rsa"
keysize = 2048
else:
principal = api.env.host
template = os.path.join(
Expand All @@ -829,21 +871,23 @@ def pki_issue_certificate(self, service, profile, keyfile, certfile,
os.fchmod(f.fileno(), 0o600)
f.write(conf)

(keytype, keysize) = api.env.key_type_size.split(':', 1)

# Generate a private key
if (keytype.lower() == 'rsa'):
args = ["openssl", "genrsa",
"-out", keyfile]
if key_passwd_file:
args.extend(
["-aes256",
"-passout", "file:{}".format(key_passwd_file)]
)
args.extend([keysize]) # must be the last argument
result = ipautil.run(args, capture_output=True)
opts = []
if keytype.lower() == 'rsa':
opts = ["-pkeyopt", "rsa_keygen_bits:{}".format(keysize)]
elif keytype.lower() == 'mldsa':
keytype = "ML-DSA-{}".format(keysize)
else:
raise RuntimeError(f"Key type not supported: {keytype}")
args = ["openssl", "genpkey", "-algorithm", keytype,
"-out", keyfile]
args.extend(opts)

if key_passwd_file:
args.extend(
["-aes256",
"-pass", "file:{}".format(key_passwd_file)]
)
result = ipautil.run(args, capture_output=True)

# Generate a CSR using the private key
args = ["openssl", "req", "-new",
Expand Down
7 changes: 3 additions & 4 deletions ipaserver/install/dsinstance.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
EXTERNAL_CA_TRUST_FLAGS,
TrustFlags)
from ipapython import ipautil, ipaldap
from ipapython import dogtag
from ipaserver.install import service
from ipaserver.install import installutils
from ipaserver.install import certs
Expand Down Expand Up @@ -861,7 +860,7 @@ def __enable_ssl(self):
keyfile = os.path.join(tmpdb.secdir, "key.pem")
certfile = os.path.join(tmpdb.secdir, "cert.pem")
tmpdb.pki_issue_certificate(
"ldap", dogtag.DEFAULT_PROFILE,
"ldap", certs.get_default_profile(api),
keyfile, certfile
)

Expand Down Expand Up @@ -892,7 +891,7 @@ def __enable_ssl(self):
passwd_fname=dsdb.passwd_fname,
subject=str(DN(('CN', self.fqdn), self.subject_base)),
ca='IPA',
profile=dogtag.DEFAULT_PROFILE,
profile=certs.get_default_profile(api),
dns=[self.fqdn],
post_command=cmd,
resubmit_timeout=api.env.certmonger_wait_timeout,
Expand Down Expand Up @@ -1206,7 +1205,7 @@ def start_tracking_certificates(self, serverid):
self.principal,
password_file=dsdb.passwd_fname,
command='restart_dirsrv %s' % serverid,
profile=dogtag.DEFAULT_PROFILE)
profile=certs.get_default_profile(api))
else:
logger.debug("Will not track DS server certificate %s as it is "
"not issued by IPA", nickname)
Expand Down
7 changes: 3 additions & 4 deletions ipaserver/install/httpinstance.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
from ipaserver.install import certs
from ipaserver.install import installutils
from ipapython import directivesetter
from ipapython import dogtag
from ipapython import ipautil
from ipapython.dn import DN
import ipapython.errors
Expand Down Expand Up @@ -345,7 +344,7 @@ def __setup_ssl(self):
tmpdb.create_from_cacert()
dns_2 = f"DNS.2={IPA_CA_RECORD}.{api.env.domain}"
tmpdb.pki_issue_certificate(
"HTTP", dogtag.DEFAULT_PROFILE,
"HTTP", certs.get_default_profile(api),
paths.HTTPD_KEY_FILE, paths.HTTPD_CERT_FILE,
key_passwd_file, dns_2_san=dns_2
)
Expand All @@ -362,7 +361,7 @@ def __setup_ssl(self):
principal=self.principal,
subject=str(DN(('CN', self.fqdn), self.subject_base)),
ca='IPA',
profile=dogtag.DEFAULT_PROFILE,
profile=certs.get_default_profile(api),
dns=[self.fqdn, f'{IPA_CA_RECORD}.{api.env.domain}'],
post_command='restart_httpd',
storage='FILE',
Expand Down Expand Up @@ -567,7 +566,7 @@ def start_tracking_certificates(self):
request_id = certmonger.start_tracking(
certpath=(paths.HTTPD_CERT_FILE, paths.HTTPD_KEY_FILE),
post_command='restart_httpd', storage='FILE',
profile=dogtag.DEFAULT_PROFILE,
profile=certs.get_default_profile(api),
pinfile=key_passwd_file,
dns=[self.fqdn, f'{IPA_CA_RECORD}.{api.env.domain}'],
)
Expand Down
Loading