Example #1
0
    def resubmit_request(self, ca=RENEWAL_CA_NAME, profile=None):
        timeout = api.env.startup_timeout + 60

        cm_profile = None
        if isinstance(profile, cainstance.MSCSTemplateV1):
            cm_profile = profile.unparsed_input

        cm_template = None
        if isinstance(profile, cainstance.MSCSTemplateV2):
            cm_template = profile.unparsed_input

        logger.debug("resubmitting certmonger request '%s'", self.request_id)
        certmonger.resubmit_request(self.request_id, ca=ca, profile=cm_profile,
                                    template_v2=cm_template, is_ca=True)
        try:
            state = certmonger.wait_for_request(self.request_id, timeout)
        except RuntimeError:
            raise admintool.ScriptError(
                "Resubmitting certmonger request '%s' timed out, "
                "please check the request manually" % self.request_id)
        ca_error = certmonger.get_request_value(self.request_id, 'ca-error')
        if state != 'MONITORING' or ca_error:
            raise admintool.ScriptError(
                "Error resubmitting certmonger request '%s', "
                "please check the request manually" % self.request_id)

        logger.debug("modifying certmonger request '%s'", self.request_id)
        certmonger.modify(self.request_id,
                          ca=RENEWAL_CA_NAME,
                          profile='', template_v2='')
Example #2
0
def get_csr_from_certmonger(nickname):
    """
    Get the csr for the provided nickname by asking certmonger.

    Returns the csr in ASCII format without the header/footer in a single line
    or None if not found.
    """
    criteria = {
        'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
        'cert-nickname': nickname,
    }

    id = certmonger.get_request_id(criteria)
    if id:
        csr = certmonger.get_request_value(id, "csr")
        if csr:
            try:
                # Make sure the value can be parsed as valid CSR
                csr_obj = crypto_x509.load_pem_x509_csr(
                    csr.encode('ascii'), default_backend())
                val = base64.b64encode(csr_obj.public_bytes(x509.Encoding.DER))
                return val.decode('ascii')
            except Exception as e:
                # Fallthrough and return None
                logger.debug("Unable to get CSR from certmonger: %s", e)
    return None
Example #3
0
    def check_dates(self):
        """Check validity dates"""
        # TODO: make this configurable
        threshold = 7  # days

        requests = self.get_requests()

        now = datetime.datetime.utcnow()

        for request in requests:
            request_id = certmonger.get_request_id(request)

            if request_id is None:
                # The missing tracking is reported in check_tracking()
                continue
            nickname = request.get('cert-nickname')
            rawcert = certmonger.get_request_value(request_id, 'cert')
            cert = load_pem_certificate(str(rawcert))
            diff = cert.not_valid_after - now
            if diff.days < 0:  # TODO: this is false-positive generator
                self.failure("Certificate %s is expired" % nickname)
            elif diff.days < threshold:
                self.failure("Certificate %s is expiring soon" % nickname)
            elif cert.not_valid_before > now:
                self.failure("Certificate %s is not valid yet" % nickname)
Example #4
0
def get_pkinit_request_ca():
    """
    Return the certmonger CA name which is serving the PKINIT certificate
    request. If the certificate is not tracked by Certmonger, return None
    """
    pkinit_request_id = certmonger.get_request_id(
        {'cert-file': paths.KDC_CERT})

    if pkinit_request_id is None:
        return

    return certmonger.get_request_value(pkinit_request_id, 'ca-name')
Example #5
0
def get_pkinit_request_ca():
    """
    Return the certmonger CA name which is serving the PKINIT certificate
    request. If the certificate is not tracked by Certmonger, return None
    """
    pkinit_request_id = certmonger.get_request_id(
        {'cert-file': paths.KDC_CERT})

    if pkinit_request_id is None:
        return

    return certmonger.get_request_value(pkinit_request_id, 'ca-name')
