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.
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.
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.
2. "mailAlias" is an interesting attributeType. It is used
in both objectClases "postfixBookMailAccount" and
"postfixBookMailForward":
https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5...
https://github.com/leonidas-o/freeipa-postfixbook-plugin/blob/e0943c52fa5...
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/e0943c52fa5...
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.
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.
4. 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...
--
/ Alexander Bokovoy
Sr. Principal Software Engineer
Security / Identity Management Engineering
Red Hat Limited, Finland