Blame SOURCES/0005-Add-check-for-IPA-KRA-Agent.patch

d18119
From 3f6ed4393dfa9ddf982e326065a3ea160bef90b6 Mon Sep 17 00:00:00 2001
d18119
From: Antonio Torres <antorres@redhat.com>
d18119
Date: Tue, 23 Feb 2021 16:11:59 +0100
d18119
Subject: [PATCH] Add check for IPA KRA Agent
d18119
d18119
Add check to validate KRA Agent in case KRA is installed, including
d18119
checking for the KRA Agent LDAP entry.
d18119
d18119
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1894781
d18119
Signed-off-by: Antonio Torres <antorres@redhat.com>
d18119
---
d18119
 README.md                       |  16 ++-
d18119
 src/ipahealthcheck/ipa/certs.py | 167 +++++++++++++++++++-------------
d18119
 2 files changed, 112 insertions(+), 71 deletions(-)
d18119
d18119
diff --git a/README.md b/README.md
d18119
index b9c60a2..0f3ed6a 100644
d18119
--- a/README.md
d18119
+++ b/README.md
d18119
@@ -547,7 +547,21 @@ Verify the description and userCertificate values in uid=ipara,ou=People,o=ipaca
d18119
       "kw": {
d18119
         "expected": "2;125;CN=Certificate Authority,O=EXAMPLE.TEST;CN=IPA RA,O=EXAMPLE.TEST",
d18119
         "got": "2;7;CN=Certificate Authority,O=EXAMPLE.TEST;CN=IPA RA,O=EXAMPLE.TEST",
d18119
-        "msg": "RA agent description does not match 2;7;CN=Certificate Authority,O=EXAMPLE.TEST;CN=IPA RA,O=EXAMPLE.TEST in LDAP and expected 2;125;CN=Certificate Authority,O=EXAMPLE.TEST;CN=IPA RA,O=EXAMPLE.TEST"
d18119
+        "msg": "RA agent description does not match. Found 2;7;CN=Certificate Authority,O=EXAMPLE.TEST;CN=IPA RA,O=EXAMPLE.TEST in LDAP and expected 2;125;CN=Certificate Authority,O=EXAMPLE.TEST;CN=IPA RA,O=EXAMPLE.TEST"
d18119
+      }
d18119
+    }
d18119
+
d18119
+### IPAKRAAgent
d18119
+Verify the description and userCertificate values in uid=ipakra,ou=people,o=kra,o=ipaca.
d18119
+
d18119
+    {
d18119
+      "source": "ipahealthcheck.ipa.certs",
d18119
+      "check": "IPAKRAAgent",
d18119
+      "result": "ERROR",
d18119
+      "kw": {
d18119
+        "expected": "2;125;CN=Certificate Authority,O=EXAMPLE.TEST;CN=IPA RA,O=EXAMPLE.TEST",
d18119
+        "got": "2;7;CN=Certificate Authority,O=EXAMPLE.TEST;CN=IPA RA,O=EXAMPLE.TEST",
d18119
+        "msg": "KRA agent description does not match. Found 2;7;CN=Certificate Authority,O=EXAMPLE.TEST;CN=IPA RA,O=EXAMPLE.TEST in LDAP and expected 2;125;CN=Certificate Authority,O=EXAMPLE.TEST;CN=IPA RA,O=EXAMPLE.TEST"
d18119
       }
d18119
     }
d18119
 
d18119
diff --git a/src/ipahealthcheck/ipa/certs.py b/src/ipahealthcheck/ipa/certs.py
d18119
index d3043d0..32c0d76 100644
d18119
--- a/src/ipahealthcheck/ipa/certs.py
d18119
+++ b/src/ipahealthcheck/ipa/certs.py
d18119
@@ -724,6 +724,83 @@ class IPAOpenSSLChainValidation(IPAPlugin):
d18119
                         self, constants.SUCCESS, key=cert)
d18119
 
d18119
 
