ldap_lookup 0.1.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 174f93602c6a5158d0f3cce5d846eff7d2718eae02dc41eab13c843afadf86c8
4
- data.tar.gz: 3d3de4dd9b981317460607a807b1a1fc0ceb38aa89dbe18fcd97e6aedab8c661
3
+ metadata.gz: 957c311d5d68fcc94258c7f1263c2c17c4f9c2455f7043832fe5c3791ebd3cc8
4
+ data.tar.gz: e3029a5edf0799b9f1d5a13407639658f7360d9a1c8e4cfd663798f014008e06
5
5
  SHA512:
6
- metadata.gz: 8f483e5246550e3aad01cb1185878b44fd7420cdb90d1b7c9126b5067e19fb6b812bbe4f448aa7144b09a8b1bd1fb998c25b281cb98d3b782745b107b8615ea6
7
- data.tar.gz: e19cad4c0c17d93c30cfcbd7e1be5f43bbffe49a0e50bcf836938285994866c93a5dbcbeeac03f3c745d50caac996f1521616227a1f3ddcbe0854556cc72f073
6
+ metadata.gz: 32f0da915876e614ca9374d59a3045e924905b7ff2f218a4b73133d92ca718dec5afdd0f91fbcdf23052b9cddde85c37f075d8311d6a91aac539dce3cf2bfc31
7
+ data.tar.gz: 8d788fd099caf5b0df62e6e7eac16303b08ec18ec2b4ec734a5d3e84d0b6a730bf1bfc4b93b8ee6ec5a3af3cfd6409a46a605a8fa2b350a1fe56987d1c50a62e
data/.env.example ADDED
@@ -0,0 +1,25 @@
1
+ # LDAP Configuration for Testing
2
+ # Copy this file to .env and fill in your actual credentials
3
+ # The .env file is gitignored and will not be committed
4
+
5
+ # Your UM uniqname (username)
6
+ LDAP_USERNAME=your_uniqname
7
+
8
+ # Your UM password
9
+ LDAP_PASSWORD=your_password
10
+
11
+ # Leave LDAP_USERNAME and LDAP_PASSWORD unset for anonymous binds
12
+
13
+ # Optional: Override default LDAP settings
14
+ # LDAP_HOST=ldap.umich.edu
15
+ # LDAP_PORT=389 # Use 389 for STARTTLS or 636 for LDAPS
16
+ # LDAP_BASE=dc=umich,dc=edu
17
+ # LDAP_ENCRYPTION=start_tls # Use 'start_tls' for port 389 or 'simple_tls' for port 636 (LDAPS)
18
+ # LDAP_DEPT_ATTRIBUTE=umichPostalAddressData
19
+ # LDAP_GROUP_ATTRIBUTE=umichGroupEmail
20
+ # LDAP_TLS_VERIFY=true # Set to false to disable cert verification (dev only)
21
+ # LDAP_CA_CERT=/path/to/ca-bundle.pem
22
+ #
23
+ # If STARTTLS (port 389) doesn't work, try LDAPS:
24
+ # LDAP_PORT=636
25
+ # LDAP_ENCRYPTION=simple_tls
data/.gitignore CHANGED
@@ -7,3 +7,8 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
  *.gem
