初始化 Panda RPKI v0.1.0 开源候选版本
This commit is contained in:
139
docs/command-line-reference.md
Normal file
139
docs/command-line-reference.md
Normal 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.
|
||||
21
docs/conformance-matrix.md
Normal file
21
docs/conformance-matrix.md
Normal 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
33
docs/development.md
Normal 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
84
docs/docker.md
Normal 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
66
docs/getting-started.md
Normal 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
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
148
docs/trust-anchors.md
Normal 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
101
docs/usage.md
Normal 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.
|
||||
Reference in New Issue
Block a user