@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,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Scoring Service
|
|
3
|
+
*
|
|
4
|
+
* Calculates security scores based on vulnerability findings
|
|
5
|
+
* Story 1.7: AD Vulnerability Detection Engine
|
|
6
|
+
*
|
|
7
|
+
* Scoring Methodology (v1.1.1):
|
|
8
|
+
* - Weighted Findings = (Critical × 10) + (High × 3) + (Medium × 1) + (Low × 0.2)
|
|
9
|
+
* - Logarithmic scale to avoid extreme scores with high finding counts
|
|
10
|
+
* - Security Score = max(0, min(100, 100 - log10(ratio + 1) * 50))
|
|
11
|
+
*
|
|
12
|
+
* Interpretation:
|
|
13
|
+
* - 90-100: Excellent - Minimal vulnerabilities, strong security posture
|
|
14
|
+
* - 70-89: Good - Some issues to address, generally secure
|
|
15
|
+
* - 50-69: Fair - Multiple vulnerabilities requiring attention
|
|
16
|
+
* - 30-49: Poor - Significant security gaps, urgent remediation needed
|
|
17
|
+
* - 0-29: Critical - Severe security risk, immediate action required
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { Finding, FindingCounts, CategoryCounts, Severity } from '../../types/finding.types';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Security score result
|
|
24
|
+
*/
|
|
25
|
+
export interface SecurityScore {
|
|
26
|
+
score: number;
|
|
27
|
+
rating: 'excellent' | 'good' | 'fair' | 'poor' | 'critical';
|
|
28
|
+
weightedPoints: number;
|
|
29
|
+
totalUsers: number;
|
|
30
|
+
findings: FindingCounts;
|
|
31
|
+
categories: CategoryCounts;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Severity weights for scoring (v1.1.0 - aligned with SaaS)
|
|
36
|
+
*/
|
|
37
|
+
const SEVERITY_WEIGHTS: Record<Severity, number> = {
|
|
38
|
+
critical: 10,
|
|
39
|
+
high: 3,
|
|
40
|
+
medium: 1,
|
|
41
|
+
low: 0.2,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Calculate security score from findings
|
|
46
|
+
*
|
|
47
|
+
* @param findings Array of vulnerability findings
|
|
48
|
+
* @param totalUsers Total number of users in the directory (for normalization)
|
|
49
|
+
* @returns Security score object with rating and details
|
|
50
|
+
*/
|
|
51
|
+
export function calculateSecurityScore(findings: Finding[], totalUsers: number): SecurityScore {
|
|
52
|
+
// Count findings by severity
|
|
53
|
+
const counts: FindingCounts = {
|
|
54
|
+
critical: 0,
|
|
55
|
+
high: 0,
|
|
56
|
+
medium: 0,
|
|
57
|
+
low: 0,
|
|
58
|
+
total: 0,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Count findings by category
|
|
62
|
+
const categories: CategoryCounts = {
|
|
63
|
+
passwords: 0,
|
|
64
|
+
kerberos: 0,
|
|
65
|
+
accounts: 0,
|
|
66
|
+
groups: 0,
|
|
67
|
+
computers: 0,
|
|
68
|
+
advanced: 0,
|
|
69
|
+
permissions: 0,
|
|
70
|
+
config: 0,
|
|
71
|
+
adcs: 0,
|
|
72
|
+
gpo: 0,
|
|
73
|
+
trusts: 0,
|
|
74
|
+
'attack-paths': 0,
|
|
75
|
+
monitoring: 0,
|
|
76
|
+
compliance: 0,
|
|
77
|
+
network: 0,
|
|
78
|
+
identity: 0,
|
|
79
|
+
applications: 0,
|
|
80
|
+
conditionalAccess: 0,
|
|
81
|
+
privilegedAccess: 0,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Aggregate findings
|
|
85
|
+
findings.forEach((finding) => {
|
|
86
|
+
counts[finding.severity] += finding.count;
|
|
87
|
+
counts.total += finding.count;
|
|
88
|
+
categories[finding.category] += finding.count;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Calculate weighted findings (v1.1.0 formula - aligned with SaaS)
|
|
92
|
+
const weightedFindings =
|
|
93
|
+
counts.critical * SEVERITY_WEIGHTS.critical +
|
|
94
|
+
counts.high * SEVERITY_WEIGHTS.high +
|
|
95
|
+
counts.medium * SEVERITY_WEIGHTS.medium +
|
|
96
|
+
counts.low * SEVERITY_WEIGHTS.low;
|
|
97
|
+
|
|
98
|
+
// Calculate security score (0-100) using logarithmic scale
|
|
99
|
+
// This prevents extreme scores (always 0) with high finding counts
|
|
100
|
+
// Multiplier 50 ensures vulnerable environments get appropriately low scores
|
|
101
|
+
const totalEntities = Math.max(totalUsers, 1);
|
|
102
|
+
const ratio = weightedFindings / totalEntities;
|
|
103
|
+
const normalizedRatio = Math.log10(ratio + 1) * 50;
|
|
104
|
+
const score = Math.max(0, Math.min(100, 100 - normalizedRatio));
|
|
105
|
+
|
|
106
|
+
// Determine rating
|
|
107
|
+
const rating = getSecurityRating(score);
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
score: Math.round(score * 10) / 10, // Round to 1 decimal place
|
|
111
|
+
rating,
|
|
112
|
+
weightedPoints: weightedFindings,
|
|
113
|
+
totalUsers,
|
|
114
|
+
findings: counts,
|
|
115
|
+
categories,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get security rating from score
|
|
121
|
+
*
|
|
122
|
+
* @param score Security score (0-100)
|
|
123
|
+
* @returns Rating category
|
|
124
|
+
*/
|
|
125
|
+
function getSecurityRating(score: number): 'excellent' | 'good' | 'fair' | 'poor' | 'critical' {
|
|
126
|
+
if (score >= 90) return 'excellent';
|
|
127
|
+
if (score >= 70) return 'good';
|
|
128
|
+
if (score >= 50) return 'fair';
|
|
129
|
+
if (score >= 30) return 'poor';
|
|
130
|
+
return 'critical';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get human-readable description for rating
|
|
135
|
+
*
|
|
136
|
+
* @param rating Security rating
|
|
137
|
+
* @returns Description string
|
|
138
|
+
*/
|
|
139
|
+
export function getRatingDescription(rating: string): string {
|
|
140
|
+
const descriptions: Record<string, string> = {
|
|
141
|
+
excellent: 'Excellent - Minimal vulnerabilities, strong security posture',
|
|
142
|
+
good: 'Good - Some issues to address, generally secure',
|
|
143
|
+
fair: 'Fair - Multiple vulnerabilities requiring attention',
|
|
144
|
+
poor: 'Poor - Significant security gaps, urgent remediation needed',
|
|
145
|
+
critical: 'Critical - Severe security risk, immediate action required',
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
return descriptions[rating] || 'Unknown rating';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Calculate category-specific scores
|
|
153
|
+
*
|
|
154
|
+
* @param findings Array of vulnerability findings
|
|
155
|
+
* @returns Map of category to score (0-100)
|
|
156
|
+
*/
|
|
157
|
+
export function calculateCategoryScores(findings: Finding[]): Record<string, number> {
|
|
158
|
+
const categoryScores: Record<string, number> = {
|
|
159
|
+
passwords: 100,
|
|
160
|
+
kerberos: 100,
|
|
161
|
+
accounts: 100,
|
|
162
|
+
groups: 100,
|
|
163
|
+
computers: 100,
|
|
164
|
+
advanced: 100,
|
|
165
|
+
permissions: 100,
|
|
166
|
+
config: 100,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Group findings by category
|
|
170
|
+
const categoryFindings = findings.reduce((acc, finding) => {
|
|
171
|
+
if (!acc[finding.category]) {
|
|
172
|
+
acc[finding.category] = [];
|
|
173
|
+
}
|
|
174
|
+
acc[finding.category]!.push(finding);
|
|
175
|
+
return acc;
|
|
176
|
+
}, {} as Record<string, Finding[]>);
|
|
177
|
+
|
|
178
|
+
// Calculate score for each category
|
|
179
|
+
Object.keys(categoryFindings).forEach((category) => {
|
|
180
|
+
const categoryFindingsList = categoryFindings[category];
|
|
181
|
+
if (!categoryFindingsList) return;
|
|
182
|
+
|
|
183
|
+
const weightedPoints = categoryFindingsList.reduce((sum, finding) => {
|
|
184
|
+
return sum + finding.count * SEVERITY_WEIGHTS[finding.severity];
|
|
185
|
+
}, 0);
|
|
186
|
+
|
|
187
|
+
// Simple deduction: -1 point per weighted point (capped at 0)
|
|
188
|
+
categoryScores[category] = Math.max(0, 100 - weightedPoints);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
return categoryScores;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Get top N most critical findings
|
|
196
|
+
*
|
|
197
|
+
* @param findings Array of vulnerability findings
|
|
198
|
+
* @param limit Number of findings to return
|
|
199
|
+
* @returns Top N findings sorted by severity and count
|
|
200
|
+
*/
|
|
201
|
+
export function getTopFindings(findings: Finding[], limit: number = 10): Finding[] {
|
|
202
|
+
// Sort by severity weight * count (descending)
|
|
203
|
+
const sorted = [...findings].sort((a, b) => {
|
|
204
|
+
const weightA = SEVERITY_WEIGHTS[a.severity] * a.count;
|
|
205
|
+
const weightB = SEVERITY_WEIGHTS[b.severity] * b.count;
|
|
206
|
+
return weightB - weightA;
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return sorted.slice(0, limit);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Generate security summary
|
|
214
|
+
*
|
|
215
|
+
* @param score Security score object
|
|
216
|
+
* @returns Human-readable summary string
|
|
217
|
+
*/
|
|
218
|
+
export function generateSecuritySummary(score: SecurityScore): string {
|
|
219
|
+
const { score: scoreValue, rating, findings } = score;
|
|
220
|
+
|
|
221
|
+
const lines = [
|
|
222
|
+
`Security Score: ${scoreValue}/100 (${rating.toUpperCase()})`,
|
|
223
|
+
getRatingDescription(rating),
|
|
224
|
+
'',
|
|
225
|
+
'Vulnerability Summary:',
|
|
226
|
+
`- Critical: ${findings.critical}`,
|
|
227
|
+
`- High: ${findings.high}`,
|
|
228
|
+
`- Medium: ${findings.medium}`,
|
|
229
|
+
`- Low: ${findings.low}`,
|
|
230
|
+
`- Total: ${findings.total}`,
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
return lines.join('\n');
|
|
234
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
import type { Logger } from 'winston';
|
|
5
|
+
import { logger } from '../../utils/logger';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* CryptoService
|
|
9
|
+
*
|
|
10
|
+
* Manages RSA key pairs for RS256 JWT signatures.
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Generates 2048-bit RSA key pairs
|
|
14
|
+
* - Persists keys to filesystem (PKCS#8 private, SPKI public)
|
|
15
|
+
* - Loads existing keys or auto-generates on first use
|
|
16
|
+
* - Sets secure file permissions (600 for private, 644 for public)
|
|
17
|
+
*
|
|
18
|
+
* Task 1: RS256 Key Management (Story 1.4)
|
|
19
|
+
*
|
|
20
|
+
* Integration Verifications:
|
|
21
|
+
* - IV1: Auto-generates key pair on first startup
|
|
22
|
+
* - IV2: Loads existing keys from filesystem
|
|
23
|
+
* - IV3: Private key has 600 permissions
|
|
24
|
+
* - IV4: Public key has 644 permissions
|
|
25
|
+
* - IV5: Keys persist across server restarts
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export interface KeyPair {
|
|
29
|
+
privateKey: string;
|
|
30
|
+
publicKey: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class CryptoService {
|
|
34
|
+
private privateKey: string | null = null;
|
|
35
|
+
private publicKey: string | null = null;
|
|
36
|
+
private logger: Logger;
|
|
37
|
+
|
|
38
|
+
constructor(
|
|
39
|
+
private privateKeyPath: string,
|
|
40
|
+
private publicKeyPath: string
|
|
41
|
+
) {
|
|
42
|
+
this.logger = logger;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Generate a new RSA key pair
|
|
47
|
+
*
|
|
48
|
+
* Specification:
|
|
49
|
+
* - Algorithm: RSA
|
|
50
|
+
* - Key size: 2048 bits
|
|
51
|
+
* - Private key format: PKCS#8 PEM
|
|
52
|
+
* - Public key format: SPKI PEM
|
|
53
|
+
*
|
|
54
|
+
* @returns KeyPair with private and public keys in PEM format
|
|
55
|
+
*/
|
|
56
|
+
generateKeyPair(): KeyPair {
|
|
57
|
+
this.logger.info('Generating new RSA key pair (2048-bit)');
|
|
58
|
+
|
|
59
|
+
const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
|
|
60
|
+
modulusLength: 2048,
|
|
61
|
+
publicKeyEncoding: {
|
|
62
|
+
type: 'spki',
|
|
63
|
+
format: 'pem',
|
|
64
|
+
},
|
|
65
|
+
privateKeyEncoding: {
|
|
66
|
+
type: 'pkcs8',
|
|
67
|
+
format: 'pem',
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
this.logger.info('RSA key pair generated successfully');
|
|
72
|
+
return { privateKey, publicKey };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Load existing keys from filesystem or generate new ones
|
|
77
|
+
*
|
|
78
|
+
* Flow:
|
|
79
|
+
* 1. Check if both key files exist
|
|
80
|
+
* 2. If yes: load from files and cache in memory
|
|
81
|
+
* 3. If no: generate new key pair, save to files, cache in memory
|
|
82
|
+
*
|
|
83
|
+
* File permissions:
|
|
84
|
+
* - Private key: 600 (owner read/write only)
|
|
85
|
+
* - Public key: 644 (owner read/write, others read)
|
|
86
|
+
*
|
|
87
|
+
* @throws Error if key loading or generation fails
|
|
88
|
+
*/
|
|
89
|
+
async loadOrGenerateKeys(): Promise<void> {
|
|
90
|
+
const privateKeyExists = existsSync(this.privateKeyPath);
|
|
91
|
+
const publicKeyExists = existsSync(this.publicKeyPath);
|
|
92
|
+
|
|
93
|
+
if (privateKeyExists && publicKeyExists) {
|
|
94
|
+
// Load existing keys
|
|
95
|
+
this.logger.info('Loading existing RSA keys from filesystem', {
|
|
96
|
+
privateKeyPath: this.privateKeyPath,
|
|
97
|
+
publicKeyPath: this.publicKeyPath,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
this.privateKey = readFileSync(this.privateKeyPath, 'utf-8');
|
|
102
|
+
this.publicKey = readFileSync(this.publicKeyPath, 'utf-8');
|
|
103
|
+
|
|
104
|
+
// Validate that keys are in correct PEM format
|
|
105
|
+
this.validateKeyFormat(this.privateKey, 'PRIVATE KEY');
|
|
106
|
+
this.validateKeyFormat(this.publicKey, 'PUBLIC KEY');
|
|
107
|
+
|
|
108
|
+
this.logger.info('RSA keys loaded successfully from filesystem');
|
|
109
|
+
} catch (error) {
|
|
110
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
111
|
+
this.logger.error('Failed to load RSA keys from filesystem', { error: message });
|
|
112
|
+
throw new Error(`Failed to load RSA keys: ${message}`);
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
// Generate and save new keys
|
|
116
|
+
if (privateKeyExists !== publicKeyExists) {
|
|
117
|
+
this.logger.warn('Only one key file exists, regenerating both', {
|
|
118
|
+
privateKeyExists,
|
|
119
|
+
publicKeyExists,
|
|
120
|
+
});
|
|
121
|
+
} else {
|
|
122
|
+
this.logger.info('No existing keys found, generating new RSA key pair');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const keyPair = this.generateKeyPair();
|
|
127
|
+
this.privateKey = keyPair.privateKey;
|
|
128
|
+
this.publicKey = keyPair.publicKey;
|
|
129
|
+
|
|
130
|
+
this.saveKeys(keyPair);
|
|
131
|
+
this.logger.info('RSA keys generated and saved successfully');
|
|
132
|
+
} catch (error) {
|
|
133
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
134
|
+
this.logger.error('Failed to generate and save RSA keys', { error: message });
|
|
135
|
+
throw new Error(`Failed to generate RSA keys: ${message}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get the cached private key
|
|
142
|
+
*
|
|
143
|
+
* @returns Private key in PEM format
|
|
144
|
+
* @throws Error if keys haven't been loaded yet
|
|
145
|
+
*/
|
|
146
|
+
getPrivateKey(): string {
|
|
147
|
+
if (!this.privateKey) {
|
|
148
|
+
throw new Error('Keys not loaded. Call loadOrGenerateKeys() first.');
|
|
149
|
+
}
|
|
150
|
+
return this.privateKey;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Get the cached public key
|
|
155
|
+
*
|
|
156
|
+
* @returns Public key in PEM format
|
|
157
|
+
* @throws Error if keys haven't been loaded yet
|
|
158
|
+
*/
|
|
159
|
+
getPublicKey(): string {
|
|
160
|
+
if (!this.publicKey) {
|
|
161
|
+
throw new Error('Keys not loaded. Call loadOrGenerateKeys() first.');
|
|
162
|
+
}
|
|
163
|
+
return this.publicKey;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Save key pair to filesystem with secure permissions
|
|
168
|
+
*
|
|
169
|
+
* Security:
|
|
170
|
+
* - Creates parent directories if needed
|
|
171
|
+
* - Sets private key to 600 (owner read/write only)
|
|
172
|
+
* - Sets public key to 644 (owner read/write, others read)
|
|
173
|
+
*
|
|
174
|
+
* @param keyPair The key pair to save
|
|
175
|
+
* @throws Error if file operations fail
|
|
176
|
+
*/
|
|
177
|
+
private saveKeys(keyPair: KeyPair): void {
|
|
178
|
+
try {
|
|
179
|
+
// Ensure parent directories exist
|
|
180
|
+
const privateKeyDir = dirname(this.privateKeyPath);
|
|
181
|
+
const publicKeyDir = dirname(this.publicKeyPath);
|
|
182
|
+
|
|
183
|
+
if (!existsSync(privateKeyDir)) {
|
|
184
|
+
mkdirSync(privateKeyDir, { recursive: true });
|
|
185
|
+
this.logger.debug('Created directory for private key', { path: privateKeyDir });
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (!existsSync(publicKeyDir)) {
|
|
189
|
+
mkdirSync(publicKeyDir, { recursive: true });
|
|
190
|
+
this.logger.debug('Created directory for public key', { path: publicKeyDir });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Write private key with restrictive permissions
|
|
194
|
+
writeFileSync(this.privateKeyPath, keyPair.privateKey, { mode: 0o600 });
|
|
195
|
+
chmodSync(this.privateKeyPath, 0o600);
|
|
196
|
+
this.logger.debug('Private key saved', {
|
|
197
|
+
path: this.privateKeyPath,
|
|
198
|
+
permissions: '600',
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Write public key with standard permissions
|
|
202
|
+
writeFileSync(this.publicKeyPath, keyPair.publicKey, { mode: 0o644 });
|
|
203
|
+
chmodSync(this.publicKeyPath, 0o644);
|
|
204
|
+
this.logger.debug('Public key saved', {
|
|
205
|
+
path: this.publicKeyPath,
|
|
206
|
+
permissions: '644',
|
|
207
|
+
});
|
|
208
|
+
} catch (error) {
|
|
209
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
210
|
+
this.logger.error('Failed to save keys to filesystem', { error: message });
|
|
211
|
+
throw new Error(`Failed to save keys: ${message}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Validate that a key string is in correct PEM format
|
|
217
|
+
*
|
|
218
|
+
* @param key The key string to validate
|
|
219
|
+
* @param keyType Expected key type ('PRIVATE KEY' or 'PUBLIC KEY')
|
|
220
|
+
* @throws Error if key format is invalid
|
|
221
|
+
*/
|
|
222
|
+
private validateKeyFormat(key: string, keyType: string): void {
|
|
223
|
+
const beginMarker = `-----BEGIN ${keyType}-----`;
|
|
224
|
+
const endMarker = `-----END ${keyType}-----`;
|
|
225
|
+
|
|
226
|
+
if (!key.includes(beginMarker) || !key.includes(endMarker)) {
|
|
227
|
+
throw new Error(`Invalid ${keyType} format: missing PEM markers`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT Authentication Errors
|
|
3
|
+
*
|
|
4
|
+
* Custom error classes for token validation and authentication failures.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export class TokenExpiredError extends Error {
|
|
8
|
+
constructor(message = 'Token has expired') {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'TokenExpiredError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class TokenRevokedError extends Error {
|
|
15
|
+
constructor(message = 'Token has been revoked') {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = 'TokenRevokedError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class UsageLimitExceededError extends Error {
|
|
22
|
+
constructor(message = 'Token usage limit exceeded') {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = 'UsageLimitExceededError';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class TokenNotFoundError extends Error {
|
|
29
|
+
constructor(message = 'Token not found in database') {
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = 'TokenNotFoundError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class InvalidSignatureError extends Error {
|
|
36
|
+
constructor(message = 'Invalid token signature') {
|
|
37
|
+
super(message);
|
|
38
|
+
this.name = 'InvalidSignatureError';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class InvalidTokenError extends Error {
|
|
43
|
+
constructor(message = 'Invalid token') {
|
|
44
|
+
super(message);
|
|
45
|
+
this.name = 'InvalidTokenError';
|
|
46
|
+
}
|
|
47
|
+
}
|