Understanding CWPP and CNAP for Cloud Security

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 detection
CNAPP — 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

PlatformVendorStrength
Prisma CloudPalo Alto NetworksMost comprehensive CNAPP
Defender for CloudMicrosoftNative Azure, multi-cloud
WizWizAgentless, graph-based, fast to deploy
LaceworkLaceworkBehavioral anomaly detection
SysdigSysdigFalco-based, container-native
Aqua SecurityAquaContainer/K8s lifecycle
Orca SecurityOrcaAgentless SideScanning
SnykSnykDeveloper-first, shift-left
Checkov / BridgecrewPalo AltoIaC 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.yml
name: Security Scanning
on:
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 — local
trivy 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 / IaC
trivy fs --security-checks vuln,secret,config .
# Scan running K8s cluster
trivy k8s --report summary cluster
Prisma Cloud / Defender — Continuous Scanning
# Defender for Cloud — enable vulnerability assessment
az security pricing create \
--name ContainerRegistry \
--tier Standard
az security pricing create \
--name KubernetesService \
--tier Standard
# Enable Defender for Containers
az security pricing create \
--name Containers \
--tier Standard
# View vulnerabilities
az security assessments list \
--query "[?contains(displayName,'vulnerability')]" \
--output table
# Pull vulnerability findings via API
import requests
# Prisma Cloud API
def 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 deploy
Months between patch cycles CVEs found at build time → fix fast
No visibility into base images Full BOM (Bill of Materials) known
Manual security reviews Automated gate in every PR
Risk 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 buckets
import boto3
def 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 VPCs
Encryption 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 workloads
Logging Controls:
├── ✅ CloudTrail / Activity Log enabled all regions
├── ✅ S3 access logging enabled
├── ✅ Database audit logging enabled
├── ✅ Kubernetes audit logging enabled
└── ✅ Log retention ≥ 1 year
Identity 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 hours
Open S3 buckets found: 23 buckets secured
Exposed databases: 8 databases made private
Compliance 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 Kubernetes
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm 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 running
kubectl get pods -n falco
# View real-time alerts
kubectl 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 unexpectedly
Example 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 capabilities
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
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 permissions
import boto3
import json
def 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 account
JIT access:
Developer requests elevated access
→ Approved for 1-4 hours only
→ Access auto-revoked
→ Full audit trail
→ Attack window = minimal
Tools:
AWS: IAM Identity Center + permission sets
Azure: Privileged Identity Management (PIM)
GCP: IAM Conditions + Access Context Manager
# Azure PIM — activate role for limited time
az 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 hours
az 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 policy
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
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 policy
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-team-label
spec:
match:
kinds:
- apiGroups: ["apps"]
kinds: ["Deployment"]
namespaces: ["production"]
parameters:
labels:
- "app"
- "team"
- "env"
- "version"
---
# Block privileged containers
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
name: no-privileged-containers
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
excludedNamespaces:
- kube-system
- falco
---
# Require resource limits
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredResources
metadata:
name: require-resource-limits
spec:
match:
kinds:
- apiGroups: ["apps"]
kinds: ["Deployment", "StatefulSet", "DaemonSet"]
parameters:
limits:
- cpu
- memory
requests:
- cpu
- memory
Image Admission Control
# Only allow images from trusted registries
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
name: allowed-repos
spec:
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 versions
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sNoLatestTag
metadata:
name: no-latest-tag
spec:
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 protocols
Detection 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 observability
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: api-network-policy
namespace: production
spec:
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-secrets
pip install detect-secrets
# Scan repo for secrets
detect-secrets scan . > .secrets.baseline
# Audit findings
detect-secrets audit .secrets.baseline
# Git pre-commit hook
cat > .pre-commit-config.yaml << EOF
repos:
- 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: gitleaks
EOF
# Install hooks
pre-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 state
Phase 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 violations
Phase 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 MTTD
Phase 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: 8
Identity:
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 permissions
Shift 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.

Leave a Reply