From 5c8b98366691e6d7c90f19ee49a5af78409cfdc5 Mon Sep 17 00:00:00 2001 From: juvdiaz Date: Mon, 29 Jun 2026 15:02:53 -0600 Subject: [PATCH] Add internal security lab app --- apps/security-lab/README.md | 16 +++++++++ apps/security-lab/juice-shop.yaml | 52 +++++++++++++++++++++++++++ apps/security-lab/kustomization.yaml | 7 ++++ apps/security-lab/namespace.yaml | 9 +++++ apps/security-lab/network-policy.yaml | 31 ++++++++++++++++ apps/security-lab/webgoat.yaml | 52 +++++++++++++++++++++++++++ bootstrap/apps/variables.tf | 9 +++++ docs/jeannie.1.md | 4 +++ security/README.md | 4 +++ 9 files changed, 184 insertions(+) create mode 100644 apps/security-lab/README.md create mode 100644 apps/security-lab/juice-shop.yaml create mode 100644 apps/security-lab/kustomization.yaml create mode 100644 apps/security-lab/namespace.yaml create mode 100644 apps/security-lab/network-policy.yaml create mode 100644 apps/security-lab/webgoat.yaml diff --git a/apps/security-lab/README.md b/apps/security-lab/README.md new file mode 100644 index 0000000..4804619 --- /dev/null +++ b/apps/security-lab/README.md @@ -0,0 +1,16 @@ +# Security Lab + +This namespace contains intentionally vulnerable applications for defensive +testing practice. It is not exposed through Traefik or the public edge. + +Use port-forwarding from the Debian host: + +```sh +kubectl -n security-lab port-forward svc/juice-shop 3000:3000 +kubectl -n security-lab port-forward svc/webgoat 8080:8080 +``` + +Then point ZAP, nuclei, or a browser at `http://127.0.0.1:3000` or +`http://127.0.0.1:8080`. + +Keep this namespace isolated. Do not add public ingress for these workloads. diff --git a/apps/security-lab/juice-shop.yaml b/apps/security-lab/juice-shop.yaml new file mode 100644 index 0000000..11e35d0 --- /dev/null +++ b/apps/security-lab/juice-shop.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: juice-shop + namespace: security-lab + labels: + app.kubernetes.io/name: juice-shop +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: juice-shop + template: + metadata: + labels: + app.kubernetes.io/name: juice-shop + homelab.dev/security-lab-app: "true" + spec: + automountServiceAccountToken: false + containers: + - name: juice-shop + image: bkimminich/juice-shop:latest + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 3000 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: "1" + memory: 768Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL +--- +apiVersion: v1 +kind: Service +metadata: + name: juice-shop + namespace: security-lab +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: juice-shop + ports: + - name: http + port: 3000 + targetPort: http diff --git a/apps/security-lab/kustomization.yaml b/apps/security-lab/kustomization.yaml new file mode 100644 index 0000000..d3e4ad3 --- /dev/null +++ b/apps/security-lab/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml + - network-policy.yaml + - juice-shop.yaml + - webgoat.yaml diff --git a/apps/security-lab/namespace.yaml b/apps/security-lab/namespace.yaml new file mode 100644 index 0000000..7c338f3 --- /dev/null +++ b/apps/security-lab/namespace.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: security-lab + labels: + homelab.dev/security-lab: "true" + pod-security.kubernetes.io/enforce: baseline + pod-security.kubernetes.io/audit: restricted + pod-security.kubernetes.io/warn: restricted diff --git a/apps/security-lab/network-policy.yaml b/apps/security-lab/network-policy.yaml new file mode 100644 index 0000000..e312e34 --- /dev/null +++ b/apps/security-lab/network-policy.yaml @@ -0,0 +1,31 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: security-lab-default-deny-ingress + namespace: security-lab +spec: + podSelector: {} + policyTypes: + - Ingress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: security-lab-allow-port-forward + namespace: security-lab +spec: + podSelector: + matchLabels: + homelab.dev/security-lab-app: "true" + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + ports: + - protocol: TCP + port: 3000 + - protocol: TCP + port: 8080 diff --git a/apps/security-lab/webgoat.yaml b/apps/security-lab/webgoat.yaml new file mode 100644 index 0000000..953c301 --- /dev/null +++ b/apps/security-lab/webgoat.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: webgoat + namespace: security-lab + labels: + app.kubernetes.io/name: webgoat +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: webgoat + template: + metadata: + labels: + app.kubernetes.io/name: webgoat + homelab.dev/security-lab-app: "true" + spec: + automountServiceAccountToken: false + containers: + - name: webgoat + image: webgoat/webgoat:latest + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 8080 + resources: + requests: + cpu: 200m + memory: 512Mi + limits: + cpu: "1" + memory: 1Gi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL +--- +apiVersion: v1 +kind: Service +metadata: + name: webgoat + namespace: security-lab +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: webgoat + ports: + - name: http + port: 8080 + targetPort: http diff --git a/bootstrap/apps/variables.tf b/bootstrap/apps/variables.tf index cfd55b2..4029f0d 100644 --- a/bootstrap/apps/variables.tf +++ b/bootstrap/apps/variables.tf @@ -84,5 +84,14 @@ variable "applications" { self_heal = true create_namespace = false } + security-lab = { + project = "default" + path = "apps/security-lab" + namespace = "security-lab" + target_revision = "main" + prune = true + self_heal = true + create_namespace = true + } } } diff --git a/docs/jeannie.1.md b/docs/jeannie.1.md index 07fe24b..bd30281 100644 --- a/docs/jeannie.1.md +++ b/docs/jeannie.1.md @@ -163,6 +163,10 @@ targets. : Summarize recent Gitea and Traefik logs for common scanner paths, suspicious user agents, auth failures, and HTTP errors. +`apps/security-lab` +: GitOps-managed internal namespace for intentionally vulnerable practice +targets. Use `kubectl port-forward`; do not expose it publicly. + ### Maintenance `state-backup` diff --git a/security/README.md b/security/README.md index c81e31a..8cb4d2a 100644 --- a/security/README.md +++ b/security/README.md @@ -62,3 +62,7 @@ command. Traefik pod logs when Kubernetes is reachable. It is intentionally heuristic: use it to spot scanner noise, auth failures, suspicious paths, and obvious client/server errors before opening the raw logs. + +The `apps/security-lab` GitOps app deploys intentionally vulnerable targets for +practice. They use ClusterIP services only and should be accessed with +`kubectl port-forward`, not public ingress.