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

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