Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Container Security Operator

Kubernetes operator that brings Quay/Clair security metadata to clusters. Watches pods, queries registries for vulnerabilities, exposes findings via `ImageManifestVuln` CRDs.

## Quick Reference

| Task | Command |
|------|---------|
| Build | `make build` |
| Run locally | `make run` |
| Install CRDs | `make installcrds` |
| Run tests | `go test -v ./...` |
| Regenerate code | `make codegen` |

## Project Structure

```
cmd/security-labeller/ # Entrypoint
labeller/ # Core controller (informers, reconciliation)
secscan/ # Registry client for vulnerability data
image/ # Container image ID parsing
apis/secscan/v1alpha1/ # CRD types
generated/ # Auto-generated clients (do not edit)
bundle/ # OLM deployment manifests
```

## Key Flow

1. Labeller watches Pod events via informers
2. Parses container image IDs from running pods
3. Queries registry's `.well-known/app-capabilities` endpoint
4. Fetches vulnerability data from Clair via manifest-security API
5. Creates/updates `ImageManifestVuln` resources
6. Garbage collects orphaned manifests on pod deletion

## Detailed Documentation

For specific topics, see:

- @agent_docs/architecture.md - Component details, CRD structure, configuration
- @agent_docs/development.md - Building, testing, code generation
- @agent_docs/deployment.md - OLM deployment, container builds
3 changes: 3 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# CLAUDE

@AGENTS.md
3 changes: 3 additions & 0 deletions GEMINI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# GEMINI

Please follow instructions from @./AGENTS.md
62 changes: 62 additions & 0 deletions agent_docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Architecture

## Components

### cmd/security-labeller/main.go
Entrypoint that:
- Parses CLI flags and config file
- Handles TLS certificate configuration
- Creates and runs the Labeller controller

### labeller/
Core controller implementation:
- `labeller.go`: Main controller with informers for Pods and ImageManifestVulns, work queue, reconciliation logic
- `manifest.go`: ImageManifestVuln creation/update, garbage collection, affected pod tracking
- `config.go`: Configuration struct and YAML loading
- `multinamespacelistwatcher.go`: Watches resources across multiple namespaces

### secscan/
Registry client for vulnerability scanning:
- `client.go`: Main client interface implementation
- `wellknown.go`: Fetches `.well-known/app-capabilities` from registries
- `types.go`: Response types from Clair (Layer, Feature, Vulnerability)
- `quay/`: Quay-specific implementations
- `rest/`: HTTP REST client utilities

### image/
Container image parsing:
- `image.go`: Parses image IDs from various formats (Docker Hub, private registries, with/without digests)
- Handles pull secret parsing from Kubernetes secrets

### apis/secscan/v1alpha1/
CRD type definitions:
- `types.go`: ImageManifestVuln, Feature, Vulnerability structs
- `register.go`: Scheme registration

## ImageManifestVuln CRD

### Spec (immutable scanner data)
- `image`: Image name
- `manifest`: Manifest digest
- `features`: List of features with vulnerabilities

### Status (dynamic cluster state)
- `affectedPods`: Map of pod paths to container IDs
- Severity counts: `unknownCount`, `lowCount`, `mediumCount`, `highCount`, `criticalCount`, `defcon1Count`
- `fixableCount`: Vulnerabilities with available fixes
- `lastUpdate`: Timestamp of last resync

## Configuration

Via CLI flags or `example/example-config.yaml`:

| Option | Default | Description |
|--------|---------|-------------|
| `namespaces` | (all) | Namespaces to watch |
| `interval` | 30m | Controller resync interval |
| `resyncThreshold` | 1h | Min time before refreshing vuln data |
| `labelPrefix` | secscan | Label prefix for resources |
| `wellknownEndpoint` | .well-known/app-capabilities | Registry endpoint |
| `promAddr` | :8081 | Prometheus metrics address |
| `insecure` | false | Skip TLS verification |
| `extraCerts` | | Directory with extra CA certificates |
92 changes: 92 additions & 0 deletions agent_docs/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Deployment

## Container Image Build

