[midPoint] My approach to FreeIPA server using LDAP Connector

Pálos Gustáv gustav.palos at gmail.com
Thu Mar 26 19:34:16 CET 2020


Hi,

We created a rest connector to manage users, groups, roles and memberships
to keep business login on FreeIPA site. If you need, we can publish it...

Best regards

Gustav

On Thu, 26 Mar 2020, 17:32 Wojciech Staszewski, <
wojciech.staszewski at diagnostyka.pl> wrote:

> My approach to FreeIPA server using LDAP Connector
>
> Assumptions:
>
> - FreeIPA v4.6.x (or maybe newer),
> - midPoint v3.9 or newer,
> - LDAP Connector v2.0 or newer,
> - Most important: Manage IPA users and group membership only.
>
> So, for those who don't know what FreeIPA (or IPA) server is: It is NOT a *free
> beer*! :(
> Link: https://www.freeipa.org/
>
> FreeIPA is a bunch of Open Source blocks stuck together, but the most
> important for us is LDAP, a 389-ds in particular, hidden under the mask.
> Another important piece is the Kerberos.
>
> Therefore the first thoughts is to use LDAP Connector. Well, there is
> dedicated IPA connector, but is dead I think, or at least its development
> is stalled long time ago.
>
> The challenge:
>
> - FreeIPA user account schema contains A LOT of ObjectClasses. Newly
> created IPA account has 14 ObjectClasses:
>
> objectClass: inetOrgPerson
> objectClass: ipaObject
> objectClass: mepManagedEntry
> objectClass: posixGroup
> objectClass: top
> objectClass: inetuser
> objectClass: ipaNTUserAttrs
> objectClass: ipaObject
> objectClass: ipaSshGroupOfPubKeys
> objectClass: ipaSshUser
> objectClass: krbPrincipalAux
> objectClass: krbTicketPolicyAux
> objectClass: mepOriginEntry
> objectClass: posixAccount
>
> - LDAP Connector doesn't like many object classes. Why?, you may ask...
>
> Example: ipaNTUserAttrs ObjectClass REQUIRES some attributes, for
> instance: ipaNTSecurityIdentifier provided in the format below:
> S-1-5-21-17112102435-2119056689-2123461762-1015
> The last part: "1015" is an incremental number, everything before is
> constant.
> The attribute value must be compound, we have constant first part and
> calculate next free number for the last part, so we have to read the max
> value from LDAP and increase it by 1.
> This value MUST be known at the moment of account creation. The DNA plugin
> is good for simple tasks, such POSIX UID and GID calculation, but this is
> something we have to calculate ourselves.
>
> There is a lot of problems like that.
> I tried to configure the LDAP resource to set the "inetOrgPerson" as
> default ObjectClass and all the rest as auxiliary object classes, and I
> failed because of so many different errors.
>
> Working solution:
>
> - The LDAP account has only one ObjectClass defined in midPoint Schema
> Handling.
>   All the rest is made using "scripting" functionality of the connector
> AFTER "create account" operation.
>
> Problem:
> If the account is created, and THEN its schema is extended, some requied
> attributes are still missing,
> for example "krbExtraData" and "krbPrincipalKey" which are binary data
> created during password change.
> But the password is already set.
>
> So creation of an LDAP account for IPA must be done in 3 steps:
> 1. create LDAP account with inetOrgPerson ObjectClass only,
> 2. extend the account schema - add missing ObjectClasses and all required
> attributes (scripting functionality),
> 3. set the password again for the missing Kerberos data (scripting
> functionality).
>
> The account created this way works good, it is visible in FreeIPA User
> Interface, we can login to our Linux boxes using this account, Kerberos
> tickets work OK.
>
> MidPoint part:
>
> 1) Resource XML
>
> Almost everything is standard for common LDAP resource, schema handling,
> mappings, etc. - nothing really sophisticated.
> These are some the parts worth mentioning:
>
> <icfc:configurationProperties>
>             <objectClassesToSynchronize>top</objectClassesToSynchronize>
>             <objectClassesToSynchronize>person</objectClassesToSynchronize>
>
> <objectClassesToSynchronize>organizationalPerson</objectClassesToSynchronize>
>
> <objectClassesToSynchronize>inetUser</objectClassesToSynchronize>
>
> <objectClassesToSynchronize>inetOrgPerson</objectClassesToSynchronize>
> </icfc:configurationProperties>
>
> <schema>
>         <generationConstraints>
>             <generateObjectClass>ri:top</generateObjectClass>
>             <generateObjectClass>ri:person</generateObjectClass>
>
> <generateObjectClass>ri:organizationalPerson</generateObjectClass>
>             <generateObjectClass>ri:inetUser</generateObjectClass>
>             <generateObjectClass>ri:inetOrgPerson</generateObjectClass>
>             <generateObjectClass>ri:ipaNTUserAttrs</generateObjectClass>
>             <generateObjectClass>ri:ipaObject</generateObjectClass>
>
> <generateObjectClass>ri:ipaSshGroupOfPubKeys</generateObjectClass>
>             <generateObjectClass>ri:ipaSshUser</generateObjectClass>
>             <generateObjectClass>ri:krbPrincipalAux</generateObjectClass>
>
> <generateObjectClass>ri:krbTicketPolicyAux</generateObjectClass>
>             <generateObjectClass>ri:mepOriginEntry</generateObjectClass>
>             <generateObjectClass>ri:posixAccount</generateObjectClass>
>             <generateObjectClass>ri:groupOfNames</generateObjectClass>
>             <generateObjectClass>ri:ipaNTGroupAttrs</generateObjectClass>
>             <generateObjectClass>ri:ipaUserGroup</generateObjectClass>
>             <generateObjectClass>ri:nestedGroup</generateObjectClass>
>             <generateObjectClass>ri:posixGroup</generateObjectClass>
>             <generateObjectClass>ri:ipaHostGroup</generateObjectClass>
>             <generateObjectClass>ri:ipaPermission</generateObjectClass>
>         </generationConstraints>
> </schema>
>
> <schemaHandling>
>             <!-- Allmost all attributes require "explicit"
> fetchStrategy!!! -->
>             <...>
>             <fetchStrategy>explicit</fetchStrategy>
>             </...>
> </schemaHandling>
>
> <scripts>
>         <script>
>             <host>connector</host>
>             <language>Groovy</language>
>             <argument>
>                 <name>username</name>
>                 <c:path xmlns:xsi=
> "http://www.w3.org/2001/XMLSchema-instance"
> <http://www.w3.org/2001/XMLSchema-instance>
> xsi:type="t:ItemPathType">$focus/name</c:path>
>             </argument>
>             <argument>
>                 <name>pass</name>
>                 <c:path xmlns:xsi=
> "http://www.w3.org/2001/XMLSchema-instance"
> <http://www.w3.org/2001/XMLSchema-instance>
> xsi:type="t:ItemPathType">$focus/credentials/password/value</c:path>
>             </argument>
>             <code>
>                println "/opt/midpoint/scripts/freeipa/after_add.sh
> $username $pass".execute().text</code>
>             <operation>add</operation>
>             <order>after</order>
>         </script>
> </scripts>
>
> 2) The Bash script:
>
> #!/bin/bash
>
> server='ipaserver.ipa.domain.ltd'
> user='cn=Directory Manager'
> password='LDAP PASSWORD'
> basedn='dc=ipa,dc=domain,dc=ltd'
> userid=$1
> pass=$2
>
> #last value for ipaNTSecurityIdentifier
> declare i ipaNTSecurityIdentifier=`ldapsearch -H ldap://$server -x -w
> $password -D "$user" -b "$basedn" '(objectClass=inetOrgPerson)'
> ipaNTSecurityIdentifier|grep ipaNTSecurityIdentifier|rev|cut -d "-" -f
> 1|rev|sort|tail -1`
>
> nextNTSecurityIdentifier=S-1-5-21-1453210229-2669001626-2403961664-$(($ipaNTSecurityIdentifier+1))
>
> #last UID i GID - Posix
> declare i olduid=`ldapsearch -H ldap://$server -x -w $password -D "$user"
> -b "$basedn" '(objectClass=inetOrgPerson)' uidNumber|grep uidNumber|cut -d
> " " -f 2|tail -1`
> NEWUID=$(($olduid+1))
> declare i oldgid=`ldapsearch -H ldap://$server -x -w $password -D "$user"
> -b "$basedn" '(objectClass=inetOrgPerson)' gidNumber|grep gidNumber|cut -d
> " " -f 2|tail -1`
> NEWGID=$(($oldgid+1))
>
> cat > /tmp/ipa_add_group_$userid.ldif <<EOF
> dn: cn=$userid,cn=groups,cn=accounts,$basedn
> objectClass: ipaObject
> objectClass: mepManagedEntry
> objectClass: posixGroup
> objectClass: top
> cn: $userid
> gidNumber: $NEWGID
> description: User private group for $userid
> mepManagedBy: uid=$userid,cn=users,cn=accounts,$basedn
> EOF
>
> /usr/bin/ldapmodify -h $server -x -w $password -D "$user" -a -f
> /tmp/ipa_add_group_$userid.ldif
>
>
>
> cat > /tmp/ipa_add_$userid.ldif <<EOF
> dn: uid=$userid,cn=users,cn=accounts,$basedn
> changetype: modify
> add: objectClass
> objectClass: inetuser
> -
> add: objectClass
> objectClass: ipaNTUserAttrs
> -
> add: objectClass
> objectClass: ipaObject
> -
> add: objectClass
> objectClass: ipaSshGroupOfPubKeys
> -
> add: objectClass
> objectClass: ipaSshUser
> -
> add: objectClass
> objectClass: krbPrincipalAux
> -
> add: objectClass
> objectClass: krbTicketPolicyAux
> -
> add: objectClass
> objectClass: mepOriginEntry
> -
> add: objectClass
> objectClass: posixAccount
> -
> add: homeDirectory
> homeDirectory: /home/$userid
> -
> add: loginshell
> loginshell: /bin/bash
> -
> add: ipaNTSecurityIdentifier
> ipaNTSecurityIdentifier: $nextNTSecurityIdentifier
> -
> add: uidNumber
> uidNumber: $NEWUID
> -
> add: gidNumber
> gidNumber: $NEWGID
> -
> add: krbCanonicalName
> krbCanonicalName: $userid at IPA.DOMAIN.LTD
> -
> add: krbPrincipalName
> krbPrincipalName: $userid at IPA.DOMAIN.LTD
> -
> add: preferredLanguage
> preferredLanguage: YourLangHere
> -
> add: gecos
> gecos: $userid
> -
> add: mepManagedEntry
> mepManagedEntry: cn=$userid,cn=groups,cn=accounts,$basedn
> EOF
>
> /usr/bin/ldapmodify -h $server -x -w $password -c -D "$user" -f
> /tmp/ipa_add_$userid.ldif
>
> # Change password once again!
> cat > /tmp/ipa_password_$userid.ldif <<EOF
> dn: uid=$userid,cn=users,cn=accounts,$basedn
> changetype: modify
> replace: userPassword
> userPassword: $pass
> EOF
>
> /usr/bin/ldapmodify -h $server -x -w $password -c -D "$user" -f
> /tmp/ipa_password_$userid.ldif
>
> rm -f /tmp/ipa_add_$userid.ldif
> rm -f /tmp/ipa_add_group_$userid.ldif
> rm -f /tmp/ipa_ipausers_$userid.ldif
> rm -f /tmp/ipa_password_$userid.ldif
>
> ##########
> If you know the better way, please let me know.
> Best Regards!
> WS
> _______________________________________________
> midPoint mailing list
> midPoint at lists.evolveum.com
> https://lists.evolveum.com/mailman/listinfo/midpoint
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.evolveum.com/pipermail/midpoint/attachments/20200326/5cdce0e5/attachment.htm>


More information about the midPoint mailing list