Example #6
0
def update_server(certs):
    instance = '-'.join(api.env.realm.split('.'))
    update_db(paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % instance, certs)
    if services.knownservices.dirsrv.is_running():
        services.knownservices.dirsrv.restart(instance)

    if services.knownservices.httpd.is_running():
        services.knownservices.httpd.restart()

    criteria = {
        'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
        'cert-nickname': IPA_CA_NICKNAME,
        'ca-name': RENEWAL_CA_NAME,
    }
    request_id = certmonger.get_request_id(criteria)
    if request_id is not None:
        timeout = api.env.startup_timeout + 60

        # The dogtag-ipa-ca-renew-agent-reuse Certmonger CA never
        # actually renews the certificate; it only pulls it from the
        # ca_renewal LDAP cert store.
        #
        # Why is this needed?  If the CA cert gets renewed long
        # before its notAfter (expiry) date (e.g. to switch from
        # self-signed to external, or to switch to new external CA),
        # then the other (i.e. not caRenewalMaster) CA replicas will
        # not promptly pick up the new CA cert.  So we make
        # ipa-certupdate always check for an updated CA cert.
        #
        logger.debug("resubmitting certmonger request '%s'", request_id)
        certmonger.resubmit_request(
            request_id, ca='dogtag-ipa-ca-renew-agent-reuse', profile='')
        try:
            state = certmonger.wait_for_request(request_id, timeout)
        except RuntimeError:
            raise admintool.ScriptError(
                "Resubmitting certmonger request '%s' timed out, "
                "please check the request manually" % request_id)
        ca_error = certmonger.get_request_value(request_id, 'ca-error')
        if state != 'MONITORING' or ca_error:
            raise admintool.ScriptError(
                "Error resubmitting certmonger request '%s', "
                "please check the request manually" % request_id)

        logger.debug("modifying certmonger request '%s'", request_id)
        certmonger.modify(request_id, ca='dogtag-ipa-ca-renew-agent')

    update_file(paths.CA_CRT, certs)
    update_file(paths.CACERT_PEM, certs)
Example #7
0
def update_server(certs):
    instance = '-'.join(api.env.realm.split('.'))
    update_db(paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % instance, certs)
    if services.knownservices.dirsrv.is_running():
        services.knownservices.dirsrv.restart(instance)

    if services.knownservices.httpd.is_running():
        services.knownservices.httpd.restart()

    criteria = {
        'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
        'cert-nickname': IPA_CA_NICKNAME,
        'ca-name': RENEWAL_CA_NAME,
    }
    request_id = certmonger.get_request_id(criteria)
    if request_id is not None:
        timeout = api.env.startup_timeout + 60

        # The dogtag-ipa-ca-renew-agent-reuse Certmonger CA never
        # actually renews the certificate; it only pulls it from the
        # ca_renewal LDAP cert store.
        #
        # Why is this needed?  If the CA cert gets renewed long
        # before its notAfter (expiry) date (e.g. to switch from
        # self-signed to external, or to switch to new external CA),
        # then the other (i.e. not caRenewalMaster) CA replicas will
        # not promptly pick up the new CA cert.  So we make
        # ipa-certupdate always check for an updated CA cert.
        #
        logger.debug("resubmitting certmonger request '%s'", request_id)
        certmonger.resubmit_request(
            request_id, ca='dogtag-ipa-ca-renew-agent-reuse', profile='')
        try:
            state = certmonger.wait_for_request(request_id, timeout)
        except RuntimeError:
            raise admintool.ScriptError(
                "Resubmitting certmonger request '%s' timed out, "
                "please check the request manually" % request_id)
        ca_error = certmonger.get_request_value(request_id, 'ca-error')
        if state != 'MONITORING' or ca_error:
            raise admintool.ScriptError(
                "Error resubmitting certmonger request '%s', "
                "please check the request manually" % request_id)

        logger.debug("modifying certmonger request '%s'", request_id)
        certmonger.modify(request_id, ca='dogtag-ipa-ca-renew-agent')

    update_file(paths.CA_CRT, certs)
    update_file(paths.CACERT_PEM, certs)
Example #8
0
    def resubmit_request(self, ca, profile):
        timeout = api.env.startup_timeout + 60

        self.log.debug("resubmitting certmonger request '%s'", self.request_id)
        certmonger.resubmit_request(self.request_id, profile=profile)
        try:
            state = certmonger.wait_for_request(self.request_id, timeout)
        except RuntimeError:
            raise admintool.ScriptError(
                "Resubmitting certmonger request '%s' timed out, "
                "please check the request manually" % self.request_id)
        ca_error = certmonger.get_request_value(self.request_id, 'ca-error')
        if state != 'MONITORING' or ca_error:
            raise admintool.ScriptError(
                "Error resubmitting certmonger request '%s', "
                "please check the request manually" % self.request_id)

        self.log.debug("modifying certmonger request '%s'", self.request_id)
        certmonger.modify(self.request_id, profile='ipaCACertRenewal')
