From cc77ce5741ff8ef048c3bd8e3677e5808c78cd75 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Thu, 29 Jul 2021 17:55:52 -0400
Subject: [PATCH 1/3] Don't assume that plugin attributes and objectclasses are
 lowercase

A user wrote their own plugin to add custom attributes which was
failing with an incorrect error that the attribute wasn't allowed.

It wasn't allowed because it wasn't being treated as case-insensitive
so wasn't being found in the schema.

https://pagure.io/freeipa/issue/8415

Signed-off-by: Rob Crittenden <rcritten@redhat.com>
---
 ipaserver/plugins/config.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/ipaserver/plugins/config.py b/ipaserver/plugins/config.py
index 3526153ec11..ad3dd6a7fdd 100644
--- a/ipaserver/plugins/config.py
+++ b/ipaserver/plugins/config.py
@@ -534,14 +534,14 @@ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
                     checked_attrs = checked_attrs + [self.api.Object[obj].uuid_attribute]
                 for obj_attr in checked_attrs:
                     obj_attr, _unused1, _unused2 = obj_attr.partition(';')
-                    if obj_attr in OPERATIONAL_ATTRIBUTES:
+                    if obj_attr.lower() in OPERATIONAL_ATTRIBUTES:
                         continue
-                    if obj_attr in self.api.Object[obj].params and \
+                    if obj_attr.lower() in self.api.Object[obj].params and \
                       'virtual_attribute' in \
-                      self.api.Object[obj].params[obj_attr].flags:
+                      self.api.Object[obj].params[obj_attr.lower()].flags:
                         # skip virtual attributes
                         continue
-                    if obj_attr not in new_allowed_attrs:
+                    if obj_attr.lower() not in new_allowed_attrs:
                         raise errors.ValidationError(name=attr,
                                 error=_('%(obj)s default attribute %(attr)s would not be allowed!') \
                                 % dict(obj=obj, attr=obj_attr))

From 242bb877d92a3ba7044dd19c82339fdd8305ad89 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Thu, 29 Jul 2021 17:56:32 -0400
Subject: [PATCH 2/3] ipatests: add suite for testing custom plugins

Ensure that attributes and objectclasses are case-insensitive.

https://pagure.io/freeipa/issue/8415

Signed-off-by: Rob Crittenden <rcritten@redhat.com>
---
 .../test_integration/test_custom_plugins.py   | 85 +++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 ipatests/test_integration/test_custom_plugins.py

diff --git a/ipatests/test_integration/test_custom_plugins.py b/ipatests/test_integration/test_custom_plugins.py
new file mode 100644
index 00000000000..6643d713d11
--- /dev/null
+++ b/ipatests/test_integration/test_custom_plugins.py
@@ -0,0 +1,85 @@
+#
+# Copyright (C) 2021  FreeIPA Contributors see COPYING for license
+#
+"""Tests for custom plugins
+"""
+from __future__ import absolute_import
+
+import logging
+import os
+import site
+
+from ipatests.test_integration.base import IntegrationTest
+from ipatests.pytest_ipa.integration import tasks
+
+logger = logging.getLogger(__name__)
+
+
+class TestCustomPlugin(IntegrationTest):
+    """
+    Tests for user-generated custom plugins
+    """
+
+    def test_add_user_objectclass_with_custom_schema(self):
+        """Test adding a custom userclass to new users
+
+           Attributes should not be case-sensitive.
+
+           Based heavily on the custom plugin and schema at
+           https://github.com/Brandeis-CS-Systems/idm-unet-id-plugin
+        """
+        schema = (
+            "dn: cn=schema\n"
+            "attributeTypes: ( 2.16.840.1.113730.3.8.24.1.1 NAME 'customID' "
+            "EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX "
+            "1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Testing' )\n"
+            "objectClasses: ( 2.16.840.1.113730.3.8.24.2.1 NAME 'customUser' "
+            "DESC 'custom user ID objectClass' AUXILIARY MAY ( customID ) "
+            "X-ORIGIN 'Testing' )\n"
+        )
+        plugin = (
+            "from ipalib.parameters import Str\n\n"
+            "from ipaserver.plugins.user import user\n\n"
+            "if 'customUser' not in user.possible_objectclasses:\n"
+            "    user.possible_objectclasses.append('customUser')\n"
+            "customuser_attributes = ['customID']\n"
+            "user.default_attributes.extend(customuser_attributes)\n"
+            "takes_params = (\n"
+            "    Str('customid?',\n"
+            "        cli_name='customid',\n"
+            "        maxlength=64,\n"
+            "        label='User custom uid'),\n"
+            ")\n"
+            "user.takes_params += takes_params\n"
+        )
+
+        tasks.kinit_admin(self.master)
+        self.master.put_file_contents('/tmp/schema.ldif', schema)
+        self.master.run_command(['ipa-ldap-updater', '-S', '/tmp/schema.ldif'])
+        self.master.put_file_contents('/tmp/schema.ldif', schema)
+
+        site_packages = site.getsitepackages()[-1]
+        site_file = os.path.join(
+            site_packages, "ipaserver", "plugins", "test.py"
+        )
+
+        self.master.put_file_contents(site_file, plugin)
+
+        self.master.run_command(['ipactl', 'restart'])
+
+        self.master.run_command([
+            'ipa', 'config-mod',
+            '--userobjectclasses', 'top',
+            '--userobjectclasses', 'person',
+            '--userobjectclasses', 'organizationalperson',
+            '--userobjectclasses', 'inetorgperson',
+            '--userobjectclasses', 'inetuser',
+            '--userobjectclasses', 'posixaccount',
+            '--userobjectclasses', 'krbprincipalaux',
+            '--userobjectclasses', 'krbticketpolicyaux',
+            '--userobjectclasses', 'ipaobject',
+            '--userobjectclasses', 'ipasshuser',
+            '--userobjectclasses', 'customuser',
+        ])
+
+        self.master.run_command(['rm', '-f', site_file])

From af9586a3d522b830211d0c08438929d43162ab88 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Fri, 30 Jul 2021 11:36:21 -0400
Subject: [PATCH 3/3] Temp commit

Note that the new test file is not yet integrated into any PR-CI
runs.
---
 .freeipa-pr-ci.yaml                        | 2 +-
 ipatests/prci_definitions/temp_commit.yaml | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/.freeipa-pr-ci.yaml b/.freeipa-pr-ci.yaml
index abcf8c5b634..80656690080 120000
--- a/.freeipa-pr-ci.yaml
+++ b/.freeipa-pr-ci.yaml
@@ -1 +1 @@
-ipatests/prci_definitions/gating.yaml
\ No newline at end of file
+ipatests/prci_definitions/temp_commit.yaml
\ No newline at end of file
diff --git a/ipatests/prci_definitions/temp_commit.yaml b/ipatests/prci_definitions/temp_commit.yaml
index 4b0398b9218..fee03889d5d 100644
--- a/ipatests/prci_definitions/temp_commit.yaml
+++ b/ipatests/prci_definitions/temp_commit.yaml
@@ -68,7 +68,7 @@ jobs:
       class: RunPytest
       args:
         build_url: '{fedora-latest/build_url}'
-        test_suite: test_integration/test_REPLACEME.py
+        test_suite: test_integration/test_custom_plugins.py
         template: *ci-master-latest
         timeout: 3600
-        topology: *master_1repl_1client
+        topology: *master_1repl
