From 908579cd602897ee244f665ca66eea474658dd87 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Thu, 13 Feb 2025 15:47:36 +0100 Subject: [PATCH] feat: rewrite google-metadata test as tdx-test Signed-off-by: Harald Hoyer --- .github/workflows/nix.yml | 2 +- Cargo.lock | 496 +++++++++++++------ Cargo.toml | 14 +- bin/google-metadata/src/main.rs | 74 --- bin/{google-metadata => tdx-test}/Cargo.toml | 10 +- bin/tdx-test/src/main.rs | 59 +++ crates/teepot/Cargo.toml | 9 + crates/teepot/src/config/mod.rs | 294 +++++++++++ crates/teepot/src/lib.rs | 3 +- packages/container-tdx-test/default.nix | 35 ++ packages/container-test-tdx/default.nix | 24 - packages/teepot/default.nix | 2 +- 12 files changed, 771 insertions(+), 251 deletions(-) delete mode 100644 bin/google-metadata/src/main.rs rename bin/{google-metadata => tdx-test}/Cargo.toml (61%) create mode 100644 bin/tdx-test/src/main.rs create mode 100644 crates/teepot/src/config/mod.rs create mode 100644 packages/container-tdx-test/default.nix delete mode 100644 packages/container-test-tdx/default.nix diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 3dafb07..f17c396 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -73,7 +73,7 @@ jobs: - { nixpackage: 'container-self-attestation-test-sgx-azure' } - { nixpackage: 'container-verify-attestation-sgx' } - { nixpackage: 'container-verify-era-proof-attestation-sgx' } - - { nixpackage: 'container-test-tdx' } + - { nixpackage: 'container-tdx-test' } steps: - uses: actions/checkout@v4 - uses: cachix/install-nix-action@v30 diff --git a/Cargo.lock b/Cargo.lock index 953205b..8f427cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -354,12 +354,40 @@ dependencies = [ "zeroize", ] +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + [[package]] name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "async-trait" version = "0.1.86" @@ -460,7 +488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.3.4", "bitflags 1.3.2", "bytes", "futures-util", @@ -481,6 +509,33 @@ dependencies = [ "tower-service", ] +[[package]] +name = "axum" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" +dependencies = [ + "async-trait", + "axum-core 0.4.5", + "bytes", + "futures-util", + "http 1.2.0", + "http-body 1.0.1", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 1.0.2", + "tower 0.5.2", + "tower-layer", + "tower-service", +] + [[package]] name = "axum-core" version = "0.3.4" @@ -498,6 +553,26 @@ dependencies = [ "tower-service", ] +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.2.0", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.2", + "tower-layer", + "tower-service", +] + [[package]] name = "backtrace" version = "0.3.74" @@ -1012,6 +1087,21 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bed69047ed42e52c7e38d6421eeb8ceefb4f2a2b52eed59137f7bad7908f6800" +[[package]] +name = "config" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf9dc8d4ef88e27a8cb23e85cb116403dedd57f7971964dc4b18ccead548901" +dependencies = [ + "async-trait", + "pathdiff", + "serde", + "serde_json", + "toml", + "winnow 0.7.1", + "yaml-rust2", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -1929,10 +2019,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", ] [[package]] @@ -2015,18 +2103,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "google-metadata" -version = "0.3.0" -dependencies = [ - "anyhow", - "reqwest 0.12.12", - "reqwest-middleware", - "reqwest-retry", - "serde_json", - "tokio", -] - [[package]] name = "gpt" version = "4.0.0" @@ -2105,12 +2181,30 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + [[package]] name = "heck" version = "0.4.1" @@ -2296,6 +2390,7 @@ dependencies = [ "http 1.2.0", "http-body 1.0.1", "httparse", + "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -2333,6 +2428,19 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper 1.6.0", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -2633,18 +2741,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "intel-tee-quote-verification-sys" version = "0.2.1" @@ -3428,7 +3524,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" dependencies = [ "opentelemetry_api", - "opentelemetry_sdk", + "opentelemetry_sdk 0.20.0", +] + +[[package]] +name = "opentelemetry" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab70038c28ed37b97d8ed414b6429d343a8bbf44c9f79ec854f3a643029ba6d7" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "pin-project-lite", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "opentelemetry-appender-tracing" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5feffc321035ad94088a7e5333abb4d84a8726e54a802e736ce9dd7237e85b" +dependencies = [ + "log", + "opentelemetry 0.27.1", + "tracing", + "tracing-core", + "tracing-log 0.2.0", + "tracing-subscriber", ] [[package]] @@ -3454,15 +3578,34 @@ dependencies = [ "futures-core", "http 0.2.12", "opentelemetry-http", - "opentelemetry-proto", - "opentelemetry-semantic-conventions", + "opentelemetry-proto 0.3.0", + "opentelemetry-semantic-conventions 0.12.0", "opentelemetry_api", - "opentelemetry_sdk", + "opentelemetry_sdk 0.20.0", "prost 0.11.9", "reqwest 0.11.27", "thiserror 1.0.69", "tokio", - "tonic", + "tonic 0.9.2", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cf61a1868dacc576bf2b2a1c3e9ab150af7272909e80085c3173384fe11f76" +dependencies = [ + "async-trait", + "futures-core", + "http 1.2.0", + "opentelemetry 0.27.1", + "opentelemetry-proto 0.27.0", + "opentelemetry_sdk 0.27.1", + "prost 0.13.5", + "thiserror 1.0.69", + "tokio", + "tonic 0.12.3", + "tracing", ] [[package]] @@ -3472,9 +3615,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1e3f814aa9f8c905d0ee4bde026afd3b2577a97c10e1699912e3e44f0c4cbeb" dependencies = [ "opentelemetry_api", - "opentelemetry_sdk", + "opentelemetry_sdk 0.20.0", "prost 0.11.9", - "tonic", + "tonic 0.9.2", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6e05acbfada5ec79023c85368af14abd0b307c015e9064d249b2a950ef459a6" +dependencies = [ + "opentelemetry 0.27.1", + "opentelemetry_sdk 0.27.1", + "prost 0.13.5", + "tonic 0.12.3", ] [[package]] @@ -3483,9 +3638,15 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269" dependencies = [ - "opentelemetry", + "opentelemetry 0.20.0", ] +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fb3a2f78c2d55362cd6c313b8abedfbc0142ab3c2676822068fd2ab7d51f9b7" + [[package]] name = "opentelemetry_api" version = "0.20.0" @@ -3525,6 +3686,27 @@ dependencies = [ "tokio-stream", ] +[[package]] +name = "opentelemetry_sdk" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231e9d6ceef9b0b2546ddf52335785ce41252bc7474ee8ba05bfad277be13ab8" +dependencies = [ + "async-trait", + "futures-channel", + "futures-executor", + "futures-util", + "glob", + "opentelemetry 0.27.1", + "percent-encoding", + "rand", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tracing", +] + [[package]] name = "ordered-float" version = "2.10.1" @@ -3626,17 +3808,6 @@ dependencies = [ "syn 2.0.98", ] -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - [[package]] name = "parking_lot" version = "0.12.3" @@ -3644,21 +3815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -3669,7 +3826,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.8", + "redox_syscall", "smallvec", "windows-targets 0.52.6", ] @@ -3691,6 +3848,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + [[package]] name = "pe-sign" version = "0.1.10" @@ -3980,7 +4143,7 @@ checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" dependencies = [ "dtoa", "itoa", - "parking_lot 0.12.3", + "parking_lot", "prometheus-client-derive-encode", ] @@ -4015,6 +4178,16 @@ dependencies = [ "prost-derive 0.12.6", ] +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive 0.13.5", +] + [[package]] name = "prost-build" version = "0.12.6" @@ -4062,6 +4235,19 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "prost-reflect" version = "0.12.0" @@ -4168,15 +4354,6 @@ dependencies = [ "getrandom 0.2.15", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.5.8" @@ -4321,52 +4498,6 @@ dependencies = [ "windows-registry", ] -[[package]] -name = "reqwest-middleware" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ccd3b55e711f91a9885a2fa6fbbb2e39db1776420b062efc058c6410f7e5e3" -dependencies = [ - "anyhow", - "async-trait", - "http 1.2.0", - "reqwest 0.12.12", - "serde", - "thiserror 1.0.69", - "tower-service", -] - -[[package]] -name = "reqwest-retry" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c73e4195a6bfbcb174b790d9b3407ab90646976c55de58a6515da25d851178" -dependencies = [ - "anyhow", - "async-trait", - "futures", - "getrandom 0.2.15", - "http 1.2.0", - "hyper 1.6.0", - "parking_lot 0.11.2", - "reqwest 0.12.12", - "reqwest-middleware", - "retry-policies", - "thiserror 1.0.69", - "tokio", - "tracing", - "wasm-timer", -] - -[[package]] -name = "retry-policies" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5875471e6cab2871bc150ecb8c727db5113c9338cc3354dc5ee3425b6aa40a1c" -dependencies = [ - "rand", -] - [[package]] name = "rfc6979" version = "0.3.1" @@ -4886,6 +5017,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -5334,6 +5474,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "tdx-test" +version = "0.3.0" +dependencies = [ + "anyhow", + "serde", + "teepot", + "thiserror 2.0.11", + "tokio", + "tracing", +] + [[package]] name = "tee-key-preexec" version = "0.3.0" @@ -5433,11 +5585,13 @@ dependencies = [ "actix-http", "actix-web", "anyhow", + "async-trait", "awc", "base64 0.22.1", "bytemuck", "bytes", "clap 4.5.28", + "config", "const-oid", "enumset", "futures-core", @@ -5445,10 +5599,16 @@ dependencies = [ "hex", "num-integer", "num-traits", + "opentelemetry 0.27.1", + "opentelemetry-appender-tracing", + "opentelemetry-otlp 0.27.0", + "opentelemetry-semantic-conventions 0.28.0", + "opentelemetry_sdk 0.27.1", "p256", "pgp", "pkcs8 0.10.2", "rand", + "reqwest 0.12.12", "rsa", "rustls", "secp256k1 0.30.0", @@ -5464,6 +5624,7 @@ dependencies = [ "thiserror 2.0.11", "tokio", "tracing", + "tracing-futures", "tracing-log 0.2.0", "tracing-subscriber", "tracing-test", @@ -5690,7 +5851,7 @@ dependencies = [ "bytes", "libc", "mio", - "parking_lot 0.12.3", + "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", @@ -5764,11 +5925,26 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.23", +] + [[package]] name = "toml_datetime" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -5788,6 +5964,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" dependencies = [ "indexmap 2.7.1", + "serde", + "serde_spanned", "toml_datetime", "winnow 0.7.1", ] @@ -5799,7 +5977,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" dependencies = [ "async-trait", - "axum", + "axum 0.6.20", "base64 0.21.7", "bytes", "futures-core", @@ -5808,7 +5986,7 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.32", - "hyper-timeout", + "hyper-timeout 0.4.1", "percent-encoding", "pin-project", "prost 0.11.9", @@ -5820,6 +5998,36 @@ dependencies = [ "tracing", ] +[[package]] +name = "tonic" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +dependencies = [ + "async-stream", + "async-trait", + "axum 0.7.9", + "base64 0.22.1", + "bytes", + "h2 0.4.7", + "http 1.2.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.6.0", + "hyper-timeout 0.5.2", + "hyper-util", + "percent-encoding", + "pin-project", + "prost 0.13.5", + "socket2", + "tokio", + "tokio-stream", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower" version = "0.4.13" @@ -5913,6 +6121,16 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "tracing-log" version = "0.1.4" @@ -5942,8 +6160,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75327c6b667828ddc28f5e3f169036cb793c3f588d83bf0f262a7f062ffed3c8" dependencies = [ "once_cell", - "opentelemetry", - "opentelemetry_sdk", + "opentelemetry 0.20.0", + "opentelemetry_sdk 0.20.0", "smallvec", "tracing", "tracing-core", @@ -6373,21 +6591,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-timer" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.11.2", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "web-sys" version = "0.3.77" @@ -6721,6 +6924,17 @@ dependencies = [ "tls_codec", ] +[[package]] +name = "yaml-rust2" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a1a1c0bc9823338a3bdf8c61f994f23ac004c6fa32c08cd152984499b445e8d" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", +] + [[package]] name = "yoke" version = "0.7.5" @@ -7103,9 +7317,9 @@ checksum = "ff02e5df2e986592b916077f210b28a35e63d947936f99431041ad79289306e8" dependencies = [ "anyhow", "chrono", - "opentelemetry", - "opentelemetry-otlp", - "opentelemetry-semantic-conventions", + "opentelemetry 0.20.0", + "opentelemetry-otlp 0.13.0", + "opentelemetry-semantic-conventions 0.12.0", "sentry", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index c883025..fb382b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,11 +19,13 @@ homepage = "https://github.com/matter-labs/teepot" actix-http = "3" actix-web = { version = "4.5", features = ["rustls-0_23"] } anyhow = "1.0.82" +async-trait = "0.1.86" awc = { version = "3.4", features = ["rustls-0_23-webpki-roots"] } base64 = "0.22.0" bytemuck = { version = "1.15.0", features = ["derive", "min_const_generics", "extern_crate_std"] } bytes = "1" clap = { version = "4.5", features = ["std", "derive", "env", "error-context", "help", "usage", "wrap_help"], default-features = false } +config = { version = "0.15.8", default-features = false, features = ["yaml", "json", "toml", "async"] } const-oid = { version = "0.9", default-features = false } enumset = { version = "1.1", features = ["serde"] } futures-core = { version = "0.3.30", features = ["alloc"], default-features = false } @@ -35,14 +37,17 @@ intel-tee-quote-verification-sys = { version = "0.2.1" } jsonrpsee-types = { version = "0.24", default-features = false } num-integer = "0.1.46" num-traits = "0.2.18" +opentelemetry = { version = "0.27.0", features = ["default", "logs"] } +opentelemetry-appender-tracing = { version = "0.27.0", features = ["experimental_metadata_attributes", "log"] } +opentelemetry-otlp = { version = "0.27.0", features = ["grpc-tonic", "logs"] } +opentelemetry-semantic-conventions = { version = "0.28.0", features = ["semconv_experimental"] } +opentelemetry_sdk = { version = "0.27.1", features = ["tokio", "rt-tokio"] } p256 = "0.13.2" pe-sign = "0.1.10" pgp = "0.15" pkcs8 = { version = "0.10" } rand = { version = "0.8", features = ["std", "std_rng"] } reqwest = { version = "0.12", features = ["json"] } -reqwest-middleware = "0.4.0" -reqwest-retry = "0.7.0" rsa = { version = "0.9.6", features = ["sha2", "pem"] } rustls = { version = "0.23.20" } secp256k1 = { version = "0.30", features = ["rand", "global-context"] } @@ -56,11 +61,12 @@ tdx-attest-rs = { version = "0.1.2", git = "https://github.com/intel/SGXDataCent teepot = { path = "crates/teepot" } testaso = "0.1.0" thiserror = "2.0.11" -tokio = { version = "1", features = ["sync", "macros", "rt-multi-thread", "fs", "time"] } +tokio = { version = "1", features = ["sync", "macros", "rt-multi-thread", "fs", "time", "signal"] } tracing = "0.1" tracing-actix-web = "0.7" +tracing-futures = { version = "0.2.5", features = ["std"] } tracing-log = "0.2" -tracing-subscriber = { version = "0.3", features = ["env-filter"] } +tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "ansi"] } tracing-test = { version = "0.2.5", features = ["no-env-filter"] } url = "2.5.2" webpki-roots = "0.26.1" diff --git a/bin/google-metadata/src/main.rs b/bin/google-metadata/src/main.rs deleted file mode 100644 index 33bdc66..0000000 --- a/bin/google-metadata/src/main.rs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright (c) 2025 Matter Labs - -use anyhow::{bail, Result}; -use reqwest::Client; -use reqwest_middleware::{ClientBuilder, ClientWithMiddleware}; -use reqwest_retry::{policies::ExponentialBackoff, Jitter, RetryTransientMiddleware}; -use serde_json::Value; -use std::time::Duration; - -const DEFAULT_INSTANCE_METADATA_BASE_URL: &str = - "http://metadata.google.internal/computeMetadata/v1/instance/attributes"; - -async fn fetch_gcp_metadata( - http_client: &ClientWithMiddleware, - metadata_key: &str, -) -> Result { - // Validate the metadata key: - if metadata_key.is_empty() { - bail!("Empty metadata_key"); - } - - let url = format!("{DEFAULT_INSTANCE_METADATA_BASE_URL}/{metadata_key}"); - - // Make an HTTP GET request: - let response = http_client - .get(url) - .header("Metadata-Flavor", "Google") - .send() - .await?; - - // Handle response: - if response.status().is_success() { - let metadata_text = response.text().await?; - serde_json::from_str(&metadata_text) - .map_err(|e| anyhow::format_err!("Failed to parse metadata JSON: {}", e)) - } else { - let status = response.status(); - let error_body = response - .text() - .await - .unwrap_or_else(|_| "".to_string()); - bail!( - "Failed to fetch metadata: {}, Response body: {}", - status, - error_body - ); - } -} - -#[tokio::main] -async fn main() -> Result<()> { - // Build the client with retry middleware and exponential backoff: - let retry_policy = ExponentialBackoff::builder() - .retry_bounds(Duration::from_secs(1), Duration::from_secs(32)) - .jitter(Jitter::Bounded) - .base(2) - .build_with_total_retry_duration(Duration::from_secs(60)); - let client = ClientBuilder::new(Client::builder().build()?) // Underlying reqwest client - .with(RetryTransientMiddleware::new_with_policy(retry_policy)) // Add retry middleware - .build(); - - // Fetch and display metadata: - match fetch_gcp_metadata(&client, "container_config").await { - Ok(container_config) => { - println!("Container config:\n{:#?}", container_config); - } - Err(e) => { - eprintln!("Error fetching container config: {}", e); - } - } - - Ok(()) -} diff --git a/bin/google-metadata/Cargo.toml b/bin/tdx-test/Cargo.toml similarity index 61% rename from bin/google-metadata/Cargo.toml rename to bin/tdx-test/Cargo.toml index 15e1a98..ea2a368 100644 --- a/bin/google-metadata/Cargo.toml +++ b/bin/tdx-test/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "google-metadata" +name = "tdx-test" version.workspace = true edition.workspace = true authors.workspace = true @@ -9,8 +9,8 @@ homepage.workspace = true [dependencies] anyhow.workspace = true -reqwest.workspace = true -reqwest-middleware.workspace = true -reqwest-retry.workspace = true -serde_json.workspace = true +serde.workspace = true +teepot.workspace = true +thiserror.workspace = true tokio.workspace = true +tracing.workspace = true diff --git a/bin/tdx-test/src/main.rs b/bin/tdx-test/src/main.rs new file mode 100644 index 0000000..217b5c2 --- /dev/null +++ b/bin/tdx-test/src/main.rs @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2025 Matter Labs + +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use teepot::config::{load_config_with_telemetry, TelemetryConfig}; +use thiserror::Error; +use tracing::{debug, error, info, trace, warn}; + +// Configuration struct +#[derive(Debug, Serialize, Deserialize)] +struct AppConfig { + server: ServerConfig, + telemetry: TelemetryConfig, +} + +impl Default for AppConfig { + fn default() -> Self { + Self { + server: ServerConfig::default(), + telemetry: TelemetryConfig::new( + env!("CARGO_CRATE_NAME").into(), + env!("CARGO_PKG_VERSION").into(), + ), + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +struct ServerConfig { + port: u16, +} + +impl Default for ServerConfig { + fn default() -> Self { + Self { port: 8080 } + } +} + +// Error handling +#[derive(Error, Debug)] +enum AppError { + #[error("Internal server error")] + Internal(#[from] anyhow::Error), +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let config = load_config_with_telemetry(|config: &AppConfig| &config.telemetry).await?; + + loop { + error!(?config, "error test!"); + warn!(?config, "warn test!"); + info!(?config, "info test!"); + debug!(?config, "debug test!"); + trace!(?config, "trace test!"); + tokio::time::sleep(std::time::Duration::from_secs(60)).await; + } +} diff --git a/crates/teepot/Cargo.toml b/crates/teepot/Cargo.toml index 3b3b6b8..ca0731e 100644 --- a/crates/teepot/Cargo.toml +++ b/crates/teepot/Cargo.toml @@ -14,10 +14,12 @@ repository.workspace = true actix-http.workspace = true actix-web.workspace = true anyhow.workspace = true +async-trait.workspace = true awc.workspace = true bytemuck.workspace = true bytes.workspace = true clap.workspace = true +config.workspace = true const-oid.workspace = true enumset.workspace = true futures-core.workspace = true @@ -26,10 +28,16 @@ hex.workspace = true intel-tee-quote-verification-rs.workspace = true num-integer.workspace = true num-traits.workspace = true +opentelemetry.workspace = true +opentelemetry-appender-tracing.workspace = true +opentelemetry-otlp.workspace = true +opentelemetry-semantic-conventions.workspace = true +opentelemetry_sdk.workspace = true p256.workspace = true pgp.workspace = true pkcs8.workspace = true rand.workspace = true +reqwest.workspace = true rsa.workspace = true rustls.workspace = true secp256k1 = { workspace = true, features = ["recovery"] } @@ -42,6 +50,7 @@ signature.workspace = true tdx-attest-rs.workspace = true thiserror.workspace = true tracing.workspace = true +tracing-futures.workspace = true tracing-log.workspace = true tracing-subscriber.workspace = true webpki-roots.workspace = true diff --git a/crates/teepot/src/config/mod.rs b/crates/teepot/src/config/mod.rs new file mode 100644 index 0000000..b5f7595 --- /dev/null +++ b/crates/teepot/src/config/mod.rs @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2025 Matter Labs + +//! Configuration handling + +use async_trait::async_trait; +use config::{ + builder::AsyncState, AsyncSource, Config, ConfigBuilder, ConfigError, File, FileFormat, Format, + Map, +}; +use opentelemetry::KeyValue; +use opentelemetry_otlp::WithExportConfig; +use opentelemetry_sdk::{logs::LoggerProvider, runtime, Resource}; +use opentelemetry_semantic_conventions::{ + attribute::{SERVICE_NAME, SERVICE_VERSION}, + SCHEMA_URL, +}; +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; +use tracing::trace; +use tracing_subscriber::{ + fmt::format::FmtSpan, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, +}; + +const DEFAULT_INSTANCE_METADATA_BASE_URL: &str = + "http://metadata.google.internal/computeMetadata/v1/instance/attributes/container_config"; + +/// Get the configuration via HTTP +#[derive(Debug)] +pub struct HttpSource { + /// the URI + pub uri: String, + /// the expected format + pub format: F, + /// if this is required, it will error, if not available + pub required: bool, +} + +#[async_trait] +impl AsyncSource for HttpSource { + async fn collect(&self) -> Result, ConfigError> { + let response = match reqwest::get(&self.uri) + .await + .map_err(|e| ConfigError::Foreign(Box::new(e))) + { + Ok(response) => response, + Err(e) => { + if self.required { + return Err(e); + } else { + return Ok(Map::new()); + } + } + }; + + // error conversion is possible from custom AsyncSource impls + response + .text() + .await + .map_err(|e| ConfigError::Foreign(Box::new(e))) + .and_then(|text| { + self.format + .parse(Some(&self.uri), &text) + .map_err(ConfigError::Foreign) + }) + .or_else(|res| { + if self.required { + Err(res) + } else { + Ok(Map::new()) + } + }) + } +} + +/// Main telemetry configuration container +#[derive(Debug, Serialize, Deserialize)] +pub struct TelemetryConfig { + /// The crate name `env!("CARGO_CRATE_NAME")` + pub crate_name: String, + /// The package version `env!("CARGO_PKG_VERSION")` + pub pkg_version: String, + /// OpenTelemetry Protocol (OTLP) specific settings + pub otlp: TelemetryOtlpConfig, + /// Logging-specific configuration + pub logging: TelemetryLoggingConfig, +} + +impl TelemetryConfig { + /// Create a new TelemetryConfig, usually with + /// ```rust, + /// # use teepot::config::TelemetryConfig; + /// let telemetry_config = TelemetryConfig::new( + /// env!("CARGO_CRATE_NAME").into(), + /// env!("CARGO_PKG_VERSION").into(), + /// ); + /// ``` + pub fn new(crate_name: String, pkg_version: String) -> Self { + Self { + crate_name, + pkg_version, + otlp: TelemetryOtlpConfig::default(), + logging: TelemetryLoggingConfig::default(), + } + } +} + +/// Configuration for logging behavior +#[derive(Debug, Serialize, Deserialize)] +pub struct TelemetryLoggingConfig { + /// The logging level (e.g., "debug", "info", "warn", "error") + pub level: String, + /// Whether to output logs in JSON format + pub json: bool, + /// Whether to output logs to console + pub console: bool, +} + +impl Default for TelemetryLoggingConfig { + fn default() -> Self { + Self { + level: "warn".into(), + json: false, + console: true, + } + } +} + +/// OpenTelemetry Protocol specific configuration +#[derive(Debug, Serialize, Deserialize)] +pub struct TelemetryOtlpConfig { + /// Controls whether OpenTelemetry Protocol (OTLP) export is enabled. + /// FIXME: has no effect right now + pub enable: bool, + /// The endpoint URL for the OpenTelemetry collector + pub endpoint: String, + /// The protocol to use for OTLP communication (e.g., "grpc", "http/protobuf") + pub protocol: String, +} + +impl Default for TelemetryOtlpConfig { + fn default() -> Self { + Self { + enable: true, + endpoint: "127.0.0.1:4317".to_string(), + protocol: "grpc".to_string(), + } + } +} + +fn protocol_from_string(protocol: &str) -> Result { + match protocol.to_lowercase().as_str() { + "http/protobuf" => Ok(opentelemetry_otlp::Protocol::HttpBinary), + "http/json" => Ok(opentelemetry_otlp::Protocol::HttpJson), + "grpc" => Ok(opentelemetry_otlp::Protocol::Grpc), + _ => Err(anyhow::anyhow!("Invalid protocol")), + } +} + +/// Loads configuration and sets up logging based on the provided configuration accessor +/// +/// # Type Parameters +/// * `S` - Configuration type that implements Default, Serialize, Deserialize, and Send +/// +/// # Arguments +/// * `get_telemetry_config` - Function to extract `TelemetryConfig` from type `S` +/// +/// # Returns +/// * `Result` - The loaded configuration or error +pub async fn load_config_with_telemetry< + S: Default + Serialize + for<'a> Deserialize<'a> + Send + 'static, +>( + get_telemetry_config: fn(&S) -> &TelemetryConfig, +) -> Result> { + with_console_logging(async move { + trace!("Loading config"); + // Load configuration + let config = ConfigBuilder::::default() + .add_source(Config::try_from(&S::default())?) + .add_source(File::with_name("config/default").required(false)) + .add_source( + config::Environment::with_prefix("APP") + .try_parsing(true) + .separator("_"), + ) + .add_async_source(HttpSource { + uri: DEFAULT_INSTANCE_METADATA_BASE_URL.into(), + format: FileFormat::Json, + required: false, + }) + .build() + .await? + .try_deserialize::()?; + + // Initialize telemetry + init_telemetry(get_telemetry_config(&config))?; + Ok::>(config) + }) + .await +} + +fn create_console_format_layer() -> tracing_subscriber::fmt::Layer +where + S: for<'a> tracing::Subscriber + Send + Sync + 'static, +{ + tracing_subscriber::fmt::layer() + .with_target(true) + .with_thread_ids(true) + .with_line_number(true) + .with_file(true) + .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE) + .with_ansi(true) + .with_thread_names(true) +} + +async fn with_console_logging(fut: F) -> F::Output +where + F: std::future::Future + Send + 'static, + F::Output: Send + 'static, +{ + // Configure console logging + let fmt_layer = create_console_format_layer(); + + let subs = tracing_subscriber::registry() + .with(EnvFilter::new("trace")) + .with(fmt_layer.pretty()); + + let _default = tracing::subscriber::set_default(subs); + + tracing_futures::WithSubscriber::with_current_subscriber(fut).await +} + +fn init_telemetry( + config: &TelemetryConfig, +) -> Result<(), Box> { + std::env::set_var( + "RUST_LOG", + std::env::var("RUST_LOG").unwrap_or_else(|_| { + format!( + // `otel::tracing` should be a level info to emit opentelemetry trace & span + // `otel::setup` set to debug to log detected resources, configuration read and infered + "warn,{crate_name}={log_level},teepot={log_level},otel::tracing=error,otel=error", + log_level = config.logging.level, + crate_name = config.crate_name + ) + }), + ); + // Configure OpenTelemetry resource + let resource = Resource::from_schema_url( + [ + KeyValue::new(SERVICE_NAME, config.crate_name.clone()), + KeyValue::new(SERVICE_VERSION, config.pkg_version.clone()), + ], + SCHEMA_URL, + ); + + // Configure the OTLP exporter + let logging_provider = LoggerProvider::builder() + .with_batch_exporter( + opentelemetry_otlp::LogExporter::builder() + .with_tonic() + .with_endpoint(&config.otlp.endpoint) + .with_protocol(protocol_from_string(&config.otlp.protocol)?) + .build()?, + runtime::Tokio, + ) + .with_resource(resource) + .build(); + + let logging_layer = + opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge::new(&logging_provider); + + // Configure console logging + let fmt_layer = create_console_format_layer(); + + // Combine layers based on configuration + let subscriber = tracing_subscriber::registry() + .with(EnvFilter::from_default_env()) + .with(logging_layer); + + // Add console logging if enabled + if config.logging.console { + // Optionally configure JSON logging + if config.logging.json { + subscriber.with(fmt_layer.json()).init() + } else { + subscriber.with(fmt_layer.pretty()).init() + } + } else { + subscriber.init() + }; + + Ok(()) +} diff --git a/crates/teepot/src/lib.rs b/crates/teepot/src/lib.rs index 8f73489..1860eb3 100644 --- a/crates/teepot/src/lib.rs +++ b/crates/teepot/src/lib.rs @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright (c) 2023-2024 Matter Labs +// Copyright (c) 2023-2025 Matter Labs //! Helper functions to verify Intel SGX enclaves and other TEEs. @@ -7,6 +7,7 @@ #![deny(clippy::all)] pub mod client; +pub mod config; pub mod ethereum; pub mod json; pub mod log; diff --git a/packages/container-tdx-test/default.nix b/packages/container-tdx-test/default.nix new file mode 100644 index 0000000..e12c646 --- /dev/null +++ b/packages/container-tdx-test/default.nix @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 Matter Labs +{ lib +, openssl +, curl +, dockerTools +, buildEnv +, teepot +, nixsgx +}: +dockerTools.buildLayeredImage { + name = "tdx-test"; + + config.Entrypoint = [ "${teepot.teepot.tdx_test}/bin/tdx-test-dcap" ]; + config.Env = [ + "SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt" + ]; + + contents = buildEnv { + name = "image-root"; + + paths = with dockerTools;[ + teepot.teepot.tdx_test + openssl.out + curl.out + nixsgx.sgx-dcap.quote_verify + nixsgx.sgx-dcap.default_qpl + usrBinEnv + binSh + caCertificates + fakeNss + ]; + pathsToLink = [ "/bin" "/lib" "/etc" "/share" ]; + }; +} diff --git a/packages/container-test-tdx/default.nix b/packages/container-test-tdx/default.nix deleted file mode 100644 index fd32c49..0000000 --- a/packages/container-test-tdx/default.nix +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# Copyright (c) 2024 Matter Labs -{ dockerTools -, buildEnv -, teepot -}: -dockerTools.buildLayeredImage { - name = "test-tdx"; - - config.Entrypoint = [ "${teepot.teepot.google_metadata}/bin/google-metadata" ]; - config.Env = [ "LD_LIBRARY_PATH=/lib" ]; - contents = buildEnv { - name = "image-root"; - - paths = with dockerTools;[ - teepot.teepot.google_metadata - usrBinEnv - binSh - caCertificates - fakeNss - ]; - pathsToLink = [ "/bin" "/lib" "/etc" "/share" ]; - }; -} diff --git a/packages/teepot/default.nix b/packages/teepot/default.nix index 1ab7982..9aee174 100644 --- a/packages/teepot/default.nix +++ b/packages/teepot/default.nix @@ -19,7 +19,7 @@ teepotCrate.craneLib.buildPackage ( outputs = [ "out" - "google_metadata" + "tdx_test" "rtmr_calc" "sha384_extend" "tdx_extend"