CWPP / CNAP Platform Work
What is CWPP and CNAP?
CWPP — Cloud Workload Protection Platform Protects: VMs, containers, serverless functions Focus: Runtime threats, vulnerability scanning, process monitoring, network detectionCNAPP — Cloud-Native Application Protection Platform = CWPP + CSPM + CIEM + IaC scanning combined Focus: Full lifecycle protection from code → cloud Gartner: Unified platform replacing point solutions┌─────────────────────────────────────────────────────────────┐│ CNAPP PILLARS │├──────────────┬──────────────┬──────────────┬───────────────┤│ CSPM │ CWPP │ CIEM │ IaC / Shift ││ │ │ │ Left ││ Cloud │ Workload │ Cloud │ ││ Security │ Protection │ Identity │ Scan Terraform││ Posture Mgmt │ (runtime) │ Entitlement │ before deploy ││ │ │ Mgmt │ ││ Misconfigured│ Container │ Over- │ Catch risks ││ resources │ threats │ privileged │ at PR time ││ Compliance │ Vuln scanning│ IAM roles │ │└──────────────┴──────────────┴──────────────┴───────────────┘
Leading CNAPP / CWPP Platforms
| Platform | Vendor | Strength |
|---|---|---|
| Prisma Cloud | Palo Alto Networks | Most comprehensive CNAPP |
| Defender for Cloud | Microsoft | Native Azure, multi-cloud |
| Wiz | Wiz | Agentless, graph-based, fast to deploy |
| Lacework | Lacework | Behavioral anomaly detection |
| Sysdig | Sysdig | Falco-based, container-native |
| Aqua Security | Aqua | Container/K8s lifecycle |
| Orca Security | Orca | Agentless SideScanning |
| Snyk | Snyk | Developer-first, shift-left |
| Checkov / Bridgecrew | Palo Alto | IaC scanning |
Architecture — Full CNAPP Coverage
┌─────────────────────────────────────────────────────────────────┐│ DEVELOPMENT LIFECYCLE ││ ││ CODE BUILD DEPLOY RUNTIME ││ ──── ───── ────── ─────── ││ IDE Plugin CI Pipeline Registry Cloud / K8s ││ IaC Scan SAST/SCA Image Scan Agent/Agentless ││ Secrets scan Container scan Admission ctrl Behavioral detect ││ ││ ◄────────────── Shift Left ──────────┤ ││ ├────── Runtime ─────────► │└─────────────────────────────────────────────────────────────────┘Controls at each stage:┌──────────────────────────────────────────────────────────────┐│ CODE │ Secret scanning, IaC linting, SAST ││ BUILD │ Dependency scanning (SCA), image build scanning ││ REGISTRY │ Vulnerability scanning, malware detection ││ DEPLOY │ Admission controllers, policy enforcement ││ RUNTIME │ Process monitoring, network detection, drift │└──────────────────────────────────────────────────────────────┘
Control Area 1 — Vulnerability Management
Container Image Scanning
# Trivy — open source scanner in CI pipeline# .github/workflows/security.ymlname: Security Scanningon: push: branches: [main] pull_request:jobs: image-scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build image run: docker build -t myapp:${{ github.sha }} . - name: Scan with Trivy uses: aquasecurity/trivy-action@master with: image-ref: myapp:${{ github.sha }} format: sarif output: trivy-results.sarif severity: CRITICAL,HIGH exit-code: '1' # fail pipeline on CRITICAL - name: Upload results to GitHub Security uses: github/codeql-action/upload-sarif@v2 with: sarif_file: trivy-results.sarif
# Trivy scan — localtrivy image \ --severity CRITICAL,HIGH \ --ignore-unfixed \ --format table \ myapp:latest# Output:# Total: 12 (HIGH: 9, CRITICAL: 3)# ┌──────────────┬───────────────┬──────────┬─────────────────┐# │ Library │ Vulnerability │ Severity │ Installed Ver │# ├──────────────┼───────────────┼──────────┼─────────────────┤# │ openssl │ CVE-2023-xxxx │ CRITICAL │ 1.1.1k │# │ libcurl │ CVE-2023-xxxx │ HIGH │ 7.68.0 │# └──────────────┴───────────────┴──────────┴─────────────────┘# Scan filesystem / IaCtrivy fs --security-checks vuln,secret,config .# Scan running K8s clustertrivy k8s --report summary cluster
Prisma Cloud / Defender — Continuous Scanning
# Defender for Cloud — enable vulnerability assessmentaz security pricing create \ --name ContainerRegistry \ --tier Standardaz security pricing create \ --name KubernetesService \ --tier Standard# Enable Defender for Containersaz security pricing create \ --name Containers \ --tier Standard# View vulnerabilitiesaz security assessments list \ --query "[?contains(displayName,'vulnerability')]" \ --output table
# Pull vulnerability findings via APIimport requests# Prisma Cloud APIdef get_vulnerabilities(prisma_url, token): response = requests.get( f"{prisma_url}/api/v1/vulnerability/scan", headers={ "x-redlock-auth": token, "Content-Type": "application/json" }, params={ "severity": "critical,high", "status": "open" } ) return response.json()
Risks Reduced by Vuln Management
Before: After:─────── ─────Unknown CVEs in production All images scanned before deployMonths between patch cycles CVEs found at build time → fix fastNo visibility into base images Full BOM (Bill of Materials) knownManual security reviews Automated gate in every PRRisk reduction:├── Critical CVEs in production: -85%├── Mean time to patch: 30 days → 3 days├── Unknown vulnerabilities: eliminated└── Compliance violations: -70%
Control Area 2 — Cloud Security Posture Management (CSPM)
Misconfiguration Detection
# Checkov — IaC scanning (catches misconfigs before deploy)# Run in CI pipeline# .github/workflows/iac-scan.yml- name: Checkov IaC Scan uses: bridgecrewio/checkov-action@master with: directory: infra/ framework: terraform soft_fail: false output_format: sarif output_file_path: checkov.sarif skip_check: CKV_AZURE_35 # example skip# Catches:# ✗ FAILED for resource: azurerm_storage_account.docs# Check: CKV_AZURE_33: "Ensure Storage logging is enabled"# File: /infra/storage.tf Line: 12## ✗ FAILED for resource: azurerm_sql_server.db# Check: CKV_AZURE_23: "Ensure TDE is enabled"# File: /infra/sql.tf Line: 45
# Custom CSPM check — detect public S3 bucketsimport boto3def check_public_buckets(): s3 = boto3.client('s3') findings = [] for bucket in s3.list_buckets()['Buckets']: name = bucket['Name'] # Check public access block try: config = s3.get_public_access_block(Bucket=name) block = config['PublicAccessBlockConfiguration'] if not all([ block['BlockPublicAcls'], block['IgnorePublicAcls'], block['BlockPublicPolicy'], block['RestrictPublicBuckets'] ]): findings.append({ "resource": f"s3://{name}", "severity": "CRITICAL", "finding": "Public access not fully blocked", "remediation": "Enable all public access block settings" }) except Exception as e: findings.append({ "resource": f"s3://{name}", "severity": "HIGH", "finding": f"Cannot verify public access: {e}" }) return findings
Common CSPM Controls Enabled
Networking Controls:├── ✅ No security groups allowing 0.0.0.0/0 on SSH (port 22)├── ✅ No security groups allowing 0.0.0.0/0 on RDP (port 3389)├── ✅ All storage accounts — public access disabled├── ✅ All databases — no public endpoints├── ✅ All load balancers — HTTPS only└── ✅ VPC flow logs enabled on all VPCsEncryption Controls:├── ✅ All storage encrypted at rest├── ✅ All databases encrypted (TDE enabled)├── ✅ All EBS volumes encrypted by default├── ✅ TLS 1.2+ enforced on all endpoints└── ✅ CMK used for sensitive workloadsLogging Controls:├── ✅ CloudTrail / Activity Log enabled all regions├── ✅ S3 access logging enabled├── ✅ Database audit logging enabled├── ✅ Kubernetes audit logging enabled└── ✅ Log retention ≥ 1 yearIdentity Controls:├── ✅ MFA required for all IAM users├── ✅ Root account has no access keys├── ✅ Password policy enforced (complexity + rotation)├── ✅ No wildcard IAM policies (Action: *)└── ✅ Service accounts have minimal permissions
Risks Reduced by CSPM
Misconfiguration findings closed: 847 → 12 (98.5% reduction)Critical findings SLA: 30 days → 24 hoursOpen S3 buckets found: 23 buckets securedExposed databases: 8 databases made privateCompliance score (CIS): 42% → 94%
Control Area 3 — Runtime Protection
Falco — Container Runtime Security
# falco-rules.yaml — custom rules# Detect shell spawned in container- rule: Shell Spawned in Container desc: A shell was spawned in a container condition: > spawned_process and container and shell_procs and not proc.pname in (shell_procs) output: > Shell spawned in container (user=%user.name container=%container.name image=%container.image.repository shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline) priority: WARNING tags: [container, shell, attack]# Detect privilege escalation- rule: Privilege Escalation via Sudo desc: Sudo was used to escalate privileges condition: > spawned_process and proc.name = sudo and container output: > Privilege escalation in container (user=%user.name container=%container.name command=%proc.cmdline) priority: CRITICAL# Detect sensitive file access- rule: Read Sensitive File in Container desc: Attempt to read sensitive files condition: > open_read and container and (fd.name startswith /etc/shadow or fd.name startswith /etc/sudoers or fd.name = /etc/passwd) and not proc.name in (known_processes) output: > Sensitive file read (file=%fd.name user=%user.name container=%container.name image=%container.image.repository) priority: HIGH# Detect crypto mining- rule: Crypto Mining Process desc: Crypto mining software detected condition: > spawned_process and (proc.name in (known_miners) or proc.cmdline contains "--mining" or proc.cmdline contains "stratum+tcp") output: > Crypto mining process detected (process=%proc.name container=%container.name) priority: CRITICAL# Detect outbound connections to unusual ports- rule: Unexpected Outbound Connection desc: Container making unexpected outbound connection condition: > outbound and container and not fd.sport in (80, 443, 8080, 8443, 5432, 6379) and not proc.name in (allowed_processes) output: > Unexpected outbound connection (container=%container.name dest=%fd.rip:%fd.rport process=%proc.name) priority: WARNING
# Deploy Falco in Kuberneteshelm repo add falcosecurity https://falcosecurity.github.io/chartshelm install falco falcosecurity/falco \ --namespace falco \ --create-namespace \ --set driver.kind=ebpf \ # use eBPF (no kernel module) --set falcosidekick.enabled=true \ # forward alerts --set falcosidekick.config.slack.webhookurl=$SLACK_WEBHOOK \ --set falcosidekick.config.pagerduty.routingKey=$PD_KEY \ --set falco.grpc.enabled=true \ --set falco.grpcOutput.enabled=true# Check Falco is runningkubectl get pods -n falco# View real-time alertskubectl logs -n falco -l app.kubernetes.io/name=falco -f
Runtime Drift Detection
Immutable Infrastructure Principle: Container built from image (known good state) Any change at runtime = drift = suspicious Controls enabled:├── Read-only root filesystem enforced├── Process whitelist — only expected binaries can run├── File integrity monitoring on key paths├── Network baseline — alert on unexpected connections└── User baseline — alert if root process spawns unexpectedlyExample drift detected: Container: api-service Expected processes: [python, gunicorn, uvicorn] Detected: bash → wget → chmod +x → ./malware Action: Alert + kill container + page on-call
# Enforce read-only filesystem + drop all capabilitiesapiVersion: apps/v1kind: Deploymentmetadata: name: apispec: template: spec: containers: - name: api securityContext: readOnlyRootFilesystem: true # ← prevent runtime changes allowPrivilegeEscalation: false runAsNonRoot: true runAsUser: 1000 capabilities: drop: - ALL # ← zero Linux capabilities add: - NET_BIND_SERVICE # only if needed
Control Area 4 — Cloud Identity & Entitlement Management (CIEM)
Detect Over-Privileged IAM
# Detect IAM roles with excessive permissionsimport boto3import jsondef find_overprivileged_roles(): iam = boto3.client('iam') findings = [] for role in iam.list_roles()['Roles']: role_name = role['RoleName'] # Get attached policies policies = iam.list_attached_role_policies( RoleName=role_name )['AttachedPolicies'] for policy in policies: policy_doc = iam.get_policy_version( PolicyArn=policy['PolicyArn'], VersionId=iam.get_policy( PolicyArn=policy['PolicyArn'] )['Policy']['DefaultVersionId'] )['PolicyVersion']['Document'] for statement in policy_doc.get('Statement', []): # Detect wildcard actions actions = statement.get('Action', []) if isinstance(actions, str): actions = [actions] if '*' in actions: findings.append({ "role": role_name, "policy": policy['PolicyName'], "issue": "Wildcard action (*)", "severity": "CRITICAL", "fix": "Replace * with specific actions" }) # Detect wildcard resources resources = statement.get('Resource', []) if isinstance(resources, str): resources = [resources] if '*' in resources and '*' not in actions: findings.append({ "role": role_name, "policy": policy['PolicyName'], "issue": "Wildcard resource (*)", "severity": "HIGH", "fix": "Restrict to specific resource ARNs" }) return findings
Just-in-Time (JIT) Access
Traditional access: Developer has admin access 24/7 → Attack window = unlimited → Blast radius = entire accountJIT access: Developer requests elevated access → Approved for 1-4 hours only → Access auto-revoked → Full audit trail → Attack window = minimalTools: AWS: IAM Identity Center + permission sets Azure: Privileged Identity Management (PIM) GCP: IAM Conditions + Access Context Manager
# Azure PIM — activate role for limited timeaz role assignment create \ --role "Contributor" \ --assignee $USER_OBJECT_ID \ --scope /subscriptions/$SUB_ID \ --condition "((!(ActionMatches{'Microsoft.Authorization/roleAssignments/*'}))" \ --description "JIT access for incident response - expires 2h"# Auto-expire after 2 hoursaz role assignment delete \ --role "Contributor" \ --assignee $USER_OBJECT_ID \ --scope /subscriptions/$SUB_ID
Control Area 5 — Admission Control (Policy Enforcement)
OPA Gatekeeper — K8s Policy Engine
# ConstraintTemplate — define the policyapiVersion: templates.gatekeeper.sh/v1kind: ConstraintTemplatemetadata: name: k8srequiredlabelsspec: crd: spec: names: kind: K8sRequiredLabels validation: openAPIV3Schema: properties: labels: type: array items: type: string targets: - target: admission.k8s.gatekeeper.sh rego: | package k8srequiredlabels violation[{"msg": msg}] { provided := {label | input.review.object.metadata.labels[label]} required := {label | label := input.parameters.labels[_]} missing := required - provided count(missing) > 0 msg := sprintf("Missing required labels: %v", [missing]) }---# Constraint — enforce the policyapiVersion: constraints.gatekeeper.sh/v1beta1kind: K8sRequiredLabelsmetadata: name: require-team-labelspec: match: kinds: - apiGroups: ["apps"] kinds: ["Deployment"] namespaces: ["production"] parameters: labels: - "app" - "team" - "env" - "version"---# Block privileged containersapiVersion: constraints.gatekeeper.sh/v1beta1kind: K8sPSPPrivilegedContainermetadata: name: no-privileged-containersspec: match: kinds: - apiGroups: [""] kinds: ["Pod"] excludedNamespaces: - kube-system - falco---# Require resource limitsapiVersion: constraints.gatekeeper.sh/v1beta1kind: K8sRequiredResourcesmetadata: name: require-resource-limitsspec: match: kinds: - apiGroups: ["apps"] kinds: ["Deployment", "StatefulSet", "DaemonSet"] parameters: limits: - cpu - memory requests: - cpu - memory
Image Admission Control
# Only allow images from trusted registriesapiVersion: constraints.gatekeeper.sh/v1beta1kind: K8sAllowedReposmetadata: name: allowed-reposspec: match: kinds: - apiGroups: [""] kinds: ["Pod"] parameters: repos: - "gcr.io/mycompany/" - "us-central1-docker.pkg.dev/myproject/" - "registry.redhat.io/" # Reject: docker.io (public) unless explicitly needed---# Block latest tag — require pinned versionsapiVersion: constraints.gatekeeper.sh/v1beta1kind: K8sNoLatestTagmetadata: name: no-latest-tagspec: match: kinds: - apiGroups: [""] kinds: ["Pod"]
Control Area 6 — Network Detection & Response
Network Baseline and Anomaly Detection
Baseline phase (14-30 days): Tool learns normal traffic patterns: ├── Which pods talk to which ├── What external IPs are contacted ├── Normal connection volumes └── Expected ports and protocolsDetection phase: Alert on deviations: ├── Pod suddenly contacting external IP ├── Lateral movement (pod-to-pod unexpected) ├── Data exfiltration (large outbound transfer) ├── C2 communication (beacon pattern) └── Port scanning behavior
# Cilium Network Policy with full observabilityapiVersion: cilium.io/v2kind: CiliumNetworkPolicymetadata: name: api-network-policy namespace: productionspec: endpointSelector: matchLabels: app: api ingress: - fromEndpoints: - matchLabels: app: frontend toPorts: - ports: - port: "8080" protocol: TCP rules: http: - method: "GET" path: "/api/.*" - method: "POST" path: "/api/.*" egress: - toEndpoints: - matchLabels: app: database toPorts: - ports: - port: "5432" # Allow DNS only to cluster DNS - toEndpoints: - matchLabels: k8s-app: kube-dns toPorts: - ports: - port: "53" protocol: UDP # Block all other egress
Control Area 7 — Secrets Detection
Pre-commit and CI Scanning
# Install detect-secretspip install detect-secrets# Scan repo for secretsdetect-secrets scan . > .secrets.baseline# Audit findingsdetect-secrets audit .secrets.baseline# Git pre-commit hookcat > .pre-commit-config.yaml << EOFrepos:- repo: https://github.com/Yelp/detect-secrets rev: v1.4.0 hooks: - id: detect-secrets args: ['--baseline', '.secrets.baseline']- repo: https://github.com/zricethezav/gitleaks rev: v8.18.0 hooks: - id: gitleaksEOF# Install hookspre-commit install
# GitLeaks in CI- name: Scan for secrets uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}# Catches:# ├── AWS access keys# ├── Azure SAS tokens# ├── GCP service account keys# ├── GitHub personal access tokens# ├── Stripe / Twilio API keys# ├── Database connection strings# ├── Private SSH keys# └── JWT secrets
Implementing CNAPP — Phased Approach
Phase 1 — Visibility (Week 1-2) Goal: Understand current risk posture ├── Deploy agentless scanner (Wiz / Orca) ├── Connect all cloud accounts ├── Enable CSPM — inventory all resources ├── Run first vulnerability scan └── Generate baseline risk report Deliverable: Risk dashboard showing current statePhase 2 — Shift Left (Week 3-4) Goal: Catch issues before they reach production ├── Integrate IaC scanning in CI (Checkov / Bridgecrew) ├── Add image scanning in build pipeline (Trivy) ├── Enable secret scanning (GitLeaks) ├── Configure policy-as-code gates └── Developer training on findings Deliverable: Pipeline fails on policy violationsPhase 3 — Posture Hardening (Week 5-8) Goal: Fix critical misconfigurations ├── Remediate all CRITICAL CSPM findings ├── Enable encryption everywhere ├── Close public-facing resources ├── Implement network segmentation └── Enable MFA everywhere Deliverable: Compliance score > 80%Phase 4 — Runtime Protection (Week 9-12) Goal: Detect threats in production ├── Deploy Falco / Defender / Prisma agent ├── Enable behavioral detection ├── Configure SIEM integration (Sentinel / Splunk) ├── Set up alert routing (PagerDuty / Slack) └── Run tabletop incident response exercise Deliverable: Alert on runtime threats < 5 min MTTDPhase 5 — Continuous Improvement Goal: Reduce alert fatigue, improve signal quality ├── Tune rules to reduce false positives ├── Automate remediation for known issues ├── Implement SOAR playbooks ├── Regular pen test validation └── Quarterly risk review with stakeholders
Metrics — Risks Reduced
Vulnerability Management: Critical CVEs in prod images: 67 → 3 (-95%) Mean time to patch critical: 45 days → 4 days Images with no scan: 100% → 0%Posture / Misconfigurations: CSPM critical findings: 234 → 8 (-97%) Public cloud resources: 31 → 0 (-100%) Non-compliant resources (CIS): 58% → 6% Compliance score: 41% → 93%Runtime Threats: Mean time to detect (MTTD): Unknown → 4.2 min Runtime incidents investigated: 0 → 47 (visibility gained) Confirmed attacks blocked: 12 (crypto miners, shell access) Lateral movement attempts caught: 8Identity: Over-privileged roles remediated: 89 roles scoped down Wildcard IAM policies: 43 → 0 Service accounts with user keys: 28 → 0 (Workload Identity) Unused access removed: 156 stale permissionsShift Left: Security issues found in CI: 78% of vulns caught before prod IaC misconfigs blocked in PR: 1,247 findings Secrets found and rotated: 34 leaked secrets cleaned up Developers trained: 45 engineers
Interview Talking Points
When asked about CWPP/CNAPP work, structure your answer:1. CONTEXT "We were running 40+ microservices on GKE/AKS with no runtime visibility — we didn't know what was running inside our containers in production."2. CONTROLS IMPLEMENTED "I led the deployment of [Prisma Cloud / Wiz / Falco] across all clusters. Specifically I enabled: - Container image scanning in every CI pipeline - Runtime behavioral detection with custom Falco rules - CSPM across 3 cloud accounts - OPA Gatekeeper for admission control - IaC scanning in PRs blocking on CRITICAL"3. RISKS REDUCED (with numbers) "Before: 234 critical misconfigurations, unknown runtime threats, 45-day patch cycle. After: 8 critical findings, 4-minute MTTD on runtime threats, 4-day patch cycle for criticals."4. CHALLENGES "Biggest challenges were false positive tuning — initial Falco deployment generated 2,000 alerts/day. Spent 3 weeks building exclusion rules and whitelists to get signal-to-noise to a workable level."5. LESSONS LEARNED "Agentless first for visibility, agent-based for deep runtime protection. Start with detect-only mode before enforce — blocking mode needs careful rollout or you'll break production workloads."
CWPP/CNAPP work is ultimately about converting unknown risk into measured, managed risk — the most important outcome is not which tool you deployed but what visibility you gained and what specific threats you can now detect and prevent that you couldn’t before.