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
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
# KrakenKey Probe Configuration #
##################################

# Mode: "standalone" or "connected"
# Mode: "standalone", "connected", or "hosted"
# standalone - fully local, no API communication, results logged only
# connected - endpoints managed in KrakenKey dashboard, fetched from API
# hosted - fully managed by KrakenKey infrastructure
KK_PROBE_MODE=standalone

# Probe display name (shown in health endpoint / dashboard)
Expand Down
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.0] - 2026-03-17

### Added

- TLS endpoint scanner with certificate metadata extraction (subject, SANs, issuer, chain, expiry, fingerprint, key type, signature algorithm)
- Connection metadata collection (TLS version, cipher suite, handshake latency, OCSP stapling)
- Three operating modes: `standalone`, `connected`, and `hosted`
- KrakenKey API integration for probe registration and result reporting
- Health check server with `/healthz` and `/readyz` endpoints
- Configurable scan interval (1m to 24h) with immediate first scan on startup
- YAML config file with environment variable overrides (`KK_PROBE_*` prefix)
- Persistent probe ID across restarts via state file
- Graceful shutdown on SIGINT/SIGTERM
- Multi-platform Docker images (linux/amd64, linux/arm64) via GoReleaser
- CI pipeline with lint, test, and build matrix
- Kubernetes deployment example with ConfigMap, Secrets, and health probes

[0.1.0]: https://github.com/krakenkey/probe/releases/tag/v0.1.0
71 changes: 71 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Contributing to KrakenKey Probe

Thank you for your interest in contributing! This guide will help you get started.

## Getting Started

### Prerequisites

- [Go 1.23+](https://go.dev/dl/)
- [golangci-lint](https://golangci-lint.run/welcome/install-locally/) (for linting)
- Docker (optional, for container builds)

### Clone and Build

```bash
git clone https://github.com/krakenkey/probe.git
cd probe
go build -o krakenkey-probe ./cmd/probe
```

### Run Tests

```bash
go test ./... -race
```

### Run Linter

```bash
golangci-lint run
```

## Project Structure

```
cmd/probe/ Entry point (CLI flags, startup, shutdown)
internal/
config/ Configuration loading, env overrides, validation
health/ HTTP health check server (/healthz, /readyz)
reporter/ KrakenKey API client (registration, reporting)
scanner/ TLS endpoint scanner (certificate extraction)
scheduler/ Scan scheduling and orchestration
state/ Probe ID generation and persistence
```

## Development Workflow

1. **Fork** the repository and create a feature branch from `main`.
2. **Make your changes** with clear, focused commits.
3. **Run tests and lint** before pushing:
```bash
go test ./... -race && golangci-lint run
```
4. **Open a pull request** against `main` with a clear description of what and why.

## Code Guidelines

- Keep dependencies minimal. The project intentionally uses only `gopkg.in/yaml.v3` beyond the standard library.
- Use `log/slog` for structured logging. Follow the existing patterns for log levels and context.
- Write tests for new functionality. Use `go test -race` to catch concurrency issues.
- Follow standard Go conventions (`gofmt`, `go vet`).

## Reporting Issues

- Use [GitHub Issues](https://github.com/krakenkey/probe/issues) to report bugs or request features.
- Include your Go version, OS/architecture, and probe version (`krakenkey-probe --version`).
- For bugs, include relevant log output (with `KK_PROBE_LOG_LEVEL=debug` if possible).

## License

By contributing, you agree that your contributions will be licensed under the [AGPL-3.0](LICENSE) license.
90 changes: 75 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,78 @@ The probe connects to configured endpoints via TLS, extracts certificate and con

## Quick Start

### Standalone (no API key needed)

```bash
docker run -d \
-e KK_PROBE_API_KEY="kk_your_api_key" \
-e KK_PROBE_ENDPOINTS="example.com:443,api.example.com:443" \
-e KK_PROBE_NAME="my-probe" \
-v probe_state:/var/lib/krakenkey-probe \
ghcr.io/krakenkey/probe:latest
```

### Connected (reports to KrakenKey)

```bash
docker run -d \
-e KK_PROBE_MODE="connected" \
-e KK_PROBE_API_KEY="kk_your_api_key" \
-e KK_PROBE_NAME="my-probe" \
-v probe_state:/var/lib/krakenkey-probe \
ghcr.io/krakenkey/probe:latest
```

## Operating Modes

The probe supports three operating modes:

| Mode | API Key | Endpoints | Description |
|---|---|---|---|
| `standalone` | Not required | Defined locally in config/env | Fully local. Scans endpoints and logs results to console. No API communication. |
| `connected` | Required (`kk_` prefix) | Managed via KrakenKey dashboard | Endpoints fetched from API. Results reported to KrakenKey for dashboard monitoring. |
| `hosted` | Required (service key) | Managed by KrakenKey | Fully managed by KrakenKey infrastructure. Probe ID, name, and region are pre-configured. |

Set the mode with `KK_PROBE_MODE` or `probe.mode` in the YAML config. Default: `standalone`.

## CLI Flags

```
krakenkey-probe [flags]

Flags:
--config <path> Path to probe.yaml config file
--version Print version and exit
--healthcheck Check health endpoint (http://localhost:8080/healthz) and exit with 0 (healthy) or 1 (unhealthy)
```

## Configuration

The probe is configured via a YAML file and/or environment variables. Environment variables take precedence over YAML values.
The probe is configured via a YAML file and/or environment variables. Configuration is loaded in order of precedence (highest wins):

1. **Environment variables** (`KK_PROBE_*` prefix)
2. **YAML config file** (if `--config` is provided)
3. **Built-in defaults**

### YAML Config

```yaml
api:
url: "https://api.krakenkey.io" # KK_PROBE_API_URL
key: "kk_..." # KK_PROBE_API_KEY (required)
key: "" # KK_PROBE_API_KEY (required for connected/hosted modes)

probe:
id: "" # KK_PROBE_ID (auto-generated if empty)
name: "my-probe" # KK_PROBE_NAME
mode: "self-hosted" # KK_PROBE_MODE (self-hosted | hosted)
region: "" # KK_PROBE_REGION
mode: "standalone" # KK_PROBE_MODE (standalone | connected | hosted)
region: "" # KK_PROBE_REGION (required for hosted mode)
interval: "60m" # KK_PROBE_INTERVAL (min: 1m, max: 24h)
timeout: "10s" # KK_PROBE_TIMEOUT
state_file: "/var/lib/krakenkey-probe/state.json" # KK_PROBE_STATE_FILE

endpoints: # KK_PROBE_ENDPOINTS (comma-separated host:port)
- host: "example.com"
port: 443
sni: "" # optional SNI override
sni: "" # optional: override the SNI hostname sent during TLS handshake
- host: "internal.corp.net"
port: 8443

Expand All @@ -55,20 +94,24 @@ logging:
format: "json" # KK_PROBE_LOG_FORMAT (json|text)
```

### SNI Override

Use the `sni` field when the hostname you connect to differs from the hostname expected by the TLS certificate. This is common with load balancers, CDNs, or internal services behind a reverse proxy. If omitted, the `host` value is used as the SNI hostname.

### Environment Variable Reference

| Variable | Default | Description |
|---|---|---|
| `KK_PROBE_API_URL` | `https://api.krakenkey.io` | KrakenKey API base URL |
| `KK_PROBE_API_KEY` | (required) | API key, must start with `kk_` |
| `KK_PROBE_API_KEY` | | API key (`kk_` prefix). Required for `connected` and `hosted` modes. |
| `KK_PROBE_ID` | (auto-generated) | Probe ID, persisted to state file |
| `KK_PROBE_NAME` | | Human-friendly probe name |
| `KK_PROBE_MODE` | `self-hosted` | `self-hosted` or `hosted` |
| `KK_PROBE_REGION` | | Geographic region label |
| `KK_PROBE_INTERVAL` | `60m` | Scan interval (Go duration) |
| `KK_PROBE_MODE` | `standalone` | `standalone`, `connected`, or `hosted` |
| `KK_PROBE_REGION` | | Geographic region label (required for `hosted` mode) |
| `KK_PROBE_INTERVAL` | `60m` | Scan interval (Go duration, e.g. `30m`, `1h`) |
| `KK_PROBE_TIMEOUT` | `10s` | Per-endpoint TLS dial timeout |
| `KK_PROBE_STATE_FILE` | `/var/lib/krakenkey-probe/state.json` | State file path |
| `KK_PROBE_ENDPOINTS` | | Comma-separated `host:port` pairs |
| `KK_PROBE_ENDPOINTS` | | Comma-separated `host:port` pairs. Port defaults to `443` if omitted. |
| `KK_PROBE_HEALTH_ENABLED` | `true` | Enable health endpoint |
| `KK_PROBE_HEALTH_PORT` | `8080` | Health endpoint port |
| `KK_PROBE_LOG_LEVEL` | `info` | Log level |
Expand All @@ -83,6 +126,7 @@ services:
container_name: krakenkey-probe
restart: unless-stopped
environment:
KK_PROBE_MODE: "connected"
KK_PROBE_API_KEY: "kk_your_api_key_here"
KK_PROBE_NAME: "my-probe"
KK_PROBE_ENDPOINTS: "example.com:443,api.example.com:443"
Expand Down Expand Up @@ -215,11 +259,11 @@ CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o krakenkey-pr
GET /readyz
```

1. On startup, the probe loads its config, generates or reads its probe ID, and registers with the KrakenKey API.
2. It immediately runs the first scan cycle: connects to each endpoint via TLS, extracts certificate metadata, and sends results to the API.
1. On startup, the probe loads its config and generates or reads its probe ID. In `connected`/`hosted` modes, it registers with the KrakenKey API.
2. It immediately runs the first scan cycle: connects to each endpoint via TLS and extracts certificate metadata. In `connected`/`hosted` modes, results are sent to the API. In `standalone` mode, results are logged to the console.
3. After the first scan, the `/readyz` endpoint returns `200 OK`.
4. Subsequent scans run on the configured interval.
5. On `SIGINT` or `SIGTERM`, the probe finishes the current scan cycle and shuts down.
5. On `SIGINT` or `SIGTERM`, the probe finishes the current scan cycle and shuts down gracefully.

### What Gets Collected

Expand Down Expand Up @@ -258,18 +302,34 @@ For each endpoint, the probe extracts:

### `/healthz` Response

Always returns `200 OK`:

```json
{
"status": "ok",
"version": "0.1.0",
"probeId": "a1b2c3d4-...",
"mode": "self-hosted",
"mode": "standalone",
"region": "us-east-1",
"lastScan": "2026-03-17T12:00:00Z",
"nextScan": "2026-03-17T13:00:00Z"
}
```

### `/readyz` Response

Returns `503 Service Unavailable` before the first scan completes:

```json
{ "status": "not ready" }
```

Returns `200 OK` after the first scan completes:

```json
{ "status": "ready" }
```

## Troubleshooting

**"api.key is required"**
Expand Down
46 changes: 46 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Security Policy

## Reporting a Vulnerability

If you discover a security vulnerability in KrakenKey Probe, please report it responsibly.

**Do not open a public GitHub issue for security vulnerabilities.**

Instead, please email **security@krakenkey.io** with:

- A description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)

We will acknowledge your report within **48 hours** and aim to provide a fix or mitigation within **7 days** for critical issues.

## Supported Versions

| Version | Supported |
|---------|-----------|
| 0.1.x | Yes |

## Security Considerations

### What the Probe Collects

The probe connects to TLS endpoints and extracts **publicly available** certificate metadata (subject, issuer, SANs, expiry, etc.) and connection metadata (TLS version, cipher suite, handshake latency). It does not intercept, decrypt, or inspect application-layer traffic.

### API Key Handling

- API keys are passed via environment variables or config files and are sent as Bearer tokens over HTTPS.
- Keys are never logged, even at debug level.
- Use Kubernetes Secrets or equivalent mechanisms to manage API keys in production.

### Container Security

- The official Docker image runs as a non-root user (UID 65532).
- The image is based on `distroless/static-debian12` to minimize attack surface.
- No shell or package manager is included in the production image.

### Network

- Outbound connections are made to configured TLS endpoints and the KrakenKey API (`https://api.krakenkey.io` by default).
- The health server listens on a configurable port (default `8080`) and serves read-only status information.
- No inbound connections are required beyond the health endpoint.
Loading