@etcsec-com/etc-collector 1.4.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.
Files changed (617) hide show
  1. package/.env.example +60 -0
  2. package/.env.test.example +33 -0
  3. package/.github/workflows/ci.yml +83 -0
  4. package/.github/workflows/release.yml +246 -0
  5. package/.prettierrc.json +10 -0
  6. package/CHANGELOG.md +15 -0
  7. package/Dockerfile +57 -0
  8. package/LICENSE +190 -0
  9. package/README.md +194 -0
  10. package/dist/api/controllers/audit.controller.d.ts +21 -0
  11. package/dist/api/controllers/audit.controller.d.ts.map +1 -0
  12. package/dist/api/controllers/audit.controller.js +179 -0
  13. package/dist/api/controllers/audit.controller.js.map +1 -0
  14. package/dist/api/controllers/auth.controller.d.ts +16 -0
  15. package/dist/api/controllers/auth.controller.d.ts.map +1 -0
  16. package/dist/api/controllers/auth.controller.js +146 -0
  17. package/dist/api/controllers/auth.controller.js.map +1 -0
  18. package/dist/api/controllers/export.controller.d.ts +27 -0
  19. package/dist/api/controllers/export.controller.d.ts.map +1 -0
  20. package/dist/api/controllers/export.controller.js +80 -0
  21. package/dist/api/controllers/export.controller.js.map +1 -0
  22. package/dist/api/controllers/health.controller.d.ts +5 -0
  23. package/dist/api/controllers/health.controller.d.ts.map +1 -0
  24. package/dist/api/controllers/health.controller.js +16 -0
  25. package/dist/api/controllers/health.controller.js.map +1 -0
  26. package/dist/api/controllers/jobs.controller.d.ts +13 -0
  27. package/dist/api/controllers/jobs.controller.d.ts.map +1 -0
  28. package/dist/api/controllers/jobs.controller.js +125 -0
  29. package/dist/api/controllers/jobs.controller.js.map +1 -0
  30. package/dist/api/controllers/providers.controller.d.ts +15 -0
  31. package/dist/api/controllers/providers.controller.d.ts.map +1 -0
  32. package/dist/api/controllers/providers.controller.js +112 -0
  33. package/dist/api/controllers/providers.controller.js.map +1 -0
  34. package/dist/api/dto/AuditRequest.dto.d.ts +6 -0
  35. package/dist/api/dto/AuditRequest.dto.d.ts.map +1 -0
  36. package/dist/api/dto/AuditRequest.dto.js +3 -0
  37. package/dist/api/dto/AuditRequest.dto.js.map +1 -0
  38. package/dist/api/dto/AuditResponse.dto.d.ts +17 -0
  39. package/dist/api/dto/AuditResponse.dto.d.ts.map +1 -0
  40. package/dist/api/dto/AuditResponse.dto.js +3 -0
  41. package/dist/api/dto/AuditResponse.dto.js.map +1 -0
  42. package/dist/api/dto/TokenRequest.dto.d.ts +6 -0
  43. package/dist/api/dto/TokenRequest.dto.d.ts.map +1 -0
  44. package/dist/api/dto/TokenRequest.dto.js +3 -0
  45. package/dist/api/dto/TokenRequest.dto.js.map +1 -0
  46. package/dist/api/dto/TokenResponse.dto.d.ts +12 -0
  47. package/dist/api/dto/TokenResponse.dto.d.ts.map +1 -0
  48. package/dist/api/dto/TokenResponse.dto.js +3 -0
  49. package/dist/api/dto/TokenResponse.dto.js.map +1 -0
  50. package/dist/api/middlewares/authenticate.d.ts +12 -0
  51. package/dist/api/middlewares/authenticate.d.ts.map +1 -0
  52. package/dist/api/middlewares/authenticate.js +141 -0
  53. package/dist/api/middlewares/authenticate.js.map +1 -0
  54. package/dist/api/middlewares/errorHandler.d.ts +3 -0
  55. package/dist/api/middlewares/errorHandler.d.ts.map +1 -0
  56. package/dist/api/middlewares/errorHandler.js +30 -0
  57. package/dist/api/middlewares/errorHandler.js.map +1 -0
  58. package/dist/api/middlewares/rateLimit.d.ts +3 -0
  59. package/dist/api/middlewares/rateLimit.d.ts.map +1 -0
  60. package/dist/api/middlewares/rateLimit.js +34 -0
  61. package/dist/api/middlewares/rateLimit.js.map +1 -0
  62. package/dist/api/middlewares/validate.d.ts +4 -0
  63. package/dist/api/middlewares/validate.d.ts.map +1 -0
  64. package/dist/api/middlewares/validate.js +31 -0
  65. package/dist/api/middlewares/validate.js.map +1 -0
  66. package/dist/api/routes/audit.routes.d.ts +5 -0
  67. package/dist/api/routes/audit.routes.d.ts.map +1 -0
  68. package/dist/api/routes/audit.routes.js +24 -0
  69. package/dist/api/routes/audit.routes.js.map +1 -0
  70. package/dist/api/routes/auth.routes.d.ts +6 -0
  71. package/dist/api/routes/auth.routes.d.ts.map +1 -0
  72. package/dist/api/routes/auth.routes.js +22 -0
  73. package/dist/api/routes/auth.routes.js.map +1 -0
  74. package/dist/api/routes/export.routes.d.ts +5 -0
  75. package/dist/api/routes/export.routes.d.ts.map +1 -0
  76. package/dist/api/routes/export.routes.js +16 -0
  77. package/dist/api/routes/export.routes.js.map +1 -0
  78. package/dist/api/routes/health.routes.d.ts +4 -0
  79. package/dist/api/routes/health.routes.d.ts.map +1 -0
  80. package/dist/api/routes/health.routes.js +11 -0
  81. package/dist/api/routes/health.routes.js.map +1 -0
  82. package/dist/api/routes/index.d.ts +10 -0
  83. package/dist/api/routes/index.d.ts.map +1 -0
  84. package/dist/api/routes/index.js +20 -0
  85. package/dist/api/routes/index.js.map +1 -0
  86. package/dist/api/routes/providers.routes.d.ts +5 -0
  87. package/dist/api/routes/providers.routes.d.ts.map +1 -0
  88. package/dist/api/routes/providers.routes.js +13 -0
  89. package/dist/api/routes/providers.routes.js.map +1 -0
  90. package/dist/api/validators/audit.schemas.d.ts +60 -0
  91. package/dist/api/validators/audit.schemas.d.ts.map +1 -0
  92. package/dist/api/validators/audit.schemas.js +55 -0
  93. package/dist/api/validators/audit.schemas.js.map +1 -0
  94. package/dist/api/validators/auth.schemas.d.ts +17 -0
  95. package/dist/api/validators/auth.schemas.d.ts.map +1 -0
  96. package/dist/api/validators/auth.schemas.js +21 -0
  97. package/dist/api/validators/auth.schemas.js.map +1 -0
  98. package/dist/app.d.ts +3 -0
  99. package/dist/app.d.ts.map +1 -0
  100. package/dist/app.js +62 -0
  101. package/dist/app.js.map +1 -0
  102. package/dist/config/config.schema.d.ts +65 -0
  103. package/dist/config/config.schema.d.ts.map +1 -0
  104. package/dist/config/config.schema.js +95 -0
  105. package/dist/config/config.schema.js.map +1 -0
  106. package/dist/config/index.d.ts +4 -0
  107. package/dist/config/index.d.ts.map +1 -0
  108. package/dist/config/index.js +75 -0
  109. package/dist/config/index.js.map +1 -0
  110. package/dist/container.d.ts +47 -0
  111. package/dist/container.d.ts.map +1 -0
  112. package/dist/container.js +137 -0
  113. package/dist/container.js.map +1 -0
  114. package/dist/data/database.d.ts +13 -0
  115. package/dist/data/database.d.ts.map +1 -0
  116. package/dist/data/database.js +68 -0
  117. package/dist/data/database.js.map +1 -0
  118. package/dist/data/jobs/token-cleanup.job.d.ts +23 -0
  119. package/dist/data/jobs/token-cleanup.job.d.ts.map +1 -0
  120. package/dist/data/jobs/token-cleanup.job.js +96 -0
  121. package/dist/data/jobs/token-cleanup.job.js.map +1 -0
  122. package/dist/data/migrations/migration.runner.d.ts +13 -0
  123. package/dist/data/migrations/migration.runner.d.ts.map +1 -0
  124. package/dist/data/migrations/migration.runner.js +136 -0
  125. package/dist/data/migrations/migration.runner.js.map +1 -0
  126. package/dist/data/models/Token.model.d.ts +30 -0
  127. package/dist/data/models/Token.model.d.ts.map +1 -0
  128. package/dist/data/models/Token.model.js +3 -0
  129. package/dist/data/models/Token.model.js.map +1 -0
  130. package/dist/data/repositories/token.repository.d.ts +16 -0
  131. package/dist/data/repositories/token.repository.d.ts.map +1 -0
  132. package/dist/data/repositories/token.repository.js +97 -0
  133. package/dist/data/repositories/token.repository.js.map +1 -0
  134. package/dist/providers/azure/auth.provider.d.ts +5 -0
  135. package/dist/providers/azure/auth.provider.d.ts.map +1 -0
  136. package/dist/providers/azure/auth.provider.js +13 -0
  137. package/dist/providers/azure/auth.provider.js.map +1 -0
  138. package/dist/providers/azure/azure-errors.d.ts +40 -0
  139. package/dist/providers/azure/azure-errors.d.ts.map +1 -0
  140. package/dist/providers/azure/azure-errors.js +121 -0
  141. package/dist/providers/azure/azure-errors.js.map +1 -0
  142. package/dist/providers/azure/azure-retry.d.ts +41 -0
  143. package/dist/providers/azure/azure-retry.d.ts.map +1 -0
  144. package/dist/providers/azure/azure-retry.js +85 -0
  145. package/dist/providers/azure/azure-retry.js.map +1 -0
  146. package/dist/providers/azure/graph-client.d.ts +26 -0
  147. package/dist/providers/azure/graph-client.d.ts.map +1 -0
  148. package/dist/providers/azure/graph-client.js +146 -0
  149. package/dist/providers/azure/graph-client.js.map +1 -0
  150. package/dist/providers/azure/graph.provider.d.ts +23 -0
  151. package/dist/providers/azure/graph.provider.d.ts.map +1 -0
  152. package/dist/providers/azure/graph.provider.js +161 -0
  153. package/dist/providers/azure/graph.provider.js.map +1 -0
  154. package/dist/providers/azure/queries/app.queries.d.ts +6 -0
  155. package/dist/providers/azure/queries/app.queries.d.ts.map +1 -0
  156. package/dist/providers/azure/queries/app.queries.js +9 -0
  157. package/dist/providers/azure/queries/app.queries.js.map +1 -0
  158. package/dist/providers/azure/queries/policy.queries.d.ts +6 -0
  159. package/dist/providers/azure/queries/policy.queries.d.ts.map +1 -0
  160. package/dist/providers/azure/queries/policy.queries.js +9 -0
  161. package/dist/providers/azure/queries/policy.queries.js.map +1 -0
  162. package/dist/providers/azure/queries/user.queries.d.ts +7 -0
  163. package/dist/providers/azure/queries/user.queries.d.ts.map +1 -0
  164. package/dist/providers/azure/queries/user.queries.js +10 -0
  165. package/dist/providers/azure/queries/user.queries.js.map +1 -0
  166. package/dist/providers/interfaces/IGraphProvider.d.ts +31 -0
  167. package/dist/providers/interfaces/IGraphProvider.d.ts.map +1 -0
  168. package/dist/providers/interfaces/IGraphProvider.js +3 -0
  169. package/dist/providers/interfaces/IGraphProvider.js.map +1 -0
  170. package/dist/providers/interfaces/ILDAPProvider.d.ts +37 -0
  171. package/dist/providers/interfaces/ILDAPProvider.d.ts.map +1 -0
  172. package/dist/providers/interfaces/ILDAPProvider.js +3 -0
  173. package/dist/providers/interfaces/ILDAPProvider.js.map +1 -0
  174. package/dist/providers/ldap/acl-parser.d.ts +8 -0
  175. package/dist/providers/ldap/acl-parser.d.ts.map +1 -0
  176. package/dist/providers/ldap/acl-parser.js +157 -0
  177. package/dist/providers/ldap/acl-parser.js.map +1 -0
  178. package/dist/providers/ldap/ad-mappers.d.ts +8 -0
  179. package/dist/providers/ldap/ad-mappers.d.ts.map +1 -0
  180. package/dist/providers/ldap/ad-mappers.js +162 -0
  181. package/dist/providers/ldap/ad-mappers.js.map +1 -0
  182. package/dist/providers/ldap/ldap-client.d.ts +33 -0
  183. package/dist/providers/ldap/ldap-client.d.ts.map +1 -0
  184. package/dist/providers/ldap/ldap-client.js +195 -0
  185. package/dist/providers/ldap/ldap-client.js.map +1 -0
  186. package/dist/providers/ldap/ldap-errors.d.ts +48 -0
  187. package/dist/providers/ldap/ldap-errors.d.ts.map +1 -0
  188. package/dist/providers/ldap/ldap-errors.js +120 -0
  189. package/dist/providers/ldap/ldap-errors.js.map +1 -0
  190. package/dist/providers/ldap/ldap-retry.d.ts +14 -0
  191. package/dist/providers/ldap/ldap-retry.d.ts.map +1 -0
  192. package/dist/providers/ldap/ldap-retry.js +102 -0
  193. package/dist/providers/ldap/ldap-retry.js.map +1 -0
  194. package/dist/providers/ldap/ldap-sanitizer.d.ts +12 -0
  195. package/dist/providers/ldap/ldap-sanitizer.d.ts.map +1 -0
  196. package/dist/providers/ldap/ldap-sanitizer.js +104 -0
  197. package/dist/providers/ldap/ldap-sanitizer.js.map +1 -0
  198. package/dist/providers/ldap/ldap.provider.d.ts +21 -0
  199. package/dist/providers/ldap/ldap.provider.d.ts.map +1 -0
  200. package/dist/providers/ldap/ldap.provider.js +165 -0
  201. package/dist/providers/ldap/ldap.provider.js.map +1 -0
  202. package/dist/providers/ldap/queries/computer.queries.d.ts +6 -0
  203. package/dist/providers/ldap/queries/computer.queries.d.ts.map +1 -0
  204. package/dist/providers/ldap/queries/computer.queries.js +9 -0
  205. package/dist/providers/ldap/queries/computer.queries.js.map +1 -0
  206. package/dist/providers/ldap/queries/group.queries.d.ts +6 -0
  207. package/dist/providers/ldap/queries/group.queries.d.ts.map +1 -0
  208. package/dist/providers/ldap/queries/group.queries.js +9 -0
  209. package/dist/providers/ldap/queries/group.queries.js.map +1 -0
  210. package/dist/providers/ldap/queries/user.queries.d.ts +7 -0
  211. package/dist/providers/ldap/queries/user.queries.d.ts.map +1 -0
  212. package/dist/providers/ldap/queries/user.queries.js +10 -0
  213. package/dist/providers/ldap/queries/user.queries.js.map +1 -0
  214. package/dist/providers/smb/smb.provider.d.ts +68 -0
  215. package/dist/providers/smb/smb.provider.d.ts.map +1 -0
  216. package/dist/providers/smb/smb.provider.js +382 -0
  217. package/dist/providers/smb/smb.provider.js.map +1 -0
  218. package/dist/server.d.ts +2 -0
  219. package/dist/server.d.ts.map +1 -0
  220. package/dist/server.js +44 -0
  221. package/dist/server.js.map +1 -0
  222. package/dist/services/audit/ad-audit.service.d.ts +70 -0
  223. package/dist/services/audit/ad-audit.service.d.ts.map +1 -0
  224. package/dist/services/audit/ad-audit.service.js +1019 -0
  225. package/dist/services/audit/ad-audit.service.js.map +1 -0
  226. package/dist/services/audit/attack-graph.service.d.ts +62 -0
  227. package/dist/services/audit/attack-graph.service.d.ts.map +1 -0
  228. package/dist/services/audit/attack-graph.service.js +702 -0
  229. package/dist/services/audit/attack-graph.service.js.map +1 -0
  230. package/dist/services/audit/audit.service.d.ts +4 -0
  231. package/dist/services/audit/audit.service.d.ts.map +1 -0
  232. package/dist/services/audit/audit.service.js +10 -0
  233. package/dist/services/audit/audit.service.js.map +1 -0
  234. package/dist/services/audit/azure-audit.service.d.ts +37 -0
  235. package/dist/services/audit/azure-audit.service.d.ts.map +1 -0
  236. package/dist/services/audit/azure-audit.service.js +153 -0
  237. package/dist/services/audit/azure-audit.service.js.map +1 -0
  238. package/dist/services/audit/detectors/ad/accounts.detector.d.ts +37 -0
  239. package/dist/services/audit/detectors/ad/accounts.detector.d.ts.map +1 -0
  240. package/dist/services/audit/detectors/ad/accounts.detector.js +881 -0
  241. package/dist/services/audit/detectors/ad/accounts.detector.js.map +1 -0
  242. package/dist/services/audit/detectors/ad/adcs.detector.d.ts +21 -0
  243. package/dist/services/audit/detectors/ad/adcs.detector.d.ts.map +1 -0
  244. package/dist/services/audit/detectors/ad/adcs.detector.js +227 -0
  245. package/dist/services/audit/detectors/ad/adcs.detector.js.map +1 -0
  246. package/dist/services/audit/detectors/ad/advanced.detector.d.ts +63 -0
  247. package/dist/services/audit/detectors/ad/advanced.detector.d.ts.map +1 -0
  248. package/dist/services/audit/detectors/ad/advanced.detector.js +867 -0
  249. package/dist/services/audit/detectors/ad/advanced.detector.js.map +1 -0
  250. package/dist/services/audit/detectors/ad/attack-paths.detector.d.ts +16 -0
  251. package/dist/services/audit/detectors/ad/attack-paths.detector.d.ts.map +1 -0
  252. package/dist/services/audit/detectors/ad/attack-paths.detector.js +369 -0
  253. package/dist/services/audit/detectors/ad/attack-paths.detector.js.map +1 -0
  254. package/dist/services/audit/detectors/ad/compliance.detector.d.ts +28 -0
  255. package/dist/services/audit/detectors/ad/compliance.detector.d.ts.map +1 -0
  256. package/dist/services/audit/detectors/ad/compliance.detector.js +896 -0
  257. package/dist/services/audit/detectors/ad/compliance.detector.js.map +1 -0
  258. package/dist/services/audit/detectors/ad/computers.detector.d.ts +30 -0
  259. package/dist/services/audit/detectors/ad/computers.detector.d.ts.map +1 -0
  260. package/dist/services/audit/detectors/ad/computers.detector.js +799 -0
  261. package/dist/services/audit/detectors/ad/computers.detector.js.map +1 -0
  262. package/dist/services/audit/detectors/ad/gpo.detector.d.ts +17 -0
  263. package/dist/services/audit/detectors/ad/gpo.detector.d.ts.map +1 -0
  264. package/dist/services/audit/detectors/ad/gpo.detector.js +257 -0
  265. package/dist/services/audit/detectors/ad/gpo.detector.js.map +1 -0
  266. package/dist/services/audit/detectors/ad/groups.detector.d.ts +19 -0
  267. package/dist/services/audit/detectors/ad/groups.detector.d.ts.map +1 -0
  268. package/dist/services/audit/detectors/ad/groups.detector.js +488 -0
  269. package/dist/services/audit/detectors/ad/groups.detector.js.map +1 -0
  270. package/dist/services/audit/detectors/ad/index.d.ts +15 -0
  271. package/dist/services/audit/detectors/ad/index.d.ts.map +1 -0
  272. package/dist/services/audit/detectors/ad/index.js +51 -0
  273. package/dist/services/audit/detectors/ad/index.js.map +1 -0
  274. package/dist/services/audit/detectors/ad/kerberos.detector.d.ts +17 -0
  275. package/dist/services/audit/detectors/ad/kerberos.detector.d.ts.map +1 -0
  276. package/dist/services/audit/detectors/ad/kerberos.detector.js +293 -0
  277. package/dist/services/audit/detectors/ad/kerberos.detector.js.map +1 -0
  278. package/dist/services/audit/detectors/ad/monitoring.detector.d.ts +23 -0
  279. package/dist/services/audit/detectors/ad/monitoring.detector.d.ts.map +1 -0
  280. package/dist/services/audit/detectors/ad/monitoring.detector.js +328 -0
  281. package/dist/services/audit/detectors/ad/monitoring.detector.js.map +1 -0
  282. package/dist/services/audit/detectors/ad/network.detector.d.ts +39 -0
  283. package/dist/services/audit/detectors/ad/network.detector.d.ts.map +1 -0
  284. package/dist/services/audit/detectors/ad/network.detector.js +257 -0
  285. package/dist/services/audit/detectors/ad/network.detector.js.map +1 -0
  286. package/dist/services/audit/detectors/ad/password.detector.d.ts +14 -0
  287. package/dist/services/audit/detectors/ad/password.detector.d.ts.map +1 -0
  288. package/dist/services/audit/detectors/ad/password.detector.js +235 -0
  289. package/dist/services/audit/detectors/ad/password.detector.js.map +1 -0
  290. package/dist/services/audit/detectors/ad/permissions.detector.d.ts +20 -0
  291. package/dist/services/audit/detectors/ad/permissions.detector.d.ts.map +1 -0
  292. package/dist/services/audit/detectors/ad/permissions.detector.js +392 -0
  293. package/dist/services/audit/detectors/ad/permissions.detector.js.map +1 -0
  294. package/dist/services/audit/detectors/ad/trusts.detector.d.ts +11 -0
  295. package/dist/services/audit/detectors/ad/trusts.detector.d.ts.map +1 -0
  296. package/dist/services/audit/detectors/ad/trusts.detector.js +186 -0
  297. package/dist/services/audit/detectors/ad/trusts.detector.js.map +1 -0
  298. package/dist/services/audit/detectors/azure/app-security.detector.d.ts +11 -0
  299. package/dist/services/audit/detectors/azure/app-security.detector.d.ts.map +1 -0
  300. package/dist/services/audit/detectors/azure/app-security.detector.js +184 -0
  301. package/dist/services/audit/detectors/azure/app-security.detector.js.map +1 -0
  302. package/dist/services/audit/detectors/azure/conditional-access.detector.d.ts +10 -0
  303. package/dist/services/audit/detectors/azure/conditional-access.detector.d.ts.map +1 -0
  304. package/dist/services/audit/detectors/azure/conditional-access.detector.js +130 -0
  305. package/dist/services/audit/detectors/azure/conditional-access.detector.js.map +1 -0
  306. package/dist/services/audit/detectors/azure/privilege-security.detector.d.ts +8 -0
  307. package/dist/services/audit/detectors/azure/privilege-security.detector.d.ts.map +1 -0
  308. package/dist/services/audit/detectors/azure/privilege-security.detector.js +113 -0
  309. package/dist/services/audit/detectors/azure/privilege-security.detector.js.map +1 -0
  310. package/dist/services/audit/detectors/azure/user-security.detector.d.ts +14 -0
  311. package/dist/services/audit/detectors/azure/user-security.detector.d.ts.map +1 -0
  312. package/dist/services/audit/detectors/azure/user-security.detector.js +198 -0
  313. package/dist/services/audit/detectors/azure/user-security.detector.js.map +1 -0
  314. package/dist/services/audit/detectors/index.d.ts +2 -0
  315. package/dist/services/audit/detectors/index.d.ts.map +1 -0
  316. package/dist/services/audit/detectors/index.js +38 -0
  317. package/dist/services/audit/detectors/index.js.map +1 -0
  318. package/dist/services/audit/response-formatter.d.ts +176 -0
  319. package/dist/services/audit/response-formatter.d.ts.map +1 -0
  320. package/dist/services/audit/response-formatter.js +240 -0
  321. package/dist/services/audit/response-formatter.js.map +1 -0
  322. package/dist/services/audit/scoring.service.d.ts +15 -0
  323. package/dist/services/audit/scoring.service.d.ts.map +1 -0
  324. package/dist/services/audit/scoring.service.js +139 -0
  325. package/dist/services/audit/scoring.service.js.map +1 -0
  326. package/dist/services/auth/crypto.service.d.ts +19 -0
  327. package/dist/services/auth/crypto.service.d.ts.map +1 -0
  328. package/dist/services/auth/crypto.service.js +135 -0
  329. package/dist/services/auth/crypto.service.js.map +1 -0
  330. package/dist/services/auth/errors.d.ts +19 -0
  331. package/dist/services/auth/errors.d.ts.map +1 -0
  332. package/dist/services/auth/errors.js +46 -0
  333. package/dist/services/auth/errors.js.map +1 -0
  334. package/dist/services/auth/token.service.d.ts +41 -0
  335. package/dist/services/auth/token.service.d.ts.map +1 -0
  336. package/dist/services/auth/token.service.js +208 -0
  337. package/dist/services/auth/token.service.js.map +1 -0
  338. package/dist/services/config/config.service.d.ts +6 -0
  339. package/dist/services/config/config.service.d.ts.map +1 -0
  340. package/dist/services/config/config.service.js +64 -0
  341. package/dist/services/config/config.service.js.map +1 -0
  342. package/dist/services/export/export.service.d.ts +28 -0
  343. package/dist/services/export/export.service.d.ts.map +1 -0
  344. package/dist/services/export/export.service.js +28 -0
  345. package/dist/services/export/export.service.js.map +1 -0
  346. package/dist/services/export/formatters/csv.formatter.d.ts +8 -0
  347. package/dist/services/export/formatters/csv.formatter.d.ts.map +1 -0
  348. package/dist/services/export/formatters/csv.formatter.js +46 -0
  349. package/dist/services/export/formatters/csv.formatter.js.map +1 -0
  350. package/dist/services/export/formatters/json.formatter.d.ts +40 -0
  351. package/dist/services/export/formatters/json.formatter.d.ts.map +1 -0
  352. package/dist/services/export/formatters/json.formatter.js +58 -0
  353. package/dist/services/export/formatters/json.formatter.js.map +1 -0
  354. package/dist/services/jobs/azure-job-runner.d.ts +38 -0
  355. package/dist/services/jobs/azure-job-runner.d.ts.map +1 -0
  356. package/dist/services/jobs/azure-job-runner.js +199 -0
  357. package/dist/services/jobs/azure-job-runner.js.map +1 -0
  358. package/dist/services/jobs/index.d.ts +4 -0
  359. package/dist/services/jobs/index.d.ts.map +1 -0
  360. package/dist/services/jobs/index.js +20 -0
  361. package/dist/services/jobs/index.js.map +1 -0
  362. package/dist/services/jobs/job-runner.d.ts +64 -0
  363. package/dist/services/jobs/job-runner.d.ts.map +1 -0
  364. package/dist/services/jobs/job-runner.js +952 -0
  365. package/dist/services/jobs/job-runner.js.map +1 -0
  366. package/dist/services/jobs/job-store.d.ts +27 -0
  367. package/dist/services/jobs/job-store.d.ts.map +1 -0
  368. package/dist/services/jobs/job-store.js +261 -0
  369. package/dist/services/jobs/job-store.js.map +1 -0
  370. package/dist/services/jobs/job.types.d.ts +67 -0
  371. package/dist/services/jobs/job.types.d.ts.map +1 -0
  372. package/dist/services/jobs/job.types.js +36 -0
  373. package/dist/services/jobs/job.types.js.map +1 -0
  374. package/dist/types/ad.types.d.ts +74 -0
  375. package/dist/types/ad.types.d.ts.map +1 -0
  376. package/dist/types/ad.types.js +3 -0
  377. package/dist/types/ad.types.js.map +1 -0
  378. package/dist/types/adcs.types.d.ts +58 -0
  379. package/dist/types/adcs.types.d.ts.map +1 -0
  380. package/dist/types/adcs.types.js +38 -0
  381. package/dist/types/adcs.types.js.map +1 -0
  382. package/dist/types/attack-graph.types.d.ts +135 -0
  383. package/dist/types/attack-graph.types.d.ts.map +1 -0
  384. package/dist/types/attack-graph.types.js +58 -0
  385. package/dist/types/attack-graph.types.js.map +1 -0
  386. package/dist/types/audit.types.d.ts +34 -0
  387. package/dist/types/audit.types.d.ts.map +1 -0
  388. package/dist/types/audit.types.js +3 -0
  389. package/dist/types/audit.types.js.map +1 -0
  390. package/dist/types/azure.types.d.ts +61 -0
  391. package/dist/types/azure.types.d.ts.map +1 -0
  392. package/dist/types/azure.types.js +3 -0
  393. package/dist/types/azure.types.js.map +1 -0
  394. package/dist/types/config.types.d.ts +63 -0
  395. package/dist/types/config.types.d.ts.map +1 -0
  396. package/dist/types/config.types.js +3 -0
  397. package/dist/types/config.types.js.map +1 -0
  398. package/dist/types/error.types.d.ts +33 -0
  399. package/dist/types/error.types.d.ts.map +1 -0
  400. package/dist/types/error.types.js +70 -0
  401. package/dist/types/error.types.js.map +1 -0
  402. package/dist/types/finding.types.d.ts +133 -0
  403. package/dist/types/finding.types.d.ts.map +1 -0
  404. package/dist/types/finding.types.js +3 -0
  405. package/dist/types/finding.types.js.map +1 -0
  406. package/dist/types/gpo.types.d.ts +39 -0
  407. package/dist/types/gpo.types.d.ts.map +1 -0
  408. package/dist/types/gpo.types.js +15 -0
  409. package/dist/types/gpo.types.js.map +1 -0
  410. package/dist/types/token.types.d.ts +26 -0
  411. package/dist/types/token.types.d.ts.map +1 -0
  412. package/dist/types/token.types.js +3 -0
  413. package/dist/types/token.types.js.map +1 -0
  414. package/dist/types/trust.types.d.ts +45 -0
  415. package/dist/types/trust.types.d.ts.map +1 -0
  416. package/dist/types/trust.types.js +71 -0
  417. package/dist/types/trust.types.js.map +1 -0
  418. package/dist/utils/entity-converter.d.ts +17 -0
  419. package/dist/utils/entity-converter.d.ts.map +1 -0
  420. package/dist/utils/entity-converter.js +285 -0
  421. package/dist/utils/entity-converter.js.map +1 -0
  422. package/dist/utils/graph.util.d.ts +66 -0
  423. package/dist/utils/graph.util.d.ts.map +1 -0
  424. package/dist/utils/graph.util.js +382 -0
  425. package/dist/utils/graph.util.js.map +1 -0
  426. package/dist/utils/logger.d.ts +7 -0
  427. package/dist/utils/logger.d.ts.map +1 -0
  428. package/dist/utils/logger.js +86 -0
  429. package/dist/utils/logger.js.map +1 -0
  430. package/dist/utils/type-name-normalizer.d.ts +5 -0
  431. package/dist/utils/type-name-normalizer.d.ts.map +1 -0
  432. package/dist/utils/type-name-normalizer.js +218 -0
  433. package/dist/utils/type-name-normalizer.js.map +1 -0
  434. package/docker-compose.yml +26 -0
  435. package/docs/api/README.md +178 -0
  436. package/docs/api/openapi.yaml +1524 -0
  437. package/eslint.config.js +54 -0
  438. package/jest.config.js +38 -0
  439. package/package.json +97 -0
  440. package/scripts/fetch-ad-cert.sh +142 -0
  441. package/src/.gitkeep +0 -0
  442. package/src/api/.gitkeep +0 -0
  443. package/src/api/controllers/.gitkeep +0 -0
  444. package/src/api/controllers/audit.controller.ts +313 -0
  445. package/src/api/controllers/auth.controller.ts +258 -0
  446. package/src/api/controllers/export.controller.ts +153 -0
  447. package/src/api/controllers/health.controller.ts +16 -0
  448. package/src/api/controllers/jobs.controller.ts +187 -0
  449. package/src/api/controllers/providers.controller.ts +165 -0
  450. package/src/api/dto/.gitkeep +0 -0
  451. package/src/api/dto/AuditRequest.dto.ts +8 -0
  452. package/src/api/dto/AuditResponse.dto.ts +19 -0
  453. package/src/api/dto/TokenRequest.dto.ts +8 -0
  454. package/src/api/dto/TokenResponse.dto.ts +14 -0
  455. package/src/api/middlewares/.gitkeep +0 -0
  456. package/src/api/middlewares/authenticate.ts +203 -0
  457. package/src/api/middlewares/errorHandler.ts +54 -0
  458. package/src/api/middlewares/rateLimit.ts +35 -0
  459. package/src/api/middlewares/validate.ts +32 -0
  460. package/src/api/routes/.gitkeep +0 -0
  461. package/src/api/routes/audit.routes.ts +77 -0
  462. package/src/api/routes/auth.routes.ts +71 -0
  463. package/src/api/routes/export.routes.ts +34 -0
  464. package/src/api/routes/health.routes.ts +14 -0
  465. package/src/api/routes/index.ts +40 -0
  466. package/src/api/routes/providers.routes.ts +24 -0
  467. package/src/api/validators/.gitkeep +0 -0
  468. package/src/api/validators/audit.schemas.ts +59 -0
  469. package/src/api/validators/auth.schemas.ts +59 -0
  470. package/src/app.ts +87 -0
  471. package/src/config/.gitkeep +0 -0
  472. package/src/config/config.schema.ts +108 -0
  473. package/src/config/index.ts +82 -0
  474. package/src/container.ts +221 -0
  475. package/src/data/.gitkeep +0 -0
  476. package/src/data/database.ts +78 -0
  477. package/src/data/jobs/token-cleanup.job.ts +166 -0
  478. package/src/data/migrations/.gitkeep +0 -0
  479. package/src/data/migrations/001_initial_schema.sql +47 -0
  480. package/src/data/migrations/migration.runner.ts +125 -0
  481. package/src/data/models/.gitkeep +0 -0
  482. package/src/data/models/Token.model.ts +35 -0
  483. package/src/data/repositories/.gitkeep +0 -0
  484. package/src/data/repositories/token.repository.ts +160 -0
  485. package/src/providers/.gitkeep +0 -0
  486. package/src/providers/azure/.gitkeep +0 -0
  487. package/src/providers/azure/auth.provider.ts +14 -0
  488. package/src/providers/azure/azure-errors.ts +189 -0
  489. package/src/providers/azure/azure-retry.ts +168 -0
  490. package/src/providers/azure/graph-client.ts +315 -0
  491. package/src/providers/azure/graph.provider.ts +294 -0
  492. package/src/providers/azure/queries/app.queries.ts +9 -0
  493. package/src/providers/azure/queries/policy.queries.ts +9 -0
  494. package/src/providers/azure/queries/user.queries.ts +10 -0
  495. package/src/providers/interfaces/.gitkeep +0 -0
  496. package/src/providers/interfaces/IGraphProvider.ts +117 -0
  497. package/src/providers/interfaces/ILDAPProvider.ts +142 -0
  498. package/src/providers/ldap/.gitkeep +0 -0
  499. package/src/providers/ldap/acl-parser.ts +231 -0
  500. package/src/providers/ldap/ad-mappers.ts +280 -0
  501. package/src/providers/ldap/ldap-client.ts +259 -0
  502. package/src/providers/ldap/ldap-errors.ts +188 -0
  503. package/src/providers/ldap/ldap-retry.ts +267 -0
  504. package/src/providers/ldap/ldap-sanitizer.ts +273 -0
  505. package/src/providers/ldap/ldap.provider.ts +293 -0
  506. package/src/providers/ldap/queries/computer.queries.ts +9 -0
  507. package/src/providers/ldap/queries/group.queries.ts +9 -0
  508. package/src/providers/ldap/queries/user.queries.ts +10 -0
  509. package/src/providers/smb/smb.provider.ts +653 -0
  510. package/src/server.ts +60 -0
  511. package/src/services/.gitkeep +0 -0
  512. package/src/services/audit/.gitkeep +0 -0
  513. package/src/services/audit/ad-audit.service.ts +1481 -0
  514. package/src/services/audit/attack-graph.service.ts +1104 -0
  515. package/src/services/audit/audit.service.ts +12 -0
  516. package/src/services/audit/azure-audit.service.ts +286 -0
  517. package/src/services/audit/detectors/ad/accounts.detector.ts +1232 -0
  518. package/src/services/audit/detectors/ad/adcs.detector.ts +449 -0
  519. package/src/services/audit/detectors/ad/advanced.detector.ts +1270 -0
  520. package/src/services/audit/detectors/ad/attack-paths.detector.ts +600 -0
  521. package/src/services/audit/detectors/ad/compliance.detector.ts +1421 -0
  522. package/src/services/audit/detectors/ad/computers.detector.ts +1188 -0
  523. package/src/services/audit/detectors/ad/gpo.detector.ts +485 -0
  524. package/src/services/audit/detectors/ad/groups.detector.ts +685 -0
  525. package/src/services/audit/detectors/ad/index.ts +84 -0
  526. package/src/services/audit/detectors/ad/kerberos.detector.ts +424 -0
  527. package/src/services/audit/detectors/ad/monitoring.detector.ts +501 -0
  528. package/src/services/audit/detectors/ad/network.detector.ts +538 -0
  529. package/src/services/audit/detectors/ad/password.detector.ts +324 -0
  530. package/src/services/audit/detectors/ad/permissions.detector.ts +637 -0
  531. package/src/services/audit/detectors/ad/trusts.detector.ts +315 -0
  532. package/src/services/audit/detectors/azure/app-security.detector.ts +246 -0
  533. package/src/services/audit/detectors/azure/conditional-access.detector.ts +186 -0
  534. package/src/services/audit/detectors/azure/privilege-security.detector.ts +176 -0
  535. package/src/services/audit/detectors/azure/user-security.detector.ts +280 -0
  536. package/src/services/audit/detectors/index.ts +18 -0
  537. package/src/services/audit/response-formatter.ts +604 -0
  538. package/src/services/audit/scoring.service.ts +234 -0
  539. package/src/services/auth/.gitkeep +0 -0
  540. package/src/services/auth/crypto.service.ts +230 -0
  541. package/src/services/auth/errors.ts +47 -0
  542. package/src/services/auth/token.service.ts +420 -0
  543. package/src/services/config/.gitkeep +0 -0
  544. package/src/services/config/config.service.ts +75 -0
  545. package/src/services/export/.gitkeep +0 -0
  546. package/src/services/export/export.service.ts +99 -0
  547. package/src/services/export/formatters/csv.formatter.ts +124 -0
  548. package/src/services/export/formatters/json.formatter.ts +160 -0
  549. package/src/services/jobs/azure-job-runner.ts +312 -0
  550. package/src/services/jobs/index.ts +9 -0
  551. package/src/services/jobs/job-runner.ts +1280 -0
  552. package/src/services/jobs/job-store.ts +384 -0
  553. package/src/services/jobs/job.types.ts +182 -0
  554. package/src/types/.gitkeep +0 -0
  555. package/src/types/ad.types.ts +91 -0
  556. package/src/types/adcs.types.ts +107 -0
  557. package/src/types/attack-graph.types.ts +260 -0
  558. package/src/types/audit.types.ts +42 -0
  559. package/src/types/azure.types.ts +68 -0
  560. package/src/types/config.types.ts +79 -0
  561. package/src/types/error.types.ts +69 -0
  562. package/src/types/finding.types.ts +284 -0
  563. package/src/types/gpo.types.ts +72 -0
  564. package/src/types/smb2.d.ts +73 -0
  565. package/src/types/token.types.ts +32 -0
  566. package/src/types/trust.types.ts +140 -0
  567. package/src/utils/.gitkeep +0 -0
  568. package/src/utils/entity-converter.ts +453 -0
  569. package/src/utils/graph.util.ts +609 -0
  570. package/src/utils/logger.ts +111 -0
  571. package/src/utils/type-name-normalizer.ts +302 -0
  572. package/tests/.gitkeep +0 -0
  573. package/tests/e2e/.gitkeep +0 -0
  574. package/tests/fixtures/.gitkeep +0 -0
  575. package/tests/integration/.gitkeep +0 -0
  576. package/tests/integration/README.md +156 -0
  577. package/tests/integration/ad-audit.integration.test.ts +216 -0
  578. package/tests/integration/api/.gitkeep +0 -0
  579. package/tests/integration/api/endpoints.integration.test.ts +431 -0
  580. package/tests/integration/auth/jwt-authentication.integration.test.ts +358 -0
  581. package/tests/integration/providers/.gitkeep +0 -0
  582. package/tests/integration/providers/azure-basic.integration.test.ts +167 -0
  583. package/tests/integration/providers/ldap-basic.integration.test.ts +152 -0
  584. package/tests/integration/providers/ldap-connectivity.test.ts +44 -0
  585. package/tests/integration/providers/ldap-provider.integration.test.ts +347 -0
  586. package/tests/mocks/.gitkeep +0 -0
  587. package/tests/setup.ts +16 -0
  588. package/tests/unit/.gitkeep +0 -0
  589. package/tests/unit/api/middlewares/authenticate.test.ts +446 -0
  590. package/tests/unit/providers/.gitkeep +0 -0
  591. package/tests/unit/providers/azure/azure-errors.test.ts +193 -0
  592. package/tests/unit/providers/azure/azure-retry.test.ts +254 -0
  593. package/tests/unit/providers/azure/graph-provider.test.ts +313 -0
  594. package/tests/unit/providers/ldap/ad-mappers.test.ts +392 -0
  595. package/tests/unit/providers/ldap/ldap-provider.test.ts +376 -0
  596. package/tests/unit/providers/ldap/ldap-retry.test.ts +377 -0
  597. package/tests/unit/providers/ldap/ldap-sanitizer.test.ts +301 -0
  598. package/tests/unit/sample.test.ts +19 -0
  599. package/tests/unit/services/.gitkeep +0 -0
  600. package/tests/unit/services/audit/detectors/ad/accounts.detector.test.ts +393 -0
  601. package/tests/unit/services/audit/detectors/ad/advanced.detector.test.ts +380 -0
  602. package/tests/unit/services/audit/detectors/ad/computers.detector.test.ts +440 -0
  603. package/tests/unit/services/audit/detectors/ad/groups.detector.test.ts +276 -0
  604. package/tests/unit/services/audit/detectors/ad/kerberos.detector.test.ts +215 -0
  605. package/tests/unit/services/audit/detectors/ad/password.detector.test.ts +226 -0
  606. package/tests/unit/services/audit/detectors/ad/permissions.detector.test.ts +244 -0
  607. package/tests/unit/services/audit/detectors/azure/app-security.detector.test.ts +349 -0
  608. package/tests/unit/services/audit/detectors/azure/conditional-access.detector.test.ts +374 -0
  609. package/tests/unit/services/audit/detectors/azure/privilege-security.detector.test.ts +374 -0
  610. package/tests/unit/services/audit/detectors/azure/user-security.detector.test.ts +297 -0
  611. package/tests/unit/services/auth/crypto.service.test.ts +296 -0
  612. package/tests/unit/services/auth/token.service.test.ts +579 -0
  613. package/tests/unit/services/export/export.service.test.ts +241 -0
  614. package/tests/unit/services/export/formatters/csv.formatter.test.ts +270 -0
  615. package/tests/unit/services/export/formatters/json.formatter.test.ts +258 -0
  616. package/tests/unit/utils/.gitkeep +0 -0
  617. package/tsconfig.json +50 -0
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Microsoft Graph Client
3
+ *
4
+ * Handles authentication and API requests to Microsoft Graph using OAuth 2.0 client credentials flow.
5
+ * Supports automatic token refresh and retry logic with rate limit handling.
6
+ *
7
+ * Task 2: Implement Microsoft Graph Client with OAuth 2.0 (Story 1.6)
8
+ */
9
+
10
+ import { Client } from '@microsoft/microsoft-graph-client';
11
+ import { ClientSecretCredential } from '@azure/identity';
12
+ import { AzureProviderConfig } from '../../types/config.types';
13
+ import {
14
+ AzureAuthenticationError,
15
+ AzureAPIError,
16
+ AzureRateLimitError,
17
+ AzureTimeoutError,
18
+ } from './azure-errors';
19
+ import { retryWithBackoff, AZURE_RETRY_CONFIGS, RetryOptions } from './azure-retry';
20
+
21
+ /**
22
+ * Graph client options
23
+ */
24
+ export interface GraphClientOptions {
25
+ timeout?: number; // milliseconds (default: 30000)
26
+ maxRetries?: number; // default: 3
27
+ apiVersion?: string; // default: 'v1.0'
28
+ }
29
+
30
+ /**
31
+ * Token info
32
+ */
33
+ interface TokenInfo {
34
+ accessToken: string;
35
+ expiresAt: Date;
36
+ }
37
+
38
+ /**
39
+ * Microsoft Graph Client
40
+ *
41
+ * Provides authenticated access to Microsoft Graph API using Azure AD service principal.
42
+ */
43
+ export class GraphClient {
44
+ private client: Client | null = null;
45
+ private credential: ClientSecretCredential;
46
+ private tokenInfo: TokenInfo | null = null;
47
+ private readonly config: AzureProviderConfig;
48
+ private readonly options: Required<GraphClientOptions>;
49
+ private readonly graphScope = 'https://graph.microsoft.com/.default';
50
+
51
+ constructor(config: AzureProviderConfig, options: GraphClientOptions = {}) {
52
+ this.config = config;
53
+ this.options = {
54
+ timeout: options.timeout || 30000,
55
+ maxRetries: options.maxRetries || 3,
56
+ apiVersion: options.apiVersion || 'v1.0',
57
+ };
58
+
59
+ // Initialize Azure AD credential
60
+ this.credential = new ClientSecretCredential(
61
+ config.tenantId,
62
+ config.clientId,
63
+ config.clientSecret
64
+ );
65
+ }
66
+
67
+ /**
68
+ * Authenticate and initialize Graph client
69
+ *
70
+ * Obtains an access token using OAuth 2.0 client credentials flow.
71
+ *
72
+ * @throws {AzureAuthenticationError} If authentication fails
73
+ */
74
+ async authenticate(): Promise<void> {
75
+ try {
76
+ // Get access token
77
+ const tokenResponse = await this.credential.getToken(this.graphScope);
78
+
79
+ if (!tokenResponse) {
80
+ throw new AzureAuthenticationError(
81
+ 'Failed to obtain access token',
82
+ this.config.tenantId,
83
+ this.config.clientId
84
+ );
85
+ }
86
+
87
+ // Store token info
88
+ this.tokenInfo = {
89
+ accessToken: tokenResponse.token,
90
+ expiresAt: tokenResponse.expiresOnTimestamp
91
+ ? new Date(tokenResponse.expiresOnTimestamp)
92
+ : new Date(Date.now() + 3600 * 1000), // 1 hour default
93
+ };
94
+
95
+ // Initialize Graph client with token
96
+ this.client = Client.init({
97
+ authProvider: (done) => {
98
+ done(null, this.tokenInfo!.accessToken);
99
+ },
100
+ defaultVersion: this.options.apiVersion,
101
+ });
102
+ } catch (error) {
103
+ throw new AzureAuthenticationError(
104
+ `Authentication failed: ${error instanceof Error ? error.message : String(error)}`,
105
+ this.config.tenantId,
106
+ this.config.clientId,
107
+ error instanceof Error ? error : undefined
108
+ );
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Check if token is expired or about to expire
114
+ *
115
+ * @returns True if token needs refresh (expired or expires in <5 minutes)
116
+ */
117
+ private isTokenExpired(): boolean {
118
+ if (!this.tokenInfo) {
119
+ return true;
120
+ }
121
+
122
+ const now = Date.now();
123
+ const expiresAt = this.tokenInfo.expiresAt.getTime();
124
+ const fiveMinutes = 5 * 60 * 1000;
125
+
126
+ return expiresAt - now < fiveMinutes;
127
+ }
128
+
129
+ /**
130
+ * Ensure client is authenticated
131
+ *
132
+ * Automatically refreshes token if expired.
133
+ *
134
+ * @throws {AzureAuthenticationError} If not authenticated and authentication fails
135
+ */
136
+ private async ensureAuthenticated(): Promise<void> {
137
+ if (!this.client || this.isTokenExpired()) {
138
+ await this.authenticate();
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Make a GET request to Graph API
144
+ *
145
+ * Handles authentication, rate limiting, and retries automatically.
146
+ *
147
+ * @param endpoint - Graph API endpoint (e.g., '/users', '/groups')
148
+ * @param params - Query parameters
149
+ * @param retryOptions - Override default retry options
150
+ * @returns Response data
151
+ * @throws {AzureAPIError} If request fails
152
+ */
153
+ async get<T = unknown>(
154
+ endpoint: string,
155
+ params?: Record<string, unknown>,
156
+ retryOptions?: RetryOptions
157
+ ): Promise<T> {
158
+ // Wrap the request with retry logic
159
+ return retryWithBackoff(async () => {
160
+ await this.ensureAuthenticated();
161
+
162
+ if (!this.client) {
163
+ throw new AzureAPIError('Graph client not initialized', endpoint);
164
+ }
165
+
166
+ try {
167
+ let request = this.client.api(endpoint);
168
+
169
+ // Add query parameters
170
+ if (params) {
171
+ const queryParams: Record<string, string> = {};
172
+ for (const [key, value] of Object.entries(params)) {
173
+ if (value !== undefined && value !== null) {
174
+ queryParams[key] = String(value);
175
+ }
176
+ }
177
+ if (Object.keys(queryParams).length > 0) {
178
+ request = request.query(queryParams);
179
+ }
180
+ }
181
+
182
+ // Set timeout
183
+ request = request.options({
184
+ timeout: this.options.timeout,
185
+ });
186
+
187
+ // Execute request
188
+ const response = await request.get();
189
+ return response as T;
190
+ } catch (error) {
191
+ // Handle rate limit (429)
192
+ if (error instanceof Error && 'statusCode' in error && error.statusCode === 429) {
193
+ const retryAfter = this.extractRetryAfter(error);
194
+ throw new AzureRateLimitError(
195
+ `Rate limit exceeded for ${endpoint}. Retry after ${retryAfter}s`,
196
+ endpoint,
197
+ retryAfter
198
+ );
199
+ }
200
+
201
+ // Handle timeout
202
+ if (error instanceof Error && error.message.includes('timeout')) {
203
+ throw new AzureTimeoutError(
204
+ `Request to ${endpoint} timed out after ${this.options.timeout}ms`,
205
+ `GET ${endpoint}`,
206
+ this.options.timeout
207
+ );
208
+ }
209
+
210
+ // Generic API error
211
+ const statusCode =
212
+ error instanceof Error && 'statusCode' in error
213
+ ? (error as { statusCode: number }).statusCode
214
+ : undefined;
215
+
216
+ throw new AzureAPIError(
217
+ `Graph API request failed: ${error instanceof Error ? error.message : String(error)}`,
218
+ endpoint,
219
+ statusCode,
220
+ error instanceof Error ? error : undefined
221
+ );
222
+ }
223
+ }, retryOptions || AZURE_RETRY_CONFIGS.default);
224
+ }
225
+
226
+ /**
227
+ * Get all results with pagination
228
+ *
229
+ * Automatically follows @odata.nextLink to retrieve all pages.
230
+ *
231
+ * @param endpoint - Graph API endpoint
232
+ * @param params - Query parameters
233
+ * @returns Array of all results
234
+ */
235
+ async getAll<T = unknown>(endpoint: string, params?: Record<string, unknown>): Promise<T[]> {
236
+ const results: T[] = [];
237
+ let nextLink: string | undefined = endpoint;
238
+ let currentParams: Record<string, unknown> | undefined = params;
239
+
240
+ while (nextLink) {
241
+ const response: { value: T[]; '@odata.nextLink'?: string } = await this.get<{
242
+ value: T[];
243
+ '@odata.nextLink'?: string;
244
+ }>(nextLink, currentParams);
245
+
246
+ if (response.value && Array.isArray(response.value)) {
247
+ results.push(...response.value);
248
+ }
249
+
250
+ nextLink = response['@odata.nextLink'];
251
+ // For subsequent pages, don't pass params (they're in the nextLink)
252
+ currentParams = undefined;
253
+ }
254
+
255
+ return results;
256
+ }
257
+
258
+ /**
259
+ * Extract retry-after value from error
260
+ *
261
+ * @param error - Error object
262
+ * @returns Retry after seconds (default: 60)
263
+ */
264
+ private extractRetryAfter(error: Error): number {
265
+ try {
266
+ if ('headers' in error && error.headers && typeof error.headers === 'object') {
267
+ const headers = error.headers as Record<string, string>;
268
+ const retryAfter = headers['retry-after'] || headers['Retry-After'];
269
+ if (retryAfter) {
270
+ const seconds = parseInt(retryAfter, 10);
271
+ if (!isNaN(seconds)) {
272
+ return seconds;
273
+ }
274
+ }
275
+ }
276
+ } catch {
277
+ // Ignore parsing errors
278
+ }
279
+ return 60; // Default to 60 seconds
280
+ }
281
+
282
+ /**
283
+ * Test connection to Microsoft Graph
284
+ *
285
+ * Verifies authentication and basic API access.
286
+ *
287
+ * @returns True if connection is successful
288
+ * @throws {AzureAuthenticationError | AzureAPIError} If connection fails
289
+ */
290
+ async testConnection(): Promise<boolean> {
291
+ await this.authenticate();
292
+
293
+ // Try a simple API call to verify access
294
+ await this.get('/organization');
295
+
296
+ return true;
297
+ }
298
+
299
+ /**
300
+ * Get current access token
301
+ *
302
+ * @returns Access token or null if not authenticated
303
+ */
304
+ getAccessToken(): string | null {
305
+ return this.tokenInfo?.accessToken || null;
306
+ }
307
+
308
+ /**
309
+ * Clear cached token and client
310
+ */
311
+ disconnect(): void {
312
+ this.client = null;
313
+ this.tokenInfo = null;
314
+ }
315
+ }
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Microsoft Graph Provider
3
+ *
4
+ * High-level provider for querying Azure AD / Microsoft Graph API.
5
+ * Implements the IGraphProvider interface with full support for users, groups, applications, and policies.
6
+ *
7
+ * Task 3: Create Azure Provider query methods (Story 1.6)
8
+ */
9
+
10
+ import {
11
+ IGraphProvider,
12
+ AzureConnectionTestResult,
13
+ GraphQueryOptions,
14
+ } from '../interfaces/IGraphProvider';
15
+ import { AzureUser, AzureGroup, AzureApp, AzurePolicy } from '../../types/azure.types';
16
+ import { AzureProviderConfig } from '../../types/config.types';
17
+ import { GraphClient } from './graph-client';
18
+ import {
19
+ AzureAPIError,
20
+ AzureAuthenticationError,
21
+ AzurePermissionError,
22
+ } from './azure-errors';
23
+
24
+ /**
25
+ * Microsoft Graph Provider
26
+ *
27
+ * Provides high-level methods for querying Azure AD objects via Microsoft Graph API.
28
+ */
29
+ export class GraphProvider implements IGraphProvider {
30
+ private readonly client: GraphClient;
31
+ private readonly config: AzureProviderConfig;
32
+ private readonly graphApiUrl = 'https://graph.microsoft.com';
33
+
34
+ constructor(config: AzureProviderConfig) {
35
+ this.config = config;
36
+ this.client = new GraphClient(config, {
37
+ timeout: 30000, // 30 seconds
38
+ maxRetries: 3,
39
+ apiVersion: 'v1.0',
40
+ });
41
+ }
42
+
43
+ /**
44
+ * Authenticate with Microsoft Graph
45
+ *
46
+ * @throws {AzureAuthenticationError} If authentication fails
47
+ */
48
+ async authenticate(): Promise<void> {
49
+ await this.client.authenticate();
50
+ }
51
+
52
+ /**
53
+ * Test connection to Microsoft Graph API
54
+ *
55
+ * @returns Connection test result with diagnostics
56
+ */
57
+ async testConnection(): Promise<AzureConnectionTestResult> {
58
+ const startTime = Date.now();
59
+
60
+ try {
61
+ // Authenticate
62
+ await this.authenticate();
63
+
64
+ // Test basic API access by getting organization info
65
+ await this.client.get<{ value: { id: string }[] }>('/organization');
66
+
67
+ const responseTime = Date.now() - startTime;
68
+
69
+ return {
70
+ success: true,
71
+ message: 'Connection successful',
72
+ details: {
73
+ tenantId: this.config.tenantId,
74
+ clientId: this.config.clientId,
75
+ graphApiUrl: this.graphApiUrl,
76
+ authenticated: true,
77
+ permissions: ['User.Read.All', 'Group.Read.All'], // TODO: Get actual permissions
78
+ responseTime,
79
+ },
80
+ };
81
+ } catch (error) {
82
+ const responseTime = Date.now() - startTime;
83
+
84
+ if (error instanceof AzureAuthenticationError) {
85
+ return {
86
+ success: false,
87
+ message: `Authentication failed: ${error.message}`,
88
+ details: {
89
+ tenantId: this.config.tenantId,
90
+ clientId: this.config.clientId,
91
+ graphApiUrl: this.graphApiUrl,
92
+ authenticated: false,
93
+ responseTime,
94
+ },
95
+ };
96
+ }
97
+
98
+ return {
99
+ success: false,
100
+ message: `Connection test failed: ${error instanceof Error ? error.message : String(error)}`,
101
+ details: {
102
+ tenantId: this.config.tenantId,
103
+ clientId: this.config.clientId,
104
+ graphApiUrl: this.graphApiUrl,
105
+ authenticated: false,
106
+ responseTime,
107
+ },
108
+ };
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Query Azure AD users
114
+ *
115
+ * @param options - Query options (filter, select, top, etc.)
116
+ * @returns Array of Azure AD users
117
+ * @throws {AzureAPIError} If the API request fails
118
+ */
119
+ async getUsers(options?: GraphQueryOptions): Promise<AzureUser[]> {
120
+ try {
121
+ const params = this.buildQueryParams(options);
122
+
123
+ // Use getAll to handle pagination
124
+ const users = await this.client.getAll<AzureUser>('/users', params);
125
+
126
+ return users;
127
+ } catch (error) {
128
+ if (
129
+ error instanceof AzureAPIError &&
130
+ error.statusCode === 403
131
+ ) {
132
+ throw new AzurePermissionError(
133
+ 'Insufficient permissions to read users. Required: User.Read.All',
134
+ '/users',
135
+ ['User.Read.All']
136
+ );
137
+ }
138
+ throw error;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Query Azure AD groups
144
+ *
145
+ * @param options - Query options (filter, select, top, etc.)
146
+ * @returns Array of Azure AD groups
147
+ * @throws {AzureAPIError} If the API request fails
148
+ */
149
+ async getGroups(options?: GraphQueryOptions): Promise<AzureGroup[]> {
150
+ try {
151
+ const params = this.buildQueryParams(options);
152
+
153
+ const groups = await this.client.getAll<AzureGroup>('/groups', params);
154
+
155
+ return groups;
156
+ } catch (error) {
157
+ if (error instanceof AzureAPIError && error.statusCode === 403) {
158
+ throw new AzurePermissionError(
159
+ 'Insufficient permissions to read groups. Required: Group.Read.All',
160
+ '/groups',
161
+ ['Group.Read.All']
162
+ );
163
+ }
164
+ throw error;
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Query Azure AD applications
170
+ *
171
+ * @param options - Query options (filter, select, top, etc.)
172
+ * @returns Array of Azure AD applications
173
+ * @throws {AzureAPIError} If the API request fails
174
+ */
175
+ async getApplications(options?: GraphQueryOptions): Promise<AzureApp[]> {
176
+ try {
177
+ const params = this.buildQueryParams(options);
178
+
179
+ const apps = await this.client.getAll<AzureApp>('/applications', params);
180
+
181
+ return apps;
182
+ } catch (error) {
183
+ if (error instanceof AzureAPIError && error.statusCode === 403) {
184
+ throw new AzurePermissionError(
185
+ 'Insufficient permissions to read applications. Required: Application.Read.All',
186
+ '/applications',
187
+ ['Application.Read.All']
188
+ );
189
+ }
190
+ throw error;
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Query Conditional Access policies
196
+ *
197
+ * @param options - Query options (filter, select, top, etc.)
198
+ * @returns Array of Conditional Access policies
199
+ * @throws {AzureAPIError} If the API request fails
200
+ */
201
+ async getPolicies(options?: GraphQueryOptions): Promise<AzurePolicy[]> {
202
+ try {
203
+ const params = this.buildQueryParams(options);
204
+
205
+ const policies = await this.client.getAll<AzurePolicy>(
206
+ '/identity/conditionalAccess/policies',
207
+ params
208
+ );
209
+
210
+ return policies;
211
+ } catch (error) {
212
+ if (error instanceof AzureAPIError && error.statusCode === 403) {
213
+ throw new AzurePermissionError(
214
+ 'Insufficient permissions to read policies. Required: Policy.Read.All',
215
+ '/identity/conditionalAccess/policies',
216
+ ['Policy.Read.All']
217
+ );
218
+ }
219
+ throw error;
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Get organization/tenant information
225
+ *
226
+ * @returns Organization info with display name
227
+ */
228
+ async getOrganization(): Promise<{ displayName: string; id: string; verifiedDomains: string[] }> {
229
+ await this.authenticate();
230
+ const response = await this.client.get<{
231
+ value: Array<{
232
+ id: string;
233
+ displayName: string;
234
+ verifiedDomains: Array<{ name: string; isDefault: boolean }>;
235
+ }>;
236
+ }>('/organization');
237
+
238
+ const org = response.value[0];
239
+ return {
240
+ id: org?.id || this.config.tenantId,
241
+ displayName: org?.displayName || 'Unknown',
242
+ verifiedDomains: org?.verifiedDomains?.map((d) => d.name) || [],
243
+ };
244
+ }
245
+
246
+ /**
247
+ * Disconnect from Microsoft Graph
248
+ *
249
+ * Clears cached tokens and connection state.
250
+ */
251
+ async disconnect(): Promise<void> {
252
+ this.client.disconnect();
253
+ }
254
+
255
+ /**
256
+ * Build OData query parameters from options
257
+ *
258
+ * @param options - Query options
259
+ * @returns Query parameters for Graph API
260
+ */
261
+ private buildQueryParams(options?: GraphQueryOptions): Record<string, string> | undefined {
262
+ if (!options) {
263
+ return undefined;
264
+ }
265
+
266
+ const params: Record<string, string> = {};
267
+
268
+ if (options.filter) {
269
+ params['$filter'] = options.filter;
270
+ }
271
+
272
+ if (options.select && options.select.length > 0) {
273
+ params['$select'] = options.select.join(',');
274
+ }
275
+
276
+ if (options.expand && options.expand.length > 0) {
277
+ params['$expand'] = options.expand.join(',');
278
+ }
279
+
280
+ if (options.orderBy) {
281
+ params['$orderby'] = options.orderBy;
282
+ }
283
+
284
+ if (options.top !== undefined) {
285
+ params['$top'] = String(options.top);
286
+ }
287
+
288
+ if (options.skip !== undefined) {
289
+ params['$skip'] = String(options.skip);
290
+ }
291
+
292
+ return Object.keys(params).length > 0 ? params : undefined;
293
+ }
294
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Microsoft Graph Application Queries
3
+ * TODO: Full implementation in Story 1.6
4
+ */
5
+ export const GraphAppQueries = {
6
+ ALL_APPS: '/applications',
7
+ SERVICE_PRINCIPALS: '/servicePrincipals',
8
+ APP_REGISTRATIONS: '/applications?$filter=signInAudience eq \'AzureADMyOrg\'',
9
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Microsoft Graph Policy Queries
3
+ * TODO: Full implementation in Story 1.6
4
+ */
5
+ export const GraphPolicyQueries = {
6
+ CONDITIONAL_ACCESS: '/identity/conditionalAccess/policies',
7
+ AUTH_METHODS: '/policies/authenticationMethodsPolicy',
8
+ AUTHORIZATION: '/policies/authorizationPolicy',
9
+ };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Microsoft Graph User Queries
3
+ * TODO: Full implementation in Story 1.6
4
+ */
5
+ export const GraphUserQueries = {
6
+ ALL_USERS: '/users',
7
+ ENABLED_USERS: '/users?$filter=accountEnabled eq true',
8
+ DISABLED_USERS: '/users?$filter=accountEnabled eq false',
9
+ ADMIN_USERS: '/directoryRoles/members',
10
+ };
File without changes