Secure Supply Chain Enforcement: Kyverno Image Verification for Java Containers

In the world of Kubernetes and containerized Java applications, ensuring that only approved, secure images run in your clusters is fundamental to supply chain security. Kyverno Image Verify provides a powerful, policy-driven approach to verifying container image signatures, digests, and metadata before they're deployed, offering Java teams a critical security gate that's native to Kubernetes itself.

What is Kyverno Image Verify?

Kyverno is a Kubernetes-native policy engine that manages policies as Kubernetes resources. The image verify functionality specifically allows you to create policies that validate container images based on digital signatures, digests, or other image metadata before pods are created. For Java applications, this means you can enforce that:

  • Only signed images from your trusted registry are deployed
  • Images use immutable digests instead of mutable tags
  • Images meet specific vulnerability thresholds
  • Images come from approved repositories

Why Kyverno Image Verify is Critical for Java

  1. Supply Chain Security: Prevents unauthorized or tampered Java application images from running in your clusters.
  2. Immutable Deployments: Enforces the use of image digests, ensuring that what you test is exactly what runs in production.
  3. Java-Specific Policies: Create policies tailored for Java applications, including JVM version requirements, base image verification, and vulnerability thresholds.
  4. Native Kubernetes Integration: Operates as a Validating Admission Webhook, meaning enforcement happens at the Kubernetes API level before any pod is scheduled.

Implementing Kyverno Image Verify for Java Applications

1. Install Kyverno

helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm install kyverno kyverno/kyverno -n kyverno --create-namespace

2. Configure Image Signing for Java Images
First, sign your Java container images using Cosign:

# Sign your Java application image
cosign sign --key cosign.key myregistry.com/java-app:1.0.0
# Generate key pair if you haven't
cosign generate-key-pair

3. Create Basic Image Verification Policy
This policy ensures all Java application images are signed:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-java-images
spec:
validationFailureAction: Enforce
background: false
webhookTimeoutSeconds: 30
failurePolicy: Fail
rules:
- name: verify-signature
match:
any:
- resources:
kinds:
- Pod
- Deployment
- StatefulSet
- DaemonSet
- Job
- CronJob
verifyImages:
- imageReferences:
- "myregistry.com/java-app:*"
attestors:
- count: 1
entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----

4. Enforce Immutable References for Java Applications
Ensure Java applications use image digests instead of tags:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-image-digests
spec:
validationFailureAction: Enforce
rules:
- name: check-image-digest
match:
any:
- resources:
kinds:
- Pod
- Deployment
validate:
message: "Java application images must use immutable digests, not tags"
pattern:
spec:
containers:
- image: "*@sha256:*"

Advanced Java-Specific Verification Policies

1. Verify JVM Base Image
Ensure Java applications use approved, secure base images:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-java-base-image
spec:
validationFailureAction: Enforce
rules:
- name: check-base-image
match:
any:
- resources:
kinds:
- Pod
preconditions:
all:
- key: "{{ request.object.metadata.labels.app }}"
operator: Equals
value: "java-application"
verifyImages:
- imageReferences:
- "myregistry.com/java-golden:*"
attestors:
- count: 1
entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
mutateDigest: true

2. Vulnerability Threshold Policy
Block deployment of Java images with critical vulnerabilities:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: java-vulnerability-threshold
spec:
validationFailureAction: Enforce
rules:
- name: check-vulnerabilities
match:
any:
- resources:
kinds:
- Pod
context:
- name: vulnResults
apiCall:
urlPath: "/api/v1/scan"
jmesPath: "results[?severity==`CRITICAL` || severity==`HIGH`]"
method: POST
data:
- key: image
value: "{{ images.{{ element }}.uri }}"
verifyImages:
- imageReferences:
- "*"
attestors:
- count: 1
entries:
- annotations:
match:
vulnerability-check: "passed"
attestations:
- predicateType: https://mycompany.com/vulnerability-report
conditions:
- all:
- key: "{{ vulnResults[0].severity }}"
operator: LessThanOrEquals
value: "MEDIUM"
- key: "{{ vulnResults | length(@) }}"
operator: LessThanOrEquals
value: 5