```bash
# Build operator image
docker build -t quay.io/<namespace>/container-security-operator .

# Push to registry
docker push quay.io/<namespace>/container-security-operator
```

The Dockerfile uses multi-stage build:
1. Go builder stage compiles the binary
2. Alpine runtime stage with ca-certificates

## Quick Deploy (Development)

```bash
# Build and push operator image
./hack/build.sh

# Deploy to cluster
./hack/deploy.sh

# Tear down
./hack/teardown.sh
```

## OLM Deployment (Production)

The operator is deployed via Operator Lifecycle Manager.

### Bundle Contents

```
bundle/
├── imagemanifestvuln.crd.yaml # CRD definition
├── manifests/
│ └── container-security-operator.v*.clusterserviceversion.yaml
├── metadata/
├── cso.catalogsource.yaml # CatalogSource
├── cso.operatorgroup.yaml # OperatorGroup
├── cso.subscription.yaml # Subscription
└── Dockerfile # Catalog image build
```

### Deploy Steps

1. Update image reference in ClusterServiceVersion:
```yaml
# bundle/manifests/container-security-operator.v1.0.0.clusterserviceversion.yaml
image: quay.io/<namespace>/container-security-operator
```

2. Build and push catalog image:
```bash
cd bundle/
docker build -t quay.io/<namespace>/cso-catalog .
docker push quay.io/<namespace>/cso-catalog
```

3. Update CatalogSource image:
```yaml
# bundle/cso.catalogsource.yaml
image: quay.io/<namespace>/cso-catalog
```

4. Create CatalogSource:
```bash
# Upstream Kubernetes
kubectl create -n olm -f bundle/cso.catalogsource.yaml

# OpenShift
kubectl create -n openshift-marketplace -f bundle/cso.catalogsource.yaml
```

5. Verify package is available:
```bash
kubectl get packagemanifest container-security-operator
```

6. Create OperatorGroup and Subscription:
```bash
kubectl create -n <namespace> -f bundle/cso.operatorgroup.yaml
kubectl create -n <namespace> -f bundle/cso.subscription.yaml
```

## Public Availability

- **Kubernetes**: [operatorhub.io/operator/container-security-operator](https://operatorhub.io/operator/container-security-operator)
- **OpenShift**: Available via OperatorHub in the console
86 changes: 86 additions & 0 deletions agent_docs/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Development

## Prerequisites

- Go 1.23+
- kubectl with cluster access
- Docker or Podman (for container builds)

## Building

```bash
# Build the operator binary
make build
# Output: bin/security-labeller

# Update vendored dependencies
make vendor
```

## Running Locally

```bash
# Install the CRD first
make installcrds

# Run with local kubeconfig
make run
# Uses: ~/.kube/config and example/example-config.yaml

# Or run directly with flags
./bin/security-labeller \
-kubeconfig ~/.kube/config \
-namespaces default,test \
-resyncInterval 15m \
-promAddr :8081
```

## Testing

```bash
# Run all tests
go test -v ./...

# Run specific package tests
go test -v ./labeller/...
go test -v ./image/...
go test -v ./secscan/...
go test -v ./k8sutils/...

# Run with coverage
go test -v -cover ./...
```

## Code Generation

The `generated/` directory contains auto-generated Kubernetes clients. To regenerate after modifying `apis/secscan/v1alpha1/types.go`:

```bash
# Clone code-generator (one-time setup)
make get-code-generator

# Regenerate clientsets, informers, listers
make codegen
```

This updates:
- `generated/clientset/` - Typed client for ImageManifestVuln
- `generated/informers/` - Shared informer factories
- `generated/listers/` - Indexer-backed listers
- `apis/secscan/v1alpha1/zz_generated.deepcopy.go` - DeepCopy methods

## Development Environment Setup

```bash
# Install CRD and apply example manifests
make devenv
# Runs: kubectl create -f bundle/imagemanifestvuln.crd.yaml
# kubectl apply -f bundle/examples/
```

## CI Checks

The GitHub Actions CI runs:
1. `go mod tidy` - Verify go.mod is clean
2. `make build` - Build compiles successfully
3. `go test -v ./...` - All tests pass