@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,420 @@
1
+ import jwt from 'jsonwebtoken';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+ import { TokenRepository } from '../../data/repositories/token.repository';
4
+ import { CryptoService } from './crypto.service';
5
+ import type { Logger } from 'winston';
6
+ import { logger } from '../../utils/logger';
7
+ import {
8
+ TokenExpiredError,
9
+ TokenRevokedError,
10
+ UsageLimitExceededError,
11
+ TokenNotFoundError,
12
+ InvalidSignatureError,
13
+ InvalidTokenError,
14
+ } from './errors';
15
+
16
+ /**
17
+ * TokenService
18
+ *
19
+ * Manages JWT token lifecycle: generation, validation, revocation, and usage tracking.
20
+ *
21
+ * Features:
22
+ * - RS256 JWT signatures with RSA key pairs
23
+ * - Token usage quotas (max_uses)
24
+ * - Token revocation
25
+ * - Expiration management
26
+ * - Usage tracking
27
+ *
28
+ * Task 2: JWT Token Service (Story 1.4)
29
+ */
30
+
31
+ export interface GenerateTokenRequest {
32
+ expiresIn: string; // e.g., '1h', '7d', '30d'
33
+ maxUses: number; // 0 = unlimited
34
+ metadata?: Record<string, any>;
35
+ }
36
+
37
+ export interface TokenPayload {
38
+ jti: string; // JWT ID (unique identifier)
39
+ iss: string; // Issuer (always 'etc-collector')
40
+ sub: string; // Subject (always 'system')
41
+ iat: number; // Issued at (Unix timestamp)
42
+ exp: number; // Expiration (Unix timestamp)
43
+ service: string; // Service name (always 'etc-collector')
44
+ maxUses: number; // Maximum allowed uses
45
+ }
46
+
47
+ export interface TokenInfo {
48
+ jti: string;
49
+ created_at: string;
50
+ expires_at: string;
51
+ max_uses: number;
52
+ used_count: number;
53
+ remaining_uses: number; // Calculated
54
+ revoked: boolean;
55
+ revoked_at: string | null;
56
+ revoked_reason: string | null;
57
+ }
58
+
59
+ export class TokenService {
60
+ private logger: Logger;
61
+
62
+ constructor(
63
+ private tokenRepo: TokenRepository,
64
+ private cryptoService: CryptoService
65
+ ) {
66
+ this.logger = logger;
67
+ }
68
+
69
+ /**
70
+ * Generate a new JWT token with usage quotas
71
+ *
72
+ * Flow:
73
+ * 1. Generate unique jti (UUID v4)
74
+ * 2. Calculate expiration timestamp
75
+ * 3. Create JWT payload with claims
76
+ * 4. Sign token with RS256 private key
77
+ * 5. Save token to database
78
+ * 6. Return signed JWT string
79
+ *
80
+ * @param options Token generation options
81
+ * @returns Signed JWT token string
82
+ */
83
+ async generate(options: GenerateTokenRequest): Promise<string> {
84
+ // 1. Generate unique jti
85
+ const jti = uuidv4();
86
+
87
+ // 2. Calculate timestamps
88
+ const iat = Math.floor(Date.now() / 1000); // Unix timestamp (seconds)
89
+ const expirySeconds = this.parseExpiry(options.expiresIn);
90
+ const exp = iat + expirySeconds;
91
+
92
+ // 3. Create JWT payload
93
+ const payload: TokenPayload = {
94
+ jti,
95
+ iss: 'etc-collector',
96
+ sub: 'system',
97
+ iat,
98
+ exp,
99
+ service: 'etc-collector',
100
+ maxUses: options.maxUses,
101
+ };
102
+
103
+ // 4. Sign token with RS256 private key
104
+ const privateKey = this.cryptoService.getPrivateKey();
105
+ const token = jwt.sign(payload, privateKey, {
106
+ algorithm: 'RS256',
107
+ });
108
+
109
+ // 5. Save token to database
110
+ const publicKey = this.cryptoService.getPublicKey();
111
+ const expiresAt = new Date(exp * 1000).toISOString();
112
+
113
+ this.tokenRepo.create({
114
+ jti,
115
+ public_key: publicKey,
116
+ expires_at: expiresAt,
117
+ max_uses: options.maxUses,
118
+ metadata: options.metadata ? JSON.stringify(options.metadata) : undefined,
119
+ });
120
+
121
+ // 6. Log token generation
122
+ this.logger.info('JWT token generated', {
123
+ jti,
124
+ expiresIn: options.expiresIn,
125
+ expiresAt,
126
+ maxUses: options.maxUses,
127
+ });
128
+
129
+ return token;
130
+ }
131
+
132
+ /**
133
+ * Validate JWT token and check revocation/usage
134
+ *
135
+ * Flow:
136
+ * 1. Verify JWT signature with RS256 public key
137
+ * 2. Check token expiration (exp claim)
138
+ * 3. Check token issuer (iss claim)
139
+ * 4. Query database for token (by jti)
140
+ * 5. Check if token is revoked
141
+ * 6. Check usage quota (used_count vs max_uses)
142
+ * 7. Return decoded payload if valid
143
+ *
144
+ * @param token JWT token string
145
+ * @returns Decoded token payload
146
+ * @throws TokenExpiredError if token expired
147
+ * @throws TokenRevokedError if token revoked
148
+ * @throws UsageLimitExceededError if usage quota exceeded
149
+ * @throws TokenNotFoundError if jti not in database
150
+ * @throws InvalidSignatureError if JWT verification fails
151
+ * @throws InvalidTokenError if token format invalid
152
+ */
153
+ async validate(token: string): Promise<TokenPayload> {
154
+ let decoded: TokenPayload;
155
+
156
+ try {
157
+ // 1. Verify JWT signature with RS256 public key
158
+ const publicKey = this.cryptoService.getPublicKey();
159
+ decoded = jwt.verify(token, publicKey, {
160
+ algorithms: ['RS256'],
161
+ }) as TokenPayload;
162
+ } catch (error) {
163
+ if (error instanceof jwt.TokenExpiredError) {
164
+ this.logger.warn('Token validation failed: expired');
165
+ throw new TokenExpiredError();
166
+ }
167
+ if (error instanceof jwt.JsonWebTokenError) {
168
+ this.logger.warn('Token validation failed: invalid signature', {
169
+ error: error.message,
170
+ });
171
+ throw new InvalidSignatureError();
172
+ }
173
+ this.logger.error('Token validation failed: unknown error', {
174
+ error: error instanceof Error ? error.message : 'Unknown error',
175
+ });
176
+ throw new InvalidTokenError('Token validation failed');
177
+ }
178
+
179
+ // 2. Check token expiration (redundant with jwt.verify, but explicit)
180
+ const now = Math.floor(Date.now() / 1000);
181
+ if (decoded.exp < now) {
182
+ this.logger.warn('Token expired', { jti: decoded.jti, exp: decoded.exp, now });
183
+ throw new TokenExpiredError();
184
+ }
185
+
186
+ // 3. Check token issuer
187
+ if (decoded.iss !== 'etc-collector') {
188
+ this.logger.warn('Token validation failed: invalid issuer', {
189
+ jti: decoded.jti,
190
+ iss: decoded.iss,
191
+ });
192
+ throw new InvalidTokenError('Invalid token issuer');
193
+ }
194
+
195
+ // 4. Query database for token
196
+ const tokenRecord = this.tokenRepo.findByJti(decoded.jti);
197
+ if (!tokenRecord) {
198
+ this.logger.warn('Token validation failed: not found in database', {
199
+ jti: decoded.jti,
200
+ });
201
+ throw new TokenNotFoundError();
202
+ }
203
+
204
+ // 5. Check if token is revoked
205
+ if (tokenRecord.revoked_at) {
206
+ this.logger.warn('Token validation failed: revoked', {
207
+ jti: decoded.jti,
208
+ revokedAt: tokenRecord.revoked_at,
209
+ revokedBy: tokenRecord.revoked_by,
210
+ revokedReason: tokenRecord.revoked_reason,
211
+ });
212
+ throw new TokenRevokedError();
213
+ }
214
+
215
+ // 6. Check usage quota (0 = unlimited)
216
+ if (tokenRecord.max_uses > 0 && tokenRecord.used_count >= tokenRecord.max_uses) {
217
+ this.logger.warn('Token validation failed: usage limit exceeded', {
218
+ jti: decoded.jti,
219
+ usedCount: tokenRecord.used_count,
220
+ maxUses: tokenRecord.max_uses,
221
+ });
222
+ throw new UsageLimitExceededError();
223
+ }
224
+
225
+ // 7. Return decoded payload
226
+ this.logger.debug('Token validated successfully', { jti: decoded.jti });
227
+ return decoded;
228
+ }
229
+
230
+ /**
231
+ * Revoke a token by jti
232
+ *
233
+ * Flow:
234
+ * 1. Find token in database
235
+ * 2. Check if already revoked
236
+ * 3. Mark as revoked
237
+ * 4. Log revocation
238
+ *
239
+ * @param jti JWT ID
240
+ * @param revokedBy Username or system identifier
241
+ * @param reason Revocation reason
242
+ * @throws TokenNotFoundError if jti not in database
243
+ */
244
+ async revoke(jti: string, revokedBy: string, reason: string): Promise<void> {
245
+ // 1. Find token in database
246
+ const tokenRecord = this.tokenRepo.findByJti(jti);
247
+ if (!tokenRecord) {
248
+ this.logger.warn('Token revocation failed: not found', { jti });
249
+ throw new TokenNotFoundError();
250
+ }
251
+
252
+ // 2. Check if already revoked
253
+ if (tokenRecord.revoked_at) {
254
+ this.logger.warn('Token already revoked', {
255
+ jti,
256
+ revokedAt: tokenRecord.revoked_at,
257
+ revokedBy: tokenRecord.revoked_by,
258
+ });
259
+ return; // Idempotent operation
260
+ }
261
+
262
+ // 3. Mark as revoked
263
+ this.tokenRepo.revoke(jti, revokedBy, reason);
264
+
265
+ // 4. Log revocation
266
+ this.logger.info('Token revoked', {
267
+ jti,
268
+ revokedBy,
269
+ reason,
270
+ });
271
+ }
272
+
273
+ /**
274
+ * Get token information by jti
275
+ *
276
+ * Flow:
277
+ * 1. Find token in database
278
+ * 2. Calculate remaining_uses
279
+ * 3. Format response
280
+ * 4. Return token info
281
+ *
282
+ * @param jti JWT ID
283
+ * @returns Token information
284
+ * @throws TokenNotFoundError if jti not in database
285
+ */
286
+ async getInfo(jti: string): Promise<TokenInfo> {
287
+ // 1. Find token in database
288
+ const tokenRecord = this.tokenRepo.findByJti(jti);
289
+ if (!tokenRecord) {
290
+ this.logger.warn('Token info request failed: not found', { jti });
291
+ throw new TokenNotFoundError();
292
+ }
293
+
294
+ // 2. Calculate remaining_uses
295
+ const remainingUses =
296
+ tokenRecord.max_uses === 0
297
+ ? -1 // Unlimited
298
+ : Math.max(0, tokenRecord.max_uses - tokenRecord.used_count);
299
+
300
+ // 3. Format response
301
+ const info: TokenInfo = {
302
+ jti: tokenRecord.jti,
303
+ created_at: tokenRecord.created_at,
304
+ expires_at: tokenRecord.expires_at,
305
+ max_uses: tokenRecord.max_uses,
306
+ used_count: tokenRecord.used_count,
307
+ remaining_uses: remainingUses,
308
+ revoked: !!tokenRecord.revoked_at,
309
+ revoked_at: tokenRecord.revoked_at || null,
310
+ revoked_reason: tokenRecord.revoked_reason || null,
311
+ };
312
+
313
+ // 4. Return token info
314
+ return info;
315
+ }
316
+
317
+ /**
318
+ * Increment token usage count
319
+ *
320
+ * Flow:
321
+ * 1. Increment used_count in database
322
+ * 2. Log usage increment
323
+ *
324
+ * @param jti JWT ID
325
+ */
326
+ async incrementUsage(jti: string): Promise<void> {
327
+ // 1. Increment used_count
328
+ this.tokenRepo.incrementUsage(jti);
329
+
330
+ // 2. Log usage increment
331
+ this.logger.debug('Token usage incremented', { jti });
332
+ }
333
+
334
+ /**
335
+ * List all tokens (including expired and revoked)
336
+ *
337
+ * Flow:
338
+ * 1. Get all tokens from database
339
+ * 2. Map to TokenInfo format
340
+ * 3. Return array of token info
341
+ *
342
+ * @returns Array of token information
343
+ */
344
+ async listAll(): Promise<TokenInfo[]> {
345
+ // 1. Get all tokens
346
+ const tokens = this.tokenRepo.findAll();
347
+
348
+ // 2. Map to TokenInfo format
349
+ const tokenInfoList: TokenInfo[] = tokens.map((token) => {
350
+ const remainingUses =
351
+ token.max_uses === 0
352
+ ? -1 // Unlimited
353
+ : Math.max(0, token.max_uses - token.used_count);
354
+
355
+ return {
356
+ jti: token.jti,
357
+ created_at: token.created_at,
358
+ expires_at: token.expires_at,
359
+ max_uses: token.max_uses,
360
+ used_count: token.used_count,
361
+ remaining_uses: remainingUses,
362
+ revoked: !!token.revoked_at,
363
+ revoked_at: token.revoked_at || null,
364
+ revoked_reason: token.revoked_reason || null,
365
+ };
366
+ });
367
+
368
+ // 3. Return array
369
+ return tokenInfoList;
370
+ }
371
+
372
+ /**
373
+ * Parse expiry string to seconds
374
+ *
375
+ * Supports:
376
+ * - s: seconds
377
+ * - m: minutes
378
+ * - h: hours
379
+ * - d: days
380
+ *
381
+ * Examples:
382
+ * - '60s' → 60
383
+ * - '30m' → 1800
384
+ * - '1h' → 3600
385
+ * - '7d' → 604800
386
+ * - '30d' → 2592000
387
+ *
388
+ * @param expiresIn Human-readable duration string
389
+ * @returns Duration in seconds
390
+ * @throws Error if format is invalid
391
+ */
392
+ private parseExpiry(expiresIn: string): number {
393
+ const match = expiresIn.match(/^(\d+)([smhd])$/);
394
+ if (!match || !match[1] || !match[2]) {
395
+ throw new Error(
396
+ `Invalid expiry format: ${expiresIn}. Expected format: <number><unit> (e.g., '1h', '7d')`
397
+ );
398
+ }
399
+
400
+ const value = parseInt(match[1], 10);
401
+ const unit = match[2];
402
+
403
+ const multipliers: Record<string, number> = {
404
+ s: 1,
405
+ m: 60,
406
+ h: 3600,
407
+ d: 86400,
408
+ };
409
+
410
+ const multiplier = multipliers[unit];
411
+ if (multiplier === undefined) {
412
+ throw new Error(`Invalid time unit: ${unit}`);
413
+ }
414
+
415
+ const seconds = value * multiplier;
416
+
417
+ this.logger.debug('Parsed expiry', { expiresIn, seconds });
418
+ return seconds;
419
+ }
420
+ }
File without changes
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Configuration Service
3
+ * Manages application configuration
4
+ */
5
+
6
+ import { ConfigSchema } from '../../config/config.schema';
7
+ import { AppConfig } from '../../types/config.types';
8
+
9
+ /**
10
+ * Load and validate application configuration
11
+ *
12
+ * @returns Promise<AppConfig> Validated configuration
13
+ */
14
+ export async function loadConfig(): Promise<AppConfig> {
15
+ // Load from environment variables
16
+ const rawConfig = {
17
+ server: {
18
+ port: process.env['PORT'] || 8443,
19
+ nodeEnv: process.env['NODE_ENV'] || 'production',
20
+ },
21
+ infoEndpoints: {
22
+ tokenInfoEnabled: process.env['TOKEN_INFO_ENABLED'],
23
+ providersInfoEnabled: process.env['PROVIDERS_INFO_ENABLED'],
24
+ },
25
+ jwt: {
26
+ privateKeyPath: process.env['JWT_PRIVATE_KEY_PATH'] || './keys/private.pem',
27
+ publicKeyPath: process.env['JWT_PUBLIC_KEY_PATH'] || './keys/public.pem',
28
+ tokenExpiry: process.env['TOKEN_EXPIRY'] || '1h',
29
+ tokenMaxUses: process.env['TOKEN_MAX_USES'] || 10,
30
+ },
31
+ ldap: {
32
+ url: process.env['LDAP_URL'] || '',
33
+ bindDN: process.env['LDAP_BIND_DN'] || '',
34
+ bindPassword: process.env['LDAP_BIND_PASSWORD'] || '',
35
+ baseDN: process.env['LDAP_BASE_DN'] || '',
36
+ tlsVerify: process.env['LDAP_TLS_VERIFY'] !== 'false',
37
+ caCertPath: process.env['LDAP_CA_CERT_PATH'],
38
+ timeout: process.env['LDAP_TIMEOUT'] || 30000,
39
+ skipHostnameVerification: process.env['LDAP_SKIP_HOSTNAME_VERIFICATION'],
40
+ tlsServername: process.env['LDAP_TLS_SERVERNAME'],
41
+ },
42
+ azure: {
43
+ enabled: process.env['AZURE_ENABLED'],
44
+ tenantId: process.env['AZURE_TENANT_ID'],
45
+ clientId: process.env['AZURE_CLIENT_ID'],
46
+ clientSecret: process.env['AZURE_CLIENT_SECRET'],
47
+ },
48
+ smb: {
49
+ enabled: process.env['SMB_ENABLED'],
50
+ username: process.env['SMB_USERNAME'],
51
+ password: process.env['SMB_PASSWORD'],
52
+ timeout: process.env['SMB_TIMEOUT'] || 10000,
53
+ },
54
+ logging: {
55
+ level: process.env['LOG_LEVEL'] || 'info',
56
+ format: process.env['LOG_FORMAT'] || 'json',
57
+ },
58
+ database: {
59
+ path: process.env['DATABASE_PATH'] || './data/etc-collector.db',
60
+ enableWAL: process.env['DATABASE_ENABLE_WAL'] !== 'false',
61
+ busyTimeout: process.env['DATABASE_BUSY_TIMEOUT'] || 5000,
62
+ },
63
+ };
64
+
65
+ // Validate with Zod schema
66
+ const config = ConfigSchema.parse(rawConfig);
67
+
68
+ return config as AppConfig;
69
+ }
70
+
71
+ export class ConfigService {
72
+ getConfig(): unknown {
73
+ throw new Error('Config service not implemented yet');
74
+ }
75
+ }
File without changes
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Export Service
3
+ *
4
+ * Orchestrates audit result export to JSON and CSV formats.
5
+ * Story 1.9: Export Service
6
+ *
7
+ * Features:
8
+ * - JSON export with full audit structure
9
+ * - CSV export with flat table structure
10
+ * - Content-Disposition headers for file downloads
11
+ * - Excel-compatible CSV (UTF-8 with BOM)
12
+ */
13
+
14
+ import { Finding } from '../../types/finding.types';
15
+ import { SecurityScore } from '../audit/scoring.service';
16
+ import { formatAsJSON, getJSONContentDisposition, JSONExportOptions } from './formatters/json.formatter';
17
+ import { formatAsCSV, getCSVContentDisposition, CSVExportOptions } from './formatters/csv.formatter';
18
+
19
+ /**
20
+ * Audit result for export
21
+ */
22
+ export interface ExportAuditResult {
23
+ score: SecurityScore;
24
+ findings: Finding[];
25
+ stats: {
26
+ totalUsers?: number;
27
+ totalGroups?: number;
28
+ totalComputers?: number;
29
+ totalApps?: number;
30
+ totalPolicies?: number;
31
+ totalFindings: number;
32
+ executionTimeMs: number;
33
+ };
34
+ timestamp: Date;
35
+ }
36
+
37
+ /**
38
+ * Export result with content and headers
39
+ */
40
+ export interface ExportResult {
41
+ content: string;
42
+ contentType: string;
43
+ contentDisposition: string;
44
+ }
45
+
46
+ /**
47
+ * Export Service
48
+ */
49
+ export class ExportService {
50
+ /**
51
+ * Export audit result as JSON
52
+ *
53
+ * @param auditResult Audit result
54
+ * @param options JSON export options
55
+ * @returns Export result with JSON content and headers
56
+ */
57
+ exportToJSON(auditResult: ExportAuditResult, options: JSONExportOptions): ExportResult {
58
+ // Format as JSON
59
+ const content = formatAsJSON(auditResult.score, auditResult.findings, auditResult.stats, options);
60
+
61
+ // Generate Content-Disposition header
62
+ const domain = options.domain || options.tenantId || 'unknown';
63
+ const contentDisposition = getJSONContentDisposition(options.provider, domain);
64
+
65
+ return {
66
+ content,
67
+ contentType: 'application/json; charset=utf-8',
68
+ contentDisposition,
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Export audit result as CSV
74
+ *
75
+ * @param auditResult Audit result
76
+ * @param provider Provider type (ad or azure)
77
+ * @param domain Domain name or tenant ID
78
+ * @param options CSV export options
79
+ * @returns Export result with CSV content and headers
80
+ */
81
+ exportToCSV(
82
+ auditResult: ExportAuditResult,
83
+ provider: string,
84
+ domain: string,
85
+ options: CSVExportOptions = {}
86
+ ): ExportResult {
87
+ // Format as CSV
88
+ const content = formatAsCSV(auditResult.findings, options);
89
+
90
+ // Generate Content-Disposition header
91
+ const contentDisposition = getCSVContentDisposition(provider, domain);
92
+
93
+ return {
94
+ content,
95
+ contentType: 'text/csv; charset=utf-8',
96
+ contentDisposition,
97
+ };
98
+ }
99
+ }