3. Namespace-Specific Java Policies
Different policies for different environments:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: production-java-policy
spec:
validationFailureAction: Enforce
rules:
- name: production-image-signing
match:
any:
- resources:
kinds:
- Pod
namespaces:
- production
verifyImages:
- imageReferences:
- "*myregistry.com/*"
attestors:
- count: 1
entries:
- keys:
publicKeys: k8s://production/cosign-key
mutateDigest: true

Integration with Java CI/CD Pipeline

1. Automated Image Signing in Pipeline

# GitHub Actions workflow for Java applications
name: Build, Sign, and Push Java Image
on:
push:
branches: [ main ]
jobs:
build-and-sign:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Maven
run: mvn clean package -DskipTests
- name: Build Docker image
run: |
docker build -t myregistry.com/java-app:${{ github.sha }} .
docker tag myregistry.com/java-app:${{ github.sha }} myregistry.com/java-app:latest
- name: Sign image with Cosign
env:
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
run: |
cosign sign --key env://COSIGN_PRIVATE_KEY \
myregistry.com/java-app:${{ github.sha }}
cosign sign --key env://COSIGN_PRIVATE_KEY \
myregistry.com/java-app:latest

2. Generate Attestations for Java Applications
Create signed attestations for build provenance and vulnerability scans:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-java-attestations
spec:
validationFailureAction: Enforce
rules:
- name: verify-build-provenance
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "myregistry.com/java-app:*"
attestors:
- count: 2
entries:
- keys:
publicKeys: k8s://default/build-key
attestations:
- predicateType: https://slsa.dev/provenance/v0.2
conditions:
- all:
- key: "{{ predicate.buildType }}"
operator: Equals
value: "https://github.com/actions/workflow"
- keys:
publicKeys: k8s://default/vuln-key
attestations:
- predicateType: https://mycompany.com/vulnerability-report
conditions:
- all:
- key: "{{ predicate.maxSeverity }}"
operator: LessThanOrEquals
value: "MEDIUM"

Best Practices for Java Teams

1. Key Management Strategy

# Store Cosign public keys as Kubernetes secrets
apiVersion: v1
kind: Secret
metadata:
name: cosign-public-key
namespace: kyverno
type: Opaque
stringData:
key.pub: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----

2. Gradual Enforcement Strategy
Start with audit mode, then move to enforcement:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: java-image-verify-audit
spec:
validationFailureAction: Audit  # Start with audit mode
background: true
rules:
- name: audit-image-signatures
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "*myregistry.com/*"
attestors:
- count: 1
entries:
- keys:
publicKeys: k8s://default/cosign-key

3. Monitoring Policy Violations

# Monitor Kyverno policy reports
kubectl get policyreport -A
# View detailed violation reports
kubectl describe policyreport -n production
# Watch for Java-specific violations
kubectl logs -l app=kyverno -n kyverno | grep -i "java"

4. Policy Exceptions for Development
Create exceptions for development namespaces:

apiVersion: kyverno.io/v2beta1
kind: PolicyException
metadata:
name: dev-namespace-exception
namespace: development
spec:
policies:
- verify-java-images
rules:
- verify-signature
exceptions:
- namespaces:
- development
- podNames:
- "*test*"
- "*dev*"

Troubleshooting Common Java Scenarios

1. Multi-Stage Build Verification
For Java applications using multi-stage builds:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-multi-stage-java
spec:
validationFailureAction: Enforce
rules:
- name: verify-builder-image
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "eclipse-temurin:17-jdk*"
- "maven:*"
attestors:
- count: 1
entries:
- keys:
publicKeys: k8s://default/dockerhub-key
- imageReferences:
- "myregistry.com/java-app:*"
attestors:
- count: 1
entries:
- keys:
publicKeys: k8s://default/company-key