10
+
11
+ # Environment variables
12
+ .env
13
+ .env.local
14
+ .env.*.local
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ --color
data/.rspec_status ADDED
@@ -0,0 +1,46 @@
1
+ example_id | status | run_time |
2
+ ------------------------------------- | ------ | --------------- |
3
+ ./spec/configuration_spec.rb[1:1:1:1] | passed | 0.00021 seconds |
4
+ ./spec/configuration_spec.rb[1:1:1:2] | passed | 0.00004 seconds |
5
+ ./spec/configuration_spec.rb[1:1:1:3] | passed | 0.00004 seconds |
6
+ ./spec/configuration_spec.rb[1:1:2:1] | passed | 0.00149 seconds |
7
+ ./spec/configuration_spec.rb[1:1:2:2] | passed | 0.00004 seconds |
8
+ ./spec/configuration_spec.rb[1:1:3:1] | passed | 0.00004 seconds |
9
+ ./spec/configuration_spec.rb[1:1:3:2] | passed | 0.00005 seconds |
10
+ ./spec/configuration_spec.rb[1:2:1] | passed | 0.00002 seconds |
11
+ ./spec/configuration_spec.rb[1:2:2] | passed | 0.00003 seconds |
12
+ ./spec/configuration_spec.rb[1:3:1] | passed | 0.00003 seconds |
13
+ ./spec/configuration_spec.rb[1:3:2] | passed | 0.00003 seconds |
14
+ ./spec/configuration_spec.rb[1:3:3] | passed | 0.00003 seconds |
15
+ ./spec/ldap_lookup_spec.rb[1:1:1:1] | passed | 0.63596 seconds |
16
+ ./spec/ldap_lookup_spec.rb[1:1:2:1] | passed | 0.61562 seconds |
17
+ ./spec/ldap_lookup_spec.rb[1:1:3:1] | passed | 0.60601 seconds |
18
+ ./spec/ldap_lookup_spec.rb[1:2:1:1] | passed | 0.64499 seconds |
19
+ ./spec/ldap_lookup_spec.rb[1:2:2:1] | passed | 0.6525 seconds |
20
+ ./spec/ldap_lookup_spec.rb[1:3:1:1] | passed | 0.66369 seconds |
21
+ ./spec/ldap_lookup_spec.rb[1:3:2:1] | passed | 1.29 seconds |
22
+ ./spec/ldap_lookup_spec.rb[1:4:1:1] | passed | 0.64139 seconds |
23
+ ./spec/ldap_lookup_spec.rb[1:4:2:1] | passed | 0.64128 seconds |
24
+ ./spec/ldap_lookup_spec.rb[1:5:1:1] | passed | 1.69 seconds |
25
+ ./spec/ldap_lookup_spec.rb[1:5:2:1] | passed | 0.75576 seconds |
26
+ ./spec/ldap_lookup_spec.rb[1:5:3:1] | passed | 0.70272 seconds |
27
+ ./spec/ldap_lookup_spec.rb[1:5:4:1] | passed | 0.74101 seconds |
28
+ ./spec/ldap_lookup_spec.rb[1:6:1:1] | passed | 0.78507 seconds |
29
+ ./spec/ldap_lookup_spec.rb[1:6:1:2] | passed | 0.77477 seconds |
30
+ ./spec/ldap_lookup_spec.rb[1:6:1:3] | passed | 0.74474 seconds |
31
+ ./spec/ldap_lookup_spec.rb[1:6:2:1] | passed | 0.70436 seconds |
32
+ ./spec/ldap_lookup_spec.rb[1:7:1:1] | passed | 13.94 seconds |
33
+ ./spec/ldap_lookup_spec.rb[1:7:1:2] | passed | 21.97 seconds |
34
+ ./spec/ldap_lookup_spec.rb[1:7:1:3] | passed | 27.87 seconds |
35
+ ./spec/ldap_lookup_spec.rb[1:7:2:1] | passed | 7.88 seconds |
36
+ ./spec/ldap_lookup_spec.rb[1:8:1:1] | passed | 0.0026 seconds |
37
+ ./spec/ldap_lookup_spec.rb[1:8:1:2] | passed | 0.00012 seconds |
38
+ ./spec/ldap_lookup_spec.rb[1:8:1:3] | passed | 0.00009 seconds |
39
+ ./spec/ldap_lookup_spec.rb[1:8:2:1] | passed | 0.0001 seconds |
40
+ ./spec/ldap_lookup_spec.rb[1:8:3:1] | passed | 0.0001 seconds |
41
+ ./spec/ldap_lookup_spec.rb[1:9:1:1] | passed | 0.0001 seconds |
42
+ ./spec/ldap_lookup_spec.rb[1:9:2:1] | passed | 0.00009 seconds |
43
+ ./spec/ldap_lookup_spec.rb[1:10:1:1] | passed | 0.525 seconds |
44
+ ./spec/ldap_lookup_spec.rb[1:10:2:1] | passed | 0.46772 seconds |
45
+ ./spec/ldap_lookup_spec.rb[1:11:1:1] | failed | 0.54755 seconds |
46
+ ./spec/ldap_lookup_spec.rb[1:11:2:1] | passed | 0.47023 seconds |
data/Gemfile.lock CHANGED
@@ -1,14 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ldap_lookup (0.1.7)
5
- net-ldap (~> 0.17.0)
4
+ ldap_lookup (0.1.8)
5
+ net-ldap (~> 0.18.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  diff-lcs (1.3)
11
- net-ldap (0.17.1)
11
+ dotenv (2.8.1)
12
+ net-ldap (0.18.0)
12
13
  rake (13.0.1)
13
14
  rspec (3.7.0)
14
15
  rspec-core (~> 3.7.0)
@@ -29,6 +30,7 @@ PLATFORMS
29
30
 
30
31
  DEPENDENCIES
31
32
  bundler (~> 2.2.26)
33
+ dotenv (~> 2.8)
32
34
  ldap_lookup!
33
35
  rake (~> 13.0)
34
36
  rspec (~> 3.7.0)
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # LdapLookup for Ruby [![Gem Version](https://badge.fury.io/rb/ldap_lookup.svg)](https://badge.fury.io/rb/ldap_lookup)
2
2
 
3
3
  ### Description
4
- This module is to be used for anonymous lookup of user attributes in the MCommunity service provide at the University of Michigan. It can be easily modifed to use other LDAP server configurations.
4
+ This module is to be used for authenticated or anonymous lookup of user attributes in the MCommunity service provided at the University of Michigan. It supports authenticated LDAP binds with encryption as per UM IT Security requirements (effective Jan 20, 2026). It can be easily modified to use other LDAP server configurations.
5
5
 
6
6
  ---
7
7
 
@@ -9,7 +9,7 @@ This module is to be used for anonymous lookup of user attributes in the MCommun
9
9
 
10
10
  Requirements:
11
11
  * Ruby at least 2.0.0
12
- * Gem 'net-ldap' ~> '0.16.1'
12
+ * Gem 'net-ldap' ~> '0.17.0'
13
13
  > *The Net::LDAP (aka net-ldap) gem before 0.16.0 for Ruby has a Missing SSL Certificate Validation.*
14
14
 
15
15
  To try the module out:
@@ -18,13 +18,24 @@ To try the module out:
18
18
  <pre>
19
19
  LdapLookup.configuration do |config|
20
20
  config.host = <em>< your host ></em> # "ldap.umich.edu"
21
- config.port = <em>< your port ></em> # "986" the default is set to "389" so this optional
21
+ config.port = <em>< your port ></em> # "389" (default) for STARTTLS, "636" for LDAPS
22
22
  config.base = <em>< your LDAP base ></em> # "dc=umich,dc=edu"
23
+ config.username = <em>< your uniqname ></em> # Your UM uniqname (e.g., "rsmoke")
24
+ config.password = <em>< your password ></em> # Your UM password
25
+ config.encryption = :start_tls # :start_tls (default, port 389) or :simple_tls (LDAPS, port 636)
23
26
  config.dept_attribute = <em>< your dept attribute ></em> # "umichPostalAddressData"
24
27
  config.group_attribute = <em>< your group email attribute ></em> # "umichGroupEmail"
25
28
  end
26
29
  </pre>
27
30
 
31
+ **Important:** As of January 20, 2026, UM LDAP requires:
32
+ - **Authenticated binds only** - Anonymous (unauthenticated) binds are not supported by UM LDAP
33
+ - Username and password are required for UM LDAP connections
34
+ - Encrypted connections (STARTTLS or LDAPS) are mandatory
35
+ - The gem uses LDAP "simple bind" authentication (authenticated with username/password)
36
+
37
+ The gem can also perform **anonymous binds** for LDAP servers that allow them. To use anonymous binds, leave `LDAP_USERNAME` and `LDAP_PASSWORD` unset.
38
+
28
39
  3. run the ldaptest.rb script
29
40
  ```ruby
30
41
  ruby ./ldaptest.rb
@@ -34,58 +45,173 @@ ruby ./ldaptest.rb
34
45
 
35
46
  ### Installation
36
47
 
48
+ #### Step 1: Add to Gemfile
49
+
37
50
  Add this line to your application's Gemfile:
38
51
 
39
52
  ```ruby
40
53
  gem 'ldap_lookup'
41
54
  ```
42
55
 
43
- And then execute:
56
+ Then run:
44
57
 
45
- $ bundle
58
+ ```bash
59
+ bundle install
60
+ ```
46
61
 
47
- Or install it yourself as:
62
+ #### Step 2: Get LDAP Credentials
48
63
 
49
- $ gem install ldap_lookup
64
+ **For Production Applications (Recommended):**
65
+ Request a **service account** from your IT department. Service accounts are designed for automated applications and don't require password changes.
50
66
 
51
- In your application create a file config/initializers/ldap_lookup.rb
52
- <pre>
67
+ **For Development/Testing:**
68
+ You can use your personal UM uniqname and password temporarily, but switch to a service account for production.
69
+
70
+ #### Step 3: Configure the Gem
71
+
72
+ **For Rails Applications:**
73
+
74
+ Create `config/initializers/ldap_lookup.rb`:
75
+
76
+ ```ruby
53
77
  LdapLookup.configuration do |config|
54
- config.host = <em>< your host ></em> # "ldap.umich.edu"
55
- config.port = <em>< your port ></em> # "954" port 389 is set by default
56
- config.base = <em>< your LDAP base ></em> # "dc=umich,dc=edu"
57
- config.dept_attribute = <em>< your dept attribute ></em> # "umichPostalAddressData"
58
- config.group_attribute = <em>< your group email attribute ></em> # "umichGroupEmail"
78
+ # Server Configuration (defaults work for UM LDAP)
79
+ config.host = ENV.fetch('LDAP_HOST', 'ldap.umich.edu')
80
+ config.port = ENV.fetch('LDAP_PORT', '389')
81
+ config.base = ENV.fetch('LDAP_BASE', 'dc=umich,dc=edu')
82
+
83
+ # Authentication (optional for anonymous binds)
84
+ # Leave unset to use anonymous binds (if your LDAP server allows it)
85
+ config.username = ENV['LDAP_USERNAME']
86
+ config.password = ENV['LDAP_PASSWORD']
87
+
88
+ # If using a service account with custom bind DN, uncomment and set:
89
+ # config.bind_dn = 'cn=service-account,ou=Service Accounts,dc=umich,dc=edu'
90
+
91
+ # Encryption - REQUIRED (defaults to STARTTLS)
92
+ config.encryption = ENV.fetch('LDAP_ENCRYPTION', 'start_tls').to_sym
93
+ # Use :simple_tls for LDAPS on port 636
94
+ # TLS verification (defaults to true). Set LDAP_TLS_VERIFY=false only for local testing.
95
+ # Optional custom CA bundle: set LDAP_CA_CERT=/path/to/ca-bundle.pem
96
+
97
+ # Optional: Attribute Configuration
98
+ config.dept_attribute = ENV.fetch('LDAP_DEPT_ATTRIBUTE', 'umichPostalAddressData')
99
+ config.group_attribute = ENV.fetch('LDAP_GROUP_ATTRIBUTE', 'umichGroupEmail')
59
100
  end
60
- </pre>
101
+ ```
102
+
103
+ **For Non-Rails Applications:**
104
+
105
+ Configure in your application startup:
106
+
107
+ ```ruby
108
+ require 'ldap_lookup'
109
+
110
+ LdapLookup.configuration do |config|
111
+ config.host = 'ldap.umich.edu'
112
+ config.base = 'dc=umich,dc=edu'
113
+ config.username = ENV['LDAP_USERNAME']
114
+ config.password = ENV['LDAP_PASSWORD']
115
+ config.encryption = :start_tls
116
+ end
117
+ ```
118
+
119
+ #### Step 4: Set Environment Variables
120
+
121
+ **Never hardcode credentials in your code!** Use environment variables (Hatchbox, Heroku, etc.):
122
+
123
+ ```bash
124
+ # In your .env file (for development)
125
+ LDAP_USERNAME=your_service_account_uniqname
126
+ LDAP_PASSWORD=your_service_account_password
127
+
128
+ # Or export in your shell
129
+ export LDAP_USERNAME=your_service_account_uniqname
130
+ export LDAP_PASSWORD=your_service_account_password
131
+
132
+ # You can also set these (all can be changed without redeploying):
133
+ # LDAP_HOST, LDAP_PORT, LDAP_BASE, LDAP_ENCRYPTION, LDAP_TLS_VERIFY, LDAP_CA_CERT
134
+ ```
135
+
136
+ **For Production:**
137
+ - Use your platform's secrets management (Rails credentials, AWS Secrets Manager, etc.)
138
+ - Never commit credentials to version control
139
+ - Use service accounts, not personal accounts
140
+
141
+ #### Service Account Bind DN
142
+
143
+ If your service account uses a non-standard bind DN format, you can specify it:
144
+
145
+ ```ruby
146
+ config.bind_dn = 'cn=my-service-account,ou=Service Accounts,dc=umich,dc=edu'
147
+ ```
148
+
149
+ If `bind_dn` is not set, it defaults to: `uid=username,ou=People,base`
61
150
 
62
151
  ---
63
152
 
64
153
  ### Methods available
65
154
 
155
+ __uid_exist?:__ returns true if uid is in LDAP
156
+ ```
157
+ LdapLookup.uid_exist?(uniqname)
158
+ response: true or false (boolean)
159
+ ```
66
160
  __get_simple_name:__ returns the Display Name
67
161
  ```
68
162
  LdapLookup.get_simple_name(uniqname = nil)
163
+ response: name or "No #{attribute} found for #{uniqname}"
69
164
  ```
70
165
  __get_dept:__ returns the users Department_name
71
166
  ```
72
167
  LdapLookup.get_dept(uniqname = nil)
168
+ response: dept name or "No #{nested_attribute} found for #{uniqname}"
73
169
  ```
74
170
  __get_email:__ returns the users email address
75
171
  ```
76
172
  LdapLookup.get_email(uniqname = nil)
173
+ response: email or "No #{attribute} found for #{uniqname}"
77
174
  ```
78
175
  __is_member_of_group?:__ returns true/false if uniqname is a member of the specified group
79
176
  ```
80
177
  LdapLookup.is_member_of_group?(uid = nil, group_name = nil)
178
+ response: true or false (boolean)
81
179
  ```
82
180
  __get_email_distribution_list:__ Returns the list of emails that are associated to a group.
83
181
  ```
84
182
  LdapLookup.get_email_distribution_list(group_name = nil)
183
+ response: result_hash
85
184
  ```
86
185
  __all_groups_for_user:__ Returns the list of groups that a user is a member of.
87
186
  ```
88
187
  LdapLookup.all_groups_for_user(uniqname = nil)
188
+ response: result_array
189
+ ```
190
+
191
+ ### Running Tests
192
+
193
+ **Security Note:** Never put passwords in command line arguments. They are visible in process lists and shell history.
194
+
195
+ **Recommended: Use a .env file (most secure)**
196
+ 1. Copy the example file: `cp .env.example .env`
197
+ 2. Edit `.env` with your credentials:
198
+ ```
199
+ LDAP_USERNAME=your_uniqname
200
+ LDAP_PASSWORD=your_password
201
+ ```
202
+ 3. Run tests: `bundle exec rspec`
203
+
204
+ **Alternative: Export environment variables**
205
+ ```bash
206
+ export LDAP_USERNAME=your_uniqname
207
+ export LDAP_PASSWORD=your_password
208
+ bundle exec rspec
209
+ ```
210
+
211
+ **Never do this (insecure):**
212
+ ```bash
213
+ # ❌ DON'T: Password visible in process list
214
+ LDAP_PASSWORD=xxx bundle exec rspec
89
215
  ```
90
216
 
91
217
  ### Contributing
data/SETUP.md ADDED
@@ -0,0 +1,117 @@
1
+ # Quick Setup Guide for Gem Users
2
+
3
+ This guide will help you quickly set up `ldap_lookup` in your Rails application.
4
+
5
+ ## Prerequisites
6
+
7
+ 1. **Get LDAP Credentials**
8
+ - For production: Request a service account from your IT department
9
+ - For development: You can temporarily use your personal uniqname/password
10
+
11
+ ## Installation Steps
12
+
13
+ ### 1. Add to Gemfile
14
+
15
+ ```ruby
16
+ gem 'ldap_lookup'
17
+ ```
18
+
19
+ Run `bundle install`
20
+
21
+ ### 2. Create Initializer
22
+
23
+ Copy the example initializer:
24
+
25
+ ```bash
26
+ # If you have the gem source
27
+ cp config/initializers/ldap_lookup.rb.example config/initializers/ldap_lookup.rb
28
+
29
+ # Or create it manually
30
+ touch config/initializers/ldap_lookup.rb
31
+ ```
32
+
33
+ ### 3. Configure Credentials
34
+
35
+ Edit `config/initializers/ldap_lookup.rb`:
36
+
37
+ ```ruby
38
+ LdapLookup.configuration do |config|
39
+ config.host = ENV.fetch('LDAP_HOST', 'ldap.umich.edu')
40
+ config.base = ENV.fetch('LDAP_BASE', 'dc=umich,dc=edu')
41
+ # Leave unset to use anonymous binds (if your LDAP server allows it)
42
+ config.username = ENV['LDAP_USERNAME']
43
+ config.password = ENV['LDAP_PASSWORD']
44
+ config.encryption = :start_tls
45
+ end
46
+ ```
47
+
48
+ ### 4. Set Environment Variables
49
+
50
+ **Development (.env file):**
51
+ ```bash
52
+ LDAP_USERNAME=your_service_account
53
+ LDAP_PASSWORD=your_password
54
+ ```
55
+
56
+ **Production:**
57
+ Use your platform's secrets management:
58
+ - Rails: `config/credentials.yml.enc`
59
+ - Heroku: `heroku config:set LDAP_USERNAME=xxx`
60
+ - AWS: Secrets Manager
61
+ - etc.
62
+
63
+ ### 5. Service Account Bind DN (if needed)
64
+
65
+ If your service account uses a custom bind DN format, add:
66
+
67
+ ```ruby
68
+ config.bind_dn = 'cn=service-account,ou=Service Accounts,dc=umich,dc=edu'
69
+ ```
70
+
71
+ Your IT department will provide this if it's different from the default format.
72
+
73
+ ## Usage
74
+
75
+ ```ruby
76
+ # Check if a user exists
77
+ LdapLookup.uid_exist?('uniqname')
78
+
79
+ # Get user's name
80
+ LdapLookup.get_simple_name('uniqname')
81
+
82
+ # Get user's email
83
+ LdapLookup.get_email('uniqname')
84
+
85
+ # Get user's department
86
+ LdapLookup.get_dept('uniqname')
87
+
88
+ # Check group membership
89
+ LdapLookup.is_member_of_group?('uniqname', 'group-name')
90
+
91
+ # Get all groups for a user
92
+ LdapLookup.all_groups_for_user('uniqname')
93
+ ```
94
+
95
+ ## Troubleshooting
96
+
97
+ **Anonymous bind fails**
98
+ - Your LDAP server may require authenticated binds
99
+ - Set `LDAP_USERNAME` and `LDAP_PASSWORD` (service account recommended)
100
+ - Verify credentials are correct
101
+
102
+ **Error: Connection timeout or SSL errors**
103
+ - Verify `config.host` is correct
104
+ - Try `config.encryption = :simple_tls` with `config.port = '636'` for LDAPS
105
+ - Check firewall rules allow outbound LDAP connections
106
+
107
+ **Service account not working**
108
+ - Verify the bind DN format with your IT department
109
+ - Set `config.bind_dn` if your service account uses a non-standard format
110
+
111
+ ## Security Reminders
112
+
113
+ - ✅ Use environment variables for credentials
114
+ - ✅ Use service accounts in production
115
+ - ✅ Never commit credentials to version control
116
+ - ❌ Don't hardcode passwords in code
117
+ - ❌ Don't use personal accounts in production
@@ -0,0 +1,32 @@
1
+ # LDAP Lookup Configuration
2
+ # Copy this file to config/initializers/ldap_lookup.rb and configure with your credentials
3
+ #
4
+ # IMPORTANT: Never commit credentials to version control!
5
+ # Use environment variables or a secrets management system.
6
+
7
+ LdapLookup.configuration do |config|
8
+ # LDAP Server Configuration
9
+ config.host = ENV.fetch('LDAP_HOST', 'ldap.umich.edu')
10
+ config.port = ENV.fetch('LDAP_PORT', '389')
11
+ config.base = ENV.fetch('LDAP_BASE', 'dc=umich,dc=edu')
12
+
13
+ # Authentication (optional for anonymous binds)
14
+ # Option 1: Use a service account (recommended for production)
15
+ # Request a service account from your IT department
16
+ # Leave unset to use anonymous binds (if your LDAP server allows it)
17
+ config.username = ENV['LDAP_USERNAME']
18
+ config.password = ENV['LDAP_PASSWORD']
19
+
20
+ # Option 2: If your service account uses a custom bind DN format, specify it:
21
+ # config.bind_dn = 'cn=service-account,ou=Service Accounts,dc=umich,dc=edu'
22
+ # (If bind_dn is not set, it defaults to: uid=username,ou=People,base)
23
+
24
+ # Encryption - REQUIRED (as of Jan 20, 2026)
25
+ # Use :start_tls for port 389 or :simple_tls for LDAPS on port 636
26
+ encryption_method = ENV.fetch('LDAP_ENCRYPTION', 'start_tls').to_sym
27
+ config.encryption = encryption_method
28
+
29
+ # Optional: Attribute Configuration
30
+ config.dept_attribute = ENV.fetch('LDAP_DEPT_ATTRIBUTE', 'umichPostalAddressData')
31
+ config.group_attribute = ENV.fetch('LDAP_GROUP_ATTRIBUTE', 'umichGroupEmail')
32
+ end
data/ldap_lookup.gemspec CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Rick Smoke"]
10
10
  spec.email = ["rsmoke@umich.edu"]
11
11
 
12
- spec.summary = %q{For anonymous lookup of user LDAP attributes.}
13
- spec.description = %q{This module is to be used for anonymous lookup of attributes in the MCommunity service provide at the University of Michigan. It can be easily modifed to use other LDAP server configurations.}
12
+ spec.summary = %q{Authenticated LDAP lookup for MCommunity user attributes at University of Michigan.}
13
+ spec.description = %q{This gem provides authenticated LDAP lookups for user attributes in the MCommunity service at the University of Michigan. It supports encrypted connections (STARTTLS/LDAPS) and service accounts as required by UM IT Security (effective Jan 20, 2026). Can be easily modified for other LDAP server configurations.}
14
14
  spec.homepage = "https://github.com/rsmoke/ldap_lookup.git"
15
15
  spec.license = "MIT"
16
16
 
@@ -24,5 +24,6 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "bundler", "~> 2.2.26"
25
25
  spec.add_development_dependency "rake", "~> 13.0"
26
26
  spec.add_development_dependency "rspec", "~> 3.7.0"
27
- spec.add_dependency 'net-ldap', '~> 0.17.0'
27
+ spec.add_development_dependency "dotenv", "~> 2.8"
28
+ spec.add_dependency 'net-ldap', '~> 0.18.0'
28
29
  end
data/ldaptest.rb CHANGED
@@ -1,5 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # Load .env file if it exists (for local development)
4
+ begin
5
+ require 'dotenv/load'
6
+ rescue LoadError
7
+ # dotenv not available, will use environment variables or fallbacks
8
+ end
9
+
3
10
  require_relative "lib/ldap_lookup"
4
11
 
5
12
  class Ldaptest
@@ -7,10 +14,20 @@ class Ldaptest
7
14
 
8
15
  ############## CONFIGURATION BLOCK ###################
9
16
  LdapLookup.configuration do |config|
10
- config.host = "ldap.umich.edu"
11
- config.base = "dc=umich,dc=edu"
12
- config.dept_attribute = "umichPostalAddressData"
13
- config.group_attribute = "umichGroupEmail"
17
+ config.host = ENV['LDAP_HOST'] || "ldap.umich.edu"
18
+ config.port = ENV['LDAP_PORT'] || "389"
19
+ config.base = ENV['LDAP_BASE'] || "dc=umich,dc=edu"
20
+ # Leave username/password unset for anonymous binds
21
+ config.username = ENV['LDAP_USERNAME']
22
+ config.password = ENV['LDAP_PASSWORD']
23
+ # Read encryption from ENV, default to start_tls
24
+ encryption_str = ENV['LDAP_ENCRYPTION'] || 'start_tls'
25
+ config.encryption = encryption_str.to_sym
26
+ config.dept_attribute = ENV['LDAP_DEPT_ATTRIBUTE'] || "umichPostalAddressData"
27
+ config.group_attribute = ENV['LDAP_GROUP_ATTRIBUTE'] || "umichGroupEmail"
28
+ # Enable LDAP debug logging in this test runner
29
+ debug_str = ENV['LDAP_DEBUG']
30
+ config.debug = debug_str ? debug_str.to_s.downcase == 'true' : true
14
31
  end
15
32
  #######################################################
16
33
 
@@ -32,7 +49,7 @@ class Ldaptest
32
49
  end
33
50
 
34
51
  def result_box(answer)
35
- print "\e[2J\e[f"
52
+ # print "\e[2J\e[f"
36
53
  2.times { puts " " }
37
54
  puts "Your Results"
38
55
  puts "======================================================"
@@ -56,6 +73,7 @@ class Ldaptest
56
73
  puts "2: set new group_uid"
57
74
  puts "+++++++++++++++++++++++++"
58
75
  puts "3: get users full name"
76
+ puts "33: check if uid exists"
59
77
  puts "4: get users department"
60
78
  puts "5: get users email"
61
79
  puts "55: get all groups a user is a member of"
@@ -64,23 +82,28 @@ class Ldaptest
64
82
  puts "7: check if uid is member of a group"
65
83
  puts "+++++++++++++++++++++++++"
66
84
  puts "8: what time is it?"
85
+ puts "99: test LDAP connection (diagnostic)"
67
86
  puts "0: exit"
87
+ puts ""
88
+ print "Enter a number: "
68
89
 
69
90
  case gets.chomp.to_i
70
91
  when 1 then result_box(reset_uid)
71
92
  when 2 then result_box(reset_group_uid)
72
93
  when 3 then result_box(LdapLookup.get_simple_name(@uid))
94
+ when 33 then result_box(LdapLookup.uid_exist?(@uid))
73
95
  when 4 then result_box(LdapLookup.get_dept(@uid))
74
96
  when 5 then result_box(LdapLookup.get_email(@uid))
75
97
  when 55 then result_box(LdapLookup.all_groups_for_user(@uid))
76
98
  when 6 then result_box(LdapLookup.get_email_distribution_list(@group_uid))
77
99
  when 7 then result_box(LdapLookup.is_member_of_group?(@uid, @group_uid))
78
100
  when 8 then result_box(timestamp)
101
+ when 99 then result_box(LdapLookup.test_connection.inspect)
79
102
  when 0 then puts "you chose exit!"
80
103
  throw(:done)
81
104
  else
82
105
  print "\e[2J\e[f"
83
- puts "====> Please type 1,2,3,4,5,55,6,7,8 or 0 only"
106
+ puts "====> Please type 1,2,3,33,4,5,55,6,7,8 or 0 only"
84
107
  2.times { puts " " }
85
108
  end
86
109
  end
@@ -1,3 +1,3 @@
1
1
  module LdapLookup
2
- VERSION = "0.1.7"
2
+ VERSION = "2.0.0"
3
3
  end