prettified scripts, docs and code

This commit is contained in:
Valentyn Faychuk 2024-08-24 06:11:39 +02:00
parent f2f2d545b3
commit ada83ece3a
Signed by: valy
GPG Key ID: F1AB995E20FEADC5
12 changed files with 137 additions and 144 deletions

@ -1,14 +1,32 @@
# Occlum SGX Remote Attestation integrated in TLS connection
Steps to test the project:
The MRSIGNER of the `example/signing_key.pem` is hardcoded in the enclave code:
```
occlum-cargo build --example server --features="occlum,actix-web"
strip -s target/x86_64-unknown-linux-musl/debug/examples/server
./build_server.sh
6871A831CED408CD99F0ED31587CC2B5C728C99D4A0A1ADF2F0C5574EBBB00DC
```
occlum-cargo build --example client --features="occlum,reqwest"
strip -s target/x86_64-unknown-linux-musl/debug/examples/client
You can generate your own signing key. Just use the following command:
```
openssl genrsa -3 -out signing_key.pem 3072
```
To get the MRSIGNER of the key, compile [this project](https://github.com/intel/sgx-ra-sample)
and use the following command:
```
./mrsigner signing_key.pem
```
## Running Examples
Before running make sure you have installed the Occlum and the SGX driver.
You should also have the Occlum Rust toolchain installed to get `occlum-cargo`.
To test the project just run client and server scripts in different terminals:
```
./build_server.sh
./build_client.sh
```

@ -1,12 +1,33 @@
#!/bin/bash
set -e
# initialize occlum workspace
rm -rf client_instance && mkdir client_instance && cd client_instance
SCRIPT=$0
EXAMPLE=$1
if [ $# -eq 0 ] || [ "$EXAMPLE" != "https" ] && [ "$EXAMPLE" != "grpcs" ]; then
echo "usage: $SCRIPT https|grpcs"
exit 1
fi
FEATURES=$(if [ "$EXAMPLE" == "https" ]; then echo "reqwest,occlum"; else echo "tonic,occlum"; fi)
occlum-cargo build --example mratls_"${EXAMPLE}"_client --features="$FEATURES"
strip target/x86_64-unknown-linux-musl/debug/examples/mratls_"${EXAMPLE}"_client
cat > client.yaml <<EOF
includes:
- base.yaml
targets:
- target: /bin
copy:
- files:
- ../target/x86_64-unknown-linux-musl/debug/examples/mratls_${EXAMPLE}_client
EOF
rm -rf client_instance && mkdir client_instance && cd client_instance
occlum init && rm -rf image
copy_bom -f ../client.yaml --root image --include-dir /opt/occlum/etc/template
occlum build
occlum build --sign-key ../examples/signing_key.pem --enable-edmm Y
occlum package --debug client.tar.gz
occlum run /bin/client

@ -1,12 +1,33 @@
#!/bin/bash
set -e
# initialize occlum workspace
rm -rf server_instance && mkdir server_instance && cd server_instance
SCRIPT=$0
EXAMPLE=$1
if [ $# -eq 0 ] || [ "$EXAMPLE" != "https" ] && [ "$EXAMPLE" != "grpcs" ]; then
echo "usage: $SCRIPT https|grpcs"
exit 1
fi
FEATURES=$(if [ "$EXAMPLE" == "https" ]; then echo "actix-web,occlum"; else echo "tonic,occlum"; fi)
occlum-cargo build --example mratls_"${EXAMPLE}"_server --features="$FEATURES"
strip target/x86_64-unknown-linux-musl/debug/examples/mratls_"${EXAMPLE}"_server
cat > server.yaml <<EOF
includes:
- base.yaml
targets:
- target: /bin
copy:
- files:
- ../target/x86_64-unknown-linux-musl/debug/examples/mratls_${EXAMPLE}_server
EOF
rm -rf server_instance && mkdir server_instance && cd server_instance
occlum init && rm -rf image
copy_bom -f ../server.yaml --root image --include-dir /opt/occlum/etc/template
occlum build
occlum build --sign-key ../examples/signing_key.pem --enable-edmm Y
occlum package --debug server.tar.gz
occlum run /bin/server

@ -4,4 +4,4 @@ targets:
- target: /bin
copy:
- files:
- ../target/x86_64-unknown-linux-musl/debug/examples/client
- ../target/x86_64-unknown-linux-musl/debug/examples/mratls_https_client

@ -12,7 +12,9 @@ use tokio_rustls::rustls::ClientConfig;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mrsigner_hex = "83D719E77DEACA1470F6BAF62A4D774303C899DB69020F9C70EE1DFC08C7CE9E";
env_logger::init_from_env(env_logger::Env::default().default_filter_or("trace"));
let mrsigner_hex = "6871A831CED408CD99F0ED31587CC2B5C728C99D4A0A1ADF2F0C5574EBBB00DC";
let mut mrsigner = [0u8; 32];
hex::decode_to_slice(mrsigner_hex, &mut mrsigner).expect("mrsigner decoding failed");
@ -39,16 +41,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.enable_http2()
.wrap_connector(s)
})
// Since our cert is signed with `example.com` but we actually want to connect
// to a local server we will override the Uri passed from the `HttpsConnector`
// and map it to the correct `Uri` that will connect us directly to the local server.
.map_request(|_| Uri::from_static("https://[::1]:50051"))
.service(http);
let client = hyper_util::client::legacy::Client::builder(TokioExecutor::new()).build(connector);
// Using `with_origin` will let the codegenerated client set the `scheme` and
// `authority` from the provided `Uri`.
let uri = Uri::from_static("https://example.com");
let mut client = EchoClient::with_origin(client, uri);

@ -23,7 +23,9 @@ use occlum_ratls::RaTlsConfigBuilder;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mrsigner_hex = "83D719E77DEACA1470F6BAF62A4D774303C899DB69020F9C70EE1DFC08C7CE9E";
env_logger::init_from_env(env_logger::Env::default().default_filter_or("trace"));
let mrsigner_hex = "6871A831CED408CD99F0ED31587CC2B5C728C99D4A0A1ADF2F0C5574EBBB00DC";
let mut mrsigner = [0u8; 32];
hex::decode_to_slice(mrsigner_hex, &mut mrsigner).expect("mrsigner decoding failed");

@ -5,18 +5,14 @@ use reqwest::ClientBuilder;
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init_from_env(env_logger::Env::default().default_filter_or("trace"));
let mrsigner_hex = "83D719E77DEACA1470F6BAF62A4D774303C899DB69020F9C70EE1DFC08C7CE9E";
let mrsigner_hex = "6871A831CED408CD99F0ED31587CC2B5C728C99D4A0A1ADF2F0C5574EBBB00DC";
let mut mrsigner = [0u8; 32];
hex::decode_to_slice(mrsigner_hex, &mut mrsigner)?;
let client = ClientBuilder::new()
.use_ratls(
RaTlsConfig::new().allow_instance_measurement(
InstanceMeasurement::new()
.with_mrsigners(vec![SGXMeasurement::new(mrsigner)])
.with_product_ids(vec![0]),
),
)
.use_ratls(RaTlsConfig::new().allow_instance_measurement(
InstanceMeasurement::new().with_mrsigners(vec![SGXMeasurement::new(mrsigner)]),
))
.build()?;
let res = client.get("https://127.0.0.1:8000").send().await?;
let data = res.text().await?;

@ -8,30 +8,23 @@ async fn index() -> String {
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init_from_env(env_logger::Env::default().default_filter_or("trace"));
let mrsigner_hex = "83D719E77DEACA1470F6BAF62A4D774303C899DB69020F9C70EE1DFC08C7CE9E";
let mrsigner_hex = "6871A831CED408CD99F0ED31587CC2B5C728C99D4A0A1ADF2F0C5574EBBB00DC";
let mut mrsigner = [0u8; 32];
hex::decode_to_slice(mrsigner_hex, &mut mrsigner).expect("mrsigner decoding failed");
hex::decode_to_slice(mrsigner_hex, &mut mrsigner)?;
HttpServer::new(|| App::new().service(index))
.bind_ratls(
SocketAddr::from(([127, 0, 0, 1], 8000)),
RaTlsConfig::new()
.allow_instance_measurement(
RaTlsConfig::new().allow_instance_measurement(
InstanceMeasurement::new().with_mrsigners(vec![SGXMeasurement::new(mrsigner)]),
)
.allow_instance_measurement(
InstanceMeasurement::new()
.with_mrenclaves(vec![
SGXMeasurement::new([0u8; 32]),
SGXMeasurement::new([1u8; 32]),
])
.with_product_ids(vec![0, 2]),
),
)
.unwrap()
.run()
.await
.await?;
Ok(())
}

40
examples/signing_key.pem Normal file

@ -0,0 +1,40 @@
-----BEGIN PRIVATE KEY-----
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
9DTouKJTmbNzsk375oViTww=
-----END PRIVATE KEY-----

@ -2,4 +2,5 @@
pub mod actix_web;
#[cfg(feature = "reqwest")]
pub mod reqwest;
//mod tonic_server;
#[cfg(feature = "tonic")]
pub mod tonic;

1
src/http/tonic.rs Normal file

@ -0,0 +1 @@

@ -1,97 +0,0 @@
use hyper::server::conn::http2::Builder;
use hyper_util::{
rt::{TokioExecutor, TokioIo},
service::TowerToHyperService,
};
use std::sync::Arc;
use tokio::net::TcpListener;
use tokio_rustls::{
rustls::{pki_types::CertificateDer, ServerConfig},
TlsAcceptor,
};
use tonic::transport::server::TcpIncoming;
use tonic::{body::boxed, service::Routes, Request, Response, Status};
use tower::ServiceExt;
use tower_http::ServiceBuilderExt;
use crate::{config::RaTlsConfig, RaTlsConfigBuilder};
fn bind_ratls(config: RaTlsConfig) -> Result<(), std::io::Error> {
let config = ServerConfig::from_ratls_config(config)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("{}", e)))?;
let tls_acceptor = TlsAcceptor::from(Arc::new(config));
// add tls_acceptor to the server
let incoming = TcpIncoming::new("[::1]:50051".parse().unwrap(), true, None)?;
let svc = tower::ServiceBuilder::new()
.add_extension(Arc::new(ConnInfo { addr, certificates }))
.service(svc);
self.bind_rustls_0_23(addr, config)
}
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("[::1]:50051").await?;
let tls_acceptor = TlsAcceptor::from(Arc::new(tls));
loop {
let (conn, addr) = match listener.accept().await {
Ok(incoming) => incoming,
Err(e) => {
eprintln!("Error accepting connection: {}", e);
continue;
}
};
let http = http.clone();
let tls_acceptor = tls_acceptor.clone();
let svc = svc.clone();
tokio::spawn(async move {
let mut certificates = Vec::new();
let conn = tls_acceptor
.accept_with(conn, |info| {
if let Some(certs) = info.peer_certificates() {
for cert in certs {
certificates.push(cert.clone());
}
}
})
.await
.unwrap();
http.serve_connection(
TokioIo::new(conn),
TowerToHyperService::new(svc.map_request(|req: http::Request<_>| req.map(boxed))),
)
.await
.unwrap();
});
}
}
#[derive(Debug)]
struct ConnInfo {
addr: std::net::SocketAddr,
certificates: Vec<CertificateDer<'static>>,
}
type EchoResult<T> = Result<Response<T>, Status>;
#[derive(Default)]
pub struct EchoServer {}
#[tonic::async_trait]
impl pb::echo_server::Echo for EchoServer {
async fn unary_echo(&self, request: Request<EchoRequest>) -> EchoResult<EchoResponse> {
let conn_info = request.extensions().get::<Arc<ConnInfo>>().unwrap();
println!(
"Got a request from: {:?} with certs: {:?}",
conn_info.addr, conn_info.certificates
);
let message = request.into_inner().message;
Ok(Response::new(EchoResponse { message }))
}
}