初始化 Panda RPKI v0.1.0 开源候选版本
Some checks failed
ci / rust (push) Has been cancelled
ci / docker (push) Has been cancelled

This commit is contained in:
Panda RPKI OSS Local
2026-09-09 18:01:15 +08:00
commit 277cbca878
203 changed files with 92495 additions and 0 deletions

View File

@@ -0,0 +1,139 @@
# Command-line reference
This reference covers v0.1.0. `panda-rpki --help` displays version and usage;
there is no separate `--version` option.
## Syntax
```text
panda-rpki validate --tal FILE --ta FILE --out DIRECTORY [OPTIONS]
panda-rpki daemon --state-root DIRECTORY [DAEMON OPTIONS] -- [VALIDATION OPTIONS]
```
Use `--name value`, not `--name=value`. Only help has a short alias (`-h`).
Values are case-sensitive; options cannot repeat unless listed as repeatable.
Paths are relative to the process working directory. No configuration-file
option is provided. No arguments or a help request exits successfully.
## Inputs and outputs
| Option | Default / requirement | Repeatable | Meaning |
| --- | --- | --- | --- |
| `--tal <file>` | Required | Yes | Local TAL file. |
| `--ta <file>` | Required | Yes | Matching DER trust-anchor certificate. |
| `--tal-id <id>` | TAL filename stem | Yes | Anchor identifier; if supplied, provide one for every TAL. |
| `--ta-constraints <tal-id>=<file>` | Adjacent `.constraints` if present | Yes | Override constraints for a known TAL ID; each ID may occur once. |
| `--out <directory>` | Required | No | Output directory, created if absent. Existing output files may be overwritten. |
| `--ccr-out <file>` | Disabled | No | CCR DER path, relative to the working directory, not `--out`. |
TAL and TA lists are paired by occurrence order and must have equal lengths.
Use distinct TAL IDs. For `input/anchor.tal`, automatic discovery checks
`input/anchor.constraints`. If absent with no explicit path, no additional
constraints are loaded for that anchor.
## State and network
| Option | Default | Meaning |
| --- | --- | --- |
| `--rrdp-state-dir <directory>` | `<out>/.state` | Dedicated persistent root; database is stored in `repository-db/`. |
| `--rrdp-sync-mode <auto\|snapshot\|delta>` | `auto` | Starting state requirements described below. |
| `--http-timeout-secs <n>` | `300` | HTTP timeout seconds; nonnegative with runtime minimum 1. Connection, retry and large-object transport policies also apply. Not a whole-run deadline. |
| `--http-root-cert <pem>` | None | Repeatable extra HTTPS roots; system roots and hostname verification remain enabled. |
| `--max-ca-depth <n>` | `64` | Nonnegative CA traversal depth limit. |
| Mode | Starting state | Behavior |
| --- | --- | --- |
| `auto` | Empty or populated database | Select snapshot, delta or noop per repository. |
| `snapshot` | Missing or empty database | Start fresh; reject a populated database. |
| `delta` | Existing populated database | Resume state, allowing protocol snapshot fallback and new-repository snapshots. |
Unrecognized state layouts and unsupported database schemas are rejected.
Use a new dedicated directory for an incompatible format. State includes
repository objects, RRDP sessions and manifest anti-rollback metadata. Do not
share a writable database between processes. Changing `--out` changes default
state location unless `--rrdp-state-dir` is explicit.
RRDP references and redirects enforce HTTPS and same-origin rules. Extra
trust roots do not relax origin checks. No separate rsync timeout is exposed.
## Workers and queues
| Option | Default | Meaning |
| --- | ---: | --- |
| `--parallel-max-repo-sync-workers-global <n>` | 8 | Global repository transport workers. |
| `--parallel-phase2-object-workers <n>` | 8 | Object workers, independent of transport. |
| `--parallel-phase2-worker-queue-capacity <n>` | 256 | Object-worker queue capacity. |
| `--parallel-repo-worker-queue-capacity <n>` | 256 | Pending repository results; effective limit is `max(n, 1024)`. |
All values must be positive. Budgets are shared across TALs. Higher concurrency
can increase memory consumption and does not guarantee proportional speedup.
## Logging
| Option | Default | Values |
| --- | --- | --- |
| `--log-level <level>` | `info` | `off`, `error`, `warn`, `info`, `debug`, `trace` |
| `--log-format <format>` | `text` | `text`, `json` |
Precedence: explicit option, then `PANDA_RPKI_LOG_LEVEL` or
`PANDA_RPKI_LOG_FORMAT`, then default. Each level includes more severe messages.
`off` suppresses logs but does not change exit codes. JSON logs contain
`timestamp`, `level`, `event`, and `fields`, one object per line. Logs use stderr;
help uses stdout; validation results are written to files.
Other `PANDA_RPKI_*` variables in [Compose](docker.md) are template substitutions,
not configuration variables read directly by the binary.
## Daemon
Daemon runs in the foreground, launching this executable's `validate` command
in a separate process per cycle. Pass validator options after `--`, without
the word `validate`. The controller owns `--out`, `--ccr-out`,
`--rrdp-state-dir` and `--rrdp-sync-mode`; do not pass them after `--`.
| Option | Default | Meaning |
| --- | --- | --- |
| `--state-root <directory>` | Required | Dedicated root for state, lifecycle metadata and run outputs. |
| `--interval-secs <n>` | 60 | Wait after run recording and retention; zero starts the next run immediately. |
| `--max-runs <n>` | Unlimited | Positive attempt count for this invocation, including failed attempts. |
| `--retain-runs <n>` | 10 | Positive number of completed run directories retained, including recorded failures. Older completed directories are deleted. |
| `--run-timeout-secs <n>` | 0 | Whole-run deadline; zero disables. Sends SIGTERM to the child group, then SIGKILL after two seconds if needed. |
| `--shutdown-grace-secs <n>` | 30 | On SIGINT/SIGTERM, stop starting runs and wait at most n seconds before terminating the active process group. |
Options cannot repeat. Seconds are nonnegative. Empty state starts with
snapshot, successful continuation requests delta, and recovery after a failed
run with existing state requests auto. Actual operations can include noop and
snapshot fallback. Normal child failures/timeouts are recorded and retried;
corrupt lifecycle metadata or inability to record state stops the controller.
Restart continues numbering and reuses state. Retention leaves incomplete,
unrelated and symlink run directories untouched. It does not trim history JSONL.
Do not remove a live lock file. After SIGKILL, ensure the old validator child
has stopped before restarting. Stop the entire container for Docker deployments.
## Outputs and exit status
| File | Content |
| --- | --- |
| `summary.json` | TAL, worker, validation and actual RRDP operation counts. |
| `vrps.csv` | ROA payloads: `asn,prefix,max_length`. |
| `vaps.csv` | ASPA payloads. |
| `stage-timing.json`, `analysis/timing.json` | Timing and analysis counters. |
| `.vrps-source.csv` | Intermediate CSV used to produce `vrps.csv`. |
| Requested CCR path | Optional CCR DER; automatic per run in daemon mode. |
Daemon adds `daemon.lock`, `daemon-status.json`, `lifecycle.json`,
`run-summary.jsonl`, `state/repository-db/`, and `runs/run_000001/` etc.
Each run includes validator outputs, `run-meta.json`, `run-summary.json`,
`stdout.log`, `stderr.log` and optional `process-time.txt`. `/usr/bin/time`
provides user/system CPU and peak RSS when installed; Docker includes it.
Controller states: `starting`, `running`, `sleeping`, `exited`, `failed`.
Help and successful validation return 0; argument and propagated runtime
errors return 2. Completion can include rejected objects or recoverable
repository failures: inspect warnings and outputs too. Failed runs can leave
partial output; use a separate output directory per cycle.
A bounded daemon returns 2 if any attempt failed, otherwise 0. Stopping during
an interval exits normally. A forcibly terminated current run is recorded as
failed and causes exit 2.

