Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a94a606
[accless] E: Make --as-cert-path Mandatory and Explicit
csegarragonz Dec 6, 2025
5fec7ba
[applications] F: Add Multi-As Test Application
csegarragonz Dec 6, 2025
a23daef
[accli] E: Adjustments Of Cert Dir Vars
csegarragonz Dec 6, 2025
c61341d
[as] E: Add Multi-As E2E Test
csegarragonz Dec 6, 2025
6cef144
[build] B: Update Cargo.lock
csegarragonz Dec 6, 2025
b6d314b
[ci] B: Fix Snp Invocation
csegarragonz Dec 6, 2025
cb975d1
[template-graph] E: Refine Error Messages
csegarragonz Dec 6, 2025
9f7b6c9
[applications] E: Make Escrow-Xpu Multi-As
csegarragonz Dec 6, 2025
5ddafbf
[config] F: Multi-As Accless Ansible Deployment
csegarragonz Dec 6, 2025
ae7b8bd
[applications] B: Fix Escrow-Xpu Args
csegarragonz Dec 6, 2025
8a67218
[accli] B: Expose --id To attestation-service run
csegarragonz Dec 6, 2025
7924ae7
[applications] B: PackFullKey With Single ID
csegarragonz Dec 6, 2025
ee80389
[accless] B: Check Sizes In packFullKey
csegarragonz Dec 6, 2025
3397aba
[accli] B: Correct Result File
csegarragonz Dec 6, 2025
5423a1b
[applications] B: Fix Result Write E-Xput
csegarragonz Dec 6, 2025
0e4c6dd
[accli] E: Add AcclessSingleAuth Baseline
csegarragonz Dec 6, 2025
19c1467
[accli] E: Refine Escrow Plots
csegarragonz Dec 6, 2025
b458a8c
[ci] B: Fix SNP GHA
csegarragonz Dec 6, 2025
1d5d885
[config] B: Remove FIXME
csegarragonz Dec 6, 2025
12aa63a
[accless] E: Thread-Local HTTP Clients
csegarragonz Dec 6, 2025
871246c
[as] E: Cache Partial USK
csegarragonz Dec 7, 2025
6267e46
[accli] E: Tweak Trustee Loop
csegarragonz Dec 7, 2025
6f4cfb1
[as] B: Run Code Formatting
csegarragonz Dec 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/snp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
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 hello-snp --as-url ${AS_URL} --as-cert-path ./certs/cert.pem --in-cvm
./scripts/accli_wrapper.sh applications run function hello-snp --backend cvm -- --as-url ${AS_URL} --as-cert-path ./certs/cert.pem

- name: "Stop attestation service in the background"
run: ./scripts/accli_wrapper.sh attestation-service stop
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ venv-bm
build-native
build-wasm

config/ansible/inventory/vms.ini
config/ansible/inventory*

datasets*