Example #9
0
    def resubmit_request(self, ca, profile):
        timeout = api.env.startup_timeout + 60

        self.log.debug("resubmitting certmonger request '%s'", self.request_id)
        certmonger.resubmit_request(self.request_id, profile=profile)
        try:
            state = certmonger.wait_for_request(self.request_id, timeout)
        except RuntimeError:
            raise admintool.ScriptError(
                "Resubmitting certmonger request '%s' timed out, "
                "please check the request manually" % self.request_id)
        ca_error = certmonger.get_request_value(self.request_id, 'ca-error')
        if state != 'MONITORING' or ca_error:
            raise admintool.ScriptError(
                "Error resubmitting certmonger request '%s', "
                "please check the request manually" % self.request_id)

        self.log.debug("modifying certmonger request '%s'", self.request_id)
        certmonger.modify(self.request_id, profile='ipaCACertRenewal')
Example #10
0
    def update_server(self, certs):
        instance = '-'.join(api.env.realm.split('.'))
        self.update_db(paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % instance,
                       certs)
        if services.knownservices.dirsrv.is_running():
            services.knownservices.dirsrv.restart(instance)

        self.update_db(paths.HTTPD_ALIAS_DIR, certs)
        if services.knownservices.httpd.is_running():
            services.knownservices.httpd.restart()

        criteria = {
            'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
            'cert-nickname': IPA_CA_NICKNAME,
            'ca-name': RENEWAL_CA_NAME
        }
        request_id = certmonger.get_request_id(criteria)
        if request_id is not None:
            timeout = api.env.startup_timeout + 60

            logger.debug("resubmitting certmonger request '%s'", request_id)
            certmonger.resubmit_request(request_id,
                                        ca='dogtag-ipa-ca-renew-agent-reuse',
                                        profile='')
            try:
                state = certmonger.wait_for_request(request_id, timeout)
            except RuntimeError:
                raise admintool.ScriptError(
                    "Resubmitting certmonger request '%s' timed out, "
                    "please check the request manually" % request_id)
            ca_error = certmonger.get_request_value(request_id, 'ca-error')
            if state != 'MONITORING' or ca_error:
                raise admintool.ScriptError(
                    "Error resubmitting certmonger request '%s', "
                    "please check the request manually" % request_id)

            logger.debug("modifying certmonger request '%s'", request_id)
            certmonger.modify(request_id, ca='dogtag-ipa-ca-renew-agent')

        self.update_file(paths.CA_CRT, certs)
        self.update_file(paths.CACERT_PEM, certs)
Example #11
0
    def update_server(self, certs):
        instance = '-'.join(api.env.realm.split('.'))
        self.update_db(
            paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % instance, certs)
        if services.knownservices.dirsrv.is_running():
            services.knownservices.dirsrv.restart(instance)

        self.update_db(paths.HTTPD_ALIAS_DIR, certs)
        if services.knownservices.httpd.is_running():
            services.knownservices.httpd.restart()

        criteria = {
            'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
            'cert-nickname': IPA_CA_NICKNAME,
            'ca-name': RENEWAL_CA_NAME
        }
        request_id = certmonger.get_request_id(criteria)
        if request_id is not None:
            timeout = api.env.startup_timeout + 60

            logger.debug("resubmitting certmonger request '%s'", request_id)
            certmonger.resubmit_request(
                request_id, ca='dogtag-ipa-ca-renew-agent-reuse', profile='')
            try:
                state = certmonger.wait_for_request(request_id, timeout)
            except RuntimeError:
                raise admintool.ScriptError(
                    "Resubmitting certmonger request '%s' timed out, "
                    "please check the request manually" % request_id)
            ca_error = certmonger.get_request_value(request_id, 'ca-error')
            if state != 'MONITORING' or ca_error:
                raise admintool.ScriptError(
                    "Error resubmitting certmonger request '%s', "
                    "please check the request manually" % request_id)

            logger.debug("modifying certmonger request '%s'", request_id)
            certmonger.modify(request_id, ca='dogtag-ipa-ca-renew-agent')

        self.update_file(paths.CA_CRT, certs)
        self.update_file(paths.CACERT_PEM, certs)
