This plugin enables you to build a self defined LDAP GUI to ease administration by distributing certain tasks to your users over a web interface. At the moment the interface is implemented by REST handlers which can be called on submit to modify or add LDAP entries by a self designed graphical user interface (GUI) consisting of forms.
The problems intended to be solved by this plugin are recurring, easy modifications to LDAP data which could be done by users, because they have the knowledge about the data. An example is that someone wants to change his email adress or data changed because the user moved to another office. That often happens over intern solutions or over an administrator because you can not expect them to know what LDAP does. So this plugin tries to provide the tools to make such things invisible and put everything together into a web based GUI. And because it is a Foswiki plugin the GUI can be designed and described flexibly.
The LdapGuiPlugin ist in an experimental state right now and will grow over time to add new functionalities. Of course there is an attempt to not alter the interface too much so that your forms are rendered useless after an update but there is a small chance that it could happen out of necessity.The following chapters will explain the specification you need to satisfy and give some examples to give you a feeling how to use it.
This plugin is currently developed for Linux and OpenLDAP. Hopefully the interface will grow much more abstract to provide functionality on different platforms. The behavior on other systems is not tested yet.
There are some requirements to be fulfilled before you can begin to build your web GUI. Of course you first need a LDAP server (OpenLDAP would be a good choice) and some experience in administration. For configuration of LdapGuiPlugin it is also useful to have basic knowledge of Perl. You will see why a little bit later in the following chapters. To configure the connection settings for this plugin, you should read the chapter "LDAP questionnaire" in the description of LdapContrib. LdapGuiPlugin does not extend the LdapContrib, because it targets a slightly different goal which is to provide not only read but also write access to a LDAP server. Also the LdapContrib is already a mature contribution and works well for the tasks it targets. But some of the configuration is similar to LdapContrib. In fact, if you installed LdapContrib the LdapGuiPlugin can use its connection configuration.Perl modules you will need:
Before the detailed explanation, here is an overview of the configuration in configure.
option | default value | description |
---|---|---|
connection | ||
{Plugins}{LdapGuiPlugin}{LdapGuiServerHost} | '127.0.0.1' | The host of your LDAP server |
{Plugins}{LdapGuiPlugin}{LdapGuiServerVersion} | '3' | Server version |
{Plugins}{LdapGuiPlugin}{LdapGuiPort} | 389 | LDAP port |
{Plugins}{LdapGuiPlugin}{LdapGuiUseSASL} | 0 | Use SASL |
{Plugins}{LdapGuiPlugin}{LdapGuiSASLMechanism} | 'PLAIN CRAM-MD5 EXTERNAL ANONYMOUS' | SASL mechanism to use |
{Plugins}{LdapGuiPlugin}{LdapGuiUseTLS} | 0 | Use TLS |
{Plugins}{LdapGuiPlugin}{LdapGuiTLSSSLVersion} | 'tlsv1' | |
{Plugins}{LdapGuiPlugin}{LdapGuiTLSVerify} | 'require' | |
{Plugins}{LdapGuiPlugin}{LdapGuiTLSCAPath} | ||
{Plugins}{LdapGuiPlugin}{LdapGuiTLSCAFile} | ||
{Plugins}{LdapGuiPlugin}{LdapGuiTLSClientCert} | ||
{Plugins}{LdapGuiPlugin}{LdapGuiTLSClientKey} | ||
{LdapGuiPlugin}{LdapGuiAllowProxyBind} | 0 | |
LDAP structure | ||
{LdapGuiPlugin}{LdapGuiBaseDN} | 'dc=my,dc=domain,dc=com' | Base DN of your LDAP DIT |
{LdapGuiPlugin}{LdapGuiUserBase} | ['ou=people,dc=my,dc=domain,dc=com'] | List of user bases |
{LdapGuiPlugin}{LdapGuiUserBaseAliases} | { 'people' => 'ou=people,dc=my,dc=domain,dc=com' }; |
User base aliases which are usable in forms by the ldapAddToGroup option. |
{LdapGuiPlugin}{LdapGuiLoginAttribute} | 'uid' | name of the attribute users must use to login |
{LdapGuiPlugin}{LdapGuiGroupBase} | ['ou=group,dc=my,dc=domain,dc=com'] | base of all groups |
{LdapGuiPlugin}{LdapGuiAllowProxyUser} | 0 | allow the plugin to bind against a proxy user to add new users to groups |
{LdapGuiPlugin}{LdapGuiBindDN} | proxy bind dn | |
{LdapGuiPlugin}{LdapGuiBindPassword} | 'secret' | proxy bind password |
{LdapGuiPlugin}{MemberAttribute} | 'memberUid' | attribute name which value defines a group member |
{LdapGuiPlugin}{GroupAttribute} | 'gidNumber' | attribute name which value refering a group |
{LdapGuiPlugin}{LdapGuiGroupIdentifier} | { '100' => 'cn=groupname,ou=group,dc=my,dc=domain,dc=com' } |
values pointing to a group dn (here for gidNumber value) |
glue function | ||
{LdapGuiPlugin}{LdapGuiGlueAllow} | 0 | allow attribute construction |
{LdapGuiPlugin}{LdapGuiGlue} | { 'cn' => { 'attributes' => [ 'LdapFirstName', 'sn' ], 'delimiter' => ' ' } } |
rules which define how attribute values are constructed |
autoset | ||
{LdapGuiPlugin}{LdapGuiAllowAutosetNumericalAttributes} | 0 | allow to set numerical attributes automatically |
{LdapGuiPlugin}{LdapGuiAutosetNumericalAttributes} | { 'uidNumber' => { min => 1000, max => 65535 } } |
defines which attributes should get autogenerated and in what range additionally you can add step => 2 to increment by 2 but 1 |
misc | ||
{LdapGuiPlugin}{LdapGuiCharSet} | 'utf-8' | |
{LdapGuiPlugin}{LdapGuiUseTrigger} | 0 | |
{LdapGuiPlugin}{LdapGuiTriggerTargetURL} | ||
{LdapGuiPlugin}{LdapGuiTriggerTargetPort} | ||
{LdapGuiPlugin}{LdapGuiTrustedWebs} | [] | a list of webs which are trusted, only requests from these webs are passed to processing |
{LdapGuiPlugin}{LdapGuiLoginSchema} | { 'add' => { 'loginName' => 'LdapLoginAttributeName', 'loginPWD' => 'LdapLoginPasswordAttributeName' }, 'modify' => { 'loginName' => 'uid', 'loginPWD' => 'LdapLoginPasswordAttributeName' } } |
defines how your form logins should get named so that the plugin understands it |
{LdapGuiPlugin}{LdapGuiTestMode} | 0 | starts the test mode, no write to the ldap will happen |
(# charaters define commentary begin)
#LDAP {Plugins}{LdapGuiPlugin}{LdapGuiServerHost} = 127.0.0.1 {Plugins}{LdapGuiPlugin}{LdapGuiPort} = 389 {Plugins}{LdapGuiPlugin}{LdapGuiServerVersion} = 3 #SASL {Plugins}{LdapGuiPlugin}{LdapGuiUseSASL} = false {Plugins}{LdapGuiPlugin}{LdapGuiSASLMechanism} = PLAIN CRAM-MD5 EXTERNAL ANONYMOUS #TLS {Plugins}{LdapGuiPlugin}{LdapGuiUseTLS} = false {Plugins}{LdapGuiPlugin}{LdapGuiTLSSSLVersion} = tlsv1 {Plugins}{LdapGuiPlugin}{LdapGuiTLSVerify} = require {Plugins}{LdapGuiPlugin}{LdapGuiTLSCAPath} = {Plugins}{LdapGuiPlugin}{LdapGuiTLSCAFile} = {Plugins}{LdapGuiPlugin}{LdapGuiTLSClientCert} = {Plugins}{LdapGuiPlugin}{LdapGuiTLSClientKey} = # user proxy {Plugins}{LdapGuiPlugin}{LdapGuiAllowProxyBind} = false # group proxy {Plugins}{LdapGuiPlugin}{LdapGuiAllowProxyUser} = true # group proxy dn {Plugins}{LdapGuiPlugin}{LdapGuiBindDN} = cn=proxyuser,dc=my,dc=domain,dc=com # group prody password {Plugins}{LdapGuiPlugin}{LdapGuiBindPassword} = secret
{ 'add' => { 'loginName' => 'LdapLoginAttributeName', 'loginPWD' => 'LdapLoginPasswordAttributeName' }, 'modify' => { 'loginName' => 'uid', 'loginPWD' => 'LdapLoginPasswordAttributeName' } }this means for the LdapGuiPlugin /addData handler, that the plugin searches for the fields LdapLoginAttributeName and LdapLoginPasswordAttributeName to bind against. For /modifyData it means, it is always searched for the uid and bind against that value.
These configurations are not necessary but can be useful to you. These settings have no effect until you actually use the corresponding option inside your forms, but they define what will be possible.
This is the configuration for the option called '!LdapGuiGlue'. You can use this option later to construct ('glue together') LDAP attributes out of form data, static strings and/or a format. (e.g.: cn = givenName + sn where givenName and sn are inside the form → cn will be "glued together" automatically) To do so you need to configure some rules how these attributes should be 'glued together'. Gluerules are specified to be a hash containing 2 - 4 parameter keys. Note that this specification will most likely change because it has great potential to be both: extended and simplified.
For this you need the following configuration for {Plugins}{LdapGuiPlugin}{LdapGuiGlue}:
'homeDirectory' => { 'delimiter' => '', 'asString' => [ 1, 0 ], 'attributes' => [ '/home/', 'uid' ] }, 'cn' => { 'delimiter' => ' ', 'attributes' => [ 'LdapFirstName', 'sn' ] }, 'uid' => { 'formatFunctions' => [ 'lowercase' ], 'delimiter' => '', 'attributes' => [ 'sn' ] }Note:
<input type="hidden" name="LdapGuiGlue" value="uid"/>for simple html or
%FORMELEMENT{ name="LdapGuiGlue" type="hidden" value="uid" }%for the FormPlugin
The goal of the plugin is to perform LDAP actions preferably by a form submit. It is also possible to invoke an action by a request URL, but this approach may be too troublesome. Therefore you must know how the form should look like and what content it represents.
Deleting entries is not yet implemented and may not be handled by the plugin in the first place.
<input name="sn" type="text" ""> <input name="HOmEdIReCtoRY" type="text" ""> <input name="givenName" type="text" "">Example for form fields which represent LDAP options:
<input name="HASHME" type="hidden" value="userPassword=ssha"> <input name="ldapguiglue" type="hidden" "uid,cn">
option | what does it? |
---|---|
LdapGuiGlue | Defines which attributes for the current form must get constructed. |
HashMe | Defines which attributes of the current form must get hashed and which methods must be used. |
LdapGuiAddToUserBase | Defines in which userbase the entry must be inserted (if adding a new entry) |
LdapGuiModifyAdd | If you modify an entry you can specify that the value of the formfield should be added to the corresponding LDAP attribute |
LdapGuiModifyDel | If you modify an entry you can specify that the value of the formfield should be deleted from the corresponding LDAP attribute |
<input type="hidden" name="LdapGuiGlue" value="uid"/>for simple html
%FORMELEMENT{ name="LdapGuiGlue" type="hidden" value="uid" }%
%FORMELEMENT{ name="HASHME" type="hidden" value="userPassword=sha,ssha,smd5,md5,crypt" }%
If for example a user of your form types in the value 'abcd12AB' as a password the stored values could be:
userPassword: {SHA}2Ky05bDZLtah6bEXwMtPd1ZeUD0= userPassword: {SSHA}UJvDy13UQpqPedUIXdPP8whJF8vFbTa6 userPassword: {SMD5}S5Ze1/Ort25FiqSGyBaUemFiY2Q= userPassword: {MD5}+fcj3ntVthYOpNtHyyu8IQ== userPassword: {CRYPT}nw37xSELAvmTI
If you want to store hashed values with forms other than that, you need some perl knowledge. The supported methods for hashing are implemented inside the Hash.pm. Feel free to improve this class or contribute new hash methods to it.
---+ New user ---++ Name %STARTFORM{ name="AddFormTest" action="rest" method="post" validate="on" strictverification="off" restaction="LdapGuiPlugin/addData" }% %FORMELEMENT{ name="LdapFirstName" title="the users first name" hint="<br/>Example: John" type="text" value="" mandatory="on" validate="required" }% %FORMELEMENT{ name="sn" title="the users last name" hint="</br>Example: Doe" type="text" value="" mandatory="on" validate="required" }% ---++ Location %FORMELEMENT{ name="roomNr" title="room number" hint="<br/>Please set the room number for the new user." type="text" value="" validate="required" }% ---+++ User password %FORMELEMENT{ name="userPassword" title="The userpassword" type="password" value="" mandatory="on" hint="<br/>The new users password" validate="required" }% ---+++ LDAP Login Please use your LDAP data to verify your identity to submit your entered data. ---- %FORMELEMENT{ name="LdapLoginAttributeName" title="Your Login Name" type="text" value="" mandatory="on" validate="required" }% %FORMELEMENT{ name="LdapLoginPasswordAttributeName" title="Your Password" type="password" mandatory="on" validate="required" value="" }% %FORMELEMENT{ name="Submit" type="submit" }% <!-- We set objectClasses invisible --> %FORMELEMENT{ name="objectClasses" type="hidden" value="posixAccount, inetOrgPerson, person" }% <!-- Also the standard group (100 is an alias for gidNumber defined in {LdapGuiPlugin}{LdapGuiGroupIdentifier}) --> %FORMELEMENT{ name="gidNumber" type="hidden" value="100" }% <!-- We define the new user gets inserted in 'ou=people,dc=my,dc=domain,dc=com' The alias 'people' is defined in {LdapGuiPlugin}{LdapGuiUserBaseAliases} --> %FORMELEMENT{ name="ldapguiaddtouserbase" type="hidden" value="people" }% <!-- The attributes cn, mail, homedirectory and uid get constructed by the rules defined in {LdapGuiPlugin}{LdapGuiGlue} for the new user. --> %FORMELEMENT{ name="ldapguiglue" type="hidden" value="cn,mail, homedirectory, uid" }% <!-- The values for the userPassword attribute should get saved as hashes. (SHA, SSHA, SMD5, MD5) --> %FORMELEMENT{ name="ldapguitohash" type="hidden" value="userPassword = sha, ssha, smd5, md5" }% %ENDFORM%
---+ I moved to another office/building %STARTFORM{ name="Employeeform" action="rest" method="post" validate="on" restaction="LdapGuiPlugin/modifyData" strictverification="off" }% <!-- Note: myPrinter is not a standard LDAP attribute if it is defined by the LDAP schema, the plugin will modify it. --> %FORMELEMENT{ name="myPrinter" title="your preferred printer:" type="select" value="%LDAPGETATTRIBUTE{attribute="myPrinter"}%" size="5" mandatory="off" options=",printera2 , printerb2, printerc2" labels="No Change, Printer 2nd floor building A, Printer 2nd floor building B, Printer 2nd floor building C" hint="<br/>Here you can change your preferred printer. If you moved to another building for example you surely want to print your stuff there." }% %FORMELEMENT{ name="roomNr" title="room number:" type="text" value="%LDAPGETATTRIBUTE{attribute="raum"}%" validate="required" hint="<br/>You moved from one room to another? Please change the room number to your current one." }% %FORMELEMENT{ name="telephone" title="telephone:" type="text" value="%LDAPGETATTRIBUTE{attribute="telephone"}%" mandatory="off" validate="required" hint="</br>Change your internal telephone number here." }% ---- ---+++ Ldap Login Please use your LDAP login name and password to verify your identity. Verify your changes by clicking submit.<br /> <!-- value="%LDAPGETATTRIBUTE{attribute="uid"}%" refers to the default value of {LdapGuiPlugin}{LdapGuiLoginSchema}. That way a modification is bound to the currently logged in user. (if uid is your login attribute) This can be changed but if uid is your login attribut the plugin will deny it to be modified. If you want to change a foreign entry, you need to provide a full dn to that entry like that: %FORMELEMENT{ name="dn" type="text" value="uid=otherGuy;dc=my;dc=domain;dc=com" }% --> %FORMELEMENT{ name="uid" title="Your ldap login name" type="text" value="%LDAPGETATTRIBUTE{attribute="uid"}%" validate="required" }% %FORMELEMENT{ name="LdapLoginPasswordAttributeName" title="Your ldap password" type="password" validate="required" value="" }% %FORMELEMENT{ name="action" type="submit" buttonlabel="Submit" }% %ENDFORM%Note: If you want a formfield value to be added to an existing set of value you need to mark it over the option LdapGuiModifyAdd. The value of that fiel needs to be the name of an LDAP formfield Example for mail attribute:
... %FORMELEMENT{ name="mail" title="mail:" type="text" value="" validate="email" hint="<br/>Your mail." }% <input name="ldapguimodifyadd" type="hidden" value="email"> ...
If no value is provided in mail it will add nothing and leave the mail attribute for this entry untouched.
If your want to delete a special value you need to mark the formfield with LdapGuiModifyDel. Make sure to provide a value because otherwise the whole attribute gets deleted from the entry. Example for mail attribute:... %FORMELEMENT{ name="mail" title="mail:" type="text" value="example@domain.com" validate="email" hint="<br/>Your mail." }% <input name="ldapguimodifydel" type="hidden" value="email"> ...
If the plugin finds a value 'example@domain.com' for the current mail attribute, it will delete it. Without a value, the attribute mail would be deleted.
%LDAPGETATTRIBUTE{attribute="cn"}%If you don't use the LdapUserMapping, or a user has not the access to the attribute, or some other issue prevented the macro to succeed, it will return nothing. If multiple values are wanted (for example to fill in options for a select box) there is an option called 'max'. With that you can specify the maximum number of values which should get retrieved. Out comes a comma seperated list of values. Example:
%LDAPGETATTRIBUTE{attribute="email" max="5"}%The output could be:
email1@domain.com,email2@domain.com,email3@domain.com,email4@domain.com,email5@domain.com
Plugin Author: | Foswiki:Main.RobertFelber |
Copyright: | ? 2013, Robert Felber |
License: | GPL ( GNU General Public License) |
Release: | 0.1 |
Version: | 0.1 |
Change History: | |
5 March 2013: | Initial version |
Foswiki Dependency: | $Foswiki::Plugins::VERSION 1.1 |
CPAN Dependencies: | none |
Other Dependencies: | none |
Perl Version: | 5.006 |
Plugin Home: | none |
Feedback: | none |