View File

@@ -0,0 +1,21 @@
# v0.1.0 conformance matrix
| Behaviour | Standard reference | Implementation | Evidence |
| --- | --- | --- | --- |
| TAL syntax and TA public-key binding | RFC 8630 §2 | `src/validation/from_tal.rs`, `src/model/ta.rs` | parser and synthetic integration tests |
| TA and issued CA profile/signature/resource checks | RFC 6487 §4 | `src/validation/`, `src/model/` | profile unit tests and synthetic integration tests |
| Manifest, manifest file hashes, CRL freshness, and ROA checks | RFC 6486, RFC 6487, RFC 6482 | `src/validation/`, `src/model/` | RRDP unit tests and self-contained `tests/synthetic_docker_e2e.sh` |
| RRDP notification, snapshot, delta/replace/withdraw and fallback | RFC 8182 §§3.4–3.5 | `src/repository/sync/rrdp.rs`, `src/repository/sync/repo.rs` | snapshot/delta state-restart unit tests and synthetic Docker tests |
| RRDP direct-reference and redirect origin checks | RFC 9674 §3.2 | `src/repository/fetch/http.rs`, `src/repository/sync/rrdp.rs` | cross-origin unit tests |
| Repeated TAL/TA pairing and stable aggregate output | RFC 8630 §2; RFC 6813 data model | `src/cli/mod.rs`, `src/cli/validate.rs`, `src/runtime/` | CLI parser checks; locked multi-TAL E2E |
| Bounded repository and object workers (default 8 each, shared across TALs) | operational support for the standard validation pipeline | `src/scheduler/`, `src/runtime/` | worker-pool unit tests |
| Resumable RRDP protocol state | RFC 8182 §3.4 | `src/repository/storage/`, `src/repository/sync/rrdp.rs` | atomic state index and restart delta test |
| CCR manifest, ROA, ASPA, trust-anchor and router-key states | `draft-ietf-sidrops-rpki-ccr-11` §§2–4 | `src/ccr/` | encode/decode tests and integration artifacts |
| TA Constraints rule normalization and EE resource checks | `draft-ietf-sidrops-constraining-rpki-trust-anchors-01` §§3–4 | `src/ta_constraints.rs`, `src/validation/` | parser/normalization tests; constrained validation E2E |
| VRP CSV output | RFC 6810 data semantics | `src/cli/validate.rs`, `src/runtime/` | self-contained Docker E2E CSV/summary assertions |
The worker pool and interval index are implementation mechanisms, not new wire
protocols; their tests must also prove deterministic output and unchanged
validation decisions. Only the table entries above are in v0.1.0 scope.
Adding a new source file or protocol feature requires a new row with a document
revision, section, test, and reviewer decision.