d18119
+def check_agent(plugin, base_dn, agent_type):
d18119
+    """Check RA/KRA Agent"""
d18119
+
d18119
+    try:
d18119
+        cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM)
d18119
+    except Exception as e:
d18119
+        yield Result(plugin, constants.ERROR,
d18119
+                     error=str(e),
d18119
+                     msg='Unable to load RA cert: {error}')
d18119
+        return
d18119
+    serial_number = cert.serial_number
d18119
+    subject = DN(cert.subject)
d18119
+    issuer = DN(cert.issuer)
d18119
+    description = '2;%d;%s;%s' % (serial_number, issuer, subject)
d18119
+    logger.debug('%s agent description should be %s', agent_type, description)
d18119
+    db_filter = ldap2.ldap2.combine_filters(
d18119
+        [
d18119
+            ldap2.ldap2.make_filter({'objectClass': 'inetOrgPerson'}),
d18119
+            ldap2.ldap2.make_filter(
d18119
+                {'description': ';%s;%s' % (issuer, subject)},
d18119
+                exact=False, trailing_wildcard=False),
d18119
+        ],
d18119
+        ldap2.ldap2.MATCH_ALL)
d18119
+    try:
d18119
+        entries = plugin.conn.get_entries(base_dn,
d18119
+                                          plugin.conn.SCOPE_SUBTREE,
d18119
+                                          db_filter)
d18119
+    except errors.NotFound:
d18119
+        yield Result(plugin, constants.ERROR,
d18119
+                     description=description,
d18119
+                     msg='%s agent not found in LDAP' % agent_type)
d18119
+        return
d18119
+    except Exception as e:
d18119
+        yield Result(plugin, constants.ERROR,
d18119
+                     error=str(e),
d18119
+                     msg='Retrieving %s agent from LDAP failed {error}'
d18119
+                         % agent_type)
d18119
+        return
d18119
+    else:
d18119
+        logger.debug('%s agent description is %s', agent_type, description)
d18119
+        if len(entries) != 1:
d18119
+            yield Result(plugin, constants.ERROR,
d18119
+                         found=len(entries),
d18119
+                         msg='Too many %s agent entries found, {found}'
d18119
+                             % agent_type)
d18119
+            return
d18119
+        entry = entries[0]
d18119
+        raw_desc = entry.get('description')
d18119
+        if raw_desc is None:
d18119
+            yield Result(plugin, constants.ERROR,
d18119
+                         msg='%s agent is missing the description '
d18119
+                             'attribute or it is not readable' % agent_type)
d18119
+            return
d18119
+        ra_desc = raw_desc[0]
d18119
+        ra_certs = entry.get('usercertificate')
d18119
+        if ra_desc != description:
d18119
+            yield Result(plugin, constants.ERROR,
d18119
+                         expected=description,
d18119
+                         got=ra_desc,
d18119
+                         msg='%s agent description does not match. Found '
d18119
+                         '{got} in LDAP and expected {expected}' % agent_type)
d18119
+            return
d18119
+        found = False
d18119
+        for candidate in ra_certs:
d18119
+            if candidate == cert:
d18119
+                found = True
d18119
+                break
d18119
+        if not found:
d18119
+            yield Result(plugin, constants.ERROR,
d18119
+                         certfile=paths.RA_AGENT_PEM,
d18119
+                         dn=str(entry.dn),
d18119
+                         msg='%s agent certificate in {certfile} not '
d18119
+                             'found in LDAP userCertificate attribute '
d18119
+                             'for the entry {dn}' % agent_type)
d18119
+        yield Result(plugin, constants.SUCCESS)
d18119
+
d18119
+
d18119
 @registry
d18119
 class IPARAAgent(IPAPlugin):
d18119
     """Validate the RA Agent used to talk to the CA
d18119
@@ -739,82 +816,32 @@ class IPARAAgent(IPAPlugin):
d18119
             logger.debug('CA is not configured, skipping RA Agent check')
d18119
             return
d18119
 
d18119
-        try:
d18119
-            cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM)
d18119
-        except Exception as e:
d18119
-            yield Result(self, constants.ERROR,
d18119
-                         error=str(e),
d18119
-                         msg='Unable to load RA cert: {error}')
d18119
-            return
d18119
+        base_dn = DN('uid=ipara,ou=people,o=ipaca')
d18119
+        yield from check_agent(self, base_dn, 'RA')
d18119
 
d18119
-        serial_number = cert.serial_number
d18119
-        subject = DN(cert.subject)
d18119
-        issuer = DN(cert.issuer)
d18119
-        description = '2;%d;%s;%s' % (serial_number, issuer, subject)
d18119
 
d18119
-        logger.debug('RA agent description should be %s', description)
d18119
+@registry
d18119
+class IPAKRAAgent(IPAPlugin):
d18119
+    """Validate the KRA Agent
d18119
 
