@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,280 @@
|
|
|
1
|
+
import { Entry } from 'ldapts';
|
|
2
|
+
import { ADUser, ADGroup, ADComputer, ADOU } from '../../types/ad.types';
|
|
3
|
+
import { logger } from '../../utils/logger';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Active Directory Type Mappers
|
|
7
|
+
*
|
|
8
|
+
* Maps raw LDAP entries to typed AD objects.
|
|
9
|
+
* Handles AD-specific attributes and data type conversions.
|
|
10
|
+
*
|
|
11
|
+
* Task 4: Create AD Type Mappers (Story 1.5)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Convert Windows FILETIME to JavaScript Date
|
|
16
|
+
*
|
|
17
|
+
* Windows FILETIME is 100-nanosecond intervals since Jan 1, 1601 UTC.
|
|
18
|
+
* JavaScript Date uses milliseconds since Jan 1, 1970 UTC.
|
|
19
|
+
*
|
|
20
|
+
* @param filetime - FILETIME value as string
|
|
21
|
+
* @returns Date object or undefined if invalid
|
|
22
|
+
*/
|
|
23
|
+
function fileTimeToDate(filetime: string | undefined): Date | undefined {
|
|
24
|
+
if (!filetime) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const value = BigInt(filetime);
|
|
30
|
+
|
|
31
|
+
// Special values in AD
|
|
32
|
+
if (value === BigInt(0) || value === BigInt('9223372036854775807')) {
|
|
33
|
+
// 0 or max value means "never" or "not set"
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Convert Windows FILETIME to Unix timestamp
|
|
38
|
+
// 116444736000000000 = 100-ns intervals between 1601 and 1970
|
|
39
|
+
const unixTimestamp = Number((value - BigInt('116444736000000000')) / BigInt(10000));
|
|
40
|
+
|
|
41
|
+
return new Date(unixTimestamp);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
logger.warn(`Failed to convert FILETIME: ${filetime}`, error);
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get string value from LDAP attribute
|
|
50
|
+
*
|
|
51
|
+
* LDAP attributes can be strings, arrays, or Buffer objects.
|
|
52
|
+
*
|
|
53
|
+
* @param value - LDAP attribute value
|
|
54
|
+
* @returns String value or undefined
|
|
55
|
+
*/
|
|
56
|
+
function getString(value: unknown): string | undefined {
|
|
57
|
+
if (!value) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (typeof value === 'string') {
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (Array.isArray(value)) {
|
|
66
|
+
return value[0]?.toString();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (Buffer.isBuffer(value)) {
|
|
70
|
+
return value.toString('utf-8');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return String(value);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Get string array from LDAP attribute
|
|
78
|
+
*
|
|
79
|
+
* @param value - LDAP attribute value
|
|
80
|
+
* @returns Array of strings or undefined
|
|
81
|
+
*/
|
|
82
|
+
function getStringArray(value: unknown): string[] | undefined {
|
|
83
|
+
if (!value) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (Array.isArray(value)) {
|
|
88
|
+
return value.map((v) => (Buffer.isBuffer(v) ? v.toString('utf-8') : String(v)));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Single value
|
|
92
|
+
return [getString(value)!].filter(Boolean);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get number from LDAP attribute
|
|
97
|
+
*
|
|
98
|
+
* @param value - LDAP attribute value
|
|
99
|
+
* @returns Number or undefined
|
|
100
|
+
*/
|
|
101
|
+
function getNumber(value: unknown): number | undefined {
|
|
102
|
+
if (!value) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const str = getString(value);
|
|
107
|
+
if (!str) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const num = parseInt(str, 10);
|
|
112
|
+
return isNaN(num) ? undefined : num;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Check if AD account is enabled
|
|
117
|
+
*
|
|
118
|
+
* Uses userAccountControl attribute bit flags.
|
|
119
|
+
* Bit 1 (0x0002) = ACCOUNTDISABLE
|
|
120
|
+
*
|
|
121
|
+
* @param userAccountControl - userAccountControl value
|
|
122
|
+
* @returns true if enabled, false if disabled
|
|
123
|
+
*/
|
|
124
|
+
function isAccountEnabled(userAccountControl: number | undefined): boolean {
|
|
125
|
+
if (userAccountControl === undefined) {
|
|
126
|
+
return true; // Default to enabled if not specified
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const ACCOUNTDISABLE = 0x0002;
|
|
130
|
+
return (userAccountControl & ACCOUNTDISABLE) === 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Map LDAP entry to ADUser
|
|
135
|
+
*
|
|
136
|
+
* @param entry - LDAP search entry
|
|
137
|
+
* @returns ADUser object
|
|
138
|
+
*/
|
|
139
|
+
export function mapToADUser(entry: Entry): ADUser {
|
|
140
|
+
const userAccountControl = getNumber(entry['userAccountControl']);
|
|
141
|
+
|
|
142
|
+
const user: ADUser = {
|
|
143
|
+
dn: entry.dn,
|
|
144
|
+
sAMAccountName: getString(entry['sAMAccountName']) || '',
|
|
145
|
+
userPrincipalName: getString(entry['userPrincipalName']),
|
|
146
|
+
displayName: getString(entry['displayName']),
|
|
147
|
+
enabled: isAccountEnabled(userAccountControl),
|
|
148
|
+
passwordLastSet: fileTimeToDate(getString(entry['pwdLastSet'])),
|
|
149
|
+
lastLogon: fileTimeToDate(getString(entry['lastLogon'])),
|
|
150
|
+
adminCount: getNumber(entry['adminCount']),
|
|
151
|
+
memberOf: getStringArray(entry['memberOf']),
|
|
152
|
+
userAccountControl,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// Include all other attributes
|
|
156
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
157
|
+
if (!(key in user)) {
|
|
158
|
+
user[key] = value;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return user;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Map LDAP entry to ADGroup
|
|
167
|
+
*
|
|
168
|
+
* @param entry - LDAP search entry
|
|
169
|
+
* @returns ADGroup object
|
|
170
|
+
*/
|
|
171
|
+
export function mapToADGroup(entry: Entry): ADGroup {
|
|
172
|
+
const group: ADGroup = {
|
|
173
|
+
dn: entry.dn,
|
|
174
|
+
sAMAccountName: getString(entry['sAMAccountName']) || '',
|
|
175
|
+
displayName: getString(entry['displayName']),
|
|
176
|
+
groupType: getNumber(entry['groupType']),
|
|
177
|
+
memberOf: getStringArray(entry['memberOf']),
|
|
178
|
+
member: getStringArray(entry['member']),
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Include all other attributes
|
|
182
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
183
|
+
if (!(key in group)) {
|
|
184
|
+
group[key] = value;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return group;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Map LDAP entry to ADComputer
|
|
193
|
+
*
|
|
194
|
+
* @param entry - LDAP search entry
|
|
195
|
+
* @returns ADComputer object
|
|
196
|
+
*/
|
|
197
|
+
export function mapToADComputer(entry: Entry): ADComputer {
|
|
198
|
+
const userAccountControl = getNumber(entry['userAccountControl']);
|
|
199
|
+
|
|
200
|
+
const computer: ADComputer = {
|
|
201
|
+
dn: entry.dn,
|
|
202
|
+
sAMAccountName: getString(entry['sAMAccountName']) || '',
|
|
203
|
+
dNSHostName: getString(entry['dNSHostName']),
|
|
204
|
+
operatingSystem: getString(entry['operatingSystem']),
|
|
205
|
+
operatingSystemVersion: getString(entry['operatingSystemVersion']),
|
|
206
|
+
lastLogon: fileTimeToDate(getString(entry['lastLogon'])),
|
|
207
|
+
enabled: isAccountEnabled(userAccountControl),
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// Include all other attributes
|
|
211
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
212
|
+
if (!(key in computer)) {
|
|
213
|
+
computer[key] = value;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return computer;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Map LDAP entry to ADOU
|
|
222
|
+
*
|
|
223
|
+
* @param entry - LDAP search entry
|
|
224
|
+
* @returns ADOU object
|
|
225
|
+
*/
|
|
226
|
+
export function mapToADOU(entry: Entry): ADOU {
|
|
227
|
+
const ou: ADOU = {
|
|
228
|
+
dn: entry.dn,
|
|
229
|
+
name: getString(entry['name']) || getString(entry['ou']) || '',
|
|
230
|
+
description: getString(entry['description']),
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Include all other attributes
|
|
234
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
235
|
+
if (!(key in ou)) {
|
|
236
|
+
ou[key] = value;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return ou;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Generic mapper for custom types
|
|
245
|
+
*
|
|
246
|
+
* Maps LDAP entry to a plain object with all attributes.
|
|
247
|
+
*
|
|
248
|
+
* @param entry - LDAP search entry
|
|
249
|
+
* @returns Plain object with all entry attributes
|
|
250
|
+
*/
|
|
251
|
+
export function mapToGeneric(entry: Entry): Record<string, unknown> {
|
|
252
|
+
const result: Record<string, unknown> = {
|
|
253
|
+
dn: entry.dn,
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// Binary attributes that should NOT be converted to strings
|
|
257
|
+
const binaryAttributes = new Set(['nTSecurityDescriptor', 'objectGUID', 'objectSid']);
|
|
258
|
+
|
|
259
|
+
// Include all attributes
|
|
260
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
261
|
+
if (key === 'dn') continue; // Already added
|
|
262
|
+
|
|
263
|
+
// Preserve binary attributes as Buffers
|
|
264
|
+
if (binaryAttributes.has(key) && Buffer.isBuffer(value)) {
|
|
265
|
+
result[key] = value;
|
|
266
|
+
}
|
|
267
|
+
// Try to convert to proper types
|
|
268
|
+
else if (typeof value === 'string' && /^\d+$/.test(value)) {
|
|
269
|
+
result[key] = parseInt(value, 10);
|
|
270
|
+
} else if (Array.isArray(value)) {
|
|
271
|
+
result[key] = value.map((v) => (Buffer.isBuffer(v) ? v.toString('utf-8') : v));
|
|
272
|
+
} else if (Buffer.isBuffer(value)) {
|
|
273
|
+
result[key] = value.toString('utf-8');
|
|
274
|
+
} else {
|
|
275
|
+
result[key] = value;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { Client, SearchResult, Entry } from 'ldapts';
|
|
2
|
+
import { logger } from '../../utils/logger';
|
|
3
|
+
import { SearchOptions, LDAPControl } from '../interfaces/ILDAPProvider';
|
|
4
|
+
import { retryWithBackoff, LDAP_RETRY_OPTIONS } from './ldap-retry';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* LDAP Client Wrapper
|
|
10
|
+
*
|
|
11
|
+
* Wraps ldapts library to provide LDAP connectivity.
|
|
12
|
+
* Handles connection lifecycle, search operations, and error handling.
|
|
13
|
+
*
|
|
14
|
+
* Task 3: Implement LDAP Provider (Story 1.5)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* LDAP connection options
|
|
19
|
+
*/
|
|
20
|
+
export interface LDAPConnectionOptions {
|
|
21
|
+
url: string;
|
|
22
|
+
bindDN: string;
|
|
23
|
+
bindPassword: string;
|
|
24
|
+
timeout?: number;
|
|
25
|
+
tlsOptions?: {
|
|
26
|
+
rejectUnauthorized?: boolean;
|
|
27
|
+
ca?: Buffer | Buffer[];
|
|
28
|
+
checkServerIdentity?: (hostname: string, cert: unknown) => Error | undefined;
|
|
29
|
+
servername?: string;
|
|
30
|
+
};
|
|
31
|
+
caCertPath?: string;
|
|
32
|
+
skipHostnameVerification?: boolean;
|
|
33
|
+
tlsServername?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* LDAP Client
|
|
38
|
+
*
|
|
39
|
+
* Low-level wrapper around ldapts client.
|
|
40
|
+
*/
|
|
41
|
+
export class LDAPClient {
|
|
42
|
+
private client: Client | null = null;
|
|
43
|
+
private options: LDAPConnectionOptions;
|
|
44
|
+
private isConnected = false;
|
|
45
|
+
|
|
46
|
+
constructor(options: LDAPConnectionOptions) {
|
|
47
|
+
this.options = options;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Connect and bind to LDAP server
|
|
52
|
+
*
|
|
53
|
+
* Uses retry logic with exponential backoff for transient failures.
|
|
54
|
+
*
|
|
55
|
+
* @throws Error if connection or bind fails after retries
|
|
56
|
+
*/
|
|
57
|
+
async connect(): Promise<void> {
|
|
58
|
+
if (this.isConnected) {
|
|
59
|
+
logger.debug('LDAP client already connected');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
await retryWithBackoff(async () => {
|
|
64
|
+
try {
|
|
65
|
+
logger.debug(`Connecting to LDAP server: ${this.options.url}`);
|
|
66
|
+
|
|
67
|
+
// Build TLS options
|
|
68
|
+
let tlsOptions = this.options.tlsOptions || {};
|
|
69
|
+
|
|
70
|
+
// Load CA certificate if path provided and TLS verification is enabled
|
|
71
|
+
// Skip CA cert loading if rejectUnauthorized is explicitly false
|
|
72
|
+
const shouldLoadCaCert =
|
|
73
|
+
this.options.caCertPath && tlsOptions.rejectUnauthorized !== false;
|
|
74
|
+
|
|
75
|
+
if (shouldLoadCaCert) {
|
|
76
|
+
try {
|
|
77
|
+
const certPath = path.resolve(this.options.caCertPath!);
|
|
78
|
+
if (fs.existsSync(certPath)) {
|
|
79
|
+
const caCert = fs.readFileSync(certPath);
|
|
80
|
+
tlsOptions = {
|
|
81
|
+
...tlsOptions,
|
|
82
|
+
ca: caCert,
|
|
83
|
+
};
|
|
84
|
+
logger.debug(`Loaded CA certificate from: ${certPath}`);
|
|
85
|
+
} else {
|
|
86
|
+
logger.warn(`CA certificate not found at ${certPath}, using system CA store`);
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
logger.warn(`Failed to load CA certificate from ${this.options.caCertPath}:`, error);
|
|
90
|
+
// Don't throw - fall back to system CA store
|
|
91
|
+
}
|
|
92
|
+
} else if (tlsOptions.rejectUnauthorized === false) {
|
|
93
|
+
logger.debug('TLS verification disabled (rejectUnauthorized=false)');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Use servername for TLS validation when connecting via IP but cert has hostname
|
|
97
|
+
if (this.options.tlsServername) {
|
|
98
|
+
tlsOptions = {
|
|
99
|
+
...tlsOptions,
|
|
100
|
+
servername: this.options.tlsServername,
|
|
101
|
+
};
|
|
102
|
+
logger.debug(`Using TLS servername for certificate validation: ${this.options.tlsServername}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Skip hostname verification if configured (for IP-based connections)
|
|
106
|
+
if (this.options.skipHostnameVerification) {
|
|
107
|
+
tlsOptions = {
|
|
108
|
+
...tlsOptions,
|
|
109
|
+
checkServerIdentity: (hostname: string, _cert: unknown): undefined => {
|
|
110
|
+
logger.debug(`Skipping hostname verification for: ${hostname}`);
|
|
111
|
+
return undefined;
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
logger.debug('Hostname verification disabled (skipHostnameVerification=true)');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Create client
|
|
118
|
+
this.client = new Client({
|
|
119
|
+
url: this.options.url,
|
|
120
|
+
timeout: this.options.timeout || 5000,
|
|
121
|
+
connectTimeout: this.options.timeout || 5000,
|
|
122
|
+
tlsOptions,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Bind to server
|
|
126
|
+
await this.client.bind(this.options.bindDN, this.options.bindPassword);
|
|
127
|
+
|
|
128
|
+
this.isConnected = true;
|
|
129
|
+
logger.info(`Connected to LDAP server: ${this.options.url}`);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
this.isConnected = false;
|
|
132
|
+
this.client = null;
|
|
133
|
+
logger.error('Failed to connect to LDAP server:', error);
|
|
134
|
+
throw new Error(
|
|
135
|
+
`LDAP connection failed: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}, LDAP_RETRY_OPTIONS);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Disconnect from LDAP server
|
|
143
|
+
*/
|
|
144
|
+
async disconnect(): Promise<void> {
|
|
145
|
+
if (!this.client) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
await this.client.unbind();
|
|
151
|
+
logger.debug('Disconnected from LDAP server');
|
|
152
|
+
} catch (error) {
|
|
153
|
+
logger.warn('Error during LDAP disconnect:', error);
|
|
154
|
+
} finally {
|
|
155
|
+
this.client = null;
|
|
156
|
+
this.isConnected = false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Test connection to LDAP server
|
|
162
|
+
*
|
|
163
|
+
* @returns Connection test with response time
|
|
164
|
+
*/
|
|
165
|
+
async testConnection(): Promise<{ success: boolean; responseTime: number }> {
|
|
166
|
+
const startTime = Date.now();
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
// Attempt to connect and bind
|
|
170
|
+
await this.connect();
|
|
171
|
+
|
|
172
|
+
const responseTime = Date.now() - startTime;
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
success: true,
|
|
176
|
+
responseTime,
|
|
177
|
+
};
|
|
178
|
+
} catch (error) {
|
|
179
|
+
logger.error('LDAP connection test failed:', error);
|
|
180
|
+
return {
|
|
181
|
+
success: false,
|
|
182
|
+
responseTime: Date.now() - startTime,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Search LDAP directory
|
|
189
|
+
*
|
|
190
|
+
* Uses retry logic with exponential backoff for transient failures.
|
|
191
|
+
*
|
|
192
|
+
* @param baseDN - Base distinguished name for search
|
|
193
|
+
* @param options - Search options (filter, scope, attributes, etc.)
|
|
194
|
+
* @returns Array of search entry results
|
|
195
|
+
*
|
|
196
|
+
* @throws Error if not connected or search fails after retries
|
|
197
|
+
*/
|
|
198
|
+
async search(baseDN: string, options: SearchOptions): Promise<Entry[]> {
|
|
199
|
+
if (!this.client || !this.isConnected) {
|
|
200
|
+
throw new Error('LDAP client not connected. Call connect() first.');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return retryWithBackoff(async () => {
|
|
204
|
+
try {
|
|
205
|
+
logger.debug(`LDAP search: baseDN=${baseDN}, filter=${options.filter}`);
|
|
206
|
+
|
|
207
|
+
// Map our SearchOptions to ldapts SearchOptions
|
|
208
|
+
const searchOptions: any = {
|
|
209
|
+
filter: options.filter,
|
|
210
|
+
scope: options.scope,
|
|
211
|
+
attributes: options.attributes,
|
|
212
|
+
sizeLimit: options.sizeLimit,
|
|
213
|
+
timeLimit: options.timeLimit,
|
|
214
|
+
paged: options.paged ? { pageSize: 1000 } : undefined,
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// Map controls if provided
|
|
218
|
+
if (options.controls && options.controls.length > 0) {
|
|
219
|
+
searchOptions.controls = options.controls.map((ctrl: LDAPControl) => {
|
|
220
|
+
const control: any = {
|
|
221
|
+
type: ctrl.oid,
|
|
222
|
+
critical: ctrl.critical || false,
|
|
223
|
+
};
|
|
224
|
+
if (ctrl.value) {
|
|
225
|
+
control.value = Buffer.isBuffer(ctrl.value) ? ctrl.value : Buffer.from(ctrl.value);
|
|
226
|
+
}
|
|
227
|
+
return control;
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Perform search
|
|
232
|
+
const searchResult: SearchResult = await this.client!.search(baseDN, searchOptions);
|
|
233
|
+
|
|
234
|
+
logger.debug(`LDAP search returned ${searchResult.searchEntries.length} entries`);
|
|
235
|
+
|
|
236
|
+
return searchResult.searchEntries;
|
|
237
|
+
} catch (error) {
|
|
238
|
+
logger.error(`LDAP search failed: baseDN=${baseDN}`, error);
|
|
239
|
+
throw new Error(
|
|
240
|
+
`LDAP search failed: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
}, LDAP_RETRY_OPTIONS);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Check if client is currently connected
|
|
248
|
+
*/
|
|
249
|
+
isClientConnected(): boolean {
|
|
250
|
+
return this.isConnected;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Get connection URL (for debugging)
|
|
255
|
+
*/
|
|
256
|
+
getConnectionUrl(): string {
|
|
257
|
+
return this.options.url;
|
|
258
|
+
}
|
|
259
|
+
}
|