Using the Anjuna Nitro Attestation Endpoint
The Anjuna Nitro Runtime exposes an internal HTTP endpoint, only accessible from within an Anjuna Nitro Enclave, for generating attestation reports.
This can be used to prove that a specific application is running in a secure enclave before releasing sensitive data. For example, a key management service could verify an application’s attestation report before releasing secrets, to verify the identity of the trusted application and ensure it is running in an enclave.
It can also be used to authenticate that a trusted Anjuna Nitro Enclave produced certain data. For example, a machine learning (ML) application can embed its inference result (or a hash of the result) in an attestation report. The client can verify that attestation report to confirm that a trusted application generated the inference result.
Generating an attestation report
When an Anjuna Nitro Enclave runs,
the Anjuna Nitro Runtime exposes the attestation endpoint at http://localhost:50123/api/v1/attestation/report
.
The API accepts an HTTP GET
request with three optional base64-URL-encoded query parameters:
-
publicKey
for supplying a public key, which is included in the attestation document. Any client, including AWS KMS, can use this public key to encrypt sensitive data to send to the enclave. The public key should be in ASN.1 DER format, and only RSA keys are supported at this time. 2048, 3072, and 4096-bit keys are supported. -
userData
for providing custom data to the report. The decoded size of this parameter cannot exceed 1024 bytes in size. -
nonce
to add a nonce value to the report for hardening the request against replay attacks. TheuserData
parameter can also be used for this purpose. In either case, a source of random data should be used for each request for it to be effective.
The API will return the AWS Nitro Attestation Report as a CBOR-encoded COSE-signed binary document.
Show OpenAPI specification
openapi: 3.0.3
info:
title: Anjuna Nitro Attestation
description: API for Anjuna Nitro Enclaves to generate an AWS Nitro Enclave attestation report
contact:
email: support@anjuna.io
version: 1.43.0001
servers:
- url: http://localhost:50123/api/v1
paths:
/attestation/report:
get:
summary: Generate a new Nitro Attestation Report
description: Generate an attestation report with optional publicKey, userData, and nonce fields.
operationId: generateReport
parameters:
- in: query
name: publicKey
description: An RSA key to include in the report. 2048, 3072, and 4096-bit keys are supported.
schema:
type: string
format: RSA key, in ASN.1 DER format, base64-URL-encoded
maxLength: 1368 # must decode to 1024 bytes or fewer
- in: query
name: userData
description: User-provided data to include in the report
schema:
type: string
format: bytes, base64-URL-encoded
maxLength: 1368 # must decode to 1024 bytes or fewer
- in: query
name: nonce
description: User-provided cryptographic nonce to include in the report
schema:
type: string
format: bytes, base64-URL-encoded
maxLength: 1368 # must decode to 1024 bytes or fewer
responses:
'200':
description: Success
content:
'*/*':
schema:
type: string
format: binary
description: AWS Nitro Attestation Report, in CBOR-encoded COSE-signed binary document format
Your application can generate an attestation report with Golang using the Anjuna go-nitro-attestation library.
Alternatively, the HTTP endpoint can be used directly with any other programming language, or even with a command line shell such as in the following example.
Both examples below must run within an enclave:
-
Go example using the Anjuna library
-
HTTP example in the shell
// defines your custom data
myData := []byte("Hello World!")
// generate RSA-2048 key (optional)
rsaKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
// generate a 12 byte random nonce value
nonce := make([]byte, 12)
if _, err = rand.Read(nonce); err != nil {
panic(err)
}
// get a new report byte stream (pass nil to rsaKey parameter if not used)
docReader, err := attester.GetAttestationReport(rsaKey.PublicKey, myData, nonce)
if err != nil {
panic(err)
}
docBytes, _ := io.ReadAll(docReader) // read the report's bytes
fmt.Printf("%x", docBytes) // print the report's bytes
openssl genrsa -out private.pem 2048 # Generate an RSA 2048 bit key pair
openssl rsa -in private.pem -pubout -outform DER -out public.der
userData=$(echo "Hello World!" | basenc -w0 --base64url)
publicKey=$(basenc -w0 --base64url public.der)
nonce=$(head -c 12 /dev/random | basenc --base64url)
curl "http://localhost:50123/api/v1/attestation/report?userData=${userData}&publicKey=${publicKey}&nonce=${nonce}" > report.bin
cat report.bin | basenc --base64 # to print the report's bytes in base64
Verifying an attestation report
Any application can verify attestation reports with Golang using the Anjuna go-nitro-attestation library, even if the verifier is not running in an enclave.
This can be used to confirm trust in an application before sending it sensitive data. Or, you can use it to authenticate that an output really came from a trusted application.
// Validate the report's root of trust and PCR values
expectedValues := verifier.PCRMap{
0: "000000",
1: "000001",
}
if err = verifier.Validate(report, expectedValues); err != nil {
panic(err)
}
fmt.Println("Report is valid!")
// Access the user data
fmt.Printf("Recovered user data: %s\n", report.Document.UserData)
The README for go-nitro-attestation contains more information on verifying attestation reports.
More information
For general information on attestation for AWS Nitro Enclaves, see AWS documentation: Nitro Enclaves Attestation Process.
The Anjuna Nitro Attestation Endpoint simplifies this process. For more information and example code, see Github: anjuna-security/go-nitro-attestation.
The AWS KMS integration for AWS Nitro Enclaves requires a specific workflow
involving the UserPublicKey
field of an attestation report and unwrapping the response.
For instructions on the AWS KMS integration, see Using AWS KMS with the Anjuna Nitro Attestation Endpoint.