idengraph 0.1.0__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.
Files changed (54) hide show
  1. idengraph-0.1.0/LICENSE +21 -0
  2. idengraph-0.1.0/MANIFEST.in +18 -0
  3. idengraph-0.1.0/PKG-INFO +225 -0
  4. idengraph-0.1.0/README.md +202 -0
  5. idengraph-0.1.0/idengraph.egg-info/PKG-INFO +225 -0
  6. idengraph-0.1.0/idengraph.egg-info/SOURCES.txt +52 -0
  7. idengraph-0.1.0/idengraph.egg-info/dependency_links.txt +1 -0
  8. idengraph-0.1.0/idengraph.egg-info/entry_points.txt +2 -0
  9. idengraph-0.1.0/idengraph.egg-info/requires.txt +4 -0
  10. idengraph-0.1.0/idengraph.egg-info/top_level.txt +2 -0
  11. idengraph-0.1.0/mcp_server.py +1021 -0
  12. idengraph-0.1.0/pyproject.toml +42 -0
  13. idengraph-0.1.0/services/__init__.py +0 -0
  14. idengraph-0.1.0/services/agent_identities.py +1905 -0
  15. idengraph-0.1.0/services/app_provenance.py +285 -0
  16. idengraph-0.1.0/services/azure_auth.py +146 -0
  17. idengraph-0.1.0/services/azure_graph.py +382 -0
  18. idengraph-0.1.0/services/azure_management_groups.py +15 -0
  19. idengraph-0.1.0/services/azure_pim.py +165 -0
  20. idengraph-0.1.0/services/azure_rbac.py +126 -0
  21. idengraph-0.1.0/services/azure_resources.py +26 -0
  22. idengraph-0.1.0/services/azure_role_definitions.py +197 -0
  23. idengraph-0.1.0/services/azure_roles.py +59 -0
  24. idengraph-0.1.0/services/blast_radius.py +231 -0
  25. idengraph-0.1.0/services/capability_executor.py +460 -0
  26. idengraph-0.1.0/services/capability_normalizer.py +309 -0
  27. idengraph-0.1.0/services/capability_router.py +466 -0
  28. idengraph-0.1.0/services/capability_service.py +521 -0
  29. idengraph-0.1.0/services/data/mock_iam.json +386 -0
  30. idengraph-0.1.0/services/data/mock_identity.json +52 -0
  31. idengraph-0.1.0/services/data/mock_resources.json +53 -0
  32. idengraph-0.1.0/services/docs.py +61 -0
  33. idengraph-0.1.0/services/effective_access.py +149 -0
  34. idengraph-0.1.0/services/entra_apps.py +172 -0
  35. idengraph-0.1.0/services/entra_authentication.py +196 -0
  36. idengraph-0.1.0/services/entra_conditional_access.py +15 -0
  37. idengraph-0.1.0/services/entra_groups.py +81 -0
  38. idengraph-0.1.0/services/entra_licenses.py +174 -0
  39. idengraph-0.1.0/services/entra_pim.py +665 -0
  40. idengraph-0.1.0/services/entra_roles.py +99 -0
  41. idengraph-0.1.0/services/entra_users.py +38 -0
  42. idengraph-0.1.0/services/entra_workload_identities.py +57 -0
  43. idengraph-0.1.0/services/graph_capabilities.py +1110 -0
  44. idengraph-0.1.0/services/iam_assessment.py +1251 -0
  45. idengraph-0.1.0/services/iam_common.py +150 -0
  46. idengraph-0.1.0/services/identity_360.py +395 -0
  47. idengraph-0.1.0/services/identity_access.py +347 -0
  48. idengraph-0.1.0/services/identity_risk.py +119 -0
  49. idengraph-0.1.0/services/license_posture.py +175 -0
  50. idengraph-0.1.0/services/ownership.py +394 -0
  51. idengraph-0.1.0/services/privilege_timeline.py +328 -0
  52. idengraph-0.1.0/services/role_risk.py +93 -0
  53. idengraph-0.1.0/services/toxic_combinations.py +146 -0
  54. idengraph-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Josimar Hedler
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,18 @@
1
+ include LICENSE
2
+ include README.md
3
+ recursive-include services/data *.json
4
+
5
+ # O pacote publicado expõe apenas o servidor MCP. O portal Streamlit e o
6
+ # orquestrador de chat existem no repositório para desenvolvimento e demo,
7
+ # e não fazem parte da superfície distribuída.
8
+ exclude app.py
9
+ exclude agent.py
10
+ exclude launcher.py
11
+ exclude test_smoke.py
12
+ exclude requirements.txt
13
+ exclude Dockerfile
14
+ exclude .env.example
15
+ prune .streamlit
16
+ prune .agents
17
+ prune assets
18
+ prune .vscode
@@ -0,0 +1,225 @@
1
+ Metadata-Version: 2.4
2
+ Name: idengraph
3
+ Version: 0.1.0
4
+ Summary: Identity & Access intelligence powered by Microsoft Graph and MCP. Read-only auditing for Microsoft Entra ID and Azure RBAC.
5
+ Author-email: josimarh <josimar.hedler@outlook.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/josimarh/idengraph
8
+ Project-URL: Repository, https://github.com/josimarh/idengraph
9
+ Project-URL: Issues, https://github.com/josimarh/idengraph/issues
10
+ Keywords: mcp,azure,entra,identity,security,rbac,audit,iam
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: System Administrators
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Security
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: mcp[cli]<3,>=2
19
+ Requires-Dist: httpx<1,>=0.28
20
+ Requires-Dist: azure-identity<2,>=1.17
21
+ Requires-Dist: python-dotenv<2,>=1.0
22
+ Dynamic: license-file
23
+
24
+ # IdenGraph
25
+
26
+ **Identity & Access intelligence powered by Microsoft Graph and MCP.**
27
+
28
+ A read-only MCP server that turns natural-language questions into audited answers about **Microsoft Entra ID** and **Azure RBAC** — answered by your own Copilot, inside VS Code.
29
+
30
+ [![VS Code Marketplace](https://img.shields.io/visual-studio-marketplace/v/josimarh.idengraph?label=VS%20Code%20Marketplace)](https://marketplace.visualstudio.com/items?itemName=josimarh.idengraph)
31
+ [![PyPI](https://img.shields.io/pypi/v/idengraph?label=PyPI)](https://pypi.org/project/idengraph/)
32
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
33
+
34
+ > **It never writes.** Every create, update, delete, grant, or privilege-activation operation is blocked before routing.
35
+
36
+ ## What you can ask
37
+
38
+ - Who has **Owner** on Azure? And who holds **Global Administrator** in Entra?
39
+ - Which applications were **created in my tenant**, and which are Microsoft first-party?
40
+ - Which users have **no MFA**, or rely on weak methods?
41
+ - Which **application secrets** expire in the next 30 days?
42
+ - Which objects have **no owner** assigned?
43
+ - What is the **blast radius** of a given identity?
44
+ - Are we **paying for security features we don't use**?
45
+
46
+ **66 tools** across users, groups, applications, service principals, managed identities, PIM, RBAC, authentication, conditional access, ownership, privilege timeline, licensing posture, and toxic combinations (SoD).
47
+
48
+ ## Design principles
49
+
50
+ These three rules define the behavior, and they matter more than the feature list.
51
+
52
+ ### Source separation
53
+
54
+ Microsoft Graph answers for identity and directory. Azure APIs answer for RBAC and resources. **Graph is never treated as a source of truth for Azure RBAC.**
55
+
56
+ ### No false zero
57
+
58
+ If a permission is missing, the answer is `PERMISSION_DENIED` with `NOT_EVALUATED` coverage — **never `0`**.
59
+
60
+ "I could not evaluate this" and "this does not exist" are different answers. Conflating them in an audit is worse than not answering at all, because a false zero looks like a clean result.
61
+
62
+ This applies to licensing too: zero conditional access policies means something entirely different when the feature isn't licensed versus when it's licensed and unused.
63
+
64
+ ### Read-only by construction
65
+
66
+ Only `GET`, `LIST`, `QUERY`, `ASSESS`, and `CORRELATE`. There is no LLM-generated KQL and no free-form endpoint: every query goes through a capability registry with an allowlist and validation of filters and scopes.
67
+
68
+ ## Architecture
69
+
70
+ ```mermaid
71
+ flowchart TB
72
+ User(["You"]) -->|natural language| Copilot["Copilot Chat<br/><i>your own model</i>"]
73
+ Copilot <-->|MCP / stdio| Server
74
+
75
+ subgraph Server["IdenGraph MCP Server · 66 read-only tools"]
76
+ direction TB
77
+ Router["Capability router<br/><i>intent → capability</i>"]
78
+ Guard{{"Write guard<br/><i>blocks mutations</i>"}}
79
+ Registry[("Capability registry<br/>43 capabilities · 29 domains")]
80
+ Executor["Read-only executor<br/><i>allowlist + validation</i>"]
81
+
82
+ Router --> Guard --> Registry --> Executor
83
+ end
84
+
85
+ Executor -->|identity & directory| Graph["Microsoft Graph"]
86
+ Executor -->|RBAC & resources| Azure["Azure Management<br/>+ Resource Graph"]
87
+
88
+ Graph --> Normalizer["Normalizer & correlation<br/><i>preserves evidence and coverage</i>"]
89
+ Azure --> Normalizer
90
+ Normalizer -->|answer + provenance| Copilot
91
+
92
+ style Guard fill:#c62828,color:#fff
93
+ style Server fill:#0B1F3A,color:#fff
94
+ style Normalizer fill:#1565c0,color:#fff
95
+ ```
96
+
97
+ Two details worth highlighting:
98
+
99
+ **The write guard sits before routing**, not after. A mutation request is rejected before it can be interpreted as a query.
100
+
101
+ **The normalizer preserves coverage**, not just data. Every answer carries where it came from and whether the source could actually be evaluated — which is what makes the no-false-zero rule enforceable rather than aspirational.
102
+
103
+ ### How the pieces are distributed
104
+
105
+ | Layer | Artifact | Role |
106
+ |---|---|---|
107
+ | Discovery | [VS Code extension](https://marketplace.visualstudio.com/items?itemName=josimarh.idengraph) | One-click install, prerequisite checks, settings UI |
108
+ | Engine | [`idengraph` on PyPI](https://pypi.org/project/idengraph/) | The MCP server itself |
109
+ | Model | Your Copilot subscription | No LLM cost to this project or to you |
110
+
111
+ The extension does not replace the Python package — it registers it. The engine runs the same way whether launched by the extension or configured by hand.
112
+
113
+ ## Install
114
+
115
+ ### Recommended: VS Code extension
116
+
117
+ Install **[IdenGraph](https://marketplace.visualstudio.com/items?itemName=josimarh.idengraph)** from the Marketplace, then sign in to Azure:
118
+
119
+ ```bash
120
+ az login
121
+ ```
122
+
123
+ Open Copilot Chat in **agent mode** and ask. The extension verifies prerequisites and guides you if anything is missing.
124
+
125
+ ### Alternative: manual MCP configuration
126
+
127
+ Create `.vscode/mcp.json`:
128
+
129
+ ```json
130
+ {
131
+ "servers": {
132
+ "idengraph": {
133
+ "type": "stdio",
134
+ "command": "uvx",
135
+ "args": ["idengraph"],
136
+ "env": { "MOCK_MODE": "false" }
137
+ }
138
+ }
139
+ }
140
+ ```
141
+
142
+ ## Prerequisites
143
+
144
+ - **Python 3.10+**
145
+ - **[uv](https://docs.astral.sh/uv/getting-started/installation/)**
146
+ - **[Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli)** with an active session (`az login`)
147
+
148
+ Authentication uses `DefaultAzureCredential`, which reuses your Azure CLI session. There is no API key to manage, and no credential is stored by this project.
149
+
150
+ ## Configuration
151
+
152
+ | Setting | Env var | Default | Purpose |
153
+ |---|---|---|---|
154
+ | `idengraph.useMockData` | `MOCK_MODE` | `false` (extension) | Query fictional data instead of your tenant |
155
+ | `idengraph.sanitizeOutput` | `SANITIZE_FOR_LLM` | `true` | Mask resource names, subscription IDs, and IPs before they reach the model |
156
+ | `idengraph.subscriptions` | `AZURE_SUBSCRIPTIONS` | all accessible | Restrict queries to specific subscriptions |
157
+
158
+ The Python package defaults to `MOCK_MODE=true` so that nothing touches a real tenant without explicit intent. The extension sets it to `false`, since installing it is already that intent.
159
+
160
+ ## Permissions
161
+
162
+ On Azure: **`Reader`** on the subscriptions you want to audit.
163
+
164
+ On Microsoft Graph, delegated permissions vary by question:
165
+
166
+ | Area | Permission |
167
+ |---|---|
168
+ | Users, groups, applications, service principals | `Directory.Read.All` |
169
+ | Directory roles and directory PIM | `RoleManagement.Read.All` |
170
+ | Authentication methods and MFA | `UserAuthenticationMethod.Read.All` |
171
+ | Conditional access | `Policy.Read.All` |
172
+ | License posture | `Organization.Read.All` |
173
+
174
+ Missing a permission only marks the matching area as not evaluated. Everything else keeps working — and the affected area reports *why* it could not be evaluated.
175
+
176
+ ## Privacy
177
+
178
+ Queried data belongs to **your** tenant and travels between your machine, Microsoft APIs, and the Copilot model **you already use**. This project sends nothing to third-party servers and collects no telemetry.
179
+
180
+ By default, `SANITIZE_FOR_LLM=true` masks resource names, resource groups, subscription IDs, and IP addresses before content reaches the model.
181
+
182
+ ## Development
183
+
184
+ ```bash
185
+ python -m venv .venv
186
+ .venv\Scripts\activate # Windows
187
+ # source .venv/bin/activate # Linux/macOS
188
+ pip install -r requirements.txt
189
+ cp .env.example .env
190
+ python test_smoke.py
191
+ ```
192
+
193
+ The smoke test runs in mock mode and never touches a tenant.
194
+
195
+ ### Repository layout
196
+
197
+ ```text
198
+ mcp_server.py MCP server and tool registration
199
+ services/azure_auth.py credentials, tokens, caching
200
+ services/graph_capabilities.py capability registry
201
+ services/capability_router.py natural language → capability
202
+ services/capability_executor.py validated read-only execution
203
+ services/azure_role_definitions.py authoritative Azure role name resolution
204
+ services/azure_pim.py resource PIM with confirmed coverage
205
+ services/entra_licenses.py tenant licensing and feature availability
206
+ services/data/ mock data used when MOCK_MODE=true
207
+ extension/ VS Code extension (TypeScript)
208
+ ```
209
+
210
+ The repository also contains a Streamlit portal (`app.py` + `agent.py`) used for development and demos. It is not part of the published package, whose surface is the MCP server only:
211
+
212
+ ```bash
213
+ streamlit run app.py
214
+ ```
215
+
216
+ ## Known limitations
217
+
218
+ - Agent Identity detection is **heuristic** where the directory exposes no dedicated type. Results are labeled as such, never presented as fact.
219
+ - `Public IP` indicates a public address, which **does not prove** workload exposure.
220
+ - Without `RoleManagement.Read.All`, directory PIM reports as not evaluated rather than empty.
221
+ - License posture currently cross-references PIM and Conditional Access. Capabilities still marked `not_integrated` in the registry are not probed, and deliberately return no verdict.
222
+
223
+ ## License
224
+
225
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,202 @@
1
+ # IdenGraph
2
+
3
+ **Identity & Access intelligence powered by Microsoft Graph and MCP.**
4
+
5
+ A read-only MCP server that turns natural-language questions into audited answers about **Microsoft Entra ID** and **Azure RBAC** — answered by your own Copilot, inside VS Code.
6
+
7
+ [![VS Code Marketplace](https://img.shields.io/visual-studio-marketplace/v/josimarh.idengraph?label=VS%20Code%20Marketplace)](https://marketplace.visualstudio.com/items?itemName=josimarh.idengraph)
8
+ [![PyPI](https://img.shields.io/pypi/v/idengraph?label=PyPI)](https://pypi.org/project/idengraph/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
10
+
11
+ > **It never writes.** Every create, update, delete, grant, or privilege-activation operation is blocked before routing.
12
+
13
+ ## What you can ask
14
+
15
+ - Who has **Owner** on Azure? And who holds **Global Administrator** in Entra?
16
+ - Which applications were **created in my tenant**, and which are Microsoft first-party?
17
+ - Which users have **no MFA**, or rely on weak methods?
18
+ - Which **application secrets** expire in the next 30 days?
19
+ - Which objects have **no owner** assigned?
20
+ - What is the **blast radius** of a given identity?
21
+ - Are we **paying for security features we don't use**?
22
+
23
+ **66 tools** across users, groups, applications, service principals, managed identities, PIM, RBAC, authentication, conditional access, ownership, privilege timeline, licensing posture, and toxic combinations (SoD).
24
+
25
+ ## Design principles
26
+
27
+ These three rules define the behavior, and they matter more than the feature list.
28
+
29
+ ### Source separation
30
+
31
+ Microsoft Graph answers for identity and directory. Azure APIs answer for RBAC and resources. **Graph is never treated as a source of truth for Azure RBAC.**
32
+
33
+ ### No false zero
34
+
35
+ If a permission is missing, the answer is `PERMISSION_DENIED` with `NOT_EVALUATED` coverage — **never `0`**.
36
+
37
+ "I could not evaluate this" and "this does not exist" are different answers. Conflating them in an audit is worse than not answering at all, because a false zero looks like a clean result.
38
+
39
+ This applies to licensing too: zero conditional access policies means something entirely different when the feature isn't licensed versus when it's licensed and unused.
40
+
41
+ ### Read-only by construction
42
+
43
+ Only `GET`, `LIST`, `QUERY`, `ASSESS`, and `CORRELATE`. There is no LLM-generated KQL and no free-form endpoint: every query goes through a capability registry with an allowlist and validation of filters and scopes.
44
+
45
+ ## Architecture
46
+
47
+ ```mermaid
48
+ flowchart TB
49
+ User(["You"]) -->|natural language| Copilot["Copilot Chat<br/><i>your own model</i>"]
50
+ Copilot <-->|MCP / stdio| Server
51
+
52
+ subgraph Server["IdenGraph MCP Server · 66 read-only tools"]
53
+ direction TB
54
+ Router["Capability router<br/><i>intent → capability</i>"]
55
+ Guard{{"Write guard<br/><i>blocks mutations</i>"}}
56
+ Registry[("Capability registry<br/>43 capabilities · 29 domains")]
57
+ Executor["Read-only executor<br/><i>allowlist + validation</i>"]
58
+
59
+ Router --> Guard --> Registry --> Executor
60
+ end
61
+
62
+ Executor -->|identity & directory| Graph["Microsoft Graph"]
63
+ Executor -->|RBAC & resources| Azure["Azure Management<br/>+ Resource Graph"]
64
+
65
+ Graph --> Normalizer["Normalizer & correlation<br/><i>preserves evidence and coverage</i>"]
66
+ Azure --> Normalizer
67
+ Normalizer -->|answer + provenance| Copilot
68
+
69
+ style Guard fill:#c62828,color:#fff
70
+ style Server fill:#0B1F3A,color:#fff
71
+ style Normalizer fill:#1565c0,color:#fff
72
+ ```
73
+
74
+ Two details worth highlighting:
75
+
76
+ **The write guard sits before routing**, not after. A mutation request is rejected before it can be interpreted as a query.
77
+
78
+ **The normalizer preserves coverage**, not just data. Every answer carries where it came from and whether the source could actually be evaluated — which is what makes the no-false-zero rule enforceable rather than aspirational.
79
+
80
+ ### How the pieces are distributed
81
+
82
+ | Layer | Artifact | Role |
83
+ |---|---|---|
84
+ | Discovery | [VS Code extension](https://marketplace.visualstudio.com/items?itemName=josimarh.idengraph) | One-click install, prerequisite checks, settings UI |
85
+ | Engine | [`idengraph` on PyPI](https://pypi.org/project/idengraph/) | The MCP server itself |
86
+ | Model | Your Copilot subscription | No LLM cost to this project or to you |
87
+
88
+ The extension does not replace the Python package — it registers it. The engine runs the same way whether launched by the extension or configured by hand.
89
+
90
+ ## Install
91
+
92
+ ### Recommended: VS Code extension
93
+
94
+ Install **[IdenGraph](https://marketplace.visualstudio.com/items?itemName=josimarh.idengraph)** from the Marketplace, then sign in to Azure:
95
+
96
+ ```bash
97
+ az login
98
+ ```
99
+
100
+ Open Copilot Chat in **agent mode** and ask. The extension verifies prerequisites and guides you if anything is missing.
101
+
102
+ ### Alternative: manual MCP configuration
103
+
104
+ Create `.vscode/mcp.json`:
105
+
106
+ ```json
107
+ {
108
+ "servers": {
109
+ "idengraph": {
110
+ "type": "stdio",
111
+ "command": "uvx",
112
+ "args": ["idengraph"],
113
+ "env": { "MOCK_MODE": "false" }
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ ## Prerequisites
120
+
121
+ - **Python 3.10+**
122
+ - **[uv](https://docs.astral.sh/uv/getting-started/installation/)**
123
+ - **[Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli)** with an active session (`az login`)
124
+
125
+ Authentication uses `DefaultAzureCredential`, which reuses your Azure CLI session. There is no API key to manage, and no credential is stored by this project.
126
+
127
+ ## Configuration
128
+
129
+ | Setting | Env var | Default | Purpose |
130
+ |---|---|---|---|
131
+ | `idengraph.useMockData` | `MOCK_MODE` | `false` (extension) | Query fictional data instead of your tenant |
132
+ | `idengraph.sanitizeOutput` | `SANITIZE_FOR_LLM` | `true` | Mask resource names, subscription IDs, and IPs before they reach the model |
133
+ | `idengraph.subscriptions` | `AZURE_SUBSCRIPTIONS` | all accessible | Restrict queries to specific subscriptions |
134
+
135
+ The Python package defaults to `MOCK_MODE=true` so that nothing touches a real tenant without explicit intent. The extension sets it to `false`, since installing it is already that intent.
136
+
137
+ ## Permissions
138
+
139
+ On Azure: **`Reader`** on the subscriptions you want to audit.
140
+
141
+ On Microsoft Graph, delegated permissions vary by question:
142
+
143
+ | Area | Permission |
144
+ |---|---|
145
+ | Users, groups, applications, service principals | `Directory.Read.All` |
146
+ | Directory roles and directory PIM | `RoleManagement.Read.All` |
147
+ | Authentication methods and MFA | `UserAuthenticationMethod.Read.All` |
148
+ | Conditional access | `Policy.Read.All` |
149
+ | License posture | `Organization.Read.All` |
150
+
151
+ Missing a permission only marks the matching area as not evaluated. Everything else keeps working — and the affected area reports *why* it could not be evaluated.
152
+
153
+ ## Privacy
154
+
155
+ Queried data belongs to **your** tenant and travels between your machine, Microsoft APIs, and the Copilot model **you already use**. This project sends nothing to third-party servers and collects no telemetry.
156
+
157
+ By default, `SANITIZE_FOR_LLM=true` masks resource names, resource groups, subscription IDs, and IP addresses before content reaches the model.
158
+
159
+ ## Development
160
+
161
+ ```bash
162
+ python -m venv .venv
163
+ .venv\Scripts\activate # Windows
164
+ # source .venv/bin/activate # Linux/macOS
165
+ pip install -r requirements.txt
166
+ cp .env.example .env
167
+ python test_smoke.py
168
+ ```
169
+
170
+ The smoke test runs in mock mode and never touches a tenant.
171
+
172
+ ### Repository layout
173
+
174
+ ```text
175
+ mcp_server.py MCP server and tool registration
176
+ services/azure_auth.py credentials, tokens, caching
177
+ services/graph_capabilities.py capability registry
178
+ services/capability_router.py natural language → capability
179
+ services/capability_executor.py validated read-only execution
180
+ services/azure_role_definitions.py authoritative Azure role name resolution
181
+ services/azure_pim.py resource PIM with confirmed coverage
182
+ services/entra_licenses.py tenant licensing and feature availability
183
+ services/data/ mock data used when MOCK_MODE=true
184
+ extension/ VS Code extension (TypeScript)
185
+ ```
186
+
187
+ The repository also contains a Streamlit portal (`app.py` + `agent.py`) used for development and demos. It is not part of the published package, whose surface is the MCP server only:
188
+
189
+ ```bash
190
+ streamlit run app.py
191
+ ```
192
+
193
+ ## Known limitations
194
+
195
+ - Agent Identity detection is **heuristic** where the directory exposes no dedicated type. Results are labeled as such, never presented as fact.
196
+ - `Public IP` indicates a public address, which **does not prove** workload exposure.
197
+ - Without `RoleManagement.Read.All`, directory PIM reports as not evaluated rather than empty.
198
+ - License posture currently cross-references PIM and Conditional Access. Capabilities still marked `not_integrated` in the registry are not probed, and deliberately return no verdict.
199
+
200
+ ## License
201
+
202
+ MIT — see [LICENSE](LICENSE).