Cratus
What is Cratus?
Cratus is a simple library, primarily used by KnuEdge to query, report on, and manage Active Directory users and groups via LDAP. The intention is to simplify this interaction and modularize it for use across several of our tools. We've open-sourced it because we think it might be useful to others, and to give back to the community from whence all of its capabilities are derived.
Why Cratus?
Why not just use Net::LDAP? Well, in fact, this library does use Net::LDAP, but does so making some assumptions based on how we (and arguably most people) use LDAP with Active Directory. By building linkages between users and groups, baking in recursion (supporting so-called nested groups), and making just the right things configurable, Cratus provides a simple interface for common LDAP admin tasks. That said, it isn't meant to be general-purpose LDAP libary, so it hides a lot and is opinionated. If you're using Active Directory and not doing strange things with it, this library might be helpful.
Installation
Add this line to your application's Gemfile:
gem 'cratus'And then execute:
$ bundle
Or install it yourself as:
$ gem install cratus
Usage
Make sure your application has required the gem:
require 'cratus'Cratus supports configuration settings, controlled via the following keys with the following default values:
{
group_dn_attribute: :cn,
group_member_attribute: :member,
group_description_attribute: :description,
group_objectclass: :group,
group_basedn: 'ou=groups,dc=example,dc=com',
group_memberof_attribute: :memberOf,
user_dn_attribute: :samaccountname,
user_objectclass: :user,
user_basedn: 'ou=users,dc=example,dc=com',
user_account_control_attribute: :userAccountControl,
user_department_attribute: :department,
user_lockout_attribute: :lockouttime,
user_mail_attribute: :mail,
user_displayname_attribute: :displayName,
user_memberof_attribute: :memberOf,
host: 'ldap.example.com',
port: 389,
basedn: 'dc=example,dc=com',
username: 'username',
password: 'p@assedWard!',
include_distribution_groups: true
}
These keys can be set in the following ways:
- A YAML Config file at
~/.cratus.ymlin the form of:
---
:basedn: ou=internal,dc=mycompany,dc=com
:host: ad1.mycompany.com
:username: cn=ldapUser,ou=serviceAccounts,ou=users,ou=internal,dc=mycompany,dc=com
:password: 'mySuperSecretP@ssw0rd'
:user_basedn: ou=users,ou=internal,dc=mycompany,dc=com
:group_basedn: ou=groups,ou=internal,dc=mycompany,dc=com- Environment variables (all uppercase with
CRATUS_prepended) in the form of:
export CRATUS_BASEDN="ou=internal,dc=mycompany,dc=com"
export CRATUS_HOST="ad1.mycompany.com"
...- In code, by calling setter methods on the
Configsingleton:
Cratus.config.basedn = 'ou=internal,dc=mycompany,dc=com'
Cratus.config.host = 'ad1.mycompany.com'With Cratus configured, you'll need to connect to LDAP:
Cratus::LDAP.connectAfter connecting, using Cratus involves using the model classes User and Group.
Groups
The Group class supports the following finder methods:
-
Cratus::Group.allreturns anArray<Cratus::Group>of all groups scoped at or below thegroup_basedn. -
Cratus::Group.new('name')creates a new instance populated with details from LDAP (or raisesCratus::Exceptions::FailedLDAPSearchif the group can't be found).
Instances of Group have the following read-only attributes and methods:
-
#membersprovides anArray<Cratus::User>of all users that are a member of the group. It does this recursively, so it supports nested groups. -
#member_groupsprovides anArray<Cratus::Group>of all groups that are a member of the group. It does this recursively, so it supports nested groups. -
#member_ofprovides anArray<Cratus::Group>of all groups that this group is a member of. It does this recursively, so it supports nested groups. -
#dnreturns the distinguished name (dn) of the LDAP object -
#descriptionreturns the configurable LDAP "description" attribute as stored in LDAP if it exists. Otherwise it returnsnil.
Instances of Group have the following methods that can change the underlying LDAP object:
-
#add_user(user)allows adding individual LDAP users to a group. This method takes as input an instance ofCratus::User. It is idempotent and will add users as direct members of the group unless the user is already a member (directly or indirectly). -
#remove_user(user)allows removing individual LDAP users from a group. This method takes as input an instance ofCratus::User. It is idempotent and will remove users that are direct members of the group.
The Group class also implements Comparable, so it supports common comparison methods, most notably ==.
Users
The User class supports the following finder methods:
-
Cratus::User.allreturns anArrayof all users scoped at or below theuser_basedn. -
Cratus::User.new('name')creates a new instance populated with details from LDAP (or raisesCratus::Exceptions::FailedLDAPSearchif the group can't be found).
Instances of User have the following read-only attributes and methods:
-
#departmentreturns the LDAP "department" attribute as stored in LDAP if it exists. Otherwise it returnsnil. -
#disabled?returnstrueoffalseto indicate whether the User is fully disabled in LDAP. -
#emailreturns the configurable LDAP "mail" attribute as stored in LDAP if it exists. Otherwise it returnsnil. -
#enabled?returnstrueoffalseto indicate whether the User is fully enabled in LDAP. -
#fullnamereturns the configurable LDAP "displayName" attribute as stored in LDAP if it exists. Otherwise it returnsnil. -
#lockouttimereturns the configurable LDAP "lockouttime" attribute as stored in LDAP if it exists. Otherwise it returns0. -
#lockoutdurationqueries the Active Directory basedn for thelockoutDurationattribute for use in calculations with#lockouttime. -
#locked?returnstrueorfalsebased on#lockouttimeand#lockoutduration. -
#member_ofprovides anArray<Cratus::Group>of all groups that this user is a member of. It does this recursively, so it supports nested groups. -
#dnreturns the distinguished name (dn) of the LDAP object
Instances of User have the following methods that can change the underlying LDAP object:
-
#add_to_group(group)allows adding an LDAP user to a group. This method takes as input an instance ofCratus::Group. It is idempotent and will add users as direct members of the group unless the user is already a member (directly or indirectly). -
#remove_from_group(group)allows removing an LDAP user from a group. This method takes as input an instance ofCratus::Group. It is idempotent and will remove the user if it is a direct members of the group. -
#disablechanges the User Account Control (usuallyuserAccountControl) attribute to514, signifying that logins are not allowed. -
#enablechanges the User Account Control (usuallyuserAccountControl) attribute to512, signifying that logins are allowed. -
#unlockchanges thelockouttimeatrribute to0, signifying that the account is not locked out.
The User class also implements Comparable, so it supports common comparison methods, most notably ==.
Contributing
See CONTRIBUTING for additional information.
Licensing
This project and all code contained within it are released under the MIT License. As stated in CONTRIBUTING:
All contributions to this project will be released under the MIT License. By submitting a pull request, you are agreeing to comply with this license and for any contributions to be released under it.