Difference between revisions of "Infrastructure:LDAP"

From Kosmos Wiki
Jump to navigation Jump to search
(Create initial Infrastructure page for LDAP)
 
(Document resetting a user's password)
 
(9 intermediate revisions by 2 users not shown)
Line 8: Line 8:
  
 
<pre>
 
<pre>
                        ------------------------
+
                                  ------------------------
                        |  dc=kosmos,dc=org  |
+
                                  |  dc=kosmos,dc=org  |
                        | (organizationalUnit) |
+
                                  | (organizationalUnit) |
                        ------------------------
+
                                  ------------------------
                                    |
+
                                  |                  |
                        ------------------------
+
    ------------------------      |                  |    -----------------------------
                        |      cn=users      |
+
    |      cn=users      |------|                  |----|  cn=applications        |
                        | (organizationalRole) |
+
    | (organizationalRole) |                              | (organizationalRole)     |
                        ------------------------
+
    ------------------------                              -----------------------------
                                |         |
+
            |             |                                  |                      |
            ------------------------ ------------------------
+
------------------------ ------------------------      ----------------------------  ------------------------
            |    ou=kosmos.org    | |    ou=account.pro   |
+
|    ou=kosmos.org    | |  ou=customdomain.com |      |    ou=kosmos.org        |   |  ou=customdomain.com |
            | (organizationalUnit) | | (organizationalUnit) |
+
| (organizationalUnit) | | (organizationalUnit) |      | (organizationalUnit)    |  | (organizationalUnit) |
            ------------------------ ------------------------
+
------------------------ ------------------------      ----------------------------  ------------------------
                        |                         |
+
            |                       |                                |          |
  ------------------------------------- -------------------------------------
+
  ----------------------- ------------------------      ------------------------- -------------------------
  | cn=example_user                   | | cn=example_user                   |
+
  | cn=example_user     | | cn=example_user     |      | uid=xmpp              | | uid=wiki              |
  | (account,person,extensibleObject) | | (account,person,extensibleObject) |
+
  | (account,person,   | | (account,person,     |      | (account,            | | (account,            |
  ------------------------------------- -------------------------------------
+
| extensibleObject)  | | extensibleObject)    |      | simpleSecurityObject) | | simpleSecurityObject) |
 +
  ----------------------- ------------------------      ------------------------- -------------------------
 +
 
 
</pre>
 
</pre>
  
 
Here is an LDIF representation of an example of what we use on ldap.kosmos.org:
 
Here is an LDIF representation of an example of what we use on ldap.kosmos.org:
 +
 +
== Applications ==
  
 
<pre>
 
<pre>
# container for the organizationUnits (domains)
+
# applications, kosmos.org
dn: cn=users,dc=kosmos,dc=org
+
dn: cn=applications,dc=kosmos,dc=org
 
objectClass: top
 
objectClass: top
 
objectClass: organizationalRole
 
objectClass: organizationalRole
 
cn: users
 
cn: users
  
# kosmos.org, users, kosmos.org
+
# kosmos.org, applications, kosmos.org
dn: ou=kosmos.org,cn=users,dc=kosmos,dc=org
+
dn: ou=kosmos.org,cn=applications,dc=kosmos,dc=org
 
objectClass: top
 
objectClass: top
 
objectClass: organizationalUnit
 
objectClass: organizationalUnit
description: Kosmos
 
 
ou: kosmos.org
 
ou: kosmos.org
aci: (target="ldap:///cn=*,ou=kosmos.org,cn=users,dc=kosmos,dc=org")(targetattr="cn || sn || uid || mail || userPassword || nsRole") (version 3.0; acl "xmpp-kosmos-read-search"; allow (read,search) userdn="ldap:///cn=xmpp,ou=kosmos.org,cn=users,dc=kosmos,dc=org";)
 
aci: (target="ldap:///cn=*,ou=kosmos.org,cn=users,dc=kosmos,dc=org")(targetattr="cn || sn || uid || mail || userPassword") (version 3.0; acl "xmpp-kosmos-read-search"; allow (read,search) userdn="ldap:///cn=wiki,ou=kosmos.org,cn=users,dc=kosmos,dc=org";)
 
aci: (target="ldap:///cn=*,ou=kosmos.org,cn=users,dc=kosmos,dc=org")(targetattr="userPassword") (version 3.0; acl "xmpp-kosmos-change-password"; allow (write) userdn="ldap:///cn=xmpp,ou=kosmos.org,cn=users,dc=kosmos,dc=org";)
 
  
# xmpp account, used by ejabberd to search for users and change passwords
+
# account.pro, applications, kosmos.org
dn: cn=xmpp,ou=kosmos.org,cn=users,dc=kosmos,dc=org
+
dn: ou=account.pro,cn=applications,dc=kosmos,dc=org
 
objectClass: top
 
objectClass: top
 +
objectClass: organizationalUnit
 +
description: Pro Account
 +
ou: account.pro
 +
 +
# wiki account, used by mediawiki to search for users and change passwords
 +
dn: uid=wiki,ou=kosmos.org,cn=applications,dc=kosmos,dc=org
 +
objectClass: simpleSecurityObject
 +
objectClass: account
 +
uid: wiki
 +
userPassword: secret
 +
 +
# # xmpp account, used by ejabberd to search for users and change passwords
 +
dn: uid=xmpp,ou=kosmos.org,cn=applications,dc=kosmos,dc=org
 +
objectClass: simpleSecurityObject
 
objectClass: account
 
objectClass: account
objectClass: person
 
cn: xmpp
 
sn: xmpp
 
 
uid: xmpp
 
uid: xmpp
 
userPassword: secret
 
userPassword: secret
  
# wiki account, used by mediawiki to search for users and change passwords
+
# xmpp account, used by ejabberd to search for users and change passwords
dn: cn=wiki,ou=kosmos.org,cn=users,dc=kosmos,dc=org
+
dn: uid=xmpp,ou=account.pro,cn=applications,dc=kosmos,dc=org
objectClass: top
+
objectClass: simpleSecurityObject
 
objectClass: account
 
objectClass: account
objectClass: person
+
uid: xmpp
cn: wiki
 
sn: wiki
 
uid: wiki
 
 
userPassword: secret
 
userPassword: secret
  
# xmpp role, used to filter users that have access to XMPP
+
</pre>
dn: cn=xmpp_role,ou=kosmos.org,cn=users,dc=kosmos,dc=org
+
 
objectclass: top
+
== Users ==
objectclass: LDAPsubentry
+
 
objectclass: nsRoleDefinition
+
<pre>
objectclass: nsComplexRoleDefinition
+
# container for the organizationUnits (domains)
objectclass: nsFilteredRoleDefinition
+
dn: cn=users,dc=kosmos,dc=org
cn: xmpp_role
+
objectClass: top
nsRoleFilter: (&(objectclass=person)(xmpp=enabled))
+
objectClass: organizationalRole
Description: filtered role for xmpp on kosmos.org
+
cn: users
 +
 
 +
# kosmos.org, users, kosmos.org
 +
dn: ou=kosmos.org,cn=users,dc=kosmos,dc=org
 +
objectClass: top
 +
objectClass: organizationalUnit
 +
description: Kosmos
 +
ou: kosmos.org
 +
aci: (target="ldap:///cn=*,ou=kosmos.org,cn=users,dc=kosmos,dc=org")(targetattr="cn || sn || uid || mail || userPassword || nsRole || objectClass") (version 3.0; acl "xmpp-kosmos-read-search"; allow (read,search) userdn="ldap:///uid=xmpp,ou=kosmos.org,cn=applications,dc=kosmos,dc=org";)
 +
aci: (target="ldap:///cn=*,ou=kosmos.org,cn=users,dc=kosmos,dc=org")(targetattr="cn || sn || uid || mail || userPassword || objectClass") (version 3.0; acl "xmpp-kosmos-read-search"; allow (read,search) userdn="ldap:///uid=wiki,ou=kosmos.org,cn=applications,dc=kosmos,dc=org";)
 +
aci: (target="ldap:///cn=*,ou=kosmos.org,cn=users,dc=kosmos,dc=org")(targetattr="userPassword") (version 3.0; acl "xmpp-kosmos-change-password"; allow (write) userdn="ldap:///uid=xmpp,ou=kosmos.org,cn=applications,dc=kosmos,dc=org";)
  
 
# example user for kosmos.org
 
# example user for kosmos.org
Line 91: Line 109:
 
xmpp: enabled
 
xmpp: enabled
 
userPassword: secret
 
userPassword: secret
 +
 +
# example admin for kosmos.org
 +
dn: cn=example_admin,ou=kosmos.org,cn=users,dc=kosmos,dc=org
 +
objectClass: top
 +
objectClass: account
 +
objectClass: person
 +
objectClass: extensibleObject
 +
cn: example_admin
 +
sn: example_admin
 +
uid: example_admin
 +
mail: example_admin@example.com
 +
admin: true
 +
userPassword: secret
 +
  
 
# account.pro, users, kosmos.org
 
# account.pro, users, kosmos.org
Line 98: Line 130:
 
description: account
 
description: account
 
ou: account.pro
 
ou: account.pro
aci: (target="ldap:///cn=*,ou=account.pro,cn=users,dc=kosmos,dc=org")(targetattr="cn || sn || uid || mail || userPassword || nsRole") (version 3.0; acl "xmpp-account-read-search"; allow (read,search) userdn="ldap:///cn=xmpp,ou=account.pro,cn=users,dc=kosmos,dc=org";)
+
aci: (target="ldap:///cn=*,ou=account.pro,cn=users,dc=kosmos,dc=org")(targetattr="cn || sn || uid || mail || userPassword || nsRole || objectClass") (version 3.0; acl "xmpp-account-read-search"; allow (read,search) userdn="ldap:///uid=xmpp,ou=account.pro,cn=applications,dc=kosmos,dc=org";)
aci: (target="ldap:///cn=*,ou=account.pro,cn=users,dc=kosmos,dc=org")(targetattr="userPassword") (version 3.0; acl "xmpp-account-change-password"; allow (write) userdn="ldap:///cn=xmpp,ou=account.pro,cn=users,dc=kosmos,dc=org";)
+
aci: (target="ldap:///cn=*,ou=account.pro,cn=users,dc=kosmos,dc=org")(targetattr="userPassword") (version 3.0; acl "xmpp-account-change-password"; allow (write) userdn="ldap:///uid=xmpp,ou=account.pro,cn=applications,dc=kosmos,dc=org";)
 
 
# xmpp account, used by ejabberd to search for users and change passwords
 
dn: cn=xmpp,ou=account.pro,cn=users,dc=kosmos,dc=org
 
objectClass: top
 
objectClass: account
 
objectClass: person
 
cn: xmpp
 
sn: xmpp
 
uid: xmpp
 
userPassword: secret
 
 
 
# xmpp role, used to filter users that have access to XMPP
 
dn: cn=xmpp_role,ou=5apps.com,cn=users,dc=kosmos,dc=org
 
objectclass: top
 
objectclass: LDAPsubentry
 
objectclass: nsRoleDefinition
 
objectclass: nsComplexRoleDefinition
 
objectclass: nsFilteredRoleDefinition
 
cn: xmpp_role
 
nsRoleFilter: (&(objectclass=person)(xmpp=enabled))
 
Description: filtered role for xmpp on 5apps.com
 
  
 
# example user for account.pro
 
# example user for account.pro
Line 135: Line 146:
 
userPassword: secret
 
userPassword: secret
 
</pre>
 
</pre>
 +
 +
== Admin commands ==
 +
 +
The ''ldapsearch'' and ''ldapadd'' command-line tool are provided by different packages depending on your OS. For example ''ldap-utils'' on Ubuntu, ''openldap-clients'' on Fedora, ''openldap'' on Arch Linux. It is already provided in a default macOS installation.
 +
 +
This can also be done using the LDAP client library of your choice.
 +
 +
=== Listing accounts ===
 +
 +
$ ldapsearch -x -W -D 'cn=Directory Manager' -b "ou=kosmos.org,cn=users,dc=kosmos,dc=org" -H "ldaps://ldap.kosmos.org"
 +
 +
=== Adding an account ===
 +
 +
==== Generate a hashed password ====
 +
 +
This example is using Ruby, but anything that can generate a salted SHA512 hash will also work.
 +
 +
$ ruby -r base64 -r digest -r securerandom -e 'salt = SecureRandom.hex(32); password = "random_password"; puts "{SSHA512}" + Base64.strict_encode64(Digest::SHA512.digest(password+salt) + salt)'
 +
{SSHA512}WsELiZM9MlUM004LF3jpV5OuV+qTsGoRR1RzffdtUuPpzOl57I7WmKL+S46/KR8HUtYPRh1ttmsNvGUX/agxLjBkZGI0MTczNWNiZjkxMDI0NGEzZTE2ZDBlNGJkMDQ5N2ZhMjVjMjQ1NzFlZmJlNmZmODhmNjE5OGM1YWM3Zjc=
 +
 +
==== Add the account ====
 +
 +
$ ldapadd -x -W -D 'cn=Directory Manager' -H "ldaps://ldap.kosmos.org" << EOF
 +
dn: cn=alice,ou=kosmos.org,cn=users,dc=kosmos,dc=org
 +
objectClass: top
 +
objectClass: account
 +
objectClass: person
 +
objectClass: extensibleObject
 +
cn: alice
 +
sn: alice
 +
uid: alice
 +
mail: alice@example.com
 +
userPassword: {SSHA512}WsELiZM9MlUM004LF3jpV5OuV+qTsGoRR1RzffdtUuPpzOl57I7WmKL+S46/KR8HUtYPRh1ttmsNvGUX/agxLjBkZGI0MTczNWNiZjkxMDI0NGEzZTE2ZDBlNGJkMDQ5N2ZhMjVjMjQ1NzFlZmJlNmZmODhmNjE5OGM1YWM3Zjc=
 +
EOF
 +
 +
adding new entry "cn=alice,ou=kosmos.org,cn=users,dc=kosmos,dc=org"
 +
 +
=== Reset a user's password ===
 +
 +
This can also be used to replace any field, for example the user's email (''mail'')
 +
 +
$ ldapmodify -x -W -D 'cn=Directory Manager' -H "ldaps://ldap.kosmos.org" << EOF
 +
dn: cn=alice,ou=kosmos.org,cn=users,dc=kosmos,dc=org
 +
changetype: modify
 +
replace: userPassword
 +
userPassword: {SSHA512}tJo0ttExKmR8UMbvygtvA23cJ0XD3I6zPxd4B+l9225XynaY8kACoUNSmr4SPjOxPWRqEb4mEIJ5sN8MTOvnpTZmNGRlNDViNGY5YzQwYjM4ZmY3NDBkYjJkZjVkMWE4MjVmYTIxMjk4NmZlYWY1Yjk0MjUyOGNiZDYyZWRhNWE=
 +
EOF
 +
 +
modifying entry "cn=alice,ou=kosmos.org,cn=users,dc=kosmos,dc=org"

Latest revision as of 09:29, 6 October 2020

Server

We use 389 Directory Server, installed using this Chef cookbook. The server runs on ldap.kosmos.org. The future plan is to make the LDAP server only accessible to services that use it for authentication and authorization, as well as the upcoming Kosmos Accounts Web UI

Directory structure

Here is a diagram of the directory structure we use on ldap.kosmos.org:

                                  ------------------------
                                  |   dc=kosmos,dc=org   |
                                  | (organizationalUnit) |
                                  ------------------------
                                   |                   |
     ------------------------      |                   |    -----------------------------
     |       cn=users       |------|                   |----|   cn=applications         |
     | (organizationalRole) |                               | (organizationalRole)      |
     ------------------------                               -----------------------------
            |              |                                   |                       |
------------------------ ------------------------       ----------------------------   ------------------------
|     ou=kosmos.org    | |  ou=customdomain.com |       |     ou=kosmos.org        |   |  ou=customdomain.com |
| (organizationalUnit) | | (organizationalUnit) |       | (organizationalUnit)     |   | (organizationalUnit) |
------------------------ ------------------------       ----------------------------   ------------------------
            |                        |                                |           |
 ----------------------- ------------------------       ------------------------- -------------------------
 | cn=example_user     | | cn=example_user      |       | uid=xmpp              | | uid=wiki              |
 | (account,person,    | | (account,person,     |       | (account,             | | (account,             |
 | extensibleObject)   | | extensibleObject)    |       | simpleSecurityObject) | | simpleSecurityObject) |
 ----------------------- ------------------------       ------------------------- -------------------------

Here is an LDIF representation of an example of what we use on ldap.kosmos.org:

Applications

# applications, kosmos.org
dn: cn=applications,dc=kosmos,dc=org
objectClass: top
objectClass: organizationalRole
cn: users

# kosmos.org, applications, kosmos.org
dn: ou=kosmos.org,cn=applications,dc=kosmos,dc=org
objectClass: top
objectClass: organizationalUnit
ou: kosmos.org

# account.pro, applications, kosmos.org
dn: ou=account.pro,cn=applications,dc=kosmos,dc=org
objectClass: top
objectClass: organizationalUnit
description: Pro Account
ou: account.pro

# wiki account, used by mediawiki to search for users and change passwords
dn: uid=wiki,ou=kosmos.org,cn=applications,dc=kosmos,dc=org
objectClass: simpleSecurityObject
objectClass: account
uid: wiki
userPassword: secret

# # xmpp account, used by ejabberd to search for users and change passwords
dn: uid=xmpp,ou=kosmos.org,cn=applications,dc=kosmos,dc=org
objectClass: simpleSecurityObject
objectClass: account
uid: xmpp
userPassword: secret

# xmpp account, used by ejabberd to search for users and change passwords
dn: uid=xmpp,ou=account.pro,cn=applications,dc=kosmos,dc=org
objectClass: simpleSecurityObject
objectClass: account
uid: xmpp
userPassword: secret

Users

# container for the organizationUnits (domains)
dn: cn=users,dc=kosmos,dc=org
objectClass: top
objectClass: organizationalRole
cn: users

# kosmos.org, users, kosmos.org
dn: ou=kosmos.org,cn=users,dc=kosmos,dc=org
objectClass: top
objectClass: organizationalUnit
description: Kosmos
ou: kosmos.org
aci: (target="ldap:///cn=*,ou=kosmos.org,cn=users,dc=kosmos,dc=org")(targetattr="cn || sn || uid || mail || userPassword || nsRole || objectClass") (version 3.0; acl "xmpp-kosmos-read-search"; allow (read,search) userdn="ldap:///uid=xmpp,ou=kosmos.org,cn=applications,dc=kosmos,dc=org";)
aci: (target="ldap:///cn=*,ou=kosmos.org,cn=users,dc=kosmos,dc=org")(targetattr="cn || sn || uid || mail || userPassword || objectClass") (version 3.0; acl "xmpp-kosmos-read-search"; allow (read,search) userdn="ldap:///uid=wiki,ou=kosmos.org,cn=applications,dc=kosmos,dc=org";)
aci: (target="ldap:///cn=*,ou=kosmos.org,cn=users,dc=kosmos,dc=org")(targetattr="userPassword") (version 3.0; acl "xmpp-kosmos-change-password"; allow (write) userdn="ldap:///uid=xmpp,ou=kosmos.org,cn=applications,dc=kosmos,dc=org";)

# example user for kosmos.org
dn: cn=example_user,ou=kosmos.org,cn=users,dc=kosmos,dc=org
objectClass: top
objectClass: account
objectClass: person
objectClass: extensibleObject
cn: example_user
sn: example_user
uid: example_user
mail: example_user@example.com
xmpp: enabled
userPassword: secret

# example admin for kosmos.org
dn: cn=example_admin,ou=kosmos.org,cn=users,dc=kosmos,dc=org
objectClass: top
objectClass: account
objectClass: person
objectClass: extensibleObject
cn: example_admin
sn: example_admin
uid: example_admin
mail: example_admin@example.com
admin: true
userPassword: secret


# account.pro, users, kosmos.org
dn: ou=account.pro,cn=users,dc=kosmos,dc=org
objectClass: top
objectClass: organizationalUnit
description: account
ou: account.pro
aci: (target="ldap:///cn=*,ou=account.pro,cn=users,dc=kosmos,dc=org")(targetattr="cn || sn || uid || mail || userPassword || nsRole || objectClass") (version 3.0; acl "xmpp-account-read-search"; allow (read,search) userdn="ldap:///uid=xmpp,ou=account.pro,cn=applications,dc=kosmos,dc=org";)
aci: (target="ldap:///cn=*,ou=account.pro,cn=users,dc=kosmos,dc=org")(targetattr="userPassword") (version 3.0; acl "xmpp-account-change-password"; allow (write) userdn="ldap:///uid=xmpp,ou=account.pro,cn=applications,dc=kosmos,dc=org";)

# example user for account.pro
dn: cn=example_pro,ou=account.pro,cn=users,dc=kosmos,dc=org
objectClass: top
objectClass: account
objectClass: person
objectClass: extensibleObject
cn: example_pro
sn: example_pro
uid: example_pro
mail: exampleaccount.pro
xmpp: enabled
userPassword: secret

Admin commands

The ldapsearch and ldapadd command-line tool are provided by different packages depending on your OS. For example ldap-utils on Ubuntu, openldap-clients on Fedora, openldap on Arch Linux. It is already provided in a default macOS installation.

This can also be done using the LDAP client library of your choice.

Listing accounts

$ ldapsearch -x -W -D 'cn=Directory Manager' -b "ou=kosmos.org,cn=users,dc=kosmos,dc=org" -H "ldaps://ldap.kosmos.org"

Adding an account

Generate a hashed password

This example is using Ruby, but anything that can generate a salted SHA512 hash will also work.

$ ruby -r base64 -r digest -r securerandom -e 'salt = SecureRandom.hex(32); password = "random_password"; puts "{SSHA512}" + Base64.strict_encode64(Digest::SHA512.digest(password+salt) + salt)'
{SSHA512}WsELiZM9MlUM004LF3jpV5OuV+qTsGoRR1RzffdtUuPpzOl57I7WmKL+S46/KR8HUtYPRh1ttmsNvGUX/agxLjBkZGI0MTczNWNiZjkxMDI0NGEzZTE2ZDBlNGJkMDQ5N2ZhMjVjMjQ1NzFlZmJlNmZmODhmNjE5OGM1YWM3Zjc=

Add the account

$ ldapadd -x -W -D 'cn=Directory Manager' -H "ldaps://ldap.kosmos.org" << EOF
dn: cn=alice,ou=kosmos.org,cn=users,dc=kosmos,dc=org
objectClass: top
objectClass: account
objectClass: person
objectClass: extensibleObject
cn: alice
sn: alice
uid: alice
mail: alice@example.com
userPassword: {SSHA512}WsELiZM9MlUM004LF3jpV5OuV+qTsGoRR1RzffdtUuPpzOl57I7WmKL+S46/KR8HUtYPRh1ttmsNvGUX/agxLjBkZGI0MTczNWNiZjkxMDI0NGEzZTE2ZDBlNGJkMDQ5N2ZhMjVjMjQ1NzFlZmJlNmZmODhmNjE5OGM1YWM3Zjc=
EOF

adding new entry "cn=alice,ou=kosmos.org,cn=users,dc=kosmos,dc=org"

Reset a user's password

This can also be used to replace any field, for example the user's email (mail)

$ ldapmodify -x -W -D 'cn=Directory Manager' -H "ldaps://ldap.kosmos.org" << EOF
dn: cn=alice,ou=kosmos.org,cn=users,dc=kosmos,dc=org
changetype: modify
replace: userPassword
userPassword: {SSHA512}tJo0ttExKmR8UMbvygtvA23cJ0XD3I6zPxd4B+l9225XynaY8kACoUNSmr4SPjOxPWRqEb4mEIJ5sN8MTOvnpTZmNGRlNDViNGY5YzQwYjM4ZmY3NDBkYjJkZjVkMWE4MjVmYTIxMjk4NmZlYWY1Yjk0MjUyOGNiZDYyZWRhNWE=
EOF

modifying entry "cn=alice,ou=kosmos.org,cn=users,dc=kosmos,dc=org"