d18119
-        db_filter = ldap2.ldap2.combine_filters(
d18119
-            [
d18119
-                ldap2.ldap2.make_filter({'objectClass': 'inetOrgPerson'}),
d18119
-                ldap2.ldap2.make_filter({'sn': 'ipara'}),
d18119
-                ldap2.ldap2.make_filter(
d18119
-                    {'description': ';%s;%s' % (issuer, subject)},
d18119
-                    exact=False, trailing_wildcard=False),
d18119
-            ],
d18119
-            ldap2.ldap2.MATCH_ALL)
d18119
+       Compare the description and usercertificate values.
d18119
+    """
d18119
 
d18119
-        base_dn = DN(('o', 'ipaca'))
d18119
-        try:
d18119
-            entries = self.conn.get_entries(base_dn,
d18119
-                                            self.conn.SCOPE_SUBTREE,
d18119
-                                            db_filter)
d18119
-        except errors.NotFound:
d18119
-            yield Result(self, constants.ERROR,
d18119
-                         description=description,
d18119
-                         msg='RA agent not found in LDAP')
d18119
+    requires = ('dirsrv',)
d18119
+
d18119
+    @duration
d18119
+    def check(self):
d18119
+        if not self.ca.is_configured():
d18119
+            logger.debug('CA is not configured, skipping KRA Agent check')
d18119
             return
d18119
-        except Exception as e:
d18119
-            yield Result(self, constants.ERROR,
d18119
-                         error=str(e),
d18119
-                         msg='Retrieving RA agent from LDAP failed {error}')
d18119
+
d18119
+        kra = krainstance.KRAInstance(api.env.realm)
d18119
+        if not kra.is_installed():
d18119
+            logger.debug('KRA is not installed, skipping KRA Agent check')
d18119
             return
d18119
-        else:
d18119
-            logger.debug('RA agent description is %s', description)
d18119
-            if len(entries) != 1:
d18119
-                yield Result(self, constants.ERROR,
d18119
-                             found=len(entries),
d18119
-                             msg='Too many RA agent entries found, {found}')
d18119
-                return
d18119
-            entry = entries[0]
d18119
-            raw_desc = entry.get('description')
d18119
-            if raw_desc is None:
d18119
-                yield Result(self, constants.ERROR,
d18119
-                             msg='RA agent is missing the description '
d18119
-                                 'attribute or it is not readable')
d18119
-                return
d18119
-            ra_desc = raw_desc[0]
d18119
-            ra_certs = entry.get('usercertificate')
d18119
-            if ra_desc != description:
d18119
-                yield Result(self, constants.ERROR,
d18119
-                             expected=description,
d18119
-                             got=ra_desc,
d18119
-                             msg='RA agent description does not match. Found '
d18119
-                             '{got} in LDAP and expected {expected}')
d18119
-                return
d18119
-            found = False
d18119
-            for candidate in ra_certs:
d18119
-                if candidate == cert:
d18119
-                    found = True
d18119
-                    break
d18119
-            if not found:
d18119
-                yield Result(self, constants.ERROR,
d18119
-                             certfile=paths.RA_AGENT_PEM,
d18119
-                             dn=str(entry.dn),
d18119
-                             msg='RA agent certificate in {certfile} not '
d18119
-                                 'found in LDAP userCertificate attribute '
d18119
-                                 'for the entry {dn}')
d18119
-            yield Result(self, constants.SUCCESS)
d18119
+
d18119
+        base_dn = DN('uid=ipakra,ou=people,o=kra,o=ipaca')
d18119
+        yield from check_agent(self, base_dn, 'KRA')
d18119
 
d18119
 
d18119
 @registry
d18119
-- 
d18119
2.26.2
d18119