@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,896 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectAnssiR1PasswordPolicy = detectAnssiR1PasswordPolicy;
|
|
4
|
+
exports.detectAnssiR2PrivilegedAccounts = detectAnssiR2PrivilegedAccounts;
|
|
5
|
+
exports.detectAnssiR3StrongAuth = detectAnssiR3StrongAuth;
|
|
6
|
+
exports.detectAnssiR4Logging = detectAnssiR4Logging;
|
|
7
|
+
exports.detectAnssiR5Segregation = detectAnssiR5Segregation;
|
|
8
|
+
exports.detectNistAc2AccountManagement = detectNistAc2AccountManagement;
|
|
9
|
+
exports.detectNistAc6LeastPrivilege = detectNistAc6LeastPrivilege;
|
|
10
|
+
exports.detectNistIa5Authenticator = detectNistIa5Authenticator;
|
|
11
|
+
exports.detectNistAu2AuditEvents = detectNistAu2AuditEvents;
|
|
12
|
+
exports.detectCisPasswordPolicy = detectCisPasswordPolicy;
|
|
13
|
+
exports.detectCisNetworkSecurity = detectCisNetworkSecurity;
|
|
14
|
+
exports.detectCisUserRights = detectCisUserRights;
|
|
15
|
+
exports.detectDisaAccountPolicies = detectDisaAccountPolicies;
|
|
16
|
+
exports.detectDisaAuditPolicies = detectDisaAuditPolicies;
|
|
17
|
+
exports.detectMfaNotEnforced = detectMfaNotEnforced;
|
|
18
|
+
exports.detectBackupNotVerified = detectBackupNotVerified;
|
|
19
|
+
exports.detectAuditLogRetentionShort = detectAuditLogRetentionShort;
|
|
20
|
+
exports.detectPrivilegedAccessReviewMissing = detectPrivilegedAccessReviewMissing;
|
|
21
|
+
exports.detectDataClassificationMissing = detectDataClassificationMissing;
|
|
22
|
+
exports.detectChangeManagementBypass = detectChangeManagementBypass;
|
|
23
|
+
exports.detectVendorAccountUnmonitored = detectVendorAccountUnmonitored;
|
|
24
|
+
exports.detectEncryptionAtRestDisabled = detectEncryptionAtRestDisabled;
|
|
25
|
+
exports.detectComplianceScore = detectComplianceScore;
|
|
26
|
+
exports.detectComplianceVulnerabilities = detectComplianceVulnerabilities;
|
|
27
|
+
const entity_converter_1 = require("../../../../utils/entity-converter");
|
|
28
|
+
function detectAnssiR1PasswordPolicy(domain, gpoSettings, _includeDetails) {
|
|
29
|
+
const issues = [];
|
|
30
|
+
let compliant = true;
|
|
31
|
+
const policy = domain['passwordPolicy'];
|
|
32
|
+
if (policy) {
|
|
33
|
+
if (policy.minPwdLength < 12) {
|
|
34
|
+
issues.push(`Minimum password length ${policy.minPwdLength} < 12 required`);
|
|
35
|
+
compliant = false;
|
|
36
|
+
}
|
|
37
|
+
if (policy.pwdHistoryLength < 12) {
|
|
38
|
+
issues.push(`Password history ${policy.pwdHistoryLength} < 12 required`);
|
|
39
|
+
compliant = false;
|
|
40
|
+
}
|
|
41
|
+
if (policy.lockoutThreshold > 5 && policy.lockoutThreshold !== 0) {
|
|
42
|
+
issues.push(`Lockout threshold ${policy.lockoutThreshold} > 5 allowed`);
|
|
43
|
+
compliant = false;
|
|
44
|
+
}
|
|
45
|
+
if (policy.maxPwdAge > 90) {
|
|
46
|
+
issues.push(`Max password age ${policy.maxPwdAge} > 90 days`);
|
|
47
|
+
compliant = false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
issues.push('Password policy not configured or not readable');
|
|
52
|
+
compliant = false;
|
|
53
|
+
}
|
|
54
|
+
if (gpoSettings?.ldapServerIntegrity !== undefined) {
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
type: 'ANSSI_R1_PASSWORD_POLICY',
|
|
58
|
+
severity: 'high',
|
|
59
|
+
category: 'compliance',
|
|
60
|
+
title: 'ANSSI R1 - Password Policy Non-Compliant',
|
|
61
|
+
description: 'Password policy does not meet ANSSI R1 recommendations. ANSSI requires minimum 12 characters, password history of 12, lockout threshold ≤5, and max age ≤90 days.',
|
|
62
|
+
count: compliant ? 0 : 1,
|
|
63
|
+
details: issues.length > 0 ? { violations: issues, framework: 'ANSSI', control: 'R1' } : undefined,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function detectAnssiR2PrivilegedAccounts(users, _groups, includeDetails) {
|
|
67
|
+
const privilegedGroups = ['Domain Admins', 'Enterprise Admins', 'Schema Admins', 'Administrators'];
|
|
68
|
+
const issues = [];
|
|
69
|
+
const privilegedUsers = users.filter((u) => {
|
|
70
|
+
if (!u.memberOf)
|
|
71
|
+
return false;
|
|
72
|
+
return u.memberOf.some((dn) => privilegedGroups.some((pg) => dn.includes(`CN=${pg}`)));
|
|
73
|
+
});
|
|
74
|
+
for (const user of privilegedUsers) {
|
|
75
|
+
const userIssues = [];
|
|
76
|
+
if (user.mail) {
|
|
77
|
+
userIssues.push('Admin account has email configured (use separate account)');
|
|
78
|
+
}
|
|
79
|
+
const uac = user.userAccountControl || 0;
|
|
80
|
+
if ((uac & 0x40000) === 0) {
|
|
81
|
+
userIssues.push('Smartcard not required for privileged account');
|
|
82
|
+
}
|
|
83
|
+
if (user.enabled && !user.lastLogon) {
|
|
84
|
+
userIssues.push('Enabled admin account never logged on');
|
|
85
|
+
}
|
|
86
|
+
if (userIssues.length > 0) {
|
|
87
|
+
issues.push({ user: user.sAMAccountName, violations: userIssues });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const domainAdmins = privilegedUsers.filter((u) => u.memberOf?.some((dn) => dn.includes('CN=Domain Admins')));
|
|
91
|
+
const domainAdminCount = domainAdmins.length;
|
|
92
|
+
return {
|
|
93
|
+
type: 'ANSSI_R2_PRIVILEGED_ACCOUNTS',
|
|
94
|
+
severity: 'high',
|
|
95
|
+
category: 'compliance',
|
|
96
|
+
title: 'ANSSI R2 - Privileged Accounts Non-Compliant',
|
|
97
|
+
description: 'Privileged accounts do not meet ANSSI R2 recommendations. Admin accounts should use separate identities, require smartcard, and not exceed 10 Domain Admins.',
|
|
98
|
+
count: issues.length,
|
|
99
|
+
affectedEntities: includeDetails
|
|
100
|
+
? (0, entity_converter_1.toAffectedUserEntities)(users.filter((u) => issues.some((i) => i.user === u.sAMAccountName)))
|
|
101
|
+
: undefined,
|
|
102
|
+
details: issues.length > 0
|
|
103
|
+
? {
|
|
104
|
+
violations: issues.slice(0, 10),
|
|
105
|
+
domainAdminCount,
|
|
106
|
+
recommendation: domainAdminCount > 10
|
|
107
|
+
? `Reduce Domain Admins from ${domainAdminCount} to ≤10`
|
|
108
|
+
: undefined,
|
|
109
|
+
framework: 'ANSSI',
|
|
110
|
+
control: 'R2',
|
|
111
|
+
}
|
|
112
|
+
: undefined,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function detectAnssiR3StrongAuth(users, domain, _includeDetails) {
|
|
116
|
+
const issues = [];
|
|
117
|
+
const functionalLevel = domain['domainFunctionalLevel'] || 0;
|
|
118
|
+
if (functionalLevel < 6) {
|
|
119
|
+
issues.push(`Domain functional level ${functionalLevel} is below 2012 R2 (6), limiting security features`);
|
|
120
|
+
}
|
|
121
|
+
const weakEncryptionUsers = users.filter((u) => {
|
|
122
|
+
const encTypes = u['msDS-SupportedEncryptionTypes'];
|
|
123
|
+
if (typeof encTypes !== 'number')
|
|
124
|
+
return false;
|
|
125
|
+
return (encTypes & 0x18) === 0 && (encTypes & 0x7) !== 0;
|
|
126
|
+
});
|
|
127
|
+
if (weakEncryptionUsers.length > 0) {
|
|
128
|
+
issues.push(`${weakEncryptionUsers.length} users with weak encryption (no AES)`);
|
|
129
|
+
}
|
|
130
|
+
const noPreAuthUsers = users.filter((u) => {
|
|
131
|
+
const uac = u.userAccountControl || 0;
|
|
132
|
+
return (uac & 0x400000) !== 0;
|
|
133
|
+
});
|
|
134
|
+
if (noPreAuthUsers.length > 0) {
|
|
135
|
+
issues.push(`${noPreAuthUsers.length} users without Kerberos pre-authentication`);
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
type: 'ANSSI_R3_STRONG_AUTH',
|
|
139
|
+
severity: 'medium',
|
|
140
|
+
category: 'compliance',
|
|
141
|
+
title: 'ANSSI R3 - Strong Authentication Issues',
|
|
142
|
+
description: 'Strong authentication mechanisms not fully enforced per ANSSI R3. Kerberos AES should be required, and weak encryption types disabled.',
|
|
143
|
+
count: issues.length > 0 ? 1 : 0,
|
|
144
|
+
details: issues.length > 0 ? { violations: issues, framework: 'ANSSI', control: 'R3' } : undefined,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function detectAnssiR4Logging(gpoSettings, _includeDetails) {
|
|
148
|
+
const issues = [];
|
|
149
|
+
if (!gpoSettings) {
|
|
150
|
+
issues.push('GPO settings not available for audit policy analysis');
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
if (gpoSettings.auditPolicies && gpoSettings.auditPolicies.length > 0) {
|
|
154
|
+
const audit = gpoSettings.auditPolicies;
|
|
155
|
+
const hasLogon = audit.some((p) => p.category.includes('Logon') && p.success && p.failure);
|
|
156
|
+
const hasAccountMgmt = audit.some((p) => p.category.includes('Account Management') && p.success && p.failure);
|
|
157
|
+
const hasPolicyChange = audit.some((p) => p.category.includes('Policy Change') && p.success && p.failure);
|
|
158
|
+
const hasPrivilegeUse = audit.some((p) => p.category.includes('Privilege Use') && p.success && p.failure);
|
|
159
|
+
if (!hasLogon)
|
|
160
|
+
issues.push('Logon events not fully audited');
|
|
161
|
+
if (!hasAccountMgmt)
|
|
162
|
+
issues.push('Account management not fully audited');
|
|
163
|
+
if (!hasPolicyChange)
|
|
164
|
+
issues.push('Policy changes not fully audited');
|
|
165
|
+
if (!hasPrivilegeUse)
|
|
166
|
+
issues.push('Privilege use not fully audited');
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
issues.push('Audit policy not configured');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
type: 'ANSSI_R4_LOGGING',
|
|
174
|
+
severity: 'medium',
|
|
175
|
+
category: 'compliance',
|
|
176
|
+
title: 'ANSSI R4 - Logging Non-Compliant',
|
|
177
|
+
description: 'Logging configuration does not meet ANSSI R4 recommendations. All security events should be audited with adequate log retention.',
|
|
178
|
+
count: issues.length > 0 ? 1 : 0,
|
|
179
|
+
details: issues.length > 0 ? { violations: issues, framework: 'ANSSI', control: 'R4' } : undefined,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function detectAnssiR5Segregation(users, computers, _includeDetails) {
|
|
183
|
+
const issues = [];
|
|
184
|
+
const privilegedGroups = ['Domain Admins', 'Enterprise Admins', 'Schema Admins'];
|
|
185
|
+
const admins = users.filter((u) => u.memberOf?.some((dn) => privilegedGroups.some((pg) => dn.includes(`CN=${pg}`))));
|
|
186
|
+
const serviceAccounts = users.filter((u) => {
|
|
187
|
+
const name = (u.sAMAccountName || '').toLowerCase();
|
|
188
|
+
return name.includes('svc') || name.includes('service') || name.startsWith('sa_');
|
|
189
|
+
});
|
|
190
|
+
const interactiveServiceAccounts = serviceAccounts.filter((u) => {
|
|
191
|
+
return u.enabled;
|
|
192
|
+
});
|
|
193
|
+
if (interactiveServiceAccounts.length > 0) {
|
|
194
|
+
issues.push(`${interactiveServiceAccounts.length} service accounts may allow interactive logon`);
|
|
195
|
+
}
|
|
196
|
+
const workstationsInServerOu = computers.filter((c) => {
|
|
197
|
+
const os = (0, entity_converter_1.ldapAttrToString)(c.operatingSystem);
|
|
198
|
+
const isWorkstation = /windows 10|windows 11|windows 7|windows 8/i.test(os);
|
|
199
|
+
const isInServerOu = /ou=servers|ou=server|ou=datacenter/i.test(c.dn);
|
|
200
|
+
return isWorkstation && isInServerOu;
|
|
201
|
+
});
|
|
202
|
+
if (workstationsInServerOu.length > 0) {
|
|
203
|
+
issues.push(`${workstationsInServerOu.length} workstations in server OUs (tier violation)`);
|
|
204
|
+
}
|
|
205
|
+
if (admins.length > 15) {
|
|
206
|
+
issues.push(`${admins.length} privileged accounts (recommend <15 for proper segregation)`);
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
type: 'ANSSI_R5_SEGREGATION',
|
|
210
|
+
severity: 'medium',
|
|
211
|
+
category: 'compliance',
|
|
212
|
+
title: 'ANSSI R5 - Segregation Issues',
|
|
213
|
+
description: 'Network and privilege segregation does not meet ANSSI R5 recommendations. Implement tiered administration model.',
|
|
214
|
+
count: issues.length > 0 ? 1 : 0,
|
|
215
|
+
details: issues.length > 0 ? { violations: issues, framework: 'ANSSI', control: 'R5' } : undefined,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function detectNistAc2AccountManagement(users, includeDetails) {
|
|
219
|
+
const issues = [];
|
|
220
|
+
const affectedUsers = [];
|
|
221
|
+
const now = Date.now();
|
|
222
|
+
const ninetyDaysAgo = now - 90 * 24 * 60 * 60 * 1000;
|
|
223
|
+
const inactiveAccounts = users.filter((u) => u.enabled && u.lastLogon && u.lastLogon.getTime() < ninetyDaysAgo);
|
|
224
|
+
if (inactiveAccounts.length > 0) {
|
|
225
|
+
issues.push({ issue: 'Inactive accounts (90+ days) still enabled', count: inactiveAccounts.length });
|
|
226
|
+
affectedUsers.push(...inactiveAccounts);
|
|
227
|
+
}
|
|
228
|
+
const neverLoggedOn = users.filter((u) => u.enabled && !u.lastLogon);
|
|
229
|
+
if (neverLoggedOn.length > 0) {
|
|
230
|
+
issues.push({ issue: 'Enabled accounts never logged on', count: neverLoggedOn.length });
|
|
231
|
+
affectedUsers.push(...neverLoggedOn.filter((u) => !affectedUsers.includes(u)));
|
|
232
|
+
}
|
|
233
|
+
const guestEnabled = users.filter((u) => u.sAMAccountName.toLowerCase() === 'guest' && u.enabled);
|
|
234
|
+
if (guestEnabled.length > 0) {
|
|
235
|
+
issues.push({ issue: 'Guest account enabled', count: 1 });
|
|
236
|
+
affectedUsers.push(...guestEnabled);
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
type: 'NIST_AC_2_ACCOUNT_MANAGEMENT',
|
|
240
|
+
severity: 'high',
|
|
241
|
+
category: 'compliance',
|
|
242
|
+
title: 'NIST AC-2 - Account Management Issues',
|
|
243
|
+
description: 'Account management does not comply with NIST AC-2. Inactive accounts should be disabled, guest account should be disabled.',
|
|
244
|
+
count: affectedUsers.length,
|
|
245
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(affectedUsers.slice(0, 50)) : undefined,
|
|
246
|
+
details: issues.length > 0 ? { violations: issues, framework: 'NIST', control: 'AC-2' } : undefined,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function detectNistAc6LeastPrivilege(users, groups, includeDetails) {
|
|
250
|
+
const issues = [];
|
|
251
|
+
const affectedUsers = [];
|
|
252
|
+
const sensitiveGroups = [
|
|
253
|
+
'Domain Admins',
|
|
254
|
+
'Enterprise Admins',
|
|
255
|
+
'Schema Admins',
|
|
256
|
+
'Administrators',
|
|
257
|
+
'Account Operators',
|
|
258
|
+
'Backup Operators',
|
|
259
|
+
'Server Operators',
|
|
260
|
+
'Print Operators',
|
|
261
|
+
];
|
|
262
|
+
const usersInMultipleSensitiveGroups = users.filter((u) => {
|
|
263
|
+
if (!u.memberOf)
|
|
264
|
+
return false;
|
|
265
|
+
const sensitiveCount = u.memberOf.filter((dn) => sensitiveGroups.some((sg) => dn.includes(`CN=${sg}`))).length;
|
|
266
|
+
return sensitiveCount > 1;
|
|
267
|
+
});
|
|
268
|
+
if (usersInMultipleSensitiveGroups.length > 0) {
|
|
269
|
+
issues.push({
|
|
270
|
+
issue: 'Users in multiple sensitive groups',
|
|
271
|
+
count: usersInMultipleSensitiveGroups.length,
|
|
272
|
+
});
|
|
273
|
+
affectedUsers.push(...usersInMultipleSensitiveGroups);
|
|
274
|
+
}
|
|
275
|
+
const domainAdmins = users.filter((u) => u.memberOf?.some((dn) => dn.includes('CN=Domain Admins')));
|
|
276
|
+
if (domainAdmins.length > 5) {
|
|
277
|
+
issues.push({
|
|
278
|
+
issue: `Excessive Domain Admins (${domainAdmins.length}, recommend ≤5)`,
|
|
279
|
+
count: domainAdmins.length,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
const oversizedPrivilegedGroups = groups.filter((g) => {
|
|
283
|
+
const isSensitive = sensitiveGroups.some((sg) => g.sAMAccountName?.toLowerCase() === sg.toLowerCase());
|
|
284
|
+
return isSensitive && (g.member?.length || 0) > 10;
|
|
285
|
+
});
|
|
286
|
+
if (oversizedPrivilegedGroups.length > 0) {
|
|
287
|
+
issues.push({
|
|
288
|
+
issue: 'Privileged groups with >10 members',
|
|
289
|
+
count: oversizedPrivilegedGroups.length,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
type: 'NIST_AC_6_LEAST_PRIVILEGE',
|
|
294
|
+
severity: 'high',
|
|
295
|
+
category: 'compliance',
|
|
296
|
+
title: 'NIST AC-6 - Least Privilege Violations',
|
|
297
|
+
description: 'Privilege assignments do not comply with NIST AC-6 least privilege principle. Review and reduce excessive privileges.',
|
|
298
|
+
count: affectedUsers.length + oversizedPrivilegedGroups.length,
|
|
299
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(affectedUsers.slice(0, 50)) : undefined,
|
|
300
|
+
details: issues.length > 0 ? { violations: issues, framework: 'NIST', control: 'AC-6' } : undefined,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function detectNistIa5Authenticator(domain, users, _includeDetails) {
|
|
304
|
+
const issues = [];
|
|
305
|
+
const policy = domain['passwordPolicy'];
|
|
306
|
+
if (policy) {
|
|
307
|
+
if (!policy.complexityEnabled) {
|
|
308
|
+
issues.push('Password complexity not enabled');
|
|
309
|
+
}
|
|
310
|
+
if (policy.minPwdLength < 14) {
|
|
311
|
+
issues.push(`Minimum password length ${policy.minPwdLength} < 14 (NIST recommends 14+)`);
|
|
312
|
+
}
|
|
313
|
+
if (policy.lockoutThreshold === 0) {
|
|
314
|
+
issues.push('Account lockout not configured');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
const noPasswordRequired = users.filter((u) => {
|
|
318
|
+
const uac = u.userAccountControl || 0;
|
|
319
|
+
return (uac & 0x20) !== 0;
|
|
320
|
+
});
|
|
321
|
+
if (noPasswordRequired.length > 0) {
|
|
322
|
+
issues.push(`${noPasswordRequired.length} accounts with password not required`);
|
|
323
|
+
}
|
|
324
|
+
const reversibleEncryption = users.filter((u) => {
|
|
325
|
+
const uac = u.userAccountControl || 0;
|
|
326
|
+
return (uac & 0x80) !== 0;
|
|
327
|
+
});
|
|
328
|
+
if (reversibleEncryption.length > 0) {
|
|
329
|
+
issues.push(`${reversibleEncryption.length} accounts with reversible encryption`);
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
type: 'NIST_IA_5_AUTHENTICATOR',
|
|
333
|
+
severity: 'medium',
|
|
334
|
+
category: 'compliance',
|
|
335
|
+
title: 'NIST IA-5 - Authenticator Management Issues',
|
|
336
|
+
description: 'Authenticator management does not comply with NIST IA-5. Password policies should enforce complexity and secure storage.',
|
|
337
|
+
count: issues.length > 0 ? 1 : 0,
|
|
338
|
+
details: issues.length > 0 ? { violations: issues, framework: 'NIST', control: 'IA-5' } : undefined,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
function detectNistAu2AuditEvents(gpoSettings, _includeDetails) {
|
|
342
|
+
const issues = [];
|
|
343
|
+
if (!gpoSettings?.auditPolicies || gpoSettings.auditPolicies.length === 0) {
|
|
344
|
+
issues.push('Audit policy not configured or not readable');
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
const audit = gpoSettings.auditPolicies;
|
|
348
|
+
const requiredCategories = [
|
|
349
|
+
'Account Logon',
|
|
350
|
+
'Account Management',
|
|
351
|
+
'Policy Change',
|
|
352
|
+
'System',
|
|
353
|
+
'Object Access',
|
|
354
|
+
];
|
|
355
|
+
for (const category of requiredCategories) {
|
|
356
|
+
const hasCategory = audit.some((p) => p.category.includes(category) && p.success && p.failure);
|
|
357
|
+
if (!hasCategory) {
|
|
358
|
+
issues.push(`${category} not fully audited (success and failure)`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
type: 'NIST_AU_2_AUDIT_EVENTS',
|
|
364
|
+
severity: 'medium',
|
|
365
|
+
category: 'compliance',
|
|
366
|
+
title: 'NIST AU-2 - Audit Events Non-Compliant',
|
|
367
|
+
description: 'Audit event configuration does not comply with NIST AU-2. All security-relevant events should be audited.',
|
|
368
|
+
count: issues.length > 0 ? 1 : 0,
|
|
369
|
+
details: issues.length > 0 ? { violations: issues, framework: 'NIST', control: 'AU-2' } : undefined,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
function detectCisPasswordPolicy(domain, _includeDetails) {
|
|
373
|
+
const issues = [];
|
|
374
|
+
const policy = domain['passwordPolicy'];
|
|
375
|
+
if (policy) {
|
|
376
|
+
if (policy.minPwdLength < 14) {
|
|
377
|
+
issues.push(`Minimum password length ${policy.minPwdLength} < 14 (CIS 1.1.1)`);
|
|
378
|
+
}
|
|
379
|
+
if (policy.pwdHistoryLength < 24) {
|
|
380
|
+
issues.push(`Password history ${policy.pwdHistoryLength} < 24 (CIS 1.1.2)`);
|
|
381
|
+
}
|
|
382
|
+
if (policy.maxPwdAge > 365) {
|
|
383
|
+
issues.push(`Max password age ${policy.maxPwdAge} > 365 days (CIS 1.1.3)`);
|
|
384
|
+
}
|
|
385
|
+
if (policy.minPwdAge < 1) {
|
|
386
|
+
issues.push(`Min password age ${policy.minPwdAge} < 1 day (CIS 1.1.4)`);
|
|
387
|
+
}
|
|
388
|
+
if (!policy.complexityEnabled) {
|
|
389
|
+
issues.push('Password complexity not enabled (CIS 1.1.5)');
|
|
390
|
+
}
|
|
391
|
+
if (policy.reversibleEncryption) {
|
|
392
|
+
issues.push('Reversible encryption enabled (CIS 1.1.6)');
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
issues.push('Password policy not available');
|
|
397
|
+
}
|
|
398
|
+
return {
|
|
399
|
+
type: 'CIS_PASSWORD_POLICY',
|
|
400
|
+
severity: 'high',
|
|
401
|
+
category: 'compliance',
|
|
402
|
+
title: 'CIS Benchmark - Password Policy Non-Compliant',
|
|
403
|
+
description: 'Password policy does not meet CIS Benchmark recommendations. Review and update password policy settings.',
|
|
404
|
+
count: issues.length > 0 ? 1 : 0,
|
|
405
|
+
details: issues.length > 0 ? { violations: issues, framework: 'CIS', control: '1.1.x' } : undefined,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
function detectCisNetworkSecurity(gpoSettings, _includeDetails) {
|
|
409
|
+
const issues = [];
|
|
410
|
+
if (gpoSettings) {
|
|
411
|
+
if (gpoSettings.smbv1ServerEnabled || gpoSettings.smbv1ClientEnabled) {
|
|
412
|
+
issues.push('SMBv1 enabled (CIS 2.3.7.1 - Disable SMBv1)');
|
|
413
|
+
}
|
|
414
|
+
if (gpoSettings.ldapServerIntegrity !== undefined && gpoSettings.ldapServerIntegrity < 2) {
|
|
415
|
+
issues.push('LDAP signing not required (CIS 2.3.7.2)');
|
|
416
|
+
}
|
|
417
|
+
if (gpoSettings.ldapChannelBinding !== undefined && gpoSettings.ldapChannelBinding < 2) {
|
|
418
|
+
issues.push('LDAP channel binding not required (CIS 2.3.7.3)');
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
issues.push('GPO settings not available for network security analysis');
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
type: 'CIS_NETWORK_SECURITY',
|
|
426
|
+
severity: 'medium',
|
|
427
|
+
category: 'compliance',
|
|
428
|
+
title: 'CIS Benchmark - Network Security Non-Compliant',
|
|
429
|
+
description: 'Network security settings do not meet CIS Benchmark recommendations. SMBv1 should be disabled, LDAP signing required.',
|
|
430
|
+
count: issues.length > 0 ? 1 : 0,
|
|
431
|
+
details: issues.length > 0 ? { violations: issues, framework: 'CIS', control: '2.3.7.x' } : undefined,
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
function detectCisUserRights(users, groups, _includeDetails) {
|
|
435
|
+
const issues = [];
|
|
436
|
+
const sensitiveGroups = ['Administrators', 'Domain Admins', 'Enterprise Admins'];
|
|
437
|
+
const problematicMembers = ['Everyone', 'Authenticated Users', 'ANONYMOUS LOGON'];
|
|
438
|
+
for (const group of groups) {
|
|
439
|
+
const isSensitive = sensitiveGroups.some((sg) => group.sAMAccountName?.toLowerCase() === sg.toLowerCase());
|
|
440
|
+
if (!isSensitive)
|
|
441
|
+
continue;
|
|
442
|
+
const hasProblematicMember = group.member?.some((memberDn) => problematicMembers.some((pm) => memberDn.toLowerCase().includes(pm.toLowerCase())));
|
|
443
|
+
if (hasProblematicMember) {
|
|
444
|
+
issues.push(`${group.sAMAccountName} contains well-known security principal (CIS 2.3.11.x)`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
const trustedForDelegation = users.filter((u) => {
|
|
448
|
+
const uac = u.userAccountControl || 0;
|
|
449
|
+
return (uac & 0x80000) !== 0;
|
|
450
|
+
});
|
|
451
|
+
if (trustedForDelegation.length > 0) {
|
|
452
|
+
issues.push(`${trustedForDelegation.length} users trusted for delegation (CIS 2.3.11.x)`);
|
|
453
|
+
}
|
|
454
|
+
return {
|
|
455
|
+
type: 'CIS_USER_RIGHTS',
|
|
456
|
+
severity: 'medium',
|
|
457
|
+
category: 'compliance',
|
|
458
|
+
title: 'CIS Benchmark - User Rights Issues',
|
|
459
|
+
description: 'User rights assignments do not meet CIS Benchmark recommendations. Review delegation and group memberships.',
|
|
460
|
+
count: issues.length > 0 ? 1 : 0,
|
|
461
|
+
details: issues.length > 0 ? { violations: issues, framework: 'CIS', control: '2.3.11.x' } : undefined,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
function detectDisaAccountPolicies(domain, users, _includeDetails) {
|
|
465
|
+
const issues = [];
|
|
466
|
+
const policy = domain['passwordPolicy'];
|
|
467
|
+
if (policy) {
|
|
468
|
+
if (policy.minPwdLength < 15) {
|
|
469
|
+
issues.push(`Min password length ${policy.minPwdLength} < 15 (V-220857)`);
|
|
470
|
+
}
|
|
471
|
+
if (policy.lockoutDuration > 0 && policy.lockoutDuration < 15) {
|
|
472
|
+
issues.push(`Lockout duration ${policy.lockoutDuration} min < 15 min (V-220857)`);
|
|
473
|
+
}
|
|
474
|
+
if (policy.lockoutThreshold > 3) {
|
|
475
|
+
issues.push(`Lockout threshold ${policy.lockoutThreshold} > 3 (V-220857)`);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
const noExpiration = users.filter((u) => {
|
|
479
|
+
const uac = u.userAccountControl || 0;
|
|
480
|
+
const hasNoExpire = (uac & 0x10000) !== 0;
|
|
481
|
+
const isServiceAccount = u.sAMAccountName.toLowerCase().includes('svc') ||
|
|
482
|
+
u.sAMAccountName.toLowerCase().includes('service');
|
|
483
|
+
return hasNoExpire && !isServiceAccount;
|
|
484
|
+
});
|
|
485
|
+
if (noExpiration.length > 0) {
|
|
486
|
+
issues.push(`${noExpiration.length} non-service accounts with password never expires (V-220857)`);
|
|
487
|
+
}
|
|
488
|
+
return {
|
|
489
|
+
type: 'DISA_ACCOUNT_POLICIES',
|
|
490
|
+
severity: 'high',
|
|
491
|
+
category: 'compliance',
|
|
492
|
+
title: 'DISA STIG - Account Policies Non-Compliant',
|
|
493
|
+
description: 'Account policies do not comply with DISA STIG V-220857. Review password and lockout policy settings.',
|
|
494
|
+
count: issues.length > 0 ? 1 : 0,
|
|
495
|
+
details: issues.length > 0 ? { violations: issues, framework: 'DISA', control: 'V-220857' } : undefined,
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
function detectDisaAuditPolicies(gpoSettings, _includeDetails) {
|
|
499
|
+
const issues = [];
|
|
500
|
+
if (!gpoSettings?.auditPolicies || gpoSettings.auditPolicies.length === 0) {
|
|
501
|
+
issues.push('Audit policy not configured (V-220858)');
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
const audit = gpoSettings.auditPolicies;
|
|
505
|
+
const disaRequirements = [
|
|
506
|
+
{ name: 'Account Logon (Success)', check: (a) => a.some((p) => p.category.includes('Logon') && p.success) },
|
|
507
|
+
{ name: 'Account Logon (Failure)', check: (a) => a.some((p) => p.category.includes('Logon') && p.failure) },
|
|
508
|
+
{ name: 'Account Management (Success)', check: (a) => a.some((p) => p.category.includes('Account Management') && p.success) },
|
|
509
|
+
{ name: 'Account Management (Failure)', check: (a) => a.some((p) => p.category.includes('Account Management') && p.failure) },
|
|
510
|
+
{ name: 'Policy Change (Success)', check: (a) => a.some((p) => p.category.includes('Policy Change') && p.success) },
|
|
511
|
+
{ name: 'Policy Change (Failure)', check: (a) => a.some((p) => p.category.includes('Policy Change') && p.failure) },
|
|
512
|
+
{ name: 'Privilege Use (Success)', check: (a) => a.some((p) => p.category.includes('Privilege Use') && p.success) },
|
|
513
|
+
{ name: 'Privilege Use (Failure)', check: (a) => a.some((p) => p.category.includes('Privilege Use') && p.failure) },
|
|
514
|
+
];
|
|
515
|
+
for (const req of disaRequirements) {
|
|
516
|
+
if (!req.check(audit)) {
|
|
517
|
+
issues.push(`${req.name} audit not enabled (V-220858)`);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return {
|
|
522
|
+
type: 'DISA_AUDIT_POLICIES',
|
|
523
|
+
severity: 'high',
|
|
524
|
+
category: 'compliance',
|
|
525
|
+
title: 'DISA STIG - Audit Policies Non-Compliant',
|
|
526
|
+
description: 'Audit policies do not comply with DISA STIG V-220858. All required audit categories should be enabled.',
|
|
527
|
+
count: issues.length > 0 ? 1 : 0,
|
|
528
|
+
details: issues.length > 0 ? { violations: issues, framework: 'DISA', control: 'V-220858' } : undefined,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
function detectMfaNotEnforced(users, includeDetails) {
|
|
532
|
+
const privilegedGroups = ['Domain Admins', 'Enterprise Admins', 'Schema Admins', 'Administrators'];
|
|
533
|
+
const privilegedUsers = users.filter((u) => {
|
|
534
|
+
if (!u.memberOf)
|
|
535
|
+
return false;
|
|
536
|
+
return u.memberOf.some((dn) => privilegedGroups.some((pg) => dn.includes(`CN=${pg}`)));
|
|
537
|
+
});
|
|
538
|
+
const noMfa = privilegedUsers.filter((u) => {
|
|
539
|
+
const uac = u.userAccountControl || 0;
|
|
540
|
+
return (uac & 0x40000) === 0;
|
|
541
|
+
});
|
|
542
|
+
return {
|
|
543
|
+
type: 'MFA_NOT_ENFORCED',
|
|
544
|
+
severity: 'high',
|
|
545
|
+
category: 'compliance',
|
|
546
|
+
title: 'MFA Not Enforced for Privileged Accounts',
|
|
547
|
+
description: 'Privileged accounts do not require multi-factor authentication (smartcard). Required by PCI-DSS 8.3, SOC2 CC6.1, ISO27001 A.9.4.2.',
|
|
548
|
+
count: noMfa.length,
|
|
549
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(noMfa.slice(0, 50)) : undefined,
|
|
550
|
+
details: noMfa.length > 0 ? {
|
|
551
|
+
frameworks: ['PCI-DSS', 'SOC2', 'ISO27001'],
|
|
552
|
+
controls: ['8.3', 'CC6.1', 'A.9.4.2'],
|
|
553
|
+
recommendation: 'Enable smartcard requirement for all privileged accounts',
|
|
554
|
+
} : undefined,
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
function detectBackupNotVerified(domain, _includeDetails) {
|
|
558
|
+
const issues = [];
|
|
559
|
+
const tombstoneLifetime = domain['tombstoneLifetime'] || 180;
|
|
560
|
+
if (tombstoneLifetime === 180 || tombstoneLifetime === 60) {
|
|
561
|
+
issues.push(`Tombstone lifetime is default (${tombstoneLifetime} days) - backup policy may not be configured`);
|
|
562
|
+
}
|
|
563
|
+
const lastBackup = domain['lastBackupTime'];
|
|
564
|
+
if (!lastBackup) {
|
|
565
|
+
issues.push('No backup metadata found - verify AD backup is configured and tested');
|
|
566
|
+
}
|
|
567
|
+
return {
|
|
568
|
+
type: 'BACKUP_AD_NOT_VERIFIED',
|
|
569
|
+
severity: 'high',
|
|
570
|
+
category: 'compliance',
|
|
571
|
+
title: 'AD Backup Not Verified',
|
|
572
|
+
description: 'Active Directory backup configuration cannot be verified. Required by SOC2 A1.2, DORA Article 11, ISO27001 A.12.3.1.',
|
|
573
|
+
count: issues.length > 0 ? 1 : 0,
|
|
574
|
+
details: issues.length > 0 ? {
|
|
575
|
+
violations: issues,
|
|
576
|
+
frameworks: ['SOC2', 'DORA', 'ISO27001'],
|
|
577
|
+
controls: ['A1.2', 'Art.11', 'A.12.3.1'],
|
|
578
|
+
recommendation: 'Configure and regularly test AD system state backups',
|
|
579
|
+
} : undefined,
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
function detectAuditLogRetentionShort(gpoSettings, _includeDetails) {
|
|
583
|
+
const issues = [];
|
|
584
|
+
if (!gpoSettings?.auditPolicies || gpoSettings.auditPolicies.length === 0) {
|
|
585
|
+
issues.push('Audit policy not configured - log retention cannot be verified');
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
const hasSecurityAudit = gpoSettings.auditPolicies.some((p) => p.category.includes('Logon') || p.category.includes('Account'));
|
|
589
|
+
if (!hasSecurityAudit) {
|
|
590
|
+
issues.push('Security events not being audited - retention policy meaningless without logging');
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (issues.length === 0) {
|
|
594
|
+
issues.push('Log retention period should be verified manually (1 year minimum for compliance)');
|
|
595
|
+
}
|
|
596
|
+
return {
|
|
597
|
+
type: 'AUDIT_LOG_RETENTION_SHORT',
|
|
598
|
+
severity: 'high',
|
|
599
|
+
category: 'compliance',
|
|
600
|
+
title: 'Audit Log Retention Below Requirements',
|
|
601
|
+
description: 'Audit log retention period may not meet compliance requirements (1 year minimum). Required by SOX Section 802, HIPAA 164.312(b), PCI-DSS 10.7.',
|
|
602
|
+
count: issues.length > 0 ? 1 : 0,
|
|
603
|
+
details: issues.length > 0 ? {
|
|
604
|
+
violations: issues,
|
|
605
|
+
frameworks: ['SOX', 'HIPAA', 'PCI-DSS'],
|
|
606
|
+
controls: ['Section 802', '164.312(b)', '10.7'],
|
|
607
|
+
recommendation: 'Configure log retention for minimum 1 year with SIEM integration',
|
|
608
|
+
} : undefined,
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
function detectPrivilegedAccessReviewMissing(users, groups, _includeDetails) {
|
|
612
|
+
const issues = [];
|
|
613
|
+
const NINETY_DAYS_MS = 90 * 24 * 60 * 60 * 1000;
|
|
614
|
+
const now = Date.now();
|
|
615
|
+
const privilegedGroupNames = ['Domain Admins', 'Enterprise Admins', 'Schema Admins', 'Administrators'];
|
|
616
|
+
for (const group of groups) {
|
|
617
|
+
if (!privilegedGroupNames.some(pg => group.sAMAccountName?.toLowerCase() === pg.toLowerCase())) {
|
|
618
|
+
continue;
|
|
619
|
+
}
|
|
620
|
+
const groupChanged = group['whenChanged'];
|
|
621
|
+
if (groupChanged && (now - groupChanged.getTime()) > NINETY_DAYS_MS) {
|
|
622
|
+
const memberCount = group.member?.length || 0;
|
|
623
|
+
if (memberCount > 0) {
|
|
624
|
+
issues.push(`${group.sAMAccountName} (${memberCount} members) not reviewed in 90+ days`);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
const privilegedUsers = users.filter((u) => {
|
|
629
|
+
if (!u.memberOf)
|
|
630
|
+
return false;
|
|
631
|
+
return u.memberOf.some((dn) => privilegedGroupNames.some((pg) => dn.includes(`CN=${pg}`)));
|
|
632
|
+
});
|
|
633
|
+
const staleAdmins = privilegedUsers.filter((u) => {
|
|
634
|
+
if (!u.lastLogon)
|
|
635
|
+
return true;
|
|
636
|
+
return (now - u.lastLogon.getTime()) > NINETY_DAYS_MS;
|
|
637
|
+
});
|
|
638
|
+
if (staleAdmins.length > 0) {
|
|
639
|
+
issues.push(`${staleAdmins.length} privileged accounts inactive for 90+ days`);
|
|
640
|
+
}
|
|
641
|
+
return {
|
|
642
|
+
type: 'PRIVILEGED_ACCESS_REVIEW_MISSING',
|
|
643
|
+
severity: 'medium',
|
|
644
|
+
category: 'compliance',
|
|
645
|
+
title: 'Privileged Access Review Missing',
|
|
646
|
+
description: 'Privileged access has not been reviewed recently. Required by SOX Section 404, ISO27001 A.9.2.5, SOC2 CC6.2.',
|
|
647
|
+
count: issues.length > 0 ? 1 : 0,
|
|
648
|
+
details: issues.length > 0 ? {
|
|
649
|
+
violations: issues,
|
|
650
|
+
frameworks: ['SOX', 'ISO27001', 'SOC2'],
|
|
651
|
+
controls: ['Section 404', 'A.9.2.5', 'CC6.2'],
|
|
652
|
+
recommendation: 'Implement quarterly privileged access reviews with documented approval',
|
|
653
|
+
} : undefined,
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
function detectDataClassificationMissing(domain, _includeDetails) {
|
|
657
|
+
const issues = [];
|
|
658
|
+
const domainDescription = domain['description'] || '';
|
|
659
|
+
const hasClassificationKeywords = /confidential|restricted|internal|public|sensitive|pii|phi|pci/i.test(domainDescription);
|
|
660
|
+
if (!hasClassificationKeywords) {
|
|
661
|
+
issues.push('Domain description does not indicate data classification policy');
|
|
662
|
+
}
|
|
663
|
+
const msExchVersion = domain['msExchVersion'];
|
|
664
|
+
if (msExchVersion) {
|
|
665
|
+
issues.push('Exchange detected - email data classification policy required for GDPR/HIPAA');
|
|
666
|
+
}
|
|
667
|
+
return {
|
|
668
|
+
type: 'DATA_CLASSIFICATION_MISSING',
|
|
669
|
+
severity: 'medium',
|
|
670
|
+
category: 'compliance',
|
|
671
|
+
title: 'Data Classification Not Implemented',
|
|
672
|
+
description: 'Data classification scheme not detected in AD structure. Required by GDPR Article 30, ISO27001 A.8.2.1, HIPAA 164.312.',
|
|
673
|
+
count: issues.length > 0 ? 1 : 0,
|
|
674
|
+
details: issues.length > 0 ? {
|
|
675
|
+
violations: issues,
|
|
676
|
+
frameworks: ['GDPR', 'ISO27001', 'HIPAA'],
|
|
677
|
+
controls: ['Art.30', 'A.8.2.1', '164.312'],
|
|
678
|
+
recommendation: 'Implement data classification scheme using OU structure and object attributes',
|
|
679
|
+
} : undefined,
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
function detectChangeManagementBypass(users, groups, _includeDetails) {
|
|
683
|
+
const issues = [];
|
|
684
|
+
const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
|
|
685
|
+
const now = Date.now();
|
|
686
|
+
const privilegedGroupNames = ['Domain Admins', 'Enterprise Admins', 'Schema Admins'];
|
|
687
|
+
for (const group of groups) {
|
|
688
|
+
if (!privilegedGroupNames.some(pg => group.sAMAccountName?.toLowerCase() === pg.toLowerCase())) {
|
|
689
|
+
continue;
|
|
690
|
+
}
|
|
691
|
+
const groupChanged = group['whenChanged'];
|
|
692
|
+
if (groupChanged && (now - groupChanged.getTime()) < SEVEN_DAYS_MS) {
|
|
693
|
+
issues.push(`${group.sAMAccountName} modified in last 7 days - verify change request exists`);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
const recentAdmins = users.filter((u) => {
|
|
697
|
+
if (!u.memberOf?.some((dn) => privilegedGroupNames.some((pg) => dn.includes(`CN=${pg}`)))) {
|
|
698
|
+
return false;
|
|
699
|
+
}
|
|
700
|
+
const created = u['whenCreated'];
|
|
701
|
+
return created && (now - created.getTime()) < SEVEN_DAYS_MS;
|
|
702
|
+
});
|
|
703
|
+
if (recentAdmins.length > 0) {
|
|
704
|
+
issues.push(`${recentAdmins.length} privileged accounts created in last 7 days - verify change requests`);
|
|
705
|
+
}
|
|
706
|
+
return {
|
|
707
|
+
type: 'CHANGE_MANAGEMENT_BYPASS',
|
|
708
|
+
severity: 'high',
|
|
709
|
+
category: 'compliance',
|
|
710
|
+
title: 'Potential Change Management Bypass',
|
|
711
|
+
description: 'Recent privileged changes detected - verify change management process was followed. Required by SOX Section 404, ISO27001 A.12.1.2, SOC2 CC8.1.',
|
|
712
|
+
count: issues.length > 0 ? 1 : 0,
|
|
713
|
+
details: issues.length > 0 ? {
|
|
714
|
+
violations: issues,
|
|
715
|
+
frameworks: ['SOX', 'ISO27001', 'SOC2'],
|
|
716
|
+
controls: ['Section 404', 'A.12.1.2', 'CC8.1'],
|
|
717
|
+
recommendation: 'Implement privileged change approval workflow with audit trail',
|
|
718
|
+
} : undefined,
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
function detectVendorAccountUnmonitored(users, includeDetails) {
|
|
722
|
+
const vendorPatterns = [
|
|
723
|
+
/vendor/i, /external/i, /contractor/i, /consultant/i,
|
|
724
|
+
/partner/i, /third.?party/i, /supplier/i, /^ext[_-]/i,
|
|
725
|
+
/^v[_-]/i, /^tmp[_-]/i, /^temp[_-]/i
|
|
726
|
+
];
|
|
727
|
+
const vendorAccounts = users.filter((u) => {
|
|
728
|
+
const name = u.sAMAccountName || '';
|
|
729
|
+
const desc = u['description'] || '';
|
|
730
|
+
const displayName = u.displayName || '';
|
|
731
|
+
return vendorPatterns.some(p => p.test(name) || p.test(desc) || p.test(displayName));
|
|
732
|
+
});
|
|
733
|
+
const unmonitoredVendors = vendorAccounts.filter((u) => {
|
|
734
|
+
const accountExpires = u['accountExpires'];
|
|
735
|
+
let hasExpiry = false;
|
|
736
|
+
if (accountExpires) {
|
|
737
|
+
if (typeof accountExpires === 'bigint') {
|
|
738
|
+
hasExpiry = accountExpires !== BigInt('9223372036854775807') && accountExpires !== BigInt(0);
|
|
739
|
+
}
|
|
740
|
+
else if (typeof accountExpires === 'number') {
|
|
741
|
+
hasExpiry = accountExpires !== 9223372036854775807 && accountExpires !== 0;
|
|
742
|
+
}
|
|
743
|
+
else if (accountExpires instanceof Date) {
|
|
744
|
+
hasExpiry = accountExpires.getTime() > Date.now();
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
const lastLogon = u.lastLogon;
|
|
748
|
+
const NINETY_DAYS_MS = 90 * 24 * 60 * 60 * 1000;
|
|
749
|
+
const isActive = lastLogon && (Date.now() - lastLogon.getTime()) < NINETY_DAYS_MS;
|
|
750
|
+
return !hasExpiry && isActive;
|
|
751
|
+
});
|
|
752
|
+
return {
|
|
753
|
+
type: 'VENDOR_ACCOUNT_UNMONITORED',
|
|
754
|
+
severity: 'medium',
|
|
755
|
+
category: 'compliance',
|
|
756
|
+
title: 'Vendor Accounts Not Properly Monitored',
|
|
757
|
+
description: 'Third-party/vendor accounts detected without proper expiration or monitoring controls. Required by DORA Article 28, ISO27001 A.15.1.1, SOC2 CC9.2.',
|
|
758
|
+
count: unmonitoredVendors.length,
|
|
759
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(unmonitoredVendors.slice(0, 50)) : undefined,
|
|
760
|
+
details: unmonitoredVendors.length > 0 ? {
|
|
761
|
+
totalVendorAccounts: vendorAccounts.length,
|
|
762
|
+
unmonitoredCount: unmonitoredVendors.length,
|
|
763
|
+
frameworks: ['DORA', 'ISO27001', 'SOC2'],
|
|
764
|
+
controls: ['Art.28', 'A.15.1.1', 'CC9.2'],
|
|
765
|
+
recommendation: 'Set expiration dates and enable enhanced logging for all vendor accounts',
|
|
766
|
+
} : undefined,
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
function detectEncryptionAtRestDisabled(computers, _includeDetails) {
|
|
770
|
+
const domainControllers = computers.filter((c) => {
|
|
771
|
+
const uac = c.userAccountControl || 0;
|
|
772
|
+
return (uac & 0x2000) !== 0;
|
|
773
|
+
});
|
|
774
|
+
const dcsWithoutBitLocker = domainControllers.filter((dc) => {
|
|
775
|
+
const hasBitLocker = dc['msFVE-RecoveryPassword'] || dc['msFVE-KeyPackage'];
|
|
776
|
+
return !hasBitLocker;
|
|
777
|
+
});
|
|
778
|
+
const servers = computers.filter((c) => {
|
|
779
|
+
const os = (0, entity_converter_1.ldapAttrToString)(c.operatingSystem).toLowerCase();
|
|
780
|
+
return os.includes('server') && !domainControllers.includes(c);
|
|
781
|
+
});
|
|
782
|
+
const serversWithoutBitLocker = servers.filter((s) => {
|
|
783
|
+
const hasBitLocker = s['msFVE-RecoveryPassword'] || s['msFVE-KeyPackage'];
|
|
784
|
+
return !hasBitLocker;
|
|
785
|
+
});
|
|
786
|
+
const issues = [];
|
|
787
|
+
if (dcsWithoutBitLocker.length > 0) {
|
|
788
|
+
issues.push(`${dcsWithoutBitLocker.length}/${domainControllers.length} Domain Controllers without BitLocker`);
|
|
789
|
+
}
|
|
790
|
+
if (serversWithoutBitLocker.length > 0 && serversWithoutBitLocker.length === servers.length) {
|
|
791
|
+
issues.push(`No servers have BitLocker recovery stored in AD`);
|
|
792
|
+
}
|
|
793
|
+
return {
|
|
794
|
+
type: 'ENCRYPTION_AT_REST_DISABLED',
|
|
795
|
+
severity: 'high',
|
|
796
|
+
category: 'compliance',
|
|
797
|
+
title: 'Encryption at Rest Not Deployed',
|
|
798
|
+
description: 'BitLocker encryption not detected on domain controllers or servers. Required by PCI-DSS 3.4, HIPAA 164.312(a)(2)(iv), ISO27001 A.10.1.1.',
|
|
799
|
+
count: dcsWithoutBitLocker.length,
|
|
800
|
+
details: issues.length > 0 ? {
|
|
801
|
+
violations: issues,
|
|
802
|
+
domainControllers: domainControllers.length,
|
|
803
|
+
dcsWithBitLocker: domainControllers.length - dcsWithoutBitLocker.length,
|
|
804
|
+
frameworks: ['PCI-DSS', 'HIPAA', 'ISO27001'],
|
|
805
|
+
controls: ['3.4', '164.312(a)(2)(iv)', 'A.10.1.1'],
|
|
806
|
+
recommendation: 'Deploy BitLocker on all domain controllers and servers with AD key backup',
|
|
807
|
+
} : undefined,
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
function detectComplianceScore(findings, _includeDetails) {
|
|
811
|
+
const anssi = { total: 5, passed: 0 };
|
|
812
|
+
const nist = { total: 4, passed: 0 };
|
|
813
|
+
const cis = { total: 3, passed: 0 };
|
|
814
|
+
const disa = { total: 2, passed: 0 };
|
|
815
|
+
const industry = { total: 8, passed: 0 };
|
|
816
|
+
const industryTypes = [
|
|
817
|
+
'MFA_NOT_ENFORCED',
|
|
818
|
+
'BACKUP_AD_NOT_VERIFIED',
|
|
819
|
+
'AUDIT_LOG_RETENTION_SHORT',
|
|
820
|
+
'PRIVILEGED_ACCESS_REVIEW_MISSING',
|
|
821
|
+
'DATA_CLASSIFICATION_MISSING',
|
|
822
|
+
'CHANGE_MANAGEMENT_BYPASS',
|
|
823
|
+
'VENDOR_ACCOUNT_UNMONITORED',
|
|
824
|
+
'ENCRYPTION_AT_REST_DISABLED',
|
|
825
|
+
];
|
|
826
|
+
const complianceFindings = findings.filter((f) => f.category === 'compliance');
|
|
827
|
+
for (const finding of complianceFindings) {
|
|
828
|
+
if (finding.count === 0) {
|
|
829
|
+
if (finding.type.startsWith('ANSSI_'))
|
|
830
|
+
anssi.passed++;
|
|
831
|
+
else if (finding.type.startsWith('NIST_'))
|
|
832
|
+
nist.passed++;
|
|
833
|
+
else if (finding.type.startsWith('CIS_'))
|
|
834
|
+
cis.passed++;
|
|
835
|
+
else if (finding.type.startsWith('DISA_'))
|
|
836
|
+
disa.passed++;
|
|
837
|
+
else if (industryTypes.includes(finding.type))
|
|
838
|
+
industry.passed++;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
const totalControls = anssi.total + nist.total + cis.total + disa.total + industry.total;
|
|
842
|
+
const passedControls = anssi.passed + nist.passed + cis.passed + disa.passed + industry.passed;
|
|
843
|
+
const compliancePercentage = Math.round((passedControls / totalControls) * 100);
|
|
844
|
+
return {
|
|
845
|
+
type: 'COMPLIANCE_SCORE',
|
|
846
|
+
severity: 'low',
|
|
847
|
+
category: 'compliance',
|
|
848
|
+
title: 'Compliance Score Summary',
|
|
849
|
+
description: `Overall compliance score: ${compliancePercentage}%. This represents adherence to ANSSI, NIST, CIS, DISA, and industry frameworks (PCI-DSS, SOC2, GDPR, SOX, DORA, HIPAA, ISO27001).`,
|
|
850
|
+
count: totalControls - passedControls,
|
|
851
|
+
details: {
|
|
852
|
+
score: compliancePercentage,
|
|
853
|
+
frameworks: {
|
|
854
|
+
ANSSI: `${anssi.passed}/${anssi.total}`,
|
|
855
|
+
NIST: `${nist.passed}/${nist.total}`,
|
|
856
|
+
CIS: `${cis.passed}/${cis.total}`,
|
|
857
|
+
DISA: `${disa.passed}/${disa.total}`,
|
|
858
|
+
'Industry (PCI/SOC2/GDPR/SOX/DORA/HIPAA/ISO)': `${industry.passed}/${industry.total}`,
|
|
859
|
+
},
|
|
860
|
+
passedControls,
|
|
861
|
+
totalControls,
|
|
862
|
+
recommendation: compliancePercentage < 70
|
|
863
|
+
? 'Compliance score is below 70%. Prioritize addressing high-severity compliance gaps.'
|
|
864
|
+
: undefined,
|
|
865
|
+
},
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
function detectComplianceVulnerabilities(users, groups, computers, domain, gpoSettings, includeDetails) {
|
|
869
|
+
const findings = [
|
|
870
|
+
detectAnssiR1PasswordPolicy(domain, gpoSettings, includeDetails),
|
|
871
|
+
detectAnssiR2PrivilegedAccounts(users, groups, includeDetails),
|
|
872
|
+
detectAnssiR3StrongAuth(users, domain, includeDetails),
|
|
873
|
+
detectAnssiR4Logging(gpoSettings, includeDetails),
|
|
874
|
+
detectAnssiR5Segregation(users, computers, includeDetails),
|
|
875
|
+
detectNistAc2AccountManagement(users, includeDetails),
|
|
876
|
+
detectNistAc6LeastPrivilege(users, groups, includeDetails),
|
|
877
|
+
detectNistIa5Authenticator(domain, users, includeDetails),
|
|
878
|
+
detectNistAu2AuditEvents(gpoSettings, includeDetails),
|
|
879
|
+
detectCisPasswordPolicy(domain, includeDetails),
|
|
880
|
+
detectCisNetworkSecurity(gpoSettings, includeDetails),
|
|
881
|
+
detectCisUserRights(users, groups, includeDetails),
|
|
882
|
+
detectDisaAccountPolicies(domain, users, includeDetails),
|
|
883
|
+
detectDisaAuditPolicies(gpoSettings, includeDetails),
|
|
884
|
+
detectMfaNotEnforced(users, includeDetails),
|
|
885
|
+
detectBackupNotVerified(domain, includeDetails),
|
|
886
|
+
detectAuditLogRetentionShort(gpoSettings, includeDetails),
|
|
887
|
+
detectPrivilegedAccessReviewMissing(users, groups, includeDetails),
|
|
888
|
+
detectDataClassificationMissing(domain, includeDetails),
|
|
889
|
+
detectChangeManagementBypass(users, groups, includeDetails),
|
|
890
|
+
detectVendorAccountUnmonitored(users, includeDetails),
|
|
891
|
+
detectEncryptionAtRestDisabled(computers, includeDetails),
|
|
892
|
+
];
|
|
893
|
+
findings.push(detectComplianceScore(findings, includeDetails));
|
|
894
|
+
return findings.filter((f) => f.count > 0 || f.type === 'COMPLIANCE_SCORE');
|
|
895
|
+
}
|
|
896
|
+
//# sourceMappingURL=compliance.detector.js.map
|