The attestation servers generate EC2 instance attestations using the AWS Nitro TPM and make them available using a HTTP server. They includes a public key that can be used to extend the chain of trust of the attestation by other applications. Intended to be run inside an EC2 instance with a TPM2-enabled AMI.
This project provides two attestation server variants:
- The standard variant which is to be used for most use cases reads the public key and user data from local files which are included in the attestation.
- The custom variant which expects callers to provide one or more of a public key, user data and nonce which are included in the attestation.
IMPORTANT: DO NOT expose the custom variant to external access or even untrusted enclave components unless you really know what you are doing, it is meant to be exposed purely to trusted applications inside the enclave as a way of accessing the NSM API over HTTP. Otherwise, it breaks the security model assumed by most enclaves since attestations can potentially be generated with public keys corresponding to private keys external to the enclave as well as with secrets which should never be exposed outside the enclave.
Prerequisites: tss2 libraries
cargo build --releaseReproducible builds can be done using Nix. The monorepo provides a Nix flake which includes this project and can be used to trigger builds:
nix build -v .#attestation.server.<variant>.<output>Supported variants:
standardcustom
Supported outputs:
default, cargo build outputservice, systemd service config
$ attestation-server --help
http server for handling attestation document requests
Usage: attestation-server [OPTIONS] --listen-addr <LISTEN_ADDR> --public-key <PUBLIC_KEY>
Options:
-l, --listen-addr <LISTEN_ADDR> listen address of the server (e.g. 127.0.0.1:1300)
-p, --public-key <PUBLIC_KEY> path to public key file (e.g. /app/id.pub)
--user-data <USER_DATA> path to user data file (e.g. /app/init-params-digest)
-h, --help Print help
-V, --version Print version
The attestation server exposes attestations through two endpoints which encode the attestation in one of two format - raw and hex. The raw format is a binary format with the raw bytes of the attestation. The hex format is the same attestation, simply hex encoded. Therefore, the raw format is about half the size of the other while the hex format is ASCII letters and numbers only.
It also provides a health endpoint for simple monitoring.
/attestation/raw
$ curl <ip:port>/attestation/raw -vs | xxd
* Trying <ip:port>...
* Connected to <ip> (<ip>) port <port> (#0)
> GET /attestation/raw HTTP/1.1
> Host: <ip:port>
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-type: application/octet-stream
< content-length: 4466
< date: Sat, 06 Apr 2024 07:28:41 GMT
<
{ [2682 bytes data]
* Connection #0 to host <ip> left intact
00000000: 8444 a101 3822 a059 1106 a969 6d6f 6475 .D..8".Y...imodu
00000010: 6c65 5f69 6478 2769 2d30 6631 6364 3737 le_idx'i-0f1cd77
00000020: 6433 3766 6438 6263 6339 2d65 6e63 3031 d37fd8bcc9-enc01
00000030: 3865 3761 6136 3165 3230 3430 6666 6664 8e7aa61e2040fffd
00000040: 6967 6573 7466 5348 4133 3834 6974 696d igestfSHA384itim
00000050: 6573 7461 6d70 1b00 0001 8eb2 4f18 9864 estamp......O..d
...
...
/attestation/hex
$ curl <ip:port>/attestation/hex -vs
* Trying <ip:port>...
* Connected to <ip> (<ip>) port <port> (#0)
> GET /attestation/hex HTTP/1.1
> Host: <ip:port>
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-type: text/plain; charset=utf-8
< content-length: 8932
< date: Sat, 06 Apr 2024 08:22:00 GMT
<
8444a1013822a0591106a9696d6f64756c655f69647827692d3066316364...
...
/health
$ curl <ip:port>/health -vs
* Trying <ip:port>...
* Connected to <ip> (<ip>) port <port> (#0)
> GET /attestation/hex HTTP/1.1
> Host: <ip:port>
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-length: 0
< date: Sat, 06 Apr 2024 08:22:00 GMT
<
$ attestation-server-custom --help
http server for handling attestation document requests
Usage: attestation-server-custom [OPTIONS]
Options:
-l, --listen-addr <LISTEN_ADDR> listen address of the server [default: 127.0.0.1:1350]
-h, --help Print help
-V, --version Print version
The attestation server exposes attestations through two endpoints which encode the attestation in one of two format - raw and hex. The raw format is a binary format with the raw bytes of the attestation. The hex format is the same attestation, simply hex encoded. Therefore, the raw format is about half the size of the other while the hex format is ASCII letters and numbers only.
Both endpoints accept query parameters which can be used to set the public key, user data and nonce in the attestation document.
/attestation/raw
public_key: Optional, hex encoded public key without the0xprefix that is included in thepublic_keyfield of the attestation after being decoded into raw bytesuser_data: Optional, hex encoded user data without the0xprefix that is included in theuser_datafield of the attestation after being decoded into raw bytesnonce: Optional, hex encoded nonce without the0xprefix that is included in thenoncefield of the attestation after being decoded into raw bytes
While all query parameters are optional, any useful attestation will likely include at least the public key to extend the chain of trust.
$ curl '<ip:port>/attestation/raw?public_key=<public_key>&user_data=<user_data>&nonce=<nonce>' -vs | xxd
* Trying <ip:port>...
* Connected to <ip> (<ip>) port <port> (#0)
> GET /attestation/raw?public_key=<public_key>&user_data=<user_data>&nonce=<nonce> HTTP/1.1
> Host: <ip:port>
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-type: application/octet-stream
< content-length: 4466
< date: Sat, 06 Apr 2024 07:28:41 GMT
<
{ [2682 bytes data]
* Connection #0 to host <ip> left intact
00000000: 8444 a101 3822 a059 1106 a969 6d6f 6475 .D..8".Y...imodu
00000010: 6c65 5f69 6478 2769 2d30 6631 6364 3737 le_idx'i-0f1cd77
00000020: 6433 3766 6438 6263 6339 2d65 6e63 3031 d37fd8bcc9-enc01
00000030: 3865 3761 6136 3165 3230 3430 6666 6664 8e7aa61e2040fffd
00000040: 6967 6573 7466 5348 4133 3834 6974 696d igestfSHA384itim
00000050: 6573 7461 6d70 1b00 0001 8eb2 4f18 9864 estamp......O..d
...
...
/attestation/hex
public_key: Optional, hex encoded public key without the0xprefix that is included in thepublic_keyfield of the attestation after being decoded into raw bytesuser_data: Optional, hex encoded user data without the0xprefix that is included in theuser_datafield of the attestation after being decoded into raw bytesnonce: Optional, hex encoded nonce without the0xprefix that is included in thenoncefield of the attestation after being decoded into raw bytes
While all query parameters are optional, any useful attestation will likely include at least the public key to extend the chain of trust.
$ curl '<ip:port>/attestation/hex?public_key=<public_key>&user_data=<user_data>&nonce=<nonce>' -vs | xxd
* Trying <ip:port>...
* Connected to <ip> (<ip>) port <port> (#0)
> GET /attestation/hex?public_key=<public_key>&user_data=<user_data>&nonce=<nonce> HTTP/1.1
> Host: <ip:port>
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-type: text/plain; charset=utf-8
< content-length: 8932
< date: Sat, 06 Apr 2024 08:22:00 GMT
<
8444a1013822a0591106a9696d6f64756c655f69647827692d3066316364...
...
/health
$ curl <ip:port>/health -vs
* Trying <ip:port>...
* Connected to <ip> (<ip>) port <port> (#0)
> GET /attestation/hex HTTP/1.1
> Host: <ip:port>
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-length: 0
< date: Sat, 06 Apr 2024 08:22:00 GMT
<
This project is licensed under the GNU AGPLv3 or any later version. See LICENSE.txt.