@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,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microsoft Graph Client
|
|
3
|
+
*
|
|
4
|
+
* Handles authentication and API requests to Microsoft Graph using OAuth 2.0 client credentials flow.
|
|
5
|
+
* Supports automatic token refresh and retry logic with rate limit handling.
|
|
6
|
+
*
|
|
7
|
+
* Task 2: Implement Microsoft Graph Client with OAuth 2.0 (Story 1.6)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Client } from '@microsoft/microsoft-graph-client';
|
|
11
|
+
import { ClientSecretCredential } from '@azure/identity';
|
|
12
|
+
import { AzureProviderConfig } from '../../types/config.types';
|
|
13
|
+
import {
|
|
14
|
+
AzureAuthenticationError,
|
|
15
|
+
AzureAPIError,
|
|
16
|
+
AzureRateLimitError,
|
|
17
|
+
AzureTimeoutError,
|
|
18
|
+
} from './azure-errors';
|
|
19
|
+
import { retryWithBackoff, AZURE_RETRY_CONFIGS, RetryOptions } from './azure-retry';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Graph client options
|
|
23
|
+
*/
|
|
24
|
+
export interface GraphClientOptions {
|
|
25
|
+
timeout?: number; // milliseconds (default: 30000)
|
|
26
|
+
maxRetries?: number; // default: 3
|
|
27
|
+
apiVersion?: string; // default: 'v1.0'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Token info
|
|
32
|
+
*/
|
|
33
|
+
interface TokenInfo {
|
|
34
|
+
accessToken: string;
|
|
35
|
+
expiresAt: Date;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Microsoft Graph Client
|
|
40
|
+
*
|
|
41
|
+
* Provides authenticated access to Microsoft Graph API using Azure AD service principal.
|
|
42
|
+
*/
|
|
43
|
+
export class GraphClient {
|
|
44
|
+
private client: Client | null = null;
|
|
45
|
+
private credential: ClientSecretCredential;
|
|
46
|
+
private tokenInfo: TokenInfo | null = null;
|
|
47
|
+
private readonly config: AzureProviderConfig;
|
|
48
|
+
private readonly options: Required<GraphClientOptions>;
|
|
49
|
+
private readonly graphScope = 'https://graph.microsoft.com/.default';
|
|
50
|
+
|
|
51
|
+
constructor(config: AzureProviderConfig, options: GraphClientOptions = {}) {
|
|
52
|
+
this.config = config;
|
|
53
|
+
this.options = {
|
|
54
|
+
timeout: options.timeout || 30000,
|
|
55
|
+
maxRetries: options.maxRetries || 3,
|
|
56
|
+
apiVersion: options.apiVersion || 'v1.0',
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Initialize Azure AD credential
|
|
60
|
+
this.credential = new ClientSecretCredential(
|
|
61
|
+
config.tenantId,
|
|
62
|
+
config.clientId,
|
|
63
|
+
config.clientSecret
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Authenticate and initialize Graph client
|
|
69
|
+
*
|
|
70
|
+
* Obtains an access token using OAuth 2.0 client credentials flow.
|
|
71
|
+
*
|
|
72
|
+
* @throws {AzureAuthenticationError} If authentication fails
|
|
73
|
+
*/
|
|
74
|
+
async authenticate(): Promise<void> {
|
|
75
|
+
try {
|
|
76
|
+
// Get access token
|
|
77
|
+
const tokenResponse = await this.credential.getToken(this.graphScope);
|
|
78
|
+
|
|
79
|
+
if (!tokenResponse) {
|
|
80
|
+
throw new AzureAuthenticationError(
|
|
81
|
+
'Failed to obtain access token',
|
|
82
|
+
this.config.tenantId,
|
|
83
|
+
this.config.clientId
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Store token info
|
|
88
|
+
this.tokenInfo = {
|
|
89
|
+
accessToken: tokenResponse.token,
|
|
90
|
+
expiresAt: tokenResponse.expiresOnTimestamp
|
|
91
|
+
? new Date(tokenResponse.expiresOnTimestamp)
|
|
92
|
+
: new Date(Date.now() + 3600 * 1000), // 1 hour default
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Initialize Graph client with token
|
|
96
|
+
this.client = Client.init({
|
|
97
|
+
authProvider: (done) => {
|
|
98
|
+
done(null, this.tokenInfo!.accessToken);
|
|
99
|
+
},
|
|
100
|
+
defaultVersion: this.options.apiVersion,
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
throw new AzureAuthenticationError(
|
|
104
|
+
`Authentication failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
105
|
+
this.config.tenantId,
|
|
106
|
+
this.config.clientId,
|
|
107
|
+
error instanceof Error ? error : undefined
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Check if token is expired or about to expire
|
|
114
|
+
*
|
|
115
|
+
* @returns True if token needs refresh (expired or expires in <5 minutes)
|
|
116
|
+
*/
|
|
117
|
+
private isTokenExpired(): boolean {
|
|
118
|
+
if (!this.tokenInfo) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const now = Date.now();
|
|
123
|
+
const expiresAt = this.tokenInfo.expiresAt.getTime();
|
|
124
|
+
const fiveMinutes = 5 * 60 * 1000;
|
|
125
|
+
|
|
126
|
+
return expiresAt - now < fiveMinutes;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Ensure client is authenticated
|
|
131
|
+
*
|
|
132
|
+
* Automatically refreshes token if expired.
|
|
133
|
+
*
|
|
134
|
+
* @throws {AzureAuthenticationError} If not authenticated and authentication fails
|
|
135
|
+
*/
|
|
136
|
+
private async ensureAuthenticated(): Promise<void> {
|
|
137
|
+
if (!this.client || this.isTokenExpired()) {
|
|
138
|
+
await this.authenticate();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Make a GET request to Graph API
|
|
144
|
+
*
|
|
145
|
+
* Handles authentication, rate limiting, and retries automatically.
|
|
146
|
+
*
|
|
147
|
+
* @param endpoint - Graph API endpoint (e.g., '/users', '/groups')
|
|
148
|
+
* @param params - Query parameters
|
|
149
|
+
* @param retryOptions - Override default retry options
|
|
150
|
+
* @returns Response data
|
|
151
|
+
* @throws {AzureAPIError} If request fails
|
|
152
|
+
*/
|
|
153
|
+
async get<T = unknown>(
|
|
154
|
+
endpoint: string,
|
|
155
|
+
params?: Record<string, unknown>,
|
|
156
|
+
retryOptions?: RetryOptions
|
|
157
|
+
): Promise<T> {
|
|
158
|
+
// Wrap the request with retry logic
|
|
159
|
+
return retryWithBackoff(async () => {
|
|
160
|
+
await this.ensureAuthenticated();
|
|
161
|
+
|
|
162
|
+
if (!this.client) {
|
|
163
|
+
throw new AzureAPIError('Graph client not initialized', endpoint);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
let request = this.client.api(endpoint);
|
|
168
|
+
|
|
169
|
+
// Add query parameters
|
|
170
|
+
if (params) {
|
|
171
|
+
const queryParams: Record<string, string> = {};
|
|
172
|
+
for (const [key, value] of Object.entries(params)) {
|
|
173
|
+
if (value !== undefined && value !== null) {
|
|
174
|
+
queryParams[key] = String(value);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (Object.keys(queryParams).length > 0) {
|
|
178
|
+
request = request.query(queryParams);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Set timeout
|
|
183
|
+
request = request.options({
|
|
184
|
+
timeout: this.options.timeout,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Execute request
|
|
188
|
+
const response = await request.get();
|
|
189
|
+
return response as T;
|
|
190
|
+
} catch (error) {
|
|
191
|
+
// Handle rate limit (429)
|
|
192
|
+
if (error instanceof Error && 'statusCode' in error && error.statusCode === 429) {
|
|
193
|
+
const retryAfter = this.extractRetryAfter(error);
|
|
194
|
+
throw new AzureRateLimitError(
|
|
195
|
+
`Rate limit exceeded for ${endpoint}. Retry after ${retryAfter}s`,
|
|
196
|
+
endpoint,
|
|
197
|
+
retryAfter
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Handle timeout
|
|
202
|
+
if (error instanceof Error && error.message.includes('timeout')) {
|
|
203
|
+
throw new AzureTimeoutError(
|
|
204
|
+
`Request to ${endpoint} timed out after ${this.options.timeout}ms`,
|
|
205
|
+
`GET ${endpoint}`,
|
|
206
|
+
this.options.timeout
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Generic API error
|
|
211
|
+
const statusCode =
|
|
212
|
+
error instanceof Error && 'statusCode' in error
|
|
213
|
+
? (error as { statusCode: number }).statusCode
|
|
214
|
+
: undefined;
|
|
215
|
+
|
|
216
|
+
throw new AzureAPIError(
|
|
217
|
+
`Graph API request failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
218
|
+
endpoint,
|
|
219
|
+
statusCode,
|
|
220
|
+
error instanceof Error ? error : undefined
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
}, retryOptions || AZURE_RETRY_CONFIGS.default);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Get all results with pagination
|
|
228
|
+
*
|
|
229
|
+
* Automatically follows @odata.nextLink to retrieve all pages.
|
|
230
|
+
*
|
|
231
|
+
* @param endpoint - Graph API endpoint
|
|
232
|
+
* @param params - Query parameters
|
|
233
|
+
* @returns Array of all results
|
|
234
|
+
*/
|
|
235
|
+
async getAll<T = unknown>(endpoint: string, params?: Record<string, unknown>): Promise<T[]> {
|
|
236
|
+
const results: T[] = [];
|
|
237
|
+
let nextLink: string | undefined = endpoint;
|
|
238
|
+
let currentParams: Record<string, unknown> | undefined = params;
|
|
239
|
+
|
|
240
|
+
while (nextLink) {
|
|
241
|
+
const response: { value: T[]; '@odata.nextLink'?: string } = await this.get<{
|
|
242
|
+
value: T[];
|
|
243
|
+
'@odata.nextLink'?: string;
|
|
244
|
+
}>(nextLink, currentParams);
|
|
245
|
+
|
|
246
|
+
if (response.value && Array.isArray(response.value)) {
|
|
247
|
+
results.push(...response.value);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
nextLink = response['@odata.nextLink'];
|
|
251
|
+
// For subsequent pages, don't pass params (they're in the nextLink)
|
|
252
|
+
currentParams = undefined;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return results;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Extract retry-after value from error
|
|
260
|
+
*
|
|
261
|
+
* @param error - Error object
|
|
262
|
+
* @returns Retry after seconds (default: 60)
|
|
263
|
+
*/
|
|
264
|
+
private extractRetryAfter(error: Error): number {
|
|
265
|
+
try {
|
|
266
|
+
if ('headers' in error && error.headers && typeof error.headers === 'object') {
|
|
267
|
+
const headers = error.headers as Record<string, string>;
|
|
268
|
+
const retryAfter = headers['retry-after'] || headers['Retry-After'];
|
|
269
|
+
if (retryAfter) {
|
|
270
|
+
const seconds = parseInt(retryAfter, 10);
|
|
271
|
+
if (!isNaN(seconds)) {
|
|
272
|
+
return seconds;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} catch {
|
|
277
|
+
// Ignore parsing errors
|
|
278
|
+
}
|
|
279
|
+
return 60; // Default to 60 seconds
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Test connection to Microsoft Graph
|
|
284
|
+
*
|
|
285
|
+
* Verifies authentication and basic API access.
|
|
286
|
+
*
|
|
287
|
+
* @returns True if connection is successful
|
|
288
|
+
* @throws {AzureAuthenticationError | AzureAPIError} If connection fails
|
|
289
|
+
*/
|
|
290
|
+
async testConnection(): Promise<boolean> {
|
|
291
|
+
await this.authenticate();
|
|
292
|
+
|
|
293
|
+
// Try a simple API call to verify access
|
|
294
|
+
await this.get('/organization');
|
|
295
|
+
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Get current access token
|
|
301
|
+
*
|
|
302
|
+
* @returns Access token or null if not authenticated
|
|
303
|
+
*/
|
|
304
|
+
getAccessToken(): string | null {
|
|
305
|
+
return this.tokenInfo?.accessToken || null;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Clear cached token and client
|
|
310
|
+
*/
|
|
311
|
+
disconnect(): void {
|
|
312
|
+
this.client = null;
|
|
313
|
+
this.tokenInfo = null;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microsoft Graph Provider
|
|
3
|
+
*
|
|
4
|
+
* High-level provider for querying Azure AD / Microsoft Graph API.
|
|
5
|
+
* Implements the IGraphProvider interface with full support for users, groups, applications, and policies.
|
|
6
|
+
*
|
|
7
|
+
* Task 3: Create Azure Provider query methods (Story 1.6)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
IGraphProvider,
|
|
12
|
+
AzureConnectionTestResult,
|
|
13
|
+
GraphQueryOptions,
|
|
14
|
+
} from '../interfaces/IGraphProvider';
|
|
15
|
+
import { AzureUser, AzureGroup, AzureApp, AzurePolicy } from '../../types/azure.types';
|
|
16
|
+
import { AzureProviderConfig } from '../../types/config.types';
|
|
17
|
+
import { GraphClient } from './graph-client';
|
|
18
|
+
import {
|
|
19
|
+
AzureAPIError,
|
|
20
|
+
AzureAuthenticationError,
|
|
21
|
+
AzurePermissionError,
|
|
22
|
+
} from './azure-errors';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Microsoft Graph Provider
|
|
26
|
+
*
|
|
27
|
+
* Provides high-level methods for querying Azure AD objects via Microsoft Graph API.
|
|
28
|
+
*/
|
|
29
|
+
export class GraphProvider implements IGraphProvider {
|
|
30
|
+
private readonly client: GraphClient;
|
|
31
|
+
private readonly config: AzureProviderConfig;
|
|
32
|
+
private readonly graphApiUrl = 'https://graph.microsoft.com';
|
|
33
|
+
|
|
34
|
+
constructor(config: AzureProviderConfig) {
|
|
35
|
+
this.config = config;
|
|
36
|
+
this.client = new GraphClient(config, {
|
|
37
|
+
timeout: 30000, // 30 seconds
|
|
38
|
+
maxRetries: 3,
|
|
39
|
+
apiVersion: 'v1.0',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Authenticate with Microsoft Graph
|
|
45
|
+
*
|
|
46
|
+
* @throws {AzureAuthenticationError} If authentication fails
|
|
47
|
+
*/
|
|
48
|
+
async authenticate(): Promise<void> {
|
|
49
|
+
await this.client.authenticate();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Test connection to Microsoft Graph API
|
|
54
|
+
*
|
|
55
|
+
* @returns Connection test result with diagnostics
|
|
56
|
+
*/
|
|
57
|
+
async testConnection(): Promise<AzureConnectionTestResult> {
|
|
58
|
+
const startTime = Date.now();
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
// Authenticate
|
|
62
|
+
await this.authenticate();
|
|
63
|
+
|
|
64
|
+
// Test basic API access by getting organization info
|
|
65
|
+
await this.client.get<{ value: { id: string }[] }>('/organization');
|
|
66
|
+
|
|
67
|
+
const responseTime = Date.now() - startTime;
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
success: true,
|
|
71
|
+
message: 'Connection successful',
|
|
72
|
+
details: {
|
|
73
|
+
tenantId: this.config.tenantId,
|
|
74
|
+
clientId: this.config.clientId,
|
|
75
|
+
graphApiUrl: this.graphApiUrl,
|
|
76
|
+
authenticated: true,
|
|
77
|
+
permissions: ['User.Read.All', 'Group.Read.All'], // TODO: Get actual permissions
|
|
78
|
+
responseTime,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
} catch (error) {
|
|
82
|
+
const responseTime = Date.now() - startTime;
|
|
83
|
+
|
|
84
|
+
if (error instanceof AzureAuthenticationError) {
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
message: `Authentication failed: ${error.message}`,
|
|
88
|
+
details: {
|
|
89
|
+
tenantId: this.config.tenantId,
|
|
90
|
+
clientId: this.config.clientId,
|
|
91
|
+
graphApiUrl: this.graphApiUrl,
|
|
92
|
+
authenticated: false,
|
|
93
|
+
responseTime,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
success: false,
|
|
100
|
+
message: `Connection test failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
101
|
+
details: {
|
|
102
|
+
tenantId: this.config.tenantId,
|
|
103
|
+
clientId: this.config.clientId,
|
|
104
|
+
graphApiUrl: this.graphApiUrl,
|
|
105
|
+
authenticated: false,
|
|
106
|
+
responseTime,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Query Azure AD users
|
|
114
|
+
*
|
|
115
|
+
* @param options - Query options (filter, select, top, etc.)
|
|
116
|
+
* @returns Array of Azure AD users
|
|
117
|
+
* @throws {AzureAPIError} If the API request fails
|
|
118
|
+
*/
|
|
119
|
+
async getUsers(options?: GraphQueryOptions): Promise<AzureUser[]> {
|
|
120
|
+
try {
|
|
121
|
+
const params = this.buildQueryParams(options);
|
|
122
|
+
|
|
123
|
+
// Use getAll to handle pagination
|
|
124
|
+
const users = await this.client.getAll<AzureUser>('/users', params);
|
|
125
|
+
|
|
126
|
+
return users;
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (
|
|
129
|
+
error instanceof AzureAPIError &&
|
|
130
|
+
error.statusCode === 403
|
|
131
|
+
) {
|
|
132
|
+
throw new AzurePermissionError(
|
|
133
|
+
'Insufficient permissions to read users. Required: User.Read.All',
|
|
134
|
+
'/users',
|
|
135
|
+
['User.Read.All']
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Query Azure AD groups
|
|
144
|
+
*
|
|
145
|
+
* @param options - Query options (filter, select, top, etc.)
|
|
146
|
+
* @returns Array of Azure AD groups
|
|
147
|
+
* @throws {AzureAPIError} If the API request fails
|
|
148
|
+
*/
|
|
149
|
+
async getGroups(options?: GraphQueryOptions): Promise<AzureGroup[]> {
|
|
150
|
+
try {
|
|
151
|
+
const params = this.buildQueryParams(options);
|
|
152
|
+
|
|
153
|
+
const groups = await this.client.getAll<AzureGroup>('/groups', params);
|
|
154
|
+
|
|
155
|
+
return groups;
|
|
156
|
+
} catch (error) {
|
|
157
|
+
if (error instanceof AzureAPIError && error.statusCode === 403) {
|
|
158
|
+
throw new AzurePermissionError(
|
|
159
|
+
'Insufficient permissions to read groups. Required: Group.Read.All',
|
|
160
|
+
'/groups',
|
|
161
|
+
['Group.Read.All']
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Query Azure AD applications
|
|
170
|
+
*
|
|
171
|
+
* @param options - Query options (filter, select, top, etc.)
|
|
172
|
+
* @returns Array of Azure AD applications
|
|
173
|
+
* @throws {AzureAPIError} If the API request fails
|
|
174
|
+
*/
|
|
175
|
+
async getApplications(options?: GraphQueryOptions): Promise<AzureApp[]> {
|
|
176
|
+
try {
|
|
177
|
+
const params = this.buildQueryParams(options);
|
|
178
|
+
|
|
179
|
+
const apps = await this.client.getAll<AzureApp>('/applications', params);
|
|
180
|
+
|
|
181
|
+
return apps;
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (error instanceof AzureAPIError && error.statusCode === 403) {
|
|
184
|
+
throw new AzurePermissionError(
|
|
185
|
+
'Insufficient permissions to read applications. Required: Application.Read.All',
|
|
186
|
+
'/applications',
|
|
187
|
+
['Application.Read.All']
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
throw error;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Query Conditional Access policies
|
|
196
|
+
*
|
|
197
|
+
* @param options - Query options (filter, select, top, etc.)
|
|
198
|
+
* @returns Array of Conditional Access policies
|
|
199
|
+
* @throws {AzureAPIError} If the API request fails
|
|
200
|
+
*/
|
|
201
|
+
async getPolicies(options?: GraphQueryOptions): Promise<AzurePolicy[]> {
|
|
202
|
+
try {
|
|
203
|
+
const params = this.buildQueryParams(options);
|
|
204
|
+
|
|
205
|
+
const policies = await this.client.getAll<AzurePolicy>(
|
|
206
|
+
'/identity/conditionalAccess/policies',
|
|
207
|
+
params
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
return policies;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
if (error instanceof AzureAPIError && error.statusCode === 403) {
|
|
213
|
+
throw new AzurePermissionError(
|
|
214
|
+
'Insufficient permissions to read policies. Required: Policy.Read.All',
|
|
215
|
+
'/identity/conditionalAccess/policies',
|
|
216
|
+
['Policy.Read.All']
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get organization/tenant information
|
|
225
|
+
*
|
|
226
|
+
* @returns Organization info with display name
|
|
227
|
+
*/
|
|
228
|
+
async getOrganization(): Promise<{ displayName: string; id: string; verifiedDomains: string[] }> {
|
|
229
|
+
await this.authenticate();
|
|
230
|
+
const response = await this.client.get<{
|
|
231
|
+
value: Array<{
|
|
232
|
+
id: string;
|
|
233
|
+
displayName: string;
|
|
234
|
+
verifiedDomains: Array<{ name: string; isDefault: boolean }>;
|
|
235
|
+
}>;
|
|
236
|
+
}>('/organization');
|
|
237
|
+
|
|
238
|
+
const org = response.value[0];
|
|
239
|
+
return {
|
|
240
|
+
id: org?.id || this.config.tenantId,
|
|
241
|
+
displayName: org?.displayName || 'Unknown',
|
|
242
|
+
verifiedDomains: org?.verifiedDomains?.map((d) => d.name) || [],
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Disconnect from Microsoft Graph
|
|
248
|
+
*
|
|
249
|
+
* Clears cached tokens and connection state.
|
|
250
|
+
*/
|
|
251
|
+
async disconnect(): Promise<void> {
|
|
252
|
+
this.client.disconnect();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Build OData query parameters from options
|
|
257
|
+
*
|
|
258
|
+
* @param options - Query options
|
|
259
|
+
* @returns Query parameters for Graph API
|
|
260
|
+
*/
|
|
261
|
+
private buildQueryParams(options?: GraphQueryOptions): Record<string, string> | undefined {
|
|
262
|
+
if (!options) {
|
|
263
|
+
return undefined;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const params: Record<string, string> = {};
|
|
267
|
+
|
|
268
|
+
if (options.filter) {
|
|
269
|
+
params['$filter'] = options.filter;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (options.select && options.select.length > 0) {
|
|
273
|
+
params['$select'] = options.select.join(',');
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (options.expand && options.expand.length > 0) {
|
|
277
|
+
params['$expand'] = options.expand.join(',');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (options.orderBy) {
|
|
281
|
+
params['$orderby'] = options.orderBy;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (options.top !== undefined) {
|
|
285
|
+
params['$top'] = String(options.top);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (options.skip !== undefined) {
|
|
289
|
+
params['$skip'] = String(options.skip);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return Object.keys(params).length > 0 ? params : undefined;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microsoft Graph Application Queries
|
|
3
|
+
* TODO: Full implementation in Story 1.6
|
|
4
|
+
*/
|
|
5
|
+
export const GraphAppQueries = {
|
|
6
|
+
ALL_APPS: '/applications',
|
|
7
|
+
SERVICE_PRINCIPALS: '/servicePrincipals',
|
|
8
|
+
APP_REGISTRATIONS: '/applications?$filter=signInAudience eq \'AzureADMyOrg\'',
|
|
9
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microsoft Graph Policy Queries
|
|
3
|
+
* TODO: Full implementation in Story 1.6
|
|
4
|
+
*/
|
|
5
|
+
export const GraphPolicyQueries = {
|
|
6
|
+
CONDITIONAL_ACCESS: '/identity/conditionalAccess/policies',
|
|
7
|
+
AUTH_METHODS: '/policies/authenticationMethodsPolicy',
|
|
8
|
+
AUTHORIZATION: '/policies/authorizationPolicy',
|
|
9
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microsoft Graph User Queries
|
|
3
|
+
* TODO: Full implementation in Story 1.6
|
|
4
|
+
*/
|
|
5
|
+
export const GraphUserQueries = {
|
|
6
|
+
ALL_USERS: '/users',
|
|
7
|
+
ENABLED_USERS: '/users?$filter=accountEnabled eq true',
|
|
8
|
+
DISABLED_USERS: '/users?$filter=accountEnabled eq false',
|
|
9
|
+
ADMIN_USERS: '/directoryRoles/members',
|
|
10
|
+
};
|
|
File without changes
|