@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.
- package/.env.example +60 -0
- package/.env.test.example +33 -0
- package/.github/workflows/ci.yml +83 -0
- package/.github/workflows/release.yml +246 -0
- package/.prettierrc.json +10 -0
- package/CHANGELOG.md +15 -0
- package/Dockerfile +57 -0
- package/LICENSE +190 -0
- package/README.md +194 -0
- package/dist/api/controllers/audit.controller.d.ts +21 -0
- package/dist/api/controllers/audit.controller.d.ts.map +1 -0
- package/dist/api/controllers/audit.controller.js +179 -0
- package/dist/api/controllers/audit.controller.js.map +1 -0
- package/dist/api/controllers/auth.controller.d.ts +16 -0
- package/dist/api/controllers/auth.controller.d.ts.map +1 -0
- package/dist/api/controllers/auth.controller.js +146 -0
- package/dist/api/controllers/auth.controller.js.map +1 -0
- package/dist/api/controllers/export.controller.d.ts +27 -0
- package/dist/api/controllers/export.controller.d.ts.map +1 -0
- package/dist/api/controllers/export.controller.js +80 -0
- package/dist/api/controllers/export.controller.js.map +1 -0
- package/dist/api/controllers/health.controller.d.ts +5 -0
- package/dist/api/controllers/health.controller.d.ts.map +1 -0
- package/dist/api/controllers/health.controller.js +16 -0
- package/dist/api/controllers/health.controller.js.map +1 -0
- package/dist/api/controllers/jobs.controller.d.ts +13 -0
- package/dist/api/controllers/jobs.controller.d.ts.map +1 -0
- package/dist/api/controllers/jobs.controller.js +125 -0
- package/dist/api/controllers/jobs.controller.js.map +1 -0
- package/dist/api/controllers/providers.controller.d.ts +15 -0
- package/dist/api/controllers/providers.controller.d.ts.map +1 -0
- package/dist/api/controllers/providers.controller.js +112 -0
- package/dist/api/controllers/providers.controller.js.map +1 -0
- package/dist/api/dto/AuditRequest.dto.d.ts +6 -0
- package/dist/api/dto/AuditRequest.dto.d.ts.map +1 -0
- package/dist/api/dto/AuditRequest.dto.js +3 -0
- package/dist/api/dto/AuditRequest.dto.js.map +1 -0
- package/dist/api/dto/AuditResponse.dto.d.ts +17 -0
- package/dist/api/dto/AuditResponse.dto.d.ts.map +1 -0
- package/dist/api/dto/AuditResponse.dto.js +3 -0
- package/dist/api/dto/AuditResponse.dto.js.map +1 -0
- package/dist/api/dto/TokenRequest.dto.d.ts +6 -0
- package/dist/api/dto/TokenRequest.dto.d.ts.map +1 -0
- package/dist/api/dto/TokenRequest.dto.js +3 -0
- package/dist/api/dto/TokenRequest.dto.js.map +1 -0
- package/dist/api/dto/TokenResponse.dto.d.ts +12 -0
- package/dist/api/dto/TokenResponse.dto.d.ts.map +1 -0
- package/dist/api/dto/TokenResponse.dto.js +3 -0
- package/dist/api/dto/TokenResponse.dto.js.map +1 -0
- package/dist/api/middlewares/authenticate.d.ts +12 -0
- package/dist/api/middlewares/authenticate.d.ts.map +1 -0
- package/dist/api/middlewares/authenticate.js +141 -0
- package/dist/api/middlewares/authenticate.js.map +1 -0
- package/dist/api/middlewares/errorHandler.d.ts +3 -0
- package/dist/api/middlewares/errorHandler.d.ts.map +1 -0
- package/dist/api/middlewares/errorHandler.js +30 -0
- package/dist/api/middlewares/errorHandler.js.map +1 -0
- package/dist/api/middlewares/rateLimit.d.ts +3 -0
- package/dist/api/middlewares/rateLimit.d.ts.map +1 -0
- package/dist/api/middlewares/rateLimit.js +34 -0
- package/dist/api/middlewares/rateLimit.js.map +1 -0
- package/dist/api/middlewares/validate.d.ts +4 -0
- package/dist/api/middlewares/validate.d.ts.map +1 -0
- package/dist/api/middlewares/validate.js +31 -0
- package/dist/api/middlewares/validate.js.map +1 -0
- package/dist/api/routes/audit.routes.d.ts +5 -0
- package/dist/api/routes/audit.routes.d.ts.map +1 -0
- package/dist/api/routes/audit.routes.js +24 -0
- package/dist/api/routes/audit.routes.js.map +1 -0
- package/dist/api/routes/auth.routes.d.ts +6 -0
- package/dist/api/routes/auth.routes.d.ts.map +1 -0
- package/dist/api/routes/auth.routes.js +22 -0
- package/dist/api/routes/auth.routes.js.map +1 -0
- package/dist/api/routes/export.routes.d.ts +5 -0
- package/dist/api/routes/export.routes.d.ts.map +1 -0
- package/dist/api/routes/export.routes.js +16 -0
- package/dist/api/routes/export.routes.js.map +1 -0
- package/dist/api/routes/health.routes.d.ts +4 -0
- package/dist/api/routes/health.routes.d.ts.map +1 -0
- package/dist/api/routes/health.routes.js +11 -0
- package/dist/api/routes/health.routes.js.map +1 -0
- package/dist/api/routes/index.d.ts +10 -0
- package/dist/api/routes/index.d.ts.map +1 -0
- package/dist/api/routes/index.js +20 -0
- package/dist/api/routes/index.js.map +1 -0
- package/dist/api/routes/providers.routes.d.ts +5 -0
- package/dist/api/routes/providers.routes.d.ts.map +1 -0
- package/dist/api/routes/providers.routes.js +13 -0
- package/dist/api/routes/providers.routes.js.map +1 -0
- package/dist/api/validators/audit.schemas.d.ts +60 -0
- package/dist/api/validators/audit.schemas.d.ts.map +1 -0
- package/dist/api/validators/audit.schemas.js +55 -0
- package/dist/api/validators/audit.schemas.js.map +1 -0
- package/dist/api/validators/auth.schemas.d.ts +17 -0
- package/dist/api/validators/auth.schemas.d.ts.map +1 -0
- package/dist/api/validators/auth.schemas.js +21 -0
- package/dist/api/validators/auth.schemas.js.map +1 -0
- package/dist/app.d.ts +3 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +62 -0
- package/dist/app.js.map +1 -0
- package/dist/config/config.schema.d.ts +65 -0
- package/dist/config/config.schema.d.ts.map +1 -0
- package/dist/config/config.schema.js +95 -0
- package/dist/config/config.schema.js.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +75 -0
- package/dist/config/index.js.map +1 -0
- package/dist/container.d.ts +47 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +137 -0
- package/dist/container.js.map +1 -0
- package/dist/data/database.d.ts +13 -0
- package/dist/data/database.d.ts.map +1 -0
- package/dist/data/database.js +68 -0
- package/dist/data/database.js.map +1 -0
- package/dist/data/jobs/token-cleanup.job.d.ts +23 -0
- package/dist/data/jobs/token-cleanup.job.d.ts.map +1 -0
- package/dist/data/jobs/token-cleanup.job.js +96 -0
- package/dist/data/jobs/token-cleanup.job.js.map +1 -0
- package/dist/data/migrations/migration.runner.d.ts +13 -0
- package/dist/data/migrations/migration.runner.d.ts.map +1 -0
- package/dist/data/migrations/migration.runner.js +136 -0
- package/dist/data/migrations/migration.runner.js.map +1 -0
- package/dist/data/models/Token.model.d.ts +30 -0
- package/dist/data/models/Token.model.d.ts.map +1 -0
- package/dist/data/models/Token.model.js +3 -0
- package/dist/data/models/Token.model.js.map +1 -0
- package/dist/data/repositories/token.repository.d.ts +16 -0
- package/dist/data/repositories/token.repository.d.ts.map +1 -0
- package/dist/data/repositories/token.repository.js +97 -0
- package/dist/data/repositories/token.repository.js.map +1 -0
- package/dist/providers/azure/auth.provider.d.ts +5 -0
- package/dist/providers/azure/auth.provider.d.ts.map +1 -0
- package/dist/providers/azure/auth.provider.js +13 -0
- package/dist/providers/azure/auth.provider.js.map +1 -0
- package/dist/providers/azure/azure-errors.d.ts +40 -0
- package/dist/providers/azure/azure-errors.d.ts.map +1 -0
- package/dist/providers/azure/azure-errors.js +121 -0
- package/dist/providers/azure/azure-errors.js.map +1 -0
- package/dist/providers/azure/azure-retry.d.ts +41 -0
- package/dist/providers/azure/azure-retry.d.ts.map +1 -0
- package/dist/providers/azure/azure-retry.js +85 -0
- package/dist/providers/azure/azure-retry.js.map +1 -0
- package/dist/providers/azure/graph-client.d.ts +26 -0
- package/dist/providers/azure/graph-client.d.ts.map +1 -0
- package/dist/providers/azure/graph-client.js +146 -0
- package/dist/providers/azure/graph-client.js.map +1 -0
- package/dist/providers/azure/graph.provider.d.ts +23 -0
- package/dist/providers/azure/graph.provider.d.ts.map +1 -0
- package/dist/providers/azure/graph.provider.js +161 -0
- package/dist/providers/azure/graph.provider.js.map +1 -0
- package/dist/providers/azure/queries/app.queries.d.ts +6 -0
- package/dist/providers/azure/queries/app.queries.d.ts.map +1 -0
- package/dist/providers/azure/queries/app.queries.js +9 -0
- package/dist/providers/azure/queries/app.queries.js.map +1 -0
- package/dist/providers/azure/queries/policy.queries.d.ts +6 -0
- package/dist/providers/azure/queries/policy.queries.d.ts.map +1 -0
- package/dist/providers/azure/queries/policy.queries.js +9 -0
- package/dist/providers/azure/queries/policy.queries.js.map +1 -0
- package/dist/providers/azure/queries/user.queries.d.ts +7 -0
- package/dist/providers/azure/queries/user.queries.d.ts.map +1 -0
- package/dist/providers/azure/queries/user.queries.js +10 -0
- package/dist/providers/azure/queries/user.queries.js.map +1 -0
- package/dist/providers/interfaces/IGraphProvider.d.ts +31 -0
- package/dist/providers/interfaces/IGraphProvider.d.ts.map +1 -0
- package/dist/providers/interfaces/IGraphProvider.js +3 -0
- package/dist/providers/interfaces/IGraphProvider.js.map +1 -0
- package/dist/providers/interfaces/ILDAPProvider.d.ts +37 -0
- package/dist/providers/interfaces/ILDAPProvider.d.ts.map +1 -0
- package/dist/providers/interfaces/ILDAPProvider.js +3 -0
- package/dist/providers/interfaces/ILDAPProvider.js.map +1 -0
- package/dist/providers/ldap/acl-parser.d.ts +8 -0
- package/dist/providers/ldap/acl-parser.d.ts.map +1 -0
- package/dist/providers/ldap/acl-parser.js +157 -0
- package/dist/providers/ldap/acl-parser.js.map +1 -0
- package/dist/providers/ldap/ad-mappers.d.ts +8 -0
- package/dist/providers/ldap/ad-mappers.d.ts.map +1 -0
- package/dist/providers/ldap/ad-mappers.js +162 -0
- package/dist/providers/ldap/ad-mappers.js.map +1 -0
- package/dist/providers/ldap/ldap-client.d.ts +33 -0
- package/dist/providers/ldap/ldap-client.d.ts.map +1 -0
- package/dist/providers/ldap/ldap-client.js +195 -0
- package/dist/providers/ldap/ldap-client.js.map +1 -0
- package/dist/providers/ldap/ldap-errors.d.ts +48 -0
- package/dist/providers/ldap/ldap-errors.d.ts.map +1 -0
- package/dist/providers/ldap/ldap-errors.js +120 -0
- package/dist/providers/ldap/ldap-errors.js.map +1 -0
- package/dist/providers/ldap/ldap-retry.d.ts +14 -0
- package/dist/providers/ldap/ldap-retry.d.ts.map +1 -0
- package/dist/providers/ldap/ldap-retry.js +102 -0
- package/dist/providers/ldap/ldap-retry.js.map +1 -0
- package/dist/providers/ldap/ldap-sanitizer.d.ts +12 -0
- package/dist/providers/ldap/ldap-sanitizer.d.ts.map +1 -0
- package/dist/providers/ldap/ldap-sanitizer.js +104 -0
- package/dist/providers/ldap/ldap-sanitizer.js.map +1 -0
- package/dist/providers/ldap/ldap.provider.d.ts +21 -0
- package/dist/providers/ldap/ldap.provider.d.ts.map +1 -0
- package/dist/providers/ldap/ldap.provider.js +165 -0
- package/dist/providers/ldap/ldap.provider.js.map +1 -0
- package/dist/providers/ldap/queries/computer.queries.d.ts +6 -0
- package/dist/providers/ldap/queries/computer.queries.d.ts.map +1 -0
- package/dist/providers/ldap/queries/computer.queries.js +9 -0
- package/dist/providers/ldap/queries/computer.queries.js.map +1 -0
- package/dist/providers/ldap/queries/group.queries.d.ts +6 -0
- package/dist/providers/ldap/queries/group.queries.d.ts.map +1 -0
- package/dist/providers/ldap/queries/group.queries.js +9 -0
- package/dist/providers/ldap/queries/group.queries.js.map +1 -0
- package/dist/providers/ldap/queries/user.queries.d.ts +7 -0
- package/dist/providers/ldap/queries/user.queries.d.ts.map +1 -0
- package/dist/providers/ldap/queries/user.queries.js +10 -0
- package/dist/providers/ldap/queries/user.queries.js.map +1 -0
- package/dist/providers/smb/smb.provider.d.ts +68 -0
- package/dist/providers/smb/smb.provider.d.ts.map +1 -0
- package/dist/providers/smb/smb.provider.js +382 -0
- package/dist/providers/smb/smb.provider.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +44 -0
- package/dist/server.js.map +1 -0
- package/dist/services/audit/ad-audit.service.d.ts +70 -0
- package/dist/services/audit/ad-audit.service.d.ts.map +1 -0
- package/dist/services/audit/ad-audit.service.js +1019 -0
- package/dist/services/audit/ad-audit.service.js.map +1 -0
- package/dist/services/audit/attack-graph.service.d.ts +62 -0
- package/dist/services/audit/attack-graph.service.d.ts.map +1 -0
- package/dist/services/audit/attack-graph.service.js +702 -0
- package/dist/services/audit/attack-graph.service.js.map +1 -0
- package/dist/services/audit/audit.service.d.ts +4 -0
- package/dist/services/audit/audit.service.d.ts.map +1 -0
- package/dist/services/audit/audit.service.js +10 -0
- package/dist/services/audit/audit.service.js.map +1 -0
- package/dist/services/audit/azure-audit.service.d.ts +37 -0
- package/dist/services/audit/azure-audit.service.d.ts.map +1 -0
- package/dist/services/audit/azure-audit.service.js +153 -0
- package/dist/services/audit/azure-audit.service.js.map +1 -0
- package/dist/services/audit/detectors/ad/accounts.detector.d.ts +37 -0
- package/dist/services/audit/detectors/ad/accounts.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/accounts.detector.js +881 -0
- package/dist/services/audit/detectors/ad/accounts.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/adcs.detector.d.ts +21 -0
- package/dist/services/audit/detectors/ad/adcs.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/adcs.detector.js +227 -0
- package/dist/services/audit/detectors/ad/adcs.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/advanced.detector.d.ts +63 -0
- package/dist/services/audit/detectors/ad/advanced.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/advanced.detector.js +867 -0
- package/dist/services/audit/detectors/ad/advanced.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/attack-paths.detector.d.ts +16 -0
- package/dist/services/audit/detectors/ad/attack-paths.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/attack-paths.detector.js +369 -0
- package/dist/services/audit/detectors/ad/attack-paths.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/compliance.detector.d.ts +28 -0
- package/dist/services/audit/detectors/ad/compliance.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/compliance.detector.js +896 -0
- package/dist/services/audit/detectors/ad/compliance.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/computers.detector.d.ts +30 -0
- package/dist/services/audit/detectors/ad/computers.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/computers.detector.js +799 -0
- package/dist/services/audit/detectors/ad/computers.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/gpo.detector.d.ts +17 -0
- package/dist/services/audit/detectors/ad/gpo.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/gpo.detector.js +257 -0
- package/dist/services/audit/detectors/ad/gpo.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/groups.detector.d.ts +19 -0
- package/dist/services/audit/detectors/ad/groups.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/groups.detector.js +488 -0
- package/dist/services/audit/detectors/ad/groups.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/index.d.ts +15 -0
- package/dist/services/audit/detectors/ad/index.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/index.js +51 -0
- package/dist/services/audit/detectors/ad/index.js.map +1 -0
- package/dist/services/audit/detectors/ad/kerberos.detector.d.ts +17 -0
- package/dist/services/audit/detectors/ad/kerberos.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/kerberos.detector.js +293 -0
- package/dist/services/audit/detectors/ad/kerberos.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/monitoring.detector.d.ts +23 -0
- package/dist/services/audit/detectors/ad/monitoring.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/monitoring.detector.js +328 -0
- package/dist/services/audit/detectors/ad/monitoring.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/network.detector.d.ts +39 -0
- package/dist/services/audit/detectors/ad/network.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/network.detector.js +257 -0
- package/dist/services/audit/detectors/ad/network.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/password.detector.d.ts +14 -0
- package/dist/services/audit/detectors/ad/password.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/password.detector.js +235 -0
- package/dist/services/audit/detectors/ad/password.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/permissions.detector.d.ts +20 -0
- package/dist/services/audit/detectors/ad/permissions.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/permissions.detector.js +392 -0
- package/dist/services/audit/detectors/ad/permissions.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/trusts.detector.d.ts +11 -0
- package/dist/services/audit/detectors/ad/trusts.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/trusts.detector.js +186 -0
- package/dist/services/audit/detectors/ad/trusts.detector.js.map +1 -0
- package/dist/services/audit/detectors/azure/app-security.detector.d.ts +11 -0
- package/dist/services/audit/detectors/azure/app-security.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/azure/app-security.detector.js +184 -0
- package/dist/services/audit/detectors/azure/app-security.detector.js.map +1 -0
- package/dist/services/audit/detectors/azure/conditional-access.detector.d.ts +10 -0
- package/dist/services/audit/detectors/azure/conditional-access.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/azure/conditional-access.detector.js +130 -0
- package/dist/services/audit/detectors/azure/conditional-access.detector.js.map +1 -0
- package/dist/services/audit/detectors/azure/privilege-security.detector.d.ts +8 -0
- package/dist/services/audit/detectors/azure/privilege-security.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/azure/privilege-security.detector.js +113 -0
- package/dist/services/audit/detectors/azure/privilege-security.detector.js.map +1 -0
- package/dist/services/audit/detectors/azure/user-security.detector.d.ts +14 -0
- package/dist/services/audit/detectors/azure/user-security.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/azure/user-security.detector.js +198 -0
- package/dist/services/audit/detectors/azure/user-security.detector.js.map +1 -0
- package/dist/services/audit/detectors/index.d.ts +2 -0
- package/dist/services/audit/detectors/index.d.ts.map +1 -0
- package/dist/services/audit/detectors/index.js +38 -0
- package/dist/services/audit/detectors/index.js.map +1 -0
- package/dist/services/audit/response-formatter.d.ts +176 -0
- package/dist/services/audit/response-formatter.d.ts.map +1 -0
- package/dist/services/audit/response-formatter.js +240 -0
- package/dist/services/audit/response-formatter.js.map +1 -0
- package/dist/services/audit/scoring.service.d.ts +15 -0
- package/dist/services/audit/scoring.service.d.ts.map +1 -0
- package/dist/services/audit/scoring.service.js +139 -0
- package/dist/services/audit/scoring.service.js.map +1 -0
- package/dist/services/auth/crypto.service.d.ts +19 -0
- package/dist/services/auth/crypto.service.d.ts.map +1 -0
- package/dist/services/auth/crypto.service.js +135 -0
- package/dist/services/auth/crypto.service.js.map +1 -0
- package/dist/services/auth/errors.d.ts +19 -0
- package/dist/services/auth/errors.d.ts.map +1 -0
- package/dist/services/auth/errors.js +46 -0
- package/dist/services/auth/errors.js.map +1 -0
- package/dist/services/auth/token.service.d.ts +41 -0
- package/dist/services/auth/token.service.d.ts.map +1 -0
- package/dist/services/auth/token.service.js +208 -0
- package/dist/services/auth/token.service.js.map +1 -0
- package/dist/services/config/config.service.d.ts +6 -0
- package/dist/services/config/config.service.d.ts.map +1 -0
- package/dist/services/config/config.service.js +64 -0
- package/dist/services/config/config.service.js.map +1 -0
- package/dist/services/export/export.service.d.ts +28 -0
- package/dist/services/export/export.service.d.ts.map +1 -0
- package/dist/services/export/export.service.js +28 -0
- package/dist/services/export/export.service.js.map +1 -0
- package/dist/services/export/formatters/csv.formatter.d.ts +8 -0
- package/dist/services/export/formatters/csv.formatter.d.ts.map +1 -0
- package/dist/services/export/formatters/csv.formatter.js +46 -0
- package/dist/services/export/formatters/csv.formatter.js.map +1 -0
- package/dist/services/export/formatters/json.formatter.d.ts +40 -0
- package/dist/services/export/formatters/json.formatter.d.ts.map +1 -0
- package/dist/services/export/formatters/json.formatter.js +58 -0
- package/dist/services/export/formatters/json.formatter.js.map +1 -0
- package/dist/services/jobs/azure-job-runner.d.ts +38 -0
- package/dist/services/jobs/azure-job-runner.d.ts.map +1 -0
- package/dist/services/jobs/azure-job-runner.js +199 -0
- package/dist/services/jobs/azure-job-runner.js.map +1 -0
- package/dist/services/jobs/index.d.ts +4 -0
- package/dist/services/jobs/index.d.ts.map +1 -0
- package/dist/services/jobs/index.js +20 -0
- package/dist/services/jobs/index.js.map +1 -0
- package/dist/services/jobs/job-runner.d.ts +64 -0
- package/dist/services/jobs/job-runner.d.ts.map +1 -0
- package/dist/services/jobs/job-runner.js +952 -0
- package/dist/services/jobs/job-runner.js.map +1 -0
- package/dist/services/jobs/job-store.d.ts +27 -0
- package/dist/services/jobs/job-store.d.ts.map +1 -0
- package/dist/services/jobs/job-store.js +261 -0
- package/dist/services/jobs/job-store.js.map +1 -0
- package/dist/services/jobs/job.types.d.ts +67 -0
- package/dist/services/jobs/job.types.d.ts.map +1 -0
- package/dist/services/jobs/job.types.js +36 -0
- package/dist/services/jobs/job.types.js.map +1 -0
- package/dist/types/ad.types.d.ts +74 -0
- package/dist/types/ad.types.d.ts.map +1 -0
- package/dist/types/ad.types.js +3 -0
- package/dist/types/ad.types.js.map +1 -0
- package/dist/types/adcs.types.d.ts +58 -0
- package/dist/types/adcs.types.d.ts.map +1 -0
- package/dist/types/adcs.types.js +38 -0
- package/dist/types/adcs.types.js.map +1 -0
- package/dist/types/attack-graph.types.d.ts +135 -0
- package/dist/types/attack-graph.types.d.ts.map +1 -0
- package/dist/types/attack-graph.types.js +58 -0
- package/dist/types/attack-graph.types.js.map +1 -0
- package/dist/types/audit.types.d.ts +34 -0
- package/dist/types/audit.types.d.ts.map +1 -0
- package/dist/types/audit.types.js +3 -0
- package/dist/types/audit.types.js.map +1 -0
- package/dist/types/azure.types.d.ts +61 -0
- package/dist/types/azure.types.d.ts.map +1 -0
- package/dist/types/azure.types.js +3 -0
- package/dist/types/azure.types.js.map +1 -0
- package/dist/types/config.types.d.ts +63 -0
- package/dist/types/config.types.d.ts.map +1 -0
- package/dist/types/config.types.js +3 -0
- package/dist/types/config.types.js.map +1 -0
- package/dist/types/error.types.d.ts +33 -0
- package/dist/types/error.types.d.ts.map +1 -0
- package/dist/types/error.types.js +70 -0
- package/dist/types/error.types.js.map +1 -0
- package/dist/types/finding.types.d.ts +133 -0
- package/dist/types/finding.types.d.ts.map +1 -0
- package/dist/types/finding.types.js +3 -0
- package/dist/types/finding.types.js.map +1 -0
- package/dist/types/gpo.types.d.ts +39 -0
- package/dist/types/gpo.types.d.ts.map +1 -0
- package/dist/types/gpo.types.js +15 -0
- package/dist/types/gpo.types.js.map +1 -0
- package/dist/types/token.types.d.ts +26 -0
- package/dist/types/token.types.d.ts.map +1 -0
- package/dist/types/token.types.js +3 -0
- package/dist/types/token.types.js.map +1 -0
- package/dist/types/trust.types.d.ts +45 -0
- package/dist/types/trust.types.d.ts.map +1 -0
- package/dist/types/trust.types.js +71 -0
- package/dist/types/trust.types.js.map +1 -0
- package/dist/utils/entity-converter.d.ts +17 -0
- package/dist/utils/entity-converter.d.ts.map +1 -0
- package/dist/utils/entity-converter.js +285 -0
- package/dist/utils/entity-converter.js.map +1 -0
- package/dist/utils/graph.util.d.ts +66 -0
- package/dist/utils/graph.util.d.ts.map +1 -0
- package/dist/utils/graph.util.js +382 -0
- package/dist/utils/graph.util.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +86 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/type-name-normalizer.d.ts +5 -0
- package/dist/utils/type-name-normalizer.d.ts.map +1 -0
- package/dist/utils/type-name-normalizer.js +218 -0
- package/dist/utils/type-name-normalizer.js.map +1 -0
- package/docker-compose.yml +26 -0
- package/docs/api/README.md +178 -0
- package/docs/api/openapi.yaml +1524 -0
- package/eslint.config.js +54 -0
- package/jest.config.js +38 -0
- package/package.json +97 -0
- package/scripts/fetch-ad-cert.sh +142 -0
- package/src/.gitkeep +0 -0
- package/src/api/.gitkeep +0 -0
- package/src/api/controllers/.gitkeep +0 -0
- package/src/api/controllers/audit.controller.ts +313 -0
- package/src/api/controllers/auth.controller.ts +258 -0
- package/src/api/controllers/export.controller.ts +153 -0
- package/src/api/controllers/health.controller.ts +16 -0
- package/src/api/controllers/jobs.controller.ts +187 -0
- package/src/api/controllers/providers.controller.ts +165 -0
- package/src/api/dto/.gitkeep +0 -0
- package/src/api/dto/AuditRequest.dto.ts +8 -0
- package/src/api/dto/AuditResponse.dto.ts +19 -0
- package/src/api/dto/TokenRequest.dto.ts +8 -0
- package/src/api/dto/TokenResponse.dto.ts +14 -0
- package/src/api/middlewares/.gitkeep +0 -0
- package/src/api/middlewares/authenticate.ts +203 -0
- package/src/api/middlewares/errorHandler.ts +54 -0
- package/src/api/middlewares/rateLimit.ts +35 -0
- package/src/api/middlewares/validate.ts +32 -0
- package/src/api/routes/.gitkeep +0 -0
- package/src/api/routes/audit.routes.ts +77 -0
- package/src/api/routes/auth.routes.ts +71 -0
- package/src/api/routes/export.routes.ts +34 -0
- package/src/api/routes/health.routes.ts +14 -0
- package/src/api/routes/index.ts +40 -0
- package/src/api/routes/providers.routes.ts +24 -0
- package/src/api/validators/.gitkeep +0 -0
- package/src/api/validators/audit.schemas.ts +59 -0
- package/src/api/validators/auth.schemas.ts +59 -0
- package/src/app.ts +87 -0
- package/src/config/.gitkeep +0 -0
- package/src/config/config.schema.ts +108 -0
- package/src/config/index.ts +82 -0
- package/src/container.ts +221 -0
- package/src/data/.gitkeep +0 -0
- package/src/data/database.ts +78 -0
- package/src/data/jobs/token-cleanup.job.ts +166 -0
- package/src/data/migrations/.gitkeep +0 -0
- package/src/data/migrations/001_initial_schema.sql +47 -0
- package/src/data/migrations/migration.runner.ts +125 -0
- package/src/data/models/.gitkeep +0 -0
- package/src/data/models/Token.model.ts +35 -0
- package/src/data/repositories/.gitkeep +0 -0
- package/src/data/repositories/token.repository.ts +160 -0
- package/src/providers/.gitkeep +0 -0
- package/src/providers/azure/.gitkeep +0 -0
- package/src/providers/azure/auth.provider.ts +14 -0
- package/src/providers/azure/azure-errors.ts +189 -0
- package/src/providers/azure/azure-retry.ts +168 -0
- package/src/providers/azure/graph-client.ts +315 -0
- package/src/providers/azure/graph.provider.ts +294 -0
- package/src/providers/azure/queries/app.queries.ts +9 -0
- package/src/providers/azure/queries/policy.queries.ts +9 -0
- package/src/providers/azure/queries/user.queries.ts +10 -0
- package/src/providers/interfaces/.gitkeep +0 -0
- package/src/providers/interfaces/IGraphProvider.ts +117 -0
- package/src/providers/interfaces/ILDAPProvider.ts +142 -0
- package/src/providers/ldap/.gitkeep +0 -0
- package/src/providers/ldap/acl-parser.ts +231 -0
- package/src/providers/ldap/ad-mappers.ts +280 -0
- package/src/providers/ldap/ldap-client.ts +259 -0
- package/src/providers/ldap/ldap-errors.ts +188 -0
- package/src/providers/ldap/ldap-retry.ts +267 -0
- package/src/providers/ldap/ldap-sanitizer.ts +273 -0
- package/src/providers/ldap/ldap.provider.ts +293 -0
- package/src/providers/ldap/queries/computer.queries.ts +9 -0
- package/src/providers/ldap/queries/group.queries.ts +9 -0
- package/src/providers/ldap/queries/user.queries.ts +10 -0
- package/src/providers/smb/smb.provider.ts +653 -0
- package/src/server.ts +60 -0
- package/src/services/.gitkeep +0 -0
- package/src/services/audit/.gitkeep +0 -0
- package/src/services/audit/ad-audit.service.ts +1481 -0
- package/src/services/audit/attack-graph.service.ts +1104 -0
- package/src/services/audit/audit.service.ts +12 -0
- package/src/services/audit/azure-audit.service.ts +286 -0
- package/src/services/audit/detectors/ad/accounts.detector.ts +1232 -0
- package/src/services/audit/detectors/ad/adcs.detector.ts +449 -0
- package/src/services/audit/detectors/ad/advanced.detector.ts +1270 -0
- package/src/services/audit/detectors/ad/attack-paths.detector.ts +600 -0
- package/src/services/audit/detectors/ad/compliance.detector.ts +1421 -0
- package/src/services/audit/detectors/ad/computers.detector.ts +1188 -0
- package/src/services/audit/detectors/ad/gpo.detector.ts +485 -0
- package/src/services/audit/detectors/ad/groups.detector.ts +685 -0
- package/src/services/audit/detectors/ad/index.ts +84 -0
- package/src/services/audit/detectors/ad/kerberos.detector.ts +424 -0
- package/src/services/audit/detectors/ad/monitoring.detector.ts +501 -0
- package/src/services/audit/detectors/ad/network.detector.ts +538 -0
- package/src/services/audit/detectors/ad/password.detector.ts +324 -0
- package/src/services/audit/detectors/ad/permissions.detector.ts +637 -0
- package/src/services/audit/detectors/ad/trusts.detector.ts +315 -0
- package/src/services/audit/detectors/azure/app-security.detector.ts +246 -0
- package/src/services/audit/detectors/azure/conditional-access.detector.ts +186 -0
- package/src/services/audit/detectors/azure/privilege-security.detector.ts +176 -0
- package/src/services/audit/detectors/azure/user-security.detector.ts +280 -0
- package/src/services/audit/detectors/index.ts +18 -0
- package/src/services/audit/response-formatter.ts +604 -0
- package/src/services/audit/scoring.service.ts +234 -0
- package/src/services/auth/.gitkeep +0 -0
- package/src/services/auth/crypto.service.ts +230 -0
- package/src/services/auth/errors.ts +47 -0
- package/src/services/auth/token.service.ts +420 -0
- package/src/services/config/.gitkeep +0 -0
- package/src/services/config/config.service.ts +75 -0
- package/src/services/export/.gitkeep +0 -0
- package/src/services/export/export.service.ts +99 -0
- package/src/services/export/formatters/csv.formatter.ts +124 -0
- package/src/services/export/formatters/json.formatter.ts +160 -0
- package/src/services/jobs/azure-job-runner.ts +312 -0
- package/src/services/jobs/index.ts +9 -0
- package/src/services/jobs/job-runner.ts +1280 -0
- package/src/services/jobs/job-store.ts +384 -0
- package/src/services/jobs/job.types.ts +182 -0
- package/src/types/.gitkeep +0 -0
- package/src/types/ad.types.ts +91 -0
- package/src/types/adcs.types.ts +107 -0
- package/src/types/attack-graph.types.ts +260 -0
- package/src/types/audit.types.ts +42 -0
- package/src/types/azure.types.ts +68 -0
- package/src/types/config.types.ts +79 -0
- package/src/types/error.types.ts +69 -0
- package/src/types/finding.types.ts +284 -0
- package/src/types/gpo.types.ts +72 -0
- package/src/types/smb2.d.ts +73 -0
- package/src/types/token.types.ts +32 -0
- package/src/types/trust.types.ts +140 -0
- package/src/utils/.gitkeep +0 -0
- package/src/utils/entity-converter.ts +453 -0
- package/src/utils/graph.util.ts +609 -0
- package/src/utils/logger.ts +111 -0
- package/src/utils/type-name-normalizer.ts +302 -0
- package/tests/.gitkeep +0 -0
- package/tests/e2e/.gitkeep +0 -0
- package/tests/fixtures/.gitkeep +0 -0
- package/tests/integration/.gitkeep +0 -0
- package/tests/integration/README.md +156 -0
- package/tests/integration/ad-audit.integration.test.ts +216 -0
- package/tests/integration/api/.gitkeep +0 -0
- package/tests/integration/api/endpoints.integration.test.ts +431 -0
- package/tests/integration/auth/jwt-authentication.integration.test.ts +358 -0
- package/tests/integration/providers/.gitkeep +0 -0
- package/tests/integration/providers/azure-basic.integration.test.ts +167 -0
- package/tests/integration/providers/ldap-basic.integration.test.ts +152 -0
- package/tests/integration/providers/ldap-connectivity.test.ts +44 -0
- package/tests/integration/providers/ldap-provider.integration.test.ts +347 -0
- package/tests/mocks/.gitkeep +0 -0
- package/tests/setup.ts +16 -0
- package/tests/unit/.gitkeep +0 -0
- package/tests/unit/api/middlewares/authenticate.test.ts +446 -0
- package/tests/unit/providers/.gitkeep +0 -0
- package/tests/unit/providers/azure/azure-errors.test.ts +193 -0
- package/tests/unit/providers/azure/azure-retry.test.ts +254 -0
- package/tests/unit/providers/azure/graph-provider.test.ts +313 -0
- package/tests/unit/providers/ldap/ad-mappers.test.ts +392 -0
- package/tests/unit/providers/ldap/ldap-provider.test.ts +376 -0
- package/tests/unit/providers/ldap/ldap-retry.test.ts +377 -0
- package/tests/unit/providers/ldap/ldap-sanitizer.test.ts +301 -0
- package/tests/unit/sample.test.ts +19 -0
- package/tests/unit/services/.gitkeep +0 -0
- package/tests/unit/services/audit/detectors/ad/accounts.detector.test.ts +393 -0
- package/tests/unit/services/audit/detectors/ad/advanced.detector.test.ts +380 -0
- package/tests/unit/services/audit/detectors/ad/computers.detector.test.ts +440 -0
- package/tests/unit/services/audit/detectors/ad/groups.detector.test.ts +276 -0
- package/tests/unit/services/audit/detectors/ad/kerberos.detector.test.ts +215 -0
- package/tests/unit/services/audit/detectors/ad/password.detector.test.ts +226 -0
- package/tests/unit/services/audit/detectors/ad/permissions.detector.test.ts +244 -0
- package/tests/unit/services/audit/detectors/azure/app-security.detector.test.ts +349 -0
- package/tests/unit/services/audit/detectors/azure/conditional-access.detector.test.ts +374 -0
- package/tests/unit/services/audit/detectors/azure/privilege-security.detector.test.ts +374 -0
- package/tests/unit/services/audit/detectors/azure/user-security.detector.test.ts +297 -0
- package/tests/unit/services/auth/crypto.service.test.ts +296 -0
- package/tests/unit/services/auth/token.service.test.ts +579 -0
- package/tests/unit/services/export/export.service.test.ts +241 -0
- package/tests/unit/services/export/formatters/csv.formatter.test.ts +270 -0
- package/tests/unit/services/export/formatters/json.formatter.test.ts +258 -0
- package/tests/unit/utils/.gitkeep +0 -0
- 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
|
+
}
|