Level: Intermediate / Advanced Last Updated: June 2026
Table of Contents
- Introduction to DevSecOps
- Module 1 – Implementing DevSecOps with AKS
- Module 2 – Securing Identity and Access
- Module 3 – Securing AKS Workloads
- Module 4 – Securing the AKS Network
- Module 5 – Storing and Managing Secrets
- Module 6 – Governance and Continuous Compliance
- Complete Code Examples
- Comparative Tables
- Glossary
Introduction to DevSecOps
Why Traditional Security Fails in Cloud-Native Environments
For decades, application security operated on a waterfall model: development teams built the product, operations teams deployed it, and security teams conducted audits or penetration tests at the end of the cycle. This model, while effective in monolithic slow-release environments, is totally inadequate in the era of microservices, containers, and continuous deployment.
In a Kubernetes cluster, a single vulnerability in a container image can compromise the entire workload. A poorly protected secret in a YAML manifest can expose credentials to malicious actors. A missing Network Policy can allow a compromised Pod to spread laterally to all other namespaces. These risks are real, documented, and occur in production in companies of all sizes.
DevSecOps addresses this problem by integrating security at every stage of the software development lifecycle (SDLC), from the planning phase to post-deployment operations. It’s no longer the exclusive responsibility of a specialized team: it’s a shared responsibility between developers, operators, and security teams.
The “Shift Left” Philosophy
The concept of “Shift Left” is fundamental in DevSecOps. It designates moving security controls toward the initial phases of the delivery pipeline, rather than at the end of the chain.
OLD MODEL:
Plan → Dev → Build → Test → [Security] → Release → Ops
NEW MODEL (Shift Left):
[Security] → Plan → [Security] → Dev → [Security] → Build → [Security] → Test → [Security] → Release → [Security] → Ops
The economic logic is simple: fixing a vulnerability found in a developer’s IDE takes a few minutes. The same vulnerability found in production can cost days of incident, data loss, regulatory penalties, and major reputation damage.
graph LR
A[IDE / Dev] -->|Cost: 1x| B[Build]
B -->|Cost: 10x| C[Test QA]
C -->|Cost: 100x| D[Staging]
D -->|Cost: 1000x| E[Production]
style A fill:#22c55e,color:#fff
style B fill:#84cc16,color:#fff
style C fill:#eab308,color:#000
style D fill:#f97316,color:#fff
style E fill:#ef4444,color:#fff
Fundamental rule: The earlier a vulnerability is discovered in the SDLC, the less expensive it is to fix. The ratio is estimated at 1:10:100:1000 between IDE, build, staging and production detection.
DevOps vs DevSecOps: Comparison
| Dimension | DevOps | DevSecOps |
|---|---|---|
| Main objective | Speed and delivery reliability | Speed + reliability + integrated security |
| Security responsibility | Separate security team | Shared between Dev, Ops, Sec |
| Control timing | End of pipeline (pentest) | Each phase (shift left) |
| Security testing | Manual and periodic | Automated and continuous |
| Secret management | Environment variables, configs | Vault, Managed Identities, OIDC |
| Compliance | Periodic audits | Continuous compliance (Azure Policy) |
| Incidents | Reactive after the fact | Proactive detection + rapid response |
Module 1 – Implementing DevSecOps with AKS
DevSecOps Pipeline Overview for AKS
flowchart TD
subgraph PLAN["Plan Phase"]
P1[Azure Landing Zones]
P2[Threat Modeling]
P3[WAF Assessment]
P4[Governance & RBAC]
end
subgraph DEV["Develop Phase"]
D1[SAST - SonarLint/Snyk]
D2[Linting - ESLint/pylint]
D3[kube-score/kube-bench]
D4[Secret Detection IDE]
end
subgraph BUILD["Build Phase"]
B1[Automated Tests]
B2[Dependency Scanning - Trivy]
B3[Image Signing - Notation]
B4[Secret Scanning]
B5[GitHub Dependency Review]
end
subgraph RELEASE["Release Phase"]
R1[Protected Branches]
R2[GitOps - Flux/ArgoCD]
R3[DAST - OWASP ZAP]
R4[Workload Identity]
R5[Approval Gates]
end
subgraph OPS["Operate Phase"]
O1[Azure Policy + Gatekeeper]
O2[Network Policies]
O3[Defender for Containers]
O4[Microsoft Sentinel]
O5[AKS Upgrades]
end
PLAN --> DEV --> BUILD --> RELEASE --> OPS
OPS -->|Continuous feedback| PLAN
style PLAN fill:#3b82f6,color:#fff
style DEV fill:#8b5cf6,color:#fff
style BUILD fill:#f59e0b,color:#000
style RELEASE fill:#10b981,color:#fff
style OPS fill:#ef4444,color:#fff
Planning Phase: Building a Secure Foundation
Azure Landing Zones
An Azure Landing Zone is a reference architecture that provides a secure, scalable and modular foundation for deploying workloads in Azure. It is not a product to install, but an architectural approach that integrates governance from the design stage.
Azure Landing Zone Structure:
graph TD
subgraph MG["Management Group Hierarchy"]
ROOT[Root Management Group]
PLATFORM[Platform MG]
APP[Application MG]
ROOT --> PLATFORM
ROOT --> APP
subgraph PLAT_SUBS["Platform Subscriptions"]
IDENT[Identity Subscription]
CONN[Connectivity Subscription]
MGMT[Management Subscription]
end
subgraph APP_SUBS["Application Subscriptions"]
PROD[Production AKS Sub]
NONPROD[Non-Prod AKS Sub]
SAND[Sandbox Sub]
end
PLATFORM --> PLAT_SUBS
APP --> APP_SUBS
end
style ROOT fill:#1e40af,color:#fff
style PLATFORM fill:#3b82f6,color:#fff
style APP fill:#10b981,color:#fff
Key Components of an AKS Landing Zone:
| Component | Description | Azure Service |
|---|---|---|
| Centralized identity | AAD tenant, PIM, Conditional Access | Microsoft Entra ID |
| Hub connectivity | VNet peering, ExpressRoute, VPN | Azure Virtual Network |
| Shared security | Firewall, DDoS, WAF | Azure Firewall, Front Door |
| Centralized monitoring | Logs, metrics, alerts | Azure Monitor, Log Analytics |
| Governance | Policies, RBAC, Blueprints | Azure Policy, RBAC |
| AKS workload | Cluster, ACR, Key Vault | AKS, ACR, Key Vault |
Well-Architected Framework (WAF) Applied to AKS
mindmap
root((WAF AKS))
Reliability
Multi-zone node pools
Pod disruption budgets
Health probes
Auto-scaling HPA/KEDA
Security
Workload Identity
Network Policies
Private cluster
Azure Policy Gatekeeper
Cost Optimization
Right-sizing nodes
Spot node pools
Resource quotas
Cluster autoscaler
Operational Excellence
GitOps Flux
Monitoring Prometheus
Alerting Grafana
Upgrade automation
Performance Efficiency
Node selectors
Resource limits/requests
Horizontal scaling
Vertical Pod Autoscaler
Threat Modeling with STRIDE
| Letter | Threat | AKS Example | Countermeasure |
|---|---|---|---|
| S | Spoofing | Pod impersonating another service | Workload Identity + mTLS |
| T | Tampering | Malicious modification of images | Image signing (Notation) + Ratify |
| R | Repudiation | Untraceable actions in cluster | Audit logs + Microsoft Sentinel |
| I | Information Disclosure | Secrets exposed in manifests | Azure Key Vault + CSI Driver |
| D | Denial of Service | Pod consuming all resources | LimitRange + ResourceQuota |
| E | Elevation of Privilege | Container running as root | SecurityContext + PodSecurity |
Governance with Azure Policy
# Enable the Azure Policy add-on for AKS
az aks enable-addons \
--resource-group myRG \
--name myCluster \
--addons azure-policy
# Assign CIS compliance policy
az policy assignment create \
--name "aks-cis-benchmark" \
--scope "/subscriptions/{subId}/resourceGroups/{rg}/providers/Microsoft.ContainerService/managedClusters/{cluster}" \
--policy-set-definition "a8640138-9b0a-4a28-b8cb-1666c838647d" \
--display-name "AKS CIS Benchmark"
Important AKS Policies:
| Policy | Description | Effect |
|---|---|---|
| Kubernetes cluster pods should not use host network | Prevents Pods from using host network | Deny |
| Kubernetes clusters should not allow container privilege escalation | Prevents privilege escalation | Deny |
| Kubernetes cluster containers should not share the host process ID namespace | PID isolation | Deny |
| Kubernetes cluster should use authorized IP ranges | Restricts API server access | Audit |
Development Phase: Securing the Developer Environment
Static Application Security Testing (SAST)
SAST analyzes source code without executing it. It is the earliest form of vulnerability detection and can be integrated directly into the developer’s IDE.
Linting and static analysis tools:
| Tool | Language(s) | Analysis Type | IDE Integration |
|---|---|---|---|
| ESLint | JavaScript/TypeScript | Syntax, style, bugs | VS Code, WebStorm |
| pylint | Python | Errors, PEP8 style | VS Code, PyCharm |
| SonarLint | Java, JS, Python, C# | Bugs, vulnerabilities, smells | VS Code, IntelliJ |
| Hadolint | Dockerfile | Docker best practices | VS Code |
| checkov | Terraform, K8s, ARM | IaC misconfigurations | VS Code, CLI |
Container and Kubernetes Scanning with Trivy
# Installation
brew install aquasecurity/trivy/trivy # macOS
# Scan a Docker image
trivy image nginx:latest
# Scan with severity threshold (fail if CRITICAL or HIGH)
trivy image --exit-code 1 --severity HIGH,CRITICAL nginx:latest
# Scan Kubernetes directory
trivy config ./kubernetes/
# Scan IaC files
trivy fs --security-checks config .
Kubernetes Validation with kube-bench and kube-score
# kube-bench: CIS Kubernetes compliance
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl logs job/kube-bench
# kube-score: Kubernetes manifest analysis
kube-score score deployment.yaml
Build Phase: Securing the Build Pipeline
GitHub Actions Pipeline for AKS
name: AKS DevSecOps Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
ACR_NAME: myacr.azurecr.io
IMAGE_NAME: my-app
CLUSTER_NAME: my-aks-cluster
RESOURCE_GROUP: my-resource-group
permissions:
id-token: write # For OIDC with Azure
contents: read
security-events: write
jobs:
security-scan:
name: Security Scan & SAST
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Gitleaks (secret detection)
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Dependency Review
uses: actions/dependency-review-action@v3
if: github.event_name == 'pull_request'
with:
fail-on-severity: high
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- name: Validate K8s manifests with kube-score
run: |
curl -L https://github.com/zegl/kube-score/releases/download/v1.17.0/kube-score_1.17.0_linux_amd64 -o kube-score
chmod +x kube-score
find ./kubernetes -name "*.yaml" | xargs ./kube-score score --exit-one-on-warning
- name: Checkov IaC Scan
uses: bridgecrewio/checkov-action@master
with:
directory: .
framework: kubernetes,dockerfile
output_format: sarif
output_file_path: reports/checkov.sarif
build-and-scan:
name: Build, Scan & Sign Image
needs: security-scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Azure Login (OIDC)
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Login to ACR
run: az acr login --name ${{ env.ACR_NAME }}
- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: ${{ env.ACR_NAME }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
- name: Trivy image vulnerability scan
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.ACR_NAME }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
format: sarif
output: trivy-results.sarif
severity: CRITICAL,HIGH
exit-code: '1'
- name: Push image to ACR
if: success()
run: docker push ${{ env.ACR_NAME }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
deploy-staging:
name: Deploy to Staging (GitOps)
needs: build-and-scan
runs-on: ubuntu-latest
environment: staging
steps:
- name: Update GitOps repository
run: |
git clone https://github.com/my-org/gitops-repo.git
cd gitops-repo
sed -i "s|image: .*my-app:.*|image: ${{ env.ACR_NAME }}/${{ env.IMAGE_NAME }}:${{ github.sha }}|g" \
environments/staging/deployment.yaml
git commit -am "feat: update my-app to ${{ github.sha }}"
git push
Module 2 – Securing Identity and Access
Workload Identity
Workload Identity allows AKS pods to access Azure resources without storing any credentials.
# ServiceAccount with Workload Identity
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-app-sa
namespace: production
annotations:
azure.workload.identity/client-id: "${USER_ASSIGNED_CLIENT_ID}"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
spec:
template:
metadata:
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: my-app-sa
containers:
- name: app
image: myacr.azurecr.io/my-app:v1.0.0
# Create the User Assigned Identity
az identity create \
--name my-app-identity \
--resource-group myRG
# Create the Federated Credential
az identity federated-credential create \
--name my-app-federated-credential \
--identity-name my-app-identity \
--resource-group myRG \
--issuer "$(az aks show --name myCluster --resource-group myRG --query 'oidcIssuerProfile.issuerUrl' -o tsv)" \
--subject "system:serviceaccount:production:my-app-sa"
# Assign RBAC role to the identity
az role assignment create \
--role "Key Vault Secrets User" \
--assignee "$(az identity show --name my-app-identity --resource-group myRG --query clientId -o tsv)" \
--scope "$(az keyvault show --name myKeyVault --query id -o tsv)"
Azure RBAC for Kubernetes
# Grant a user Kubernetes Cluster Admin access via Azure RBAC
az role assignment create \
--role "Azure Kubernetes Service Cluster Admin Role" \
--assignee "user@company.com" \
--scope "$(az aks show --name myCluster --resource-group myRG --query id -o tsv)"
# Developer access (namespace limited)
az role assignment create \
--role "Azure Kubernetes Service Cluster User Role" \
--assignee "dev-user@company.com" \
--scope "$(az aks show --name myCluster --resource-group myRG --query id -o tsv)"
Module 3 – Securing AKS Workloads
Pod Security Standards
# Enforce security context on all pods
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
---
# Secure deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: production
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myacr.azurecr.io/my-app:v1.0.0
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
ResourceQuota and LimitRange
# ResourceQuota per namespace
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
count/pods: "20"
---
# LimitRange to enforce defaults
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: production
spec:
limits:
- default:
cpu: 200m
memory: 256Mi
defaultRequest:
cpu: 50m
memory: 64Mi
type: Container
Module 4 – Securing the AKS Network
Network Policies
# Default: deny all ingress traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
---
# Allow only specific traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-to-db
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 5432
Private AKS Cluster
# Create a private cluster
az aks create \
--resource-group myRG \
--name privateCluster \
--enable-private-cluster \
--enable-managed-identity \
--node-count 3 \
--enable-azure-policy \
--enable-azure-rbac \
--network-plugin azure \
--generate-ssh-keys
# Verify private cluster
az aks show --name privateCluster --resource-group myRG \
--query "apiServerAccessProfile.enablePrivateCluster"
Module 5 – Storing and Managing Secrets
Azure Key Vault with CSI Driver
# Install the Secrets Store CSI Driver
az aks enable-addons \
--addons azure-keyvault-secrets-provider \
--name myCluster \
--resource-group myRG
# SecretProviderClass to access Key Vault
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: azure-kvname-workload-identity
namespace: production
spec:
provider: azure
parameters:
usePodIdentity: "false"
clientID: "${USER_ASSIGNED_CLIENT_ID}"
keyvaultName: "myKeyVault"
cloudName: ""
objects: |
array:
- |
objectName: database-password
objectType: secret
- |
objectName: api-key
objectType: secret
tenantId: "${TENANT_ID}"
secretObjects:
- data:
- key: password
objectName: database-password
secretName: db-credentials
type: Opaque
Module 6 – Governance and Continuous Compliance
Azure Policy Gatekeeper Constraints
# Constraint: Require container security context
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequireSecurityContext
metadata:
name: require-security-context
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
excludedNamespaces: ["kube-system"]
parameters:
allowPrivilegeEscalation: false
runAsNonRoot: true
readOnlyRootFilesystem: true
Microsoft Defender for Containers
# Enable Defender for Containers
az security pricing create \
--name Containers \
--tier Standard
# View container security recommendations
az security assessment list \
--query "[?properties.metadata.categories[0]=='Compute'].{Name:displayName,Severity:properties.metadata.severity}" \
--output table
GitOps with Flux CD
# Install Flux CLI
curl -s https://fluxcd.io/install.sh | sudo bash
# Bootstrap Flux in AKS cluster with GitHub
flux bootstrap github \
--owner=my-org \
--repository=gitops-aks \
--branch=main \
--path=clusters/production \
--personal \
--token-auth
# HelmRelease via GitOps
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: my-app
namespace: production
spec:
interval: 5m
chart:
spec:
chart: my-app
version: ">=1.0.0"
sourceRef:
kind: HelmRepository
name: my-charts
namespace: flux-system
values:
image:
repository: myacr.azurecr.io/my-app
tag: "v1.0.0"
Comparative Tables
Security Tools for AKS
| Tool | Category | Phase | Coverage |
|---|---|---|---|
| Trivy | Vulnerability scanning | Build + Runtime | Images, IaC, OS packages |
| Gitleaks | Secret detection | Develop + Build | Git history |
| kube-score | K8s best practices | Develop + Build | Manifests |
| kube-bench | CIS compliance | Runtime | Node + cluster |
| OPA Gatekeeper | Policy enforcement | Runtime | All K8s resources |
| Falco | Runtime threat detection | Runtime | Syscalls, containers |
| Notation | Image signing | Build | Container images |
| Ratify | Image verification | Runtime | Signed images |
| Flux CD | GitOps | Release + Ops | K8s configurations |
| Azure Policy | Compliance | All phases | Azure + K8s resources |
| Defender for Containers | Runtime security | Runtime | Clusters, images |
AKS Security Levels
| Level | Configuration | Tools | Compliance |
|---|---|---|---|
| Basic | RBAC, Network Policies | Trivy, kube-score | CIS L1 |
| Standard | + Workload Identity, Private cluster | + OPA Gatekeeper | CIS L2 |
| Advanced | + Image signing, mTLS, Falco | + Ratify, Notation | NIST, SOC2 |
| Enterprise | + Landing Zone, full audit | + Sentinel, Defender | PCI-DSS, HIPAA |
Glossary
| Term | Definition |
|---|---|
| AKS | Azure Kubernetes Service — Microsoft’s managed Kubernetes service |
| Cluster Autoscaler | Automatically adjusts node count based on Pod resource requirements |
| CSI Driver | Container Storage Interface — standardized driver for integrating storage in K8s |
| DevSecOps | Integration of security in all phases of DevOps |
| DPoP | Demonstration of Proof-of-Possession — token binding protocol |
| Falco | Open-source runtime security tool based on system calls |
| Flux CD | Open-source GitOps operator for Kubernetes |
| GitOps | Practice of using Git as single source of truth for K8s configurations |
| HPA | Horizontal Pod Autoscaler — scales Pod replicas based on metrics |
| Kustomize | Tool for K8s manifest customization without templating |
| LimitRange | K8s resource defining default resource constraints per namespace |
| NAMESPACE | Kubernetes virtual cluster for resource isolation |
| Notation | CNCF tool for signing container images |
| OPA | Open Policy Agent — general-purpose policy engine |
| Gatekeeper | OPA-based admission controller for Kubernetes |
| Pod | Smallest deployable unit in Kubernetes (one or more containers) |
| Pod Security Standards | K8s security profiles (privileged, baseline, restricted) |
| Ratify | Tool that verifies image signatures and attestations in AKS |
| RBAC | Role-Based Access Control — role-based access control |
| ResourceQuota | K8s resource limiting total resource consumption per namespace |
| SecurityContext | Security configuration applied to a Pod or container |
| Service Account | Kubernetes identity for pods to access the K8s API |
| Shift Left | Moving security controls toward early phases of the SDLC |
| SAST | Static Application Security Testing — static code analysis |
| DAST | Dynamic Application Security Testing — tests on running application |
| STRIDE | Threat modeling framework (Spoofing, Tampering, Repudiation, etc.) |
| Trivy | Open-source vulnerability scanner for images, IaC and file systems |
| VPA | Vertical Pod Autoscaler — automatically adjusts CPU/memory requests |
| WAF | Well-Architected Framework — Microsoft’s architecture best practices framework |
| Workload Identity | AKS feature for granting pods access to Azure resources without secrets |
Search Terms
strategic · devsecops · foundations · azure · kubernetes · service · aks · ci/cd · git · devops · securing · security · phase · pipeline · governance · identity · network · policy