Production-grade DevSecOps platform on AWS EKS — security enforced automatically at every layer, from code commit to running container.
| Capability | Tool | Status |
|---|---|---|
| Container orchestration | AWS EKS 1.34 | ✅ Running |
| Infrastructure as Code | Terraform — 4 modules | ✅ Complete |
| GitOps delivery | ArgoCD app-of-apps | ✅ Deployed |
| Admission control | Kyverno — 8 policies | ✅ Enforcing |
| Security CI/CD | Gitleaks, Bandit, Trivy, Checkov | ✅ Live |
| Observability | Prometheus + Grafana | ✅ Deployed |
| AI security analysis | Claude via AWS Bedrock | ✅ Complete |
| Node autoscaling | Karpenter | 🔄 Phase 2 |
| Secret management | External Secrets + IRSA | 🔄 Phase 2 |
| Zero-trust networking | Istio + Cilium | 🔄 Phase 2 |
Developer pushes code
↓
GitHub Actions CI Pipeline
├── Gitleaks — secret scanning
├── Bandit — Python SAST
├── Safety — dependency CVE audit
├── Trivy — container CVE scan
├── Checkov — IaC security scan
└── Bedrock AI — plain English security summary
↓
ArgoCD GitOps (pull-based deployment)
↓
EKS Cluster
├── Kyverno — admission control (8 policies)
├── Prometheus — metrics collection
├── Grafana — dashboards and alerting
└── App Pods — FastAPI with OTel instrumentation
---
app/
├── main.py FastAPI — OTel instrumented, 2 intentional security flaws
├── Dockerfile --platform linux/amd64 explicit
└── requirements.txt
k8s/ 8 hardened Kubernetes manifests
├── deployment.yaml securityContext, IRSA, anti-affinity, probes
├── networkpolicy.yaml default-deny + TCP+UDP 53
├── hpa.yaml 2-10 replicas, CPU 70%, memory 80%
├── pdb.yaml minAvailable: 1
├── resourcequota.yaml namespace resource cap
└── limitrange.yaml per-container defaults
terraform/
├── modules/
│ ├── vpc/ VPC, subnets, NAT gateway, flow logs
│ ├── eks/ EKS 1.34, KMS encryption, IMDSv2, OIDC
│ ├── ecr/ ECR, scan-on-push, lifecycle policy
│ └── iam/ GitHub OIDC, IRSA, Karpenter roles
└── environments/
├── dev/ t3.small, 2 nodes, ap-south-1
└── staging/
gitops/
├── argocd/apps/ app-of-apps + 5 ArgoCD applications
└── infrastructure/
├── kyverno/policies/ 8 ClusterPolicy admission rules
└── observability/ Prometheus, Grafana, OTel, Loki, Tempo
scripts/
└── ai-security-summary.py Bedrock Claude security summariser
docs/
├── adr/ 5 Architecture Decision Records
├── architecture.md Full platform design document
├── platform-roadmap.md Production evolution roadmap
├── rebuild-runbook.md Step-by-step rebuild guide
└── commands.md All commands used with explanations
.github/workflows/
└── ci.yml 8-stage security pipeline
---
Job 1 — Security Scanning:
Gitleaks secret detection across full git history
Bandit Python SAST — SQL injection, hardcoded secrets
Safety dependency CVE audit
Job 2 — Build, Scan and Push:
Trivy container CVE scan (CRITICAL + HIGH)
Syft SBOM generation (CycloneDX format)
tflint Terraform linting
Checkov IaC security — 40+ policy checks
Bedrock AI Claude summarises all findings in plain English
Job 3 — Deploy (when DEPLOY_ENABLED=true):
kubectl apply all 8 manifests
rollout status verify deployment succeeded
Two intentional flaws in `app/main.py` prove the gates work:
```python
# Flaw 1 — caught by Gitleaks (hardcoded secret)
SECRET_API_KEY = "sk-prod-9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c"
# Flaw 2 — caught by Bandit B608 (SQL injection)
query = "SELECT * FROM users WHERE id = " + user_id
Download bandit-sast-report or ai-security-summary from
any pipeline run to see real output.
## Kyverno Admission Policies
| Policy | Mode | Blocks |
|---|---|---|
| require-resource-limits | Enforce | Pods without CPU/memory limits |
| restrict-image-registries | Enforce | Non-ECR images |
| disallow-latest-tag | Enforce | :latest image tag |
| require-non-root | Enforce | Root containers |
| require-labels | Enforce | Missing app/version/managed-by |
| disallow-privileged | Enforce | Privileged containers |
| require-readonly-filesystem | Enforce | Writable root filesystem |
| require-pod-disruption-budget | Audit | Deployments with no PDB |
---
## Architecture Decisions
Five ADRs document the key decisions made during platform design:
| ADR | Decision | Why |
|---|---|---|
| [001](docs/adr/001-eks-over-ecs.md) | EKS over ECS | Cloud-agnostic, full CNCF ecosystem |
| [002](docs/adr/002-gitops-argocd-over-kubectl.md) | ArgoCD over kubectl | Drift detection, self-healing |
| [003](docs/adr/003-kyverno-over-opa-gatekeeper.md) | Kyverno over OPA | Developer experience, YAML policies |
| [004](docs/adr/004-karpenter-over-cluster-autoscaler.md) | Karpenter over CAS | 40-60% cost reduction |
| [005](docs/adr/005-irsa-over-instance-profile.md) | IRSA over instance profiles | Minimal blast radius |
---
## Screenshots
| What | Screenshot |
|---|---|
| Platform stack — all namespaces | [view](screenshots/01-platform-stack-overview-3.png) |
| EKS cluster | [view](screenshots/02-eks-cluster.png) |
| Node group | [view](screenshots/03-eks-nodegroup.png) |
| ECR repository | [view](screenshots/04-ecr-repo.png) |
| CI pipeline green | [view](screenshots/05-github-pipeline-blue.png) |
| App health endpoint | [view](screenshots/06-app-health.png) |
| App running in browser | [view](screenshots/07-app-browser.png) |
| FastAPI docs | [view](screenshots/08-app-docs.png) |
| Kyverno 8 policies | [view](screenshots/09-cluster-policy.png) |
| Nodes running | [view](screenshots/10-nodes.png) |
| Grafana node dashboard | [view](screenshots/11-grafana-dashboard-nodes.png) |
| Grafana namespace workloads | [view](screenshots/12-grafana-namespace-workloads.png) |
| Grafana login | [view](screenshots/13-grafana-loginpage.png) |
| Grafana metrics | [view](screenshots/23-grafana-metrics.png) |
---
## Rebuild From Scratch
```bash
# 1. Provision infrastructure (~12 minutes)
cd terraform
terraform init
terraform apply -auto-approve
# 2. Configure kubectl
aws eks update-kubeconfig \
--name devsecops-cluster \
--region ap-south-1
# 3. Build and push image
docker buildx build \
--platform linux/amd64 \
-t <AWS_ACCOUNT_ID>.dkr.ecr.ap-south-1.amazonaws.com/devsecops-app:v1.0.0 \
--push ./app
# 4. Deploy application
kubectl apply -f k8s/
# 5. Install GitOps and policy engine
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
helm install kyverno kyverno/kyverno -n kyverno --create-namespace
kubectl apply -f gitops/infrastructure/kyverno/policies/
# 6. Install observability
helm install prometheus prometheus-community/kube-prometheus-stack \
-n observability --create-namespace \
--set grafana.adminPassword=your-password
# 7. Verify everything
kubectl get pods -n devsecops
kubectl get pods -n argocd
kubectl get pods -n kyverno
kubectl get pods -n observability
kubectl get clusterpolicy
# 8. Destroy when done
terraform destroy -auto-approve
Full runbook: docs/rebuild-runbook.md All commands with explanations: docs/commands.md
Apple Silicon architecture mismatch
Building without --platform linux/amd64 produces ARM images
that cannot run on EKS x86 nodes. Always specify explicitly.
EKS KMS key and launch template conflict Custom KMS key on EBS volumes in launch template requires the node IAM role to have explicit KMS permissions. Fix: use AWS default EBS encryption key instead of custom KMS.
NetworkPolicy blocking DNS TCP-only port 53 egress breaks DNS — Kubernetes uses UDP by default. Fix: allow both TCP and UDP on port 53 in egress rules.
ECR token expiry
ECR tokens expire after 12 hours.
Fix: re-run aws ecr get-login-password before any push session.
t3.small memory pressure Running ArgoCD + Kyverno + Prometheus on t3.small causes OOM. Fix: use t3.medium for full observability stack deployment.
See docs/platform-roadmap.md for the full production evolution plan including:
- External Secrets Operator — AWS Secrets Manager via IRSA
- Karpenter — spot + on-demand autoscaling (~40% cost reduction)
- Falco — runtime threat detection
- Zero-trust networking — Istio mTLS + Cilium L7
- Multi-environment promotion — dev → staging → prod via ArgoCD
Saroj Naik — Principal Cloud Architect
20+ years experience in Cloud AI, Zero-Trust Architecture, Multi-Cloud Observability, Kubernetes, GitOps, and DevOps.
- Email: sarojnaik.official@gmail.com
- LinkedIn: linkedin.com/in/nsaroj