Difference between revisions of "Infrastructure:LDAP"
(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 | | |
− | + | | (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 | | cn=example_user | | uid=xmpp | | uid=wiki | |
− | | (account,person, | + | | (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> | ||
− | # | + | # applications, kosmos.org |
− | dn: cn= | + | dn: cn=applications,dc=kosmos,dc=org |
objectClass: top | objectClass: top | ||
objectClass: organizationalRole | objectClass: organizationalRole | ||
cn: users | cn: users | ||
− | # kosmos.org, | + | # kosmos.org, applications, kosmos.org |
− | dn: ou=kosmos.org,cn= | + | dn: ou=kosmos.org,cn=applications,dc=kosmos,dc=org |
objectClass: top | objectClass: top | ||
objectClass: organizationalUnit | objectClass: organizationalUnit | ||
− | |||
ou: kosmos.org | ou: kosmos.org | ||
− | |||
− | |||
− | |||
− | # | + | # account.pro, applications, kosmos.org |
− | dn: | + | 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 | ||
− | |||
− | |||
− | |||
uid: xmpp | uid: xmpp | ||
userPassword: secret | userPassword: secret | ||
− | # | + | # xmpp account, used by ejabberd to search for users and change passwords |
− | dn: | + | dn: uid=xmpp,ou=account.pro,cn=applications,dc=kosmos,dc=org |
− | objectClass: | + | objectClass: simpleSecurityObject |
objectClass: account | objectClass: account | ||
− | + | uid: xmpp | |
− | |||
− | |||
− | uid: | ||
userPassword: secret | userPassword: secret | ||
− | # | + | </pre> |
− | dn: cn= | + | |
− | + | == Users == | |
− | + | ||
− | + | <pre> | |
− | + | # container for the organizationUnits (domains) | |
− | + | dn: cn=users,dc=kosmos,dc=org | |
− | cn: | + | 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 | # 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:/// | + | 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:/// | + | 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 | # 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
Contents
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"