Hello,
running on the FreeIPA rocky-8-4.9.6 docker container. I would like to extend FreeIPA with the postfix-book schema. I need it for a mail server. Unfortunately I can't find any documentation about that. Just some old presentation (FreeIPA 3.3 Training Series) + also some old, maybe still valid, example: https://github.com/abbra/freeipa-userstatus-plugin. A documentation would be really good and helpful. Does anyone have some Notes, doesn't have to be a full polished documentation, some notes maybe some more examples for the current FreeIPA version? Thanks
On pe, 20 touko 2022, Leo O via FreeIPA-users wrote:
Hello,
running on the FreeIPA rocky-8-4.9.6 docker container. I would like to extend FreeIPA with the postfix-book schema. I need it for a mail server. Unfortunately I can't find any documentation about that. Just some old presentation (FreeIPA 3.3 Training Series) + also some old, maybe still valid, example: https://github.com/abbra/freeipa-userstatus-plugin. A documentation would be really good and helpful. Does anyone have some Notes, doesn't have to be a full polished documentation, some notes maybe some more examples for the current FreeIPA version?
There is no documentation other than what is in IPA source code. You can look at other plugins on my github, like the one for FleetCommander integration. But you'd learn more by looking at the IPA's source code, especially checking git history and changes that introduce individual plugins.
Hello Alexander,
oh that's a pity. I would have expected that there are at least some notes, maybe some technical explanations about such general things, anything which helps to speed up the process and not making a newcomer having to read the source code. I mean, it looks like FreeIPA isn't a small project, it is used by Red Hat IDM, somewhere in Fedora and as community FreeIPA. I really expected more than an almost non existing documentation and/ or really outdated pdfs. What can you do with the best application of the world if "nobody knows how to set it up for their needs" to exagerate that statement a bit ;) Hope there are plans to improve on that in the near future, I would say that's more important than new features. Lot's of tests and documentation for the win. Anyways, thanks for the quick reply, I still think this is a great software package which could reach way more projects, teams, businesses, github stars etc. with just having a better documentation.
On pe, 20 touko 2022, Leo O via FreeIPA-users wrote:
Hello Alexander,
oh that's a pity. I would have expected that there are at least some notes, maybe some technical explanations about such general things, anything which helps to speed up the process and not making a newcomer having to read the source code. I mean, it looks like FreeIPA isn't a small project, it is used by Red Hat IDM, somewhere in Fedora and as community FreeIPA. I really expected more than an almost non existing documentation and/ or really outdated pdfs. What can you do with the best application of the world if "nobody knows how to set it up for their needs" to exagerate that statement a bit ;) Hope there are plans to improve on that in the near future, I would say that's more important than new features. Lot's of tests and documentation for the win. Anyways, thanks for the quick reply, I still think this is a great software package which could reach way more projects, teams, businesses, github stars etc. with just having a better documentation.
There is no such thing as 'just having a better documentation' for what is effectively a development process. One needs to understand that one and reading source code is the best way to do that right now. There are plenty of comments in ipalib/*, ipapython/*, ipaserver/plugins/* and in related places, code and git commit messages are the developer documentation at this point. Documentation writers aren't developers themselves, with very little exceptions, and cannot replace developers in writing that knowledge base.
There is always a balance between fixing bugs and working full time on producing a documentation you are asking for. Having large number of customer- and community-driven deployments sometimes skews priorities towards more realistic tasks.
You are welcome to contribute to developer documentation as you go through a journey to discover how to extend IPA. It certainly will be beneficial to everyone.
Yes I know and in case I continue on that, I will of course upload my findings and results (maybe on my public GitHub account or get in touch with you to find a good place). I mean that's the least I can do. The only issue right now is, I'm working on weekdays in an external freelancer project, on weekends for my own company. Unfortunately I can't make up some time for another project like a deep dive into e.g. FreeIPA. Nevertheless, maybe a bit off but still connected to this topic. I saw you are also involved in the alternative to FreeIPA, Samba AD DC (with cockpit UI). In terms of stability, security and of course extensibility compared to FreeIPA. Any preference here from you? My personal feeling is, FreeIPA super easy setup (at least when using the docker container), but as soon as you have to extend it, it's getting tricky. Cannot say that much about security and stability so far. Hope this is not too off, and looking forward to hear your personal opinion about samba AD DC + cockpit compared to FreeIPA. Thanks a lot
On pe, 20 touko 2022, Leo O via FreeIPA-users wrote:
Yes I know and in case I continue on that, I will of course upload my findings and results (maybe on my public GitHub account or get in touch with you to find a good place). I mean that's the least I can do. The only issue right now is, I'm working on weekdays in an external freelancer project, on weekends for my own company. Unfortunately I can't make up some time for another project like a deep dive into e.g. FreeIPA. Nevertheless, maybe a bit off but still connected to this topic. I saw you are also involved in the alternative to FreeIPA, Samba AD DC (with cockpit UI). In terms of stability, security and of course extensibility compared to FreeIPA. Any preference here from you? My personal feeling is, FreeIPA super easy setup (at least when using the docker container), but as soon as you have to extend it, it's getting tricky. Cannot say that much about security and stability so far. Hope this is not too off, and looking forward to hear your personal opinion about samba AD DC + cockpit compared to FreeIPA.
I think you'd need to separate the two. Samba AD DC is a fine solution to handle Windows systems. FreeIPA does not address that part at all, intentionally, to avoid doing double work. Cockpit plugin to Samba AD is not ready for any production use, it is a prototype at best.
FreeIPA relies in a lot of areas on the work of Samba Team, so we are tightly collaborating here and there but at the same time we focus on different target audiences. FreeIPA is focused on making Linux systems usable with all the features you'd need from them in today's world. Samba AD solves a problem of making the life with Windows workstations scalable to different directions than what Microsoft intended. It has less integration for features that might be more needed in a Linux-only environments.
They both can integrate through the forest trust support, with FreeIPA treating Samba AD as, well, Active Directory deployment, and vice versa. There are few missing bits to complete this integration but the point is that FreeIPA intentionally is not focusing on those Windows systems that can be put at Samba AD control instead. We choose what to focus on and coordinate a lot.
Oh thought cockpit UI for samba ad dc is already far more advanced. thanks for clarifying that.
Back to FreeIPA, I was about the create some plugin dirs to put the actual .js files in there. But as I'm using FreeIPA docker, I get a
``` mkdir: cannot create directory ‘/usr/share/ipa/ui/js/plugins/mailalias’: Read-only file system ... ```
So my volume mount is: "-v /srv/freeipa/ipa-data:/data" therefore I got some of the files inside the container in the "/data".
For example wenn looking into: "ls -la /usr/share/ipa/html/" it shows: ``` lrwxrwxrwx. 1 root root 31 May 4 04:50 ca.crt -> /data/usr/share/ipa/html/ca.crt ... ```
so seems a bunch of symbolic links were created, but how would I now incorporate my plugins into that docker environment, as it should also be preserved when deleting the container and starting up a new one. Therefore I have to stay in my "/data" dir but I doubt I can simply use: "/data/usr/share/ipa/" as there is for sure no automagic mechanism which checks that for plugin files, right?
On la, 21 touko 2022, Leo O via FreeIPA-users wrote:
Oh thought cockpit UI for samba ad dc is already far more advanced. thanks for clarifying that.
Back to FreeIPA, I was about the create some plugin dirs to put the actual .js files in there. But as I'm using FreeIPA docker, I get a
mkdir: cannot create directory ‘/usr/share/ipa/ui/js/plugins/mailalias’: Read-only file system ...
So my volume mount is: "-v /srv/freeipa/ipa-data:/data" therefore I got some of the files inside the container in the "/data".
For example wenn looking into: "ls -la /usr/share/ipa/html/" it shows:
lrwxrwxrwx. 1 root root 31 May 4 04:50 ca.crt -> /data/usr/share/ipa/html/ca.crt ...
so seems a bunch of symbolic links were created, but how would I now incorporate my plugins into that docker environment, as it should also be preserved when deleting the container and starting up a new one. Therefore I have to stay in my "/data" dir but I doubt I can simply use: "/data/usr/share/ipa/" as there is for sure no automagic mechanism which checks that for plugin files, right?
I think you felt victim of several issues here. First, you are using a wrong approach in development. I wouldn't start with a containerized FreeIPA at all if you want to develop something on top of FreeIPA, let alone with read-only containers. These are simply wrong tools for iteractive and interactive development on top of a running FreeIPA environment.
Second, if you'd want to use containerized deployment, you need to prepare own image on top of a basic container because what you are adding is effectively a new package. FreeIPA plugins typically include both client-side and server-side bits, may be LDAP schema and upgrade scripts. These all are best to package using native packaging technology for your operating system. In case of Fedora or RHEL-based systems -- RPMs. IPA plugins in my github repositories also have samples of how to package those.
My suggestion would be to start with a VM, do your plugin development there, then package resulting code as an RPM, for example, and if you want to deploy it in containers, build an image on top of existing one, by adding installation of the required packages in a layer of your container image. Only then you'd deploy your own image.
For FreeIPA Web UI development, Petr Vobornik made some time ago a page https://pvoborni.fedorapeople.org/doc/ that also has a debugging section: https://pvoborni.fedorapeople.org/doc/#!/guide/Debugging. It is a bit outdated in terms of versions it mentions but the approach is stil valid. I have used it recently to add my UI fixes and develop Web UI extension for the IdP support, so I know most of those notes are working well, in a VM, of course.
I wouldn't say "wrong approach in development" rather "wrong approach in FreeIPA development". There are a lot of products which you can extend pretty easy, e.g. by just mounting volumes with your files into the container. Especially a kind of a small extension like this, a ldap schema and a few ui elements makes you go through such a hassle, build a rpm package and an own docker image. That's horrible to be honest. Whoever is responsible here, I hope they read this, too, taking this into consideration on any FreeIPA upgrades making it more friendly for extensions and also give the docs a higher priority (P.S. I had to google how to install the FreeIPA packages on a fresh Rocky Linux VM, as I couldn't find it in the official FreeiPA docs, that's ridiculous). I don't know give us something like a environment variable where we can add a plugin path, then we simply mount a volume with the extensions in whatever format/structure it needs and point to it using the env var. Idk, anything which is less cumbersome than the current approach.
Nevertheless, back to the technical part. By the way, thanks for your time Alexander, I appreciate it. I prepared a repo: https://github.com/leonidas-o/freeipa-postfixbook-plugin When I execute the command: "rpmbuild -ba freeipa-userstatus-plugin.spec" I get a "error: Failed build dependencies: python2-ipaserver >= 4.4.0 is needed by freeipa-postfixbook-plugin-0.9.0-1.el8.noarch"
So how do you setup your dev env? I've never build a rpm package, so this is pretty new to me. I mean currently is python3-ipaserver with all its dependencies installed, can't simply install python2-ipserver with all its dependencies as there are for sure dependency conflicts. Do you even build with one spec file several packages or having multiple spec files, e.g. one for python3, one for python2 and therefore also multiple dev env VMs where you can build that?
Leo O via FreeIPA-users wrote:
I wouldn't say "wrong approach in development" rather "wrong approach in FreeIPA development". There are a lot of products which you can extend pretty easy, e.g. by just mounting volumes with your files into the container. Especially a kind of a small extension like this, a ldap schema and a few ui elements makes you go through such a hassle, build a rpm package and an own docker image. That's horrible to be honest. Whoever is responsible here, I hope they read this, too, taking this into consideration on any FreeIPA upgrades making it more friendly for extensions and also give the docs a higher priority (P.S. I had to google how to install the FreeIPA packages on a fresh Rocky Linux VM, as I couldn't find it in the official FreeiPA docs, that's ridiculous).
What docs do you look at? It's pretty clearly documented at https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/htm...
I don't know give us something like a environment variable where we can add a plugin path, then we simply mount a volume with the extensions in whatever format/structure it needs and point to it using the env var. Idk, anything which is less cumbersome than the current approach.
IPA in a container is still a work in process and an engineering feat in itself to stuff multiple servers into a single container. Your expectations are simply too high for what it is.
Nevertheless, back to the technical part. By the way, thanks for your time Alexander, I appreciate it. I prepared a repo: https://github.com/leonidas-o/freeipa-postfixbook-plugin When I execute the command: "rpmbuild -ba freeipa-userstatus-plugin.spec" I get a "error: Failed build dependencies: python2-ipaserver >= 4.4.0 is needed by freeipa-postfixbook-plugin-0.9.0-1.el8.noarch"
So how do you setup your dev env? I've never build a rpm package, so this is pretty new to me. I mean currently is python3-ipaserver with all its dependencies installed, can't simply install python2-ipserver with all its dependencies as there are for sure dependency conflicts. Do you even build with one spec file several packages or having multiple spec files, e.g. one for python3, one for python2 and therefore also multiple dev env VMs where you can build that?
This requirement is specified in your specfile, not something IPA imposes. If you a building only for RHEL 8 (or clone) then you can drop all the RHEL-7 boilerplate, and probably much of the older Fedora stuff as well.
rob
On pe, 27 touko 2022, Rob Crittenden via FreeIPA-users wrote:
Leo O via FreeIPA-users wrote:
I wouldn't say "wrong approach in development" rather "wrong approach in FreeIPA development". There are a lot of products which you can extend pretty easy, e.g. by just mounting volumes with your files into the container. Especially a kind of a small extension like this, a ldap schema and a few ui elements makes you go through such a hassle, build a rpm package and an own docker image. That's horrible to be honest. Whoever is responsible here, I hope they read this, too, taking this into consideration on any FreeIPA upgrades making it more friendly for extensions and also give the docs a higher priority (P.S. I had to google how to install the FreeIPA packages on a fresh Rocky Linux VM, as I couldn't find it in the official FreeiPA docs, that's ridiculous).
What docs do you look at? It's pretty clearly documented at https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/htm...
Rob is right. In addition, if you'd go to freeipa.org -> Documentation, https://www.freeipa.org/page/Documentation, it tells you where the user guides are (I did not copy the links below, to increase readability):
------------------------- User Guides Use Red Hat Enteprise Linux documentation:
- FreeIPA 3.0.x: - Identity Management Guide for RHEL 6 (report bug) - FreeIPA 3.3.x and 4.x: - Linux Domain Identity, Authentication and Policy Guide for RHEL 7 (report bug) - Windows Integration Guide for RHEL 7 (report bug) - System-Level Authentication Guide for RHEL 7 (report bug) - RHEL 8 / FreeIPA 4.7+: Documentation for planning Identity Management and setting up access control - RHEL 8 / FreeIPA 4.7+: Getting started using Identity Management - RHEL 8 / FreeIPA 4.7+: Configuring, managing and maintaining Identity Management in Red Hat Enterprise Linux 8
Upstream user guide is not maintained anymore as all effort is put into the Red Hat Enteprise Linux documentation. Bugs found in the documentation can be reported in Red Hat bugzilla -------------------------
You are welcome to contribute improvements to discover documentation.
I don't know give us something like a environment variable where we can add a plugin path, then we simply mount a volume with the extensions in whatever format/structure it needs and point to it using the env var. Idk, anything which is less cumbersome than the current approach.
IPA in a container is still a work in process and an engineering feat in itself to stuff multiple servers into a single container. Your expectations are simply too high for what it is.
Nevertheless, back to the technical part. By the way, thanks for your time Alexander, I appreciate it. I prepared a repo: https://github.com/leonidas-o/freeipa-postfixbook-plugin When I execute the command: "rpmbuild -ba freeipa-userstatus-plugin.spec" I get a "error: Failed build dependencies: python2-ipaserver >= 4.4.0 is needed by freeipa-postfixbook-plugin-0.9.0-1.el8.noarch"
So how do you setup your dev env? I've never build a rpm package, so this is pretty new to me. I mean currently is python3-ipaserver with all its dependencies installed, can't simply install python2-ipserver with all its dependencies as there are for sure dependency conflicts. Do you even build with one spec file several packages or having multiple spec files, e.g. one for python3, one for python2 and therefore also multiple dev env VMs where you can build that?
This requirement is specified in your specfile, not something IPA imposes. If you a building only for RHEL 8 (or clone) then you can drop all the RHEL-7 boilerplate, and probably much of the older Fedora stuff as well.
Also, instead of hacking right away, consider first how you'd be deploying and maintaining your changes. Supplying volumes with plugins is not something that I'd consider a good way to maintain software in containers. Typically, you'd build a new image that includes all your bits and supply data volumes. This is how FreeIPA container is built in itself. If you want to maintain a healthy image going forward, make sure you have that process automated too. Sure, you can simply copy bits here and there during image build phase but this is much easier if all your bits packaged with a proper packaging tool first.
@Rob yeah, maybe my expectations are a bit too high. I just like red hat based tooling like SELinux, Podman, the RHEL clones like Rocky Linux and also FreeIPA, so maybe I just expected too much when I saw red hat is behind it. I mean, when I saw the vulnerabilities scan results between the docker images "rocky-8-4.9.6" and "rocky-8-4.9.8", they went from 55 to 27, so cut in half, which is pretty impressive. So technically it looks very promising, but as I said, somehow the overall image of FreeIPA is ..., let's call it blurry, at leas to me. You are jumping between several different pages, FreeIPA website, some 5 year olds pdfs, Fedora websites (they call it FreeIPA), RHEL websites (e.g. your link, they call it IDM), when it comes to extensions then you have to read the source code and/ or Alexanders Github Repo, etc. I just think it's a real pity for such a product not being able to deliver a better introduction for new users. I know, I know I'm welcome to contribute to that ;) I'm trying but my schedule says: "no no no, there are 13883" other tasks with a higher priority, so let's go!" And Rob I know I can strip out the python2 parts, that's what I've done in the end, I just thought maybe there is an easy way to build all of the packages in case someone else need the python2 stuff.
@Alexander speaking of extending FreeIPA, yes, automation will of course be a point, but first I need to have something working at all. But even with a rpm package it's not easy at all to create an own image. Mentioned my issue here: https://github.com/freeipa/freeipa-container/issues/457
I had a running docker container with "rocky-8-4.9.6", created one user with the web ui and used the (maybe broken) docker image "rocky-8-pfb-4.9.8" mentioned in my issue above. According to logs, the container logic did start with an upgrade but then failed at "[6/9]: updating schema [error] DuplicateEntry: Type or value exists"
Uploaded a bit more of the "/data/var/log/ipaupgrade.log" on pastebin: https://pastebin.com/vBjLFtj6
Some strange lines I spotted, especially as hbac is nothing I bring in via the plugin. It's a plugin coming with FreeIPA. What does this mean, is this plugin broken or just a false error message? But it is also saying to all my plugins -> not valid: " 2022-05-28T19:48:22Z DEBUG importing plugin module ipaserver.plugins.hbac 2022-05-28T19:48:22Z DEBUG ipaserver.plugins.hbac is not a valid plugin module ... 2022-05-28T19:48:22Z DEBUG importing plugin module ipaserver.plugins.mailalias 2022-05-28T19:48:22Z DEBUG ipaserver.plugins.mailalias is not a valid plugin module 2022-05-28T19:48:22Z DEBUG importing plugin module ipaserver.plugins.mailenabled 2022-05-28T19:48:22Z DEBUG ipaserver.plugins.mailenabled is not a valid plugin module ... "
Another interesting part is here, as this error message does not make any sense to me. I checked on a clean "rocky-8-4.9.6" with ldapsearch for attributes and couldn't find anything with has the name "mailForwardingAddress" or the OID "1.3.6.1.4.1.29426.1.10.10". " ldap.TYPE_OR_VALUE_EXISTS: {'msgtype': 103, 'msgid': 17, 'result': 20, 'desc': 'Type or value exists', 'ctrls': [], 'info': 'attribute type mailForwardingAddress: Does not match the OID "1.3.6.1.4.1.29426.1.10.10". Another attribute type is already using the name or OID.'} ... 2022-05-28T19:48:30Z DEBUG [error] DuplicateEntry: Type or value exists "
Any suggestions, is this maybe the "broken" image or anything else inside FreeIPA, I just found a kind of a similar issue here: https://pagure.io/freeipa/issue/5972
On la, 28 touko 2022, Leo O via FreeIPA-users wrote:
I had a running docker container with "rocky-8-4.9.6", created one user with the web ui and used the (maybe broken) docker image "rocky-8-pfb-4.9.8" mentioned in my issue above. According to logs, the container logic did start with an upgrade but then failed at "[6/9]: updating schema [error] DuplicateEntry: Type or value exists"
Uploaded a bit more of the "/data/var/log/ipaupgrade.log" on pastebin: https://pastebin.com/vBjLFtj6
Some strange lines I spotted, especially as hbac is nothing I bring in via the plugin. It's a plugin coming with FreeIPA. What does this mean, is this plugin broken or just a false error message? But it is also saying to all my plugins -> not valid: " 2022-05-28T19:48:22Z DEBUG importing plugin module ipaserver.plugins.hbac 2022-05-28T19:48:22Z DEBUG ipaserver.plugins.hbac is not a valid plugin module ... 2022-05-28T19:48:22Z DEBUG importing plugin module ipaserver.plugins.mailalias 2022-05-28T19:48:22Z DEBUG ipaserver.plugins.mailalias is not a valid plugin module 2022-05-28T19:48:22Z DEBUG importing plugin module ipaserver.plugins.mailenabled 2022-05-28T19:48:22Z DEBUG ipaserver.plugins.mailenabled is not a valid plugin module ... "
Ignore these. This typically is issued when a plugin module is imported but does not have registry calls. ipaserver.plugins.hbac is a stub to allow
ipa help hbac
to show up in the help topics output.
It is done so that hbacrule, hbacsvc, and hbacsvcgroup shown under the same HBAC topic.
I guess your plugin does not introduce any additional IPA commands that get registered in IPA objects/commands registries. This means a warning is issued like that but it is harmless.
Another interesting part is here, as this error message does not make any sense to me. I checked on a clean "rocky-8-4.9.6" with ldapsearch for attributes and couldn't find anything with has the name "mailForwardingAddress" or the OID "1.3.6.1.4.1.29426.1.10.10". " ldap.TYPE_OR_VALUE_EXISTS: {'msgtype': 103, 'msgid': 17, 'result': 20, 'desc': 'Type or value exists', 'ctrls': [], 'info': 'attribute type mailForwardingAddress: Does not match the OID "1.3.6.1.4.1.29426.1.10.10". Another attribute type is already using the name or OID.'} ... 2022-05-28T19:48:30Z DEBUG [error] DuplicateEntry: Type or value exists "
This is a problem with your LDAP schema. It conflicts with a default schema provided by 389-ds LDAP server -- besides the schema extensions IPA provides, we rely on the default schema in 389-ds.
389-ds has default 50ns-mail.ldif schema that already provides mailForwardingAddress (and many other) attribute. Your definition of mailForwardingAddress conflicts with the default definition, hence the issue.
I'd recommend you to look into schema defaults that 389-ds already provides and reuse them. Your plugin should ideally package only the difference on top of 389-ds+IPA. If you have conflicting type definitions which really do conflict by their properties, a better approach would be to create your own schema and ask IANA to issue your own OID subtree which then can be used to allocate OIDs for your own schema.
I don't think in this case it is required though. Check /usr/share/dirsrv/schema -- all schema files from there are automatically loaded by the 389-ds LDAP server and don't need to be repeated as instance-specific schema.
It is typical that LDAP schemas may have conflicting definitions either on attribute/class names or on used OIDs. Many of the attributes might have common names and application developers didn't look into coordinating their activities.
The schema in question comes from '97 as a part of Hans Lachman's draft for what did not become an RFC for intranet mail routing: https://datatracker.ietf.org/doc/draft-lachman-ldap-mail-routing/ The draft was issued, went through several rounds of editions but did not get accepted formally. Nevertheless, its schema is packaged by default by LDAP servers derived from Netscape Communications' LDAP server code. 389-ds is the opensourced version of the Netscape's LDAP server code.
Any suggestions, is this maybe the "broken" image or anything else inside FreeIPA, I just found a kind of a similar issue here: https://pagure.io/freeipa/issue/5972
FreeIPA-users mailing list -- freeipa-users@lists.fedorahosted.org To unsubscribe send an email to freeipa-users-leave@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/freeipa-users@lists.fedorahoste... Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure
@Alexander Thanks for the detailed explanation. I was able to solve some issues (adelton - Jan) helped me out. Could make "dnf install ..." to work inside the container, used that instead "rpm -i ...". The docker build is now running without error messages. There was also another issue which is a bug: https://bugzilla.redhat.com/show_bug.cgi?id=2083570 Because of this I had issues with upgrading from `rocky-8-4.9.6` to `rocky-8-4.9.8` respectively from `rocky-8-4.9.6` to my custom `rocky-8-pfb-4.9.8`. Therefore went down to `container-tools:3.0` and using podman 3.0.1 atm. As this is now working, I'm still missing the Web UI elements inside a users details page.
As said, I commented out the two already existing attributeTypes (mailQuota and mailForwardingAddress). Everything else, is still in my plugin. So mailForwardingAddress is still PostfixBookMailForward ObjectClass and mailQuota on PostfixBookMailAccount ObjectClass. I hope that's correct so far? https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/main/plugin/sc...
I also entered the container and looked into the paths: /usr/share/ipa/ui/js/plugins/postfixbook/ -> exists and contains all the .js files /usr/lib/python3.6/site-packages/ipaserver/plugins/ -> contains the .py files
Checked ldap: ldapsearch -D 'cn=Directory Manager' -W -x -s base -b 'cn=schema' objectclasses | grep -i postfixbook
objectclasses: ( 1.3.6.1.4.1.29426.1.2.2.2 NAME 'PostfixBookMailForward' DESC objectclasses: ( 1.3.6.1.4.1.29426.1.2.2.1 NAME 'PostfixBookMailAccount' DESC
ldapsearch -D 'cn=Directory Manager' -o ldif-wrap=no -W -x -s base -b 'cn=schema' attributetypes | grep -i mail
... attributetypes: ( 2.16.840.1.113730.3.1.21 NAME 'mailQuota' DESC 'Netscape Messaging Server 4.x defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Messaging Server 4.x' ) ... attributetypes: ( 1.3.6.1.4.1.29426.1.10.2 NAME 'mailAlias' DESC 'RFC822 Mailbox - mail alias' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN ( 'IPA v4.9.8' 'user defined' ) ) ... attributetypes: ( 1.3.6.1.4.1.29426.1.10.5 NAME 'mailEnabled' DESC 'TRUE to enable, FALSE to disable account' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN ( 'IPA v4.9.8' 'user defined' ) )
Any idea?
On ma, 30 touko 2022, Leo O via FreeIPA-users wrote:
@Alexander Thanks for the detailed explanation. I was able to solve some issues (adelton - Jan) helped me out. Could make "dnf install ..." to work inside the container, used that instead "rpm -i ...". The docker build is now running without error messages. There was also another issue which is a bug: https://bugzilla.redhat.com/show_bug.cgi?id=2083570 Because of this I had issues with upgrading from `rocky-8-4.9.6` to `rocky-8-4.9.8` respectively from `rocky-8-4.9.6` to my custom `rocky-8-pfb-4.9.8`. Therefore went down to `container-tools:3.0` and using podman 3.0.1 atm. As this is now working, I'm still missing the Web UI elements inside a users details page.
As said, I commented out the two already existing attributeTypes (mailQuota and mailForwardingAddress). Everything else, is still in my plugin. So mailForwardingAddress is still PostfixBookMailForward ObjectClass and mailQuota on PostfixBookMailAccount ObjectClass. I hope that's correct so far? https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/main/plugin/sc...
I also entered the container and looked into the paths: /usr/share/ipa/ui/js/plugins/postfixbook/ -> exists and contains all the .js files /usr/lib/python3.6/site-packages/ipaserver/plugins/ -> contains the .py files
JS plugin loader expects that for every plugin named foo you are providing foo/foo.js loader which then pulls all required files itself. I don't see postfixbook/postfixbook.js at all. You are copying all js files when building the package but there is no main file that would be loaded by the framework.
See install/ui/doc/guides/plugins/README.md for details.
I absolutely don't how the file "postfixbook/postfixbook.js" has to be structured. It's not clear to me, even when reading the README.md you proposed.
Maybe something like: " { name: '$plugin_name', path: 'plugins/$plugin_name' } " But how to continue? I mean, do I have to put this inside an array or an JSON object etc. How would that look like for multiple plugins like I have?
On ke, 01 kesä 2022, Leo O via FreeIPA-users wrote:
I absolutely don't how the file "postfixbook/postfixbook.js" has to be structured. It's not clear to me, even when reading the README.md you proposed.
Maybe something like: " { name: '$plugin_name', path: 'plugins/$plugin_name' } " But how to continue? I mean, do I have to put this inside an array or an JSON object etc. How would that look like for multiple plugins like I have?
You have one plugin in terms of IPA UI -- it is loaded via postfixbook/postfixbook.js. The rest can be loaded similar to how we load internal plugins.
define([ './mailalias', './mailenabled', './mailforwardingaddress', './mailgidnumber', './mailgroupmember', './mailhomedirectory', './mailquota', './mailsieverulesource', './mailstoragedirectory', './mailuidnumber'],function(){ });
'define()' function will load each of those and run them and after that is done, the function will be called.
I did a small experiment with a plugin 'foo':
# cat foo/foo.js define([ './bar'], function(){ })
# cat foo/bar.js define([ 'freeipa/text', 'freeipa/widgets/LoginScreen' ],function(text, LoginScreen){ LoginScreen.field_specs[0].label = text.get('@i18n:login.username1', "Username 1"); });
This 'bar' subplugin replaces 'Username' label on the login page by 'Username 1'. Obviously, login.username1 translation is not provided by anything -- for that one needs Python code that extends ipaserver.internal.i18n_messages.messages['login'] dict with 'username1' element:
--------------------------------------------------------- from ipalib.text import _ from .internal import i18n_messages
i18n_messages.messages['login']['username1'] = _("My other username") ----------------------------------------------------------
If you'd provide one, then it would be 'My other username' rather than 'Username 1'.
The paths in 'define' are relative to /ipa/ui/js, so all FreeIPA components are in 'freeipa/', all Dojo components are in 'dojo/' and so on. Your own plugin code would be at './' inside 'foo' or at 'plugins/foo/', if you want the full path to reference it from other plugin.
Hopefully, this helps.
Okay it worked, the ui fields appeared finally.
But there is still an issue. When I now e.g. click on the checkbox "Mail enabled" and save it, I get an error: "IPA Error 4002: DuplicateEntry" - "Type or value exists".
Looked through the logs, but couldn't find anything useful, which points me into a direction.
Also added change type modify etc. to the schema: https://github.com/leonidas-o/freeipa-postfixbook-plugin/commit/d7ba2c2593db...
But same error. Doesn't look like, that's doing anything.
On to, 02 kesä 2022, Leo O via FreeIPA-users wrote:
Okay it worked, the ui fields appeared finally.
But there is still an issue. When I now e.g. click on the checkbox "Mail enabled" and save it, I get an error: "IPA Error 4002: DuplicateEntry" - "Type or value exists".
Looked through the logs, but couldn't find anything useful, which points me into a direction.
Enable debug in /etc/ipa/server.conf [global] debug=True
and restart httpd, then re-try. /var/log/httpd/error_log will have more details.
I suspect these are from your unguarded appends:
def usermod_precallback(self, ldap, dn, entry, attrs_list, *keys, **options):
if "objectclass" not in entry.keys(): old_entry = ldap.get_entry(dn, ["objectclass"]) entry["objectclass"] = old_entry["objectclass"] entry["objectclass"].append("postfixbookmailaccount") return dn
instead of that, simply use add_missing_object_class(). This is how it is done in user-add-certmapdata, for example:
from .baseldap import add_missing_object_class
class baseuser_add_certmapdata(ModCertMapData, LDAPAddAttribute): __doc__ = _("Add one or more certificate mappings to the user entry.") msg_summary = _('Added certificate mappings to user "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
dn = super(baseuser_add_certmapdata, self).pre_callback( ldap, dn, entry_attrs, attrs_list, *keys, **options)
# The objectclass ipacertmapobject may not be present on # existing user entries. We need to add it if we define a new # value for ipacertmapdata add_missing_object_class(ldap, u'ipacertmapobject', dn)
return dn
So many questions come up when reading your reply. I also done some troubleshooting.
1. Not a question, but a observation: set debug=true, still not helpful 2. Still open question from my last post, do I need the "change type modify, add: attributeTypes, add: objectClasses" inside my schema, is it doing something or should I remove it again?
Side note: About your reply, I'm not a python dev and I absolutely don't know the application so best preconditions to probably do every mistake possible. Nevertheless, according to "instead of that, simply use add_missing_object_class()", the one you are talking about is a class, my plugins are not, different structure, so I can't say what's here important/ needed.
3. you mentioned my "usermod_precallback" function, what about the "useradd_precallback" above, there is an append too, should this be refactored as well with "add_missing_object_class"? 4. Speaking of "add_missing_object_class(ldap, u'ipacertmapobject', dn)" what's the u'... before the objectClass doing, meaning? 5. And what about the statements after the first useradd and second usermod callbacks: "user.user_add.register_pre_callback(useradd_precallback)" and "user.user_mod.register_pre_callback(usermod_precallback)", do they stay, after your proposed refactoring or do they have to be removed?
Another observation: I've setup a VM where I installed freeIPA, so I don't have to deal with the read-only container and images. I started to create the files one by one. So created "postfixbook.js", "mailenabled.js" and "mailenabled.py", strangely no error, I could create a user, I could click on the Mail enabled checkbox and save successfully. Ldapsearch showed even that it was correctly set for that user. The only issue so far, the checkbox in the UI is always unchecked, so entering a user with checked mail enabled, when I check it, I can't save, FreeIpa sees that nothing has changed, then when I uncheck, now I can save. So simply on entering the details view, this checkbox element isn't set according to the stored value, it's simply always unchecked. This was done with the "old" unguarded appends, so it seems, this is working. I then added the second file pairs "mailalias.js" and "mailalias.py". Now I had this weird behaviour, couldn't create user anymore, couldn't save the mail alias. I then discovered that "mailenabled.py" had "entry["objectclass"].append("postfixbookmailaccount")" whereas "mailalias.py" had "entry["objectclass"].append("postfixbookMailaccount")" with a capital "M". BTW the same typo was in "mailsieverulesource". So how should I know when to use lowercase or camelCase? For example in the pdf: https://www.freeipa.org/images/5/5b/FreeIPA33-extending-freeipa.pdf "objectclasses" is sometimes written lowercased and sometimes camelCased "objectClasses". When I look into my schema, the objectClasses name is even written as "PostfixBookMailAccount". In the schema one attributeType is written as "mailEnabled", in the "mailenabled.js" and "mailenabled.py" files everywhere is "mailenabled" lowercased. In your (abbra freeIpa user status) repo the same with "inetuserstatus" in the .py and .js files whereas "inetUserStatus" in the schema. So I'm totally confused when to use what, it feels totally wrong, feels like a big mess.
On pe, 03 kesä 2022, Leo O via FreeIPA-users wrote:
So many questions come up when reading your reply. I also done some troubleshooting.
- Not a question, but a observation: set debug=true, still not helpful
If you have specific problems, outline them with more details. "still not helpful" is not a problem statement that I can help with, sorry.
For example, this is how it works for me:
[root@idm ~]# vim /etc/ipa/server.conf [root@idm ~]# cat /etc/ipa/server.conf [global] debug = True [root@idm ~]# systemctl restart httpd [root@idm ~]# kinit admin Password for admin@IPA.TEST: [root@idm ~]# ipa ping ---------------------------------------------------------------- IPA server version 4.10.0.dev202205301426+git. API version 2.248 ----------------------------------------------------------------
And in the /var/log/httpd/error_log I can see:
[Sat Jun 04 06:13:05.625413 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: WSGI wsgi_dispatch.__call__: [Sat Jun 04 06:13:05.625469 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: WSGI jsonserver.__call__: [Sat Jun 04 06:13:05.625497 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: KerberosWSGIExecutioner.__call__: [Sat Jun 04 06:13:05.639304 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: Created connection context.ldap2_140315178175936 [Sat Jun 04 06:13:05.639380 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: WSGI WSGIExecutioner.__call__: [Sat Jun 04 06:13:05.643317 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: raw: schema(known_fingerprints=('73d45d48',), version='2.170') [Sat Jun 04 06:13:05.643450 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: schema(known_fingerprints=('73d45d48',), version='2.170') [Sat Jun 04 06:13:05.761966 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: WSGI wsgi_execute PublicError: Traceback (most recent call last): [Sat Jun 04 06:13:05.761990 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] File "/usr/lib/python3.10/site-packages/ipaserver/rpcserver.py", line 407, in wsgi_execute [Sat Jun 04 06:13:05.761994 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] result = command(*args, **options) [Sat Jun 04 06:13:05.761997 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] File "/usr/lib/python3.10/site-packages/ipalib/frontend.py", line 471, in __call__ [Sat Jun 04 06:13:05.762000 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] return self.__do_call(*args, **options) [Sat Jun 04 06:13:05.762002 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] File "/usr/lib/python3.10/site-packages/ipalib/frontend.py", line 499, in __do_call [Sat Jun 04 06:13:05.762005 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ret = self.run(*args, **options) [Sat Jun 04 06:13:05.762008 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] File "/usr/lib/python3.10/site-packages/ipalib/frontend.py", line 816, in run [Sat Jun 04 06:13:05.762011 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] return self.execute(*args, **options) [Sat Jun 04 06:13:05.762013 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] File "/usr/lib/python3.10/site-packages/ipaserver/plugins/schema.py", line 855, in execute [Sat Jun 04 06:13:05.762016 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] raise errors.SchemaUpToDate( [Sat Jun 04 06:13:05.762019 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipalib.errors.SchemaUpToDate: Schema is up to date (FP '73d45d48', TTL 3600 s) [Sat Jun 04 06:13:05.762021 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] [Sat Jun 04 06:13:05.762089 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: INFO: [jsonserver_kerb] admin@IPA.TEST: schema(known_fingerprints=('73d45d48',), version='2.170'): SchemaUpToDate [Sat Jun 04 06:13:05.762120 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: [jsonserver_kerb] admin@IPA.TEST: schema(known_fingerprints=('73d45d48',), version='2.170'): SchemaUpToDate etime=122649405 [Sat Jun 04 06:13:05.762674 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: FINAL: Hits 0 Misses 0 Size 0 [Sat Jun 04 06:13:05.762711 2022] [wsgi:error] [pid 25641:tid 25865] [remote 10.0.189.65:40858] ipa: DEBUG: Destroyed connection context.ldap2_140315178175936 [Sat Jun 04 06:13:05.915087 2022] [:warn] [pid 25646:tid 25746] [client 10.0.189.65:40862] failed to set perms (3140) on file (/run/ipa/ccaches/admin@IPA.TEST-GboQvM)!, referer: https://idm.ipa.test/ipa/xml [Sat Jun 04 06:13:05.915684 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: DEBUG: WSGI wsgi_dispatch.__call__: [Sat Jun 04 06:13:05.915729 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: DEBUG: WSGI jsonserver_session.__call__: [Sat Jun 04 06:13:05.926136 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: DEBUG: Created connection context.ldap2_140315178176560 [Sat Jun 04 06:13:05.926198 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: DEBUG: WSGI jsonserver.__call__: [Sat Jun 04 06:13:05.926237 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: DEBUG: WSGI WSGIExecutioner.__call__: [Sat Jun 04 06:13:05.930928 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: DEBUG: raw: ping(version='2.248') [Sat Jun 04 06:13:05.931037 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: DEBUG: ping(version='2.248') [Sat Jun 04 06:13:05.931142 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: INFO: [jsonserver_session] admin@IPA.TEST: ping/1(version='2.248'): SUCCESS [Sat Jun 04 06:13:05.931177 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: DEBUG: [jsonserver_session] admin@IPA.TEST: ping/1(version='2.248'): SUCCESS etime=4850346 [Sat Jun 04 06:13:05.932134 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: DEBUG: FINAL: Hits 0 Misses 0 Size 0 [Sat Jun 04 06:13:05.932180 2022] [wsgi:error] [pid 25642:tid 25868] [remote 10.0.189.65:40862] ipa: DEBUG: Destroyed connection context.ldap2_140315178176560
In non-debug run you'd only see entries with ipa: INFO or ipa: ERROR.
- Still open question from my last post, do I need the "change type
modify, add: attributeTypes, add: objectClasses" inside my schema, is it doing something or should I remove it again?
No. You have to provide a schema file in a format like this in a schema.d subdirectory: https://github.com/abbra/freeipa-desktop-profile/blob/master/plugin/schema.d...
This is enough. IPA upgrade code will pick it up and perform proper integration of it. The key is to put the LDAP schema files in /usr/share/ipa/schema.d/. README file in that directory explains what is required and expected.
Side note: About your reply, I'm not a python dev and I absolutely don't know the application so best preconditions to probably do every mistake possible. Nevertheless, according to "instead of that, simply use add_missing_object_class()", the one you are talking about is a class, my plugins are not, different structure, so I can't say what's here important/ needed.
- you mentioned my "usermod_precallback" function, what about the
"useradd_precallback" above, there is an append too, should this be refactored as well with "add_missing_object_class"?
Yes.
- Speaking of "add_missing_object_class(ldap, u'ipacertmapobject',
dn)" what's the u'... before the objectClass doing, meaning?
This is Python 2 way of saying the string is in Unicode. You can drop it these days, e.g. just 'ipacertmapobject' instead of u'ipacertmapobject' as current IPA code is not targetted to Python 2 anymore.
- And what about the statements after the first useradd and second
usermod callbacks: "user.user_add.register_pre_callback(useradd_precallback)" and "user.user_mod.register_pre_callback(usermod_precallback)", do they stay, after your proposed refactoring or do they have to be removed?
They stay. I have tried to help you with that specific fragment, not with the whole plugin or plugins.
Another observation: I've setup a VM where I installed freeIPA, so I don't have to deal with the read-only container and images. I started to create the files one by one. So created "postfixbook.js", "mailenabled.js" and "mailenabled.py", strangely no error, I could create a user, I could click on the Mail enabled checkbox and save successfully. Ldapsearch showed even that it was correctly set for that user. The only issue so far, the checkbox in the UI is always unchecked, so entering a user with checked mail enabled, when I check it, I can't save, FreeIpa sees that nothing has changed, then when I uncheck, now I can save. So simply on entering the details view, this checkbox element isn't set according to the stored value, it's simply always unchecked. This was done with the "old" unguarded appends, so it seems, this is working. I then added the second file pairs "mailalias.js" and "mailalias.py". Now I had this weird behaviour, couldn't create user anymore, couldn't save the mail alias. I then discovered that "mailenabled.py" had "entry["objectclass"].append("postfixbookmailaccount")" whereas "mailalias.py" had "entry["objectclass"].append("postfixbookMailaccount")" with a capital "M". BTW the same typo was in "mailsieverulesource". So how should I know when to use lowercase or camelCase? For example in the pdf: https://www.freeipa.org/images/5/5b/FreeIPA33-extending-freeipa.pdf "objectclasses" is sometimes written lowercased and sometimes camelCased "objectClasses". When I look into my schema, the objectClasses name is even written as "PostfixBookMailAccount". In the schema one attributeType is written as "mailEnabled", in the "mailenabled.js" and "mailenabled.py" files everywhere is "mailenabled" lowercased. In your (abbra freeIpa user status) repo the same with "inetuserstatus" in the .py and .js files whereas "inetUserStatus" in the schema. So I'm totally confused when to use what, it feels totally wrong, feels like a big mess.
There are three separate parts here.
LDAP attribute and objectclass names are case-insensitive in LDAP. You can build an LDAP filter that asks for (&(objectClass=PostfixBookMailAccount)(mailEnabled=TRUE)) and (&(objectclass=postfixbookmailaccount)(mailenabled=TRUE)) and get the same result. Values might have different matching rules, sensitive and insensitive, but the attribute/class names are insensitive. And objectclass attribute values are treated case-insensitive in LDAP schema. So that's why 'postfixbookmailaccount' and 'PostfixBookMailAccount' in the queries above both work.
When you use
entry["objectclass"].append("postfixbookMailaccount")
you are dealing with Python representation of the LDAP entry in IPA framework. 'entry' is a dictionary. Python dictionary uses case-sensitive keys, so entry["ObjectClass"] is addressing a different object than entry["objectclass"]. Objects, stored in the dictionary, treated elsewhere.
LDAP attribute names in IPA framework Python code often used to search in various Python dictionaries or Python lists. When that search is done, in most cases it is case-sensitive, so uniform casing is important. We choose to use lower case in IPA framework.
There are few exceptions that help developers. For example, add_missing_object_class() helper in its entirety is here:
def add_missing_object_class(ldap, objectclass, dn, entry_attrs=None, update=True): """ Add object class if missing into entry. Fetches entry if not passed. Updates the entry by default.
Returns the entry """
if not entry_attrs: entry_attrs = ldap.get_entry(dn, ['objectclass']) if (objectclass.lower() not in (o.lower() for o in entry_attrs['objectclass'])): entry_attrs['objectclass'].append(objectclass) if update: ldap.update_entry(entry_attrs) return entry_attrs
You can see that we use .lower() method a lot in comparisons of string values and address 'objectclass' always in lower case when accessing entry_attrs dictionary. But this is not the case for all code paths, so we expect lowcase attribute/objectclass names.
Finally, your issue:
The only issue so far, the checkbox in the UI is always unchecked, so entering a user with checked mail enabled, when I check it, I can't save
This is most likely because your 'mailenabled' attribute is not fetched by default when a corresponding object is retrieved. Do you see 'mailenabled' returned for 'ipa user-show'?
Yes, it was already a bit late therefore the "still not helpful" was meant to be "the log output is still not helpful", sorry for that. So for me it's not "/etc/ipa/server.conf" but "/etc/ipa/default.conf". Debug mode is on, I see the extra debug log but no new findings through that.
Is there something "hidden" a rpm plugin is doing compared to manually creating the files at the specific locations and running ipa-server-install? I wan't to avoid creating a plugin all the time as I'm currently simply refactoring, trying out. I've done the following on the VM (all files updated with the latest insights):
executed: "ipa-server-install --uninstall" updated the three .js files (postfixbook.js, mailalias.js, mailenabled.js) in "/usr/share/ipa/ui/js/plugins/postfixbook" updated their two python files in "/usr/lib/python3.6/site-packages/ipaserver/plugins" updated the schema file (75-postfix-book-schema.ldif) in "/usr/share/ipa/schema.d" executed: "ipa-server-install"
The ipaserver-install log shows: 2022-06-04T12:10:57Z DEBUG [7/11]: updating schema 2022-06-04T12:10:57Z DEBUG Processing schema LDIF file /usr/share/ipa/schema.d/75-postfix-book-schema.ldif 2022-06-04T12:10:57Z DEBUG Not updating schema 2022-06-04T12:10:57Z DEBUG step duration: dirsrv __update_schema 0.21 sec 2022-06-04T12:10:57Z DEBUG [8/11]: upgrading server
So it says already "Not updating schema". I even run "ipa-server-upgrade" but it simply doesn't care about the schema, as it seems.
When I execute ldapsearch -o ldif-wrap=no -D 'cn=Directory Manager' -W -x -s base -b 'cn=schema' objectclasses | grep -I mail ldapsearch -o ldif-wrap=no -D 'cn=Directory Manager' -W -x -s base -b 'cn=schema' attributetypes | grep -i mail
My attributeTypes and objectClasses are therefore missing. I. even reverted the schema file back to the initial state and tried again, but same behaviour, it gets ignored. So what is the plugin approach doing more than the manual approach?
I went through the whole process, created rpm packages, created docker image, tested the rpm packages installation on the VM, same behaviour, same DEBUG message "... DEBUG Not updating schema". Tested the docker image on another VM with podman, same behaviour. So to answer my own question, the plugin approach is not doing anything more than the manual approach. I'm pretty much on the verge to give up on FreeIpa and switch to a simple openLDAP, this is getting out of control.
okay, empty lines in the schema caused this behaviour. I forgot abut that totally in Ldif files. Tested that back and forth and this is working now. The schema could be correct now (unsure about the two commented out attributeTypes).
So again placed all js, py and the schema under their given paths. Executed an ipa-server-install (the log looks good now) and tried to create a new user. I get the following error: " IPA Error 4001: NotFound no such entry "
I suspect either 1. The wrong usage of "add_missing_object_class" inside the python files e.g. in https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/main/plugin/ip...
2. The two commented out attributeTypes "mailQuota", "mailForwardingAddress" in the schema: https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/main/plugin/sc... I mean mailQuota and mailForwardingAddress exists in /usr/share/dirsrv/schema/50ns-mail.ldif. The question is, do I provide the mailQuota.js and mailQuota.py files (respectively mailForwardingAddress.js and mailForwardingAddress.py)? That's what I'm doing right now. As this schema is already implemented, maybe its js and py file is so, too, therefore they exists somewhere already? Also if I want to re-use them, I have to address that in a special secret way, which I don't know yet. This feels pretty much like the culprit here.
A little breakthrough, I removed all sub-plugins except "mailenabled". Commented out all attributeTypes within the ldif schema, just left mailEnabled and the objectClass, also removed all entries in the "MAY" field except "mailenabled".
" objectClasses: ( 1.3.6.1.4.1.29426.1.2.2.1 NAME 'postfixBookMailAccount' DESC 'Mail account used in Postfix Book' SUP top AUXILIARY MUST ( mail ) MAY ( mailEnabled ) ) "
I still had the same issue "IPA Error 4001: NotFound" when trying to create a user. I then saw the argument "update=True" on the "add_missing_object_class". So I set "update=False" in "mailenabled.py" on the useradd_precallback while leaving it as it is on the usermod_precallback. (I added the "u" prefix before the objectClass name but that's irrelevant anyway for python3, will leave it)
" def useradd_precallback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): add_missing_object_class(ldap, u'postfixbookmailaccount', dn, entry_attrs, update=False) return dn
user.user_add.register_pre_callback(useradd_precallback)
def usermod_precallback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): add_missing_object_class(ldap, u'postfixbookmailaccount', dn) return dn
user.user_mod.register_pre_callback(usermod_precallback) "
I can now finally create a user without having that error message. I will refactor the other python files and see if I can re-enable all of them.
There is still the issue, where the checkbox is not displaying the stored value when entering the details view. To answer your question from last time:
"ipa user-show" is showing that attribute like: " ... Account disabled: False Mail enabled: TRUE ... " A bit strange, don't know if this could cause some issues, but the value is "TRUE" all uppercase, while the others are written as "True". When doing an ldapsearch, I see it also on my user as: "mailEnabled: TRUE".
Any idea how to solve that loading stored values issue?
Sorry for spamming but looks like I'm almost done. At least no unexpected behaviour anymore. To sum it up:
1. MailEnabled checkbox not loading looks like a bug to me. Other fields like "mailAlias", "mailHomeDirectory" or even "mailAlias" work as expected. I can save a value and it will be loaded into the filed after entering the details view.
2. "mailAlias" is an interesting attributeType. It is used in both objectClases "postfixBookMailAccount" and "postfixBookMailForward": - https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5fba...
- https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5fba...
Does that mean for me, I have to use "add_missing_object_class(...)" for both objectClasses in its mailalias.py file? - https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5fba...
3. As "mailAlias" is mandatory according to the schema (see second link above, line 95 in "postfixBookMailForward" objectClass), how can I let it be generated like the regular "mail" field is generated? For example, "mail" is using "uid@domain", I think it would make sense to use "firstname.lastname@domain" for "mailAlias". I couldn't find the source code for the "mail" generation process.
4. Is there a way to say "mailAlias" values has to be unique across all users?
On su, 05 kesä 2022, Leo O via FreeIPA-users wrote:
A little breakthrough, I removed all sub-plugins except "mailenabled". Commented out all attributeTypes within the ldif schema, just left mailEnabled and the objectClass, also removed all entries in the "MAY" field except "mailenabled".
" objectClasses: ( 1.3.6.1.4.1.29426.1.2.2.1 NAME 'postfixBookMailAccount' DESC 'Mail account used in Postfix Book' SUP top AUXILIARY MUST ( mail ) MAY ( mailEnabled ) ) "
I still had the same issue "IPA Error 4001: NotFound" when trying to create a user. I then saw the argument "update=True" on the "add_missing_object_class". So I set "update=False" in "mailenabled.py" on the useradd_precallback while leaving it as it is on the usermod_precallback. (I added the "u" prefix before the objectClass name but that's irrelevant anyway for python3, will leave it)
" def useradd_precallback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): add_missing_object_class(ldap, u'postfixbookmailaccount', dn, entry_attrs, update=False) return dn
user.user_add.register_pre_callback(useradd_precallback)
The logic here should be to add an object class to entry_attrs in user_add's pre-callback directly. That's what 'update=False' is effectively doing because the entry at this point does not yet exist, pre-callback is called before entry is created in user_add.
def usermod_precallback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): add_missing_object_class(ldap, u'postfixbookmailaccount', dn) return dn
user.user_mod.register_pre_callback(usermod_precallback) "
I can now finally create a user without having that error message. I will refactor the other python files and see if I can re-enable all of them.
Please update your github repository.
There is still the issue, where the checkbox is not displaying the stored value when entering the details view. To answer your question from last time:
"ipa user-show" is showing that attribute like: " ... Account disabled: False Mail enabled: TRUE ... " A bit strange, don't know if this could cause some issues, but the value is "TRUE" all uppercase, while the others are written as "True". When doing an ldapsearch, I see it also on my user as: "mailEnabled: TRUE".
TRUE/FALSE in LDAP is correct (that's how boolean type is expected to behave). What is probably happening is that in IPA framework we don't properly convert to Python bool type and just return a string (TRUE or FALSE). This is worth a bug to be opened -- I can see this with other boolean attributes, like
Bool('idnsallowdynupdate?', cli_name='dynamic_update', label=_('Dynamic update'), doc=_('Allow dynamic updates.'), attribute=True, default=False, autofill=True ),
in 'ipa dnszone-show':
api.Command.dnszone_show('ipa.test')['result']['idnsallowdynupdate']
['TRUE']
This is because we don't have the reverse (from LDAP to Python) mapping for the LDAP boolean OID 1.3.6.1.4.1.1466.115.121.1.7.
When Web UI asks for the entry, it gets back JSON output that contains this 'TRUE' value:
"idnsallowdynupdate": [ "TRUE" ],
I suspect what happens next is that JavaScript-based parser of our JSON output is not converting it to boolean either. Instead, we work around it this way:
{ $type: 'radio', name: 'idnsallowdynupdate', options: [ { value: 'TRUE', label: '@i18n:true' }, { value: 'FALSE', label: '@i18n:false' } ] },
while for idnsallowsyncptr we do
{ $type: 'checkbox', name: 'idnsallowsyncptr' },
It is a mess. Please open a bug about boolean handling and I'll see to fix all these places too.
I guess I have caused a mess with the amount of emails sent.
So I will bring back in here the summed up points and also reply to your last mail.
Please update your github repository.
What do you mean? My repo has the latest source code changes, just no uploaded rpm packages. I haven't created a release yet, as I would like to solve the points 2, 3 and maybe 4 (see below). Bu if you need the packages, I can of course create and upload them, just let me know.
It is a mess. Please open a bug about boolean handling and I'll see to fix all these places too.
Bug was opened under: https://pagure.io/freeipa/issue/9171
So the first point is clear then and related to the submitted issue.
1. MailEnabled checkbox not loading looks like a bug to me. Other fields like "mailAlias", "mailHomeDirectory" or even "mailAlias" work as expected. I can save a value and it will be loaded into the filed after entering the details view.
2. "mailAlias" is an interesting attributeType. It is used in both objectClases "postfixBookMailAccount" and "postfixBookMailForward": https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5fba...
https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5fba...
Does that mean for me, I have to use "add_missing_object_class(...)" for both objectClasses in its mailalias.py file?
https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5fba...
3. As "mailAlias" is mandatory according to the schema (see second link above, line 95 in "postfixBookMailForward" objectClass), how can I let it be generated like the regular "mail" field is generated? For example, "mail" is using "uid@domain", I think it would make sense to use "firstname.lastname@domain" for "mailAlias". I couldn't find the source code for the "mail" generation process.
4. Is there a way to say "mailAlias" values has to be unique across all users?
On ma, 06 kesä 2022, Leo O via FreeIPA-users wrote:
I guess I have caused a mess with the amount of emails sent.
So I will bring back in here the summed up points and also reply to your last mail.
Please update your github repository.
What do you mean? My repo has the latest source code changes, just no uploaded rpm packages. I haven't created a release yet, as I would like to solve the points 2, 3 and maybe 4 (see below). Bu if you need the packages, I can of course create and upload them, just let me know.
When I looked at it earlier today, it looked to me as some of the changes discussed were missing. That was certainly a state on Saturday when I looked at it before being occupied by family matters.
It is a mess. Please open a bug about boolean handling and I'll see to fix all these places too.
Bug was opened under: https://pagure.io/freeipa/issue/9171
Thank you. I submitted https://github.com/freeipa/freeipa/pull/6294 to address it.
So the first point is clear then and related to the submitted issue.
- MailEnabled checkbox not loading looks like a bug to me. Other
fields like "mailAlias", "mailHomeDirectory" or even "mailAlias" work as expected. I can save a value and it will be loaded into the filed after entering the details view.
Without fixes from https://github.com/freeipa/freeipa/pull/6294, you'd need to use an approach taken by idnsallowdynupdate:
{ $type: 'radio', name: 'idnsallowdynupdate', options: [ { value: 'TRUE', label: '@i18n:true' }, { value: 'FALSE', label: '@i18n:false' } ] },
E.g. it forces to use a radio-box. The fixes from PR 6294 would be needed to use plain 'checkbox' type.
- "mailAlias" is an interesting attributeType. It is used in both objectClases "postfixBookMailAccount" and "postfixBookMailForward":
https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5fba...
https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5fba...
Does that mean for me, I have to use "add_missing_object_class(...)" for both objectClasses in its mailalias.py file?
You only need one class to allow an attribute. If you want to add either Account or Forward, it would probably be driven by a different logic -- e.g. whether the user entry would be a primary one or only a mail forward. I cannot help here -- it is pretty much your plugin's logic what to use here.
https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5fba...
- As "mailAlias" is mandatory according to the schema (see second link
above, line 95 in "postfixBookMailForward" objectClass), how can I let it be generated like the regular "mail" field is generated? For example, "mail" is using "uid@domain", I think it would make sense to use "firstname.lastname@domain" for "mailAlias". I couldn't find the source code for the "mail" generation process.
Use lambda or a function for a default_from attribute of the parameter. For example,
Str('cn', label=_('Full name'), default_from=lambda givenname, sn: '%s %s' % (givenname, sn), autofill=True, ),
If you need a bit more complex logic, then you'd need to use a helper function that is run as a part of the pre-callback. 'mail' attribute in user entries is handled this way:
Str('mail*', cli_name='email', label=_('Email address'), ),
...
normalize and validate email happens in a helper function:
def normalize_and_validate_email(self, email, config=None): if not config: config = self.backend.get_ipa_config()
# check if default email domain should be added defaultdomain = config.get('ipadefaultemaildomain', [None])[0] if email: norm_email = [] if not isinstance(email, (list, tuple)): email = [email] for m in email: if isinstance(m, str): if '@' not in m and defaultdomain: m = m + u'@' + defaultdomain if not Email(m): raise errors.ValidationError(name='email', error=_('invalid e-mail format: %(email)s') % dict(email=m)) norm_email.append(m) else: if not Email(m): raise errors.ValidationError(name='email', error=_('invalid e-mail format: %(email)s') % dict(email=m)) norm_email.append(m) return norm_email
return email
this helper is called from check_mail() helper:
def check_mail(self, entry_attrs): if 'mail' in entry_attrs: entry_attrs['mail'] = self.obj.normalize_and_validate_email(entry_attrs['mail'])
which, in turn, is called from the pre-callback of baseuser_mod class:
def pre_common_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): assert isinstance(dn, DN) add_sshpubkey_to_attrs_pre(self.context, attrs_list)
self.check_namelength(ldap, **options)
self.check_mail(entry_attrs)
self.check_manager(entry_attrs, self.obj.active_container_dn)
self.check_userpassword(entry_attrs, **options)
self.check_objectclass(ldap, dn, entry_attrs) self.obj.convert_usercertificate_pre(entry_attrs) self.preserve_krbprincipalname_pre(ldap, entry_attrs, *keys, **options) update_samba_attrs(ldap, dn, entry_attrs, **options)
and pre-callback of user_add calls it directly:
if 'mail' in entry_attrs: entry_attrs['mail'] = self.obj.normalize_and_validate_email(entry_attrs['mail'], config) else: # No e-mail passed in. If we have a default e-mail domain set # then we'll add it automatically. defaultdomain = config.get('ipadefaultemaildomain', [None])[0] if defaultdomain: entry_attrs['mail'] = self.obj.normalize_and_validate_email(keys[-1], config)
This complex behavior is because we have a lifecycle of user management, where user accounts can be active, staged, removed-and-stored, and so on, which puts different requirements for objects in different phases.
For your plugin a simple pre-callback that is added for both user_add and user_mod to validate or generate mail aliases should be enough.
- Is there a way to say "mailAlias" values has to be unique across all users?
This should be done at LDAP level. Your plugin needs to add a uniqueness constraint to LDAP, there is a well-defined method to do so.
For example, this is how POSIX account entry's 'uid' attribute uniqueness is defined:
----------------------------------------------------------- dn: cn=uid uniqueness,cn=plugins,cn=config default:objectClass: top default:objectClass: nsSlapdPlugin default:objectClass: extensibleObject default:cn: uid uniqueness default:nsslapd-pluginPath: libattr-unique-plugin default:nsslapd-pluginInitfunc: NSUniqueAttr_Init default:nsslapd-pluginType: preoperation default:nsslapd-pluginEnabled: on default:uniqueness-attribute-name: uid default:uniqueness-subtrees: $SUFFIX default:uniqueness-exclude-subtrees: cn=compat,$SUFFIX default:uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX default:uniqueness-across-all-subtrees: on default:uniqueness-subtree-entries-oc: posixAccount default:nsslapd-plugin-depends-on-type: database default:nsslapd-pluginId: NSUniqueAttr default:nsslapd-pluginVersion: 1.1.0 default:nsslapd-pluginVendor: Fedora Project default:nsslapd-pluginDescription: Enforce unique attribute values ------------------------------------------------------------
It uses a 389-ds plugin 'libattr-unique-plugin' that would look at 'uid' attribute values and ensure there are no two entries with the same 'uid' attribute value in there in $SUFFIX (dc=ipa,dc=test) subtree except two subtrees: - cn=compat,$SUFFIX, and - cn=staged users,cn=accounts,cn=provisioning,$SUFFIX subtree.
In those two subtrees it can have duplicates according to the plugin configuration because these are either generated to represent main objects in a different LDAP schema (compat tree) or are allowed to be present but not active (staged users).
For more details about the attribute uniqueness plugin see https://access.redhat.com/documentation/en-us/red_hat_directory_server/12/ht...
E.g. it forces to use a radio-box. The fixes from PR 6294 would be needed to use plain 'checkbox' type.
okay, I will leave it for now as checkbox, as the underlying ldap structure is more important to me atm than the UI.
You only need one class to allow an attribute. If you want to add either Account or Forward, it would probably be driven by a different logic -- e.g. whether the user entry would be a primary one or only a mail forward. I cannot help here -- it is pretty much your plugin's logic what to use here.
Hm, I don't know, to be honest. It is not obvious to me what that actually means, what the consequences are. So I can't do any logic decisions here. I mean the ldap schema is not something I created. It's a common postfix-book schema. The only modifications I made was to lowercase the first letters of the objectClasses (just that the naming style matches the other entries, shouldn't have any effect anyways) and commented out "mailQuota" and "mailForwardingAddress" attributeTypes as they exist already. I think I will remove the second "add_missing_object_class(ldap, u'postfixbookmailforward', dn)" completely from "mailalias.py". Somehow it doesn't feel correct.
Use lambda or a function for a default_from attribute of the parameter.
Lambda it is. It's enough for me, plus discovered these handy function like "lower()" and the object "api.env.realm". Tested this pretty nice function and it works as expected: "default_from=lambda givenname, sn: '%s.%s@%s' % (givenname.lower(), sn.lower(), api.env.realm.lower()),"
The unique attribute is something which causes some headache. I saw it also in here: https://directory.fedoraproject.org/docs/389ds/howto/howto-uid-uniqueness.ht...
1. Still don't know how to implement it, would I create it inside my plugins schema? But I can't just adapt the entries and throw them into the ldif file, can I? (commented out a few lines, unsure about the "default:" prefix in each line)
dn: cn=mailalias uniqueness,cn=plugins,cn=config default:objectClass: top default:objectClass: nsSlapdPlugin default:objectClass: extensibleObject default:cn: mailalias uniqueness default:nsslapd-pluginPath: libattr-unique-plugin default:nsslapd-pluginInitfunc: NSUniqueAttr_Init default:nsslapd-pluginType: preoperation default:nsslapd-pluginEnabled: on default:uniqueness-attribute-name: mailalias default:uniqueness-subtrees: $SUFFIX default:uniqueness-exclude-subtrees: cn=compat,$SUFFIX default:uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX default:uniqueness-across-all-subtrees: on default:nsslapd-plugin-depends-on-type: database #default:uniqueness-subtree-entries-oc: posixAccount #default:nsslapd-pluginId: NSUniqueAttr #default:nsslapd-pluginVersion: 1.1.0 #default:nsslapd-pluginVendor: Fedora Project #default:nsslapd-pluginDescription: Enforce unique attribute values ---------------------------------------------------------------------------------
But then a few questions came to my mind. 2. I'm using the lambda value to generate a mailAlias out of first name and last name. If I now create such a unique constraint, it would throw an error when creating a user with the same first name, last name, so it would't be possible to create a user at all. 2.a: I would have to either remove the default_value lambda mailAlias, make it optional. Which is not possible because then I get the error again: "missing attribute "mailAlias" required by object class "postfixBookMailForward"" Or 2.b: I don't use the unique constraint and therefore pushing the responsibility to a human person/ the admin to take care that the mail aliases stay unique. which brings me to 2.c: IIRC general emails like "webmaster@yourdomain.com" are used and put on multiple user accounts, if I'm not mistaken. Please correct me if I'm wrong. That would mean, I definitely should not use such a unique constraint on mail alias.
Puhhh, pure logical issues for that one, I still would like to hear your opinion about that. I tend to go with 2.b and let the admin create users (In case a user with the same first- and last name already exists, add a suffix to the generated mail alias). As this is a real edge case (especially if you plan to use that for 0 - 20 users), no need to create complex mail alias generating functions. Means, the current implementation is done and can be used.
Leo O via FreeIPA-users wrote:
E.g. it forces to use a radio-box. The fixes from PR 6294 would be needed to use plain 'checkbox' type.
okay, I will leave it for now as checkbox, as the underlying ldap structure is more important to me atm than the UI.
You only need one class to allow an attribute. If you want to add either Account or Forward, it would probably be driven by a different logic -- e.g. whether the user entry would be a primary one or only a mail forward. I cannot help here -- it is pretty much your plugin's logic what to use here.
Hm, I don't know, to be honest. It is not obvious to me what that actually means, what the consequences are. So I can't do any logic decisions here. I mean the ldap schema is not something I created. It's a common postfix-book schema. The only modifications I made was to lowercase the first letters of the objectClasses (just that the naming style matches the other entries, shouldn't have any effect anyways) and commented out "mailQuota" and "mailForwardingAddress" attributeTypes as they exist already. I think I will remove the second "add_missing_object_class(ldap, u'postfixbookmailforward', dn)" completely from "mailalias.py". Somehow it doesn't feel correct.
Use lambda or a function for a default_from attribute of the parameter.
Lambda it is. It's enough for me, plus discovered these handy function like "lower()" and the object "api.env.realm". Tested this pretty nice function and it works as expected: "default_from=lambda givenname, sn: '%s.%s@%s' % (givenname.lower(), sn.lower(), api.env.realm.lower()),"
The unique attribute is something which causes some headache. I saw it also in here: https://directory.fedoraproject.org/docs/389ds/howto/howto-uid-uniqueness.ht...
- Still don't know how to implement it, would I create it inside my plugins schema?
But I can't just adapt the entries and throw them into the ldif file, can I? (commented out a few lines, unsure about the "default:" prefix in each line)
dn: cn=mailalias uniqueness,cn=plugins,cn=config default:objectClass: top default:objectClass: nsSlapdPlugin default:objectClass: extensibleObject default:cn: mailalias uniqueness default:nsslapd-pluginPath: libattr-unique-plugin default:nsslapd-pluginInitfunc: NSUniqueAttr_Init default:nsslapd-pluginType: preoperation default:nsslapd-pluginEnabled: on default:uniqueness-attribute-name: mailalias default:uniqueness-subtrees: $SUFFIX default:uniqueness-exclude-subtrees: cn=compat,$SUFFIX default:uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX default:uniqueness-across-all-subtrees: on default:nsslapd-plugin-depends-on-type: database #default:uniqueness-subtree-entries-oc: posixAccount #default:nsslapd-pluginId: NSUniqueAttr #default:nsslapd-pluginVersion: 1.1.0 #default:nsslapd-pluginVendor: Fedora Project
#default:nsslapd-pluginDescription: Enforce unique attribute values
This is in the IPA "update" format which is ldif-like. You can either modify this to be a pure ldif, in a separate file from the schema, or as an IPA update file (recommended). For the latter you want to name it something like 10-postfix-uniqueness.update and install it in /usr/share/ipa/updates. It will get picked up automatically by ipa-server-upgrade.
You may want to consider adding an index for it as well if postfix will search on mailalias.
But then a few questions came to my mind. 2. I'm using the lambda value to generate a mailAlias out of first name and last name. If I now create such a unique constraint, it would throw an error when creating a user with the same first name, last name, so it would't be possible to create a user at all. 2.a: I would have to either remove the default_value lambda mailAlias, make it optional. Which is not possible because then I get the error again: "missing attribute "mailAlias" required by object class "postfixBookMailForward"" Or 2.b: I don't use the unique constraint and therefore pushing the responsibility to a human person/ the admin to take care that the mail aliases stay unique. which brings me to 2.c: IIRC general emails like "webmaster@yourdomain.com" are used and put on multiple user accounts, if I'm not mistaken. Please correct me if I'm wrong. That would mean, I definitely should not use such a unique constraint on mail alias.
Puhhh, pure logical issues for that one, I still would like to hear your opinion about that. I tend to go with 2.b and let the admin create users (In case a user with the same first- and last name already exists, add a suffix to the generated mail alias). As this is a real edge case (especially if you plan to use that for 0 - 20 users), no need to create complex mail alias generating functions. Means, the current implementation is done and can be used.
I don't know much about using LDAP to store mail aliases but I think you're right about 2b. Leave it up to the admin.
rob
@Alexander, @Rob thanks your time and help, it was a hell of a ride, I really appreciate it. I think I got pretty solid foundation right now, extended FreeIPA just a little bit, so I don't expect too much trouble on getting my plugin run on future FreeIPA releases. I will have to test it a bit more, but I think, as soon as the checkbox bug is resolved, I'm good to go.
For the other readers here, I've summed up the process in the readme, the source code can be found here: https://github.com/leonidas-o/freeipa-postfixbook-plugin
The container image can be found here: https://hub.docker.com/r/leonidaso/freeipa-server
Maybe that helps the next one, who is trying to extend FreeIPA or simply wants FreeIPA already extended with the postfix book schema.
Hello guys,
Inside my mailalias.py, I'm using: "default_from=lambda givenname, sn: '%s.%s@%s' % (givenname.lower(), sn.lower(), api.env.realm.lower()),"
Which pretty much blocks the user creation if the first- or last name contains a whitespace. Is there a function similar to "lower()", let's say a kind of "trim()" or anything else which removes whitespaces, or replaces them with a dash etc.?
Hi,
On Sat, Jun 18, 2022 at 1:43 PM Leo O via FreeIPA-users < freeipa-users@lists.fedorahosted.org> wrote:
Hello guys,
Inside my mailalias.py, I'm using: "default_from=lambda givenname, sn: '%s.%s@%s' % (givenname.lower(), sn.lower(), api.env.realm.lower()),"
Which pretty much blocks the user creation if the first- or last name contains a whitespace. Is there a function similar to "lower()", let's say a kind of "trim()" or anything else which removes whitespaces, or replaces them with a dash etc.?
It's a python question rather than an IPA one :) You can combine split and join like this: "".join(givenname.split())
split() without the sep parameter considers consecutive whitespaces as a single separator (see https://docs.python.org/3/library/stdtypes.html#string-methods) and join concatenates the items that were found in the previous step.
HTH, flo
_______________________________________________
FreeIPA-users mailing list -- freeipa-users@lists.fedorahosted.org To unsubscribe send an email to freeipa-users-leave@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/freeipa-users@lists.fedorahoste... Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure
freeipa-users@lists.fedorahosted.org