LDAP-Monitor 2.0.0__tar.gz → 2.0.1__tar.gz
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.
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/LDAP_Monitor.egg-info/PKG-INFO +52 -39
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/LDAP_Monitor.egg-info/SOURCES.txt +4 -1
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/LICENSE +81 -68
- ldap_monitor-2.0.1/MANIFEST.in +3 -0
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/PKG-INFO +52 -39
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/README.md +49 -35
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/ldap_watchdog/__init__.py +1 -1
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/ldap_watchdog/config.py +25 -10
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/ldap_watchdog/watchdog.py +1 -1
- ldap_monitor-2.0.1/pyproject.toml +3 -0
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/setup.py +2 -2
- ldap_monitor-2.0.1/tests/certs/ldap.example.com.pem +16 -0
- ldap_monitor-2.0.1/tests/certs/localhost.pem +15 -0
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/tests/test_watchdog.py +48 -0
- ldap_monitor-2.0.0/MANIFEST.in +0 -2
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/LDAP_Monitor.egg-info/dependency_links.txt +0 -0
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/LDAP_Monitor.egg-info/entry_points.txt +0 -0
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/LDAP_Monitor.egg-info/requires.txt +0 -0
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/LDAP_Monitor.egg-info/top_level.txt +0 -0
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/ldap_watchdog/__main__.py +0 -0
- {ldap_monitor-2.0.0 → ldap_monitor-2.0.1}/setup.cfg +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: LDAP-Monitor
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.1
|
|
4
4
|
Summary: Monitor LDAP directory changes in real-time
|
|
5
5
|
Home-page: https://github.com/MegaManSec/LDAP-Monitoring-Watchdog
|
|
6
6
|
Author: Joshua Rogers
|
|
7
7
|
Author-email: ldap-watchdog@joshua.hu
|
|
8
|
-
License: GPL-3.0
|
|
8
|
+
License-Expression: GPL-3.0-or-later
|
|
9
9
|
Project-URL: Blog Post, https://joshua.hu/ldap-watchdog-openldap-python-monitoring-tool-realtime-directory-slack-notifications
|
|
10
10
|
Project-URL: Author, https://joshua.hu/
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -13,7 +13,6 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
17
16
|
Classifier: Operating System :: OS Independent
|
|
18
17
|
Classifier: Topic :: System :: Monitoring
|
|
19
18
|
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory :: LDAP
|
|
@@ -30,8 +29,8 @@ Dynamic: classifier
|
|
|
30
29
|
Dynamic: description
|
|
31
30
|
Dynamic: description-content-type
|
|
32
31
|
Dynamic: home-page
|
|
33
|
-
Dynamic: license
|
|
34
32
|
Dynamic: license-file
|
|
33
|
+
Dynamic: license-expression
|
|
35
34
|
Dynamic: project-url
|
|
36
35
|
Dynamic: provides-extra
|
|
37
36
|
Dynamic: requires-dist
|
|
@@ -43,12 +42,12 @@ Dynamic: summary
|
|
|
43
42
|
## Overview
|
|
44
43
|
LDAP Watchdog is a tool designed to monitor record changes in an LDAP directory in real-time.
|
|
45
44
|
It provides a mechanism to track and visualize modifications, additions, and removals to user and group entries, allowing users to correlate expected changes with actual changes and identify potential security incidents.
|
|
46
|
-
It was created with OpenLDAP and Linux in mind,
|
|
47
|
-
It is written in Python and
|
|
45
|
+
It was created with OpenLDAP and Linux in mind, and needs a server that gives every entry an `entryUUID` (RFC 4530), so Active Directory, which uses `objectGUID` instead, is not supported.
|
|
46
|
+
It is written in Python and requires the ldap3 library, plus requests for Slack notifications.
|
|
48
47
|
|
|
49
48
|
This software was written by [Joshua Rogers](https://joshua.hu/).
|
|
50
49
|
|
|
51
|
-
If you're
|
|
50
|
+
If you're interested in any of the following, then LDAP Watchdog is for you:
|
|
52
51
|
- Know what's going on in your LDAP directory on-demand with Slack webhook integration.
|
|
53
52
|
- See new hires, leavers, and promotions as they appear in LDAP.
|
|
54
53
|
- Monitor _when_ and what HR is doing.
|
|
@@ -58,7 +57,7 @@ If you're interesting in any of the following, then LDAP Watchdog is for you:
|
|
|
58
57
|
|
|
59
58
|
In addition to monitoring for modifications, additions, and removals in an LDAP directory, it can be configured to ignore specific attributes, or even fine-tuned to ignore fine-grained attributes depending on their old/new values.
|
|
60
59
|
|
|
61
|
-
|
|
60
|
+
Changes are always printed to the terminal, and are also forwarded to a Slack webhook if one is configured. Colored output can be turned off.
|
|
62
61
|
|
|
63
62
|
Previously named LDAP-Stalker (because monitoring changes of an LDAP directory is an excellent way to stalk changes in a company: learn about promotions before they're announced, new hires, leavers, etc.), a blog post about the details and history of this project [can be found here](https://joshua.hu/ldap-watchdog-openldap-python-monitoring-tool-realtime-directory-slack-notifications).
|
|
64
63
|
|
|
@@ -90,7 +89,7 @@ Note: in the below examples, changes to entryCSN and modifyTimestamp on existing
|
|
|
90
89
|
|
|
91
90
|
7. **Ignored Entries and Attributes:** Users can specify UUIDs and attributes to ignore when comparing changes to existing entries.
|
|
92
91
|
|
|
93
|
-
8. **Conditional Ignored Attributes:**
|
|
92
|
+
8. **Conditional Ignored Attributes:** Users can ignore changes to an attribute only when they involve specific values, such as one group in `memberOf`.
|
|
94
93
|
|
|
95
94
|
|
|
96
95
|
## Requirements
|
|
@@ -108,7 +107,7 @@ pip install LDAP-Monitor
|
|
|
108
107
|
To include Slack webhook support:
|
|
109
108
|
|
|
110
109
|
```bash
|
|
111
|
-
pip install LDAP-Monitor[slack]
|
|
110
|
+
pip install "LDAP-Monitor[slack]"
|
|
112
111
|
```
|
|
113
112
|
|
|
114
113
|
### Docker
|
|
@@ -131,6 +130,12 @@ cd LDAP-Monitoring-Watchdog
|
|
|
131
130
|
pip install ".[slack]"
|
|
132
131
|
```
|
|
133
132
|
|
|
133
|
+
### Upgrading
|
|
134
|
+
|
|
135
|
+
**From 1.x:** Since 2.0.0, LDAPS connections verify the server certificate and that it matches the host name or IP address in `LDAP_WATCHDOG_SERVER`; 1.0.0 checked neither. Before upgrading, set `LDAP_WATCHDOG_CA_CERTS_FILE` if the certificate is self-signed or from a private CA, and if it does not match that name, use a matching certificate or set `LDAP_WATCHDOG_TLS_VERIFY=false` (see the TLS notes under [Configuration](#configuration)). The [release notes](https://github.com/MegaManSec/LDAP-Monitoring-Watchdog/releases/tag/v2.0.0) list the other changes.
|
|
136
|
+
|
|
137
|
+
**From 1.x or 2.0.0:** Since 2.0.1, boolean settings only accept the values listed under [Configuration](#configuration). Earlier versions read anything other than `true`, `1` or `yes` as false. Now an unrecognized value stops the process at startup, an empty value means the default, and `on` or a quoted `"true"` means true. For example, an empty `LDAP_WATCHDOG_USE_SSL` with a bare host name now connects with LDAPS on port 636 instead of plain LDAP on port 389.
|
|
138
|
+
|
|
134
139
|
## Usage
|
|
135
140
|
|
|
136
141
|
### Running with pip install
|
|
@@ -138,7 +143,7 @@ pip install ".[slack]"
|
|
|
138
143
|
```bash
|
|
139
144
|
export LDAP_WATCHDOG_SERVER='ldaps://ldaps.intra.lan'
|
|
140
145
|
export LDAP_WATCHDOG_BASE_DN='dc=mouse,dc=com'
|
|
141
|
-
export LDAP_WATCHDOG_USERNAME='Emily'
|
|
146
|
+
export LDAP_WATCHDOG_USERNAME='cn=Emily,ou=People,dc=mouse,dc=com'
|
|
142
147
|
export LDAP_WATCHDOG_PASSWORD='qwerty123'
|
|
143
148
|
ldap-watchdog
|
|
144
149
|
```
|
|
@@ -152,34 +157,37 @@ python -m ldap_watchdog
|
|
|
152
157
|
### Running with Docker
|
|
153
158
|
|
|
154
159
|
```bash
|
|
155
|
-
docker run -d \
|
|
160
|
+
docker run -d --restart unless-stopped \
|
|
156
161
|
-e LDAP_WATCHDOG_SERVER='ldaps://ldaps.intra.lan' \
|
|
157
162
|
-e LDAP_WATCHDOG_BASE_DN='dc=mouse,dc=com' \
|
|
158
|
-
-e LDAP_WATCHDOG_USERNAME='Emily' \
|
|
163
|
+
-e LDAP_WATCHDOG_USERNAME='cn=Emily,ou=People,dc=mouse,dc=com' \
|
|
159
164
|
-e LDAP_WATCHDOG_PASSWORD='qwerty123' \
|
|
160
165
|
-e SLACK_WEBHOOK_URL='https://hooks.slack.com/services/[...]' \
|
|
161
|
-
-e LDAP_WATCHDOG_IGNORED_ATTRIBUTES='modifyTimestamp,
|
|
166
|
+
-e LDAP_WATCHDOG_IGNORED_ATTRIBUTES='entryCSN,modifyTimestamp,telephoneNumber,roomNumber,gecos' \
|
|
167
|
+
-e LDAP_WATCHDOG_DISABLE_COLOR_OUTPUT='true' \
|
|
162
168
|
megamansec/ldap-monitor
|
|
163
169
|
```
|
|
164
170
|
|
|
165
171
|
### Systemd Installation (Debian-based)
|
|
166
172
|
|
|
167
|
-
A Debian-based installation script, [install.sh](https://github.com/MegaManSec/LDAP-Monitoring-Watchdog/blob/main/install.sh), is provided. When run as root from a clone of this repository, this script:
|
|
173
|
+
A Debian-based installation script, [install.sh](https://github.com/MegaManSec/LDAP-Monitoring-Watchdog/blob/main/install.sh), is provided. It needs Python 3.10 or later and the `python3-venv` package. When run as root from a clone of this repository, this script:
|
|
168
174
|
|
|
169
175
|
1. Creates (if necessary) a Python virtual environment in `/opt/ldap-watchdog`.
|
|
170
176
|
2. Installs LDAP Watchdog from the clone into that virtual environment, with the dependency versions pinned in `requirements.txt`.
|
|
171
|
-
3. Creates an environment file at `/etc/ldap-watchdog.env` for configuration.
|
|
172
|
-
4. Installs and
|
|
177
|
+
3. Creates an environment file at `/etc/ldap-watchdog.env` for configuration, unless one already exists.
|
|
178
|
+
4. Installs, enables and starts a systemd service (`/etc/systemd/system/ldap-watchdog.service`) that runs **ldap-watchdog** in the background as an unprivileged dynamic user, so a CA bundle must be world-readable.
|
|
173
179
|
5. Configures logging to `/var/log/ldap-watchdog.log` and `/var/log/ldap-watchdog-error.log`.
|
|
174
180
|
6. Sets up log rotation in `/etc/logrotate.d/ldap-watchdog`.
|
|
175
181
|
|
|
176
|
-
|
|
182
|
+
Rerunning the script from an updated clone upgrades the installation.
|
|
183
|
+
|
|
184
|
+
You may optionally pass a single argument to `install.sh` to set the `SLACK_WEBHOOK_URL` when the environment file is first created:
|
|
177
185
|
|
|
178
186
|
```bash
|
|
179
187
|
sudo ./install.sh "https://hooks.slack.com/services/[...]"
|
|
180
188
|
```
|
|
181
189
|
|
|
182
|
-
After installation, edit `/etc/ldap-watchdog.env` to configure the LDAP connection settings, then restart the service:
|
|
190
|
+
After installation, edit `/etc/ldap-watchdog.env` to configure the LDAP connection settings (the service fails until then), then restart the service:
|
|
183
191
|
|
|
184
192
|
```bash
|
|
185
193
|
sudo systemctl restart ldap-watchdog
|
|
@@ -187,24 +195,26 @@ sudo systemctl restart ldap-watchdog
|
|
|
187
195
|
|
|
188
196
|
## Configuration
|
|
189
197
|
|
|
190
|
-
All configuration is done via environment variables
|
|
198
|
+
All configuration is done via environment variables; an empty value is the same as an unset one, except for `LDAP_WATCHDOG_SLACK_BULLETPOINT`. The following variables are supported:
|
|
191
199
|
|
|
192
200
|
### General Settings
|
|
193
201
|
|
|
194
202
|
| Environment Variable | Description | Default |
|
|
195
203
|
|---|---|---|
|
|
196
|
-
| `LDAP_WATCHDOG_SERVER` | LDAP server URL (e.g. `ldaps://ldaps.intra.lan`) | `""` |
|
|
204
|
+
| `LDAP_WATCHDOG_SERVER` | LDAP server URL or host name (e.g. `ldaps://ldaps.intra.lan`). Required. | `""` |
|
|
197
205
|
| `LDAP_WATCHDOG_BASE_DN` | Base Distinguished Name for LDAP searches | `""` |
|
|
198
|
-
| `LDAP_WATCHDOG_USERNAME` |
|
|
199
|
-
| `LDAP_WATCHDOG_PASSWORD` |
|
|
200
|
-
| `LDAP_WATCHDOG_USE_SSL` | Set to `true` to use SSL, `false` otherwise | `true` |
|
|
206
|
+
| `LDAP_WATCHDOG_USERNAME` | Bind DN for authentication (e.g. `cn=Emily,ou=People,dc=mouse,dc=com`). If this or the password is empty, the bind is anonymous. | `""` |
|
|
207
|
+
| `LDAP_WATCHDOG_PASSWORD` | Password for `LDAP_WATCHDOG_USERNAME` | `""` |
|
|
208
|
+
| `LDAP_WATCHDOG_USE_SSL` | Set to `true` to use SSL (LDAPS, default port 636 instead of 389), `false` otherwise. An `ldaps://` or `ldap://` scheme in `LDAP_WATCHDOG_SERVER` overrides this. | `true` |
|
|
201
209
|
| `LDAP_WATCHDOG_CA_CERTS_FILE` | Optional PEM CA bundle for verifying the LDAP server certificate. If unset, system trust roots are used. | Unset |
|
|
202
210
|
| `LDAP_WATCHDOG_TLS_VERIFY` | Set to `false` to skip verifying the LDAP server certificate and host name. The connection is still encrypted but not authenticated. | `true` |
|
|
203
|
-
| `LDAP_WATCHDOG_SEARCH_FILTER` | LDAP filter for user and group entries | `(&(
|
|
211
|
+
| `LDAP_WATCHDOG_SEARCH_FILTER` | LDAP filter for user and group entries | `(&(\|(objectClass=inetOrgPerson)(objectClass=groupOfNames)))` |
|
|
204
212
|
| `LDAP_WATCHDOG_SEARCH_ATTRIBUTE` | Comma-separated list of attributes to retrieve. [`*,+`](https://joshua.hu/tracking-secret-ldap-login-times-with-modifytimestamp-heuristics) is used by default to include operational attributes. `entryUUID` is always requested and must be readable for every entry. | `*,+` |
|
|
205
|
-
| `LDAP_WATCHDOG_REFRESH_RATE` |
|
|
213
|
+
| `LDAP_WATCHDOG_REFRESH_RATE` | Whole number of seconds to wait after each LDAP search before the next one | `60` |
|
|
206
214
|
| `LDAP_WATCHDOG_NETWORK_TIMEOUT` | Positive integer timeout in seconds for LDAP and Slack connection/read operations. This limits individual waits, not the total duration of a poll. | `30` |
|
|
207
|
-
| `LDAP_WATCHDOG_DISABLE_COLOR_OUTPUT` | Set to `true` to disable colored
|
|
215
|
+
| `LDAP_WATCHDOG_DISABLE_COLOR_OUTPUT` | Set to `true` to disable colored output, which is used even when output goes to a file or `docker logs` | `false` |
|
|
216
|
+
|
|
217
|
+
Boolean settings accept `true`, `yes`, `on` or `1` and `false`, `no`, `off` or `0`, in any case and optionally quoted; any other value stops the process at startup.
|
|
208
218
|
|
|
209
219
|
LDAPS connections verify the server certificate and check that it is valid for the host name or IP address in `LDAP_WATCHDOG_SERVER`. For a private CA, set `LDAP_WATCHDOG_CA_CERTS_FILE` to a readable PEM CA bundle; in Docker, mount the bundle into the container and use its container path. A self-signed server certificate can be used as the bundle itself. If the certificate can't be provided or doesn't match the server's name, `LDAP_WATCHDOG_TLS_VERIFY=false` turns verification off; anyone on the network path can then impersonate the server and capture the bind password. For a server without TLS, use an `ldap://` URL or set `LDAP_WATCHDOG_USE_SSL=false`.
|
|
210
220
|
|
|
@@ -212,7 +222,7 @@ LDAPS connections verify the server certificate and check that it is valid for t
|
|
|
212
222
|
|
|
213
223
|
| Environment Variable | Description | Default |
|
|
214
224
|
|---|---|---|
|
|
215
|
-
| `LDAP_WATCHDOG_CONTROL_UUID` |
|
|
225
|
+
| `LDAP_WATCHDOG_CONTROL_UUID` | `entryUUID` of a control user that is changed (e.g. by a cron job) before every poll. Unless one of its attributes present in both snapshots has a new value, the comparison is rejected with an error. The user must match the base DN and search filter, and its changes are announced unless the ignore filters hide them, e.g. by listing it in `LDAP_WATCHDOG_IGNORED_UUIDS`. | `""` |
|
|
216
226
|
| `LDAP_WATCHDOG_CONTROL_USER_ATTRIBUTE` | Specific attribute to check in the control user. If set, it must exist in both snapshots and its value must differ. | `""` |
|
|
217
227
|
|
|
218
228
|
A failed control check logs an error and skips that comparison. The next poll compares against the most recent successfully retrieved snapshot; changes from a rejected comparison are not replayed. A failed LDAP retrieval instead preserves the previous snapshot and is retried on the next poll. Failure to retrieve the initial snapshot stops the process.
|
|
@@ -221,14 +231,14 @@ A failed control check logs an error and skips that comparison. The next poll co
|
|
|
221
231
|
|
|
222
232
|
| Environment Variable | Description | Default |
|
|
223
233
|
|---|---|---|
|
|
224
|
-
| `SLACK_WEBHOOK_URL` | Slack Webhook URL for notifications. Requires the `slack` extra (`pip install LDAP-Monitor[slack]`). |
|
|
225
|
-
| `LDAP_WATCHDOG_SLACK_BULLETPOINT` |
|
|
234
|
+
| `SLACK_WEBHOOK_URL` | Slack Webhook URL for notifications. Requires the `slack` extra (`pip install "LDAP-Monitor[slack]"`). | Unset |
|
|
235
|
+
| `LDAP_WATCHDOG_SLACK_BULLETPOINT` | Text that starts each line of changes in Slack and console output | • with one space before and three after |
|
|
226
236
|
|
|
227
|
-
Slack delivery is best effort: HTTP and network failures are logged to stderr, and monitoring and console output continue. Failed notifications are not queued or retried.
|
|
237
|
+
Slack delivery is best effort: HTTP and network failures are logged to stderr, and monitoring and console output continue. Failed notifications are not queued or retried. Messages longer than 4,000 characters are shortened by replacing their longest words with `[...truncated...]`; if that is not enough, they are cut at 4,000 characters, dropping their last lines (additions are listed first, then removals, then modifications). Console output is never shortened.
|
|
228
238
|
|
|
229
239
|
### Ignored Entries and Attributes
|
|
230
240
|
|
|
231
|
-
These filters apply to attribute changes on entries present in both snapshots. Entry additions and deletions are always announced with all retrieved attributes, including for ignored UUIDs.
|
|
241
|
+
These filters apply to attribute changes on entries present in both snapshots. Entry additions and deletions are always announced with all retrieved attributes, including for ignored UUIDs. UUIDs are `entryUUID` values, shown in parentheses after the DN in each message, and names and values must match exactly, including case (`modifyTimestamp`, not `modifytimestamp`). Changes hidden by `LDAP_WATCHDOG_IGNORED_ATTRIBUTES` or `LDAP_WATCHDOG_CONDITIONAL_IGNORED_ATTRIBUTES` are still written to stderr with their values; those of ignored UUIDs are skipped silently.
|
|
232
242
|
|
|
233
243
|
| Environment Variable | Description | Default |
|
|
234
244
|
|---|---|---|
|
|
@@ -238,7 +248,7 @@ These filters apply to attribute changes on entries present in both snapshots. E
|
|
|
238
248
|
|
|
239
249
|
### Conditional Ignored Attributes
|
|
240
250
|
|
|
241
|
-
The `LDAP_WATCHDOG_CONDITIONAL_IGNORED_ATTRIBUTES` variable accepts a JSON
|
|
251
|
+
The `LDAP_WATCHDOG_CONDITIONAL_IGNORED_ATTRIBUTES` variable accepts a JSON object where keys are attribute names and values are arrays of values to ignore (an array even for one value):
|
|
242
252
|
|
|
243
253
|
```bash
|
|
244
254
|
export LDAP_WATCHDOG_CONDITIONAL_IGNORED_ATTRIBUTES='{
|
|
@@ -248,21 +258,23 @@ export LDAP_WATCHDOG_CONDITIONAL_IGNORED_ATTRIBUTES='{
|
|
|
248
258
|
}'
|
|
249
259
|
```
|
|
250
260
|
|
|
261
|
+
If an attribute has exactly one value before and after, the whole change is hidden when either value is listed (see Limitations). Otherwise only the listed values are dropped from the added or removed values. Invalid JSON stops the process at startup.
|
|
262
|
+
|
|
251
263
|
## Example Configuration
|
|
252
264
|
|
|
253
265
|
```bash
|
|
254
266
|
export LDAP_WATCHDOG_CONTROL_UUID='a71c6e4c-8881-4a03-95bf-4fc25d5e6359'
|
|
255
267
|
export LDAP_WATCHDOG_SERVER='ldaps://ldaps.intra.lan'
|
|
256
268
|
export LDAP_WATCHDOG_BASE_DN='dc=mouse,dc=com'
|
|
257
|
-
export LDAP_WATCHDOG_USERNAME='Emily'
|
|
269
|
+
export LDAP_WATCHDOG_USERNAME='cn=Emily,ou=People,dc=mouse,dc=com'
|
|
258
270
|
export LDAP_WATCHDOG_PASSWORD='qwerty123'
|
|
259
271
|
export LDAP_WATCHDOG_USE_SSL='true'
|
|
260
272
|
export LDAP_WATCHDOG_TLS_VERIFY='true'
|
|
261
273
|
export LDAP_WATCHDOG_REFRESH_RATE='60'
|
|
262
274
|
export LDAP_WATCHDOG_NETWORK_TIMEOUT='30'
|
|
263
275
|
export LDAP_WATCHDOG_DISABLE_COLOR_OUTPUT='false'
|
|
264
|
-
export LDAP_WATCHDOG_IGNORED_UUIDS='e191c564-6e6d-42c1-ae51-bda0509fe846,8655e0d9-ecdc-46ce-ba42-1fa3dfbf5faa'
|
|
265
|
-
export LDAP_WATCHDOG_IGNORED_ATTRIBUTES='modifyTimestamp,
|
|
276
|
+
export LDAP_WATCHDOG_IGNORED_UUIDS='a71c6e4c-8881-4a03-95bf-4fc25d5e6359,e191c564-6e6d-42c1-ae51-bda0509fe846,8655e0d9-ecdc-46ce-ba42-1fa3dfbf5faa'
|
|
277
|
+
export LDAP_WATCHDOG_IGNORED_ATTRIBUTES='entryCSN,modifyTimestamp,telephoneNumber,roomNumber,gecos'
|
|
266
278
|
export LDAP_WATCHDOG_CONDITIONAL_IGNORED_ATTRIBUTES='{"objectClass":["posixAccount"],"memberOf":["cn=mailing-list-user,ou=Accessgroups,dc=mouse,dc=com","cn=interns,ou=Accessgroups,dc=mouse,dc=com"],"organizationalStatus":["researcher"]}'
|
|
267
279
|
export SLACK_WEBHOOK_URL='https://hooks.slack.com/services/[...]'
|
|
268
280
|
|
|
@@ -270,8 +282,9 @@ ldap-watchdog
|
|
|
270
282
|
```
|
|
271
283
|
|
|
272
284
|
## Limitations
|
|
273
|
-
1. The
|
|
274
|
-
2. Similar to #1, there is no real way to determine whether a change is really a change in some cases, or a removal and then addition
|
|
285
|
+
1. The `LDAP_WATCHDOG_CONDITIONAL_IGNORED_ATTRIBUTES` configuration may unfortunately hide important changes that are not intended to be hidden. This may happen if an attribute has a single value which is changed. This is because conditional ignored attributes will hide changes to the attribute both when the value is changed __to__ _as well as_ __from__ the ignored value; for example, if a user is a memberOf _cn=mailing-list-user,ou=Accessgroups,dc=mouse,dc=com_ which gets __changed__ to _cn=super-administrator,ou=Accessgroups,dc=mouse,dc=com_, it will be missed.
|
|
286
|
+
2. Similar to #1, there is no real way to determine whether a change is really a change in some cases, or a removal and then addition at the same time. In theory, it doesn't really matter, however it's important to note.
|
|
287
|
+
3. LDAP Watchdog polls rather than receiving changes as they happen: after each search it waits `LDAP_WATCHDOG_REFRESH_RATE` seconds, then retrieves all matching entries again and compares them with the previous snapshot. A change made and undone between two polls is never reported, and the timestamp on each message is when the change was detected, not when it was made (which `modifyTimestamp` records).
|
|
275
288
|
|
|
276
289
|
|
|
277
290
|
## Development
|
|
@@ -286,4 +299,4 @@ python -m unittest discover -s tests
|
|
|
286
299
|
`requirements.txt` pins every dependency for the Docker image and `install.sh`. After changing the dependencies in `setup.py`, regenerate it with `pip-compile --extra=slack --output-file=requirements.txt setup.py`.
|
|
287
300
|
|
|
288
301
|
## License
|
|
289
|
-
This project is licensed under [
|
|
302
|
+
This project is licensed under [GPL-3.0-or-later](https://github.com/MegaManSec/LDAP-Monitoring-Watchdog/blob/main/LICENSE).
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
LICENSE
|
|
2
2
|
MANIFEST.in
|
|
3
3
|
README.md
|
|
4
|
+
pyproject.toml
|
|
4
5
|
setup.py
|
|
5
6
|
LDAP_Monitor.egg-info/PKG-INFO
|
|
6
7
|
LDAP_Monitor.egg-info/SOURCES.txt
|
|
@@ -12,4 +13,6 @@ ldap_watchdog/__init__.py
|
|
|
12
13
|
ldap_watchdog/__main__.py
|
|
13
14
|
ldap_watchdog/config.py
|
|
14
15
|
ldap_watchdog/watchdog.py
|
|
15
|
-
tests/test_watchdog.py
|
|
16
|
+
tests/test_watchdog.py
|
|
17
|
+
tests/certs/ldap.example.com.pem
|
|
18
|
+
tests/certs/localhost.pem
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
GNU
|
|
2
|
-
Version 3,
|
|
1
|
+
GNU GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 3, 29 June 2007
|
|
3
3
|
|
|
4
4
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
5
5
|
Everyone is permitted to copy and distribute verbatim copies
|
|
@@ -7,15 +7,17 @@
|
|
|
7
7
|
|
|
8
8
|
Preamble
|
|
9
9
|
|
|
10
|
-
The GNU
|
|
11
|
-
software and other kinds of works
|
|
12
|
-
cooperation with the community in the case of network server software.
|
|
10
|
+
The GNU General Public License is a free, copyleft license for
|
|
11
|
+
software and other kinds of works.
|
|
13
12
|
|
|
14
13
|
The licenses for most software and other practical works are designed
|
|
15
14
|
to take away your freedom to share and change the works. By contrast,
|
|
16
|
-
|
|
15
|
+
the GNU General Public License is intended to guarantee your freedom to
|
|
17
16
|
share and change all versions of a program--to make sure it remains free
|
|
18
|
-
software for all its users.
|
|
17
|
+
software for all its users. We, the Free Software Foundation, use the
|
|
18
|
+
GNU General Public License for most of our software; it applies also to
|
|
19
|
+
any other work released this way by its authors. You can apply it to
|
|
20
|
+
your programs, too.
|
|
19
21
|
|
|
20
22
|
When we speak of free software, we are referring to freedom, not
|
|
21
23
|
price. Our General Public Licenses are designed to make sure that you
|
|
@@ -24,34 +26,44 @@ them if you wish), that you receive source code or can get it if you
|
|
|
24
26
|
want it, that you can change the software or use pieces of it in new
|
|
25
27
|
free programs, and that you know you can do these things.
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this
|
|
29
|
+
To protect your rights, we need to prevent others from denying you
|
|
30
|
+
these rights or asking you to surrender the rights. Therefore, you have
|
|
31
|
+
certain responsibilities if you distribute copies of the software, or if
|
|
32
|
+
you modify it: responsibilities to respect the freedom of others.
|
|
33
|
+
|
|
34
|
+
For example, if you distribute copies of such a program, whether
|
|
35
|
+
gratis or for a fee, you must pass on to the recipients the same
|
|
36
|
+
freedoms that you received. You must make sure that they, too, receive
|
|
37
|
+
or can get the source code. And you must show them these terms so they
|
|
38
|
+
know their rights.
|
|
39
|
+
|
|
40
|
+
Developers that use the GNU GPL protect your rights with two steps:
|
|
41
|
+
(1) assert copyright on the software, and (2) offer you this License
|
|
42
|
+
giving you legal permission to copy, distribute and/or modify it.
|
|
43
|
+
|
|
44
|
+
For the developers' and authors' protection, the GPL clearly explains
|
|
45
|
+
that there is no warranty for this free software. For both users' and
|
|
46
|
+
authors' sake, the GPL requires that modified versions be marked as
|
|
47
|
+
changed, so that their problems will not be attributed erroneously to
|
|
48
|
+
authors of previous versions.
|
|
49
|
+
|
|
50
|
+
Some devices are designed to deny users access to install or run
|
|
51
|
+
modified versions of the software inside them, although the manufacturer
|
|
52
|
+
can do so. This is fundamentally incompatible with the aim of
|
|
53
|
+
protecting users' freedom to change the software. The systematic
|
|
54
|
+
pattern of such abuse occurs in the area of products for individuals to
|
|
55
|
+
use, which is precisely where it is most unacceptable. Therefore, we
|
|
56
|
+
have designed this version of the GPL to prohibit the practice for those
|
|
57
|
+
products. If such problems arise substantially in other domains, we
|
|
58
|
+
stand ready to extend this provision to those domains in future versions
|
|
59
|
+
of the GPL, as needed to protect the freedom of users.
|
|
60
|
+
|
|
61
|
+
Finally, every program is threatened constantly by software patents.
|
|
62
|
+
States should not allow patents to restrict development and use of
|
|
63
|
+
software on general-purpose computers, but in those that do, we wish to
|
|
64
|
+
avoid the special danger that patents applied to a free program could
|
|
65
|
+
make it effectively proprietary. To prevent this, the GPL assures that
|
|
66
|
+
patents cannot be used to render the program non-free.
|
|
55
67
|
|
|
56
68
|
The precise terms and conditions for copying, distribution and
|
|
57
69
|
modification follow.
|
|
@@ -60,7 +72,7 @@ modification follow.
|
|
|
60
72
|
|
|
61
73
|
0. Definitions.
|
|
62
74
|
|
|
63
|
-
"This License" refers to version 3 of the GNU
|
|
75
|
+
"This License" refers to version 3 of the GNU General Public License.
|
|
64
76
|
|
|
65
77
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
66
78
|
works, such as semiconductor masks.
|
|
@@ -537,45 +549,35 @@ to collect a royalty for further conveying from those to whom you convey
|
|
|
537
549
|
the Program, the only way you could satisfy both those terms and this
|
|
538
550
|
License would be to refrain entirely from conveying the Program.
|
|
539
551
|
|
|
540
|
-
13.
|
|
541
|
-
|
|
542
|
-
Notwithstanding any other provision of this License, if you modify the
|
|
543
|
-
Program, your modified version must prominently offer all users
|
|
544
|
-
interacting with it remotely through a computer network (if your version
|
|
545
|
-
supports such interaction) an opportunity to receive the Corresponding
|
|
546
|
-
Source of your version by providing access to the Corresponding Source
|
|
547
|
-
from a network server at no charge, through some standard or customary
|
|
548
|
-
means of facilitating copying of software. This Corresponding Source
|
|
549
|
-
shall include the Corresponding Source for any work covered by version 3
|
|
550
|
-
of the GNU General Public License that is incorporated pursuant to the
|
|
551
|
-
following paragraph.
|
|
552
|
+
13. Use with the GNU Affero General Public License.
|
|
552
553
|
|
|
553
554
|
Notwithstanding any other provision of this License, you have
|
|
554
555
|
permission to link or combine any covered work with a work licensed
|
|
555
|
-
under version 3 of the GNU General Public License into a single
|
|
556
|
+
under version 3 of the GNU Affero General Public License into a single
|
|
556
557
|
combined work, and to convey the resulting work. The terms of this
|
|
557
558
|
License will continue to apply to the part which is the covered work,
|
|
558
|
-
but the
|
|
559
|
-
|
|
559
|
+
but the special requirements of the GNU Affero General Public License,
|
|
560
|
+
section 13, concerning interaction through a network will apply to the
|
|
561
|
+
combination as such.
|
|
560
562
|
|
|
561
563
|
14. Revised Versions of this License.
|
|
562
564
|
|
|
563
565
|
The Free Software Foundation may publish revised and/or new versions of
|
|
564
|
-
the GNU
|
|
565
|
-
|
|
566
|
+
the GNU General Public License from time to time. Such new versions will
|
|
567
|
+
be similar in spirit to the present version, but may differ in detail to
|
|
566
568
|
address new problems or concerns.
|
|
567
569
|
|
|
568
570
|
Each version is given a distinguishing version number. If the
|
|
569
|
-
Program specifies that a certain numbered version of the GNU
|
|
571
|
+
Program specifies that a certain numbered version of the GNU General
|
|
570
572
|
Public License "or any later version" applies to it, you have the
|
|
571
573
|
option of following the terms and conditions either of that numbered
|
|
572
574
|
version or of any later version published by the Free Software
|
|
573
575
|
Foundation. If the Program does not specify a version number of the
|
|
574
|
-
GNU
|
|
576
|
+
GNU General Public License, you may choose any version ever published
|
|
575
577
|
by the Free Software Foundation.
|
|
576
578
|
|
|
577
579
|
If the Program specifies that a proxy can decide which future
|
|
578
|
-
versions of the GNU
|
|
580
|
+
versions of the GNU General Public License can be used, that proxy's
|
|
579
581
|
public statement of acceptance of a version permanently authorizes you
|
|
580
582
|
to choose that version for the Program.
|
|
581
583
|
|
|
@@ -633,29 +635,40 @@ the "copyright" line and a pointer to where the full notice is found.
|
|
|
633
635
|
Copyright (C) <year> <name of author>
|
|
634
636
|
|
|
635
637
|
This program is free software: you can redistribute it and/or modify
|
|
636
|
-
it under the terms of the GNU
|
|
637
|
-
|
|
638
|
+
it under the terms of the GNU General Public License as published by
|
|
639
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
638
640
|
(at your option) any later version.
|
|
639
641
|
|
|
640
642
|
This program is distributed in the hope that it will be useful,
|
|
641
643
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
642
644
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
643
|
-
GNU
|
|
645
|
+
GNU General Public License for more details.
|
|
644
646
|
|
|
645
|
-
You should have received a copy of the GNU
|
|
647
|
+
You should have received a copy of the GNU General Public License
|
|
646
648
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
647
649
|
|
|
648
650
|
Also add information on how to contact you by electronic and paper mail.
|
|
649
651
|
|
|
650
|
-
If
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
652
|
+
If the program does terminal interaction, make it output a short
|
|
653
|
+
notice like this when it starts in an interactive mode:
|
|
654
|
+
|
|
655
|
+
<program> Copyright (C) <year> <name of author>
|
|
656
|
+
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
657
|
+
This is free software, and you are welcome to redistribute it
|
|
658
|
+
under certain conditions; type `show c' for details.
|
|
659
|
+
|
|
660
|
+
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
661
|
+
parts of the General Public License. Of course, your program's commands
|
|
662
|
+
might be different; for a GUI interface, you would use an "about box".
|
|
657
663
|
|
|
658
664
|
You should also get your employer (if you work as a programmer) or school,
|
|
659
665
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
660
|
-
For more information on this, and how to apply and follow the GNU
|
|
666
|
+
For more information on this, and how to apply and follow the GNU GPL, see
|
|
661
667
|
<https://www.gnu.org/licenses/>.
|
|
668
|
+
|
|
669
|
+
The GNU General Public License does not permit incorporating your program
|
|
670
|
+
into proprietary programs. If your program is a subroutine library, you
|
|
671
|
+
may consider it more useful to permit linking proprietary applications with
|
|
672
|
+
the library. If this is what you want to do, use the GNU Lesser General
|
|
673
|
+
Public License instead of this License. But first, please read
|
|
674
|
+
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|