A Kubernetes-native, event-driven service that automatically triggers enterprise contract verification for application snapshots using Tekton bundles.
The Conforma Knative Service is a CloudEvents-based service that monitors for the creation of Snapshot resources and automatically triggers compliance verification workflows. It implements an event-driven architecture to bridge CloudEvents with Tekton pipelines, using bundle resolution to dynamically fetch verification tasks from container registries.
- Listens for CloudEvents of type
dev.knative.apiserver.resource.add - Processes Snapshot resources from the
appstudio.redhat.com/v1alpha1API - Automatically creates Tekton TaskRuns for compliance verification
- Uses Tekton's bundle resolver to fetch tasks from
quay.io/conforma/tekton-task:latest - Eliminates the need for pre-installed tasks in the cluster
- Enables dynamic task updates without redeploying the service
- ConfigMap-based configuration with caching and TTL
- Supports multiple namespaces with isolated configuration
- Configurable parameters for policy verification
- Automated Compliance: Triggers verification workflows without manual intervention
- Multi-Namespace Support: Handles snapshots across different namespaces
- Configurable Policies: Supports custom policy configurations and public keys
- Cloud-Native: Stateless, horizontally scalable, and Kubernetes-native
- Bundle-Based: Dynamic task resolution from container registries
make setup-knativeThis creates a kind cluster named "knative" with Knative Eventing installed (Knative Serving is not required).
make deploy-localThis will automatically:
- Build the Go application locally using
ko - Load the image into the kind cluster (for kind) or use existing registry images (for other clusters)
- Deploy all Kubernetes resources to the
defaultnamespace - Wait for pods to be ready
- Display the service URL
Expected Duration: ~1-2 minutes for kind clusters
Note: This deploys to the default namespace. For staging-like testing in an isolated namespace, use make deploy-staging-local instead.
make test-localThis creates a sample Snapshot resource to verify the service is working correctly.
The service reads configuration from a ConfigMap named taskrun-config in each namespace:
apiVersion: v1
kind: ConfigMap
metadata:
name: taskrun-config
namespace: default
data:
POLICY_CONFIGURATION: "github.com/conforma/config//slsa3"
PUBLIC_KEY: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZP/0htjhVt2y0ohjgtIIgICOtQtA
naYJRuLprwIv6FDhZ5yFjYUEtsmoNcW7rx2KM6FOXGsCX3BNc7qhHELT+g==
-----END PUBLIC KEY-----
IGNORE_REKOR: "true"The make deploy-local target automatically detects your environment and chooses the optimal deployment strategy:
- Fast local deployment: Uses
ko build --local+kind load docker-image - No registry required: Images are loaded directly into the kind cluster
- Optimized for development: ~90 second deployment cycle
- Registry-based deployment: Uses existing images from
KO_DOCKER_REPOregistry - Production-like: Tests with the same images used in production
You can override the automatic detection using parameters:
# Default: Auto-detect environment (recommended)
make deploy-local
# Force registry mode (even on kind clusters)
make deploy-local DEPLOY_MODE=registry
# Force direct image loading (kind clusters only)
make deploy-local DEPLOY_MODE=autoUse DEPLOY_MODE=registry when you want to:
- Test with existing published images: Use pre-built images from registries
- Validate production images: Test the exact same images used in production
- Skip build time: Deploy quickly without building locally
- Test different versions: Easily switch between different image tags
# Use latest tag (automatically appended)
make deploy-local DEPLOY_MODE=registry KO_DOCKER_REPO=quay.io/conforma/knative-service
# Use specific version tag
make deploy-local DEPLOY_MODE=registry KO_DOCKER_REPO=quay.io/conforma/knative-service:v1.2.3
# Use development tag
make deploy-local DEPLOY_MODE=registry KO_DOCKER_REPO=quay.io/conforma/knative-service:main-abc123
# Use local registry
make deploy-local DEPLOY_MODE=registry KO_DOCKER_REPO=localhost:5000/myapp:devNote: Registry mode uses existing images from the specified registry - it does not build or push new images.
- Make code changes in
cmd/launch-taskrun/ - Redeploy:
make deploy-local(automatically optimized for your environment) - Test:
make test-local - View logs:
make logs - Check status:
make status
| Method | Build Time | Deploy Time | Total Time | Use Case |
|---|---|---|---|---|
make deploy-local (kind) |
~30s | ~60s | ~90s | Development with local builds |
make deploy-local DEPLOY_MODE=registry |
0s | ~30-60s | ~30-60s | Testing with existing images |
| Legacy registry build | ~60s | ~2-5min | ~3-6min | Building and pushing to registry |
Test locally using Red Hat App Studio staging configuration:
# Deploy using infra-deployments staging config
make deploy-staging-local
# This fetches the actual staging configuration from infra-deployments
# and deploys it locally in the 'conforma-local' namespace for realistic testing
# View logs from staging deployment
make logs-staging-local
# Clean up staging deployment
make undeploy-staging-localOur deployment targets use different namespaces for isolation:
| Target | Namespace | Purpose | Cleanup Method |
|---|---|---|---|
make deploy-local |
default (configurable via NAMESPACE env var) |
Development workflow | File-based cleanup |
make deploy-staging-local |
conforma-local (fixed) |
Staging-like testing | Namespace deletion |
Examples:
# Deploy to default namespace
make deploy-local
# Deploy to custom namespace
make deploy-local NAMESPACE=my-dev
# Deploy to staging namespace (always conforma-local)
make deploy-staging-local
# View logs from appropriate namespace
make logs # default namespace (or NAMESPACE value)
make logs-staging-local # conforma-local namespacemake setup-knative- Install and configure kind cluster with Knativemake check-knative- Verify Knative installation
make build- Build the service using komake build-local- Build locally without pushing to registrymake test- Run unit testsmake quiet-test- Run tests without verbose outputmake test-coverage- Run tests with coverage reportmake lint- Run lintermake fmt- Format codemake tidy- Tidy go modules
make deploy-local- Smart deployment (auto-detects environment)make deploy-local DEPLOY_MODE=registry- Use existing images from registry (no build)make undeploy-local- Remove local deploymentmake logs- View service logsmake test-local- Test with sample snapshotmake status- Show deployment status
make deploy-staging-local- Deploy using infra-deployments staging config (conforma-local namespace)make undeploy-staging-local- Remove staging-local deployment (deletes conforma-local namespace)make logs-staging-local- View staging-local service logs (conforma-local namespace)
make help- Show all available targets with descriptions
If you see errors like "Unable to fetch image":
- The image wasn't properly loaded into the kind cluster
- The image name doesn't match what's expected
Solution: Use make deploy-local which automatically handles image loading for kind clusters.
If ko build fails:
- Ensure Go modules are tidy:
make tidy - Check that Docker daemon is running
- Verify ko is properly installed:
ko version
If pods don't become ready:
- Check events:
kubectl get events -n default --sort-by='.lastTimestamp' - Check pod logs:
kubectl logs -l serving.knative.dev/service=conforma-knative-service -n default - Verify Knative is installed:
make check-knative
If deploy-local hangs or fails when KO_DOCKER_REPO is set:
- Fixed: Direct mode now ignores
KO_DOCKER_REPOand always builds locally - Root cause:
ko build --localwas affected by registry environment variables - Solution: Local builds now use
KO_DOCKER_REPO=ko.localinternally
Local and staging deployments are isolated:
make deploy-local→defaultnamespace (orNAMESPACEenv var)make deploy-staging-local→conforma-localnamespace- They can coexist without conflicts
- Use appropriate cleanup:
make undeploy-localvsmake undeploy-staging-local
Once deployed, the service will automatically:
- Monitor for Snapshot resource creation events
- Read configuration from the snapshot's namespace
- Create Tekton TaskRuns with the appropriate parameters
- Execute enterprise contract verification using bundle resolution
apiVersion: appstudio.redhat.com/v1alpha1
kind: Snapshot
metadata:
name: test-snapshot
namespace: default
spec:
application: application-sample
displayName: test-snapshot
displayDescription: my first snapshot
components:
- name: test-component
containerImage: "quay.io/redhat-user-workloads/rhtap-contract-tenant/golden-container/golden-container@sha256:185f6c39e5544479863024565bb7e63c6f2f0547c3ab4ddf99ac9b5755075cc9"┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Kubernetes │ │ Knative │ │ Regular │
│ API Server │───▶│ Eventing │───▶│ Kubernetes │
│ │ │ (ApiServerSource │ │ Service │
│ (Snapshots) │ │ + Trigger) │ │ + Deployment │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌─────────────────┐
│ CloudEvents │ │ Tekton │
│ HTTP Delivery │ │ TaskRuns │
│ (/events) │ │ │
└──────────────────┘ └─────────────────┘
# Use existing image from custom registry (latest tag)
make deploy-local DEPLOY_MODE=registry KO_DOCKER_REPO=your-registry/conforma
# Use specific version from custom registry
make deploy-local DEPLOY_MODE=registry KO_DOCKER_REPO=your-registry/conforma:v1.2.3
# Use image from local registry
make deploy-local DEPLOY_MODE=registry KO_DOCKER_REPO=localhost:5000/conforma:devDeploy using Kustomize and ko directly:
# Development (builds and pushes to registry)
kustomize build config/dev/ | ko apply -f -
# Using existing image (no build)
kustomize build config/dev/ | sed "s|ko://github.com/conforma/knative-service/cmd/launch-taskrun|your-registry/conforma:latest|g" | kubectl apply -f -go run cmd/launch-taskrun/main.goRun unit tests for the service:
make test # Run tests with verbose output
make quiet-test # Run tests without verbose output
make test-coverage # Run tests with coverage reportThe project includes comprehensive acceptance tests using Godog/Cucumber for behavior-driven development. The acceptance tests verify end-to-end workflows including:
- Snapshot resource creation and event processing
- Tekton TaskRun creation and execution
- VSA (Verification Summary Attestation) generation and Rekor integration
- Multi-component snapshot handling
- Knative Serving and Eventing integration
Current Status: ✅ PRODUCTION READY - All 3 acceptance test scenarios are fully implemented with production-grade Kubernetes integrations.
# Run all acceptance tests
make acceptance
# The tests will automatically:
# 1. Create a kind cluster with Knative installed
# 2. Deploy the service and dependencies
# 3. Execute all test scenarios
# 4. Clean up resourcesThe acceptance test suite includes:
- Snapshot triggers TaskRun creation - Verifies the basic event-driven workflow
- Multiple components in snapshot - Tests handling of multi-component snapshots
- VSA creation in Rekor - Tests complete VSA workflow including:
- Rekor transparency log deployment
- Enterprise Contract Policy configuration
- TaskRun execution and completion monitoring
- VSA generation and Rekor upload
- VSA content validation (SLSA format)
- Signature verification with Rekor
For detailed information about the acceptance test framework, see the acceptance test README.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Run
make testandmake lint - Run
make acceptanceto verify end-to-end workflows - Submit a pull request
- Use
make deploy-localfor all development (automatically optimized, deploys to default namespace) - Use
make deploy-local DEPLOY_MODE=registryto test with existing published images - Use
make deploy-staging-localfor testing with realistic staging configuration (deploys to conforma-local namespace) - Use
make helpto see all available commands - Setup and deploy:
make setup-knative && make deploy-localfor complete setup - Namespace isolation: Local and staging deployments use separate namespaces and can coexist
- Run acceptance tests:
make acceptancefor comprehensive end-to-end testing - The locally built image includes your latest code changes
- Kind cluster persists between sessions unless deleted
- Use appropriate undeploy target for the namespace you want to clean up
The service is designed to be built and deployed using ko, which handles container image building and deployment directly from Go source code.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.