Closed Jonas-Metzger closed 3 years ago
Also answering for: https://github.com/aws/aws-nitro-enclaves-sdk-c/issues/57.
We don't currently have a python API for this, specifically, although pyo3 could be a neat solution to it, but we haven't looked into it so far.
In broad, to get an Attestation Document containing any form of user data, the user needs to create a request for it:
fn main() {
let nsm_fd = nsm_driver::nsm_init();
let public_key = serde_bytes::ByteBuf::from("my super secret key");
let hello = serde_bytes::ByteBuf::from("hello, world!");
let request = nsm_io::Request::Attestation {
public_key: Some(public_key),
user_data: Some(hello),
nonce: None,
};
let response = nsm_driver::nsm_process_request(nsm_fd, request);
println!("{:?}", response);
nsm_driver::nsm_exit(nsm_fd);
}
Another solution for python, but less elegant, would be create an executable that python can call using the already available libraries.
Thanks a lot @petreeftime ! Sorry for spamming, I wasn't sure about the right place to ask.
I'm not familiar with Rust at all, so I'll try to code up some way to call your fn main()
from python. I hope you'll bear with me while I figure out what to do.
Compared to pyo3, it actually seems easier for me to just code a minimal working attest.rs
containing your fn main()
and use runner to run it with a simple shell command (e.g. from python's subprocess
). The readme at
https://github.com/aws/aws-nitro-enclaves-samples/tree/main/vsock_sample/py
describes a specific container setup process for the enclave that suffices to run the vsock example. Let's say attest.rs
is inside that container. Are there any use
statements I need to put inside attest.rs
before fn main()
? Do I need to explicitly install aws-nitro-enclaves-nsm-api
somehow, or maybe nsm_driver
serde_bytes
and nsm_io
manually? Or does Nitro make sure that these tools are all installed inside every .eif
automatically?
If you have the time, it would be super helpful if you could also tell me how the fn main()
snippet has to change to make it
The enclave itself doesn't provide any software, and all the software comes from the person building the enclave, via the build-enclave command. The default tooling provides a Linux kernel, and init process + parameters for it and whatever the user specifies as the Docker image to use, so in this case all the user software comes from that Docker image.
With regards to how one would build the Rust code, I'll look to adding a sample to the samples repo, but in short: you first need to declare the dependency in the Cargo.toml
file of the project:
[dependencies]
serde_bytes = "0.11"
[dependencies.nsm-driver]
git = "https://github.com/aws/aws-nitro-enclaves-nsm-api.git"
rev = "4f468c4"
[dependencies.nsm-io]
git = "https://github.com/aws/aws-nitro-enclaves-nsm-api.git"
rev = "4f468c4"
The use inside the files just helps with keeping the lines short, and doesn't have an impact on usage otherwise. For example, the code above can be "compressed" to:
use nsm_io::Request;
use serde_bytes::ByteBuf;
fn main() {
let nsm_fd = nsm_driver::nsm_init();
let public_key = ByteBuf::from("my super secret key");
let hello = ByteBuf::from("hello, world!");
let request = Request::Attestation {
public_key: Some(public_key),
user_data: Some(hello),
nonce: None,
};
let response = nsm_driver::nsm_process_request(nsm_fd, request);
println!("{:?}", response);
nsm_driver::nsm_exit(nsm_fd);
}
The other important aspect here is the docker file. I will come back with an example that builds both a Rust binary and includes it in a Docker container container with Python.
Thank you very much for the clarification and the little Rust 101 @petreeftime ! I think I'm beginning to understand what's going on. A minimal docker example that builds such a Rust binary and contains client-server communication in python similar to the vsock-sample would be awesome. Should then be straightforward to call this binary from python's subprocess
(no pyo3
or runner
needed), right?
Thank you so much for taking the time to do this! That will be way more efficient than me trying to get these basics to work via trial and error. Keep me posted!
Hi @petreeftime , I'd love to start building off the docker container example you offered to share. What's your guess for when you'll be able to share it?
I'm having trouble understanding how I would have to set up the container to get it to build a working rust executable inside the .eif
Hi @Jonas-Metzger, please check the open PR which implements what @petreeftime suggested above. The PR is still work in progress, however this should get you started.
Thank you so much for your efforts! I'll try it out asap!
Thank you again @dblanzeanu and @petreeftime , the att-doc-retriever-sample works for me now, and I was able to play around and modify the python and rust code a bit, allowing python to insert custom values into the public_key
and user_data
fields of the attestation request. I was also able to decode the resulting attestation document using cbor2.loads(bytes(integer_list))
, where integer_list
are the bytes of the attestation document, which I currently manually collect by copying from the console output.
In @dblanzeanu 's example, what's the best way to collect the vsock data stream into a single string in python, and close the connection after all the transmission is completed?
Thanks a lot for your support!
Found a solution here: https://stackoverflow.com/a/17668009.
Everything works now. Thanks!
Hi @petreeftime and other contributors!
You have this neat sample showing how to communicate with the enclave ("server") from the EC2 instance ("client"), in python:
https://github.com/aws/aws-nitro-enclaves-samples/blob/main/vsock_sample/py/vsock-sample.py
I'm wondering how to get the enclave/server side of the code to request the attestation document (to then share it with the client). Is there a CLI command that would obtain it from the Nitro Hypervisor? Otherwise, I assume I'd have to use a python-rust bindings utility like pyo3. Which is the right rust function to point it to?
Am I correct in assuming that I will be able to include arbitrary data (in particular: a public key manually generated by the python code running inside the enclave) into the attestation document by including it in the attestation request call?
Thanks a lot!