User_Life-Cycle_Management#
Overview#
Corporate or big setups of Identity Management system often requires an advanced user life-cycle management capabilities (like staging area for new or deleted users) or standard LDAP interface for adding or removing users that can be used by provisioning systems.
Use Cases#
External Provisioning System#
User Story#
As an Administrator, I want to configure my employee provisioning system to manipulate the employee records to FreeIPA via LDAP protocol using standard LDAP objectclasses, so that I do not have to request FreeIPA specific integration with my provisioning system vendor.
Description#
The following supported workflows are expected:
Create a user: provisioning system adds user to staging tree are using standard LDAP add. Not all fields that standard FreeIPA user has need to be specified. Provisioning system may or may not use the Freeipa CLI to add the user.
Activate user: activate user by moving it from staging area to active user area. All attributes required by FreeIPA are generated if they are missing. All activations of a user accounts must be done on the same server, else it can leads to replication issues as attribute uniqueness can reject some operation.
Assign group memberships: add group membership to activated user. Membership can only be added in active users tree. Staged or deleted users have no membership information.
Update user: modify user attributes
Change password: administratively change user password
Delete user: move user from active user tree to staging tree to keep it’s attributes (like UID) and settings in case the user returns back and need to be restored
Restore deleted user: move deleted user back to the tree of active users
Lock user: temporarily lock user so that it is not accessible
Unlock user: unlock temporarily locked user
Privilege Separation for Employee Entry and Activation#
User Story#
As an Administrator, I want to allow Human Resources Administrators to add future employees to FreeIPA and in the same time I do not want to allow them activating them, so that I can delegate that privilege to my Security Administrator after the employee credentials are verified on the first day of employment.
Design#
User status#
In User Life Cycle, a user account is stored in a LDAP repository as an entry in the DIT. A user account follows a workflow that changes the status of the user. There are 3 differents status:
Stage
This is an initial state where some of the user properties may not be already set
In this state the user account can not be used to authenticate.
The ldap entry of a user account is stored: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
The staging container usually contains few user account that represent the few new comers in the organisation.
Active
This is the normal state where all necessary properties are set
In this state the user account can be used to authenticate (if user is enabled)
The ldap entry of a user account is stored: cn=users,cn=accounts,$SUFFIX
The active container contains hundreds/tousands user accounts that represent all the people currently in the organisation.
Delete
This is the state of deleted active user account. Most of its properties have been preserved. Unpreserved properties are for example membership properties that have been reset
The user account can not be used to authenticate
The ldap entry of a user account is stored: cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX
The deleted container contains hundreds/tousands user accounts that represent all the people who left the organisation.
The deleted container preserves former users to conform legacy, law and policies. It can help to recover user properties in case a former user returns back to the organization.
Active account
in addition to active user, a special container contains all the active accounts. Accounts are not only users
the ldap entry of active accounts is stored: cn=accounts,$SUFFIX
workflows#
The main workflow allows moves: stage --> active <--> delete
stage -> active: The appropriate set of approvals are granted and a new comer is now fully operational in the organisation
active -> delete: The user leaves temporary the organisation
delete -> active: The user join back the organisation and recover some of his previous settings
The workflow allows to recreate a user if the entry gets corrupted:
delete -> stage: The entry got corrupted and was deleted. Moving it back to ‘ Stage ‘ the entry can later be activated again. The following FreeIPA attribute are preserved: ‘ ipaUniqueID ‘ , ‘ uidNumber ‘ and ‘ gidNumber ‘.
The workflow allows to add user accounts in:
stage: the user needs some approval before being active
active: the user does not need any approval before being active
The workflow allows to delete user accounts from:
staging: The user account will never receive the approval in order to be active
delete: The user will never join back the organisation
Note: delete action will erase permanently the entry from the repository. It is a LDAP DEL.
The workflow allows to modify user account from:
stage: modify the user account that remains in stage
active: modify the user account that remains in active
-- find ---+ -- find --+
-- show ---+ -- show --+
-- add-----+ |
-- mod ----+ |
| |
V V
------------------- ---------------- ---------------
-- find --> | | | | | |
--- mod --> | | | | | |
--- add --> | | --- activate --> | | --- delete --> | |
<-- delete -- | STAGE | | ACTIVE | <-- undelete -- | DELETE | -- delete ->
| | | | | |
| <plg. stageuser>| | <plg user> | | <plg. user> |
-- show --> | | | | | |
------------------- ---------------- ---------------
^ /
\ /
----------------------- add (from-delete opt.) ---------------------
stageuser plugin#
Add a stage entry#
Support engineer can use the following command
ipa stageuser-add <user_identifier> –first=<first name> –last=<last name>
ipa stageuser-add tuser --first=test --last=user
if needed, command may specify more details about the user, including the password
ipa stageuser-add tuser --first=Test --last=User --random --manager=muser --phone 123456789
ipa stageuser-add supports almost the same options as user-add, but compare to user-add here is the list of differences:
noprivate: no supported as a stage entry has no private group
manager: must be an active user
Filled with placeholders the entry will look like
dn: uid=tuser,cn=staged users,cn=accounts,cn=provisioning,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalperson
objectClass: posixAccount
cn: Test User
sn: User
uid: tuser
uidNumber: -1
gidNumber: -1
homeDirectory: /home/tuser
loginShell: autogenerate
A stage user can also be created from a former user. There is still discussion (see 1 and 2 ) if the former user can be picked up from the ‘Delete’ container or from the ‘Active’ container or both.
Currently the proposed interface are
stageuser-add <uid> --from-delete
or
user-undel <uid> --to-stage
or
user-unactivate <uid>
The drawback of the first CLI (stageuser-add) is that lastname/firstname are required option, but when the ‘uid’ entry is taken from the ‘Delete’ container lastname/firstname are useless.
Provision stage entry#
As described in the first Use case, provisioning systems (external) create the vast majority of Stage entries (using or not the FreeIPA CLI).
Provisioned entries MUST follow the following rules
Provisioning system places a staged user entry to cn=staged users,cn=accounts,cn=provisioning,SUFFIX
Entry RDN attribute is ‘ uid ‘ (see Supported Staged entries)
Entry may contain both data and placeholders. Note that when the entry will become active, some of the data/placeholders may be changed.
Provisoning system can create an entry with few constraints, that mean that the activation of a stage entry must be done with care. So provisioning systems is the main justification why activation will be done using a ADD-DEL approach
A Stage entry does not need to have all attributes that standard FreeIPA user has. In order to allow the correct processing of User Life Cycle, staged users must have a minimal set of attributes
dn: uid=tuser,cn=staged users,cn=accounts,cn=provisioning,dc=example,dc=com
objectClass: top
objectClass: inetOrgPerson
cn: Test User
sn: User
uid: tuser
Activate StageUser#
Activating a user is a major step in the User Life Cycle. It allows FreeIPA to start managing the entry and the user to authenticate with it. This action is only authorised to Support Engineer.
Support Engineer is using FreeIPA CLI: ipa stageuser-activate <user_identifier>
ipa stageuser-activate tuser
The CLI supports only one account ID (no series of accounts can be activated in a row)
This operation ‘moves’ the entry, using LDAP ADD on the destination entry then DEL on the source entry
Source: cn=staged users,cn=accounts,cn=provisioning,SUFFIX
Destination: cn=users,cn=accounts,SUFFIX
Error handling
ADD fails, the source entry is preserved and the CLI reports an error
if DEL fails, the destination entry is removed and the CLI reports an error. If it fails to delete destination entry, both entries will remain. This is not a concern as the Stage entry will never be activated as long as the destination entry exists and have the same uid.
The destination Active LDAP entry is a NEW entry compare to the source Stage entry (see MODRDN vs ADD-DEL)
It contains all FreeIPA required objectclasses/attributes (including structural objectclasses) (comment: TBL in implementation)
Unsupported objectclasses/attributes present in the Stage entry have been removed
The destination Active LDAP entry is a NEW entry (LDAP ADD). The source Stage entry may contain userPassword in an hashed way (see http://www.freeipa.org/page/V4/User_Life-Cycle_Management#Staging_entry stored password). To allow the storing of pre-hashed password ipa-pwd-extop:ipapwd_pre_add must relax its control for example if the krb keys already exists in the entry.
Stage container is out of the scope of uid uniqueness plugin, so the destination entry can be added even if the source entry still exists
Active and Delete containers are in scope of uid uniqueness plugin, so destination entry can not be added if it already exists an Active or Delete entry with the same RDN (‘uid’) value. For example, it exists jdoe Active or Delete entry that contains several uid values. The entry jdoe has been created by a provisioning system, in fact Regular Freeipa CLI do not create user entry with multiple uid. foo can not be Activate because jdoe already have the uid: foo value:
dn: uid=foo,cn=staged users,cn=accounts,cn=provisioning,SUFFIX
...
uid: foo
dn: uid=jdoe,cn=users,cn=accounts,cn=provisioning,SUFFIX
...
uid: jdoe
uid: foo
or if it exists a Delete entry that already have the ‘’uid: foo value:
dn: uid=foo,cn=staged users,cn=accounts,cn=provisioning,SUFFIX
...
uid: foo
dn: uid=jdoe,cn=deleted users,cn=accounts,cn=provisioning,SUFFIX
...
uid: jdoe
uid: foo
There are ajustments of DN syntax attributes
MODRDN vs. ADD-DEL
When a staged user is moved to active users tree or an active user is
moved to deleted users tree, there are 2 possible approaches -
renaming (LDAP MODRDN operation with defining newsuperior
attribute) and moving the LDAP object (LDAP ADD and DEL operations).
In the end, the result will the same for outer world, but the operation
will affect DS internals and plugin function.
Renaming operation is a better approach from atomicity point of view (second, delete opration may fail and there would be 2 duplicate entries), but it may interfere with both internal DS plugin (referential integrity, memberOf, manged entry plugin) and 3rd party plugins. They may tend to keep all DN links to the entry unless they are modified not to do so when such entry is moved to deleted tree.
Moving operation seems cleaner approach as all these plugins (including current plugins) will understand the operation in the right semantics. However, it is more difficult to control (see related tickets) and ability to move a user from staging tree to active users tree would require ability to read and write all user attributes, including
userPassword
.
Provisioning system does not guarantee to create the stage entry with the appropriate set of structural objectclasses (see Activating staged user. The active entry requires all the FreeIPA structural objectclasses/attributes. It can be addressed:
Adding in the stage entry each missing objectclasses/attributes - Remove the unwanted objectclasses/attributes
Create a new entry with all the required objectclasses/attributes and fill it from values taken in the stage entry
A stage entry is possibly partially initialized (especially with provisioning systems), using MODRDN means that this incomplete entry becomes active and one can bind with it (if credential are set). So some MODs are needed to make it a valid entry, before we can issue the MODRDN.
The second approach is chosen solution because:
it allows to (see this thread ‘Supported Stage entries’ )
filter objectclasses/attributes set in the Stage entry but the admin do not want to see in Active. When filling the new entry we just need to skip the no wished values/attributes.
add objectclasses/attributes necessary for Active entries. The new entry contains by default all required OC/Attribute, we need to pick values from the Stage entry
guaranty that structural objectclasses are present
It is most simplest solution to implement.
Adjustment of DN syntax attributes
A Stage or Delete user entry may contains DN syntax attributes. Referential integrity plugin is not checking the validity of the DN in those containers, so they may contain invalid values. When an Active entry is deleted (user-del), most of the its DN syntax attributes are replaced with empty values except for manager/managedby/secretary that are preserved.
A Stage entry may contain any values in its DN syntax attributes.
When an entry becomes Active (userstage-activate or user-undel) the values of DN syntax attributes need to be checked. The value is preserved if it is the DN of an Active entry, else it is replaced with an empty value. (see this thread)
Update StageUser#
Support engineer uses standard FreeIPA calls to modify user attributes (including password)
ipa stageuser-mod tuser --phone=123456789
ipa stageuser-mod supports the same options as user-mod, but more control are done when updating a stage user.
manager must be an active user
nsaccountlock can not be set. Its value is forced to be True by a COS
Delete StageUser#
Support engineer deletes the stage user using the following CLI
ipa stageuser-del <user identifier>
stageuser-del
triggers LDAP delete operation on LDAP stage entry that deletes it permanently
Restore StageUser#
``Support engineer can restore a Delete user (under cn=deletedusers,cn=accounts,cn=provisioning,SUFFIX). Delete user contains properties of a former user. If some of the properties are corrupted, it may be not acceptable to ``\ ```restoreandactivate`` <http://www.freeipa.org/page/V4/User_Life-Cycle_Management#Restore_Deleted_User>`__\ `` a Delete user. Stepping the entry into Stage allows to keep valid properties and update the corrupted ones before making the user Active.``
Support engineer restore the user using the following CLI
ipa stageuser-add –from-preserved
Find StageUser#
authenticate user can find an Stage account with
ipa stageuser-find [] []
ipa stageuser-find supports the same options as user-find except the flag –preserved=<true|false because stageuser-find only deal with Stage accounts (not Delete or Active)
ipa stageuser-find
---------------
2 users matched
---------------
User login: kau1
Home directory: /home/kau1
UID: 181818
GID: 181818
Password: True
Kerberos keys available: False
User login: xy2
First name: x
Last name: y
Home directory: /home/xy2
Login shell: /bin/sh
Email address: xy2@domain.com
UID: -1
GID: -1
Password: False
Kerberos keys available: False
----------------------------
Number of entries returned 2
----------------------------
Show StageUser#
authenticate user can show an Stage account (entry uid=LOGIN,cn=staged users,cn=accounts,cn=provisioning,$SUFFIX)
ipa stageuser-show <LOGIN>
user plugin#
Add an active user#
Support Engineer has permission to add active users using the following FreeIPA CLI : ipa user-add <user_identifier> –first=<first name> –last=<last name>
ipa user-add tuser --first=test --last=user
provisioning systems has not the permission to add active user (they are only allowed to add Stage entries)
if needed, command may specify more details about the user
ipa user-add tuser --first=Test --last=User --manager=muser --phone 123456789
if password is specfies, to allow FreeIPA generate Kerberos keys, the following modifications occur
add krbprincipalaux objectclass and krbPrincipalName attribute
When the entry will be added FreeIPA plugin generates krbPrincipalKey, krbLastPwdChange and krbPasswordExpiration which will allow the user to authenticate by Kerberos
The active user entry looks like
dn: uid=test_user, cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
objectClass: top
objectClass: person
objectClass: organizationalperson
objectClass: inetorgperson
objectClass: inetuser
objectClass: posixaccount
objectClass: krbprincipalaux
objectClass: krbticketpolicyaux
objectClass: ipaobject
objectClass: ipasshuser
objectClass: ipaSshGroupOfPubKeys
homeDirectory: /home/tuser
uidNumber: 646400009
gidNumber: 646400009
ipaUniqueID: 3f1b5cce-e1b8-11e3-86fe-001a4a104ecd
nsAccountLock: yes
uid: test_user
cn: first last
sn: last
givenName: first
gecos: first last
displayName: first last
loginShell: /bin/sh
mail: test_user@domain.com
krbPrincipalName: test_user@domain.com
initials: tu
Assign Group Memberships (already available)#
Support engineer uses standard FreeIPA calls to assign membership
ipa group-add-member testgroup --user tuser
This command is only available on ‘Active’ entries. When a ‘Stage’ entry containing memberOf attribute is Activate, the memberOf attribute is not preserved and membershift is recomputed .
Update User (already available)#
Support engineer uses standard FreeIPA calls to modify user attributes (including password)
ipa user-mod tuser --phone=123456789
Regular user uses standard FreeIPA CLI calls to modify its own entry (including password)
Standard FreeIPA CLI does not allow to modify
:* ipaUniqueID
:* objectclass
When updating DN syntax attributes (like –manager option) , if the entry is not an Active entry the modification fails.
Change Password (already available)#
Support engineer uses standard FreeIPA calls to change user password:
ipa passwd tuser
Regular user uses same CLI to modify the password of its own entry
Delete User#
Once activated a user is fully managed by freeIPA. If the user leaves the company, his account can be permanently removed (deleting the ldap entry) or moved (modrdn) to a ‘Delete’ container (cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX) in order to preserve it.
ipa user-del tuser [[--no-preserve][--preserve]]
Option –no-preserve and –preserve are mutually exclusive. The default option is –no-preserve. A configuration attribute could decide what is the default option (see global policy)TBD
If the entry was preserved (moved to Delete container), it can be deleted (permanently) with the same command.
Both Active/Delete containers are under uid attribute uniqueness. So for a give value val, it exists either uid=val,cn=accounts,$SUFFIX or uid=val,cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX. So when the Support engineer decides to delete a user, he does not need to specify if the user is in Delete or Active state.
delete (Permanently) of an active entry
This is done by a direct ldap delete of the entry.
all references to the entry are removed. That is done by referential integrity and memberof that scope Active containers.
delete (preserve) of an active entry
removes credential attributes
userPassword
and kerberors keys (krbPrincipalKey, krbLastPwdChange and krbPasswordExpiration) attributes to prevent any chance of using that entry to bind to LDAP serversave manager/managedby/secretary that may get cleared when the entry will be moved to Delete container
LDAP MODRDN operation on LDAP entry to move the entry (discussed 1 and 2 and 3)
Source: cn=users,cn=accounts,SUFFIX Destination: cn=deleted users,cn=accounts,cn=provisioning,SUFFIX
all references to the entry must be removed. That is done by referential integrity and memberof that only scope Active containers.
Replace others existing DN syntax attributes with an Empty
DN syntax attributes contains reference to entries. When the user entry is in Delete container, it is no longer in the scope of integrity plugin and then may contain invalid values (Note: is it usefull ? attribute covered by RI have been cleared on MODRDN, attribute not covered may be checked during activation rather than clearing them)
removing the attribute may not be possible if it is required by the schema. So the attribute will be kept with an Empty value.
restore manager/managedby/secretary with the original values
Some attributes are preserved, so that a corrupted active entry can get deleted/staged/activate and keep its previous settings
ipaUniqueID
uidNumber
gidNumber
delete (Permanently) of a Delete entry
This is done by a direct ldap delete of the entry.
Restore Deleted User#
Once activated a user is fully managed by freeIPA. If the user leaves the company, his account is moved to a ‘Delete’ Status and is hold in a separated container (cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX). Both Active/Delete containers are under uid attribute uniqueness. So for a give value val, if the entry was delelte (uid=val,cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX) it does not exists uid=val,cn=accounts,$SUFFIX.
Once deleted a user entry still contains some properties that are specific to the former user. The user account may becomes Active again,
Support engineer call the following command
ipa user-undel tuser
user-undel triggers LDAP MODRDN operation on LDAP entry to move the entry (appropriate aci allows only support engineer to move the entry)
Source: cn=deleted users,cn=accounts,cn=provisioning,SUFFIX Destination: cn=users,cn=accounts,SUFFIX DS plugin will recompute the memberbship attributes and will add nsAccountLock: True
There is ajustments of DN syntax attributes
Lock User (already available)#
Support engineer uses standard FreeIPA call:
ipa user-disable tuser
nsAccountLock
operation attribute is put toTRUE
, user cannot bind to LDAP. Membership and password attributes are preservedOnly Active account can be locked/disabled
Unlock User (already available)#
Support engineer uses standard FreeIPA call:
ipa user-enable tuser
nsAccountLock
operation attribute is put toFALSE
, user operation is restoredOnly Active account can be unlocked/enabled
Find User#
authenticate user can find an Active account (Active container cn=users,cn=accounts,$SUFFIX) with
ipa user-find [] []
a new flag –preserved=true is used to find the entries from the Delete container (cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX)
by default or if the flag is –preserved=false it only lookup into the Active container
In addition if the retrieved entry is preserved it displays a flag: Preserved user: True
prompt> ipa user-find --preserved=true
--------------
1 user matched
--------------
User login: xy2
First name: x
Last name: y
Home directory: /home/xy2
Login shell: /bin/sh
Email address: xy2@domain.com
UID: 1337000003
GID: 1337000003
Account disabled: True
Preserved user: True
Password: False
Kerberos keys available: False
----------------------------
Number of entries returned 1
----------------------------
Show User#
authenticate user can show an Active account (entry uid=LOGIN,cn=users,cn=accounts,$SUFFIX)
ipa user-show <LOGIN> []
This command can retrieve Active or Deleted account. If the returned account is delete account, it displays a flag: Preserved user: True
prompt> ipa user-show xy2
User login: xy2
First name: x
Last name: y
Home directory: /home/xy2
Login shell: /bin/sh
Email address: xy2@domain.com
UID: 1337000003
GID: 1337000003
Account disabled: True
Preserved user: True
Password: False
Kerberos keys available: False
Placeholders#
When an entry is created using FreeIPA CLI user-add, the value of the required attributes need to be specify somewhere. Usually it is provided using the CLI options or if absent CLI uses some default values.
A provisioning system when creating an entry needs to provide all required attribute or to modify the CLI to adapt the default values. That is not really flexible.
In addition with User Life Cycle, an entry will follow a workflow that means that some require attribute value may be unknown at some point of the flow and defined later. If a new plugin is developed to generate the value, it requires to adapt CLI options/default value.
Instead of that we will use placeholders. A placeholder is added to the entry and contains an initial value (waiting for its final value to be set). A placeholder is couple attribute/value that defines the default value of a given attribute. The placeholders definitions will be stored under the FreeiPa configuration under the following entries:
# placeholders for ADD entries
dn: cn=placeholders,cn=ipaConfig,cn=etc,$SUFFIX
cn: placeholders
objectClass: top
objectClass: extensibleObject
# placeholders for ADDed entries in staging
dn: cn=stage,cn=placeholders,cn=ipaConfig,cn=etc,$SUFFIX
cn: stage
objectClass: top
objectClass: extensibleObject
<attrname>: <value>
...
#placeholders for ADDed entries in active
dn: cn=active,cn=placeholders,cn=ipaConfig,cn=etc,$SUFFIX
cn: active
objectClass: top
objectClass: extensibleObject
<attrname>: <value>
...
Syntax#
attribute name is : ALPHA *(ALPHA / DIGIT / HYPHEN)
The value of the placeholder may be used in different attribute types with different syntaxes, they should follow the most restrictive syntax. In case of LDAP, it should follow Printable String syntax (also see RFC 4517):
PrintableCharacter = ALPHA / DIGIT / SQUOTE / LPAREN / RPAREN /
PLUS / COMMA / HYPHEN / DOT / EQUALS /
SLASH / COLON / QUESTION / SPACE
PrintableString = 1*PrintableCharacter
Mechanism#
When creating an entry, the CLI picks up all definitions found in the placeholders (of the container) and add them to the entry. There is no modification of the value from what is in the placeholder definition.
An exception is if the placeholder value starts and finishes with ‘ ? ‘, then CLI strip ‘ ? ‘ from the value before adding it (i.e. placeholder value is ‘?autogenerate?’ -> added value is ‘autogenerate’).
Priority#
When an entry is created the attribute value is taken in the following order:
CLI option
placeholder
CLI default value
That means that if the attribute value is defined as a CLI option it selects it and the possible values in placeholder or default value are ignored. Else if the placeholder attribute exists in the placeholders entry it selects the placeholder value and the possible default value is ignored. Else it selects the default values.
Limitation - Future enhancement#
A placeholder allows an entry to conform the schema. In that purpose it is sufficient to define a single value for a required attribute. If a placeholder defines multiple values for an attribute, there is no guaranty that all the values will be added in the entry.
As futur enhancement, we can imagine a placeholder being defined with: homeDirectory: /home/net/%{uid}. In that case for user ‘uid=tuser’, the added value for homeDirectory will be /home/net/tuser
Staging container#
Staging tree#
Core part of the feature is to allow provisioning system to add or
delete users with standard LDAP protocol without a need to understand or
use FreeIPA API. Standard tree of active FreeIPA users
(cn=users,cn=accounts,$SUFFIX
) is not used to avoid collisions or
misinterpretation of active and staged users by other IdM systems.
Staging tree should have the following structure:
SUFFIX
cn=provisioning
cn=accounts
cn=staged users
: new staged users
Staging Users in a Special Database#
Stage user container is separated from the Active container. A question is to store the containers in separated database or keep them in the same database protected by special ACIs. Both approaches have pros and cons.
Pros
Is naturally separated from standard FreeIPA objects, no need to re-configure existing plugins (like attribute uniqueness or memberOf plugin) to ignore users in the staging area
Easier management in heterogeneous environment when some FreeIPA replicas have the feature and and some does not
Cons
Increased maintenance burden with multiple LDAP databases
Increased maintenance burden with replication agreements of the new database
Staging Users in a Normal Suffix (preferred)#
Pros
IdM systems are kept idempotent - command to activate a user or moving it to deleted users tree can be done against any FreeIPA server.
No need to manage new databases or replication agreements
Cons
Staging or deleted users container may interfere with normal users in the
cn=users,cn=accounts,$SUFFIX
in older FreeIPA replicas. Even though the tree is not visible by standard users due to ACIs, it is still visible by plugins.during upgrade from a old instance, the Staging/deleted containers will be created if they do not already exists. The use of COS to disable potential already existing stage/deleted entry will prevent to authenticate with them.
Running in a topology with different versions, will require that the ACI, containers are replicated
Stage placeholders#
The placeholders for the staging container are:
# placeholders for ADD entries
dn: cn=placeholders,cn=ipaConfig,cn=etc,$SUFFIX
cn: placeholders
objectClass: top
objectClass: extensibleObject
# placeholders for ADDed entries in staging
dn: cn=stage,cn=placeholders,cn=ipaConfig,cn=etc,$SUFFIX
cn: stage
objectClass: top
objectClass: extensibleObject
uidNumber: -1
gidNumber: -1
ipaUniqueId: ?autogenerate?
nsAccountLock: yes
Stage entry requirements#
This container can contain entries coming from
external provisioning systems
stageuser CLI (stageuser-add)
Delete entries
The common requirements from these origins are
entry must conform the schema
Entry RDN attribute is ‘ uid ‘ (see Supported Staged entries)
entry is disabled (i.e. contains operational attribute ‘nsAccountLock: True’)
ipaUniqueID is set to autogenerate. This requirement is not enforced for provisioning systems (but for stageuser CLI) but if an entry have a different value its value will be reset during activation of the Stage entry (stageuser-activate). (see ipaUniqueID reset)
Example of Stage entry (provisioning origin)#
In addition to the common requirements above, the entry may contains any objectclasses/attributes
Example of Stage entry (stageuser-add)#
A staged entry created with FreeIPA CLI is looking like the following:
dn: uid=test_user, cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
objectClass: top
objectClass: person
objectClass: organizationalperson
objectClass: inetorgperson
objectClass: inetuser
objectClass: posixaccount
objectClass: krbprincipalaux
objectClass: krbticketpolicyaux
objectClass: ipaobject
objectClass: ipasshuser
objectClass: ipaSshGroupOfPubKeys
homeDirectory: /home/tuser
uidNumber: -1
gidNumber: -1
ipaUniqueID: autogenerate
nsAccountLock: yes
uid: test_user
cn: first last
sn: last
givenName: first
gecos: first last
displayName: first last
loginShell: /bin/sh
mail: test_user@domain.com
krbPrincipalName: test_user@domain.com
initials: tu
In case CLI option/placeholder do not define them, the entries in staging will contains those default values:
uid
: generated from first letter ofcn
andsn
givenName
: generated fromcn
by removing the last part of the namedisplayName
: copied fromcn
initials
: first letter ofcn
, first letter ofsn
homeDirectory
: default value defined in FreeIPA configurationgecos
: copied fromcn
loginShell
: default value defined in FreeIPA configurationmail
: generated from uid and default domain defined in FreeIPA configurationkrbPrincipalName
: generate from uid and kerberos realm defined in FreeIPA configuration
The way those values are generated is hardcoded in the CLI core.
Example of Stage entry (stageuser-undel)#
A staged entry that is created from a former Delete entry mainly differs from an entry created by stageuser-add because the following attributes:
uidNumber (with value different from -1)
gidNumber (with value different from -1)
ipaUniqueID (with value different from autogenerate)
dn: uid=test_user, cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
objectClass: top
objectClass: person
objectClass: organizationalperson
objectClass: inetorgperson
objectClass: inetuser
objectClass: posixaccount
objectClass: krbprincipalaux
objectClass: krbticketpolicyaux
objectClass: ipaobject
objectClass: ipasshuser
objectClass: ipaSshGroupOfPubKeys
homeDirectory: /home/tuser
uidNumber: 646400009
gidNumber: 646400009
ipaUniqueID: 3f1b5cce-e1b8-11e3-86fe-001a4a104ecd
nsAccountLock: yes
uid: test_user
cn: first last
sn: last
givenName: first
gecos: first last
displayName: first last
loginShell: /bin/sh
mail: test_user@domain.com
krbPrincipalName: test_user@domain.com
initials: tu
Active container#
Active tree#
Active entries are under cn=users,cn=accounts,SUFFIX
Active Placeholders#
The placeholders for the Active container are:
# placeholders for ADD entries
dn: cn=placeholders,cn=ipaConfig,cn=etc,$SUFFIX
cn: placeholders
objectClass: top
objectClass: extensibleObject
# placeholders for ADDed active entries
dn: cn=active,cn=placeholders,cn=ipaConfig,cn=etc,$SUFFIX
cn: active
objectClass: top
objectClass: extensibleObject
uidNumber: -1
gidNumber: -1
ipaUniqueId: ?autogenerate?
uidNumber
: value generated by FreeIPA DNA plugin, based on the defined UID range of the servergidNumber
: copied from uidNumberipaUniqueId
(final value generated by FreeIPA IPA UUID plugin)
Active entry requirements#
The requirements for active entries are
entry must conform the schema
entry RDN is uid
entry is enabled (nsAccountLock: False or absent)
entry is a objectclass: posixAccount and contains the following required attributes
uidNumber (final value generated by FreeIPA DNA plugin)
gidNumber (final value generated by FreeIPA DNA plugin)
ipaUniqueId (final value generated by FreeIPA IPA UUID plugin)
homeDirectory (generated from default FeeIPA configuration cn=ipaConfig,cn=etc,$SUFFIX)
uid/cn (generated from the CLI)
Example of Active entry (user-add)#
The freeipa CLI creates an entry like:
dn: uid=test_user, cn=users,cn=accounts,SUFFIX
objectClass: top
objectClass: person
objectClass: organizationalperson
objectClass: inetorgperson
objectClass: inetuser
objectClass: posixaccount
objectClass: krbprincipalaux
objectClass: krbticketpolicyaux
objectClass: ipaobject
objectClass: ipasshuser
objectClass: ipaSshGroupOfPubKeys
homeDirectory: /home/tuser
uidNumber: 646400009
gidNumber: 646400009
ipaUniqueID: 3f1b5cce-e1b8-11e3-86fe-001a4a104ecd
nsAccountLock: yes
uid: test_user
cn: first last
sn: last
givenName: first
gecos: first last
displayName: first last
loginShell: /bin/sh
mail: test_user@domain.com
krbPrincipalName: test_user@domain.com
initials: tu
memberOf: cn=ipausers,cn=groups,cn=accounts,SUFFIX
Delete container#
Delete tree#
Delete entries are under cn=deleted users,cn=accounts,cn=provisioning, SUFFIX
Delete placeholders#
N/A No entry are added in the Delete container
Delete entry requirements#
A Delete entry was create with user-del and conform the following requirements
entry must conform the schema
entry RDN is uid
entry is disabled (nsAccountLock: True)
entry is a objectclass: posixAccount and contains the at least the following required attributes
uidNumber (value different from -1)
gidNumber (value different from -1)
ipaUniqueId (value different from autogenerate)
homeDirectory
uid
cn
entry has no ‘memberof’ attribute
Example of Delete entry#
A entry in Delete container is looking like
dn: uid=test_user, cn=deleted users,cn=accounts,cn=provisioning,SUFFIX
objectClass: top
objectClass: person
objectClass: organizationalperson
objectClass: inetorgperson
objectClass: inetuser
objectClass: posixaccount
objectClass: krbprincipalaux
objectClass: krbticketpolicyaux
objectClass: ipaobject
objectClass: ipasshuser
objectClass: ipaSshGroupOfPubKeys
homeDirectory: /home/tuser
uidNumber: 646400009
gidNumber: 646400009
ipaUniqueID: 3f1b5cce-e1b8-11e3-86fe-001a4a104ecd
nsAccountLock: yes
uid: test_user
cn: first last
sn: last
givenName: first
gecos: first last
displayName: first last
loginShell: /bin/sh
mail: test_user@domain.com
krbPrincipalName: test_user@domain.com
initials: tu
nsAccountLock: True
Authentication#
Authentication is not allowed with Stage and Delete entries. Authentication can be done with simple bind or through an external mechanism (like GSSAPI).
Staging entry#
A first idea to prevent this authentication was to prevent credentials (password / krb keys) creation in both stageuser-add/stageuser-mod. But this is not enough because provisioning system can create entries with userPassword and then allow simple bind. For kerberos authentication, it requires kerberos keys that are generated from a plain text password. userPassword being stored in an hashed way, we can not generate kerberos keys from a stored password. kerberos keys need to be generated when the userPassword is set (see https://www.redhat.com/archives/freeipa-devel/2014-June/msg00462.html credential). So if a stage entry receives a userPassword then kerberos keys need to be generated as well. That means:
stageuser-add / staguser-mod must support –password option
ipa-pwd-extop DS plugin must scope Stage container.
To prevent authentication from Stage entry, we can use two methods:
using a COS (likely a pointer COS), that overwrite the nsAccountLock operational attribute.nsAccountLockis added to anActiveentry when we need to disable (user-disable) it. It prevents simple bind as well as kerberos authentication. It is quite easy to implement (likely in the.updates’’ files). A drawback is to use a DS opertional attribute to do this.
using a pre-op DS plugin, that would reject bind (simple or SASL) on Stage and Delete containers. It is a bit more complex solution and requires a new deliverable.
The COS solution will be use because it seems good enough without major drawback
Active entry#
Authentication is allowed with an Active entry (as long as it owns credential).
If this is a newly activated (stageuser-activate) entry it owns credentials (userpassword/krb) at the condition userPassword was set in the staging area. To activate such entry it requires a change in ipa-pwd-extop to relax the setting of pre-hashed password.
If this is a newly undelete (“user-undelete”) entry, credentials have been removed. So it is not possible to authenticate with it before the userPassword (user-mod –password) is set (and krb keys generated).
If this is a True new user (user-add), it is possible to authenticate with it at the condition it has userPassword and kerberos keys
Delete entry#
Authentication is not allowed with Delete entry. Delete entries are kept for legal or regulation reasons but they may become Active (user-undelete) or Stage (stageuser-add) again. In that case we do not want to preserve any credential because they are likely too old and we want the user to assign again new credential.
So when deleting (user-delete) an Active entry, kerberos keys must be cleared. Password attribute must be cleared as well at the exception of passwordHistory. passwordHistory will prevent the user to reuse one of password it used when the entry was Active.
Permissions and ACIs#
New permissions should be created:
Add Staged Users
Delete Staged Users
Modify Staged Users
Read Staged Users
Discard Deleted Users
Modify Deleted Users
Read Deleted Users
Add Deleted Users permission is needed as this operation would be done by new DS plugin.
New privilege should be created:
Staged User Administrators: should contain all permissions listed above
Staged User Provisioning: should contain Add Staged Users permission
Following roles should be updated:
User Administrator: should contain Staged User Administrators privilege
Allow Moving Staged Users Only#
We cannot distinguish a situation when a new user is added and when a
user is moved (copied) from staged or deleted tree. Both require
add access control on
cn=staged users, cn=accounts,cn=provisioning,SUFFIX
tree. It is
therefore difficult to allow helpdesk people only moving an entry from
staged tree and not allowing creating a new random user.
The stageuser-activate command selects a stage user and “move” it to the active container. The stage user attributes/values may be not appropriated to because a true operational active user. The command prepares a new user entry, taking the existing values from the stage user and the check them, fills the required (for active user) values that are missing from the stage entry. So the “helpdesk” people will not move entry but always create new user from one the example stored in the staging container.
User life cycle do not “move” entries (LDAP moddn) but create valid user and delete stage user/preserved user.
Moving Users from Staging Tree Automatically#
By default, new staged users are moved to active user area manually, by
running a specified user-add
command. However, some deployments may
want to active users automatically. This operation should be done
periodically using a custom script run on one chosen server (to prevent
race unexpected conditions when more servers are activating staged
users).
Proposed Script Workflow#
kinit as a special user (with keytab)
With
user-find
, search for all staged usersFor each new staged user:
Activate user with
user-add
, log result
Affected Directory Server Plugins#
Active FreeIPA plugins that are active in any user-related operation need to be checked or updated, to avoid interference with users in staged or deleted tree, namely:
DNA plugin#
This plugin is reponsible to update uidNumber and gidNumber attribute. If those attributes have a predefined value (dnaMagicRegen: -1), then the plugin generate a new value and replace -1 value with it. This plugin should not update values of Stage and Delete entries. so DNA plugin should exclude cn=provisioning,SUFFIX (relies on 47828) from its scope set to:
dn: cn=Posix IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
...
dnaScope: $SUFFIX
dnaExcludeScope: cn=provisioning,$SUFFIX
dnaMagicRegen: -1
dnaFilter: (|(objectClass=posixAccount)(objectClass=posixGroup)(objectClass=ipaIDobject))
The following possibilities were evaluated but did not work:
dnaScope: cn=accounts,$SUFFIX. This is not possible because freeipa trust requires cn=trusts,SUFFIX (see trusted domains)
dnaFilter: (&(|(objectClass=posixAccount)(objectClass=posixGroup)(objectClass=ipaIDobject))(!(entrydn=*cn=provisioning)))*. This is not possible because entrydn is not present in the added entry when the DNA preop-plugin is called (see filter entrydn)
trusts domain is sharing the same DS config entry for cn=Posix IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config (because it needs the same IPA range). So having a different DNA config entry (i.e. “cn=Trust IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config’’ is not an option)
krbPrincipalName uniqueness#
This plugin is reponsible to enforce the uniqueness of an krbPrincipalName value in Active and Delete containers. So that a given value of krbPrincipalName is unique in both Delete and Active containers together
This is important the krbPrincipalName remains unique as for regulation, law or policy we need to be able to uniquely identify a user (Active or not) with his krbPrincipalName
Active and Delete containers are under separated subtrees (see attribute uniqueness). In order to check simultaneous (requires 47823) both container the plugin configuration contains:
dn: cn=krbPrincipalName uniqueness,cn=plugins,cn=config
...
nsslapd-pluginAllSubtrees: on
nsslapd-pluginAttributeName: krbPrincipalName
nsslapd-pluginContainerScope: cn=accounts,SUFFIX
nsslapd-pluginContainerScope: cn=deleted users,cn=accounts,cn=provisioning,SUFFIX
uniqueness-across-all-subtrees: on
krbCanonicalName uniqueness#
For the same reasons as krbPrincipalName, we apply the following configuration
dn: cn=krbCanonicalName uniqueness,cn=plugins,cn=config
...
nsslapd-pluginAllSubtrees: on
nsslapd-pluginAttributeName: krbCanonicalName
nsslapd-pluginContainerScope: cn=accounts,SUFFIX
nsslapd-pluginContainerScope: cn=deleted users,cn=accounts,cn=provisioning,SUFFIX
uniqueness-across-all-subtrees: on
uid uniqueness#
For the same reasons as krbPrincipalName, we apply the following configuration
nsslapd-pluginAllSubtrees: on
nsslapd-pluginAttributeName: uid
nsslapd-pluginContainerScope: cn=accounts,SUFFIX
nsslapd-pluginContainerScope: cn=deleted users,cn=accounts,cn=provisioning,SUFFIX
uniqueness-across-all-subtrees: on
ipaUniqueID uniquness#
For the same reasons as krbPrincipalName, we apply the following configuration
dn: cn=ipaUniqueID uniqueness,cn=plugins,cn=config
...
nsslapd-pluginAllSubtrees: on
nsslapd-pluginAttributeName: ipaUniqueID
nsslapd-pluginContainerScope: cn=accounts,SUFFIX
nsslapd-pluginContainerScope: cn=deleted users,cn=accounts,cn=provisioning,SUFFIX
uniqueness-across-all-subtrees: on
Stage container is not part of the scope because first provisioning system can set any values and stageuser-add CLI creates entries with the same value autogenerate
Referential integrity#
This plugin scopes Active account (nsslapd-pluginContainerScope and nsslapd-pluginEntryScope). To correctly update the reference in entries it requires that an Active account (A) refers only Active accounts (B) (This is a requirement enforced during stageuser-active, user-undel, user-mod, user-add). If it follow that requirements then:
entry B is deleted (LDAP DEL) => entry A is updated removing B DN
entry B is moved (MODRDN) in Active container => entry A is updated with the new DN
entry B is moved (MODRDN) out of Active container (user-del) => entry A is updated removing B DN
If an Active account does not follow this requirement, Active account A refers an external entry B ( in Stage or Delete or elsewhere), then the entry A may get corrupted
entry B is deleted (LDAP DEL) => entry A is NOT modified
entry B is moved (MODRDN) in Active container => entry A is updated with the new B DN
entry B is moved (MODRDN) out of Active container => entry A is NOT modified
The configuration of this plugin is :
dn: cn=referential integrity postoperation,cn=plugins,cn=config
...
nsslapd-pluginContainerScope: cn=accounts,SUFFIX
nsslapd-pluginEntryScope: cn=accounts,SUFFIX
MemberOf plugin#
MemberOf plugins excludes Active and Delete containers that are both under cn=provisioning,SUFFX (config attribute memberofentryscopeexcludesubtree). Like described in referential integrity if an Active account is member of a group and the account is deleted
RI remove the (member) account from the group
MemberOf plugin removes memberof from the account for the group
the configuration of this plugin is:
dn: cn=MemberOf Plugin,cn=plugins,cn=config
..
memberofentryscope: SUFFIX
memberofentryscopeexcludesubtree: cn=provisioning,SUFFIX
Managed Entries plugin#
When a new Active entry is created (ADD or MODRDN), it creates a managed entry and adds mepManagedEntry to the entry. When an Active entry is deleted (MODRDN or DEL), the managed entry is removed and mepManagedEntry
So configuration of that
dn: cn=NGP Definition,cn=Definitions,cn=Managed Entries,cn=etc,SUFFIX
...
originscope: cn=hostgroups,cn=accounts,SUFFIX
dn: cn=UPG Definition,cn=Definitions,cn=Managed Entries,cn=etc,SUFFIX
...
originscope: cn=users,cn=accounts,SUFFIX
When a stage entry is created/deleted it is not in under originscope, so no managed entry is added/delete. This is the expected behaviour. When a stage entry is activated, it is deleted from the stage container and added into the Active container. When it is added to the Active container, it falls under the scope of mep plugin and its managed entry is created. Here again this is the expected behavior.
When an Active entry is deleted (permanently (del) or move (modrdn) from the Active container), its associated managed entry is deleted. This is the expected behavior.
In conclusion, the current configuration of the mep plugin does not need to be change because of user life cycle.
IPA UUID plugin#
This plugin excludes Stage and Delete entries (ipaUuidExcludeSubtee) from generation of ipaUniqueID (if the current value is autogenerate (ipauuidmagicregen)). Delete entries (user-del) will keep the value of ipaUniqueID.
The configuration of that plugin is
dn: cn=IPA Unique IDs,cn=IPA UUID,cn=plugins,cn=config
...
ipaUuidExcludeSubtree: cn=provisioning,SUFFIX
Schema Compatibility plugin#
should not be affected as it is already focused on
cn=users, cn=accounts, SUFFIX
tree only TBC
IPA MODRDN plugin#
This plugin make sure that a targetattribute (krbPrincipaLName) is composed of a sourceattribute (RDN) (uid) and a given suffix. For example uid=foo,cn=accounts,SUFFIX will have krbPrincipalName: foo@.
Scoping the plugin to the full SUFFIX mean that Stage and Delete entries will be updated if the sourceattribute is modified. It is not strictly necessary, but it makes sense that any provisioning entry (even Stage) conforms the same rules as Active.
So this plugin scope will not be restricted to Active entries but to the full SUFFIX.
ipa-kdb#
Stage and Delete entries should not contain valid kerberos keys. Now to be sure Stage or Delete are not used for kerberos authentication, ipa-kdb should ignore users in staged or deleted
ipa-pwd-extop#
This plugin should scope Stage and Active containers. In fact both Stage and Active container may receive userpassword (see authenticate) This plugin should allow the storing of pre-hashed password ipa-pwd-extop:ipapwd_pre_add must relax its control for example if the krb keys already exists in the entry (see user-activate)
Future enhancements#
Deletion of active user#
When using the FreeIPA CLI user-del, the entry is moved (MODRDN) from the Active container to the Delete container. If the authorized person, issue LDAP DEL (outside of FreeIPA framework) on an active user the entry will be deleted permanently from the database and its properties lost. It could be interesting to implement a new preop DS plugin, which would intercept the LDAP delete operation and move the Active entry to the Delete container.
Implementation#
http://www.freeipa.org/page/V3/User_Life-Cycle_Management/Implementation Implementation details still need to be defined. Consider this section as a work in progress.
FreeIPA tickets#
389 Directory Server tickets#
Scoping of plugins#
#47527: Allow referential integrity suffixes to be configurable (fixed 1.3.2.8)
#47621: make referential integrity configuration more flexible (exclude subtree) (fixed 1.3.2.9)
#47525: Allow memberOf to use an alternate config area (fixed 1.3.3)
#47526: Allow memberOf suffixes to be configurable (fixed 1.3.2.8)
#47829: memberof scope: allow to exclude subtrees (fixed 1.3.3)
#47828: DNA scope: allow to exlude some subtrees
others#
Feature Management#
UI
When user provisioning is enabled, add new tab to Identity section - Staged Users. There should be 2 user sections:
List of staged users. Ability to make the staged user active
List of deleted users. Ability to make the deleted user active and move either to staged or active users area.
In IPA Server section, Configuration tab, there should be a new section User Life-Cycle Management with configuration options described in section #Major configuration options and enablement.
CLI
user-add#
New option
--from-staged=tuser
: activates user specified by it’s primary key in the staged treeNew option
--to-staged
: creates a new user in the staging treeNew option
--staged-pkey=uid
: optional, defines alternative primary key of the staged user.uid
is the defaultNew option
--from-deleted=tuser
: specifies primary key of the deleted user to be activated
user-find#
New option
--staged
: lists staged users instead of active usersNew option
--deleted
: lists deleted users instead of active users
user_provisioning_is_enabled#
Returns TRUE if cn=provisioning
exists. Will be used by Web UI to
find out if the feature is enabled or not.
config-mod#
New config options described in section #Major configuration options and enablement
Major configuration options and enablement#
Following global user configuration options should be implemented:
ipaStagedUserNumericMagic
: placeholder for generation of user value for numeric attribute types. Default is -1ipaStageDeletedUser
: move deleted users to deleted users tree instead of deleting them permanently. Default is FALSE
Replication#
cn=provisioning
subtree should be replicated.
Given number of affected plugin configuration described in section
#Affected Directory Server
Plugins we should consider
moving configuration of some of these plugins from cn=config
to
replicated tree to enable easier changes in the configuration.
Attribute uniqueness will scope Active and Delete containers. In order to prevent replication issue, all activation (stageuser-activate) of user account should be done on the same server.
Updates and Upgrades#
Feature should not be enabled by default, but after running a
configuration script ipa-advanced-provisioning-install
. The script
should:
Check if all replicas are of the current FreeIPA version. If not, it should end with error stating that the feature may have negative impact on the older FreeIPA versions. There should be a
--force
option to overcome this limitation.When check is successful or
--force
flag is used:Create
cn=provisioning
structureAdd new schema and config options
Add new ACIs, permissions, privileges and roles
Add new Directory Server plugins
Restart Directory Server
Heterogeneous Environment#
If there is an environment with FreeIPA servers supporting the feature and olded FreeIPA servers, there may be issues with the life-cycle management, like:
When user delete operation is run against an older FreeIPA server, it is not copied to deleted users tree
Staged or deleted users in
cn=provisioning
tree may interfere with older FreeIPA and it’s DS plugins.
External Impact#
Changes in 389 Directory Server and slapi-nis packages will be required.
How to Test#
External Provisioning System#
Adding New User#
In following example, we will simulate adding new Stage User by provisioning system using the standard inetorgperson objectclass, without using any FreeIPA specific attribute.
Add Stage User with ldapmodify:
# ldapmodify -Y GSSAPI
SASL/GSSAPI authentication started
SASL username: admin@RHEL72
SASL SSF: 56
SASL data security layer installed.
dn: uid=stageuser,cn=staged users,cn=accounts,cn=provisioning,dc=rhel72
changetype: add
objectClass: top
objectClass: inetorgperson
cn: Stage
sn: User
adding new entry "uid=stageuser,cn=staged users,cn=accounts,cn=provisioning,dc=rhel72"
Show it’s all attributes (see that the account is explicitly disabled by nsaccountlock attribute):
# ipa stageuser-show stageuser --all --raw
dn: uid=stageuser,cn=staged users,cn=accounts,cn=provisioning,dc=rhel72
uid: stageuser
sn: User
cn: Stage
has_password: FALSE
has_keytab: FALSE
nsaccountlock: TRUE
objectClass: top
objectClass: inetorgperson
objectClass: organizationalPerson
objectClass: person
Activate the Stage User (may be also done by other admin, with System: Add Users permission):
# ipa stageuser-activate stageuser
------------------------------
Stage user stageuser activated
------------------------------
User login: stageuser
First name: Stage
Last name: User
Full name: Stage
Home directory: /home/stageuser
Login shell: /bin/sh
Kerberos principal: stageuser@RHEL72
UID: 626000004
GID: 626000004
Show the resulting activated user which has all the FreeIPA specific attributes generated:
# ipa user-show stageuser --all --raw
dn: uid=stageuser,cn=users,cn=accounts,dc=rhel72
uid: stageuser
givenname: Stage
sn: User
cn: Stage
homedirectory: /home/stageuser
loginshell: /bin/sh
uidnumber: 626000004
gidnumber: 626000004
nsaccountlock: FALSE
has_password: FALSE
has_keytab: FALSE
ipaUniqueID: 48a58be2-dc67-11e5-b93e-001a4a23140a
krbPrincipalName: stageuser@RHEL72
memberof: cn=ipausers,cn=groups,cn=accounts,dc=rhel72
mepManagedEntry: cn=stageuser,cn=groups,cn=accounts,dc=rhel72
objectClass: ipaobject
objectClass: person
objectClass: top
objectClass: ipasshuser
objectClass: inetorgperson
objectClass: organizationalperson
objectClass: krbticketpolicyaux
objectClass: krbprincipalaux
objectClass: inetuser
objectClass: posixaccount
objectClass: ipaSshGroupOfPubKeys
objectClass: mepOriginEntry
Activating Users Automatically#
Alternatively, if the Provisioning System does not have any means of calling the API operation and you do not want to do it manually, you can also setup a cron call (example for Fedora) that would periodically kinit with a keytab of a service allowed to add users, search for staged users and activating them.
Original situation:
# ipa stageuser-find
---------------
2 users matched
---------------
User login: bar
First name: bar
Last name: bar
Home directory: /home/bar
Login shell: /bin/sh
Email address: bar@rhel72.test
UID: -1
GID: -1
Password: False
Kerberos keys available: False
User login: foo
First name: foo
Last name: bar
Home directory: /home/foo
Login shell: /bin/sh
Email address: foo@rhel72.test
UID: -1
GID: -1
Password: False
Kerberos keys available: False
----------------------------
Number of entries returned 2
----------------------------
The automated activation task example that can be used in cron script:
# kinit -kt service.keytab activator/ipa.provisioning.system.rhel72.test
# for x in `ipa stageuser-find | grep "User login:" | cut -d":" -f 2`; do
ipa stageuser-activate $x;
done
------------------------
Stage user bar activated
------------------------
User login: bar
First name: bar
Last name: bar
Full name: bar bar
Display name: bar bar
Initials: bb
Home directory: /home/bar
GECOS: bar bar
Login shell: /bin/sh
Kerberos principal: bar@RHEL72
Email address: bar@rhel72.test
UID: 626000005
GID: 626000005
------------------------
Stage user foo activated
------------------------
User login: foo
First name: foo
Last name: bar
Full name: foo bar
Display name: foo bar
Initials: fb
Home directory: /home/foo
GECOS: foo bar
Login shell: /bin/sh
Kerberos principal: foo@RHEL72
Email address: foo@rhel72.test
UID: 626000006
GID: 626000006
Deleting a User#
When a user account is deleted permanently, Provisioning System should simply issue LDAP DEL operation. When the user account is to be preserved, it just needs to be moved to specific container.
Preserving a user can be done with CLI/API call:
# ipa user-find
...
User login: fbar
First name: Foo
Last name: Bar
Home directory: /home/fbar
Login shell: /bin/sh
Email address: foo@rhel72.test
UID: 626000001
GID: 626000001
Account disabled: False
Password: True
Kerberos keys available: True
User login: stageuser
First name: Stage
Last name: User
Home directory: /home/stageuser
Login shell: /bin/sh
UID: 626000004
GID: 626000004
Account disabled: False
Password: False
Kerberos keys available: False
...
# ipa user-del fbar --preserve
-------------------
Deleted user "fbar"
-------------------
# ipa user-find --preserved=1
--------------
1 user matched
--------------
User login: fbar
First name: Foo
Last name: Bar
Home directory: /home/fbar
Login shell: /bin/sh
Email address: foo@rhel72.test
UID: 626000001
GID: 626000001
Account disabled: True
Preserved user: True
Password: False
Kerberos keys available: False
----------------------------
Number of entries returned 1
----------------------------
The preserved user is automatically disabled and can no longer authenticate.
Second option is to preserve the user via LDAP MODRDN command directly:
# ldapmodify -Y GSSAPI
SASL/GSSAPI authentication started
SASL username: admin@RHEL72
SASL SSF: 56
SASL data security layer installed.
dn: uid=stageuser,cn=users,cn=accounts,dc=rhel72
changetype: modrdn
newrdn: uid=stageuser
deleteoldrdn: 0
newsuperior: cn=deleted users,cn=accounts,cn=provisioning,dc=rhel72
modifying rdn of entry "uid=stageuser,cn=users,cn=accounts,dc=rhel72"
# ipa user-find --preserved=1
---------------
2 users matched
---------------
User login: fbar
First name: Foo
Last name: Bar
Home directory: /home/fbar
Login shell: /bin/sh
Email address: foo@rhel72.test
UID: 626000001
GID: 626000001
Account disabled: True
Preserved user: True
Password: False
Kerberos keys available: False
User login: stageuser
First name: Stage
Last name: User
Home directory: /home/stageuser
Login shell: /bin/sh
UID: 626000004
GID: 626000004
Account disabled: True
Preserved user: True
Password: False
Kerberos keys available: False
----------------------------
Number of entries returned 2
----------------------------
Privilege Separation for Employee Entry and Activation#
In following example, we will simulate adding a user in 2 steps. First, adding a Stage User by a Helpdesk administrator without a permission to add active users and second activating the user by Security Administrator.
First, Stage User is added (System: Add Stage User permission is sufficient for that operation):
# ipa stageuser-add barbar --first Bar --last Bar
-------------------------
Added stage user "barbar"
-------------------------
User login: barbar
First name: Bar
Last name: Bar
Full name: Bar Bar
Display name: Bar Bar
Initials: BB
Home directory: /home/barbar
GECOS: Bar Bar
Login shell: /bin/sh
Kerberos principal: barbar@RHEL72
Email address: barbar@rhel72.test
UID: -1
GID: -1
Password: False
Kerberos keys available: False
The user is already created with all FreeIPA specific attributes. UID and GID are not generated yet:
# ipa stageuser-show barbar --all --raw
dn: uid=barbar,cn=staged users,cn=accounts,cn=provisioning,dc=rhel72
uid: barbar
givenname: Bar
sn: Bar
cn: Bar Bar
initials: BB
homedirectory: /home/barbar
gecos: Bar Bar
loginshell: /bin/sh
mail: barbar@rhel72.test
uidnumber: -1
gidnumber: -1
has_password: FALSE
has_keytab: FALSE
description: __no_upg__
displayName: Bar Bar
ipaUniqueID: autogenerate
krbPrincipalName: barbar@RHEL72
nsaccountlock: TRUE
objectClass: ipaobject
objectClass: person
objectClass: top
objectClass: ipasshuser
objectClass: inetorgperson
objectClass: organizationalperson
objectClass: krbticketpolicyaux
objectClass: krbprincipalaux
objectClass: inetuser
objectClass: posixaccount
objectClass: ipaSshGroupOfPubKeys
Activate the Stage User (System: Add Users permission is required):
# ipa stageuser-activate barbar
---------------------------
Stage user barbar activated
---------------------------
User login: barbar
First name: Bar
Last name: Bar
Full name: Bar Bar
Display name: Bar Bar
Initials: BB
Home directory: /home/barbar
GECOS: Bar Bar
Login shell: /bin/sh
Kerberos principal: barbar@RHEL72
Email address: barbar@rhel72.test
UID: 626000003
GID: 626000003
See that the user has all the FreeIPA attributes including UID and GID generated:
# ipa user-show barbar --all --raw
dn: uid=barbar,cn=users,cn=accounts,dc=rhel72
uid: barbar
givenname: Bar
sn: Bar
cn: Bar Bar
initials: BB
homedirectory: /home/barbar
gecos: Bar Bar
loginshell: /bin/sh
mail: barbar@rhel72.test
uidnumber: 626000003
gidnumber: 626000003
nsaccountlock: FALSE
has_password: FALSE
has_keytab: FALSE
displayName: Bar Bar
ipaUniqueID: 9d5dddca-dc66-11e5-b542-001a4a23140a
krbPrincipalName: barbar@RHEL72
memberof: cn=ipausers,cn=groups,cn=accounts,dc=rhel72
mepManagedEntry: cn=barbar,cn=groups,cn=accounts,dc=rhel72
objectClass: ipasshgroupofpubkeys
objectClass: ipaobject
objectClass: person
objectClass: top
objectClass: ipasshuser
objectClass: inetorgperson
objectClass: organizationalperson
objectClass: krbticketpolicyaux
objectClass: krbprincipalaux
objectClass: inetuser
objectClass: posixaccount
objectClass: mepOriginEntry
Test Plan#
See Unit tests plan