2. Sidecar Container Exceptions
For Java applications with sidecars (like service meshes):

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: java-app-with-sidecars
spec:
validationFailureAction: Enforce
rules:
- name: verify-main-container
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- resources:
namespaces:
- istio-system
verifyImages:
- imageReferences:
- "myregistry.com/java-app:*"
attestors:
- count: 1
entries:
- keys:
publicKeys: k8s://default/company-key
excludeImages:
- "istio/proxyv2:*"
- "jaegertracing/*"

Conclusion

Kyverno Image Verify provides Java development teams with a powerful, Kubernetes-native mechanism to enforce supply chain security. By requiring digital signatures, immutable digests, and specific attestations for Java container images, organizations can prevent unauthorized deployments, ensure image integrity, and maintain a secure software supply chain.

The combination of policy-as-code approach, seamless Kubernetes integration, and flexible verification conditions makes Kyverno an essential tool for securing Java applications in production environments. As software supply chain attacks continue to evolve, implementing robust image verification through Kyverno becomes not just a security best practice, but a critical requirement for enterprise Java applications running in Kubernetes.

Advanced Java Supply Chain Security, Kubernetes Hardening & Runtime Threat Detection

Sigstore Rekor in Java – https://macronepal.com/blog/sigstore-rekor-in-java/
Explains integrating Sigstore Rekor into Java systems to create a transparent, tamper-proof log of software signatures and metadata for verifying supply chain integrity.

Securing Java Applications with Chainguard Wolfi – https://macronepal.com/blog/securing-java-applications-with-chainguard-wolfi-a-comprehensive-guide/
Explains using Chainguard Wolfi minimal container images to reduce vulnerabilities and secure Java applications with hardened, lightweight runtime environments.

Cosign Image Signing in Java Complete Guide – https://macronepal.com/blog/cosign-image-signing-in-java-complete-guide/
Explains how to digitally sign container images using Cosign in Java-based workflows to ensure authenticity and prevent unauthorized modifications.

Secure Supply Chain Enforcement Kyverno Image Verification for Java Containers – https://macronepal.com/blog/secure-supply-chain-enforcement-kyverno-image-verification-for-java-containers/
Explains enforcing Kubernetes policies with Kyverno to verify container image signatures and ensure only trusted Java container images are deployed.

Pod Security Admission in Java Securing Kubernetes Deployments for JVM Applications – https://macronepal.com/blog/pod-security-admission-in-java-securing-kubernetes-deployments-for-jvm-applications/
Explains Kubernetes Pod Security Admission policies that enforce security rules like restricted privileges and safe configurations for Java workloads.

Securing Java Applications at Runtime Kubernetes Security Context – https://macronepal.com/blog/securing-java-applications-at-runtime-a-guide-to-kubernetes-security-context/
Explains how Kubernetes security contexts control runtime permissions, user IDs, and access rights for Java containers to improve isolation.

Process Anomaly Detection in Java Behavioral Monitoring – https://macronepal.com/blog/process-anomaly-detection-in-java-comprehensive-behavioral-monitoring-2/
Explains detecting abnormal runtime behavior in Java applications to identify potential security threats using process monitoring techniques.

Achieving Security Excellence CIS Benchmark Compliance for Java Applications – https://macronepal.com/blog/achieving-security-excellence-implementing-cis-benchmark-compliance-for-java-applications/
Explains applying CIS security benchmarks to Java environments to standardize hardening and improve overall system security posture.

Process Anomaly Detection in Java Behavioral Monitoring – https://macronepal.com/blog/process-anomaly-detection-in-java-comprehensive-behavioral-monitoring/
Explains behavioral monitoring of Java processes to detect anomalies and improve runtime security through continuous observation and analysis.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper