mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2026-10-24 14:17:41 -05:00
Add config option for RSA key size for HTTP, DS, PKINIT, RA certs
A new command-line option was added, --key-type-size, to define the type of key to generate and the size of the key, or equivalent. Only rsa is supported currently but this can be expanded easily if additional key types are added. Placeholders have been added for ec and ml-dsa key types but they are not yet supported. There is also a config plugin option to modify this value. It does NOT modify any certificates already issued. Changing it will only apply to new replicas added. Related: https://pagure.io/freeipa/issue/9738 Also add a test to verify installation key sizes. Signed-off-by: Rob Crittenden <rcritten@redhat.com> Reviewed-By: Fraser Tweedale <ftweedal@redhat.com> Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com> Reviewed-By: Rafael Guterres Jeffman <rjeffman@redhat.com> Reviewed-By: Thomas Woerner <twoerner@redhat.com>
This commit is contained in:
1 parent
cdc8054453
commit
5d55b4efb2
23 files changed
+218
-20
No files matched your search
@@ -61,7 +61,7 @@ aci: (targetattr = "cn || description || ipacertprofilestoreissued")(targetfilte
|
||||
dn: cn=certprofiles,cn=ca,dc=ipa,dc=example
|
||||
aci: (targetattr = "cn || createtimestamp || description || entryusn || ipacertprofilestoreissued || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipacertprofile)")(version 3.0;acl "permission:System: Read Certificate Profiles";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=ipaconfig,cn=etc,dc=ipa,dc=example
|
||||
aci: (targetattr = "cn || createtimestamp || entryusn || ipacertificatesubjectbase || ipaconfigstring || ipacustomfields || ipadefaultemaildomain || ipadefaultloginshell || ipadefaultprimarygroup || ipadomainresolutionorder || ipagroupobjectclasses || ipagroupsearchfields || ipahomesrootdir || ipakrbauthzdata || ipamaxhostnamelength || ipamaxusernamelength || ipamigrationenabled || ipapwdexpadvnotify || ipasearchrecordslimit || ipasearchtimelimit || ipaselinuxusermapdefault || ipaselinuxusermaporder || ipauserauthtype || ipauserdefaultsubordinateid || ipauserobjectclasses || ipausersearchfields || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipaguiconfig)")(version 3.0;acl "permission:System: Read Global Configuration";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
aci: (targetattr = "cn || createtimestamp || entryusn || ipacertificatesubjectbase || ipaconfigstring || ipacustomfields || ipadefaultemaildomain || ipadefaultloginshell || ipadefaultprimarygroup || ipadomainresolutionorder || ipagroupobjectclasses || ipagroupsearchfields || ipahomesrootdir || ipakrbauthzdata || ipamaxhostnamelength || ipamaxusernamelength || ipamigrationenabled || ipapwdexpadvnotify || ipasearchrecordslimit || ipasearchtimelimit || ipaselinuxusermapdefault || ipaselinuxusermaporder || ipaservicekeytypesize || ipauserauthtype || ipauserdefaultsubordinateid || ipauserobjectclasses || ipausersearchfields || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipaguiconfig)")(version 3.0;acl "permission:System: Read Global Configuration";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=costemplates,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetfilter = "(objectclass=costemplate)")(version 3.0;acl "permission:System: Add Group Password Policy costemplate";allow (add) groupdn = "ldap:///cn=System: Add Group Password Policy costemplate,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=costemplates,cn=accounts,dc=ipa,dc=example
|
||||
|
||||
@@ -1076,7 +1076,7 @@ args: 0,1,1
|
||||
option: Str('version?')
|
||||
output: Output('result')
|
||||
command: config_mod/1
|
||||
args: 0,32,3
|
||||
args: 0,33,3
|
||||
option: Flag('add_sids?', autofill=True, default=False)
|
||||
option: Str('addattr*', cli_name='addattr')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
@@ -1100,6 +1100,7 @@ option: Int('ipasearchrecordslimit?', autofill=False, cli_name='searchrecordslim
|
||||
option: Int('ipasearchtimelimit?', autofill=False, cli_name='searchtimelimit')
|
||||
option: Str('ipaselinuxusermapdefault?', autofill=False)
|
||||
option: Str('ipaselinuxusermaporder?', autofill=False)
|
||||
option: Str('ipaservicekeytypesize?', autofill=False, cli_name='key_type_size')
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey', u'disabled'])
|
||||
option: Bool('ipauserdefaultsubordinateid?', autofill=False, cli_name='user_default_subid')
|
||||
option: Str('ipauserobjectclasses*', autofill=False, cli_name='userobjectclasses')
|
||||
|
||||
+2
-2
@@ -86,8 +86,8 @@ define(IPA_DATA_VERSION, 20100614120000)
|
||||
# #
|
||||
########################################################
|
||||
define(IPA_API_VERSION_MAJOR, 2)
|
||||
# Last change: add sysaccounts
|
||||
define(IPA_API_VERSION_MINOR, 256)
|
||||
# Last change: add key_type_size option to config
|
||||
define(IPA_API_VERSION_MINOR, 257)
|
||||
|
||||
########################################################
|
||||
# Following values are auto-generated from values above
|
||||
|
||||
@@ -220,6 +220,9 @@ Specifies the URI of the JSON server for a client. This is used by IPA. If not g
|
||||
.B rpc_protocol <URI>
|
||||
Specifies the type of RPC calls IPA makes: 'jsonrpc' or 'xmlrpc'. Defaults to 'jsonrpc'.
|
||||
.TP
|
||||
.B key_type_size TYPE:SIZE
|
||||
Specifies the type and size of private keys for the Apache, LDAP, PKINIT and RA (if configuring the CA) certificates. The CA/KRA certificate sizes need to be specified using a pki-config-override file provided to the installer. Currently only supports the RSA key type. Valid type values are: rsa. This only applies during initial server installation. The value is stored in the IPA config. Changing it there will not change existing certificates. It will only apply when a new replica is added. The default is: rsa:2048.
|
||||
.TP
|
||||
The following define the containers for the IPA server. Containers define where in the DIT that objects can be found. The full location is the value of container + basedn.
|
||||
container_accounts: cn=accounts
|
||||
container_applications: cn=applications,cn=configs,cn=policies
|
||||
|
||||
@@ -42,6 +42,7 @@ No arguments.
|
||||
* add_sids : :ref:`Flag<Flag>`
|
||||
* Default: False
|
||||
* netbios_name : :ref:`Str<Str>`
|
||||
* ipaservicekeytypesize : :ref:`Str<Str>`
|
||||
* setattr : :ref:`Str<Str>`
|
||||
* addattr : :ref:`Str<Str>`
|
||||
* delattr : :ref:`Str<Str>`
|
||||
|
||||
@@ -48,11 +48,12 @@ attributeTypes: ( 2.16.840.1.113730.3.8.3.27 NAME 'ipaSELinuxUserMapOrder' DESC
|
||||
attributeTypes: ( 2.16.840.1.113730.3.8.1.28 NAME 'ipaMaxHostnameLength' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE)
|
||||
# ipaUserDefaultSubordinateId - if TRUE new user entries gain subordinate id by default
|
||||
attributeTypes: ( 2.16.840.1.113730.3.8.23.14 NAME 'ipaUserDefaultSubordinateId' DESC 'Enable adding user entries with subordinate id' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'IPA v4.9')
|
||||
attributeTypes: ( 2.16.840.1.113730.3.8.1.14 NAME 'ipaServiceKeyTypeSize' DESC 'Key type and size for IPA certs' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'IPA v4.12')
|
||||
###############################################
|
||||
##
|
||||
## ObjectClasses
|
||||
##
|
||||
## ipaGuiConfig - GUI config parameters objectclass
|
||||
objectClasses: ( 2.16.840.1.113730.3.8.2.1 NAME 'ipaGuiConfig' AUXILIARY MAY ( ipaUserSearchFields $ ipaGroupSearchFields $ ipaSearchTimeLimit $ ipaSearchRecordsLimit $ ipaCustomFields $ ipaHomesRootDir $ ipaDefaultLoginShell $ ipaDefaultPrimaryGroup $ ipaMaxUsernameLength $ ipaPwdExpAdvNotify $ ipaUserObjectClasses $ ipaGroupObjectClasses $ ipaDefaultEmailDomain $ ipaMigrationEnabled $ ipaCertificateSubjectBase $ ipaSELinuxUserMapDefault $ ipaSELinuxUserMapOrder $ ipaKrbAuthzData $ ipaMaxHostnameLength $ ipaUserDefaultSubordinateId) )
|
||||
objectClasses: ( 2.16.840.1.113730.3.8.2.1 NAME 'ipaGuiConfig' AUXILIARY MAY ( ipaUserSearchFields $ ipaGroupSearchFields $ ipaSearchTimeLimit $ ipaSearchRecordsLimit $ ipaCustomFields $ ipaHomesRootDir $ ipaDefaultLoginShell $ ipaDefaultPrimaryGroup $ ipaMaxUsernameLength $ ipaPwdExpAdvNotify $ ipaUserObjectClasses $ ipaGroupObjectClasses $ ipaDefaultEmailDomain $ ipaMigrationEnabled $ ipaCertificateSubjectBase $ ipaSELinuxUserMapDefault $ ipaSELinuxUserMapOrder $ ipaKrbAuthzData $ ipaMaxHostnameLength $ ipaUserDefaultSubordinateId $ ipaServiceKeyTypeSize) )
|
||||
## ipaConfigObject - Generic config strings object holder
|
||||
objectClasses: (2.16.840.1.113730.3.8.4.13 NAME 'ipaConfigObject' DESC 'generic config object for IPA' AUXILIARY MAY ( ipaConfigString ) X-ORIGIN 'IPA v2' )
|
||||
@@ -415,6 +415,7 @@ ipaDefaultPrimaryGroup: ipausers
|
||||
ipaMaxUsernameLength: 32
|
||||
ipaMaxHostnameLength: 64
|
||||
ipaPwdExpAdvNotify: 4
|
||||
ipaServiceKeyTypeSize: $DEFAULT_KEY_TYPE_SIZE
|
||||
ipaGroupObjectClasses: top
|
||||
ipaGroupObjectClasses: groupofnames
|
||||
ipaGroupObjectClasses: nestedgroup
|
||||
|
||||
@@ -172,6 +172,9 @@ The subject base for certificates issued by IPA (default O=REALM.NAME). RDNs are
|
||||
.TP
|
||||
\fB\-\-ca\-signing\-algorithm\fR=\fIALGORITHM\fR
|
||||
Signing algorithm of the IPA CA certificate. Possible values are SHA1withRSA, SHA256withRSA, SHA384withRSA, SHA512withRSA. Default value is SHA256withRSA. Use this option with --external-ca if the external CA does not support the default signing algorithm.
|
||||
.TP
|
||||
\fB\-\-key\-type\-size\fR=\fITYPE:SIZE\fR
|
||||
Specifies the key type and size for the HTTP, LDAP, PKINIT and RA certificates (if configured with a CA). The format is type:size where type is the type of key and size is the number represents the number of bits. Currently type only supports RSA keys. The sizes will depend on what the crypto engines and CA profiles support. Typical RSA sizes are 2048, 3072, 4096, 7168 and 8192. The default is rsa:2048.
|
||||
|
||||
.SS "HSM OPTIONS"
|
||||
.TP
|
||||
|
||||
@@ -8,3 +8,4 @@ remove:ipaConfigString:AllowLMhash
|
||||
add:objectClass: ipaUserAuthTypeClass
|
||||
add:objectClass: ipaNameResolutionData
|
||||
addifnew:ipamaxhostnamelength: 64
|
||||
addifnew:ipaservicekeytypesize: rsa:2048
|
||||
@@ -63,6 +63,8 @@ TLS_VERSION_MAXIMAL = "tls1.3"
|
||||
TLS_VERSION_DEFAULT_MIN = None
|
||||
TLS_VERSION_DEFAULT_MAX = None
|
||||
|
||||
DEFAULT_KEY_TYPE_SIZE = "rsa:2048"
|
||||
|
||||
SD_IPA_API_MESSAGE_ID = uuid.uuid3(uuid.NAMESPACE_DNS, 'IPA.API')
|
||||
|
||||
# regular expression NameSpace member names must match:
|
||||
@@ -251,6 +253,9 @@ DEFAULT_CONFIG = (
|
||||
# Ignore TTL. Perform schema call and download schema if not in cache.
|
||||
('force_schema_check', False),
|
||||
|
||||
# Default key type and size for IPA certs (HTTP, DS, KDC and RA)
|
||||
('key_type_size', DEFAULT_KEY_TYPE_SIZE),
|
||||
|
||||
# ********************************************************
|
||||
# The remaining keys are never set from the values here!
|
||||
# ********************************************************
|
||||
|
||||
@@ -352,7 +352,7 @@ def request_and_wait_for_cert(
|
||||
dns=None, ca='IPA', profile=None,
|
||||
pre_command=None, post_command=None, storage='NSSDB', perms=None,
|
||||
resubmit_timeout=0, stop_tracking_on_error=False,
|
||||
nss_user=None):
|
||||
nss_user=None, keytype=None, keysize=None):
|
||||
"""Request certificate, wait and possibly resubmit failing requests
|
||||
|
||||
Submit a cert request to certmonger and wait until the request has
|
||||
@@ -367,7 +367,8 @@ def request_and_wait_for_cert(
|
||||
"""
|
||||
req_id = request_cert(
|
||||
certpath, subject, principal, nickname, passwd_fname, dns, ca,
|
||||
profile, pre_command, post_command, storage, perms, nss_user
|
||||
profile, pre_command, post_command, storage, perms, nss_user,
|
||||
keytype, keysize,
|
||||
)
|
||||
# Don't wait longer than resubmit timeout if it is configured
|
||||
certmonger_timeout = api.env.certmonger_wait_timeout
|
||||
@@ -421,7 +422,7 @@ def request_cert(
|
||||
certpath, subject, principal, nickname=None, passwd_fname=None,
|
||||
dns=None, ca='IPA', profile=None,
|
||||
pre_command=None, post_command=None, storage='NSSDB', perms=None,
|
||||
nss_user=None):
|
||||
nss_user=None, keytype=None, keysize=None):
|
||||
"""
|
||||
Execute certmonger to request a server certificate.
|
||||
|
||||
@@ -462,6 +463,12 @@ def request_cert(
|
||||
request_parameters['ca-profile'] = profile
|
||||
if nss_user:
|
||||
request_parameters['nss-user'] = nss_user
|
||||
if keysize is None:
|
||||
keysize = 2048
|
||||
if keytype is None:
|
||||
keytype = "rsa"
|
||||
request_parameters['key-type'] = keytype
|
||||
request_parameters['key-size'] = int(keysize)
|
||||
|
||||
certmonger_cmd_template = paths.CERTMONGER_COMMAND_TEMPLATE
|
||||
if pre_command:
|
||||
@@ -494,7 +501,7 @@ def request_cert(
|
||||
def start_tracking(
|
||||
certpath, ca='IPA', nickname=None, pin=None, pinfile=None,
|
||||
pre_command=None, post_command=None, profile=None, storage="NSSDB",
|
||||
token_name=None, dns=None, nss_user=None):
|
||||
token_name=None, dns=None, nss_user=None, perms=None):
|
||||
"""
|
||||
Tell certmonger to track the given certificate in either a file or an NSS
|
||||
database. The certificate access can be protected by a password_file.
|
||||
@@ -533,6 +540,8 @@ def start_tracking(
|
||||
List of DNS names
|
||||
:param nss_user:
|
||||
login of the private key owner
|
||||
:params perms:
|
||||
A tuple of (cert, key) permissions in e.g., (0644,0660)
|
||||
:returns: certificate tracking nickname.
|
||||
"""
|
||||
if storage == 'FILE':
|
||||
@@ -581,6 +590,12 @@ def start_tracking(
|
||||
params['DNS'] = dns
|
||||
if nss_user:
|
||||
params['nss-user'] = nss_user
|
||||
if perms:
|
||||
(cert, key) = perms
|
||||
if cert:
|
||||
params['cert-perms'] = cert
|
||||
if cert:
|
||||
params['key-perms'] = key
|
||||
|
||||
logger.debug("start tracking %s", params)
|
||||
result = cm.obj_if.add_request(params,
|
||||
|
||||
@@ -961,11 +961,14 @@ class CAInstance(DogtagInstance):
|
||||
tmpdb.import_pkcs12(
|
||||
paths.DOGTAG_ADMIN_P12, pkcs12_passwd=self.dm_password)
|
||||
|
||||
(_keytype, keysize) = api.env.key_type_size.split(':', 1)
|
||||
|
||||
ipautil.run(
|
||||
[paths.CERTUTIL,
|
||||
"-d", tmpdb.secdir,
|
||||
"-R", "-s", str(DN(('CN', 'IPA RA'), self.subject_base)),
|
||||
"-g", "2048",
|
||||
# eventually use -q curve-name for ECC
|
||||
"-g", keysize,
|
||||
"-z", os.path.join(tmpdb.secdir, tmpdb.noise_fname),
|
||||
"-f", tmpdb.passwd_fname,
|
||||
"-o", os.path.join(tmpdb.secdir, "csr"),
|
||||
|
||||
@@ -728,8 +728,9 @@ class CertDB:
|
||||
self.nssdb.convert_db()
|
||||
|
||||
def pki_issue_certificate(self, service, profile, subject,
|
||||
keyfile, certfile, key_passwd_file=None,
|
||||
dns_2_san='', use_admin=False):
|
||||
keyfile, certfile,
|
||||
key_passwd_file=None, dns_2_san='',
|
||||
use_admin=False):
|
||||
"""Use openssl to generate a CSR and submit it using the pki
|
||||
cli tool.
|
||||
|
||||
@@ -794,14 +795,29 @@ class CertDB:
|
||||
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)
|
||||
|
||||
# Generate a CSR using the private key
|
||||
args = ["openssl", "req", "-new",
|
||||
"-key", keyfile,
|
||||
"-out", os.path.join(self.secdir, "csr"),
|
||||
"-keyout", keyfile,
|
||||
"-config", destfile]
|
||||
if key_passwd_file:
|
||||
args.extend(["-passout", "file:{}".format(key_passwd_file)])
|
||||
else:
|
||||
args.extend(["-nodes"])
|
||||
args.extend(
|
||||
["-passin", "file:{}".format(key_passwd_file)]
|
||||
)
|
||||
result = ipautil.run(args, capture_output=True)
|
||||
nickname = 'IPA RA'
|
||||
|
||||
|
||||
@@ -883,6 +883,7 @@ class DsInstance(service.Service):
|
||||
os.path.join(tmpdb.secdir, 'server.p12'), key_password
|
||||
)
|
||||
else:
|
||||
(keytype, keysize) = installutils.lookup_key_type(api)
|
||||
cmd = 'restart_dirsrv %s' % self.serverid
|
||||
certmonger.request_and_wait_for_cert(
|
||||
certpath=dirname,
|
||||
@@ -895,7 +896,9 @@ class DsInstance(service.Service):
|
||||
profile=dogtag.DEFAULT_PROFILE,
|
||||
dns=[self.fqdn],
|
||||
post_command=cmd,
|
||||
resubmit_timeout=api.env.certmonger_wait_timeout
|
||||
resubmit_timeout=api.env.certmonger_wait_timeout,
|
||||
keytype=keytype,
|
||||
keysize=keysize,
|
||||
)
|
||||
|
||||
api.Backend.ldap2.disconnect()
|
||||
|
||||
@@ -357,6 +357,7 @@ class HTTPInstance(service.Service):
|
||||
# have codepaths to support the ipa-ca.$DOMAIN dnsName in HTTP
|
||||
# cert. Therefore if request fails, try again without the
|
||||
# ipa-ca.$DOMAIN dnsName.
|
||||
(keytype, keysize) = installutils.lookup_key_type(api)
|
||||
args = dict(
|
||||
certpath=(paths.HTTPD_CERT_FILE, paths.HTTPD_KEY_FILE),
|
||||
principal=self.principal,
|
||||
@@ -369,6 +370,8 @@ class HTTPInstance(service.Service):
|
||||
passwd_fname=key_passwd_file,
|
||||
resubmit_timeout=api.env.certmonger_wait_timeout,
|
||||
stop_tracking_on_error=True,
|
||||
keytype=keytype,
|
||||
keysize=keysize,
|
||||
)
|
||||
try:
|
||||
certmonger.request_and_wait_for_cert(**args)
|
||||
|
||||
@@ -43,7 +43,7 @@ from dns import rrset, rdatatype, rdataclass
|
||||
from dns.exception import DNSException
|
||||
import ldap
|
||||
|
||||
from ipalib import facts
|
||||
from ipalib import facts, _
|
||||
from ipalib.install.kinit import kinit_password
|
||||
import ipaplatform
|
||||
from ipapython import ipautil, admintool, version, ipaldap
|
||||
@@ -1591,3 +1591,68 @@ def get_replication_plugin_name(dirsrv_get_entry):
|
||||
'LDAP query returned unknown type for cn %s: %s' %
|
||||
(cn, type(cn))
|
||||
)
|
||||
|
||||
|
||||
def validate_key_type_size(value):
|
||||
"""Do some basic validation of key type and size.
|
||||
|
||||
Returns None on success and an error string on failure.
|
||||
"""
|
||||
types = {
|
||||
'rsa': (2048, 3072, 4096, 7168, 8192),
|
||||
'ec': tuple(),
|
||||
'ml-dsa': tuple(),
|
||||
}
|
||||
if len(value.split(':', 1)) != 2:
|
||||
return _('Must be of the form type:size')
|
||||
(type, size) = value.split(':', 1)
|
||||
type = type.strip()
|
||||
size = size.strip()
|
||||
|
||||
if type not in types:
|
||||
if len(types) == 1:
|
||||
return _('Key type must be "%(type)s"') % {
|
||||
'type': next(iter(types))
|
||||
}
|
||||
else:
|
||||
return _("Key type must be one of: %(types)s") % {
|
||||
"types": ", ".join(types)
|
||||
}
|
||||
|
||||
if type == 'rsa':
|
||||
try:
|
||||
size = int(size)
|
||||
except ValueError:
|
||||
return _('Not an integer: %(size)s') % {'size': size}
|
||||
else:
|
||||
return _('%(type)s keys are not supported yet') % {'type': type}
|
||||
|
||||
if size not in types.get(type):
|
||||
return _('Invalid size {}. Allowed {}').format(size, types.get(type))
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def lookup_key_type(api):
|
||||
"""
|
||||
Retrieve the key type and size configuration.
|
||||
|
||||
This can be used when installing a new replica to set the key
|
||||
type and sizing.
|
||||
|
||||
Returns a tuple of (type, size) or (None, None)
|
||||
"""
|
||||
try:
|
||||
ret = api.Command['config_show']()
|
||||
except errors.PublicError as e:
|
||||
logger.error('Cannot retrieve key type/size %s', e)
|
||||
|
||||
keytype = None
|
||||
keysize = None
|
||||
|
||||
if ret:
|
||||
type_size = ret['result'].get('ipaservicekeytypesize')
|
||||
if type_size:
|
||||
(keytype, keysize) = type_size[0].split(':', 1)
|
||||
|
||||
return (keytype, keysize)
|
||||
@@ -499,6 +499,7 @@ class KrbInstance(service.Service):
|
||||
certmonger_ca, helper
|
||||
)
|
||||
|
||||
(keytype, keysize) = installutils.lookup_key_type(api)
|
||||
certmonger.request_and_wait_for_cert(
|
||||
certpath=certpath,
|
||||
subject=subject,
|
||||
@@ -509,7 +510,9 @@ class KrbInstance(service.Service):
|
||||
profile=KDC_PROFILE,
|
||||
post_command='renew_kdc_cert',
|
||||
perms=(0o644, 0o600),
|
||||
resubmit_timeout=api.env.certmonger_wait_timeout
|
||||
resubmit_timeout=api.env.certmonger_wait_timeout,
|
||||
keytype=keytype,
|
||||
keysize=keysize,
|
||||
)
|
||||
except dbus.DBusException as e:
|
||||
# if the certificate is already tracked, ignore the error
|
||||
|
||||
@@ -125,6 +125,7 @@ def get_sub_dict(realm, domain, suffix, fqdn, idstart=None, idmax=None):
|
||||
SELINUX_USERMAP_ORDER=platformconstants.SELINUX_USERMAP_ORDER,
|
||||
NAMED_UID=named_uid,
|
||||
NAMED_GID=named_gid,
|
||||
DEFAULT_KEY_TYPE_SIZE=api.env.key_type_size,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ from ipapython.install.core import group, knob, extend_knob
|
||||
from ipapython.install.common import step
|
||||
from ipaplatform import services
|
||||
|
||||
from ipaserver.install.installutils import validate_key_type_size
|
||||
from .install import validate_admin_password, validate_dm_password
|
||||
from .install import get_min_idstart
|
||||
from .install import init as master_init
|
||||
@@ -138,6 +139,20 @@ class ServerCertificateInstallInterface(service.ServiceInstallInterface):
|
||||
)
|
||||
pkinit_cert_name = prepare_only(pkinit_cert_name)
|
||||
|
||||
key_type_size = knob(
|
||||
str, None,
|
||||
description=("The key type and size for HTTP, LDAP, PKINIT and "
|
||||
"RA (if CA configured) certificates (default: "
|
||||
"rsa:2048)"),
|
||||
)
|
||||
key_type_size = master_install_only(key_type_size)
|
||||
|
||||
@key_type_size.validator
|
||||
def key_type_size(self, value):
|
||||
msg = validate_key_type_size(value)
|
||||
if msg:
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
@group
|
||||
class ServerHSMInstallInterface(service.ServiceInstallInterface):
|
||||
|
||||
@@ -681,6 +681,8 @@ def install_check(installer):
|
||||
# make sure host name specified by user is used instead of default
|
||||
host=host_name,
|
||||
)
|
||||
if options.key_type_size:
|
||||
cfg['key_type_size'] = options.key_type_size
|
||||
if setup_ca:
|
||||
# we have an IPA-integrated CA
|
||||
cfg['ca_host'] = host_name
|
||||
|
||||
@@ -39,6 +39,7 @@ from ipapython.dn import DN
|
||||
from ipapython.ipavalidate import Email
|
||||
from ipaserver.plugins.privilege import principal_has_privilege
|
||||
from ipaserver.install.adtrust import set_and_check_netbios_name
|
||||
from ipaserver.install.installutils import validate_key_type_size
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -128,6 +129,12 @@ def validate_emaildomain(ugettext, value):
|
||||
return _('Invalid e-mail domain')
|
||||
return None
|
||||
|
||||
|
||||
def validate_key_type_size_wrapper(ugettext, value):
|
||||
"""Do some basic validation of key type and size.
|
||||
"""
|
||||
return validate_key_type_size(value)
|
||||
|
||||
@register()
|
||||
class config(LDAPObject):
|
||||
"""
|
||||
@@ -142,7 +149,7 @@ class config(LDAPObject):
|
||||
'ipapwdexpadvnotify', 'ipaselinuxusermaporder',
|
||||
'ipaselinuxusermapdefault', 'ipaconfigstring', 'ipakrbauthzdata',
|
||||
'ipauserauthtype', 'ipadomainresolutionorder', 'ipamaxhostnamelength',
|
||||
'ipauserdefaultsubordinateid',
|
||||
'ipauserdefaultsubordinateid', 'ipaservicekeytypesize',
|
||||
]
|
||||
container_dn = DN(('cn', 'ipaconfig'), ('cn', 'etc'))
|
||||
permission_filter_objectclasses = ['ipaguiconfig']
|
||||
@@ -165,6 +172,7 @@ class config(LDAPObject):
|
||||
'ipauserauthtype', 'ipauserobjectclasses',
|
||||
'ipausersearchfields', 'ipacustomfields',
|
||||
'ipamaxhostnamelength', 'ipauserdefaultsubordinateid',
|
||||
'ipaservicekeytypesize',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -387,6 +395,13 @@ class config(LDAPObject):
|
||||
doc=_('The HSM token name storing the CA private keys'),
|
||||
flags={'virtual_attribute', 'no_create', 'no_update'}
|
||||
),
|
||||
Str(
|
||||
'ipaservicekeytypesize?',
|
||||
validate_key_type_size_wrapper,
|
||||
cli_name='key_type_size',
|
||||
label=_('IPA Service key type:size'),
|
||||
doc=_('IPA Service key type:size'),
|
||||
),
|
||||
)
|
||||
|
||||
def get_dn(self, *keys, **kwargs):
|
||||
|
||||
@@ -25,6 +25,7 @@ from ipalib.constants import IPA_CA_RECORD
|
||||
from ipalib.constants import ALLOWED_NETBIOS_CHARS
|
||||
from ipalib.sysrestore import SYSRESTORE_STATEFILE, SYSRESTORE_INDEXFILE
|
||||
from ipapython.dn import DN
|
||||
from ipapython.ipaldap import realm_to_serverid
|
||||
from ipaplatform.constants import constants
|
||||
from ipaplatform.osinfo import osinfo
|
||||
from ipaplatform.paths import paths
|
||||
@@ -2226,3 +2227,42 @@ class TestNsslapdIgnoreTimeSkew(IntegrationTest):
|
||||
conn = self.replicas[0].ldap_connect()
|
||||
ldap_entry = conn.get_entry(DN("cn=config"))
|
||||
assert ldap_entry.single_value['nsslapd-ignore-time-skew'] == "on"
|
||||
|
||||
|
||||
class TestInstallKeySizes(IntegrationTest):
|
||||
|
||||
num_replicas = 1
|
||||
master_with_dns = True
|
||||
|
||||
@classmethod
|
||||
def install(cls, mh):
|
||||
extra_args = ["--key-type-size", "rsa:3072",]
|
||||
tasks.install_master(cls.master, setup_dns=True,
|
||||
extra_args=extra_args)
|
||||
tasks.install_replica(
|
||||
cls.master, cls.replicas[0], setup_ca=False)
|
||||
|
||||
def check_key_sizes(self, host):
|
||||
serverid = (realm_to_serverid(host.domain.realm)).upper()
|
||||
instance = paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % serverid
|
||||
result = host.run_command(
|
||||
"certutil -L -d %s -n Server-Cert -a | "
|
||||
"openssl x509 -text -noout | "
|
||||
"grep Public-Key" % instance)
|
||||
assert "3072 bit" in result.stdout_text
|
||||
|
||||
for file in (
|
||||
paths.HTTPD_CERT_FILE,
|
||||
paths.KDC_CERT,
|
||||
paths.RA_AGENT_PEM,
|
||||
):
|
||||
result = host.run_command(
|
||||
"openssl x509 -text -noout -in %s | "
|
||||
"grep Public-Key" % file)
|
||||
assert "3072 bit" in result.stdout_text
|
||||
|
||||
def test_master_key_sizes(self):
|
||||
self.check_key_sizes(self.master)
|
||||
|
||||
def test_replica_key_sizes(self):
|
||||
self.check_key_sizes(self.replicas[0])
|
||||
@@ -475,6 +475,7 @@ AstroidBuilder(MANAGER).string_build(textwrap.dedent(
|
||||
api.env.in_tree = False # object
|
||||
api.env.interactive = True
|
||||
api.env.ipalib = '' # object
|
||||
api.env.key_type_size = 'rsa:2048'
|
||||
api.env.kinit_lifetime = None
|
||||
api.env.log = '' # object
|
||||
api.env.logdir = '' # object
|
||||
|
||||
Reference in new issue
Block a user