Within an organization using Free IPA there may be a need to create a subordinate CA. A subordinate CA can issue certificates on behalf of the Root CA in the organization so it should be treated with the same security as an organization’s Root CA. The main advantage is Subordinate CA can be revoked if it goes rogue and so keep part of the organization still working.
Free IPA 4.2.0 allows the use of certificate profiles (certificate template) to sign new certificate requests. This allows you to create your own profiles that will allow sign any type of certificate request. Earlier than FreeIPA 4.2.0, this was not possible, although the underlying dogtag PKI already allowed it.
RFC 5280 is the X.509 certificate description and specifically subordinate CA description. If you have openSSL installed, look at man x509v3_config
for detailed description of V3 extensions.
Characteristics of a Sub-CA
For all practical purposes a Sub-CA is a CA that ideally:
- Has the CA flag set to true
- Preferably not issue further Sub-CA certificates
Creating the Certificate Profile
A subordinate CA is a very powerful element in the PKI’s trust chain. So ensure people who have access to it have adequate knowledge of what’s happening.
Here is the raw config file we used for our Sub CA certificate profile. Some notes follow this long listing.
[root@idm01 fedora]# cat caSubCACert2.cfg desc=This certificate profile is for enrolling Subordinate Certificate Authority certificates. visible=true enable=true auth.instance_id=raCertAuth classId=caEnrollImpl enableBy=ipara name=Manual Certificate Manager Subordinate Signing Certificate Enrollment input.list=i1,i2 input.i1.class_id=certReqInputImpl input.i2.class_id=submitterInfoInputImpl output.list=o1 output.o1.class_id=certOutputImpl policyset.list=caSubCertSet policyset.caSubCertSet.list=1,2,3,4,5,6,8,9,10 policyset.caSubCertSet.1.constraint.class_id=subjectNameConstraintImpl policyset.caSubCertSet.1.constraint.name=Subject Name Constraint policyset.caSubCertSet.1.constraint.params.pattern=.*CN=.+ policyset.caSubCertSet.1.constraint.params.accept=true policyset.caSubCertSet.1.default.class_id=userSubjectNameDefaultImpl policyset.caSubCertSet.1.default.name=Subject Name Default policyset.caSubCertSet.1.default.params.name= policyset.caSubCertSet.2.constraint.class_id=validityConstraintImpl policyset.caSubCertSet.2.constraint.name=Validity Constraint policyset.caSubCertSet.2.constraint.params.range=7305 policyset.caSubCertSet.2.constraint.params.notBeforeCheck=false policyset.caSubCertSet.2.constraint.params.notAfterCheck=false policyset.caSubCertSet.2.default.class_id=caValidityDefaultImpl policyset.caSubCertSet.2.default.name=CA Certificate Validity Default policyset.caSubCertSet.2.default.params.range=7305 policyset.caSubCertSet.2.default.params.startTime=0 policyset.caSubCertSet.3.constraint.class_id=keyConstraintImpl policyset.caSubCertSet.3.constraint.name=Key Constraint policyset.caSubCertSet.3.constraint.params.keyType=- policyset.caSubCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096,nistp256,nistp384,nistp521 policyset.caSubCertSet.3.default.class_id=userKeyDefaultImpl policyset.caSubCertSet.3.default.name=Key Default policyset.caSubCertSet.4.constraint.class_id=noConstraintImpl policyset.caSubCertSet.4.constraint.name=No Constraint policyset.caSubCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl policyset.caSubCertSet.4.default.name=Authority Key Identifier Default policyset.caSubCertSet.5.constraint.class_id=basicConstraintsExtConstraintImpl policyset.caSubCertSet.5.constraint.name=Basic Constraint Extension Constraint policyset.caSubCertSet.5.constraint.params.basicConstraintsCritical=true policyset.caSubCertSet.5.constraint.params.basicConstraintsIsCA=true policyset.caSubCertSet.5.constraint.params.basicConstraintsMinPathLen=0 policyset.caSubCertSet.5.constraint.params.basicConstraintsMaxPathLen=0 policyset.caSubCertSet.5.default.class_id=basicConstraintsExtDefaultImpl policyset.caSubCertSet.5.default.name=Basic Constraints Extension Default policyset.caSubCertSet.5.default.params.basicConstraintsCritical=true policyset.caSubCertSet.5.default.params.basicConstraintsIsCA=true policyset.caSubCertSet.5.default.params.basicConstraintsPathLen=0 policyset.caSubCertSet.6.constraint.class_id=keyUsageExtConstraintImpl policyset.caSubCertSet.6.constraint.name=Key Usage Extension Constraint policyset.caSubCertSet.6.constraint.params.keyUsageCritical=true policyset.caSubCertSet.6.constraint.params.keyUsageDigitalSignature=true policyset.caSubCertSet.6.constraint.params.keyUsageNonRepudiation=true policyset.caSubCertSet.6.constraint.params.keyUsageDataEncipherment=false policyset.caSubCertSet.6.constraint.params.keyUsageKeyEncipherment=false policyset.caSubCertSet.6.constraint.params.keyUsageKeyAgreement=false policyset.caSubCertSet.6.constraint.params.keyUsageKeyCertSign=true policyset.caSubCertSet.6.constraint.params.keyUsageCrlSign=true policyset.caSubCertSet.6.constraint.params.keyUsageEncipherOnly=false policyset.caSubCertSet.6.constraint.params.keyUsageDecipherOnly=false policyset.caSubCertSet.6.default.class_id=keyUsageExtDefaultImpl policyset.caSubCertSet.6.default.name=Key Usage Default policyset.caSubCertSet.6.default.params.keyUsageCritical=true policyset.caSubCertSet.6.default.params.keyUsageDigitalSignature=true policyset.caSubCertSet.6.default.params.keyUsageNonRepudiation=true policyset.caSubCertSet.6.default.params.keyUsageDataEncipherment=false policyset.caSubCertSet.6.default.params.keyUsageKeyEncipherment=false policyset.caSubCertSet.6.default.params.keyUsageKeyAgreement=false policyset.caSubCertSet.6.default.params.keyUsageKeyCertSign=true policyset.caSubCertSet.6.default.params.keyUsageCrlSign=true policyset.caSubCertSet.6.default.params.keyUsageEncipherOnly=false policyset.caSubCertSet.6.default.params.keyUsageDecipherOnly=false policyset.caSubCertSet.8.constraint.class_id=noConstraintImpl policyset.caSubCertSet.8.constraint.name=No Constraint policyset.caSubCertSet.8.default.class_id=subjectKeyIdentifierExtDefaultImpl policyset.caSubCertSet.8.default.name=Subject Key Identifier Extension Default policyset.caSubCertSet.8.default.params.critical=false policyset.caSubCertSet.9.constraint.class_id=signingAlgConstraintImpl policyset.caSubCertSet.9.constraint.name=No Constraint policyset.caSubCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withEC,SHA512withEC policyset.caSubCertSet.9.default.class_id=signingAlgDefaultImpl policyset.caSubCertSet.9.default.name=Signing Alg policyset.caSubCertSet.9.default.params.signingAlg=- policyset.caSubCertSet.9.constraint.class_id=noConstraintImpl policyset.caSubCertSet.9.constraint.name=No Constraint policyset.caSubCertSet.9.default.class_id=crlDistributionPointsExtDefaultImpl policyset.caSubCertSet.9.default.name=CRL Distribution Points Extension Default policyset.caSubCertSet.9.default.params.crlDistPointsCritical=false policyset.caSubCertSet.9.default.params.crlDistPointsEnable_0=true policyset.caSubCertSet.9.default.params.crlDistPointsIssuerName_0=CN=Certificate Authority,o=ipaca policyset.caSubCertSet.9.default.params.crlDistPointsIssuerType_0=DirectoryName policyset.caSubCertSet.9.default.params.crlDistPointsNum=1 policyset.caSubCertSet.9.default.params.crlDistPointsPointName_0=http://<your IPA's CRL revocation list> policyset.caSubCertSet.9.default.params.crlDistPointsPointType_0=URIName policyset.caSubCertSet.9.default.params.crlDistPointsReasons_0= policyset.caSubCertSet.10.constraint.class_id=noConstraintImpl policyset.caSubCertSet.10.constraint.name=No Constraint policyset.caSubCertSet.10.default.class_id=authInfoAccessExtDefaultImpl policyset.caSubCertSet.10.default.name=AIA Extension Default policyset.caSubCertSet.10.default.params.authInfoAccessADEnable_0=true policyset.caSubCertSet.10.default.params.authInfoAccessADLocationType_0=URIName policyset.caSubCertSet.10.default.params.authInfoAccessADLocation_0= policyset.caSubCertSet.10.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 policyset.caSubCertSet.10.default.params.authInfoAccessCritical=false policyset.caSubCertSet.10.default.params.authInfoAccessNumADs=1 profileId=caSubCertAuth2 [root@idm01 fedora]#
This constraint says, the CSR must have a “CN=” string somewhere.
policyset.caSubCertSet.1.constraint.params.pattern=.*CN=.+
The following says that the certificate is for a CA and path len =0, which means the CA can issue further Sub CAs.
policyset.caSubCertSet.5.constraint.params.basicConstraintsIsCA=true
policyset.caSubCertSet.5.constraint.params.basicConstraintsMinPathLen=0
policyset.caSubCertSet.5.constraint.params.basicConstraintsMaxPathLen=0
policyset.caSubCertSet.5.default.params.basicConstraintsIsCA=true
policyset.caSubCertSet.5.default.params.basicConstraintsPathLen=0
Importing the profile into FreeIPA
[root@idm01 fedora]# ipa certprofile-import caSubCertAuth2 --store=true --file=caSubCACert2.cfg Profile description: This certificate profile is for enrolling Subordinate Certificate Authority certificates (v2). --------------------------------- Imported profile "caSubCertAuth2" --------------------------------- Profile ID: caSubCertAuth2 Profile description: This certificate profile is for enrolling Subordinate Certificate Authority certificates (v2). Store issued certificates: TRUE [root@idm01 fedora]#
Don’t forget to add the Certificate ACL allowing appropriate groups s access to the certificate profile either from the WebUI or command line.
Certificate Signing Request
The CSR is not different than other requests you can use OpenSSL to create a CSR. Just ensure the CN and others follow the restrictions that is set in the profile above.
Issuing the Certificate
[root@idm01 fedora]# ipa cert-request ./cert.req --principal SUBCA/SUBCA01.silverskysoft.com --profile-id caSubCertAuth2
This should issue the certificate.
That’s cool, but where’s the green bar?
The green bar that shows up when you visit certain e-commerce websites is a very nice marketing thing. As a result, some users would like to see the green bar. Our next quest is to see if we can create certificate profile that allows generating a certificate with EV flags set. Cursory reading of documentation shows its not well documented and probably not possible.