Example #12
0
    def resubmit_request(self, ca='dogtag-ipa-ca-renew-agent', profile=''):
        timeout = api.env.startup_timeout + 60

        logger.debug("resubmitting certmonger request '%s'", self.request_id)
        certmonger.resubmit_request(self.request_id,
                                    ca=ca,
                                    profile=profile,
                                    is_ca=True)
        try:
            state = certmonger.wait_for_request(self.request_id, timeout)
        except RuntimeError:
            raise admintool.ScriptError(
                "Resubmitting certmonger request '%s' timed out, "
                "please check the request manually" % self.request_id)
        ca_error = certmonger.get_request_value(self.request_id, 'ca-error')
        if state != 'MONITORING' or ca_error:
            raise admintool.ScriptError(
                "Error resubmitting certmonger request '%s', "
                "please check the request manually" % self.request_id)

        logger.debug("modifying certmonger request '%s'", self.request_id)
        certmonger.modify(self.request_id,
                          ca='dogtag-ipa-ca-renew-agent',
                          profile='')
Example #13
0
    def execute(self, **options):
        ca = cainstance.CAInstance(self.api.env.realm, certs.NSS_DIR)
        if not ca.is_configured():
            self.debug("CA is not configured on this host")
            return False, []

        ldap = self.api.Backend.ldap2
        base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
                     self.api.env.basedn)
        dn = DN(('cn', 'CA'), ('cn', self.api.env.host), base_dn)
        filter = '(&(cn=CA)(ipaConfigString=caRenewalMaster))'
        try:
            entries = ldap.get_entries(base_dn=base_dn,
                                       filter=filter,
                                       attrs_list=[])
        except errors.NotFound:
            pass
        else:
            self.debug("found CA renewal master %s", entries[0].dn[1].value)

            master = False
            updates = []

            for entry in entries:
                if entry.dn == dn:
                    master = True
                    continue

                updates.append({
                    'dn':
                    entry.dn,
                    'updates': [
                        dict(action='remove',
                             attr='ipaConfigString',
                             value='caRenewalMaster')
                    ],
                })

            if master:
                return False, updates
            else:
                return False, []

        criteria = {
            'cert-database': paths.HTTPD_ALIAS_DIR,
            'cert-nickname': 'ipaCert',
        }
        request_id = certmonger.get_request_id(criteria)
        if request_id is not None:
            self.debug("found certmonger request for ipaCert")

            ca_name = certmonger.get_request_value(request_id, 'ca-name')
            if ca_name is None:
                self.warning(
                    "certmonger request for ipaCert is missing ca_name, "
                    "assuming local CA is renewal slave")
                return False, []
            ca_name = ca_name.strip()

            if ca_name == 'dogtag-ipa-renew-agent':
                pass
            elif ca_name == 'dogtag-ipa-retrieve-agent-submit':
                return False, []
            elif ca_name == 'dogtag-ipa-ca-renew-agent':
                return False, []
            else:
                self.warning(
                    "certmonger request for ipaCert has unknown ca_name '%s', "
                    "assuming local CA is renewal slave", ca_name)
                return False, []
        else:
            self.debug("certmonger request for ipaCert not found")

            config = installutils.get_directive(paths.CA_CS_CFG_PATH,
                                                'subsystem.select', '=')

            if config == 'New':
                pass
            elif config == 'Clone':
                return False, []
            else:
                self.warning(
                    "CS.cfg has unknown subsystem.select value '%s', "
                    "assuming local CA is renewal slave", config)
                return (False, False, [])

        update = {
            'dn':
            dn,
            'updates': [
                dict(action='add',
                     attr='ipaConfigString',
                     value='caRenewalMaster')
            ],
        }

        return False, [update]
