diff --git a/.github/workflows/snp.yml b/.github/workflows/snp.yml
new file mode 100644
index 0000000..4b1dcc1
--- /dev/null
+++ b/.github/workflows/snp.yml
@@ -0,0 +1,59 @@
+name: "SNP End-to-End Tests"
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+ types: [opened, synchronize, reopened, ready_for_review]
+
+
+defaults:
+ run:
+ shell: bash
+
+# Cancel previous running actions for the same PR
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
+
+jobs:
+ run-functions:
+ if: github.event.pull_request.draft == false
+ runs-on: [self-hosted, snp]
+ steps:
+ - name: "Check out the code"
+ uses: actions/checkout@v4
+
+ - name: "Run SNP setup"
+ run: ./scripts/accli_wrapper.sh dev cvm setup --clean
+
+ - name: "Start attestation service in the background"
+ run: ./scripts/accli_wrapper.sh attestation-service run --background --certs-dir ./certs --force-clean-certs --rebuild
+
+ # Fetch latest version of the code in the cVM.
+ - name: "Fetch code in the cVM"
+ run: |
+ # Work-out current branch name.
+ if [ -n "${{ github.head_ref }}" ]; then
+ BRANCH=${{ github.head_ref }}
+ else
+ BRANCH=${GITHUB_REF_NAME}
+ fi
+ ./scripts/accli_wrapper.sh dev cvm run -- \
+ "git fetch origin $BRANCH && git checkout $BRANCH && git reset --hard origin/$BRANCH"
+
+ # Build SNP applications and embed the attestation service's certificate.
+ - name: "Build SNP applications"
+ run: ./scripts/accli_wrapper.sh applications build --clean --as-cert-path ./certs/cert.pem --in-cvm
+
+ - name: "Run supported SNP applications"
+ run: |
+ # First get the external IP so that we can reach the attestation-service from the cVM.
+ AS_URL=$(./scripts/accli_wrapper.sh attestation-service health --url "https://0.0.0.0:8443" --cert-path ./certs/cert.pem 2>&1 \
+ | grep "attestation service is healthy and reachable on:" | awk '{print $NF}')
+ echo "Got AS URL: ${AS_URL}"
+ ./scripts/accli_wrapper.sh applications run function escrow-xput --as-url ${AS_URL} --as-cert-path ./certs/cert.pem --in-cvm
+
+ - name: "Stop attestation service in the background"
+ run: ./scripts/accli_wrapper.sh attestation-service stop
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 8124e9f..fe14a32 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -36,6 +36,8 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@v4
+ - name: "Install APT deps"
+ run: ./scripts/apt.sh
- name: "Run Rust unit tests"
run: |
source ./scripts/workon.sh
@@ -52,9 +54,9 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@v4
+ - name: "Install APT deps"
+ run: ./scripts/apt.sh
- name: "Build C++ code"
- shell: bash
run: ./scripts/accli_wrapper.sh accless build --clean
- name: "Run C++ unit tests"
- shell: bash
run: ./scripts/accli_wrapper.sh accless test
diff --git a/.gitignore b/.gitignore
index 159a377..2e6ee87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,5 +16,8 @@ datasets*
agent-plans
# Default path for auto-generated TLS certificates.
-config/certs
-config/test-certs
+config/attestation-service/certs
+config/attestation-service/test-certs
+
+# Path for attestation service PID.
+config/attestation-service/PID
diff --git a/Cargo.lock b/Cargo.lock
index d2a03b2..12d9056 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,7 +4,7 @@ version = 4
[[package]]
name = "abe4"
-version = "0.8.1"
+version = "0.9.0"
dependencies = [
"anyhow",
"ark-bls12-381",
@@ -22,7 +22,7 @@ dependencies = [
[[package]]
name = "accless-finra-cloudevent-handler"
-version = "0.8.1"
+version = "0.9.0"
dependencies = [
"cloudevents-sdk",
"futures-util",
@@ -38,7 +38,7 @@ dependencies = [
[[package]]
name = "accless-ml-inference-cloudevent-handler"
-version = "0.8.1"
+version = "0.9.0"
dependencies = [
"cloudevents-sdk",
"futures-util",
@@ -54,7 +54,7 @@ dependencies = [
[[package]]
name = "accless-ml-training-cloudevent-handler"
-version = "0.8.1"
+version = "0.9.0"
dependencies = [
"cloudevents-sdk",
"futures-util",
@@ -70,7 +70,7 @@ dependencies = [
[[package]]
name = "accless-word-count-cloudevent-handler"
-version = "0.8.1"
+version = "0.9.0"
dependencies = [
"cloudevents-sdk",
"futures-util",
@@ -86,7 +86,7 @@ dependencies = [
[[package]]
name = "accli"
-version = "0.8.1"
+version = "0.9.0"
dependencies = [
"anyhow",
"base64 0.22.1",
@@ -101,6 +101,7 @@ dependencies = [
"indicatif",
"log",
"minio",
+ "nix 0.28.0",
"plotters",
"rand 0.8.5",
"regex",
@@ -447,7 +448,7 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]]
name = "attestation-service"
-version = "0.8.1"
+version = "0.9.0"
dependencies = [
"abe4",
"accli",
@@ -475,11 +476,11 @@ dependencies = [
"serde",
"serde_json",
"serial_test",
+ "sev",
"snpguest",
"tempfile",
"tokio",
"tokio-rustls",
- "ureq",
]
[[package]]
@@ -537,7 +538,7 @@ dependencies = [
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
- "sync_wrapper 1.0.2",
+ "sync_wrapper",
"tokio",
"tower",
"tower-layer",
@@ -560,7 +561,7 @@ dependencies = [
"mime",
"pin-project-lite",
"rustversion",
- "sync_wrapper 1.0.2",
+ "sync_wrapper",
"tower-layer",
"tower-service",
"tracing",
@@ -572,6 +573,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
+[[package]]
+name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
[[package]]
name = "base64"
version = "0.21.7"
@@ -625,6 +632,26 @@ version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c821a6e124197eb56d907ccc2188eab1038fb919c914f47976e64dd8dbc855d1"
+[[package]]
+name = "bitfield"
+version = "0.19.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21ba6517c6b0f2bf08be60e187ab64b038438f22dd755614d8fe4d4098c46419"
+dependencies = [
+ "bitfield-macros",
+]
+
+[[package]]
+name = "bitfield-macros"
+version = "0.19.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f48d6ace212fdf1b45fd6b566bb40808415344642b76c3224c07c8df9da81e97"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.108",
+]
+
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -678,7 +705,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce"
dependencies = [
"borsh-derive",
- "cfg_aliases",
+ "cfg_aliases 0.2.1",
]
[[package]]
@@ -751,6 +778,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+[[package]]
+name = "cfg_aliases"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
+
[[package]]
name = "cfg_aliases"
version = "0.2.1"
@@ -876,12 +909,6 @@ dependencies = [
"cc",
]
-[[package]]
-name = "codicon"
-version = "3.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12170080f3533d6f09a19f81596f836854d0fa4867dc32c8172b8474b4e9de61"
-
[[package]]
name = "color_quant"
version = "1.1.0"
@@ -1277,34 +1304,13 @@ dependencies = [
"subtle",
]
-[[package]]
-name = "dirs"
-version = "5.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
-dependencies = [
- "dirs-sys 0.4.1",
-]
-
[[package]]
name = "dirs"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
dependencies = [
- "dirs-sys 0.5.0",
-]
-
-[[package]]
-name = "dirs-sys"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
-dependencies = [
- "libc",
- "option-ext",
- "redox_users 0.4.6",
- "windows-sys 0.48.0",
+ "dirs-sys",
]
[[package]]
@@ -1315,7 +1321,7 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
dependencies = [
"libc",
"option-ext",
- "redox_users 0.5.2",
+ "redox_users",
"windows-sys 0.61.2",
]
@@ -1546,7 +1552,7 @@ dependencies = [
"core-foundation",
"core-graphics",
"core-text",
- "dirs 6.0.0",
+ "dirs",
"dwrote",
"float-ord",
"freetype-sys",
@@ -2109,7 +2115,7 @@ dependencies = [
"tokio",
"tokio-rustls",
"tower-service",
- "webpki-roots 1.0.3",
+ "webpki-roots",
]
[[package]]
@@ -2160,7 +2166,7 @@ dependencies = [
"percent-encoding",
"pin-project-lite",
"socket2 0.6.1",
- "system-configuration 0.6.1",
+ "system-configuration",
"tokio",
"tower-service",
"tracing",
@@ -2370,7 +2376,7 @@ dependencies = [
"socket2 0.5.10",
"widestring",
"windows-sys 0.48.0",
- "winreg",
+ "winreg 0.50.0",
]
[[package]]
@@ -2497,7 +2503,7 @@ dependencies = [
[[package]]
name = "jwt"
-version = "0.8.1"
+version = "0.9.0"
dependencies = [
"base64 0.22.1",
"rsa",
@@ -2770,6 +2776,18 @@ dependencies = [
"memoffset",
]
+[[package]]
+name = "nix"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
+dependencies = [
+ "bitflags 2.10.0",
+ "cfg-if",
+ "cfg_aliases 0.1.1",
+ "libc",
+]
+
[[package]]
name = "nom"
version = "7.1.3"
@@ -2792,11 +2810,10 @@ dependencies = [
[[package]]
name = "num-bigint-dig"
-version = "0.8.4"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
+checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7"
dependencies = [
- "byteorder",
"lazy_static",
"libm",
"num-integer",
@@ -3300,7 +3317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
dependencies = [
"bytes",
- "cfg_aliases",
+ "cfg_aliases 0.2.1",
"pin-project-lite",
"quinn-proto",
"quinn-udp",
@@ -3340,7 +3357,7 @@ version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
dependencies = [
- "cfg_aliases",
+ "cfg_aliases 0.2.1",
"libc",
"once_cell",
"socket2 0.6.1",
@@ -3446,17 +3463,6 @@ dependencies = [
"bitflags 2.10.0",
]
-[[package]]
-name = "redox_users"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
-dependencies = [
- "getrandom 0.2.16",
- "libredox",
- "thiserror 1.0.69",
-]
-
[[package]]
name = "redox_users"
version = "0.5.2"
@@ -3499,11 +3505,11 @@ checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
[[package]]
name = "reqwest"
-version = "0.11.27"
+version = "0.11.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
+checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb"
dependencies = [
- "base64 0.21.7",
+ "base64 0.13.1",
"bytes",
"encoding_rs",
"futures-core",
@@ -3515,26 +3521,22 @@ dependencies = [
"hyper-tls 0.5.0",
"ipnet",
"js-sys",
+ "lazy_static",
"log",
"mime",
"native-tls",
- "once_cell",
"percent-encoding",
"pin-project-lite",
- "rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
- "sync_wrapper 0.1.2",
- "system-configuration 0.5.1",
"tokio",
"tokio-native-tls",
- "tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
- "winreg",
+ "winreg 0.10.1",
]
[[package]]
@@ -3571,7 +3573,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
- "sync_wrapper 1.0.2",
+ "sync_wrapper",
"tokio",
"tokio-native-tls",
"tokio-rustls",
@@ -3584,7 +3586,7 @@ dependencies = [
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
- "webpki-roots 1.0.3",
+ "webpki-roots",
]
[[package]]
@@ -3853,15 +3855,6 @@ dependencies = [
"serde_derive",
]
-[[package]]
-name = "serde-big-array"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f"
-dependencies = [
- "serde",
-]
-
[[package]]
name = "serde-human-bytes"
version = "0.1.1"
@@ -3872,16 +3865,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "serde_bytes"
-version = "0.11.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8"
-dependencies = [
- "serde",
- "serde_core",
-]
-
[[package]]
name = "serde_core"
version = "1.0.228"
@@ -3979,26 +3962,21 @@ dependencies = [
[[package]]
name = "sev"
-version = "5.0.0"
+version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b06afe5192a43814047ea0072f4935f830a1de3c8cb43b56c90ae6918468b94d"
+checksum = "c2ff74d7e7d1cc172f3a45adec74fbeee928d71df095b85aaaf66eb84e1e31e6"
dependencies = [
"base64 0.22.1",
- "bincode",
- "bitfield",
- "bitflags 1.3.2",
+ "bitfield 0.19.4",
+ "bitflags 2.10.0",
"byteorder",
- "codicon",
- "dirs 5.0.1",
+ "dirs",
"hex",
"iocuddle",
"lazy_static",
"libc",
"openssl",
"rdrand",
- "serde",
- "serde-big-array",
- "serde_bytes",
"static_assertions",
"uuid",
]
@@ -4037,7 +4015,7 @@ version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb"
dependencies = [
- "dirs 6.0.0",
+ "dirs",
]
[[package]]
@@ -4118,24 +4096,24 @@ dependencies = [
[[package]]
name = "snpguest"
-version = "0.8.3"
-source = "git+https://github.com/faasm/snpguest.git#d3697058d4981db9c8dca1f6321cab3ca5cb029d"
+version = "0.10.0"
+source = "git+https://github.com/faasm/snpguest.git#cb4dcf19403edd0b3be458f82df7d72c89e6a0e6"
dependencies = [
"anyhow",
"asn1-rs",
"base64 0.22.1",
"bincode",
- "bitfield",
+ "bitfield 0.15.0",
"clap",
"clap-num",
"colorful",
"env_logger 0.10.2",
"hex",
"msru",
- "nix",
+ "nix 0.23.2",
"openssl",
"rand 0.8.5",
- "reqwest 0.11.27",
+ "reqwest 0.11.10",
"serde",
"sev",
"x509-parser",
@@ -4223,12 +4201,6 @@ dependencies = [
"unicode-ident",
]
-[[package]]
-name = "sync_wrapper"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
-
[[package]]
name = "sync_wrapper"
version = "1.0.2"
@@ -4249,17 +4221,6 @@ dependencies = [
"syn 2.0.108",
]
-[[package]]
-name = "system-configuration"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
-dependencies = [
- "bitflags 1.3.2",
- "core-foundation",
- "system-configuration-sys 0.5.0",
-]
-
[[package]]
name = "system-configuration"
version = "0.6.1"
@@ -4268,17 +4229,7 @@ checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.10.0",
"core-foundation",
- "system-configuration-sys 0.6.0",
-]
-
-[[package]]
-name = "system-configuration-sys"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
-dependencies = [
- "core-foundation-sys",
- "libc",
+ "system-configuration-sys",
]
[[package]]
@@ -4318,7 +4269,7 @@ dependencies = [
[[package]]
name = "template-graph"
-version = "0.8.1"
+version = "0.9.0"
dependencies = [
"abe4",
"anyhow",
@@ -4559,7 +4510,7 @@ dependencies = [
"futures-core",
"futures-util",
"pin-project-lite",
- "sync_wrapper 1.0.2",
+ "sync_wrapper",
"tokio",
"tower-layer",
"tower-service",
@@ -4711,24 +4662,6 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
-[[package]]
-name = "ureq"
-version = "2.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
-dependencies = [
- "base64 0.22.1",
- "flate2",
- "log",
- "once_cell",
- "rustls",
- "rustls-pki-types",
- "serde",
- "serde_json",
- "url",
- "webpki-roots 0.26.11",
-]
-
[[package]]
name = "url"
version = "2.5.7"
@@ -4957,15 +4890,6 @@ dependencies = [
"wasm-bindgen",
]
-[[package]]
-name = "webpki-roots"
-version = "0.26.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
-dependencies = [
- "webpki-roots 1.0.3",
-]
-
[[package]]
name = "webpki-roots"
version = "1.0.3"
@@ -5352,6 +5276,15 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "winreg"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
+dependencies = [
+ "winapi",
+]
+
[[package]]
name = "winreg"
version = "0.50.0"
diff --git a/Cargo.toml b/Cargo.toml
index 649a1d3..d84e9e0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@ members = [
]
[workspace.package]
-version = "0.8.1"
+version = "0.9.0"
license-file = "LICENSE"
authors = ["Large-Scale Data & Systems Group - Imperial College London"]
edition = "2024"
@@ -65,6 +65,7 @@ serde = { version = "^1.0", features = ["derive"] }
serde_json = "^1.0"
serde_with = "3.8.1"
serde_yaml = "0.9"
+sev = "7.1.0"
shellexpand = "^3.1"
sha2 = "0.10"
shell-words = "^1.1.0"
@@ -72,8 +73,8 @@ snpguest = { git = "https://github.com/faasm/snpguest.git" }
subtle = "2.6.1"
tempfile = "3.23.0"
tokio = { version = "1" }
+nix = "0.28"
tokio-rustls = "0.26.2"
-ureq = { version = "2" }
uuid = { version = "^1.3" }
walkdir = "2"
warp = "^0.3"
diff --git a/GEMINI.md b/GEMINI.md
index 0e0bc1b..e989544 100644
--- a/GEMINI.md
+++ b/GEMINI.md
@@ -84,10 +84,10 @@ optional `--help` flag: `./scrips/accli_wrapper.sh --help`.
error handling through the `anyhow` crate.
- For each new method, make sure to add extensive documentation in the following format:
```rust
+///
///
-/// # Description
-///
-///
+///
+///
///
/// # Arguments
///
@@ -102,6 +102,13 @@ optional `--help` flag: `./scrips/accli_wrapper.sh --help`.
///
///
+
+
+
diff --git a/VERSION b/VERSION
index 6f4eebd..ac39a10 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.8.1
+0.9.0
diff --git a/accless/CMakeLists.txt b/accless/CMakeLists.txt
index db8914c..cc99387 100644
--- a/accless/CMakeLists.txt
+++ b/accless/CMakeLists.txt
@@ -65,12 +65,24 @@ add_subdirectory(./libs/jwt/cpp-bindings)
add_subdirectory(./libs/abe4/cpp-bindings)
add_subdirectory(./libs/base64)
-set(ACCLESS_COMMON_HEADERS
- ${ACCLESS_ROOT}/include
- ${ACCLESS_ROOT}/libs/jwt/cpp-bindings
- ${ACCLESS_ROOT}/libs/abe4/cpp-bindings
- ${ACCLESS_ROOT}/libs/base64
-)
+# Create a directory for namespaced headers. This allows including accless
+# headers with a namespace prefix, e.g. #include "accless/attestation/attestation.h"
+set(ACCLESS_INCLUDE_PREFIX_DIR ${CMAKE_CURRENT_BINARY_DIR}/include_prefix)
+set(ACCLESS_INCLUDE_PREFIX_DIR ${ACCLESS_INCLUDE_PREFIX_DIR} PARENT_SCOPE)
+if (EXISTS ${ACCLESS_INCLUDE_PREFIX_DIR})
+ file(REMOVE_RECURSE ${ACCLESS_INCLUDE_PREFIX_DIR})
+endif()
+file(MAKE_DIRECTORY ${ACCLESS_INCLUDE_PREFIX_DIR}/accless)
+# Create symlinks for common libraries
+set(ACCLESS_LIBS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs)
+file(CREATE_LINK ${ACCLESS_LIBS_DIR}/jwt/cpp-bindings ${ACCLESS_INCLUDE_PREFIX_DIR}/accless/jwt SYMBOLIC)
+file(CREATE_LINK ${ACCLESS_LIBS_DIR}/abe4/cpp-bindings ${ACCLESS_INCLUDE_PREFIX_DIR}/accless/abe4 SYMBOLIC)
+file(CREATE_LINK ${ACCLESS_LIBS_DIR}/base64 ${ACCLESS_INCLUDE_PREFIX_DIR}/accless/base64 SYMBOLIC)
+# Symlink individual headers from accless/include
+file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/include/accless.h ${ACCLESS_INCLUDE_PREFIX_DIR}/accless/accless.h SYMBOLIC)
+file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/include/dag.h ${ACCLESS_INCLUDE_PREFIX_DIR}/accless/dag.h SYMBOLIC)
+file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/include/utils.h ${ACCLESS_INCLUDE_PREFIX_DIR}/accless/utils.h SYMBOLIC)
+
set(ACCLESS_COMMON_LIBRARIES accless::jwt accless::abe4 accless::base64)
if (CMAKE_SYSTEM_NAME STREQUAL "WASI")
@@ -96,18 +108,20 @@ else ()
add_subdirectory(./libs/attestation)
add_subdirectory(./libs/s3)
+ # Create symlinks for native-only libraries
+ file(CREATE_LINK ${ACCLESS_LIBS_DIR}/attestation ${ACCLESS_INCLUDE_PREFIX_DIR}/accless/attestation SYMBOLIC)
+ file(CREATE_LINK ${ACCLESS_LIBS_DIR}/s3 ${ACCLESS_INCLUDE_PREFIX_DIR}/accless/s3 SYMBOLIC)
+
set(ACCLESS_LIBRARIES
accless::s3
accless::attestation
# We use the installed curl as part of azure-cvm-attestation
/usr/local/attestationcurl/lib/libcurl.a
)
- set(ACCLESS_HEADERS ${ACCLESS_ROOT}/libs)
endif()
target_include_directories(${CMAKE_PROJECT_TARGET} PUBLIC
- ${ACCLESS_COMMON_HEADERS}
- ${ACCLESS_HEADERS}
+ ${ACCLESS_INCLUDE_PREFIX_DIR}
)
target_link_libraries(${CMAKE_PROJECT_TARGET} PUBLIC
${ACCLESS_COMMON_LIBRARIES}
diff --git a/accless/libs/attestation/mock.h b/accless/libs/attestation/mock.h
index e8fadfa..4cb5ff6 100644
--- a/accless/libs/attestation/mock.h
+++ b/accless/libs/attestation/mock.h
@@ -10,7 +10,7 @@ namespace accless::attestation::mock {
const std::array MOCK_QUOTE_MAGIC_SNP = {'A', 'C', 'C', 'L',
'S', 'N', 'P', '!'};
-const std::string MOCK_GID = "baz";
+const std::string MOCK_GID = "MOCKGID";
const std::string MOCK_WORKFLOW_ID = "foo";
const std::string MOCK_NODE_ID = "bar";
diff --git a/accless/libs/attestation/snp.cpp b/accless/libs/attestation/snp.cpp
index 03bbfc0..d6a8cb1 100644
--- a/accless/libs/attestation/snp.cpp
+++ b/accless/libs/attestation/snp.cpp
@@ -181,6 +181,7 @@ std::vector getReport(std::array reportData) {
return getSnpReportFromDev(reportData, std::nullopt);
}
+ // FIXME: enable report data for AzCVM use-case.
if (std::filesystem::exists("/dev/tpmrm0")) {
return getSnpReportFromTPM();
}
@@ -204,7 +205,9 @@ std::string getAttestationJwt(const std::string &gid,
// Fetch HW attestation report and include the auxiliary report data in
// the signature.
std::vector report;
+ // FIXME: consider making this check more reliable.
if (gid == mock::MOCK_GID) {
+ std::cout << "accless(att): WARNING: mocking SNP quote" << std::endl;
report = accless::attestation::mock::buildMockQuote(
reportDataVec, mock::MOCK_QUOTE_MAGIC_SNP);
} else {
diff --git a/accless/src/accless.cpp b/accless/src/accless.cpp
index a064cd9..a23eefa 100644
--- a/accless/src/accless.cpp
+++ b/accless/src/accless.cpp
@@ -1,15 +1,15 @@
-#include "accless.h"
-#include "base64.h"
-#include "dag.h"
-#include "jwt.h"
-#include "utils.h"
+#include "accless/accless.h"
+#include "accless/base64/base64.h"
+#include "accless/dag.h"
+#include "accless/jwt/jwt.h"
+#include "accless/utils.h"
#ifdef __faasm
// Faasm includes
#include
#else
-#include "attestation/attestation.h"
-#include "s3/S3Wrapper.hpp"
+#include "accless/attestation/attestation.h"
+#include "accless/s3/S3Wrapper.hpp"
#endif
#include
diff --git a/accless/src/dag.cpp b/accless/src/dag.cpp
index 980abb6..773850d 100644
--- a/accless/src/dag.cpp
+++ b/accless/src/dag.cpp
@@ -1,4 +1,4 @@
-#include "dag.h"
+#include "accless/dag.h"
#include
#include
diff --git a/accless/src/utils.cpp b/accless/src/utils.cpp
index 169612d..1f008e8 100644
--- a/accless/src/utils.cpp
+++ b/accless/src/utils.cpp
@@ -1,4 +1,4 @@
-#include "utils.h"
+#include "accless/utils.h"
#ifdef __faasm
extern "C" {
diff --git a/accli/Cargo.toml b/accli/Cargo.toml
index e344676..a90669f 100644
--- a/accli/Cargo.toml
+++ b/accli/Cargo.toml
@@ -28,6 +28,7 @@ futures-util.workspace = true
hex.workspace = true
indicatif.workspace = true
log.workspace = true
+nix = { workspace = true, features = ["signal", "process"] }
minio.workspace = true
plotters.workspace = true
rand.workspace = true
diff --git a/accli/src/main.rs b/accli/src/main.rs
index a5bb16f..3b75b19 100644
--- a/accli/src/main.rs
+++ b/accli/src/main.rs
@@ -2,8 +2,10 @@ use crate::{
env::Env,
tasks::{
accless::Accless,
- applications::Applications,
+ applications::{self, Applications},
+ attestation_service::AttestationService,
azure::Azure,
+ cvm::{self, Component, parse_host_guest_path},
dev::Dev,
docker::{Docker, DockerContainer},
experiments::{E2eSubScommand, Experiment, UbenchSubCommand},
@@ -11,7 +13,8 @@ use crate::{
},
};
use clap::{Parser, Subcommand};
-use std::{collections::HashMap, process};
+use env_logger::Builder;
+use std::{collections::HashMap, path::PathBuf, process};
pub mod attestation_service;
pub mod env;
@@ -49,11 +52,6 @@ enum Command {
#[command(subcommand)]
dev_command: DevCommand,
},
- /// Build and push different docker images
- Docker {
- #[command(subcommand)]
- docker_command: DockerCommand,
- },
/// Run evaluation experiments and plot results
Experiment {
#[command(subcommand)]
@@ -64,6 +62,52 @@ enum Command {
#[command(subcommand)]
s3_command: S3Command,
},
+ /// Build and run the attestation service
+ AttestationService {
+ #[command(subcommand)]
+ attestation_service_command: AttestationServiceCommand,
+ },
+}
+
+#[derive(Debug, Subcommand)]
+enum AttestationServiceCommand {
+ /// Build the attestation service
+ Build {},
+ /// Run the attestation service
+ Run {
+ /// Directory where to look-for and store TLS certificates.
+ #[arg(long)]
+ certs_dir: Option,
+ /// Port to bind the server to.
+ #[arg(long)]
+ port: Option,
+ /// URL to fetch SGX platform collateral information.
+ #[arg(long)]
+ sgx_pccs_url: Option,
+ /// Whether to overwrite the existing TLS certificates (if any).
+ #[arg(long)]
+ force_clean_certs: bool,
+ /// Run the attestation service in mock mode, skipping quote
+ /// verification.
+ #[arg(long, default_value_t = false)]
+ mock: bool,
+ /// Rebuild the attestation service before running.
+ #[arg(long, default_value_t = false)]
+ rebuild: bool,
+ /// Run the attestation service in the background, storing its PID.
+ #[arg(long, default_value_t = false)]
+ background: bool,
+ },
+ /// Stop a running attestation service (started with --background).
+ Stop {},
+ Health {
+ /// URL of the attestation service
+ #[arg(long)]
+ url: Option,
+ /// Path to the attestation service's public certificate PEM file
+ #[arg(long)]
+ cert_path: Option,
+ },
}
#[derive(Debug, Subcommand)]
@@ -99,6 +143,46 @@ enum DevCommand {
#[arg(long)]
force: bool,
},
+ /// Build and run commands in the work-on container image
+ Docker {
+ #[command(subcommand)]
+ docker_command: DockerCommand,
+ },
+ /// Build and run commands in an SNP-enabled cVM (requires SNP hardware)
+ Cvm {
+ #[command(subcommand)]
+ cvm_command: CvmCommand,
+ },
+}
+
+#[derive(Debug, Subcommand)]
+enum CvmCommand {
+ /// Run a command inside the cVM.
+ Run {
+ #[arg(last = true)]
+ cmd: Vec,
+ /// Optional: SCP files into the cVM.
+ /// Specify as :. Can be repeated.
+ #[arg(long, value_name = "HOST_PATH:GUEST_PATH", value_parser = parse_host_guest_path)]
+ scp_file: Vec<(PathBuf, PathBuf)>,
+ /// Set the working directory inside the container
+ #[arg(long)]
+ cwd: Option,
+ },
+ /// Configure the cVM image by building and installing the different
+ /// components.
+ Setup {
+ #[arg(long)]
+ clean: bool,
+ #[arg(long)]
+ component: Option,
+ },
+ /// Get an interactive shell inside the cVM.
+ Cli {
+ /// Set the working directory inside the container
+ #[arg(long)]
+ cwd: Option,
+ },
}
#[derive(Debug, Subcommand)]
@@ -106,7 +190,7 @@ enum DockerCommand {
/// Build one of Accless' docker containers. Run build --help to see the
/// possibe options
Build {
- #[arg(short, long, num_args = 1.., value_name = "CTR_NAME")]
+ /// Container image to build.
ctr: Vec,
#[arg(long)]
push: bool,
@@ -292,30 +376,45 @@ enum AcclessCommand {
enum ApplicationsCommand {
/// Build the Accless applications
Build {
+ /// Force a clean build.
#[arg(long)]
clean: bool,
+ /// Force a debug build.
#[arg(long)]
debug: bool,
+ /// Path to the attestation service's public certificate PEM file.
+ #[arg(long)]
+ as_cert_path: Option,
+ /// Whether to build the application inside a cVM.
+ #[arg(long, default_value_t = false)]
+ in_cvm: bool,
+ },
+ /// Run one of the Accless applications
+ Run {
+ /// Type of the application to run
+ app_type: applications::ApplicationType,
+ /// Name of the application to run
+ app_name: applications::ApplicationName,
+ /// Whether to run the application inside a cVM.
+ #[arg(long, default_value_t = false)]
+ in_cvm: bool,
+ /// URL of the attestation service to contact.
+ #[arg(long)]
+ as_url: Option,
+ /// Path to the attestation service's public certificate PEM file.
#[arg(long)]
- cert_path: Option,
+ as_cert_path: Option,
},
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
- let cli = Cli::parse();
-
- // Initialize the logger based on the debug flag
- if cli.debug {
- env_logger::Builder::from_default_env()
- .filter_level(log::LevelFilter::Debug)
- .init();
- } else {
- env_logger::Builder::from_default_env()
- .filter_level(log::LevelFilter::Info)
- .init();
- }
+ // Initialize the logger.
+ let env = env_logger::Env::default().filter_or("RUST_LOG", "info");
+ let mut builder = Builder::from_env(env);
+ builder.init();
+ let cli = Cli::parse();
match &cli.task {
Command::Accless { accless_command } => match accless_command {
AcclessCommand::Build { clean, debug } => {
@@ -331,9 +430,25 @@ async fn main() -> anyhow::Result<()> {
ApplicationsCommand::Build {
clean,
debug,
- cert_path,
+ as_cert_path,
+ in_cvm,
} => {
- Applications::build(*clean, *debug, cert_path.as_deref(), false)?;
+ Applications::build(*clean, *debug, as_cert_path.clone(), false, *in_cvm)?;
+ }
+ ApplicationsCommand::Run {
+ app_type,
+ app_name,
+ in_cvm,
+ as_url,
+ as_cert_path,
+ } => {
+ Applications::run(
+ app_type.clone(),
+ app_name.clone(),
+ *in_cvm,
+ as_url.clone(),
+ as_cert_path.clone(),
+ )?;
}
},
Command::Dev { dev_command } => match dev_command {
@@ -355,36 +470,52 @@ async fn main() -> anyhow::Result<()> {
DevCommand::Tag { force } => {
Dev::tag_code(*force)?;
}
- },
- Command::Docker { docker_command } => match docker_command {
- DockerCommand::Build { ctr, push, nocache } => {
- for c in ctr {
- Docker::build(c, *push, *nocache);
+ DevCommand::Docker { docker_command } => match docker_command {
+ DockerCommand::Build { ctr, push, nocache } => {
+ for c in ctr {
+ Docker::build(c, *push, *nocache);
+ }
}
- }
- DockerCommand::BuildAll { push, nocache } => {
- for ctr in DockerContainer::iter_variants() {
- // Do not push the base build image
- if *ctr == DockerContainer::Experiments {
- Docker::build(ctr, false, *nocache);
- } else {
- Docker::build(ctr, *push, *nocache);
+ DockerCommand::BuildAll { push, nocache } => {
+ for ctr in DockerContainer::iter_variants() {
+ // Do not push the base build image
+ if *ctr == DockerContainer::Experiments {
+ Docker::build(ctr, false, *nocache);
+ } else {
+ Docker::build(ctr, *push, *nocache);
+ }
}
}
- }
- DockerCommand::Cli { net } => {
- Docker::cli(*net)?;
- }
- DockerCommand::Run {
- cmd,
- mount,
- cwd,
- env,
- net,
- capture_output,
- } => {
- Docker::run(cmd, *mount, cwd.as_deref(), env, *net, *capture_output)?;
- }
+ DockerCommand::Cli { net } => {
+ Docker::cli(*net)?;
+ }
+ DockerCommand::Run {
+ cmd,
+ mount,
+ cwd,
+ env,
+ net,
+ capture_output,
+ } => {
+ Docker::run(cmd, *mount, cwd.as_deref(), env, *net, *capture_output)?;
+ }
+ },
+ DevCommand::Cvm { cvm_command } => match cvm_command {
+ CvmCommand::Run { cmd, scp_file, cwd } => {
+ let scp_files_option = if scp_file.is_empty() {
+ None
+ } else {
+ Some(scp_file.as_slice())
+ };
+ cvm::run(cmd, scp_files_option, cwd.as_ref())?;
+ }
+ CvmCommand::Setup { clean, component } => {
+ cvm::build(*clean, *component)?;
+ }
+ CvmCommand::Cli { cwd } => {
+ cvm::cli(cwd.as_ref())?;
+ }
+ },
},
Command::Experiment {
experiments_command: exp,
@@ -757,6 +888,38 @@ async fn main() -> anyhow::Result<()> {
}
},
},
+ Command::AttestationService {
+ attestation_service_command,
+ } => match attestation_service_command {
+ AttestationServiceCommand::Build {} => {
+ AttestationService::build()?;
+ }
+ AttestationServiceCommand::Run {
+ certs_dir,
+ port,
+ sgx_pccs_url,
+ force_clean_certs,
+ mock,
+ rebuild,
+ background,
+ } => {
+ AttestationService::run(
+ certs_dir.as_deref(),
+ *port,
+ sgx_pccs_url.as_deref(),
+ *force_clean_certs,
+ *mock,
+ *rebuild,
+ *background,
+ )?;
+ }
+ AttestationServiceCommand::Stop {} => {
+ AttestationService::stop()?;
+ }
+ AttestationServiceCommand::Health { url, cert_path } => {
+ AttestationService::health(url.clone(), cert_path.clone()).await?;
+ }
+ },
}
Ok(())
diff --git a/accli/src/tasks/applications.rs b/accli/src/tasks/applications.rs
index cfc6b54..e7ced13 100644
--- a/accli/src/tasks/applications.rs
+++ b/accli/src/tasks/applications.rs
@@ -1,5 +1,112 @@
-use crate::tasks::docker::{DOCKER_ACCLESS_CODE_MOUNT_DIR, Docker};
-use std::path::Path;
+use crate::tasks::{
+ attestation_service, cvm,
+ docker::{DOCKER_ACCLESS_CODE_MOUNT_DIR, Docker},
+};
+use anyhow::Result;
+use clap::ValueEnum;
+use log::error;
+use std::{
+ fmt::{Display, Formatter, Result as FmtResult},
+ path::{Path, PathBuf},
+ str::FromStr,
+};
+
+#[derive(Clone, Debug, ValueEnum)]
+pub enum ApplicationType {
+ Function,
+ Test,
+}
+
+impl Display for ApplicationType {
+ fn fmt(&self, f: &mut Formatter) -> FmtResult {
+ match self {
+ ApplicationType::Function => write!(f, "function"),
+ ApplicationType::Test => write!(f, "test"),
+ }
+ }
+}
+
+impl FromStr for ApplicationType {
+ type Err = anyhow::Error;
+
+ fn from_str(s: &str) -> Result {
+ match s {
+ "function" => Ok(ApplicationType::Function),
+ _ => anyhow::bail!("Invalid ApplicationType: {}", s),
+ }
+ }
+}
+
+#[derive(Clone, Debug, ValueEnum)]
+pub enum ApplicationName {
+ #[value(name = "att-client-sgx")]
+ AttClientSgx,
+ #[value(name = "att-client-snp")]
+ AttClientSnp,
+ #[value(name = "escrow-xput")]
+ EscrowXput,
+}
+
+impl Display for ApplicationName {
+ fn fmt(&self, f: &mut Formatter) -> FmtResult {
+ match self {
+ ApplicationName::AttClientSgx => write!(f, "att-client-sgx"),
+ ApplicationName::AttClientSnp => write!(f, "att-client-snp"),
+ ApplicationName::EscrowXput => write!(f, "escrow-xput"),
+ }
+ }
+}
+
+impl FromStr for ApplicationName {
+ type Err = anyhow::Error;
+
+ fn from_str(s: &str) -> Result {
+ match s {
+ "att-client-sgx" => Ok(ApplicationName::AttClientSgx),
+ "att-client-snp" => Ok(ApplicationName::AttClientSnp),
+ "escrow-xput" => Ok(ApplicationName::EscrowXput),
+ _ => anyhow::bail!("Invalid Function: {}", s),
+ }
+ }
+}
+
+fn host_cert_path_to_target_path(
+ as_cert_path: &Path,
+ in_cvm: bool,
+ in_docker: bool,
+) -> Result {
+ if in_cvm & in_docker {
+ let reason = "cannot set in_cvm and in_docker";
+ error!("as_cert_path_arg_to_real_path(): {reason}");
+ anyhow::bail!(reason);
+ }
+
+ if !as_cert_path.exists() {
+ let reason = format!(
+ "as certificate path does not exist (path={})",
+ as_cert_path.display()
+ );
+ error!("as_cert_path_arg_to_real_path(): {reason}");
+ anyhow::bail!(reason);
+ }
+
+ if !as_cert_path.is_file() {
+ let reason = format!(
+ "as certificate path does not point to a file (path={})",
+ as_cert_path.display()
+ );
+ error!("as_cert_path_arg_to_real_path(): {reason}");
+ anyhow::bail!(reason);
+ }
+
+ if in_docker {
+ Ok(Docker::remap_to_docker_path(as_cert_path)?)
+ } else if in_cvm {
+ Ok(cvm::remap_to_cvm_path(as_cert_path)?)
+ } else {
+ Ok(as_cert_path.to_path_buf())
+ }
+}
#[derive(Debug)]
pub struct Applications {}
@@ -8,28 +115,134 @@ impl Applications {
pub fn build(
clean: bool,
debug: bool,
- cert_path: Option<&str>,
+ as_cert_path: Option,
capture_output: bool,
- ) -> anyhow::Result