|
1 | | -# Cosmian KMS |
| 1 | +# Cosmian KMS — Nix-first build, test, and packaging |
2 | 2 |
|
3 | | -Cosmian KMS is a high-performance, open-source FIPS 140-3 compliant Key Management System written in Rust. The repository contains the KMS server (`cosmian_kms_server`) and supporting libraries for cryptographic operations, database management, and various integrations. |
| 3 | +Cosmian KMS is a high-performance, open-source FIPS 140-3 compliant Key Management System written in Rust. |
4 | 4 |
|
5 | | -Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here. |
| 5 | +This repository is maintained to be reproducible, deterministic, and offline-friendly. All build, test, and packaging is orchestrated via a single entrypoint: |
6 | 6 |
|
7 | | -## Working Effectively |
| 7 | +- Build and package: `bash .github/scripts/nix.sh package [deb|rpm|dmg]` |
| 8 | +- Run tests: `bash .github/scripts/nix.sh test [all|sqlite|mysql|psql|redis|google_cse|hsm]` |
8 | 9 |
|
9 | | -- **Bootstrap and build the repository:** |
| 10 | +Always reference these instructions first; only fall back to ad‑hoc commands when troubleshooting discrepancies. |
10 | 11 |
|
11 | | - - First, initialize git submodules: `git submodule update --recursive --init` |
12 | | - - System requires Rust stable toolchain (1.90.0) with rustfmt and clippy components |
13 | | - - OpenSSL 3.2.0 is REQUIRED (not 3.0.13+) for proper FIPS compliance and static linking |
14 | | - - OpenSSL must be installed to `/usr/local/openssl` using `.github/reusable_scripts/get_openssl_binaries.sh` |
15 | | - - Build process follows CI workflow: `bash .github/scripts/cargo_build.sh` |
16 | | - - Environment variables required: `OPENSSL_DIR=/usr/local/openssl`, `DEBUG_OR_RELEASE=debug|release` |
17 | | - - For non-FIPS builds: `FEATURES=non-fips` |
18 | | - - The CLI binary `cosmian` IS built in this repository and included in build artifacts |
| 12 | +## Why Nix? |
19 | 13 |
|
20 | | -- **UI and Packaging:** |
| 14 | +- Pinned nixpkgs for hermetic, reproducible environments |
| 15 | +- Native deterministic verification in the derivation (installCheckPhase) |
| 16 | +- Pinned Rust toolchain (1.90.0) from Nix — no rustup downloads |
| 17 | +- Pinned OpenSSL 3.1.2 with static linking (no dynamic OpenSSL at runtime) |
| 18 | +- One-command packaging for DEB/RPM/DMG with smoke tests |
21 | 19 |
|
22 | | - - UI is built on Ubuntu distributions using `bash .github/scripts/build_ui.sh` |
23 | | - - UI files are located in `crate/server/ui` directory |
24 | | - - Release builds create Debian packages via `cargo deb -p cosmian_kms_server` |
25 | | - - RPM packages created via `cargo generate-rpm -p crate/server` |
26 | | - - Packages support both FIPS and non-FIPS variants |
| 20 | +## Quick start |
27 | 21 |
|
28 | | -- **Testing and validation:** |
| 22 | +```bash |
| 23 | +# Build default packages for your platform (Linux → deb+rpm, macOS → dmg) |
| 24 | +bash .github/scripts/nix.sh package |
29 | 25 |
|
30 | | - - Multi-database testing: sqlite, postgresql, mysql, redis-findex |
31 | | - - Database environment variables: `KMS_POSTGRES_URL=postgresql://kms:[email protected]:5432/kms`, `KMS_MYSQL_URL=mysql://kms:kms@localhost:3306/kms`, `KMS_SQLITE_PATH=data/shared` |
32 | | - - MySQL tests are currently disabled (skipped in CI) |
33 | | - - Redis-findex tests skipped in FIPS mode (not supported) |
34 | | - - Debug builds only test sqlite; release builds test all enabled databases |
35 | | - - macOS runners only support sqlite tests (no docker containers) |
36 | | - - HSM testing on Ubuntu with Utimaco: `HSM_USER_PASSWORD="12345678" cargo test -p utimaco_pkcs11_loader --features utimaco` |
37 | | - - Logging control: `RUST_LOG="cosmian_kms_cli=error,cosmian_kms_server=error,cosmian_kmip=error,test_kms_server=error"` |
38 | | - - Test execution: `cargo test --workspace --lib $RELEASE $FEATURES -- --nocapture $SKIP_SERVICES_TESTS` |
| 26 | +# Build a specific format/variant |
| 27 | +bash .github/scripts/nix.sh --variant fips package deb |
| 28 | +bash .github/scripts/nix.sh --variant non-fips package rpm |
39 | 29 |
|
40 | | -- **Build artifacts and binaries:** |
| 30 | +# Build and test on SQLite only |
| 31 | +bash .github/scripts/nix.sh test sqlite |
41 | 32 |
|
42 | | - - Primary binaries: `cosmian`, `cosmian_kms`, `cosmian_findex_server` |
43 | | - - Binary locations: `target/$DEBUG_OR_RELEASE/` (e.g., `target/debug/`) |
44 | | - - Release builds include benchmarks: `cargo bench $FEATURES --no-run` |
45 | | - - Static linking verified (no dynamic OpenSSL dependencies): `ldd cosmian_kms | grep ssl` should fail |
46 | | - - Version verification: `cosmian_kms --info` must show OpenSSL 3.2.0 |
47 | | - - Binary tests: `cargo test --workspace --bins $RELEASE $FEATURES` |
| 33 | +# Run tests (defaults to 'all' - run 'docker compose up -d' first for DB backends) |
| 34 | +bash .github/scripts/nix.sh test |
| 35 | +``` |
48 | 36 |
|
49 | | -- **Run the KMS server:** |
| 37 | +Artifacts are placed under `result-deb-<variant>/`, `result-rpm-<variant>/`, and `result-dmg-<variant>/`. |
50 | 38 |
|
51 | | - - ALWAYS build first using the build script above |
52 | | - - Debug mode: `./target/debug/cosmian_kms --database-type sqlite --sqlite-path /tmp/kms-data` |
53 | | - - Release mode: `./target/release/cosmian_kms --database-type sqlite --sqlite-path /tmp/kms-data` |
54 | | - - Server listens on <http://0.0.0.0:9998> by default |
55 | | - - Supported databases: sqlite, postgresql, mysql, redis-findex (redis-findex not available in FIPS mode) |
| 39 | +## Determinism and native hash enforcement |
56 | 40 |
|
57 | | -- **Docker usage:** |
58 | | - - Development with services: `docker compose up -d` (starts postgresql, mysql, redis) |
59 | | - - Production: `docker run -p 9998:9998 --name kms ghcr.io/cosmian/kms:latest` |
60 | | - - Pre-built images include UI at <http://localhost:9998/ui> |
61 | | - - Local Docker builds use the same OpenSSL setup as CI |
| 41 | +The KMS server derivation computes the SHA-256 of the output binary and compares it to `nix/expected-hashes/{fips,non-fips}.sha256` during `installCheckPhase`. Any mismatch fails the build. Packaging scripts also enforce the expected hash when reusing prebuilt results to ensure drift is caught early. |
62 | 42 |
|
63 | | -## Validation |
| 43 | +To update an expected hash after a legitimate change: |
64 | 44 |
|
65 | | -- **CRITICAL**: Always manually test server functionality after making changes by starting the server and verifying it responds to HTTP requests |
66 | | -- Test server startup: Start server with `--database-type sqlite --sqlite-path /tmp/test-db` |
67 | | -- Test API responses: `curl -s -X POST -H "Content-Type: application/json" -d '{}' http://localhost:9998/kmip/2_1` should return KMIP validation error (confirms server is working) |
68 | | -- Test server version: `./target/release/cosmian_kms --version` should show version 5.11.1 |
69 | | -- OpenSSL validation: `./target/release/cosmian_kms --info` should show OpenSSL 3.2.0 |
70 | | -- Static linking check: `ldd ./target/release/cosmian_kms | grep ssl` should return empty (no dynamic OpenSSL) |
71 | | -- Always run `cargo fmt --check` before committing (takes 3 seconds) |
72 | | -- Clippy requires installation: `rustup component add clippy` |
| 45 | +```bash |
| 46 | +nix-build -A kms-server-fips -o result-server-fips |
| 47 | +sha256sum result-server-fips/bin/cosmian_kms | cut -d' ' -f1 > nix/expected-hashes/fips.sha256 |
| 48 | +# repeat for non-fips |
| 49 | +``` |
73 | 50 |
|
74 | | -## Common tasks |
| 51 | +## Offline packaging |
75 | 52 |
|
76 | | -The following are outputs from frequently run commands. Reference them instead of viewing, searching, or running bash commands to save time. |
| 53 | +The first run can prewarm the Nix store (pinned nixpkgs, tools) and the Cargo registry cache. Subsequent runs can be fully offline: |
77 | 54 |
|
78 | | -### Repo root structure |
| 55 | +- Nix: store prewarmed and reused; builds run with empty `substituters` |
| 56 | +- Cargo: registry and crate sources cached in `target/cargo-offline-home` and packaging runs with `CARGO_NET_OFFLINE=true` |
| 57 | +- OpenSSL: `resources/tarballs/openssl-3.1.2.tar.gz` must exist locally (script fetches it once if online) |
79 | 58 |
|
80 | | -```text |
81 | | -.cargo/ # Cargo configuration |
82 | | -.github/ # CI/CD workflows and scripts |
83 | | - scripts/ # Build scripts (cargo_build.sh, build_ui.sh) |
84 | | - reusable_scripts/ # OpenSSL setup scripts |
85 | | -crate/ # Rust workspace crates |
86 | | - server/ # KMS server binary crate |
87 | | - ui/ # Web UI files (built by build_ui.sh) |
88 | | - cli/ # CLI binary crate (cosmian) |
89 | | - crypto/ # Cryptographic operations |
90 | | - kmip/ # KMIP protocol implementation |
91 | | - client_utils/ # Client utilities |
92 | | - kms_client/ # KMS client library |
93 | | - access/ # Access control |
94 | | - interfaces/ # Database and HSM interfaces |
95 | | - server_database/ # Database management |
96 | | - hsm/ # HSM integrations (proteccio, utimaco, softhsm2) |
97 | | -documentation/ # Project documentation |
98 | | -docker-compose.yml # Development services (postgres, mysql, redis) |
99 | | -Dockerfile # Container build |
100 | | -README.md # Project documentation |
101 | | -Cargo.toml # Workspace configuration |
102 | | -rust-toolchain.toml # Rust toolchain: 1.90.0 |
103 | | -``` |
| 59 | +Verification: disconnect network, then re-run `bash .github/scripts/nix.sh package deb` — it should succeed and produce the same artifact hash. |
104 | 60 |
|
105 | | -### Key build commands and timing |
| 61 | +## Testing |
106 | 62 |
|
107 | 63 | ```bash |
108 | | -# Full CI build process (includes UI, packaging, multi-database tests) |
109 | | -git submodule update --recursive --init |
110 | | -export OPENSSL_DIR=/usr/local/openssl |
111 | | -export DEBUG_OR_RELEASE=debug # or release |
112 | | -export FEATURES=non-fips # optional, for non-FIPS builds |
113 | | - |
114 | | -# OpenSSL setup (required first) |
115 | | -sudo mkdir -p /usr/local/openssl/ssl /usr/local/openssl/lib64/ossl-modules |
116 | | -sudo chown -R $USER /usr/local/openssl |
117 | | -bash .github/reusable_scripts/get_openssl_binaries.sh |
118 | | -bash .github/scripts/cargo_build.sh |
| 64 | +# Typical flows |
| 65 | +bash .github/scripts/nix.sh test # all tests supported on your OS |
| 66 | +bash .github/scripts/nix.sh test sqlite # sqlite-only (macOS/Linux) |
| 67 | +bash .github/scripts/nix.sh test psql # requires local PostgreSQL |
| 68 | +bash .github/scripts/nix.sh test redis # non-FIPS only |
| 69 | + |
| 70 | +# HSM tests (Linux only) |
| 71 | +bash .github/scripts/nix.sh test hsm # softhsm2 + utimaco + proteccio |
| 72 | +bash .github/scripts/nix.sh test hsm softhsm2 # single backend |
| 73 | +``` |
119 | 74 |
|
| 75 | +Environment variables for DB tests: |
120 | 76 |
|
121 | | -# UI build (Ubuntu only) |
122 | | -bash .github/scripts/build_ui.sh |
| 77 | +- `KMS_POSTGRES_URL=postgresql://kms:[email protected]:5432/kms` |
| 78 | +- `KMS_MYSQL_URL=mysql://kms:kms@localhost:3306/kms` |
| 79 | +- `KMS_SQLITE_PATH=data/shared` |
123 | 80 |
|
124 | | -# Individual builds (after OpenSSL setup) |
125 | | -cargo build --features non-fips |
126 | | -cargo build --release --features non-fips |
| 81 | +Notes: |
127 | 82 |
|
128 | | -# Multi-database testing |
129 | | -export KMS_TEST_DB=sqlite # or postgresql, mysql, redis-findex |
130 | | -cargo test --workspace --lib --features non-fips |
| 83 | +- MySQL tests are currently disabled in CI |
| 84 | +- Redis-findex tests are skipped in FIPS mode |
| 85 | +- On macOS, only sqlite tests run (no DB containers) |
131 | 86 |
|
132 | | -# HSM testing (Ubuntu only) |
133 | | -bash .github/reusable_scripts/test_utimaco.sh |
134 | | -HSM_USER_PASSWORD="12345678" cargo test -p utimaco_pkcs11_loader --features utimaco |
| 87 | +## Validation and smoke tests |
135 | 88 |
|
136 | | -# Packaging (release builds only) |
137 | | -cargo install cargo-deb cargo-generate-rpm |
138 | | -cargo deb -p cosmian_kms_server |
139 | | -cargo generate-rpm -p crate/server |
| 89 | +Packaging runs include a smoke test that extracts the artifact and runs `cosmian_kms --info` to verify OpenSSL 3.1.2 and static linkage. You can also run the server manually (after building or unpacking a package): |
140 | 90 |
|
141 | | -# Format check (3 seconds) |
142 | | -cargo fmt --check |
| 91 | +```bash |
| 92 | +./cosmian_kms --database-type sqlite --sqlite-path /tmp/kms-data |
143 | 93 | ``` |
144 | 94 |
|
145 | | -### Server startup and validation |
| 95 | +Basic API probe: |
146 | 96 |
|
147 | 97 | ```bash |
148 | | -# Start server (debug) |
149 | | -./target/debug/cosmian_kms --database-type sqlite --sqlite-path /tmp/kms-data |
150 | | - |
151 | | -# Start server (release) |
152 | | -./target/release/cosmian_kms --database-type sqlite --sqlite-path /tmp/kms-data |
153 | | - |
154 | | -# Test server is responding |
155 | 98 | curl -s -X POST -H "Content-Type: application/json" -d '{}' http://localhost:9998/kmip/2_1 |
156 | | -# Expected response: "Invalid Request: missing field `tag` at line 1 column 2" |
| 99 | +``` |
157 | 100 |
|
158 | | -# Check version and OpenSSL |
159 | | -./target/release/cosmian_kms --version |
160 | | -# Expected: "cosmian_kms_server 5.11.1" |
| 101 | +Expected response is a KMIP validation error, confirming the server is alive. |
161 | 102 |
|
162 | | -./target/release/cosmian_kms --info |
163 | | -# Expected: Output containing "OpenSSL 3.2.0" |
| 103 | +## Repository layout (high level) |
164 | 104 |
|
165 | | -# Verify static linking (should return empty) |
166 | | -ldd ./target/release/cosmian_kms | grep ssl |
| 105 | +```text |
| 106 | +.github/ # Orchestrator scripts (nix.sh), CI, and helpers |
| 107 | +nix/ # Nix derivations, scripts, expected hashes |
| 108 | +crate/ # Rust workspace crates (server, cli, crypto, …) |
| 109 | +pkg/ # Packaging metadata (deb/rpm service files, configs) |
| 110 | +resources/tarballs/ # OpenSSL 3.1.2 tarball (local copy for offline) |
| 111 | +result-*/ # Symlinks to build/package results |
167 | 112 | ``` |
168 | 113 |
|
169 | | -### Docker quick start |
| 114 | +## Tips |
| 115 | + |
| 116 | +- Format/lints: run `cargo fmt --check` and clippy inside the Nix environment if needed |
| 117 | +- If repeated packaging triggers rebuilds, set `NO_PREWARM=1` for faster reuse-only runs |
| 118 | +- If a package fails due to hash mismatch, update the relevant file in `nix/expected-hashes/` only after reviewing the change |
| 119 | + |
| 120 | +## Docker |
170 | 121 |
|
171 | 122 | ```bash |
172 | | -# Pull and run pre-built image (includes UI) |
173 | 123 | docker pull ghcr.io/cosmian/kms:latest |
174 | 124 | docker run -p 9998:9998 --name kms ghcr.io/cosmian/kms:latest |
175 | | - |
176 | | -# Development with services |
177 | | -docker compose up -d |
178 | | - |
179 | | -# Access UI |
180 | | -curl http://localhost:9998/ui |
181 | | -# Expected: HTML content with KMS web interface |
182 | 125 | ``` |
183 | 126 |
|
184 | | -## Important notes |
185 | | - |
186 | | -- **OpenSSL Version**: OpenSSL 3.2.0 is mandatory, not 3.0.13+. The build verifies this specific version. |
187 | | -- **Static Linking**: All binaries must be statically linked with OpenSSL. CI verifies no dynamic OpenSSL dependencies. |
188 | | -- **Build Artifacts**: Three primary binaries are built: `cosmian`, `cosmian_kms`, `cosmian_findex_server` |
189 | | -- **Database Testing**: Only sqlite works in debug mode and on macOS. Full database testing requires release builds. |
190 | | -- **FIPS vs non-FIPS**: Redis-findex database support is not available in FIPS mode |
191 | | -- **UI Building**: UI is only built on Ubuntu distributions and requires separate build script |
192 | | -- **Packaging**: Debian and RPM packages are created as part of release builds with proper FIPS/non-FIPS variants |
193 | | -- **HSM Support**: Utimaco HSM testing is included but only runs on Ubuntu with specific setup |
194 | | -- **MySQL**: MySQL database tests are currently disabled in CI |
195 | | -- **Workspace**: Build from workspace root using cargo_build.sh script, not individual crate directories |
| 127 | +Images include the UI at `http://localhost:9998/ui`. |
0 commit comments