|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +This file provides guidance to AI coding agents when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +Harbor Scanner Adapter for Sysdig Secure. Implements Harbor's Pluggable Scanner API so Harbor can use Sysdig Secure as its vulnerability scanning engine. The adapter receives scan requests from Harbor, spawns Kubernetes jobs running `sysdig-cli-scanner`, and translates results back into Harbor's vulnerability report format. |
| 8 | + |
| 9 | +## Build and Development |
| 10 | + |
| 11 | +The project uses **Nix flakes** for reproducible builds and `just` as a task runner. Enter the dev shell with `nix develop` to get all required tools. |
| 12 | + |
| 13 | +```bash |
| 14 | +just test # Run tests (Ginkgo with race detection, randomized) |
| 15 | +just lint # Run golangci-lint |
| 16 | +just fmt # Format code (go fmt + gofumpt) |
| 17 | +just check # Run all checks: lint, vulnerability scan, tests |
| 18 | +just check-vulns # Scan Go dependencies with govulncheck |
| 19 | +``` |
| 20 | + |
| 21 | +To run a single test or test file, use Ginkgo directly: |
| 22 | +```bash |
| 23 | +ginkgo --focus "test description" ./pkg/scanner/ |
| 24 | +ginkgo -r ./pkg/http/api/v1/ |
| 25 | +``` |
| 26 | + |
| 27 | +After changing Go dependencies: |
| 28 | +```bash |
| 29 | +just update # Update flake + go deps + rehash |
| 30 | +just rehash-package-nix # Only recalculate vendorHash in package.nix |
| 31 | +``` |
| 32 | + |
| 33 | +## Architecture |
| 34 | + |
| 35 | +**Adapter pattern** is the core abstraction. All scanning backends implement `scanner.Adapter`: |
| 36 | + |
| 37 | +``` |
| 38 | +scanner.Adapter (interface) |
| 39 | +├── InlineAdapter – creates K8s batch Jobs running sysdig-cli-scanner |
| 40 | +├── AsyncAdapter – wraps any Adapter with goroutine-based async polling |
| 41 | +└── BackendAdapter – legacy, no longer supported |
| 42 | +``` |
| 43 | + |
| 44 | +`base_adapter.go` holds shared logic (metadata, vulnerability severity mapping) embedded by concrete adapters. |
| 45 | + |
| 46 | +**HTTP layer** (`pkg/http/api/v1/handler.go`): gorilla/mux router with four endpoints: |
| 47 | +- `GET /health` — health check |
| 48 | +- `GET /api/v1/metadata` — scanner capabilities |
| 49 | +- `POST /api/v1/scan` — trigger scan (returns 202) |
| 50 | +- `GET /api/v1/scan/{scan_request_id}/report` — fetch report (302 + Refresh-After if not ready) |
| 51 | + |
| 52 | +Custom `loggingMiddleware` using `log/slog` wraps the router for structured request logging. |
| 53 | + |
| 54 | +**Sysdig Secure client** (`pkg/secure/client.go`): HTTP client with retry and rate-limit handling. |
| 55 | + |
| 56 | +## Testing |
| 57 | + |
| 58 | +Tests use **Ginkgo v2 + Gomega** (BDD-style) with **gomock** for interface mocking. Mocks live in `mocks/` subdirectories and are generated via `go:generate mockgen`. |
| 59 | + |
| 60 | +Test suites configure `gomega.format.MaxLength = 9999` to avoid truncated assertion output. |
| 61 | + |
| 62 | +## Configuration |
| 63 | + |
| 64 | +The adapter is configured via environment variables (auto-bound by viper) or CLI flags: |
| 65 | + |
| 66 | +| Flag / Env Var | Required | Description | |
| 67 | +|---|---|---| |
| 68 | +| `SECURE_API_TOKEN` | Yes | Sysdig Secure API token | |
| 69 | +| `SECURE_URL` | No | Sysdig endpoint (default: `https://secure.sysdig.com`) | |
| 70 | +| `CLI_SCANNING` | Yes* | Enable CLI scanning mode (only supported mode) | |
| 71 | +| `NAMESPACE_NAME` | When CLI | K8s namespace for scanner jobs | |
| 72 | +| `SECRET_NAME` | When CLI | K8s secret with scanner credentials | |
| 73 | +| `VERIFY_SSL` | No | SSL verification (default: true) | |
| 74 | +| `ASYNC_MODE` | No | Enable async report retrieval | |
| 75 | + |
| 76 | +## CI Workflows |
| 77 | + |
| 78 | +Three GitHub Actions workflows run on PRs to `master`: |
| 79 | + |
| 80 | +**CI (`ci.yaml`)** — three parallel jobs: |
| 81 | +- **Lint**: `just lint` |
| 82 | +- **Pre-commit**: `pre-commit run -a` (fmt, lint, trivy vulnerability scan) |
| 83 | +- **Build and test**: `just test` (requires `SECURE_API_TOKEN` and `SECURE_URL` secrets) |
| 84 | + |
| 85 | +**E2E (`ci-e2e.yaml`)** — full integration test on Minikube: |
| 86 | +1. Starts Minikube, installs Harbor via Helm |
| 87 | +2. Builds the adapter Docker image with `nix build .#harbor-adapter-docker` |
| 88 | +3. Deploys the scanner adapter via the `sysdig/harbor-scanner-sysdig-secure` Helm chart |
| 89 | +4. Pushes an Alpine image to Harbor, triggers a scan, and polls the vulnerability report API until completion (30 attempts, 10s intervals) |
| 90 | + |
| 91 | +**Release (`release.yaml`)** — triggers on `package.nix` changes pushed to `master`: |
| 92 | +- Extracts version from `package.nix`, compares with latest git tag |
| 93 | +- Builds and pushes Docker image to DockerHub (`sysdiglabs/harbor-scanner-sysdig-secure`) |
| 94 | +- Creates a GitHub release with changelog generated by `git-chglog` |
| 95 | + |
| 96 | +## Conventions |
| 97 | + |
| 98 | +- Logging uses Go stdlib `log/slog` (recently migrated from logrus). No external logging libraries. |
| 99 | +- Code formatting enforced by `gofumpt` (stricter than `go fmt`). |
| 100 | +- Pre-commit hooks run on `nix develop` entry: trailing whitespace, YAML checks, fmt, lint, trivy scan. |
| 101 | +- Nix builds use `buildGoModule` with a pinned `vendorHash` in `package.nix`. |
0 commit comments