blockmine 1.21.0 → 1.22.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/.claude/agents/README.md +469 -0
- package/.claude/agents/auth-route-debugger.md +118 -0
- package/.claude/agents/auth-route-tester.md +93 -0
- package/.claude/agents/auto-error-resolver.md +97 -0
- package/.claude/agents/build-optimizer.md +236 -0
- package/.claude/agents/code-architecture-reviewer.md +83 -0
- package/.claude/agents/code-refactor-master.md +94 -0
- package/.claude/agents/cost-optimizer.md +134 -0
- package/.claude/agents/deployment-orchestrator.md +113 -0
- package/.claude/agents/documentation-architect.md +82 -0
- package/.claude/agents/frontend-error-fixer.md +77 -0
- package/.claude/agents/iac-code-generator.md +71 -0
- package/.claude/agents/incident-responder.md +346 -0
- package/.claude/agents/infrastructure-architect.md +31 -0
- package/.claude/agents/kubernetes-specialist.md +56 -0
- package/.claude/agents/migration-planner.md +181 -0
- package/.claude/agents/network-architect.md +196 -0
- package/.claude/agents/plan-reviewer.md +52 -0
- package/.claude/agents/refactor-planner.md +63 -0
- package/.claude/agents/security-scanner.md +102 -0
- package/.claude/agents/web-research-specialist.md +78 -0
- package/.claude/commands/cost-analysis.md +315 -0
- package/.claude/commands/dev-docs-update.md +55 -0
- package/.claude/commands/dev-docs.md +51 -0
- package/.claude/commands/incident-debug.md +247 -0
- package/.claude/commands/infra-plan.md +81 -0
- package/.claude/commands/migration-plan.md +478 -0
- package/.claude/commands/route-research-for-testing.md +37 -0
- package/.claude/commands/security-review.md +66 -0
- package/.claude/hooks/CONFIG.md +448 -0
- package/.claude/hooks/README.md +163 -0
- package/.claude/hooks/SKILL_ACTIVATION_COMPLETE.md +226 -0
- package/.claude/hooks/WINDOWS_HOOKS_README.md +151 -0
- package/.claude/hooks/add-skill-activation-banners.ts +132 -0
- package/.claude/hooks/comprehensive-skill-test.ts +1315 -0
- package/.claude/hooks/error-handling-reminder.sh +12 -0
- package/.claude/hooks/error-handling-reminder.ts +222 -0
- package/.claude/hooks/k8s-manifest-validator.sh +56 -0
- package/.claude/hooks/package-lock.json +556 -0
- package/.claude/hooks/package.json +16 -0
- package/.claude/hooks/post-tool-use-tracker.ps1 +174 -0
- package/.claude/hooks/post-tool-use-tracker.sh +183 -0
- package/.claude/hooks/security-policy-check.sh +247 -0
- package/.claude/hooks/skill-activation-prompt.ps1 +10 -0
- package/.claude/hooks/skill-activation-prompt.sh +10 -0
- package/.claude/hooks/skill-activation-prompt.ts +141 -0
- package/.claude/hooks/stop-build-check-enhanced.sh +130 -0
- package/.claude/hooks/terraform-validator.sh +53 -0
- package/.claude/hooks/test-input.json +7 -0
- package/.claude/hooks/test-skill-activation.ts +427 -0
- package/.claude/hooks/trigger-build-resolver.sh +79 -0
- package/.claude/hooks/tsc-check.sh +173 -0
- package/.claude/hooks/tsconfig.json +19 -0
- package/.claude/settings.json +55 -0
- package/.claude/settings.local.json +27 -14
- package/.claude/skills/README.md +507 -0
- package/.claude/skills/api-engineering/SKILL.md +63 -0
- package/.claude/skills/api-engineering/resources/api-versioning.md +88 -0
- package/.claude/skills/api-engineering/resources/graphql-patterns.md +106 -0
- package/.claude/skills/api-engineering/resources/rate-limiting.md +118 -0
- package/.claude/skills/api-engineering/resources/rest-api-design.md +105 -0
- package/.claude/skills/backend-dev-guidelines/SKILL.md +306 -0
- package/.claude/skills/backend-dev-guidelines/resources/architecture-overview.md +451 -0
- package/.claude/skills/backend-dev-guidelines/resources/async-and-errors.md +307 -0
- package/.claude/skills/backend-dev-guidelines/resources/complete-examples.md +638 -0
- package/.claude/skills/backend-dev-guidelines/resources/configuration.md +275 -0
- package/.claude/skills/backend-dev-guidelines/resources/database-patterns.md +224 -0
- package/.claude/skills/backend-dev-guidelines/resources/middleware-guide.md +213 -0
- package/.claude/skills/backend-dev-guidelines/resources/routing-and-controllers.md +756 -0
- package/.claude/skills/backend-dev-guidelines/resources/sentry-and-monitoring.md +336 -0
- package/.claude/skills/backend-dev-guidelines/resources/services-and-repositories.md +789 -0
- package/.claude/skills/backend-dev-guidelines/resources/testing-guide.md +235 -0
- package/.claude/skills/backend-dev-guidelines/resources/validation-patterns.md +754 -0
- package/.claude/skills/budget-and-cost-management/SKILL.md +850 -0
- package/.claude/skills/build-engineering/SKILL.md +431 -0
- package/.claude/skills/build-engineering/resources/artifact-repositories.md +72 -0
- package/.claude/skills/build-engineering/resources/build-caching.md +96 -0
- package/.claude/skills/build-engineering/resources/build-pipelines.md +105 -0
- package/.claude/skills/build-engineering/resources/build-security.md +95 -0
- package/.claude/skills/build-engineering/resources/build-systems.md +389 -0
- package/.claude/skills/build-engineering/resources/compilation-optimization.md +201 -0
- package/.claude/skills/build-engineering/resources/dependency-management.md +73 -0
- package/.claude/skills/build-engineering/resources/monorepo-builds.md +110 -0
- package/.claude/skills/build-engineering/resources/performance-optimization.md +113 -0
- package/.claude/skills/build-engineering/resources/reproducible-builds.md +82 -0
- package/.claude/skills/cloud-engineering/SKILL.md +675 -0
- package/.claude/skills/cloud-engineering/resources/aws-patterns.md +742 -0
- package/.claude/skills/cloud-engineering/resources/azure-patterns.md +714 -0
- package/.claude/skills/cloud-engineering/resources/cleared-cloud-environments.md +987 -0
- package/.claude/skills/cloud-engineering/resources/cloud-cost-optimization.md +757 -0
- package/.claude/skills/cloud-engineering/resources/cloud-networking.md +1058 -0
- package/.claude/skills/cloud-engineering/resources/cloud-security-tools.md +1530 -0
- package/.claude/skills/cloud-engineering/resources/cloud-security.md +990 -0
- package/.claude/skills/cloud-engineering/resources/gcp-patterns.md +758 -0
- package/.claude/skills/cloud-engineering/resources/migration-strategies.md +820 -0
- package/.claude/skills/cloud-engineering/resources/multi-cloud-strategies.md +670 -0
- package/.claude/skills/cloud-engineering/resources/oci-patterns.md +1198 -0
- package/.claude/skills/cloud-engineering/resources/serverless-patterns.md +795 -0
- package/.claude/skills/cloud-engineering/resources/well-architected-frameworks.md +966 -0
- package/.claude/skills/cybersecurity/SKILL.md +409 -0
- package/.claude/skills/cybersecurity/resources/security-architecture.md +266 -0
- package/.claude/skills/database-engineering/SKILL.md +61 -0
- package/.claude/skills/database-engineering/resources/backup-and-recovery.md +72 -0
- package/.claude/skills/database-engineering/resources/database-replication.md +63 -0
- package/.claude/skills/database-engineering/resources/postgresql-fundamentals.md +70 -0
- package/.claude/skills/database-engineering/resources/query-optimization.md +68 -0
- package/.claude/skills/devsecops/SKILL.md +374 -0
- package/.claude/skills/devsecops/resources/ci-cd-security.md +204 -0
- package/.claude/skills/devsecops/resources/compliance-automation.md +530 -0
- package/.claude/skills/devsecops/resources/compliance-frameworks.md +2322 -0
- package/.claude/skills/devsecops/resources/container-security.md +915 -0
- package/.claude/skills/devsecops/resources/cspm-integration.md +1440 -0
- package/.claude/skills/devsecops/resources/policy-enforcement.md +619 -0
- package/.claude/skills/devsecops/resources/secrets-management.md +755 -0
- package/.claude/skills/devsecops/resources/security-monitoring.md +146 -0
- package/.claude/skills/devsecops/resources/security-scanning.md +887 -0
- package/.claude/skills/devsecops/resources/security-testing.md +203 -0
- package/.claude/skills/devsecops/resources/supply-chain-security.md +518 -0
- package/.claude/skills/devsecops/resources/vulnerability-management.md +481 -0
- package/.claude/skills/devsecops/resources/zero-trust-architecture.md +177 -0
- package/.claude/skills/documentation-as-code/SKILL.md +323 -0
- package/.claude/skills/documentation-as-code/resources/api-documentation.md +90 -0
- package/.claude/skills/documentation-as-code/resources/changelog-management.md +79 -0
- package/.claude/skills/documentation-as-code/resources/diagram-generation.md +44 -0
- package/.claude/skills/documentation-as-code/resources/docs-as-code-workflow.md +99 -0
- package/.claude/skills/documentation-as-code/resources/documentation-automation.md +68 -0
- package/.claude/skills/documentation-as-code/resources/documentation-sites.md +79 -0
- package/.claude/skills/documentation-as-code/resources/markdown-best-practices.md +162 -0
- package/.claude/skills/documentation-as-code/resources/openapi-specification.md +77 -0
- package/.claude/skills/documentation-as-code/resources/readme-engineering.md +60 -0
- package/.claude/skills/documentation-as-code/resources/technical-writing-guide.md +202 -0
- package/.claude/skills/engineering-management/SKILL.md +356 -0
- package/.claude/skills/engineering-management/resources/career-ladders.md +609 -0
- package/.claude/skills/engineering-management/resources/hiring-and-assessment.md +555 -0
- package/.claude/skills/engineering-management/resources/one-on-one-guides.md +609 -0
- package/.claude/skills/engineering-management/resources/resource-planning.md +557 -0
- package/.claude/skills/engineering-management/resources/team-organization-patterns.md +491 -0
- package/.claude/skills/engineering-management/resources/technical-interviews.md +474 -0
- package/.claude/skills/engineering-operations-management/SKILL.md +817 -0
- package/.claude/skills/error-tracking/SKILL.md +379 -0
- package/.claude/skills/frontend-dev-guidelines/SKILL.md +403 -0
- package/.claude/skills/frontend-dev-guidelines/resources/common-patterns.md +331 -0
- package/.claude/skills/frontend-dev-guidelines/resources/complete-examples.md +872 -0
- package/.claude/skills/frontend-dev-guidelines/resources/component-patterns.md +502 -0
- package/.claude/skills/frontend-dev-guidelines/resources/data-fetching.md +767 -0
- package/.claude/skills/frontend-dev-guidelines/resources/file-organization.md +502 -0
- package/.claude/skills/frontend-dev-guidelines/resources/loading-and-error-states.md +501 -0
- package/.claude/skills/frontend-dev-guidelines/resources/performance.md +406 -0
- package/.claude/skills/frontend-dev-guidelines/resources/routing-guide.md +364 -0
- package/.claude/skills/frontend-dev-guidelines/resources/styling-guide.md +428 -0
- package/.claude/skills/frontend-dev-guidelines/resources/typescript-standards.md +418 -0
- package/.claude/skills/general-it-engineering/SKILL.md +393 -0
- package/.claude/skills/general-it-engineering/resources/asset-management.md +712 -0
- package/.claude/skills/general-it-engineering/resources/automation-orchestration.md +817 -0
- package/.claude/skills/general-it-engineering/resources/business-continuity.md +786 -0
- package/.claude/skills/general-it-engineering/resources/change-management.md +715 -0
- package/.claude/skills/general-it-engineering/resources/enterprise-monitoring.md +729 -0
- package/.claude/skills/general-it-engineering/resources/help-desk-operations.md +738 -0
- package/.claude/skills/general-it-engineering/resources/incident-service-management.md +834 -0
- package/.claude/skills/general-it-engineering/resources/it-governance.md +753 -0
- package/.claude/skills/general-it-engineering/resources/itil-framework.md +503 -0
- package/.claude/skills/general-it-engineering/resources/service-management.md +669 -0
- package/.claude/skills/infrastructure-architecture/SKILL.md +328 -0
- package/.claude/skills/infrastructure-architecture/resources/architecture-decision-records.md +505 -0
- package/.claude/skills/infrastructure-architecture/resources/architecture-patterns.md +528 -0
- package/.claude/skills/infrastructure-architecture/resources/capacity-planning.md +453 -0
- package/.claude/skills/infrastructure-architecture/resources/cleared-environment-architecture.md +773 -0
- package/.claude/skills/infrastructure-architecture/resources/cost-architecture.md +499 -0
- package/.claude/skills/infrastructure-architecture/resources/data-architecture.md +501 -0
- package/.claude/skills/infrastructure-architecture/resources/disaster-recovery.md +535 -0
- package/.claude/skills/infrastructure-architecture/resources/migration-architecture.md +512 -0
- package/.claude/skills/infrastructure-architecture/resources/multi-region-design.md +608 -0
- package/.claude/skills/infrastructure-architecture/resources/reference-architectures.md +562 -0
- package/.claude/skills/infrastructure-architecture/resources/security-architecture.md +538 -0
- package/.claude/skills/infrastructure-architecture/resources/system-design-principles.md +489 -0
- package/.claude/skills/infrastructure-architecture/resources/workload-classification.md +1000 -0
- package/.claude/skills/infrastructure-strategy/SKILL.md +924 -0
- package/.claude/skills/network-engineering/SKILL.md +385 -0
- package/.claude/skills/network-engineering/resources/dns-management.md +738 -0
- package/.claude/skills/network-engineering/resources/load-balancing.md +820 -0
- package/.claude/skills/network-engineering/resources/network-architecture.md +546 -0
- package/.claude/skills/network-engineering/resources/network-security.md +921 -0
- package/.claude/skills/network-engineering/resources/network-troubleshooting.md +749 -0
- package/.claude/skills/network-engineering/resources/routing-switching.md +373 -0
- package/.claude/skills/network-engineering/resources/sdn-networking.md +695 -0
- package/.claude/skills/network-engineering/resources/service-mesh-networking.md +777 -0
- package/.claude/skills/network-engineering/resources/tcp-ip-protocols.md +444 -0
- package/.claude/skills/network-engineering/resources/vpn-connectivity.md +672 -0
- package/.claude/skills/observability-engineering/SKILL.md +101 -0
- package/.claude/skills/observability-engineering/resources/apm-tools.md +97 -0
- package/.claude/skills/observability-engineering/resources/correlation-strategies.md +87 -0
- package/.claude/skills/observability-engineering/resources/distributed-tracing.md +98 -0
- package/.claude/skills/observability-engineering/resources/logs-aggregation.md +118 -0
- package/.claude/skills/observability-engineering/resources/observability-cost-optimization.md +141 -0
- package/.claude/skills/observability-engineering/resources/opentelemetry.md +110 -0
- package/.claude/skills/platform-engineering/SKILL.md +555 -0
- package/.claude/skills/platform-engineering/resources/architecture-overview.md +600 -0
- package/.claude/skills/platform-engineering/resources/container-orchestration.md +916 -0
- package/.claude/skills/platform-engineering/resources/cost-optimization.md +634 -0
- package/.claude/skills/platform-engineering/resources/developer-platforms.md +670 -0
- package/.claude/skills/platform-engineering/resources/gitops-automation.md +650 -0
- package/.claude/skills/platform-engineering/resources/infrastructure-as-code.md +778 -0
- package/.claude/skills/platform-engineering/resources/infrastructure-standards.md +708 -0
- package/.claude/skills/platform-engineering/resources/multi-tenancy.md +602 -0
- package/.claude/skills/platform-engineering/resources/platform-security.md +711 -0
- package/.claude/skills/platform-engineering/resources/resource-management.md +592 -0
- package/.claude/skills/platform-engineering/resources/service-mesh.md +628 -0
- package/.claude/skills/release-engineering/SKILL.md +393 -0
- package/.claude/skills/release-engineering/resources/artifact-management.md +108 -0
- package/.claude/skills/release-engineering/resources/build-optimization.md +84 -0
- package/.claude/skills/release-engineering/resources/ci-cd-pipelines.md +411 -0
- package/.claude/skills/release-engineering/resources/deployment-strategies.md +197 -0
- package/.claude/skills/release-engineering/resources/pipeline-security.md +62 -0
- package/.claude/skills/release-engineering/resources/progressive-delivery.md +83 -0
- package/.claude/skills/release-engineering/resources/release-automation.md +68 -0
- package/.claude/skills/release-engineering/resources/release-orchestration.md +77 -0
- package/.claude/skills/release-engineering/resources/rollback-strategies.md +66 -0
- package/.claude/skills/release-engineering/resources/versioning-strategies.md +59 -0
- package/.claude/skills/route-tester/SKILL.md +392 -0
- package/.claude/skills/skill-developer/ADVANCED.md +197 -0
- package/.claude/skills/skill-developer/HOOK_MECHANISMS.md +306 -0
- package/.claude/skills/skill-developer/PATTERNS_LIBRARY.md +152 -0
- package/.claude/skills/skill-developer/SKILL.md +430 -0
- package/.claude/skills/skill-developer/SKILL_RULES_REFERENCE.md +315 -0
- package/.claude/skills/skill-developer/TRIGGER_TYPES.md +305 -0
- package/.claude/skills/skill-developer/TROUBLESHOOTING.md +514 -0
- package/.claude/skills/skill-rules.json +2940 -0
- package/.claude/skills/sre/SKILL.md +464 -0
- package/.claude/skills/sre/resources/alerting-best-practices.md +282 -0
- package/.claude/skills/sre/resources/capacity-planning.md +226 -0
- package/.claude/skills/sre/resources/chaos-engineering.md +193 -0
- package/.claude/skills/sre/resources/disaster-recovery.md +232 -0
- package/.claude/skills/sre/resources/incident-management.md +436 -0
- package/.claude/skills/sre/resources/observability-stack.md +240 -0
- package/.claude/skills/sre/resources/on-call-runbooks.md +167 -0
- package/.claude/skills/sre/resources/performance-optimization.md +108 -0
- package/.claude/skills/sre/resources/reliability-patterns.md +183 -0
- package/.claude/skills/sre/resources/slo-sli-sla.md +464 -0
- package/.claude/skills/sre/resources/toil-reduction.md +145 -0
- package/.claude/skills/systems-engineering/SKILL.md +648 -0
- package/.claude/skills/systems-engineering/resources/automation-patterns.md +771 -0
- package/.claude/skills/systems-engineering/resources/configuration-management.md +998 -0
- package/.claude/skills/systems-engineering/resources/linux-administration.md +672 -0
- package/.claude/skills/systems-engineering/resources/networking-fundamentals.md +982 -0
- package/.claude/skills/systems-engineering/resources/performance-tuning.md +871 -0
- package/.claude/skills/systems-engineering/resources/powershell-scripting.md +482 -0
- package/.claude/skills/systems-engineering/resources/security-hardening.md +739 -0
- package/.claude/skills/systems-engineering/resources/shell-scripting.md +915 -0
- package/.claude/skills/systems-engineering/resources/storage-management.md +628 -0
- package/.claude/skills/systems-engineering/resources/system-monitoring.md +787 -0
- package/.claude/skills/systems-engineering/resources/troubleshooting-guide.md +753 -0
- package/.claude/skills/systems-engineering/resources/windows-administration.md +738 -0
- package/.claude/skills/technical-leadership/SKILL.md +728 -0
- package/CHANGELOG.md +90 -54
- package/README.md +94 -0
- package/backend/docs/SECRETS_DOCUMENTATION.md +327 -0
- package/backend/jest.config.js +59 -0
- package/backend/package-lock.json +6129 -0
- package/backend/package.json +16 -4
- package/backend/prisma/migrations/20251026104609_add_websocket_api/migration.sql +33 -0
- package/backend/prisma/schema.prisma +33 -0
- package/backend/src/__tests__/core/DependencyService.test.js +336 -0
- package/backend/src/__tests__/core/UserService.test.js +875 -0
- package/backend/src/__tests__/repositories/BaseRepository.test.js +146 -0
- package/backend/src/__tests__/repositories/BotRepository.test.js +118 -0
- package/backend/src/__tests__/repositories/CommandRepository.test.js +132 -0
- package/backend/src/__tests__/repositories/EventGraphRepository.test.js +93 -0
- package/backend/src/__tests__/repositories/GroupRepository.test.js +155 -0
- package/backend/src/__tests__/repositories/PermissionRepository.test.js +130 -0
- package/backend/src/__tests__/repositories/PluginRepository.test.js +107 -0
- package/backend/src/__tests__/repositories/ServerRepository.test.js +80 -0
- package/backend/src/__tests__/repositories/UserRepository.test.js +128 -0
- package/backend/src/__tests__/secretsFilter.test.js +425 -0
- package/backend/src/__tests__/services/BotLifecycleService.test.js +411 -0
- package/backend/src/__tests__/services/BotProcessManager.test.js +285 -0
- package/backend/src/__tests__/services/CacheManager.test.js +125 -0
- package/backend/src/__tests__/services/CommandExecutionService.test.js +460 -0
- package/backend/src/__tests__/services/ResourceMonitorService.test.js +207 -0
- package/backend/src/__tests__/services/TelemetryService.test.js +291 -0
- package/backend/src/__tests__/setup.js +25 -0
- package/backend/src/api/routes/apiKeys.js +181 -0
- package/backend/src/api/routes/bots.js +49 -7
- package/backend/src/api/routes/plugins.js +2 -1
- package/backend/src/api/routes/system.js +174 -0
- package/backend/src/container.js +82 -0
- package/backend/src/core/BotManager.js +142 -871
- package/backend/src/core/BotManager.old.js +1093 -0
- package/backend/src/core/BotProcess.js +1092 -858
- package/backend/src/core/EventGraphManager.js +280 -198
- package/backend/src/core/GraphExecutionEngine.js +321 -325
- package/backend/src/core/MessageQueue.js +27 -6
- package/backend/src/core/NodeRegistry.js +37 -1134
- package/backend/src/core/PluginManager.js +62 -12
- package/backend/src/core/PrismaService.js +32 -0
- package/backend/src/core/UserService.js +3 -3
- package/backend/src/core/__tests__/PrismaService.test.js +24 -0
- package/backend/src/core/commands/README.md +305 -0
- package/backend/src/core/commands/dev.js +13 -7
- package/backend/src/core/commands/ping.js +10 -4
- package/backend/src/core/commands/whois.js +63 -0
- package/backend/src/core/config/validation.js +27 -0
- package/backend/src/core/constants/graphTypes.js +21 -0
- package/backend/src/core/node-registries/actions.js +132 -0
- package/backend/src/core/node-registries/arrays.js +137 -0
- package/backend/src/core/node-registries/bot.js +23 -0
- package/backend/src/core/node-registries/data.js +290 -0
- package/backend/src/core/node-registries/debug.js +26 -0
- package/backend/src/core/node-registries/events.js +187 -0
- package/backend/src/core/node-registries/flow.js +139 -0
- package/backend/src/core/node-registries/logic.js +45 -0
- package/backend/src/core/node-registries/math.js +42 -0
- package/backend/src/core/node-registries/objects.js +98 -0
- package/backend/src/core/node-registries/strings.js +153 -0
- package/backend/src/core/node-registries/time.js +113 -0
- package/backend/src/core/node-registries/users.js +79 -0
- package/backend/src/core/nodes/{action_bot_look_at.js → actions/bot_look_at.js} +36 -36
- package/backend/src/core/nodes/{action_bot_set_variable.js → actions/bot_set_variable.js} +32 -32
- package/backend/src/core/nodes/{action_send_log.js → actions/send_log.js} +28 -23
- package/backend/src/core/nodes/{action_send_message.js → actions/send_message.js} +32 -32
- package/backend/src/core/nodes/actions/send_websocket_response.js +33 -0
- package/backend/src/core/nodes/arrays/get_next.js +35 -0
- package/backend/src/core/nodes/{data_cast.js → data/cast.js} +8 -0
- package/backend/src/core/nodes/data/datetime_literal.js +27 -0
- package/backend/src/core/nodes/data/entity_info.js +69 -0
- package/backend/src/core/nodes/data/get_nearby_entities.js +32 -0
- package/backend/src/core/nodes/data/get_nearby_players.js +64 -0
- package/backend/src/core/nodes/{data_get_user_field.js → data/get_user_field.js} +1 -1
- package/backend/src/core/nodes/data/type_check.js +53 -0
- package/backend/src/core/nodes/{debug_log.js → debug/log.js} +16 -16
- package/backend/src/core/nodes/{flow_branch.js → flow/branch.js} +15 -15
- package/backend/src/core/nodes/{flow_break.js → flow/break.js} +14 -14
- package/backend/src/core/nodes/flow/delay.js +43 -0
- package/backend/src/core/nodes/{flow_for_each.js → flow/for_each.js} +39 -39
- package/backend/src/core/nodes/{flow_sequence.js → flow/sequence.js} +16 -16
- package/backend/src/core/nodes/{flow_switch.js → flow/switch.js} +47 -47
- package/backend/src/core/nodes/{flow_while.js → flow/while.js} +1 -1
- package/backend/src/core/nodes/logic/__tests__/compare.test.js +83 -0
- package/backend/src/core/nodes/math/__tests__/operation.test.js +65 -0
- package/backend/src/core/nodes/strings/__tests__/concat.test.js +89 -0
- package/backend/src/core/nodes/time/__tests__/now.test.js +24 -0
- package/backend/src/core/nodes/time/add.js +33 -0
- package/backend/src/core/nodes/time/compare.js +35 -0
- package/backend/src/core/nodes/time/diff.js +29 -0
- package/backend/src/core/nodes/time/format.js +32 -0
- package/backend/src/core/nodes/time/now.js +18 -0
- package/backend/src/core/nodes/{user_check_blacklist.js → users/check_blacklist.js} +37 -37
- package/backend/src/core/nodes/{user_get_groups.js → users/get_groups.js} +36 -36
- package/backend/src/core/nodes/{user_get_permissions.js → users/get_permissions.js} +36 -36
- package/backend/src/core/nodes/{user_set_blacklist.js → users/set_blacklist.js} +37 -37
- package/backend/src/core/services/BotLifecycleService.js +596 -0
- package/backend/src/core/services/BotProcessManager.js +163 -0
- package/backend/src/core/services/CacheManager.js +111 -0
- package/backend/src/core/services/CommandExecutionService.js +351 -0
- package/backend/src/core/services/ResourceMonitorService.js +90 -0
- package/backend/src/core/services/TelemetryService.js +124 -0
- package/backend/src/core/services/ValidationService.js +132 -0
- package/backend/src/core/services/__tests__/ValidationService.test.js +148 -0
- package/backend/src/core/services.js +20 -5
- package/backend/src/core/system/CommandContext.js +84 -0
- package/backend/src/core/system/Transport.js +78 -0
- package/backend/src/core/utils/__tests__/jsonParser.test.js +44 -0
- package/backend/src/core/utils/jsonParser.js +18 -0
- package/backend/src/core/utils/secretsFilter.js +262 -0
- package/backend/src/core/utils/variableParser.js +89 -0
- package/backend/src/core/validation/__tests__/nodeSchemas.test.js +175 -0
- package/backend/src/core/validation/nodeSchemas.js +112 -0
- package/backend/src/lib/prisma.js +2 -4
- package/backend/src/real-time/botApi/handlers/commandHandlers.js +28 -0
- package/backend/src/real-time/botApi/handlers/graphHandlers.js +99 -0
- package/backend/src/real-time/botApi/handlers/graphWebSocketHandlers.js +147 -0
- package/backend/src/real-time/botApi/handlers/index.js +43 -0
- package/backend/src/real-time/botApi/handlers/messageHandlers.js +66 -0
- package/backend/src/real-time/botApi/handlers/statusHandlers.js +17 -0
- package/backend/src/real-time/botApi/handlers/userHandlers.js +141 -0
- package/backend/src/real-time/botApi/index.js +40 -0
- package/backend/src/real-time/botApi/middleware.js +79 -0
- package/backend/src/real-time/botApi/utils.js +54 -0
- package/backend/src/real-time/socketHandler.js +6 -2
- package/backend/src/repositories/BaseRepository.js +43 -0
- package/backend/src/repositories/BotRepository.js +42 -0
- package/backend/src/repositories/CommandRepository.js +53 -0
- package/backend/src/repositories/EventGraphRepository.js +40 -0
- package/backend/src/repositories/GroupRepository.js +69 -0
- package/backend/src/repositories/PermissionRepository.js +48 -0
- package/backend/src/repositories/PluginRepository.js +42 -0
- package/backend/src/repositories/ServerRepository.js +27 -0
- package/backend/src/repositories/UserRepository.js +48 -0
- package/backend/src/server.js +3 -0
- package/backend/src/test-refactor.js +85 -0
- package/frontend/dist/assets/index-CfTo92bP.css +1 -0
- package/frontend/dist/assets/index-CiFD5X9Z.js +8344 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/package.json +0 -5
- package/package.json +2 -1
- package/frontend/dist/assets/index-B9GedHEa.js +0 -8352
- package/frontend/dist/assets/index-zLiy9MDx.css +0 -1
- package/nul +0 -0
- /package/backend/src/core/nodes/{action_http_request.js → actions/http_request.js} +0 -0
- /package/backend/src/core/nodes/{array_add_element.js → arrays/add_element.js} +0 -0
- /package/backend/src/core/nodes/{array_contains.js → arrays/contains.js} +0 -0
- /package/backend/src/core/nodes/{array_find_index.js → arrays/find_index.js} +0 -0
- /package/backend/src/core/nodes/{array_get_by_index.js → arrays/get_by_index.js} +0 -0
- /package/backend/src/core/nodes/{array_get_random_element.js → arrays/get_random_element.js} +0 -0
- /package/backend/src/core/nodes/{array_remove_by_index.js → arrays/remove_by_index.js} +0 -0
- /package/backend/src/core/nodes/{bot_get_position.js → bot/get_position.js} +0 -0
- /package/backend/src/core/nodes/{data_array_literal.js → data/array_literal.js} +0 -0
- /package/backend/src/core/nodes/{data_boolean_literal.js → data/boolean_literal.js} +0 -0
- /package/backend/src/core/nodes/{data_get_argument.js → data/get_argument.js} +0 -0
- /package/backend/src/core/nodes/{data_get_bot_look.js → data/get_bot_look.js} +0 -0
- /package/backend/src/core/nodes/{data_get_entity_field.js → data/get_entity_field.js} +0 -0
- /package/backend/src/core/nodes/{data_get_server_players.js → data/get_server_players.js} +0 -0
- /package/backend/src/core/nodes/{data_get_variable.js → data/get_variable.js} +0 -0
- /package/backend/src/core/nodes/{data_length.js → data/length.js} +0 -0
- /package/backend/src/core/nodes/{data_make_object.js → data/make_object.js} +0 -0
- /package/backend/src/core/nodes/{data_number_literal.js → data/number_literal.js} +0 -0
- /package/backend/src/core/nodes/{data_string_literal.js → data/string_literal.js} +0 -0
- /package/backend/src/core/nodes/{logic_compare.js → logic/compare.js} +0 -0
- /package/backend/src/core/nodes/{logic_operation.js → logic/operation.js} +0 -0
- /package/backend/src/core/nodes/{math_operation.js → math/operation.js} +0 -0
- /package/backend/src/core/nodes/{math_random_number.js → math/random_number.js} +0 -0
- /package/backend/src/core/nodes/{object_create.js → objects/create.js} +0 -0
- /package/backend/src/core/nodes/{object_delete.js → objects/delete.js} +0 -0
- /package/backend/src/core/nodes/{object_get.js → objects/get.js} +0 -0
- /package/backend/src/core/nodes/{object_has_key.js → objects/has_key.js} +0 -0
- /package/backend/src/core/nodes/{object_set.js → objects/set.js} +0 -0
- /package/backend/src/core/nodes/{string_concat.js → strings/concat.js} +0 -0
- /package/backend/src/core/nodes/{string_contains.js → strings/contains.js} +0 -0
- /package/backend/src/core/nodes/{string_ends_with.js → strings/ends_with.js} +0 -0
- /package/backend/src/core/nodes/{string_equals.js → strings/equals.js} +0 -0
- /package/backend/src/core/nodes/{string_length.js → strings/length.js} +0 -0
- /package/backend/src/core/nodes/{string_matches.js → strings/matches.js} +0 -0
- /package/backend/src/core/nodes/{string_split.js → strings/split.js} +0 -0
- /package/backend/src/core/nodes/{string_starts_with.js → strings/starts_with.js} +0 -0
|
@@ -0,0 +1,1440 @@
|
|
|
1
|
+
# CSPM Integration
|
|
2
|
+
|
|
3
|
+
Cloud Security Posture Management (CSPM) tool integration into CI/CD pipelines for continuous security validation and compliance enforcement.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Overview](#overview)
|
|
8
|
+
- [Pipeline Integration Patterns](#pipeline-integration-patterns)
|
|
9
|
+
- [Tool-Specific Integration](#tool-specific-integration)
|
|
10
|
+
- [Policy as Code](#policy-as-code)
|
|
11
|
+
- [Shift-Left Security](#shift-left-security)
|
|
12
|
+
- [Continuous Compliance](#continuous-compliance)
|
|
13
|
+
- [Remediation Workflows](#remediation-workflows)
|
|
14
|
+
- [Best Practices](#best-practices)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Overview
|
|
19
|
+
|
|
20
|
+
**CSPM Integration** enables security and compliance checks throughout the development lifecycle, catching misconfigurations before deployment.
|
|
21
|
+
|
|
22
|
+
**Integration Points:**
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
CI/CD Pipeline with CSPM:
|
|
26
|
+
┌─────────────────────────────────────────────────────┐
|
|
27
|
+
│ DEVELOPMENT │
|
|
28
|
+
│ ┌──────────────┐ │
|
|
29
|
+
│ │ IDE Plugins │ → Pre-commit hooks │
|
|
30
|
+
│ │ - Checkov │ (local scanning) │
|
|
31
|
+
│ │ - tfsec │ │
|
|
32
|
+
│ └──────────────┘ │
|
|
33
|
+
├─────────────────────────────────────────────────────┤
|
|
34
|
+
│ SOURCE CONTROL │
|
|
35
|
+
│ ┌──────────────┐ │
|
|
36
|
+
│ │ Git Push │ → PR/MR scan │
|
|
37
|
+
│ │ │ (automated checks) │
|
|
38
|
+
│ └──────────────┘ │
|
|
39
|
+
├─────────────────────────────────────────────────────┤
|
|
40
|
+
│ CI/CD PIPELINE │
|
|
41
|
+
│ ┌──────────────┐ ┌──────────────┐ │
|
|
42
|
+
│ │ Build │ → │ CSPM Scan │ │
|
|
43
|
+
│ │ │ │ - IaC scan │ │
|
|
44
|
+
│ │ │ │ - Image scan │ │
|
|
45
|
+
│ └──────────────┘ └──────────────┘ │
|
|
46
|
+
│ ↓ │
|
|
47
|
+
│ ┌──────────────┐ │
|
|
48
|
+
│ │ Gate Check │ │
|
|
49
|
+
│ │ Pass/Fail │ │
|
|
50
|
+
│ └──────────────┘ │
|
|
51
|
+
├─────────────────────────────────────────────────────┤
|
|
52
|
+
│ RUNTIME │
|
|
53
|
+
│ ┌──────────────┐ │
|
|
54
|
+
│ │ Continuous │ → Runtime scanning │
|
|
55
|
+
│ │ Monitoring │ (drift detection) │
|
|
56
|
+
│ └──────────────┘ │
|
|
57
|
+
└─────────────────────────────────────────────────────┘
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Pipeline Integration Patterns
|
|
63
|
+
|
|
64
|
+
### GitHub Actions Integration
|
|
65
|
+
|
|
66
|
+
**1. Prisma Cloud (Checkov)**
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
# .github/workflows/prisma-scan.yml
|
|
70
|
+
name: Prisma Cloud IaC Scan
|
|
71
|
+
|
|
72
|
+
on:
|
|
73
|
+
pull_request:
|
|
74
|
+
branches: [main, develop]
|
|
75
|
+
push:
|
|
76
|
+
branches: [main]
|
|
77
|
+
|
|
78
|
+
jobs:
|
|
79
|
+
prisma_cloud_scan:
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
name: Prisma Cloud IaC Scan
|
|
82
|
+
|
|
83
|
+
steps:
|
|
84
|
+
- name: Checkout code
|
|
85
|
+
uses: actions/checkout@v3
|
|
86
|
+
|
|
87
|
+
- name: Run Prisma Cloud IaC Scan
|
|
88
|
+
uses: bridgecrewio/checkov-action@master
|
|
89
|
+
with:
|
|
90
|
+
# Prisma Cloud API credentials
|
|
91
|
+
api-key: ${{ secrets.PRISMA_ACCESS_KEY }}::${{ secrets.PRISMA_SECRET_KEY }}
|
|
92
|
+
|
|
93
|
+
# Scan directories
|
|
94
|
+
directory: terraform/
|
|
95
|
+
framework: terraform,kubernetes,dockerfile
|
|
96
|
+
|
|
97
|
+
# Fail pipeline on findings
|
|
98
|
+
soft_fail: false
|
|
99
|
+
|
|
100
|
+
# Skip specific checks
|
|
101
|
+
skip_check: CKV_AWS_18,CKV_AWS_19
|
|
102
|
+
|
|
103
|
+
# Output formats
|
|
104
|
+
output_format: cli,sarif,junitxml
|
|
105
|
+
output_file_path: console,results.sarif,results.xml
|
|
106
|
+
|
|
107
|
+
# Compliance frameworks
|
|
108
|
+
check: CKV_AWS_*,CKV_K8S_*
|
|
109
|
+
|
|
110
|
+
- name: Upload SARIF file
|
|
111
|
+
if: always()
|
|
112
|
+
uses: github/codeql-action/upload-sarif@v2
|
|
113
|
+
with:
|
|
114
|
+
sarif_file: results.sarif
|
|
115
|
+
|
|
116
|
+
- name: Upload test results
|
|
117
|
+
if: always()
|
|
118
|
+
uses: actions/upload-artifact@v3
|
|
119
|
+
with:
|
|
120
|
+
name: prisma-scan-results
|
|
121
|
+
path: results.xml
|
|
122
|
+
|
|
123
|
+
- name: Comment PR with results
|
|
124
|
+
if: github.event_name == 'pull_request'
|
|
125
|
+
uses: actions/github-script@v6
|
|
126
|
+
with:
|
|
127
|
+
script: |
|
|
128
|
+
const fs = require('fs');
|
|
129
|
+
const results = fs.readFileSync('results.xml', 'utf8');
|
|
130
|
+
// Parse and format results
|
|
131
|
+
github.rest.issues.createComment({
|
|
132
|
+
issue_number: context.issue.number,
|
|
133
|
+
owner: context.repo.owner,
|
|
134
|
+
repo: context.repo.repo,
|
|
135
|
+
body: `## Prisma Cloud Scan Results\n\n${results}`
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**2. Wiz CLI Integration**
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
# .github/workflows/wiz-scan.yml
|
|
143
|
+
name: Wiz IaC Security Scan
|
|
144
|
+
|
|
145
|
+
on:
|
|
146
|
+
pull_request:
|
|
147
|
+
push:
|
|
148
|
+
branches: [main]
|
|
149
|
+
|
|
150
|
+
jobs:
|
|
151
|
+
wiz_scan:
|
|
152
|
+
runs-on: ubuntu-latest
|
|
153
|
+
|
|
154
|
+
steps:
|
|
155
|
+
- name: Checkout code
|
|
156
|
+
uses: actions/checkout@v3
|
|
157
|
+
|
|
158
|
+
- name: Download Wiz CLI
|
|
159
|
+
run: |
|
|
160
|
+
curl -o wizcli https://wizcli.app.wiz.io/wizcli
|
|
161
|
+
chmod +x wizcli
|
|
162
|
+
|
|
163
|
+
- name: Authenticate Wiz
|
|
164
|
+
env:
|
|
165
|
+
WIZ_CLIENT_ID: ${{ secrets.WIZ_CLIENT_ID }}
|
|
166
|
+
WIZ_CLIENT_SECRET: ${{ secrets.WIZ_CLIENT_SECRET }}
|
|
167
|
+
run: |
|
|
168
|
+
./wizcli auth
|
|
169
|
+
|
|
170
|
+
- name: Scan IaC
|
|
171
|
+
run: |
|
|
172
|
+
./wizcli iac scan \
|
|
173
|
+
--path ./terraform \
|
|
174
|
+
--policy-id ${{ secrets.WIZ_POLICY_ID }} \
|
|
175
|
+
--output-format json \
|
|
176
|
+
--output-file wiz-results.json \
|
|
177
|
+
--fail-on high
|
|
178
|
+
|
|
179
|
+
- name: Upload results
|
|
180
|
+
if: always()
|
|
181
|
+
uses: actions/upload-artifact@v3
|
|
182
|
+
with:
|
|
183
|
+
name: wiz-scan-results
|
|
184
|
+
path: wiz-results.json
|
|
185
|
+
|
|
186
|
+
- name: Scan Docker images
|
|
187
|
+
run: |
|
|
188
|
+
docker build -t myapp:${{ github.sha }} .
|
|
189
|
+
./wizcli docker scan \
|
|
190
|
+
--image myapp:${{ github.sha }} \
|
|
191
|
+
--policy "Production Policy" \
|
|
192
|
+
--fail-on high
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**3. Trend Micro Cloud One**
|
|
196
|
+
|
|
197
|
+
```yaml
|
|
198
|
+
# .github/workflows/trend-micro-scan.yml
|
|
199
|
+
name: Trend Micro Container Scan
|
|
200
|
+
|
|
201
|
+
on:
|
|
202
|
+
push:
|
|
203
|
+
branches: [main, develop]
|
|
204
|
+
|
|
205
|
+
jobs:
|
|
206
|
+
container_scan:
|
|
207
|
+
runs-on: ubuntu-latest
|
|
208
|
+
|
|
209
|
+
steps:
|
|
210
|
+
- name: Checkout code
|
|
211
|
+
uses: actions/checkout@v3
|
|
212
|
+
|
|
213
|
+
- name: Build Docker image
|
|
214
|
+
run: |
|
|
215
|
+
docker build -t ${{ github.repository }}:${{ github.sha }} .
|
|
216
|
+
|
|
217
|
+
- name: Scan with Trend Micro
|
|
218
|
+
uses: deep-security/smartcheck-scan-action@v3
|
|
219
|
+
with:
|
|
220
|
+
dssc-image-name: ${{ github.repository }}:${{ github.sha }}
|
|
221
|
+
dssc-host: ${{ secrets.DSSC_HOST }}
|
|
222
|
+
dssc-username: ${{ secrets.DSSC_USERNAME }}
|
|
223
|
+
dssc-password: ${{ secrets.DSSC_PASSWORD }}
|
|
224
|
+
dssc-insecure-skip-tls-verify: false
|
|
225
|
+
dssc-min-severity: medium
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### GitLab CI Integration
|
|
229
|
+
|
|
230
|
+
```yaml
|
|
231
|
+
# .gitlab-ci.yml
|
|
232
|
+
stages:
|
|
233
|
+
- build
|
|
234
|
+
- security_scan
|
|
235
|
+
- deploy
|
|
236
|
+
|
|
237
|
+
variables:
|
|
238
|
+
IMAGE_NAME: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}
|
|
239
|
+
|
|
240
|
+
build:
|
|
241
|
+
stage: build
|
|
242
|
+
script:
|
|
243
|
+
- docker build -t ${IMAGE_NAME} .
|
|
244
|
+
- docker push ${IMAGE_NAME}
|
|
245
|
+
|
|
246
|
+
# Prisma Cloud scan
|
|
247
|
+
prisma_iac_scan:
|
|
248
|
+
stage: security_scan
|
|
249
|
+
image: bridgecrew/checkov:latest
|
|
250
|
+
script:
|
|
251
|
+
- |
|
|
252
|
+
checkov \
|
|
253
|
+
--directory terraform/ \
|
|
254
|
+
--framework terraform \
|
|
255
|
+
--output cli \
|
|
256
|
+
--output junitxml \
|
|
257
|
+
--output-file-path console,prisma-results.xml \
|
|
258
|
+
--prisma-api-url https://api.prismacloud.io \
|
|
259
|
+
--bc-api-key ${PRISMA_ACCESS_KEY}::${PRISMA_SECRET_KEY} \
|
|
260
|
+
--repo-id ${CI_PROJECT_PATH} \
|
|
261
|
+
--branch ${CI_COMMIT_REF_NAME}
|
|
262
|
+
artifacts:
|
|
263
|
+
reports:
|
|
264
|
+
junit: prisma-results.xml
|
|
265
|
+
paths:
|
|
266
|
+
- prisma-results.xml
|
|
267
|
+
expire_in: 30 days
|
|
268
|
+
allow_failure: false
|
|
269
|
+
|
|
270
|
+
# Aqua Security scan
|
|
271
|
+
aqua_image_scan:
|
|
272
|
+
stage: security_scan
|
|
273
|
+
image: aquasec/aqua-scanner:latest
|
|
274
|
+
script:
|
|
275
|
+
- |
|
|
276
|
+
docker run --rm \
|
|
277
|
+
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
278
|
+
aquasec/aqua-scanner:latest \
|
|
279
|
+
scan \
|
|
280
|
+
--host ${AQUA_SERVER} \
|
|
281
|
+
--user ${AQUA_USERNAME} \
|
|
282
|
+
--password ${AQUA_PASSWORD} \
|
|
283
|
+
--local ${IMAGE_NAME} \
|
|
284
|
+
--register \
|
|
285
|
+
--show-negligible
|
|
286
|
+
allow_failure: false
|
|
287
|
+
|
|
288
|
+
# Native GitLab SAST
|
|
289
|
+
sast:
|
|
290
|
+
stage: security_scan
|
|
291
|
+
include:
|
|
292
|
+
- template: Security/SAST.gitlab-ci.yml
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Jenkins Pipeline
|
|
296
|
+
|
|
297
|
+
```groovy
|
|
298
|
+
// Jenkinsfile
|
|
299
|
+
pipeline {
|
|
300
|
+
agent any
|
|
301
|
+
|
|
302
|
+
environment {
|
|
303
|
+
PRISMA_API_KEY = credentials('prisma-api-key')
|
|
304
|
+
WIZ_CLIENT_ID = credentials('wiz-client-id')
|
|
305
|
+
WIZ_CLIENT_SECRET = credentials('wiz-client-secret')
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
stages {
|
|
309
|
+
stage('Checkout') {
|
|
310
|
+
steps {
|
|
311
|
+
checkout scm
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
stage('IaC Security Scan - Prisma Cloud') {
|
|
316
|
+
steps {
|
|
317
|
+
script {
|
|
318
|
+
docker.image('bridgecrew/checkov:latest').inside {
|
|
319
|
+
sh '''
|
|
320
|
+
checkov \
|
|
321
|
+
--directory terraform/ \
|
|
322
|
+
--framework terraform,kubernetes \
|
|
323
|
+
--output cli \
|
|
324
|
+
--output junitxml \
|
|
325
|
+
--output-file-path console,results.xml \
|
|
326
|
+
--bc-api-key ${PRISMA_API_KEY} \
|
|
327
|
+
--repo-id ${JOB_NAME} \
|
|
328
|
+
--branch ${GIT_BRANCH}
|
|
329
|
+
'''
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
post {
|
|
334
|
+
always {
|
|
335
|
+
junit 'results.xml'
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
stage('Container Security Scan - Aqua') {
|
|
341
|
+
steps {
|
|
342
|
+
script {
|
|
343
|
+
sh '''
|
|
344
|
+
docker run --rm \
|
|
345
|
+
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
346
|
+
aquasec/aqua-scanner:latest \
|
|
347
|
+
scan \
|
|
348
|
+
--host ${AQUA_SERVER} \
|
|
349
|
+
--user ${AQUA_USERNAME} \
|
|
350
|
+
--password ${AQUA_PASSWORD} \
|
|
351
|
+
--local myapp:${BUILD_NUMBER}
|
|
352
|
+
'''
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
stage('Policy Gate Check') {
|
|
358
|
+
steps {
|
|
359
|
+
script {
|
|
360
|
+
// Parse scan results
|
|
361
|
+
def scanResults = readJSON file: 'results.json'
|
|
362
|
+
def criticalCount = scanResults.summary.critical
|
|
363
|
+
def highCount = scanResults.summary.high
|
|
364
|
+
|
|
365
|
+
// Fail if critical or high severity findings
|
|
366
|
+
if (criticalCount > 0 || highCount > 5) {
|
|
367
|
+
error("Security scan failed: ${criticalCount} critical, ${highCount} high severity findings")
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
stage('Deploy') {
|
|
374
|
+
when {
|
|
375
|
+
branch 'main'
|
|
376
|
+
}
|
|
377
|
+
steps {
|
|
378
|
+
echo 'Deploying to production...'
|
|
379
|
+
// Deployment steps
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
post {
|
|
385
|
+
always {
|
|
386
|
+
// Send notifications
|
|
387
|
+
emailext(
|
|
388
|
+
subject: "Security Scan Results - ${JOB_NAME} #${BUILD_NUMBER}",
|
|
389
|
+
body: "Security scan completed. Check Jenkins for details.",
|
|
390
|
+
to: "security@company.com"
|
|
391
|
+
)
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Tool-Specific Integration
|
|
400
|
+
|
|
401
|
+
### Prisma Cloud (Checkov) Configuration
|
|
402
|
+
|
|
403
|
+
**1. Custom Policy Configuration**
|
|
404
|
+
|
|
405
|
+
```yaml
|
|
406
|
+
# .checkov.yml
|
|
407
|
+
# Prisma Cloud / Checkov configuration
|
|
408
|
+
|
|
409
|
+
branch: main
|
|
410
|
+
skip-path:
|
|
411
|
+
- tests/
|
|
412
|
+
- .terraform/
|
|
413
|
+
- node_modules/
|
|
414
|
+
|
|
415
|
+
skip-check:
|
|
416
|
+
# Skip specific checks that don't apply
|
|
417
|
+
- CKV_AWS_18 # EBS encryption (not applicable to public AMIs)
|
|
418
|
+
- CKV_K8S_8 # Liveness probe (not applicable to jobs)
|
|
419
|
+
|
|
420
|
+
framework:
|
|
421
|
+
- terraform
|
|
422
|
+
- kubernetes
|
|
423
|
+
- dockerfile
|
|
424
|
+
- helm
|
|
425
|
+
- cloudformation
|
|
426
|
+
|
|
427
|
+
output: cli,junitxml,sarif
|
|
428
|
+
|
|
429
|
+
# Soft fail mode (for initial rollout)
|
|
430
|
+
soft-fail: false
|
|
431
|
+
|
|
432
|
+
# External checks directory
|
|
433
|
+
external-checks-dir:
|
|
434
|
+
- custom-policies/
|
|
435
|
+
|
|
436
|
+
# Compact output
|
|
437
|
+
compact: true
|
|
438
|
+
|
|
439
|
+
# Prisma Cloud integration
|
|
440
|
+
prisma-api-url: https://api.prismacloud.io
|
|
441
|
+
repo-id: myorg/myrepo
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
**2. Custom Policies**
|
|
445
|
+
|
|
446
|
+
```python
|
|
447
|
+
# custom-policies/check_mandatory_tags.py
|
|
448
|
+
from checkov.common.models.enums import CheckResult, CheckCategories
|
|
449
|
+
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
|
|
450
|
+
|
|
451
|
+
class MandatoryTags(BaseResourceCheck):
|
|
452
|
+
def __init__(self):
|
|
453
|
+
name = "Ensure all resources have mandatory tags"
|
|
454
|
+
id = "CKV_CUSTOM_1"
|
|
455
|
+
supported_resources = ['*']
|
|
456
|
+
categories = [CheckCategories.CONVENTION]
|
|
457
|
+
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)
|
|
458
|
+
|
|
459
|
+
def scan_resource_conf(self, conf):
|
|
460
|
+
"""
|
|
461
|
+
Looks for mandatory tags on all resources
|
|
462
|
+
:param conf: resource configuration
|
|
463
|
+
:return: CheckResult
|
|
464
|
+
"""
|
|
465
|
+
required_tags = ['Environment', 'Owner', 'CostCenter', 'DataClassification']
|
|
466
|
+
|
|
467
|
+
if 'tags' in conf:
|
|
468
|
+
tags = conf['tags'][0] if isinstance(conf['tags'], list) else conf['tags']
|
|
469
|
+
missing_tags = [tag for tag in required_tags if tag not in tags]
|
|
470
|
+
|
|
471
|
+
if not missing_tags:
|
|
472
|
+
return CheckResult.PASSED
|
|
473
|
+
else:
|
|
474
|
+
self.details.append(f"Missing required tags: {', '.join(missing_tags)}")
|
|
475
|
+
return CheckResult.FAILED
|
|
476
|
+
|
|
477
|
+
self.details.append(f"No tags defined. Required tags: {', '.join(required_tags)}")
|
|
478
|
+
return CheckResult.FAILED
|
|
479
|
+
|
|
480
|
+
check = MandatoryTags()
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### Wiz Integration
|
|
484
|
+
|
|
485
|
+
**1. Wiz Policy as Code**
|
|
486
|
+
|
|
487
|
+
```yaml
|
|
488
|
+
# wiz-policies/fedramp-policy.yaml
|
|
489
|
+
name: "FedRAMP Moderate Compliance"
|
|
490
|
+
description: "Enforces FedRAMP Moderate controls for IaC"
|
|
491
|
+
severity: HIGH
|
|
492
|
+
|
|
493
|
+
rules:
|
|
494
|
+
- id: encryption-at-rest
|
|
495
|
+
description: "All storage must be encrypted at rest"
|
|
496
|
+
resource_types:
|
|
497
|
+
- aws_s3_bucket
|
|
498
|
+
- aws_ebs_volume
|
|
499
|
+
- aws_rds_instance
|
|
500
|
+
check: |
|
|
501
|
+
resource.encryption.enabled == true
|
|
502
|
+
|
|
503
|
+
- id: public-access-blocked
|
|
504
|
+
description: "No public access to resources containing sensitive data"
|
|
505
|
+
resource_types:
|
|
506
|
+
- aws_s3_bucket
|
|
507
|
+
check: |
|
|
508
|
+
resource.public_access_block.block_public_acls == true &&
|
|
509
|
+
resource.public_access_block.block_public_policy == true &&
|
|
510
|
+
resource.public_access_block.ignore_public_acls == true &&
|
|
511
|
+
resource.public_access_block.restrict_public_buckets == true
|
|
512
|
+
|
|
513
|
+
- id: logging-enabled
|
|
514
|
+
description: "Audit logging must be enabled"
|
|
515
|
+
resource_types:
|
|
516
|
+
- aws_s3_bucket
|
|
517
|
+
- aws_cloudtrail
|
|
518
|
+
- aws_vpc
|
|
519
|
+
check: |
|
|
520
|
+
resource.logging.enabled == true
|
|
521
|
+
|
|
522
|
+
compliance_mappings:
|
|
523
|
+
- framework: FedRAMP
|
|
524
|
+
controls:
|
|
525
|
+
- SC-28 # encryption-at-rest
|
|
526
|
+
- AC-3 # public-access-blocked
|
|
527
|
+
- AU-2 # logging-enabled
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
**2. Wiz API Integration Script**
|
|
531
|
+
|
|
532
|
+
```python
|
|
533
|
+
# wiz_cicd_integration.py
|
|
534
|
+
"""Integrate Wiz scanning into CI/CD pipelines"""
|
|
535
|
+
|
|
536
|
+
import requests
|
|
537
|
+
import sys
|
|
538
|
+
import json
|
|
539
|
+
|
|
540
|
+
class WizCICD:
|
|
541
|
+
def __init__(self, client_id, client_secret, api_url="https://api.us1.app.wiz.io"):
|
|
542
|
+
self.api_url = api_url
|
|
543
|
+
self.token = self._authenticate(client_id, client_secret)
|
|
544
|
+
|
|
545
|
+
def _authenticate(self, client_id, client_secret):
|
|
546
|
+
"""Authenticate with Wiz"""
|
|
547
|
+
auth_url = f"{self.api_url}/oauth/token"
|
|
548
|
+
payload = {
|
|
549
|
+
"grant_type": "client_credentials",
|
|
550
|
+
"client_id": client_id,
|
|
551
|
+
"client_secret": client_secret,
|
|
552
|
+
"audience": "wiz-api"
|
|
553
|
+
}
|
|
554
|
+
response = requests.post(auth_url, json=payload)
|
|
555
|
+
return response.json()["access_token"]
|
|
556
|
+
|
|
557
|
+
def scan_iac(self, directory, policy_id):
|
|
558
|
+
"""Scan IaC directory"""
|
|
559
|
+
headers = {"Authorization": f"Bearer {self.token}"}
|
|
560
|
+
|
|
561
|
+
mutation = """
|
|
562
|
+
mutation ScanIaC($input: IaCScanInput!) {
|
|
563
|
+
scanIaC(input: $input) {
|
|
564
|
+
scanId
|
|
565
|
+
findings {
|
|
566
|
+
id
|
|
567
|
+
severity
|
|
568
|
+
title
|
|
569
|
+
description
|
|
570
|
+
resourceType
|
|
571
|
+
resourceName
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
"""
|
|
576
|
+
|
|
577
|
+
variables = {
|
|
578
|
+
"input": {
|
|
579
|
+
"directory": directory,
|
|
580
|
+
"policyId": policy_id
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
response = requests.post(
|
|
585
|
+
f"{self.api_url}/graphql",
|
|
586
|
+
json={"query": mutation, "variables": variables},
|
|
587
|
+
headers=headers
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
return response.json()
|
|
591
|
+
|
|
592
|
+
def check_scan_results(self, scan_results, fail_on="high"):
|
|
593
|
+
"""Check if scan should fail the pipeline"""
|
|
594
|
+
severity_levels = ["critical", "high", "medium", "low"]
|
|
595
|
+
fail_index = severity_levels.index(fail_on.lower())
|
|
596
|
+
|
|
597
|
+
findings_by_severity = {}
|
|
598
|
+
for finding in scan_results.get("data", {}).get("scanIaC", {}).get("findings", []):
|
|
599
|
+
severity = finding["severity"].lower()
|
|
600
|
+
findings_by_severity[severity] = findings_by_severity.get(severity, 0) + 1
|
|
601
|
+
|
|
602
|
+
# Check if we have findings at or above the fail threshold
|
|
603
|
+
for i, severity in enumerate(severity_levels):
|
|
604
|
+
if i <= fail_index and findings_by_severity.get(severity, 0) > 0:
|
|
605
|
+
print(f"❌ Found {findings_by_severity[severity]} {severity} severity findings")
|
|
606
|
+
return False
|
|
607
|
+
|
|
608
|
+
print("✅ No blocking security findings")
|
|
609
|
+
return True
|
|
610
|
+
|
|
611
|
+
# CI/CD usage
|
|
612
|
+
if __name__ == "__main__":
|
|
613
|
+
import os
|
|
614
|
+
|
|
615
|
+
wiz = WizCICD(
|
|
616
|
+
client_id=os.environ["WIZ_CLIENT_ID"],
|
|
617
|
+
client_secret=os.environ["WIZ_CLIENT_SECRET"]
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
# Scan IaC
|
|
621
|
+
results = wiz.scan_iac(
|
|
622
|
+
directory="./terraform",
|
|
623
|
+
policy_id=os.environ.get("WIZ_POLICY_ID", "default-policy")
|
|
624
|
+
)
|
|
625
|
+
|
|
626
|
+
# Check results
|
|
627
|
+
passed = wiz.check_scan_results(results, fail_on="high")
|
|
628
|
+
|
|
629
|
+
if not passed:
|
|
630
|
+
print(json.dumps(results, indent=2))
|
|
631
|
+
sys.exit(1)
|
|
632
|
+
|
|
633
|
+
sys.exit(0)
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Aqua Security Integration
|
|
637
|
+
|
|
638
|
+
**1. Aqua Scanner Configuration**
|
|
639
|
+
|
|
640
|
+
```yaml
|
|
641
|
+
# aqua-scanner.yaml
|
|
642
|
+
# Aqua Security scanner configuration
|
|
643
|
+
|
|
644
|
+
scanner:
|
|
645
|
+
image_scan:
|
|
646
|
+
enabled: true
|
|
647
|
+
registries:
|
|
648
|
+
- type: docker
|
|
649
|
+
url: docker.io
|
|
650
|
+
- type: ecr
|
|
651
|
+
region: us-east-1
|
|
652
|
+
|
|
653
|
+
policy:
|
|
654
|
+
name: "production-policy"
|
|
655
|
+
fail_on:
|
|
656
|
+
- critical
|
|
657
|
+
- high
|
|
658
|
+
ignore_unfixed: false
|
|
659
|
+
|
|
660
|
+
compliance:
|
|
661
|
+
frameworks:
|
|
662
|
+
- FedRAMP
|
|
663
|
+
- NIST-800-171
|
|
664
|
+
- PCI-DSS
|
|
665
|
+
|
|
666
|
+
vulnerability_severity_threshold: medium
|
|
667
|
+
|
|
668
|
+
malware_scanning:
|
|
669
|
+
enabled: true
|
|
670
|
+
|
|
671
|
+
secrets_scanning:
|
|
672
|
+
enabled: true
|
|
673
|
+
|
|
674
|
+
output:
|
|
675
|
+
format: json
|
|
676
|
+
include_evidence: true
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
**2. Aqua CI/CD Script**
|
|
680
|
+
|
|
681
|
+
```bash
|
|
682
|
+
#!/bin/bash
|
|
683
|
+
# aqua-scan.sh - Scan container images with Aqua
|
|
684
|
+
|
|
685
|
+
set -e
|
|
686
|
+
|
|
687
|
+
IMAGE_NAME="$1"
|
|
688
|
+
AQUA_SERVER="${AQUA_SERVER}"
|
|
689
|
+
AQUA_USERNAME="${AQUA_USERNAME}"
|
|
690
|
+
AQUA_PASSWORD="${AQUA_PASSWORD}"
|
|
691
|
+
|
|
692
|
+
if [ -z "$IMAGE_NAME" ]; then
|
|
693
|
+
echo "Usage: $0 <image-name>"
|
|
694
|
+
exit 1
|
|
695
|
+
fi
|
|
696
|
+
|
|
697
|
+
echo "🔍 Scanning image: $IMAGE_NAME"
|
|
698
|
+
|
|
699
|
+
# Run Aqua scanner
|
|
700
|
+
docker run --rm \
|
|
701
|
+
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
702
|
+
registry.aquasec.com/scanner:latest \
|
|
703
|
+
scan \
|
|
704
|
+
--host "$AQUA_SERVER" \
|
|
705
|
+
--user "$AQUA_USERNAME" \
|
|
706
|
+
--password "$AQUA_PASSWORD" \
|
|
707
|
+
--local "$IMAGE_NAME" \
|
|
708
|
+
--register \
|
|
709
|
+
--show-negligible \
|
|
710
|
+
--output json > scan-results.json
|
|
711
|
+
|
|
712
|
+
# Parse results
|
|
713
|
+
CRITICAL=$(jq '.resources[0].vulnerabilities | map(select(.aqua_severity == "critical")) | length' scan-results.json)
|
|
714
|
+
HIGH=$(jq '.resources[0].vulnerabilities | map(select(.aqua_severity == "high")) | length' scan-results.json)
|
|
715
|
+
|
|
716
|
+
echo "📊 Scan Results:"
|
|
717
|
+
echo " Critical: $CRITICAL"
|
|
718
|
+
echo " High: $HIGH"
|
|
719
|
+
|
|
720
|
+
# Fail if critical or high vulnerabilities found
|
|
721
|
+
if [ "$CRITICAL" -gt 0 ] || [ "$HIGH" -gt 5 ]; then
|
|
722
|
+
echo "❌ Security scan failed!"
|
|
723
|
+
jq '.resources[0].vulnerabilities | map(select(.aqua_severity == "critical" or .aqua_severity == "high"))' scan-results.json
|
|
724
|
+
exit 1
|
|
725
|
+
fi
|
|
726
|
+
|
|
727
|
+
echo "✅ Security scan passed!"
|
|
728
|
+
exit 0
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
## Policy as Code
|
|
734
|
+
|
|
735
|
+
### OPA (Open Policy Agent) Integration
|
|
736
|
+
|
|
737
|
+
```rego
|
|
738
|
+
# policies/terraform.rego
|
|
739
|
+
# OPA policy for Terraform validation
|
|
740
|
+
|
|
741
|
+
package terraform
|
|
742
|
+
|
|
743
|
+
import future.keywords
|
|
744
|
+
|
|
745
|
+
# Deny S3 buckets without encryption
|
|
746
|
+
deny[msg] {
|
|
747
|
+
resource := input.resource_changes[_]
|
|
748
|
+
resource.type == "aws_s3_bucket"
|
|
749
|
+
not resource.change.after.server_side_encryption_configuration
|
|
750
|
+
|
|
751
|
+
msg := sprintf("S3 bucket '%s' must have encryption enabled", [resource.name])
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
# Deny public S3 buckets
|
|
755
|
+
deny[msg] {
|
|
756
|
+
resource := input.resource_changes[_]
|
|
757
|
+
resource.type == "aws_s3_bucket"
|
|
758
|
+
resource.change.after.acl == "public-read"
|
|
759
|
+
|
|
760
|
+
msg := sprintf("S3 bucket '%s' cannot have public-read ACL", [resource.name])
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
# Require mandatory tags
|
|
764
|
+
mandatory_tags := ["Environment", "Owner", "CostCenter"]
|
|
765
|
+
|
|
766
|
+
deny[msg] {
|
|
767
|
+
resource := input.resource_changes[_]
|
|
768
|
+
resource.type == "aws_instance"
|
|
769
|
+
tags := object.keys(resource.change.after.tags)
|
|
770
|
+
|
|
771
|
+
missing := [tag | tag := mandatory_tags[_]; not tag in tags]
|
|
772
|
+
count(missing) > 0
|
|
773
|
+
|
|
774
|
+
msg := sprintf("Resource '%s' missing required tags: %v", [resource.name, missing])
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
# Require MFA for IAM users
|
|
778
|
+
deny[msg] {
|
|
779
|
+
resource := input.resource_changes[_]
|
|
780
|
+
resource.type == "aws_iam_user"
|
|
781
|
+
not has_mfa_device(resource.name)
|
|
782
|
+
|
|
783
|
+
msg := sprintf("IAM user '%s' must have MFA enabled", [resource.name])
|
|
784
|
+
}
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### Policy Enforcement Pipeline
|
|
788
|
+
|
|
789
|
+
```yaml
|
|
790
|
+
# .github/workflows/policy-enforcement.yml
|
|
791
|
+
name: Policy Enforcement
|
|
792
|
+
|
|
793
|
+
on:
|
|
794
|
+
pull_request:
|
|
795
|
+
push:
|
|
796
|
+
branches: [main]
|
|
797
|
+
|
|
798
|
+
jobs:
|
|
799
|
+
opa_policy_check:
|
|
800
|
+
runs-on: ubuntu-latest
|
|
801
|
+
|
|
802
|
+
steps:
|
|
803
|
+
- uses: actions/checkout@v3
|
|
804
|
+
|
|
805
|
+
- name: Setup Terraform
|
|
806
|
+
uses: hashicorp/setup-terraform@v2
|
|
807
|
+
|
|
808
|
+
- name: Terraform Plan
|
|
809
|
+
run: |
|
|
810
|
+
terraform init
|
|
811
|
+
terraform plan -out=tfplan.binary
|
|
812
|
+
terraform show -json tfplan.binary > tfplan.json
|
|
813
|
+
|
|
814
|
+
- name: Setup OPA
|
|
815
|
+
uses: open-policy-agent/setup-opa@v2
|
|
816
|
+
|
|
817
|
+
- name: Run OPA Tests
|
|
818
|
+
run: |
|
|
819
|
+
opa test policies/ -v
|
|
820
|
+
|
|
821
|
+
- name: Evaluate Terraform Plan
|
|
822
|
+
run: |
|
|
823
|
+
opa eval \
|
|
824
|
+
--data policies/terraform.rego \
|
|
825
|
+
--input tfplan.json \
|
|
826
|
+
--format pretty \
|
|
827
|
+
"data.terraform.deny" > violations.txt
|
|
828
|
+
|
|
829
|
+
if [ -s violations.txt ]; then
|
|
830
|
+
echo "❌ Policy violations found:"
|
|
831
|
+
cat violations.txt
|
|
832
|
+
exit 1
|
|
833
|
+
else
|
|
834
|
+
echo "✅ No policy violations"
|
|
835
|
+
fi
|
|
836
|
+
|
|
837
|
+
- name: Comment PR with violations
|
|
838
|
+
if: failure() && github.event_name == 'pull_request'
|
|
839
|
+
uses: actions/github-script@v6
|
|
840
|
+
with:
|
|
841
|
+
script: |
|
|
842
|
+
const fs = require('fs');
|
|
843
|
+
const violations = fs.readFileSync('violations.txt', 'utf8');
|
|
844
|
+
github.rest.issues.createComment({
|
|
845
|
+
issue_number: context.issue.number,
|
|
846
|
+
owner: context.repo.owner,
|
|
847
|
+
repo: context.repo.repo,
|
|
848
|
+
body: `## ⚠️ Policy Violations Detected\n\n\`\`\`\n${violations}\n\`\`\``
|
|
849
|
+
});
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
---
|
|
853
|
+
|
|
854
|
+
## Shift-Left Security
|
|
855
|
+
|
|
856
|
+
### Pre-Commit Hooks
|
|
857
|
+
|
|
858
|
+
**1. Setup pre-commit framework**
|
|
859
|
+
|
|
860
|
+
```yaml
|
|
861
|
+
# .pre-commit-config.yaml
|
|
862
|
+
repos:
|
|
863
|
+
- repo: https://github.com/antonbabenko/pre-commit-terraform
|
|
864
|
+
rev: v1.83.5
|
|
865
|
+
hooks:
|
|
866
|
+
- id: terraform_fmt
|
|
867
|
+
- id: terraform_validate
|
|
868
|
+
- id: terraform_tflint
|
|
869
|
+
- id: terraform_docs
|
|
870
|
+
|
|
871
|
+
- repo: https://github.com/bridgecrewio/checkov
|
|
872
|
+
rev: 2.5.0
|
|
873
|
+
hooks:
|
|
874
|
+
- id: checkov
|
|
875
|
+
args:
|
|
876
|
+
- --quiet
|
|
877
|
+
- --framework=terraform
|
|
878
|
+
|
|
879
|
+
- repo: https://github.com/aquasecurity/tfsec
|
|
880
|
+
rev: v1.28.4
|
|
881
|
+
hooks:
|
|
882
|
+
- id: tfsec
|
|
883
|
+
|
|
884
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
885
|
+
rev: v4.5.0
|
|
886
|
+
hooks:
|
|
887
|
+
- id: trailing-whitespace
|
|
888
|
+
- id: end-of-file-fixer
|
|
889
|
+
- id: check-yaml
|
|
890
|
+
- id: check-json
|
|
891
|
+
- id: detect-aws-credentials
|
|
892
|
+
args: ['--allow-missing-credentials']
|
|
893
|
+
- id: detect-private-key
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
**2. Install and use**
|
|
897
|
+
|
|
898
|
+
```bash
|
|
899
|
+
# Install pre-commit
|
|
900
|
+
pip install pre-commit
|
|
901
|
+
|
|
902
|
+
# Install hooks
|
|
903
|
+
pre-commit install
|
|
904
|
+
|
|
905
|
+
# Run manually
|
|
906
|
+
pre-commit run --all-files
|
|
907
|
+
|
|
908
|
+
# Run on specific files
|
|
909
|
+
pre-commit run --files terraform/*.tf
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
### IDE Integration
|
|
913
|
+
|
|
914
|
+
**1. VSCode Extension Configuration**
|
|
915
|
+
|
|
916
|
+
```json
|
|
917
|
+
// .vscode/settings.json
|
|
918
|
+
{
|
|
919
|
+
"terraform.languageServer": {
|
|
920
|
+
"enabled": true,
|
|
921
|
+
"args": []
|
|
922
|
+
},
|
|
923
|
+
|
|
924
|
+
"tflint.enabled": true,
|
|
925
|
+
"tflint.configFile": ".tflint.hcl",
|
|
926
|
+
|
|
927
|
+
"checkov.token": "${env:PRISMA_API_KEY}",
|
|
928
|
+
"checkov.enabledFrameworks": [
|
|
929
|
+
"terraform",
|
|
930
|
+
"kubernetes",
|
|
931
|
+
"dockerfile"
|
|
932
|
+
],
|
|
933
|
+
|
|
934
|
+
"editor.formatOnSave": true,
|
|
935
|
+
"editor.codeActionsOnSave": {
|
|
936
|
+
"source.fixAll": true
|
|
937
|
+
},
|
|
938
|
+
|
|
939
|
+
"files.associations": {
|
|
940
|
+
"*.tf": "terraform",
|
|
941
|
+
"*.hcl": "terraform"
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
**2. TFLint Configuration**
|
|
947
|
+
|
|
948
|
+
```hcl
|
|
949
|
+
# .tflint.hcl
|
|
950
|
+
plugin "terraform" {
|
|
951
|
+
enabled = true
|
|
952
|
+
preset = "recommended"
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
plugin "aws" {
|
|
956
|
+
enabled = true
|
|
957
|
+
version = "0.27.0"
|
|
958
|
+
source = "github.com/terraform-linters/tflint-ruleset-aws"
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
rule "terraform_naming_convention" {
|
|
962
|
+
enabled = true
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
rule "terraform_required_version" {
|
|
966
|
+
enabled = true
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
rule "terraform_required_providers" {
|
|
970
|
+
enabled = true
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
# AWS-specific rules
|
|
974
|
+
rule "aws_instance_invalid_type" {
|
|
975
|
+
enabled = true
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
rule "aws_s3_bucket_lifecycle_configuration" {
|
|
979
|
+
enabled = true
|
|
980
|
+
}
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
---
|
|
984
|
+
|
|
985
|
+
## Continuous Compliance
|
|
986
|
+
|
|
987
|
+
### Automated Compliance Reporting
|
|
988
|
+
|
|
989
|
+
```python
|
|
990
|
+
# compliance_reporter.py
|
|
991
|
+
"""Generate compliance reports from CSPM scans"""
|
|
992
|
+
|
|
993
|
+
import boto3
|
|
994
|
+
import json
|
|
995
|
+
from datetime import datetime
|
|
996
|
+
|
|
997
|
+
class ComplianceReporter:
|
|
998
|
+
def __init__(self):
|
|
999
|
+
self.securityhub = boto3.client('securityhub')
|
|
1000
|
+
self.config = boto3.client('config')
|
|
1001
|
+
|
|
1002
|
+
def get_compliance_summary(self):
|
|
1003
|
+
"""Get compliance summary from AWS Security Hub"""
|
|
1004
|
+
response = self.securityhub.get_findings(
|
|
1005
|
+
Filters={
|
|
1006
|
+
'RecordState': [{'Value': 'ACTIVE', 'Comparison': 'EQUALS'}],
|
|
1007
|
+
'WorkflowStatus': [{'Value': 'NEW', 'Comparison': 'EQUALS'}]
|
|
1008
|
+
},
|
|
1009
|
+
MaxResults=100
|
|
1010
|
+
)
|
|
1011
|
+
|
|
1012
|
+
summary = {
|
|
1013
|
+
'total_findings': len(response['Findings']),
|
|
1014
|
+
'by_severity': {},
|
|
1015
|
+
'by_standard': {},
|
|
1016
|
+
'by_control': {}
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
for finding in response['Findings']:
|
|
1020
|
+
# Count by severity
|
|
1021
|
+
severity = finding['Severity']['Label']
|
|
1022
|
+
summary['by_severity'][severity] = summary['by_severity'].get(severity, 0) + 1
|
|
1023
|
+
|
|
1024
|
+
# Count by compliance standard
|
|
1025
|
+
if 'Compliance' in finding:
|
|
1026
|
+
status = finding['Compliance']['Status']
|
|
1027
|
+
summary['by_standard'][status] = summary['by_standard'].get(status, 0) + 1
|
|
1028
|
+
|
|
1029
|
+
return summary
|
|
1030
|
+
|
|
1031
|
+
def generate_report(self, output_file='compliance-report.json'):
|
|
1032
|
+
"""Generate comprehensive compliance report"""
|
|
1033
|
+
report = {
|
|
1034
|
+
'generated_at': datetime.now().isoformat(),
|
|
1035
|
+
'summary': self.get_compliance_summary(),
|
|
1036
|
+
'frameworks': self.get_framework_compliance(),
|
|
1037
|
+
'top_violations': self.get_top_violations(),
|
|
1038
|
+
'remediation_recommendations': self.get_remediation_recommendations()
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
with open(output_file, 'w') as f:
|
|
1042
|
+
json.dump(report, f, indent=2)
|
|
1043
|
+
|
|
1044
|
+
return report
|
|
1045
|
+
|
|
1046
|
+
def get_framework_compliance(self):
|
|
1047
|
+
"""Get compliance status for each framework"""
|
|
1048
|
+
standards = [
|
|
1049
|
+
'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0',
|
|
1050
|
+
'arn:aws:securityhub:us-east-1::standards/aws-foundational-security-best-practices/v/1.0.0',
|
|
1051
|
+
'arn:aws:securityhub:us-east-1::standards/pci-dss/v/3.2.1'
|
|
1052
|
+
]
|
|
1053
|
+
|
|
1054
|
+
framework_compliance = {}
|
|
1055
|
+
|
|
1056
|
+
for standard in standards:
|
|
1057
|
+
results = self.securityhub.get_compliance_summary_by_resource_type(
|
|
1058
|
+
StandardsSubscriptionArn=standard
|
|
1059
|
+
)
|
|
1060
|
+
framework_compliance[standard] = results
|
|
1061
|
+
|
|
1062
|
+
return framework_compliance
|
|
1063
|
+
|
|
1064
|
+
def get_top_violations(self, limit=10):
|
|
1065
|
+
"""Get most common violations"""
|
|
1066
|
+
findings = self.securityhub.get_findings(
|
|
1067
|
+
Filters={'RecordState': [{'Value': 'ACTIVE', 'Comparison': 'EQUALS'}]},
|
|
1068
|
+
MaxResults=100
|
|
1069
|
+
)
|
|
1070
|
+
|
|
1071
|
+
violation_counts = {}
|
|
1072
|
+
for finding in findings['Findings']:
|
|
1073
|
+
title = finding['Title']
|
|
1074
|
+
violation_counts[title] = violation_counts.get(title, 0) + 1
|
|
1075
|
+
|
|
1076
|
+
# Sort and get top violations
|
|
1077
|
+
sorted_violations = sorted(
|
|
1078
|
+
violation_counts.items(),
|
|
1079
|
+
key=lambda x: x[1],
|
|
1080
|
+
reverse=True
|
|
1081
|
+
)[:limit]
|
|
1082
|
+
|
|
1083
|
+
return [{'violation': v[0], 'count': v[1]} for v in sorted_violations]
|
|
1084
|
+
|
|
1085
|
+
def get_remediation_recommendations(self):
|
|
1086
|
+
"""Get remediation recommendations"""
|
|
1087
|
+
return {
|
|
1088
|
+
'automated': self.get_automated_remediation(),
|
|
1089
|
+
'manual': self.get_manual_remediation()
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
# Usage in CI/CD
|
|
1093
|
+
if __name__ == "__main__":
|
|
1094
|
+
reporter = ComplianceReporter()
|
|
1095
|
+
report = reporter.generate_report()
|
|
1096
|
+
print(f"Compliance report generated: {report['summary']['total_findings']} findings")
|
|
1097
|
+
```
|
|
1098
|
+
|
|
1099
|
+
### Drift Detection
|
|
1100
|
+
|
|
1101
|
+
```yaml
|
|
1102
|
+
# .github/workflows/drift-detection.yml
|
|
1103
|
+
name: Infrastructure Drift Detection
|
|
1104
|
+
|
|
1105
|
+
on:
|
|
1106
|
+
schedule:
|
|
1107
|
+
- cron: '0 */6 * * *' # Every 6 hours
|
|
1108
|
+
workflow_dispatch:
|
|
1109
|
+
|
|
1110
|
+
jobs:
|
|
1111
|
+
detect_drift:
|
|
1112
|
+
runs-on: ubuntu-latest
|
|
1113
|
+
|
|
1114
|
+
steps:
|
|
1115
|
+
- uses: actions/checkout@v3
|
|
1116
|
+
|
|
1117
|
+
- name: Configure AWS credentials
|
|
1118
|
+
uses: aws-actions/configure-aws-credentials@v2
|
|
1119
|
+
with:
|
|
1120
|
+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
1121
|
+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
1122
|
+
aws-region: us-east-1
|
|
1123
|
+
|
|
1124
|
+
- name: Setup Terraform
|
|
1125
|
+
uses: hashicorp/setup-terraform@v2
|
|
1126
|
+
|
|
1127
|
+
- name: Terraform Init
|
|
1128
|
+
run: terraform init
|
|
1129
|
+
|
|
1130
|
+
- name: Terraform Plan (Detect Drift)
|
|
1131
|
+
id: plan
|
|
1132
|
+
run: |
|
|
1133
|
+
terraform plan -detailed-exitcode -no-color -out=tfplan.binary || exit_code=$?
|
|
1134
|
+
terraform show -json tfplan.binary > tfplan.json
|
|
1135
|
+
|
|
1136
|
+
if [ $exit_code -eq 2 ]; then
|
|
1137
|
+
echo "drift_detected=true" >> $GITHUB_OUTPUT
|
|
1138
|
+
else
|
|
1139
|
+
echo "drift_detected=false" >> $GITHUB_OUTPUT
|
|
1140
|
+
fi
|
|
1141
|
+
|
|
1142
|
+
- name: Analyze Drift
|
|
1143
|
+
if: steps.plan.outputs.drift_detected == 'true'
|
|
1144
|
+
run: |
|
|
1145
|
+
python3 << 'EOF'
|
|
1146
|
+
import json
|
|
1147
|
+
import sys
|
|
1148
|
+
|
|
1149
|
+
with open('tfplan.json') as f:
|
|
1150
|
+
plan = json.load(f)
|
|
1151
|
+
|
|
1152
|
+
drift = {
|
|
1153
|
+
'created': [],
|
|
1154
|
+
'modified': [],
|
|
1155
|
+
'deleted': []
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
for change in plan.get('resource_changes', []):
|
|
1159
|
+
actions = change['change']['actions']
|
|
1160
|
+
resource = f"{change['type']}.{change['name']}"
|
|
1161
|
+
|
|
1162
|
+
if 'create' in actions:
|
|
1163
|
+
drift['created'].append(resource)
|
|
1164
|
+
elif 'update' in actions:
|
|
1165
|
+
drift['modified'].append(resource)
|
|
1166
|
+
elif 'delete' in actions:
|
|
1167
|
+
drift['deleted'].append(resource)
|
|
1168
|
+
|
|
1169
|
+
print("🔍 Infrastructure Drift Detected:")
|
|
1170
|
+
print(f" Created: {len(drift['created'])}")
|
|
1171
|
+
print(f" Modified: {len(drift['modified'])}")
|
|
1172
|
+
print(f" Deleted: {len(drift['deleted'])}")
|
|
1173
|
+
|
|
1174
|
+
if drift['created']:
|
|
1175
|
+
print("\n➕ Created Resources:")
|
|
1176
|
+
for resource in drift['created']:
|
|
1177
|
+
print(f" - {resource}")
|
|
1178
|
+
|
|
1179
|
+
if drift['modified']:
|
|
1180
|
+
print("\n✏️ Modified Resources:")
|
|
1181
|
+
for resource in drift['modified']:
|
|
1182
|
+
print(f" - {resource}")
|
|
1183
|
+
|
|
1184
|
+
if drift['deleted']:
|
|
1185
|
+
print("\n❌ Deleted Resources:")
|
|
1186
|
+
for resource in drift['deleted']:
|
|
1187
|
+
print(f" - {resource}")
|
|
1188
|
+
|
|
1189
|
+
with open('drift-summary.json', 'w') as f:
|
|
1190
|
+
json.dump(drift, f, indent=2)
|
|
1191
|
+
EOF
|
|
1192
|
+
|
|
1193
|
+
- name: Create Issue for Drift
|
|
1194
|
+
if: steps.plan.outputs.drift_detected == 'true'
|
|
1195
|
+
uses: actions/github-script@v6
|
|
1196
|
+
with:
|
|
1197
|
+
script: |
|
|
1198
|
+
const fs = require('fs');
|
|
1199
|
+
const drift = JSON.parse(fs.readFileSync('drift-summary.json', 'utf8'));
|
|
1200
|
+
|
|
1201
|
+
const body = `## ⚠️ Infrastructure Drift Detected
|
|
1202
|
+
|
|
1203
|
+
**Created:** ${drift.created.length} resources
|
|
1204
|
+
**Modified:** ${drift.modified.length} resources
|
|
1205
|
+
**Deleted:** ${drift.deleted.length} resources
|
|
1206
|
+
|
|
1207
|
+
<details>
|
|
1208
|
+
<summary>View Details</summary>
|
|
1209
|
+
|
|
1210
|
+
### Created Resources
|
|
1211
|
+
${drift.created.map(r => `- ${r}`).join('\n')}
|
|
1212
|
+
|
|
1213
|
+
### Modified Resources
|
|
1214
|
+
${drift.modified.map(r => `- ${r}`).join('\n')}
|
|
1215
|
+
|
|
1216
|
+
### Deleted Resources
|
|
1217
|
+
${drift.deleted.map(r => `- ${r}`).join('\n')}
|
|
1218
|
+
|
|
1219
|
+
</details>
|
|
1220
|
+
|
|
1221
|
+
**Action Required:** Review and either:
|
|
1222
|
+
1. Update Terraform code to match actual state
|
|
1223
|
+
2. Investigate unauthorized changes
|
|
1224
|
+
`;
|
|
1225
|
+
|
|
1226
|
+
github.rest.issues.create({
|
|
1227
|
+
owner: context.repo.owner,
|
|
1228
|
+
repo: context.repo.repo,
|
|
1229
|
+
title: `Infrastructure Drift Detected - ${new Date().toISOString().split('T')[0]}`,
|
|
1230
|
+
body: body,
|
|
1231
|
+
labels: ['security', 'infrastructure', 'drift']
|
|
1232
|
+
});
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
---
|
|
1236
|
+
|
|
1237
|
+
## Remediation Workflows
|
|
1238
|
+
|
|
1239
|
+
### Automated Remediation
|
|
1240
|
+
|
|
1241
|
+
```python
|
|
1242
|
+
# auto_remediation.py
|
|
1243
|
+
"""Automated remediation for common security findings"""
|
|
1244
|
+
|
|
1245
|
+
import boto3
|
|
1246
|
+
import json
|
|
1247
|
+
|
|
1248
|
+
class AutoRemediation:
|
|
1249
|
+
def __init__(self):
|
|
1250
|
+
self.s3 = boto3.client('s3')
|
|
1251
|
+
self.ec2 = boto3.client('ec2')
|
|
1252
|
+
self.iam = boto3.client('iam')
|
|
1253
|
+
|
|
1254
|
+
def remediate_s3_public_access(self, bucket_name):
|
|
1255
|
+
"""Block public access on S3 bucket"""
|
|
1256
|
+
try:
|
|
1257
|
+
self.s3.put_public_access_block(
|
|
1258
|
+
Bucket=bucket_name,
|
|
1259
|
+
PublicAccessBlockConfiguration={
|
|
1260
|
+
'BlockPublicAcls': True,
|
|
1261
|
+
'IgnorePublicAcls': True,
|
|
1262
|
+
'BlockPublicPolicy': True,
|
|
1263
|
+
'RestrictPublicBuckets': True
|
|
1264
|
+
}
|
|
1265
|
+
)
|
|
1266
|
+
print(f"✅ Blocked public access on bucket: {bucket_name}")
|
|
1267
|
+
return True
|
|
1268
|
+
except Exception as e:
|
|
1269
|
+
print(f"❌ Failed to remediate {bucket_name}: {str(e)}")
|
|
1270
|
+
return False
|
|
1271
|
+
|
|
1272
|
+
def remediate_s3_encryption(self, bucket_name, kms_key_id):
|
|
1273
|
+
"""Enable encryption on S3 bucket"""
|
|
1274
|
+
try:
|
|
1275
|
+
self.s3.put_bucket_encryption(
|
|
1276
|
+
Bucket=bucket_name,
|
|
1277
|
+
ServerSideEncryptionConfiguration={
|
|
1278
|
+
'Rules': [{
|
|
1279
|
+
'ApplyServerSideEncryptionByDefault': {
|
|
1280
|
+
'SSEAlgorithm': 'aws:kms',
|
|
1281
|
+
'KMSMasterKeyID': kms_key_id
|
|
1282
|
+
},
|
|
1283
|
+
'BucketKeyEnabled': True
|
|
1284
|
+
}]
|
|
1285
|
+
}
|
|
1286
|
+
)
|
|
1287
|
+
print(f"✅ Enabled encryption on bucket: {bucket_name}")
|
|
1288
|
+
return True
|
|
1289
|
+
except Exception as e:
|
|
1290
|
+
print(f"❌ Failed to enable encryption on {bucket_name}: {str(e)}")
|
|
1291
|
+
return False
|
|
1292
|
+
|
|
1293
|
+
def remediate_sg_unrestricted_access(self, security_group_id, port):
|
|
1294
|
+
"""Remove unrestricted inbound rules"""
|
|
1295
|
+
try:
|
|
1296
|
+
self.ec2.revoke_security_group_ingress(
|
|
1297
|
+
GroupId=security_group_id,
|
|
1298
|
+
IpPermissions=[{
|
|
1299
|
+
'IpProtocol': 'tcp',
|
|
1300
|
+
'FromPort': port,
|
|
1301
|
+
'ToPort': port,
|
|
1302
|
+
'IpRanges': [{'CidrIp': '0.0.0.0/0'}]
|
|
1303
|
+
}]
|
|
1304
|
+
)
|
|
1305
|
+
print(f"✅ Removed unrestricted access on SG: {security_group_id}")
|
|
1306
|
+
return True
|
|
1307
|
+
except Exception as e:
|
|
1308
|
+
print(f"❌ Failed to remediate {security_group_id}: {str(e)}")
|
|
1309
|
+
return False
|
|
1310
|
+
|
|
1311
|
+
def remediate_iam_password_policy(self):
|
|
1312
|
+
"""Update IAM password policy to meet compliance"""
|
|
1313
|
+
try:
|
|
1314
|
+
self.iam.update_account_password_policy(
|
|
1315
|
+
MinimumPasswordLength=14,
|
|
1316
|
+
RequireSymbols=True,
|
|
1317
|
+
RequireNumbers=True,
|
|
1318
|
+
RequireUppercaseCharacters=True,
|
|
1319
|
+
RequireLowercaseCharacters=True,
|
|
1320
|
+
AllowUsersToChangePassword=True,
|
|
1321
|
+
MaxPasswordAge=90,
|
|
1322
|
+
PasswordReusePrevention=24,
|
|
1323
|
+
HardExpiry=False
|
|
1324
|
+
)
|
|
1325
|
+
print("✅ Updated IAM password policy")
|
|
1326
|
+
return True
|
|
1327
|
+
except Exception as e:
|
|
1328
|
+
print(f"❌ Failed to update password policy: {str(e)}")
|
|
1329
|
+
return False
|
|
1330
|
+
|
|
1331
|
+
# Lambda handler for automated remediation
|
|
1332
|
+
def lambda_handler(event, context):
|
|
1333
|
+
"""
|
|
1334
|
+
AWS Lambda function to auto-remediate Security Hub findings
|
|
1335
|
+
Triggered by EventBridge when new findings detected
|
|
1336
|
+
"""
|
|
1337
|
+
remediation = AutoRemediation()
|
|
1338
|
+
|
|
1339
|
+
finding = event['detail']['findings'][0]
|
|
1340
|
+
finding_type = finding['Types'][0]
|
|
1341
|
+
|
|
1342
|
+
if 'S3.1' in finding['Title']: # S3 bucket public read
|
|
1343
|
+
bucket_name = finding['Resources'][0]['Id'].split(':')[-1]
|
|
1344
|
+
remediation.remediate_s3_public_access(bucket_name)
|
|
1345
|
+
|
|
1346
|
+
elif 'S3.4' in finding['Title']: # S3 bucket encryption
|
|
1347
|
+
bucket_name = finding['Resources'][0]['Id'].split(':')[-1]
|
|
1348
|
+
kms_key_id = os.environ.get('KMS_KEY_ID')
|
|
1349
|
+
remediation.remediate_s3_encryption(bucket_name, kms_key_id)
|
|
1350
|
+
|
|
1351
|
+
elif 'EC2.19' in finding['Title']: # Unrestricted security group
|
|
1352
|
+
sg_id = finding['Resources'][0]['Id'].split('/')[-1]
|
|
1353
|
+
remediation.remediate_sg_unrestricted_access(sg_id, 22)
|
|
1354
|
+
|
|
1355
|
+
elif 'IAM.15' in finding['Title']: # IAM password policy
|
|
1356
|
+
remediation.remediate_iam_password_policy()
|
|
1357
|
+
|
|
1358
|
+
return {'statusCode': 200, 'body': 'Remediation completed'}
|
|
1359
|
+
```
|
|
1360
|
+
|
|
1361
|
+
---
|
|
1362
|
+
|
|
1363
|
+
## Best Practices
|
|
1364
|
+
|
|
1365
|
+
### 1. Fail Fast, Fail Early
|
|
1366
|
+
|
|
1367
|
+
```
|
|
1368
|
+
Development Pipeline Gates:
|
|
1369
|
+
┌─────────────────────────────────────────────────────┐
|
|
1370
|
+
│ Pre-commit: Local checks (fast feedback) │
|
|
1371
|
+
│ ↓ PASS │
|
|
1372
|
+
│ PR Review: Automated scans (block merge) │
|
|
1373
|
+
│ ↓ PASS │
|
|
1374
|
+
│ CI Build: Comprehensive scanning │
|
|
1375
|
+
│ ↓ PASS │
|
|
1376
|
+
│ Deploy to Dev: Runtime validation │
|
|
1377
|
+
│ ↓ PASS │
|
|
1378
|
+
│ Deploy to Prod: Final checks + monitoring │
|
|
1379
|
+
└─────────────────────────────────────────────────────┘
|
|
1380
|
+
```
|
|
1381
|
+
|
|
1382
|
+
### 2. Progressive Rollout
|
|
1383
|
+
|
|
1384
|
+
```markdown
|
|
1385
|
+
# CSPM Rollout Strategy
|
|
1386
|
+
|
|
1387
|
+
## Phase 1: Observation (Week 1-2)
|
|
1388
|
+
- [ ] Run scans in `soft_fail` mode
|
|
1389
|
+
- [ ] Collect baseline metrics
|
|
1390
|
+
- [ ] Identify false positives
|
|
1391
|
+
- [ ] Tune policies
|
|
1392
|
+
|
|
1393
|
+
## Phase 2: Warnings (Week 3-4)
|
|
1394
|
+
- [ ] Enable warnings in PR comments
|
|
1395
|
+
- [ ] Don't block merges
|
|
1396
|
+
- [ ] Track remediation rate
|
|
1397
|
+
- [ ] Refine policies
|
|
1398
|
+
|
|
1399
|
+
## Phase 3: Enforcement (Week 5+)
|
|
1400
|
+
- [ ] Enable hard failures for critical/high
|
|
1401
|
+
- [ ] Block deployments on violations
|
|
1402
|
+
- [ ] Automated remediation where possible
|
|
1403
|
+
- [ ] Continuous monitoring
|
|
1404
|
+
```
|
|
1405
|
+
|
|
1406
|
+
### 3. Exception Management
|
|
1407
|
+
|
|
1408
|
+
```yaml
|
|
1409
|
+
# cspm-exceptions.yaml
|
|
1410
|
+
# Documented exceptions to security policies
|
|
1411
|
+
|
|
1412
|
+
exceptions:
|
|
1413
|
+
- id: EXCEPT-001
|
|
1414
|
+
policy: CKV_AWS_18
|
|
1415
|
+
resource: "aws_ebs_volume.public_ami_volume"
|
|
1416
|
+
justification: "Public AMI requires unencrypted volume"
|
|
1417
|
+
approved_by: "security-team@company.com"
|
|
1418
|
+
approved_date: "2024-01-15"
|
|
1419
|
+
expiration_date: "2024-07-15"
|
|
1420
|
+
review_frequency: "quarterly"
|
|
1421
|
+
|
|
1422
|
+
- id: EXCEPT-002
|
|
1423
|
+
policy: CKV_K8S_8
|
|
1424
|
+
resource: "kubernetes_job.batch_processor"
|
|
1425
|
+
justification: "Batch jobs don't require liveness probes"
|
|
1426
|
+
approved_by: "platform-team@company.com"
|
|
1427
|
+
approved_date: "2024-02-01"
|
|
1428
|
+
expiration_date: "2025-02-01"
|
|
1429
|
+
compensating_controls:
|
|
1430
|
+
- "Job completion monitoring"
|
|
1431
|
+
- "Dead letter queue for failures"
|
|
1432
|
+
```
|
|
1433
|
+
|
|
1434
|
+
---
|
|
1435
|
+
|
|
1436
|
+
**Related Resources:**
|
|
1437
|
+
- [cloud-security-tools.md](../cloud-engineering/resources/cloud-security-tools.md) - CSPM tool details
|
|
1438
|
+
- [compliance-frameworks.md](compliance-frameworks.md) - Compliance requirements
|
|
1439
|
+
- [security-scanning.md](security-scanning.md) - Security scanning strategies
|
|
1440
|
+
- [ci-cd-security.md](ci-cd-security.md) - CI/CD security patterns
|