33
docs/development.md Normal file
View File

@@ -0,0 +1,33 @@
# Development and testing
Use Rust 1.92 or newer on Linux and the [native dependencies](getting-started.md).
Tests additionally need Python 3, Python `cryptography`, and OpenSSL's CLI.
```bash
cargo fmt --all --check
cargo check --locked --no-default-features
cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
cargo build --locked --release
bash tests/synthetic_docker_e2e.sh
```
Synthetic tests generate fresh keys, TALs, certificates and an HTTPS RRDP
repository. They cover snapshot, actual delta, persistence, daemon restart and
outputs without public RIR requests. Docker tests require Linux host networking.
Generated keys and outputs are temporary and unsuitable as production inputs.
## Code organization
- `src/cli/` parses arguments; `src/runtime/` coordinates validation.
- `src/repository/` handles transport, RRDP and persistence.
- `src/scheduler/` coordinates bounded workers.
- `src/model/` and `src/validation/` parse and validate RPKI objects.
- `src/ccr/` exports canonical state; `src/ta_constraints/` evaluates constraints.
- `src/daemon/` schedules runs; logging/output modules provide diagnostics.
- `tests/` contains integration tests and generated fixtures.
- `docker/` contains container and Compose deployment files.
Internal Rust modules are not a stable library API. The supported interface is
the CLI and documented output files. Add behavior tests and update documentation
when changing these interfaces.

