SETUP.md — Users and Apps Audit
From version 0.1.0 of Users and Apps Audit, shown publicly by its creator. 3.9 KiB · SHA-256 46daabdfdf4eb97d12263efa744e4a86c99170cec5aad942985f160eedea570a.
# Setup 1. Register an application in Microsoft Entra ID and grant Microsoft Graph application permissions `User.Read.All`, `Directory.Read.All` and `Application.Read.All`; grant admin consent. Optionally grant `AuditLog.Read.All` for sign-in activity. 2. Supply `GRAPH_TENANT_ID`, `GRAPH_CLIENT_ID` and `GRAPH_CLIENT_SECRET` in the process environment. The tenant identifier can be a GUID or a domain name; it accepts only ASCII letters, digits, hyphens and periods. Keep secrets out of files, logs and chat. 3. Run `python3 scripts/users_and_apps_audit.py report --expiring-days 30`. Add `--json` or `--sections apps,roles` as needed. For a file, run `python3 scripts/users_and_apps_audit.py report --json --out ./audit.json --dry-run`, review the preview, then rerun `python3 scripts/users_and_apps_audit.py report --json --out ./audit.json --approve DIGEST`. The digest binds the resolved destination and directory identities plus exact report; a change requires a new dry run. An output path must not already exist. `--allow-partial` permits exit 0 while retaining the `incomplete` label and skipped list. The token request goes to `login.microsoftonline.com`; report requests and pagination go to `graph.microsoft.com`. Every URL and redirect is checked for HTTPS and its declared host. Python urllib honors `HTTPS_PROXY`, `https_proxy`, `NO_PROXY`, `no_proxy`, and macOS system proxy settings. A configured proxy sees the destination host; TLS still terminates at the declared hosts with certificate verification. The report includes personal data. Protect terminal logs and any created file. The test-only `GRAPH_AUDIT_FAKE_RESPONSES` and `GRAPH_AUDIT_FAKE_TRANSPORT_TEST_ACK=1` variables load synthetic responses from the named file; never set them for a live report. A missing fixture fails before a request. Supported platforms: macOS and Linux with POSIX directory-descriptor and no-follow APIs; Windows is unsupported and fails before file or network I/O. The approval digest binds the selected and fully resolved file path, exact report content, and device/inode identities of the existing destination directory and its parent. Live creation walks the resolved path with no-follow directory descriptors, verifies identities and the selected path resolution, and creates the file relative to the directory descriptor with exclusive/no-follow flags at mode 0600. A swapped parent is refused before writing. All output directories must already exist; no folders are created. Section selection restricts Graph queries, but users, licenses or guests each fetch the full selected users field set for all paginated users; report filters run after those reads. The no-sign-in list uses lastSignInDateTime, which records a sign-in attempt and does not prove successful sign-in or actual inactivity. Named activated roles are a fixed English display-name set; this is an inventory, not a policy evaluation. The token POST sends tenant identifier in the URL and client ID, client secret, scope and grant type to login.microsoftonline.com. Graph GETs send the bearer access token and query paths to graph.microsoft.com, including role identifiers and same-host pagination paths obtained from Graph responses. Fetched pagination path/query contents are sent as received; display-name and UPN fields are not explicitly resent. Report content is not uploaded. Hostnames are given to the configured system resolver or proxy; no application DNS lookup of fetched user names occurs. Proxy settings may introduce a configured proxy destination. Each JSON fixture and HTTP response body is limited to 8 MiB before parsing; oversized or malformed input fails with a clear error. Pagination is limited to 1000 pages per query. No stdin is read. Invalid nested Graph fields or timestamps produce explicit incomplete-section errors; missing optional values are not evidence of inactivity. Remote paths reject dot segments, controls and encoded slash or backslash within a segment before requests. By Zero Width Lab (zerowidthlab.com)
License: MIT (read it).
MIT
MIT LicenseCopyright (c) 2026 Zero Width Lab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.