Example #14
0
    def check(self):
        fqdn = socket.getfqdn()
        requests = get_expected_requests(self.ca, self.ds, self.serverid)

        for request in requests:
            request_id = certmonger.get_request_id(request)
            if request_id is None:
                yield Result(self,
                             constants.ERROR,
                             key=request_id,
                             msg='Found request id {key} but it is not tracked'
                             'by certmonger!?')
                continue

            ca_name = certmonger.get_request_value(request_id, 'ca-name')
            if ca_name != 'IPA':
                logger.debug('Skipping request %s with CA %s', request_id,
                             ca_name)
                continue
            profile = certmonger.get_request_value(request_id,
                                                   'template_profile')
            if profile != 'caIPAserviceCert':
                logger.debug('Skipping request %s with profile %s', request_id,
                             profile)
                continue

            certfile = None
            if request.get('cert-file') is not None:
                certfile = request.get('cert-file')
                try:
                    cert = x509.load_certificate_from_file(certfile)
                except Exception as e:
                    yield Result(self,
                                 constants.ERROR,
                                 key=request_id,
                                 certfile=certfile,
                                 error=str(e),
                                 msg='Unable to open cert file {certfile}: '
                                 '{error}')
                    continue
            elif request.get('cert-database') is not None:
                nickname = request.get('cert-nickname')
                dbdir = request.get('cert-database')
                try:
                    db = certdb.NSSDatabase(dbdir)
                except Exception as e:
                    yield Result(self,
                                 constants.ERROR,
                                 key=request_id,
                                 dbdir=dbdir,
                                 error=str(e),
                                 msg='Unable to open NSS database {dbdir}: '
                                 '{error}')
                    continue
                try:
                    cert = db.get_cert(nickname)
                except Exception as e:
                    yield Result(self,
                                 constants.ERROR,
                                 key=id,
                                 dbdir=dbdir,
                                 nickname=nickname,
                                 error=str(e),
                                 msg='Unable to retrieve certificate '
                                 '\'{nickname}\' from {dbdir}: {error}')
                    continue

            hostlist = [fqdn]
            if self.ca.is_configured() and certfile == paths.HTTPD_CERT_FILE:
                hostlist.append(f'{IPA_CA_RECORD}.{api.env.domain}')
            error = False
            for host in hostlist:
                if host not in cert.san_a_label_dns_names:
                    error = True
                    yield Result(self,
                                 constants.ERROR,
                                 key=request_id,
                                 hostname=host,
                                 san=cert.san_a_label_dns_names,
                                 ca=ca_name,
                                 profile=profile,
                                 msg='Certificate request id {key} with '
                                 'profile {profile} for CA {ca} does not '
                                 'have a DNS SAN {san} matching name '
                                 '{hostname}')
            if not error:
                yield Result(self,
                             constants.SUCCESS,
                             key=request_id,
                             hostname=hostlist,
                             san=cert.san_a_label_dns_names,
                             ca=ca_name,
                             profile=profile)
Example #15
0
    def execute(self, **options):
        ca = cainstance.CAInstance(self.api.env.realm)
        if not ca.is_configured():
            logger.debug("CA is not configured on this host")
            return False, []

        ldap = self.api.Backend.ldap2
        base_dn = DN(self.api.env.container_masters, self.api.env.basedn)
        dn = DN(('cn', 'CA'), ('cn', self.api.env.host), base_dn)
        filter = '(&(cn=CA)(ipaConfigString=caRenewalMaster))'
        try:
            entries = ldap.get_entries(base_dn=base_dn, filter=filter,
                                       attrs_list=[])
        except errors.NotFound:
            pass
        else:
            logger.debug("found CA renewal master %s", entries[0].dn[1].value)

            master = False
            updates = []

            for entry in entries:
                if entry.dn == dn:
                    master = True
                    continue

                updates.append({
                    'dn': entry.dn,
                    'updates': [
                        dict(action='remove', attr='ipaConfigString',
                             value='caRenewalMaster')
                    ],
                })

            if master:
                return False, updates
            else:
                return False, []

        criteria = {
            'cert-file': paths.RA_AGENT_PEM,
        }
        request_id = certmonger.get_request_id(criteria)
        if request_id is not None:
            logger.debug("found certmonger request for RA cert")

            ca_name = certmonger.get_request_value(request_id, 'ca-name')
            if ca_name is None:
                logger.warning(
                    "certmonger request for RA cert is missing ca_name, "
                    "assuming local CA is renewal slave")
                return False, []
            ca_name = ca_name.strip()

            if ca_name == 'dogtag-ipa-renew-agent':
                pass
            elif ca_name == 'dogtag-ipa-retrieve-agent-submit':
                return False, []
            elif ca_name == 'dogtag-ipa-ca-renew-agent':
                return False, []
            else:
                logger.warning(
                    "certmonger request for RA cert has unknown ca_name '%s', "
                    "assuming local CA is renewal slave", ca_name)
                return False, []
        else:
            logger.debug("certmonger request for RA cert not found")

            config = directivesetter.get_directive(
                paths.CA_CS_CFG_PATH, 'subsystem.select', '=')

            if config == 'New':
                pass
            elif config == 'Clone':
                return False, []
            else:
                logger.warning(
                    "CS.cfg has unknown subsystem.select value '%s', "
                    "assuming local CA is renewal slave", config)
                return (False, False, [])

        update = {
                'dn': dn,
                'updates': [
                    dict(action='add', attr='ipaConfigString',
                         value='caRenewalMaster')
                ],
        }

        return False, [update]