@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,446 @@
1
+ import { Response, NextFunction } from 'express';
2
+ import { authenticate, AuthenticatedRequest } from '../../../../src/api/middlewares/authenticate';
3
+ import { TokenService } from '../../../../src/services/auth/token.service';
4
+ import {
5
+ TokenExpiredError,
6
+ TokenRevokedError,
7
+ UsageLimitExceededError,
8
+ TokenNotFoundError,
9
+ InvalidSignatureError,
10
+ InvalidTokenError,
11
+ } from '../../../../src/services/auth/errors';
12
+
13
+ /**
14
+ * Unit Tests for Authentication Middleware
15
+ * Task 10: Write Unit Tests for Authentication Middleware (Story 1.4)
16
+ */
17
+
18
+ // Mock logger
19
+ jest.mock('../../../../src/utils/logger', () => ({
20
+ logger: {
21
+ info: jest.fn(),
22
+ warn: jest.fn(),
23
+ error: jest.fn(),
24
+ debug: jest.fn(),
25
+ },
26
+ }));
27
+
28
+ describe('authenticate middleware', () => {
29
+ let mockTokenService: jest.Mocked<TokenService>;
30
+ let middleware: ReturnType<typeof authenticate>;
31
+ let mockReq: Partial<AuthenticatedRequest>;
32
+ let mockRes: Partial<Response>;
33
+ let mockNext: jest.Mock;
34
+ let mockJson: jest.Mock;
35
+ let mockStatus: jest.Mock;
36
+
37
+ const VALID_TOKEN = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.mock.signature';
38
+ const VALID_PAYLOAD = {
39
+ jti: 'test-jti-123',
40
+ iss: 'etc-collector',
41
+ sub: 'system',
42
+ iat: Math.floor(Date.now() / 1000),
43
+ exp: Math.floor(Date.now() / 1000) + 3600,
44
+ service: 'etc-collector',
45
+ maxUses: 10,
46
+ };
47
+
48
+ beforeEach(() => {
49
+ // Create mock TokenService
50
+ mockTokenService = {
51
+ validate: jest.fn(),
52
+ incrementUsage: jest.fn(),
53
+ } as any;
54
+
55
+ // Create middleware with mock service
56
+ middleware = authenticate(mockTokenService);
57
+
58
+ // Setup mock Express objects
59
+ mockJson = jest.fn();
60
+ mockStatus = jest.fn(() => ({ json: mockJson }));
61
+
62
+ mockReq = {
63
+ headers: {},
64
+ path: '/api/v1/test',
65
+ method: 'GET',
66
+ };
67
+
68
+ mockRes = {
69
+ status: mockStatus as any,
70
+ json: mockJson,
71
+ };
72
+
73
+ mockNext = jest.fn();
74
+ });
75
+
76
+ describe('Successful Authentication', () => {
77
+ it('should authenticate valid token and call next()', async () => {
78
+ // Arrange
79
+ mockReq.headers = {
80
+ authorization: `Bearer ${VALID_TOKEN}`,
81
+ };
82
+
83
+ mockTokenService.validate.mockResolvedValue(VALID_PAYLOAD);
84
+ mockTokenService.incrementUsage.mockResolvedValue(undefined);
85
+
86
+ // Act
87
+ await middleware(
88
+ mockReq as AuthenticatedRequest,
89
+ mockRes as Response,
90
+ mockNext as NextFunction
91
+ );
92
+
93
+ // Assert
94
+ expect(mockTokenService.validate).toHaveBeenCalledWith(VALID_TOKEN);
95
+ expect(mockTokenService.incrementUsage).toHaveBeenCalledWith(VALID_PAYLOAD.jti);
96
+ expect(mockReq.token).toEqual({
97
+ jti: VALID_PAYLOAD.jti,
98
+ iat: VALID_PAYLOAD.iat,
99
+ exp: VALID_PAYLOAD.exp,
100
+ maxUses: VALID_PAYLOAD.maxUses,
101
+ });
102
+ expect(mockNext).toHaveBeenCalled();
103
+ expect(mockStatus).not.toHaveBeenCalled();
104
+ });
105
+
106
+ it('should attach token info to request object', async () => {
107
+ // Arrange
108
+ mockReq.headers = {
109
+ authorization: `Bearer ${VALID_TOKEN}`,
110
+ };
111
+
112
+ mockTokenService.validate.mockResolvedValue(VALID_PAYLOAD);
113
+ mockTokenService.incrementUsage.mockResolvedValue(undefined);
114
+
115
+ // Act
116
+ await middleware(
117
+ mockReq as AuthenticatedRequest,
118
+ mockRes as Response,
119
+ mockNext as NextFunction
120
+ );
121
+
122
+ // Assert
123
+ expect(mockReq.token).toBeDefined();
124
+ expect(mockReq.token!.jti).toBe(VALID_PAYLOAD.jti);
125
+ expect(mockReq.token!.iat).toBe(VALID_PAYLOAD.iat);
126
+ expect(mockReq.token!.exp).toBe(VALID_PAYLOAD.exp);
127
+ expect(mockReq.token!.maxUses).toBe(VALID_PAYLOAD.maxUses);
128
+ });
129
+
130
+ it('should increment token usage on successful authentication', async () => {
131
+ // Arrange
132
+ mockReq.headers = {
133
+ authorization: `Bearer ${VALID_TOKEN}`,
134
+ };
135
+
136
+ mockTokenService.validate.mockResolvedValue(VALID_PAYLOAD);
137
+ mockTokenService.incrementUsage.mockResolvedValue(undefined);
138
+
139
+ // Act
140
+ await middleware(
141
+ mockReq as AuthenticatedRequest,
142
+ mockRes as Response,
143
+ mockNext as NextFunction
144
+ );
145
+
146
+ // Assert
147
+ expect(mockTokenService.incrementUsage).toHaveBeenCalledWith(VALID_PAYLOAD.jti);
148
+ });
149
+ });
150
+
151
+ describe('Missing or Invalid Authorization Header', () => {
152
+ it('should reject missing Authorization header with 401', async () => {
153
+ // Arrange
154
+ mockReq.headers = {};
155
+
156
+ // Act
157
+ await middleware(
158
+ mockReq as AuthenticatedRequest,
159
+ mockRes as Response,
160
+ mockNext as NextFunction
161
+ );
162
+
163
+ // Assert
164
+ expect(mockStatus).toHaveBeenCalledWith(401);
165
+ expect(mockJson).toHaveBeenCalledWith({
166
+ success: false,
167
+ error: {
168
+ code: 'AUTHENTICATION_FAILED',
169
+ message: 'Missing or invalid Authorization header',
170
+ },
171
+ });
172
+ expect(mockNext).not.toHaveBeenCalled();
173
+ expect(mockTokenService.validate).not.toHaveBeenCalled();
174
+ });
175
+
176
+ it('should reject Authorization header without Bearer prefix', async () => {
177
+ // Arrange
178
+ mockReq.headers = {
179
+ authorization: VALID_TOKEN, // Missing 'Bearer ' prefix
180
+ };
181
+
182
+ // Act
183
+ await middleware(
184
+ mockReq as AuthenticatedRequest,
185
+ mockRes as Response,
186
+ mockNext as NextFunction
187
+ );
188
+
189
+ // Assert
190
+ expect(mockStatus).toHaveBeenCalledWith(401);
191
+ expect(mockJson).toHaveBeenCalledWith({
192
+ success: false,
193
+ error: {
194
+ code: 'AUTHENTICATION_FAILED',
195
+ message: 'Missing or invalid Authorization header',
196
+ },
197
+ });
198
+ expect(mockNext).not.toHaveBeenCalled();
199
+ });
200
+
201
+ it('should reject Authorization header with wrong scheme', async () => {
202
+ // Arrange
203
+ mockReq.headers = {
204
+ authorization: `Basic ${VALID_TOKEN}`, // Wrong scheme
205
+ };
206
+
207
+ // Act
208
+ await middleware(
209
+ mockReq as AuthenticatedRequest,
210
+ mockRes as Response,
211
+ mockNext as NextFunction
212
+ );
213
+
214
+ // Assert
215
+ expect(mockStatus).toHaveBeenCalledWith(401);
216
+ expect(mockNext).not.toHaveBeenCalled();
217
+ });
218
+ });
219
+
220
+ describe('Expired Token', () => {
221
+ it('should reject expired token with 401 TOKEN_EXPIRED', async () => {
222
+ // Arrange
223
+ mockReq.headers = {
224
+ authorization: `Bearer ${VALID_TOKEN}`,
225
+ };
226
+
227
+ mockTokenService.validate.mockRejectedValue(new TokenExpiredError());
228
+
229
+ // Act
230
+ await middleware(
231
+ mockReq as AuthenticatedRequest,
232
+ mockRes as Response,
233
+ mockNext as NextFunction
234
+ );
235
+
236
+ // Assert
237
+ expect(mockStatus).toHaveBeenCalledWith(401);
238
+ expect(mockJson).toHaveBeenCalledWith({
239
+ success: false,
240
+ error: {
241
+ code: 'TOKEN_EXPIRED',
242
+ message: 'Token has expired',
243
+ },
244
+ });
245
+ expect(mockNext).not.toHaveBeenCalled();
246
+ expect(mockTokenService.incrementUsage).not.toHaveBeenCalled();
247
+ });
248
+ });
249
+
250
+ describe('Revoked Token', () => {
251
+ it('should reject revoked token with 401 TOKEN_REVOKED', async () => {
252
+ // Arrange
253
+ mockReq.headers = {
254
+ authorization: `Bearer ${VALID_TOKEN}`,
255
+ };
256
+
257
+ mockTokenService.validate.mockRejectedValue(new TokenRevokedError());
258
+
259
+ // Act
260
+ await middleware(
261
+ mockReq as AuthenticatedRequest,
262
+ mockRes as Response,
263
+ mockNext as NextFunction
264
+ );
265
+
266
+ // Assert
267
+ expect(mockStatus).toHaveBeenCalledWith(401);
268
+ expect(mockJson).toHaveBeenCalledWith({
269
+ success: false,
270
+ error: {
271
+ code: 'TOKEN_REVOKED',
272
+ message: 'Token has been revoked',
273
+ },
274
+ });
275
+ expect(mockNext).not.toHaveBeenCalled();
276
+ expect(mockTokenService.incrementUsage).not.toHaveBeenCalled();
277
+ });
278
+ });
279
+
280
+ describe('Usage Limit Exceeded', () => {
281
+ it('should reject token with quota exceeded with 403 USAGE_LIMIT_EXCEEDED', async () => {
282
+ // Arrange
283
+ mockReq.headers = {
284
+ authorization: `Bearer ${VALID_TOKEN}`,
285
+ };
286
+
287
+ mockTokenService.validate.mockRejectedValue(new UsageLimitExceededError());
288
+
289
+ // Act
290
+ await middleware(
291
+ mockReq as AuthenticatedRequest,
292
+ mockRes as Response,
293
+ mockNext as NextFunction
294
+ );
295
+
296
+ // Assert
297
+ expect(mockStatus).toHaveBeenCalledWith(403);
298
+ expect(mockJson).toHaveBeenCalledWith({
299
+ success: false,
300
+ error: {
301
+ code: 'USAGE_LIMIT_EXCEEDED',
302
+ message: 'Token usage limit exceeded',
303
+ },
304
+ });
305
+ expect(mockNext).not.toHaveBeenCalled();
306
+ expect(mockTokenService.incrementUsage).not.toHaveBeenCalled();
307
+ });
308
+ });
309
+
310
+ describe('Token Not Found', () => {
311
+ it('should reject token not in database with 401 AUTHENTICATION_FAILED', async () => {
312
+ // Arrange
313
+ mockReq.headers = {
314
+ authorization: `Bearer ${VALID_TOKEN}`,
315
+ };
316
+
317
+ mockTokenService.validate.mockRejectedValue(new TokenNotFoundError());
318
+
319
+ // Act
320
+ await middleware(
321
+ mockReq as AuthenticatedRequest,
322
+ mockRes as Response,
323
+ mockNext as NextFunction
324
+ );
325
+
326
+ // Assert
327
+ expect(mockStatus).toHaveBeenCalledWith(401);
328
+ expect(mockJson).toHaveBeenCalledWith({
329
+ success: false,
330
+ error: {
331
+ code: 'AUTHENTICATION_FAILED',
332
+ message: 'Invalid token',
333
+ },
334
+ });
335
+ expect(mockNext).not.toHaveBeenCalled();
336
+ });
337
+ });
338
+
339
+ describe('Invalid Signature', () => {
340
+ it('should reject token with invalid signature with 401', async () => {
341
+ // Arrange
342
+ mockReq.headers = {
343
+ authorization: `Bearer ${VALID_TOKEN}`,
344
+ };
345
+
346
+ mockTokenService.validate.mockRejectedValue(new InvalidSignatureError());
347
+
348
+ // Act
349
+ await middleware(
350
+ mockReq as AuthenticatedRequest,
351
+ mockRes as Response,
352
+ mockNext as NextFunction
353
+ );
354
+
355
+ // Assert
356
+ expect(mockStatus).toHaveBeenCalledWith(401);
357
+ expect(mockJson).toHaveBeenCalledWith({
358
+ success: false,
359
+ error: {
360
+ code: 'AUTHENTICATION_FAILED',
361
+ message: 'Invalid token signature',
362
+ },
363
+ });
364
+ expect(mockNext).not.toHaveBeenCalled();
365
+ });
366
+ });
367
+
368
+ describe('Invalid Token', () => {
369
+ it('should reject malformed token with 401', async () => {
370
+ // Arrange
371
+ mockReq.headers = {
372
+ authorization: `Bearer ${VALID_TOKEN}`,
373
+ };
374
+
375
+ mockTokenService.validate.mockRejectedValue(new InvalidTokenError());
376
+
377
+ // Act
378
+ await middleware(
379
+ mockReq as AuthenticatedRequest,
380
+ mockRes as Response,
381
+ mockNext as NextFunction
382
+ );
383
+
384
+ // Assert
385
+ expect(mockStatus).toHaveBeenCalledWith(401);
386
+ expect(mockJson).toHaveBeenCalledWith({
387
+ success: false,
388
+ error: {
389
+ code: 'AUTHENTICATION_FAILED',
390
+ message: 'Invalid token',
391
+ },
392
+ });
393
+ expect(mockNext).not.toHaveBeenCalled();
394
+ });
395
+ });
396
+
397
+ describe('Unexpected Errors', () => {
398
+ it('should handle unexpected error with generic 401', async () => {
399
+ // Arrange
400
+ mockReq.headers = {
401
+ authorization: `Bearer ${VALID_TOKEN}`,
402
+ };
403
+
404
+ mockTokenService.validate.mockRejectedValue(new Error('Unexpected error'));
405
+
406
+ // Act
407
+ await middleware(
408
+ mockReq as AuthenticatedRequest,
409
+ mockRes as Response,
410
+ mockNext as NextFunction
411
+ );
412
+
413
+ // Assert
414
+ expect(mockStatus).toHaveBeenCalledWith(401);
415
+ expect(mockJson).toHaveBeenCalledWith({
416
+ success: false,
417
+ error: {
418
+ code: 'AUTHENTICATION_FAILED',
419
+ message: 'Authentication failed',
420
+ },
421
+ });
422
+ expect(mockNext).not.toHaveBeenCalled();
423
+ });
424
+ });
425
+
426
+ describe('Error Response Format', () => {
427
+ it('should always return consistent error format', async () => {
428
+ // Arrange
429
+ mockReq.headers = {};
430
+
431
+ // Act
432
+ await middleware(
433
+ mockReq as AuthenticatedRequest,
434
+ mockRes as Response,
435
+ mockNext as NextFunction
436
+ );
437
+
438
+ // Assert
439
+ const errorResponse = mockJson.mock.calls[0][0];
440
+ expect(errorResponse).toHaveProperty('success', false);
441
+ expect(errorResponse).toHaveProperty('error');
442
+ expect(errorResponse.error).toHaveProperty('code');
443
+ expect(errorResponse.error).toHaveProperty('message');
444
+ });
445
+ });
446
+ });
File without changes
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Azure Error Types Unit Tests
3
+ *
4
+ * Tests for Azure-specific error classes and error handling utilities.
5
+ */
6
+
7
+ import {
8
+ AzureError,
9
+ AzureAuthenticationError,
10
+ AzureAPIError,
11
+ AzureRateLimitError,
12
+ AzureTimeoutError,
13
+ AzurePermissionError,
14
+ AzureConfigurationError,
15
+ AzureTokenExpiredError,
16
+ isRetryableError,
17
+ } from '../../../../src/providers/azure/azure-errors';
18
+
19
+ describe('Azure Error Types', () => {
20
+ describe('AzureError', () => {
21
+ it('should create base Azure error', () => {
22
+ const error = new AzureError('Test error');
23
+
24
+ expect(error).toBeInstanceOf(Error);
25
+ expect(error).toBeInstanceOf(AzureError);
26
+ expect(error.name).toBe('AzureError');
27
+ expect(error.message).toBe('Test error');
28
+ });
29
+ });
30
+
31
+ describe('AzureAuthenticationError', () => {
32
+ it('should create authentication error with context', () => {
33
+ const error = new AzureAuthenticationError(
34
+ 'Auth failed',
35
+ 'tenant-123',
36
+ 'client-456'
37
+ );
38
+
39
+ expect(error).toBeInstanceOf(AzureError);
40
+ expect(error.name).toBe('AzureAuthenticationError');
41
+ expect(error.message).toBe('Auth failed');
42
+ expect(error.tenantId).toBe('tenant-123');
43
+ expect(error.clientId).toBe('client-456');
44
+ });
45
+
46
+ it('should store cause error', () => {
47
+ const cause = new Error('Invalid credentials');
48
+ const error = new AzureAuthenticationError(
49
+ 'Auth failed',
50
+ 'tenant-123',
51
+ 'client-456',
52
+ cause
53
+ );
54
+
55
+ expect(error.cause).toBe(cause);
56
+ });
57
+ });
58
+
59
+ describe('AzureAPIError', () => {
60
+ it('should create API error with status code', () => {
61
+ const error = new AzureAPIError('API failed', '/users', 500);
62
+
63
+ expect(error).toBeInstanceOf(AzureError);
64
+ expect(error.name).toBe('AzureAPIError');
65
+ expect(error.endpoint).toBe('/users');
66
+ expect(error.statusCode).toBe(500);
67
+ });
68
+
69
+ it('should create API error without status code', () => {
70
+ const error = new AzureAPIError('API failed', '/groups');
71
+
72
+ expect(error.endpoint).toBe('/groups');
73
+ expect(error.statusCode).toBeUndefined();
74
+ });
75
+ });
76
+
77
+ describe('AzureRateLimitError', () => {
78
+ it('should create rate limit error with retry-after', () => {
79
+ const error = new AzureRateLimitError('Rate limited', '/users', 60);
80
+
81
+ expect(error).toBeInstanceOf(AzureError);
82
+ expect(error.name).toBe('AzureRateLimitError');
83
+ expect(error.endpoint).toBe('/users');
84
+ expect(error.retryAfter).toBe(60);
85
+ });
86
+ });
87
+
88
+ describe('AzureTimeoutError', () => {
89
+ it('should create timeout error', () => {
90
+ const error = new AzureTimeoutError('Timeout', 'GET /users', 30000);
91
+
92
+ expect(error).toBeInstanceOf(AzureError);
93
+ expect(error.name).toBe('AzureTimeoutError');
94
+ expect(error.operation).toBe('GET /users');
95
+ expect(error.timeoutMs).toBe(30000);
96
+ });
97
+ });
98
+
99
+ describe('AzurePermissionError', () => {
100
+ it('should create permission error with required permissions', () => {
101
+ const error = new AzurePermissionError(
102
+ 'Insufficient permissions',
103
+ '/users',
104
+ ['User.Read.All', 'Directory.Read.All']
105
+ );
106
+
107
+ expect(error).toBeInstanceOf(AzureError);
108
+ expect(error.name).toBe('AzurePermissionError');
109
+ expect(error.endpoint).toBe('/users');
110
+ expect(error.requiredPermissions).toEqual(['User.Read.All', 'Directory.Read.All']);
111
+ });
112
+ });
113
+
114
+ describe('AzureConfigurationError', () => {
115
+ it('should create configuration error', () => {
116
+ const error = new AzureConfigurationError('Missing tenant ID', 'tenantId');
117
+
118
+ expect(error).toBeInstanceOf(AzureError);
119
+ expect(error.name).toBe('AzureConfigurationError');
120
+ expect(error.configKey).toBe('tenantId');
121
+ });
122
+ });
123
+
124
+ describe('AzureTokenExpiredError', () => {
125
+ it('should create token expired error', () => {
126
+ const expiresAt = new Date('2026-01-13T00:00:00Z');
127
+ const error = new AzureTokenExpiredError('Token expired', expiresAt);
128
+
129
+ expect(error).toBeInstanceOf(AzureError);
130
+ expect(error.name).toBe('AzureTokenExpiredError');
131
+ expect(error.expiresAt).toEqual(expiresAt);
132
+ });
133
+ });
134
+
135
+ describe('isRetryableError', () => {
136
+ it('should identify rate limit errors as retryable', () => {
137
+ const error = new AzureRateLimitError('Rate limited', '/users', 60);
138
+ expect(isRetryableError(error)).toBe(true);
139
+ });
140
+
141
+ it('should identify timeout errors as retryable', () => {
142
+ const error = new AzureTimeoutError('Timeout', 'GET /users', 30000);
143
+ expect(isRetryableError(error)).toBe(true);
144
+ });
145
+
146
+ it('should identify 429 API errors as retryable', () => {
147
+ const error = new AzureAPIError('Too many requests', '/users', 429);
148
+ expect(isRetryableError(error)).toBe(true);
149
+ });
150
+
151
+ it('should identify 500 API errors as retryable', () => {
152
+ const error = new AzureAPIError('Server error', '/users', 500);
153
+ expect(isRetryableError(error)).toBe(true);
154
+ });
155
+
156
+ it('should identify 503 API errors as retryable', () => {
157
+ const error = new AzureAPIError('Service unavailable', '/users', 503);
158
+ expect(isRetryableError(error)).toBe(true);
159
+ });
160
+
161
+ it('should NOT identify 404 API errors as retryable', () => {
162
+ const error = new AzureAPIError('Not found', '/users', 404);
163
+ expect(isRetryableError(error)).toBe(false);
164
+ });
165
+
166
+ it('should NOT identify authentication errors as retryable', () => {
167
+ const error = new AzureAuthenticationError('Auth failed', 'tenant', 'client');
168
+ expect(isRetryableError(error)).toBe(false);
169
+ });
170
+
171
+ it('should NOT identify permission errors as retryable', () => {
172
+ const error = new AzurePermissionError('No access', '/users', ['User.Read.All']);
173
+ expect(isRetryableError(error)).toBe(false);
174
+ });
175
+
176
+ it('should identify network errors as retryable', () => {
177
+ const error = new Error('Network error') as Error & { code: string };
178
+ error.code = 'ECONNREFUSED';
179
+ expect(isRetryableError(error)).toBe(true);
180
+ });
181
+
182
+ it('should identify ETIMEDOUT errors as retryable', () => {
183
+ const error = new Error('Connection timed out') as Error & { code: string };
184
+ error.code = 'ETIMEDOUT';
185
+ expect(isRetryableError(error)).toBe(true);
186
+ });
187
+
188
+ it('should NOT identify unknown errors as retryable', () => {
189
+ const error = new Error('Unknown error');
190
+ expect(isRetryableError(error)).toBe(false);
191
+ });
192
+ });
193
+ });