diff --git a/.github/workflows/build-dockers.yml b/.github/workflows/build-dockers.yml index 6757fb0..68c6fad 100644 --- a/.github/workflows/build-dockers.yml +++ b/.github/workflows/build-dockers.yml @@ -21,3 +21,11 @@ jobs: LATEST_TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" TAGS="-t ${IMAGE_TAG} -t ${LATEST_TAG}" docker buildx build --platform='linux/amd64,linux/arm64' $TAGS --push . + IMAGE_TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}_enclave_arm64:${{ github.ref_name }}" + LATEST_TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}_enclave_arm64:latest" + TAGS="-t ${IMAGE_TAG} -t ${LATEST_TAG}" + docker build -f enclave/arm64.Dockerfile $TAGS --push . + IMAGE_TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}_enclave_amd64:${{ github.ref_name }}" + LATEST_TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}_enclave_amd64:latest" + TAGS="-t ${IMAGE_TAG} -t ${LATEST_TAG}" + docker build -f enclave/amd64.Dockerfile $TAGS --push . diff --git a/Cargo.lock b/Cargo.lock index fe9db28..c52f8e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,21 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "anyhow" version = "1.0.86" @@ -340,21 +325,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets 0.52.6", -] - [[package]] name = "ciborium" version = "0.2.2" @@ -388,12 +358,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - [[package]] name = "cpufeatures" version = "0.2.12" @@ -979,29 +943,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "ic-cdk" version = "0.14.0" @@ -1123,11 +1064,7 @@ dependencies = [ name = "idempotent-proxy-types" version = "1.1.1" dependencies = [ - "anyhow", - "async-trait", - "axum", "base64", - "chrono", "ciborium", "ed25519-dalek", "hex-conservative", @@ -2494,15 +2431,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.48.0" diff --git a/README.md b/README.md index 8107360..e884438 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,20 @@ cargo run -p idempotent-proxy-server https://docs.marlin.org/user-guides/oyster/instances/quickstart/build +The following steps should be run in AWS Nitro-based instances. + +Spin up a new Docker container based on our nitro-cli image and mount the current directory using: +```bash +sudo docker run --rm --privileged --name nitro-cli -v `pwd`:/mnt/my-server marlinorg/nitro-cli +``` + +In a new terminal, run ```bash -docker build -f enclave/arm64.Dockerfile -t enclave:latest . +cd /mnt/my-server +sudo docker exec -it nitro-cli sh +# or docker pull enclave image +docker build -f enclave/arm64.Dockerfile -t enclave_arm64:latest . +nitro-cli build-enclave --docker-uri enclave_arm64:latest --output-file enclave_arm64.eif ``` ### Running as Cloudflare Worker diff --git a/src/idempotent-proxy-server/src/cache/memory.rs b/src/idempotent-proxy-server/src/cache/memory.rs index e0e7af9..93517af 100644 --- a/src/idempotent-proxy-server/src/cache/memory.rs +++ b/src/idempotent-proxy-server/src/cache/memory.rs @@ -1,4 +1,5 @@ use async_trait::async_trait; +use idempotent_proxy_types::unix_ms; use std::{ collections::{ hash_map::{Entry, HashMap}, @@ -6,7 +7,6 @@ use std::{ }, sync::Arc, }; -use structured_logger::unix_ms; use tokio::{ sync::RwLock, time::{sleep, Duration}, @@ -39,7 +39,6 @@ impl MemoryCacher { kv.remove(&key); } - () }) } } diff --git a/src/idempotent-proxy-types/Cargo.toml b/src/idempotent-proxy-types/Cargo.toml index a2ba0e3..89a77b9 100644 --- a/src/idempotent-proxy-types/Cargo.toml +++ b/src/idempotent-proxy-types/Cargo.toml @@ -13,21 +13,17 @@ license.workspace = true [lib] [dependencies] -axum = { workspace = true } http = { workspace = true } -async-trait = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } serde_bytes = { workspace = true } ciborium = { workspace = true } -anyhow = { workspace = true } k256 = { workspace = true } ed25519-dalek = { workspace = true } -base64 = { workspace = true } sha3 = { workspace = true } -chrono = { workspace = true } [dev-dependencies] +base64 = { workspace = true } rand_core = "0.6" hex = { package = "hex-conservative", version = "0.2", default-features = false, features = [ "alloc", diff --git a/src/idempotent-proxy-types/src/auth.rs b/src/idempotent-proxy-types/src/auth.rs index 3e4f818..8d11d0a 100644 --- a/src/idempotent-proxy-types/src/auth.rs +++ b/src/idempotent-proxy-types/src/auth.rs @@ -8,6 +8,8 @@ use serde::{Deserialize, Serialize}; use serde_bytes::ByteBuf; use sha3::{Digest, Sha3_256}; +use crate::unix_ms; + const PERMITTED_DRIFT: u64 = 10; // seconds // Token format: [expire_at in seconds, agent, signature] @@ -27,7 +29,7 @@ pub fn ed25519_sign(key: &ed25519_dalek::SigningKey, expire_at: u64, agent: Stri pub fn ed25519_verify(keys: &[ed25519_dalek::VerifyingKey], data: &[u8]) -> Result { let token: Token = from_reader(data).map_err(|_err| "failed to decode CBOR data")?; - if token.0 + PERMITTED_DRIFT < chrono::Utc::now().timestamp() as u64 { + if token.0 + PERMITTED_DRIFT < unix_ms() / 1000 { return Err("token expired".to_string()); } let sig = ed25519_dalek::Signature::from_slice(token.2.as_slice()) @@ -60,7 +62,7 @@ pub fn ecdsa_sign(key: &ecdsa::SigningKey, expire_at: u64, agent: String) -> Vec // Secp256k1 pub fn ecdsa_verify(keys: &[ecdsa::VerifyingKey], data: &[u8]) -> Result { let token: Token = from_reader(data).map_err(|_err| "failed to decode CBOR data")?; - if token.0 + PERMITTED_DRIFT < chrono::Utc::now().timestamp() as u64 { + if token.0 + PERMITTED_DRIFT < unix_ms() / 1000 { return Err("token expired".to_string()); } let sig = ecdsa::Signature::try_from(token.2.as_slice()) @@ -98,7 +100,7 @@ mod test { let signing_key: ed25519_dalek::SigningKey = ed25519_dalek::SigningKey::from_bytes(&secret_key); let agent = "alice".to_string(); - let expire_at = chrono::Utc::now().timestamp() as u64 + 3600; + let expire_at = unix_ms() / 1000 + 3600; let signed = super::ed25519_sign(&signing_key, expire_at, agent.clone()); let token = super::ed25519_verify(&[signing_key.verifying_key()], &signed).unwrap(); assert_eq!(token.0, expire_at); @@ -110,7 +112,7 @@ mod test { fn test_secp256k1_token() { let signing_key = ecdsa::SigningKey::random(&mut OsRng); let agent = "alice".to_string(); - let expire_at = chrono::Utc::now().timestamp() as u64 + 3600; + let expire_at = unix_ms() / 1000 + 3600; let signed = super::ecdsa_sign(&signing_key, expire_at, agent.clone()); let token = super::ecdsa_verify(&[ecdsa::VerifyingKey::from(&signing_key)], &signed).unwrap(); diff --git a/src/idempotent-proxy-types/src/lib.rs b/src/idempotent-proxy-types/src/lib.rs index 5228ecb..3d40336 100644 --- a/src/idempotent-proxy-types/src/lib.rs +++ b/src/idempotent-proxy-types/src/lib.rs @@ -1,4 +1,5 @@ use http::header::HeaderName; +use std::time::{SystemTime, UNIX_EPOCH}; pub mod auth; @@ -13,3 +14,11 @@ pub static HEADER_RESPONSE_HEADERS: HeaderName = HeaderName::from_static("respon pub fn err_string(err: impl std::fmt::Display) -> String { err.to_string() } + +/// Returns the current unix timestamp in milliseconds. +pub fn unix_ms() -> u64 { + let ts = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("system time before Unix epoch"); + ts.as_millis() as u64 +}