[demos] Refactor and update the Azure attestation demos

This commit is contained in:
Zheng, Qi 2022-06-17 17:14:48 +08:00 committed by volcano
parent 153b8c6454
commit dd295c1391
17 changed files with 1307 additions and 13 deletions

@ -0,0 +1,44 @@
## Sample code for doing Microsoft Azure Attestation in Occlum
Two examples are provided for reference. All are running in Occlum Enclave environment and verified on Azure confidential VM.
### MAA format json file generation demo [`maa_json`](./maa_json)
This demo is programming in C, covering the SGX quote generation and format the quote to MAA format json file. It doesn't cover the attestation part.
### MAA attestation flow demo [`maa_attestation`](./maa_attestation)
This demo is programming in RUST, based on the Azure provided [`REST APIs`](https://docs.microsoft.com/en-us/rest/api/attestation/). It provides steps to do SGX quote generation and attestation.
## Prerequisites
### Platform
An Azure confidential VM. Users could follow the [`guide`](https://docs.microsoft.com/en-us/azure/confidential-computing/quick-create-portal) to create one.
### Container
Start the Occlum latest docker container image for the demo in Azure confidential VM. Follow the [guide](https://github.com/occlum/occlum#how-to-use) or just try below command.
```
sudo docker run --rm -it \
--device /dev/sgx/enclave --device /dev/sgx/provision \
--name occlum-dev occlum/occlum:0.27.3-ubuntu20.04 bash
```
### PCK caching service
The Occlum docker container image assuming the Intel PCK caching service for DCAP remote attestation in default. But Azure has an Azure DCAP library instead, details please refer to the [`link`](https://docs.microsoft.com/en-us/azure/attestation/faq#how-can-a-verifier-obtain-the-collateral-for-sgx-attestation-supported-by-azure-attestation). To support the Occlum DCAP remote attestation running in Azure, below commands need to be executed in the Occlum docker container.
* Uninstall Intel default DCAP qpl library.
```
apt purge libsgx-dcap-default-qpl
```
* Install Azure DCAP library
```
echo "deb [arch=amd64] https://packages.microsoft.com/ubuntu/20.04/prod focal main" | sudo tee /etc/apt/sources.list.d/msprod.list
wget -qO - https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
apt update
apt install az-dcap-client
```

@ -0,0 +1,26 @@
## Sample code for doing Microsoft Azure Attestation in Occlum
This demo is programming in RUST, based on the Azure provided [`REST APIs`](https://docs.microsoft.com/en-us/rest/api/attestation/). It provides steps to do SGX quote generation and attestation.
* Build
1. Pull rust-sgx-sdk submodule which is the dependence of occlum dcap library.
```
# cd occlum
# git submodule update --init
```
2. Do the build with the [`scrit`](./build.sh).
```
# ./build.sh
```
* Run
```
# cd occlum_instance
# occlum run /bin/azure_att
```
If successful, it prints the Azure attestation token.

File diff suppressed because it is too large Load Diff

@ -0,0 +1,14 @@
[package]
name = "azure_att"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
base64 = "0.9"
sha2 = "0.9.5"
reqwest = { version = "0.11", features = ["blocking", "json"] }
occlum_dcap = { path = "../../../../../tools/toolchains/dcap_lib" }

@ -0,0 +1,82 @@
use serde_json::json;
use sha2::{Digest, Sha256};
use reqwest::blocking::Client;
use occlum_dcap::*;
pub const MAX_REPORT_DATA_SIZE: usize = 64;
fn maa_get_quote_base64(user_data: &[u8]) -> Result<String, &'static str> {
let mut dcap = DcapQuote::new();
let quote_size = dcap.get_quote_size();
let mut quote_buf: Vec<u8> = vec![0; quote_size as usize];
let mut report_data = sgx_report_data_t::default();
//fill in the report data array
let len = {
if user_data.len() > MAX_REPORT_DATA_SIZE {
MAX_REPORT_DATA_SIZE
} else {
user_data.len()
}
};
for i in 0..len {
report_data.d[i] = user_data[i];
}
dcap.generate_quote(quote_buf.as_mut_ptr(), &mut report_data).unwrap();
dcap.close();
let quote = base64::encode(&quote_buf);
Ok(quote)
}
pub fn maa_generate_json(user_data: &[u8]) -> Result<serde_json::Value, &'static str> {
let mut hasher = Sha256::new();
hasher.update(user_data);
let hash = hasher.finalize();
let quote_base64 = maa_get_quote_base64(&hash).unwrap();
// Format to MAA rest attestation API request body
// https://docs.microsoft.com/en-us/rest/api/attestation/attestation/attest-sgx-enclave#request-body
let mut maa_json: serde_json::Value = json!({
"quote": "0",
"runtimeData": {
"data": "0",
"dataType":"Binary"
}
});
*maa_json
.pointer_mut("/quote")
.unwrap() = serde_json::Value::String(quote_base64);
*maa_json
.pointer_mut("/runtimeData/data")
.unwrap() = serde_json::Value::String(base64::encode(&user_data));
Ok(maa_json.to_owned())
}
pub fn maa_attestation(url: String, request_body: serde_json::Value) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
let client = Client::new();
let att_url = format!("{}/attest/SgxEnclave?api-version=2020-10-01", url);
let resp = client.post(att_url)
.json(&request_body)
.send()?;
match resp.status() {
reqwest::StatusCode::OK => {
println!("success!");
Ok(resp.json().unwrap())
},
s => {
println!("Received response status: {:?}", s);
Err("maa attestation failed".into())
}
}
}

@ -0,0 +1,16 @@
use crate::maa::{maa_generate_json, maa_attestation};
pub mod maa;
const ATTESTATION_PROVIDER_URL: &str = "https://shareduks.uks.attest.azure.net";
fn main() {
// Sample enclave held data
let ehd: [u8;8] = [1,2,3,4,5,6,7,8];
let maa_json = maa_generate_json(&ehd).unwrap();
println!("maa json: {}", maa_json);
let response = maa_attestation(String::from(ATTESTATION_PROVIDER_URL), maa_json).unwrap();
println!("response: {}", response);
}

@ -0,0 +1,22 @@
includes:
- base.yaml
# dcap
targets:
# copy bins
- target: /bin
copy:
- files:
- ../azure_att/target/debug/azure_att
# copy libnss_files
- target: /opt/occlum/glibc/lib
copy:
- files:
- /opt/occlum/glibc/lib/libnss_files.so.2
- /opt/occlum/glibc/lib/libnss_dns.so.2
- /opt/occlum/glibc/lib/libresolv.so.2
# copy root CA
- target: /etc/ssl
copy:
- dirs:
- /etc/ssl/

@ -0,0 +1,31 @@
#!/bin/bash
set -e
BLUE='\033[1;34m'
NC='\033[0m'
INSTANCE_DIR="occlum_instance"
bomfile="../bom.yaml"
function build() {
pushd azure_att
cargo clean
cargo build
popd
rm -rf ${INSTANCE_DIR} && occlum new ${INSTANCE_DIR}
pushd ${INSTANCE_DIR}
rm -rf image
copy_bom -f $bomfile --root image --include-dir /opt/occlum/etc/template
new_json="$(jq '.resource_limits.user_space_size = "600MB" |
.resource_limits.kernel_space_heap_size = "128MB"' Occlum.json)" && \
echo "${new_json}" > Occlum.json
occlum build
popd
}
build

@ -3,19 +3,6 @@
### References
* Part of the sample code, specifically the part to generate MAA format json file, is derived from the [Sample code for Intel® SGX Attestation using Microsoft Azure Attestation service and Intel® SGX SDK for Linux OS](https://github.com/Azure-Samples/microsoft-azure-attestation/tree/master/intel.sdk.attest.sample)
## Prerequisites
- Platform: Intel SGX enabled platform with DCAP installed. Follow [DCAP
Quick Install
Guide](https://software.intel.com/content/www/us/en/develop/articles/intel-software-guard-extensions-data-center-attestation-primitives-quick-install-guide.html)
for the detailed installation procedure.
- Container: Start the Occlum latest docker container image for the demo. Follow
the [guide](https://github.com/occlum/occlum#how-to-use).
Remember to configure `/etc/sgx_default_qcnl.conf`
in the container according to your PCCS setting after running the docker image.
### Overview
The full Microsoft Azure Attestation flow includes generating a quote in an SGX enclave and then get it validated by the Microsoft [`Azure Attestation (MAA) service`](https://github.com/Azure-Samples/microsoft-azure-attestation).