84
docs/docker.md Normal file
View File

@@ -0,0 +1,84 @@
# Docker and Compose
Run commands from the project root. A Linux Docker engine is required for the
documented deployment and integration tests.
```bash
docker build -f docker/Dockerfile -t panda-rpki:v0.1.0 .
```
The image defaults to an unprivileged user and includes CA certificates,
`rsync` and `/usr/bin/time`. Compose uses a read-only root filesystem and a
temporary `/tmp`. Host input mounts are read-only; state and outputs are writable.
## Single anchor
```bash
mkdir -p state output
export INPUT_DIR="$PWD/input" STATE_DIR="$PWD/state" OUTPUT_DIR="$PWD/output"
export TAL_FILE=anchor.tal TA_FILE=anchor.cer
export PUID="$(id -u)" PGID="$(id -g)"
docker compose -f docker/compose.yaml run --build --rm validator
```
Supply absolute host paths as above. Relative Compose paths are resolved from
the Compose file's directory, which is `docker/`. Build context is explicitly
the project root. `PANDA_RPKI_RRDP_SYNC_MODE` defaults to `auto`.
## All five regional anchors
Follow [Prepare all five RIR trust anchors](trust-anchors.md) to download and
check each TAL and matching certificate under `input/`, then run:
```bash
mkdir -p state output
export INPUT_DIR="$PWD/input" STATE_DIR="$PWD/state" OUTPUT_DIR="$PWD/output"
export PUID="$(id -u)" PGID="$(id -g)"
export AFRINIC_TAL_FILE=afrinic.tal AFRINIC_TA_FILE=afrinic.cer
export APNIC_TAL_FILE=apnic.tal APNIC_TA_FILE=apnic.cer
export ARIN_TAL_FILE=arin.tal ARIN_TA_FILE=arin.cer
export LACNIC_TAL_FILE=lacnic.tal LACNIC_TA_FILE=lacnic.cer
export RIPE_TAL_FILE=ripe.tal RIPE_TA_FILE=ripe.cer
docker compose -f docker/compose.all5.yaml run --build --rm validator
```
| Template variable | Default | Applies to |
| --- | --- | --- |
| `PANDA_RPKI_WORKERS` | 8 | all5 and daemon object workers |
| `PANDA_RPKI_REPO_WORKERS` | 8 | all5 and daemon transport workers |
| `PANDA_RPKI_WORKER_QUEUE_CAPACITY` | 256 | all5 object queue |
| `PANDA_RPKI_HTTP_TIMEOUT_SECS` | 600 | all5 HTTP timeout (native CLI default is 300) |
| `PANDA_RPKI_RRDP_SYNC_MODE` | auto | single-anchor and all5 |
The all5 CCR is `OUTPUT_DIR/all5.ccr`; the single-anchor CCR is
`OUTPUT_DIR/result.ccr`. Reuse `STATE_DIR` and select new `OUTPUT_DIR` values
to retain multiple cycles. These templates take no bundled RIR input files.
## Daemon service
```bash
mkdir -p data/daemon
export INPUT_DIR="$PWD/input" DAEMON_DIR="$PWD/data/daemon"
export TAL_FILE=anchor.tal TA_FILE=anchor.cer
export PUID="$(id -u)" PGID="$(id -g)"
export PANDA_RPKI_INTERVAL_SECS=600 PANDA_RPKI_RETAIN_RUNS=10
docker compose -f docker/compose.daemon.yaml up -d --build
docker compose -f docker/compose.daemon.yaml logs -f validator
# Stop gracefully; persistent host data remains available.
docker compose -f docker/compose.daemon.yaml stop
```
Defaults: interval 60 seconds, retain 10, `PANDA_RPKI_RUN_TIMEOUT_SECS=0`
(disabled), log level `info`, log format `json`. The daemon template passes
`PANDA_RPKI_LOG_LEVEL` and `PANDA_RPKI_LOG_FORMAT` into the container.
It restarts unless stopped and allows 40 seconds for shutdown, exceeding the
controller's default 30-second grace plus termination wait.
For multiple anchors, append TAL/TA pairs after `--` in the daemon service's
command. For other validator options, edit that same list. A finite run can
be invoked with `docker compose run --rm validator daemon ...` using the
[daemon CLI](command-line-reference.md#daemon); use `--max-runs` before `--`.
Compose variables are expanded into arguments; only the two documented log
environment variables are read directly by the binary. For single-anchor/all5
logs, pass them with `docker compose run -e PANDA_RPKI_LOG_LEVEL=debug ...`.

66
docs/getting-started.md Normal file
View File

@@ -0,0 +1,66 @@
# Getting started
Panda RPKI v0.1.0 is a Linux command-line application. You can use Docker without
installing Rust, or build a native binary. It requires outbound HTTPS to RPKI
repositories, a writable state directory, and enough disk space for repository
objects and outputs. Resource use depends on the selected trust anchors.
## Prepare trust anchors
A trust anchor defines what you trust. Obtain its TAL from the responsible RIR
and obtain the current DER certificate from a certificate URI in that TAL.
Panda RPKI checks that the certificate matches the TAL public key. It takes
both files as explicit inputs; it does not refresh the supplied TA file for you.
For example, the [RIPE NCC trust-anchor page](https://www.ripe.net/manage-ips-and-asns/resource-management/rpki/ripe-ncc-rpki-trust-anchor-structure/)
publishes the RIPE NCC TAL. From the project root:
```bash
mkdir -p input
curl --fail --location --proto '=https' --proto-redir '=https' \
--connect-timeout 15 --max-time 120 \
https://tal.rpki.ripe.net/ripe-ncc.tal -o input/anchor.tal
curl --fail --location --proto '=https' --proto-redir '=https' \
--connect-timeout 15 --max-time 120 \
https://rpki.ripe.net/ta/ripe-ncc-ta.cer -o input/anchor.cer
```
Check the TAL's current certificate URI before downloading. The
[RIR trust-anchor directory](https://www.ripe.net/manage-ips-and-asns/resource-management/rpki/rir-trust-anchor-statistics/)
links the other regional anchors. Use their official TALs and corresponding
certificate locations when preparing a multiple-anchor deployment. Store inputs
outside version control, keep TA certificates current, and retain local policy
files alongside the appropriate TALs. For all five RIRs, use the complete
[five-RIR input guide](trust-anchors.md), including official sources, download
commands, input checks, and the filenames used by Compose.
## Docker first run
Follow the [README Quick start](../README.md#quick-start). It creates
`output/summary.json`, `output/vrps.csv` and `output/result.ccr`. State is retained
under `state/repository-db/`. View warnings in the terminal and inspect the
summary to distinguish rejected objects from successful repository updates.
## Build from source
Install Rust 1.92 or newer. On Debian/Ubuntu, native build dependencies include:
```bash
sudo apt-get update
sudo apt-get install --no-install-recommends build-essential clang libclang-dev \
pkg-config ca-certificates rsync time
cargo build --locked --release
target/release/panda-rpki --help
```
Run with the same inputs:
```bash
target/release/panda-rpki validate \
--tal input/anchor.tal --ta input/anchor.cer \
--rrdp-state-dir state --out output/native \
--ccr-out output/native/result.ccr
```
For tests, install `python3-cryptography` and `openssl`. See
[Development](development.md) and [Usage](usage.md) for next steps.

42111
docs/third-party-licenses.txt Normal file

File diff suppressed because it is too large Load Diff

148
docs/trust-anchors.md Normal file
View File

@@ -0,0 +1,148 @@
# Prepare all five RIR trust anchors
Panda RPKI requires a TAL and a matching DER-encoded TA certificate for each
anchor. The TAL supplies the trusted public key; the certificate supplies the
current trust-anchor certificate. A certificate alone is not a substitute for
an independently obtained TAL. No RIR inputs are bundled with this project.
## Official sources
Use the five ordinary production anchors below. Separate AS0 and test anchors
are not part of this all-five example. Review the applicable RIR terms before
using their services, including the [ARIN TAL page](https://www.arin.net/resources/manage/rpki/tal/)
and its linked [Relying Party Agreement](https://www.arin.net/resources/manage/rpki/rpa.pdf).
The project's BSD license does not replace those terms.
| RIR | Official TAL download | TA certificate location | Local files |
| --- | --- | --- | --- |
| AFRINIC | [afrinic.tal](https://rpki.afrinic.net/tal/afrinic.tal) | `https://rpki.afrinic.net/repository/AfriNIC.cer` | `afrinic.tal`, `afrinic.cer` |
| APNIC | [apnic.tal](https://tal.apnic.net/apnic.tal) | `rsync://rpki.apnic.net/repository/apnic-rpki-root-iana-origin.cer` | `apnic.tal`, `apnic.cer` |
| ARIN | [arin.tal](https://www.arin.net/resources/manage/rpki/arin.tal) | `https://rrdp.arin.net/arin-rpki-ta.cer` | `arin.tal`, `arin.cer` |
| LACNIC | [lacnic.tal (official file endpoint)](https://www.lacnic.net/innovaportal/file/4983/1/lacnic.tal) | `https://rrdp.lacnic.net/ta/rta-lacnic-rpki.cer` | `lacnic.tal`, `lacnic.cer` |
| RIPE NCC | [ripe-ncc.tal](https://tal.rpki.ripe.net/ripe-ncc.tal) | `https://rpki.ripe.net/ta/ripe-ncc-ta.cer` | `ripe.tal`, `ripe.cer` |
Further official references: [APNIC TAL archive](https://www.apnic.net/community/security/resource-certification/tal-archive/),
[LACNIC trust anchors](https://www.lacnic.net/4984/2/lacnic/rpki-rpki-trust-anchor),
and [RIPE NCC trust-anchor structure](https://www.ripe.net/manage-ips-and-asns/resource-management/rpki/ripe-ncc-rpki-trust-anchor-structure/).
Locations can change: inspect the downloaded TAL before using a certificate URL
from this table. Do not rewrite TAL public keys or invent certificate URLs.
## Download the TAL files
Requirements: Bash, curl, OpenSSL, and rsync. On Debian/Ubuntu:
```bash
sudo apt-get install --no-install-recommends ca-certificates curl openssl rsync
```
Run from the project root, in a Bash shell. Use a fresh input directory when
updating an existing deployment; the commands below overwrite matching filenames.
```bash
set -euo pipefail
mkdir -p input
fetch_https() {
curl --fail --show-error --location \
--proto '=https' --proto-redir '=https' \
--connect-timeout 15 --max-time 120 --retry 2 --retry-max-time 300 \
"$1" --output "$2"
}
fetch_https https://rpki.afrinic.net/tal/afrinic.tal input/afrinic.tal
fetch_https https://tal.apnic.net/apnic.tal input/apnic.tal
fetch_https https://www.arin.net/resources/manage/rpki/arin.tal input/arin.tal
fetch_https https://www.lacnic.net/innovaportal/file/4983/1/lacnic.tal input/lacnic.tal
fetch_https https://tal.rpki.ripe.net/ripe-ncc.tal input/ripe.tal
```
An HTTP 200 response does not prove that a file is a TAL. During a documentation
check on 2026-09-09, LACNIC's short download URL
`https://www.lacnic.net/rpki/lacnic.tal` returned an HTML website instead;
the official file endpoint used above returned a TAL. If either download
stops working, open the official LACNIC trust-anchor page above and
save its **ordinary production TAL** text as `input/lacnic.tal`: URI lines,
one blank line, then the complete Base64 public key. Do not copy the separate
AS0 TAL, page markup, or a certificate-derived key. If the official TAL text is
unavailable, stop and obtain it from LACNIC; do not substitute an arbitrary mirror.
Check all five TALs before downloading certificates:
```bash
for rir in afrinic apnic arin lacnic ripe; do
tal="input/$rir.tal"
if grep -Eiq '<!doctype|<html' "$tal"; then
echo "HTML received instead of a TAL: $tal" >&2
exit 1
fi
grep -E '^(https|rsync)://' "$tal"
awk '
{ sub(/\r$/, "") }
/^#/ { next }
/^(https|rsync):\/\// { uri=1; next }
/^[[:space:]]*$/ { if (uri) key=1; next }
key { printf "%s", $0 }
' "$tal" | tr -d '[:space:]' | openssl base64 -d -A \
| openssl pkey -pubin -inform DER -noout
done
```
## Download the TA certificates
After checking that the URI lines match the table, run in the same Bash shell
(which defines `fetch_https`):
```bash
fetch_https https://rpki.afrinic.net/repository/AfriNIC.cer input/afrinic.cer
timeout 120 rsync --timeout=60 --contimeout=15 \
rsync://rpki.apnic.net/repository/apnic-rpki-root-iana-origin.cer input/apnic.cer
fetch_https https://rrdp.arin.net/arin-rpki-ta.cer input/arin.cer
fetch_https https://rrdp.lacnic.net/ta/rta-lacnic-rpki.cer input/lacnic.cer
fetch_https https://rpki.ripe.net/ta/ripe-ncc-ta.cer input/ripe.cer
```
APNIC's TAL currently lists only rsync, which requires outbound TCP port 873
for this bootstrap step. This does not change Panda RPKI's HTTPS RRDP sync
mode. APNIC also serves the certificate at the following HTTPS endpoint,
which can be used when port 873 is blocked; this is an alternative download
endpoint, not an HTTPS URI present in the current APNIC TAL:
```bash
fetch_https https://rpki.apnic.net/repository/apnic-rpki-root-iana-origin.cer input/apnic.cer
```
Always verify the downloaded certificate against the independently obtained
TAL, including when using this alternative endpoint.
## Check the pairs and run
The following checks DER parsing, expiration, and equality of the certificate's
SubjectPublicKeyInfo with the TAL key. They are input sanity checks, not a full
RPKI profile or chain validation; Panda RPKI performs its validation during a run.
```bash
for rir in afrinic apnic arin lacnic ripe; do
openssl x509 -inform DER -in "input/$rir.cer" -noout -subject -dates
openssl x509 -inform DER -in "input/$rir.cer" -noout -checkend 0
tal_key=$(awk '
{ sub(/\r$/, "") }
/^#/ { next }
/^(https|rsync):\/\// { uri=1; next }
/^[[:space:]]*$/ { if (uri) key=1; next }
key { printf "%s", $0 }
' "input/$rir.tal" | tr -d '[:space:]')
cert_key=$(openssl x509 -inform DER -in "input/$rir.cer" -pubkey -noout \
| openssl pkey -pubin -outform DER | openssl base64 -A)
test -n "$tal_key" && test "$tal_key" = "$cert_key"
echo "$rir: TAL/TA public keys match"
done
```
You now have ten files in `input/`, named exactly as expected by the
[all-five Compose example](docker.md#all-five-regional-anchors). For the
single-anchor README example only, copy a chosen pair to `input/anchor.tal`
and `input/anchor.cer`, or change the CLI arguments to use its RIR filenames.
Keep inputs out of version control. Monitor certificate validity and RIR
announcements; Panda RPKI does not refresh supplied TA files automatically.
Stage and check updated pairs before replacing active inputs between runs.
Never resolve a key mismatch by replacing the TAL key with the downloaded
certificate's key: retrieve the current TAL from the RIR and investigate first.

101
docs/usage.md Normal file
View File

@@ -0,0 +1,101 @@
# Usage
Examples assume `panda-rpki` is on PATH; for a local build use
`target/release/panda-rpki`. Prepare TAL/TA files as described in
[Getting started](getting-started.md).
## Snapshot and delta
Use a fresh state directory for an explicit snapshot:
```bash
panda-rpki validate --tal input/anchor.tal --ta input/anchor.cer \
--rrdp-state-dir state/anchor --rrdp-sync-mode snapshot \
--out output/snapshot --ccr-out output/snapshot/result.ccr
panda-rpki validate --tal input/anchor.tal --ta input/anchor.cer \
--rrdp-state-dir state/anchor --rrdp-sync-mode delta \
--out output/delta-01 --ccr-out output/delta-01/result.ccr
```
Subsequent runs reuse state and can use `auto`. Delta mode can include a
protocol-required snapshot or noop. Check actual operation counters in the
summary. Do not discard persistent state between scheduled runs.
## Multiple anchors and constraints
```bash
panda-rpki validate \
--tal input/arin.tal --ta input/arin.cer --tal-id arin \
--tal input/ripe.tal --ta input/ripe.cer --tal-id ripe \
--parallel-max-repo-sync-workers-global 8 \
--parallel-phase2-object-workers 8 \
--rrdp-state-dir state/multi --out output/multi \
--ccr-out output/multi/result.ccr
```
Add further pairs in the same way. Optional resource constraints are read from
the TAL-adjacent `.constraints` file, or specified with
`--ta-constraints arin=input/arin.constraints`. Rules follow the WG profile
listed in the [standards matrix](conformance-matrix.md).
A constraint file contains `allow`/`deny` followed by an IPv4/IPv6 prefix,
address range, ASN or ASN range. Blank lines and `#` comments are allowed.
For a synthetic test anchor, an example is:
```text
# Example resources only: do not apply this policy to a production RIR.
allow 192.0.2.0/24
deny 192.0.2.128/25
allow 2001:db8::/32
allow 64496 - 64511
```
Deny overlap rejects an EE resource; otherwise the resource must be fully
covered by allow rules of its resource family. Unlisted resources are not
implicitly allowed. An empty constraint file therefore differs from having
no constraint file. Overlapping rules are normalized and may produce warnings.
## Continuous operation
```bash
panda-rpki daemon --state-root data/daemon \
--interval-secs 600 --retain-runs 10 -- \
--tal input/anchor.tal --ta input/anchor.cer \
--log-level info --log-format json
```
The daemon runs in the foreground. It starts with snapshot for empty state and
requests delta after successful runs. The interval starts after each cycle
finishes. Add `--max-runs 3` before `--` for a finite run. SIGTERM requests a
graceful stop. Restart with the same root to continue numbering and state.
Each cycle writes to `data/daemon/runs/run_000001/`, then `run_000002/`, etc.
Retention deletes the oldest completed run directories beyond the configured
limit, including their artifacts. Copy anything you need to retain elsewhere.
The append-only summary history is not trimmed by retention.
## Outputs and diagnostics
`vrps.csv` contains `asn,prefix,max_length`. CCR contains canonical state;
duplicate routing payloads can collapse into a single CCR entry. Count raw
rows and normalized unique payloads separately when comparing outputs.
ASPA canonicalization groups providers by customer ASN.
Use `--log-level debug` for diagnosis, or `trace` for detailed object/worker
events. Logs are written to stderr and can be redirected independently from
outputs. In daemon mode, inspect per-run `stderr.log` and the controller's
`daemon-status.json` and `run-summary.jsonl`.
| Symptom | Action |
| --- | --- |
| TAL/TA key mismatch or expired TA | Refresh the certificate from the TAL's official URI and check the selected pair. |
| State-layout/schema error | Preserve the directory and select a new dedicated root for a compatible run. |
| Snapshot refuses existing state | Use `auto`/`delta`, or choose a fresh directory for a new snapshot. |
| Delta refuses empty state | Establish state with `auto` or `snapshot`. |
| Permission denied in Docker | Pre-create writable host directories and use your UID/GID mapping. |
| RRDP origin rejection | Inspect the publisher's notification/references; extra TLS roots do not bypass origin policy. |
| Daemon root locked | Stop the other instance normally; do not delete its lock file. |
| Unexpected counts or partial output | Inspect warnings and per-run status; use new output paths to avoid stale files. |
See the [CLI reference](command-line-reference.md) for precise defaults,
timeouts, exit codes and recovery behavior.