Expand Down
18 changes: 9 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions accless/libs/abe4/cpp-bindings/abe4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ unpackFullKey(const std::vector<uint8_t> &full_key_bytes) {
std::vector<uint8_t>
packFullKey(const std::vector<std::string> &authorities,
const std::vector<std::vector<uint8_t>> &partial_keys) {
if (authorities.size() != partial_keys.size()) {
std::cerr << "accless(abe4): packFullKey(): size mismatch between"
<< " authorities (" << authorities.size() << ") and partial"
<< "keys (" << partial_keys.size() << ")" << std::endl;
throw std::runtime_error(
"accless(abe4): size mismatch packing full key");
}

std::map<std::string, std::vector<uint8_t>> key_map;
for (size_t i = 0; i < authorities.size(); ++i) {
key_map[authorities[i]] = partial_keys[i];
Expand Down
1 change: 1 addition & 0 deletions accless/libs/attestation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ set(AZ_GUEST_ATTESTATION_INCLUDE_DIRS
add_library(${CMAKE_PROJECT_TARGET}
attestation.cpp
ec_keypair.cpp
http_client.cpp
mock.cpp
mock_sgx.cpp
mock_snp.cpp
Expand Down
127 changes: 11 additions & 116 deletions accless/libs/attestation/attestation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,86 +10,16 @@
#include <vector>

namespace accless::attestation {
// Must match the signature libcurl expects
static size_t curlWriteCallback(char *ptr, size_t size, size_t nmemb,
void *userdata) {
auto *out = static_cast<std::string *>(userdata);
if (!out) {
return 0; // tells libcurl this is an error
}

const size_t total = size * nmemb;
out->append(ptr, total);
return total;
}

// Helper for GET requests
static std::string http_get(const std::string &url,
const std::string &certPath) {
CURL *curl = curl_easy_init();
if (curl == nullptr) {
throw std::runtime_error("accless(att): failed to init curl");
}

char errbuf[CURL_ERROR_SIZE];
errbuf[0] = 0;

std::string response;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_CAINFO, certPath.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);

CURLcode res = curl_easy_perform(curl);
long status = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
curl_easy_cleanup(curl);

if (res != CURLE_OK) {
size_t len = strlen(errbuf);
fprintf(stderr, "accless(att): curl error: ");
if (len) {
fprintf(stderr, "%s%s", errbuf,
((errbuf[len - 1] != '\n') ? "\n" : ""));
} else {
fprintf(stderr, "%s\n", curl_easy_strerror(res));
}
throw std::runtime_error("accless(att): curl GET error");
}
if (status != 200) {
throw std::runtime_error(
"accless(att): GET request failed with status " +
std::to_string(status));
}

return response;
auto &client = http::getHttpClient(certPath);
return client.get(url);
}

// Get the URL of our own attestation service (**not** MAA)
std::string getAttestationServiceUrl() {
const char *val = std::getenv("ACCLESS_AS_URL");
if (val == nullptr) {
// This url uses https://ip:port
std::cerr << "accless(att): must set ACCLESS_AS_URL" << std::endl;
throw std::runtime_error("must set ACCLESS_AS_URL");
}
return std::string(val);
}

std::string getAttestationServiceCertPath() {
const char *val = std::getenv("ACCLESS_AS_CERT_PATH");
if (val == nullptr) {
std::cerr << "accless(att): must set ACCLESS_AS_CERT_PATH" << std::endl;
throw std::runtime_error("must set ACCLESS_AS_CERT_PATH");
}
return std::string(val);
}

std::pair<std::string, std::string> getAttestationServiceState() {
std::string asUrl = getAttestationServiceUrl();
std::string certPath = getAttestationServiceCertPath();
std::pair<std::string, std::string>
getAttestationServiceState(const std::string &asUrl,
const std::string &certPath) {
std::string url = asUrl + "/state";

std::string response = http_get(url, certPath);
Expand All @@ -102,48 +32,13 @@ std::pair<std::string, std::string> getAttestationServiceState() {

// endpoint must be one in `/verify-snp-report` or `/verify-sgx-report`.
// the report here is a JSON-string
std::string getJwtFromReport(const std::string &endpoint,
std::string getJwtFromReport(const std::string &asUrl,
const std::string &certPath,
const std::string &endpoint,
const std::string &reportJson) {
std::string jwt;

CURL *curl = curl_easy_init();
if (!curl) {
std::cerr << "accless: failed to initialize CURL" << std::endl;
throw std::runtime_error("curl error");
}

std::string asUrl = getAttestationServiceUrl() + endpoint;
std::string certPath = getAttestationServiceCertPath();
curl_easy_setopt(curl, CURLOPT_URL, asUrl.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_CAINFO, certPath.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, reportJson.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,
static_cast<long>(reportJson.size()));
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &jwt);

// TODO: set error-buffer in C++ format

struct curl_slist *headers = nullptr;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

// Perform the request
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "accless: CURL error: " << curl_easy_strerror(res)
<< std::endl;
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
throw std::runtime_error("curl error");
}

curl_easy_cleanup(curl);
curl_slist_free_all(headers);

return jwt;
std::string url = asUrl + endpoint;
auto &client = http::getHttpClient(certPath);
return client.postJson(url, reportJson);
}

std::string decryptJwt(const std::vector<uint8_t> &encrypted,
Expand Down
45 changes: 38 additions & 7 deletions accless/libs/attestation/attestation.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include <array>
#include <cstdint>
#include <curl/curl.h>
#include <memory>
#include <optional>
#include <string>
#include <vector>
Expand Down Expand Up @@ -42,10 +44,35 @@ std::string buildRequestBody(const std::string &quoteB64,
const std::string &nodeId);
} // namespace utils

// Helper methods around a thread-local, re-usable HTTP client.
namespace http {
class HttpClient {
public:
explicit HttpClient(const std::string &certPath);
~HttpClient();

std::string get(const std::string &url);
std::string postJson(const std::string &url, const std::string &body);

private:
CURL *curl_{nullptr};
std::string certPath_;
std::string response_;
char errbuf_[CURL_ERROR_SIZE];

void prepareRequest();
void perform();
};

HttpClient &getHttpClient(const std::string &certPath);
} // namespace http

// Mock helpers used in integration tests.
namespace mock {
std::string getMockSgxAttestationJwt();
std::string getMockSnpAttestationJwt();
std::string getMockSgxAttestationJwt(const std::string &asUrl,
const std::string &certPath);
std::string getMockSnpAttestationJwt(const std::string &asUrl,
const std::string &certPath);
} // namespace mock

// SNP-related methods
Expand Down Expand Up @@ -97,16 +124,20 @@ std::vector<uint8_t> getReport(std::array<uint8_t, 64> reportData);
* @param nodeId The node ID.
* @return A JSON string representing the JWT.
*/
std::string getAttestationJwt(const std::string &gid,
std::string getAttestationJwt(const std::string &asUrl,
const std::string &certPath,
const std::string &gid,
const std::string &workflowId,
const std::string &nodeId);
} // namespace snp

// Attestation-service methods
std::string getAttestationServiceUrl();
std::string getAttestationServiceCertPath();
std::pair<std::string, std::string> getAttestationServiceState();
std::string getJwtFromReport(const std::string &endpoint,
std::pair<std::string, std::string>
getAttestationServiceState(const std::string &asUrl,
const std::string &certPath);
std::string getJwtFromReport(const std::string &asUrl,
const std::string &certPath,
const std::string &endpoint,
const std::string &reportJson);
std::string decryptJwt(const std::vector<uint8_t> &encrypted,
const std::vector<uint8_t> &aesKey);
Expand Down
Loading
Loading