feat: add Kyverno admission controller + cosign image verification
- Deploy Kyverno v1.13.4 (chart 3.3.4) via ArgoCD Helm chart - Add ClusterPolicy to verify cosign signatures on registry images (Audit mode) - Add NetworkPolicy for kyverno namespace (default-deny + selective allow) - Extend keycloak-secrets-manager RBAC to kyverno namespace for cosign key sync - ArgoCD Application for kyverno-policies directory
This commit is contained in:
parent
efe1aba2c4
commit
4188d1dd6f
104
apps/infra-network-policies/kyverno.yaml
Normal file
104
apps/infra-network-policies/kyverno.yaml
Normal file
@ -0,0 +1,104 @@
|
||||
# Kyverno NetworkPolicies
|
||||
# Default deny + selective allow for kyverno namespace
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: default-deny-all
|
||||
namespace: kyverno
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
---
|
||||
# Allow DNS egress (all kyverno pods need DNS)
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-dns-egress
|
||||
namespace: kyverno
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
- port: 53
|
||||
protocol: TCP
|
||||
---
|
||||
# Admission controller: receives webhook calls from K8s API, needs K8s API + registry
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-kyverno-admission
|
||||
namespace: kyverno
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/component: admission-controller
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
# K8s API calls webhook on port 9443
|
||||
- ports:
|
||||
- port: 9443
|
||||
protocol: TCP
|
||||
egress:
|
||||
# K8s API server
|
||||
- ports:
|
||||
- port: 6443
|
||||
protocol: TCP
|
||||
# Gitea registry (verify image signatures)
|
||||
- to:
|
||||
- ipBlock:
|
||||
cidr: 10.10.10.1/32
|
||||
ports:
|
||||
- port: 3000
|
||||
protocol: TCP
|
||||
---
|
||||
# Background controller: K8s API + registry
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-kyverno-background
|
||||
namespace: kyverno
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/component: background-controller
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
# K8s API server
|
||||
- ports:
|
||||
- port: 6443
|
||||
protocol: TCP
|
||||
# Gitea registry
|
||||
- to:
|
||||
- ipBlock:
|
||||
cidr: 10.10.10.1/32
|
||||
ports:
|
||||
- port: 3000
|
||||
protocol: TCP
|
||||
---
|
||||
# Cleanup controller: K8s API only
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-kyverno-cleanup
|
||||
namespace: kyverno
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/component: cleanup-controller
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
# K8s API server
|
||||
- ports:
|
||||
- port: 6443
|
||||
protocol: TCP
|
||||
39
apps/kyverno-policies/verify-images.yaml
Normal file
39
apps/kyverno-policies/verify-images.yaml
Normal file
@ -0,0 +1,39 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: verify-image-signatures
|
||||
annotations:
|
||||
policies.kyverno.io/title: Verify Image Signatures
|
||||
policies.kyverno.io/description: >-
|
||||
Verifies that container images from our Gitea registry are signed
|
||||
with cosign. Unsigned images are blocked in Enforce mode.
|
||||
policies.kyverno.io/category: Supply Chain Security
|
||||
policies.kyverno.io/severity: high
|
||||
spec:
|
||||
validationFailureAction: Audit
|
||||
background: true
|
||||
webhookTimeoutSeconds: 30
|
||||
failurePolicy: Ignore
|
||||
rules:
|
||||
- name: verify-gitea-registry-images
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
namespaces:
|
||||
- dev
|
||||
- staging
|
||||
- prod
|
||||
verifyImages:
|
||||
- imageReferences:
|
||||
- "10.10.10.1:3000/claude/*"
|
||||
attestors:
|
||||
- entries:
|
||||
- keys:
|
||||
publicKeys: |-
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEh5WuZfakVC/MApgZIfU4MYoKtbWq
|
||||
ekPSqfXznycT1OBUIdHQ7O4tpXwSppEiruJ7gV8+iexSRqGQOWL9y4dK3A==
|
||||
-----END PUBLIC KEY-----
|
||||
required: true
|
||||
@ -85,3 +85,28 @@ subjects:
|
||||
- kind: ServiceAccount
|
||||
name: keycloak-secrets-manager
|
||||
namespace: kube-system
|
||||
---
|
||||
# Secrets management in kyverno namespace (cosign public key)
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: keycloak-secrets-manager
|
||||
namespace: kyverno
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "create", "update", "patch"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: keycloak-secrets-manager
|
||||
namespace: kyverno
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: keycloak-secrets-manager
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: keycloak-secrets-manager
|
||||
namespace: kube-system
|
||||
|
||||
21
argocd-apps/kyverno-policies.yaml
Normal file
21
argocd-apps/kyverno-policies.yaml
Normal file
@ -0,0 +1,21 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: kyverno-policies
|
||||
namespace: argocd
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: http://10.10.10.1:3000/claude/k8s-apps.git
|
||||
targetRevision: main
|
||||
path: apps/kyverno-policies
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=false
|
||||
59
argocd-apps/kyverno.yaml
Normal file
59
argocd-apps/kyverno.yaml
Normal file
@ -0,0 +1,59 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: kyverno
|
||||
namespace: argocd
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
chart: kyverno
|
||||
repoURL: https://kyverno.github.io/kyverno/
|
||||
targetRevision: "3.3.4"
|
||||
helm:
|
||||
values: |
|
||||
admissionController:
|
||||
replicas: 1
|
||||
container:
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
serviceMonitor:
|
||||
enabled: false
|
||||
backgroundController:
|
||||
enabled: true
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
cleanupController:
|
||||
enabled: true
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
reportsController:
|
||||
enabled: false
|
||||
features:
|
||||
registryClient:
|
||||
allowInsecure: true
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: kyverno
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
Loading…
x
Reference in New Issue
Block a user