Skip to content

Instantly share code, notes, and snippets.

@mohashari
Created July 23, 2026 01:03
Show Gist options
  • Select an option

  • Save mohashari/05ba5b92914b3a97272477e3c1033bcf to your computer and use it in GitHub Desktop.

Select an option

Save mohashari/05ba5b92914b3a97272477e3c1033bcf to your computer and use it in GitHub Desktop.
Implementing Cryptographic Attestation for Ephemeral Microservice Identities using AWS Nitro Enclaves and KMS — code snippets
#!/usr/bin/env bash
# build_eif.sh
set -euo pipefail
echo "[*] Building statically linked Go application..."
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
-ldflags="-w -s -extldflags '-static'" \
-o bootstrap_app ./cmd/bootstrap
echo "[*] Generating container definition..."
cat <<EOF > Dockerfile.enclave
FROM alpine:3.19
RUN apk add --no-cache ca-certificates
COPY bootstrap_app /usr/local/bin/bootstrap_app
ENTRYPOINT ["/usr/local/bin/bootstrap_app"]
EOF
echo "[*] Building target Docker container..."
docker build -t enclave-service:v1.0.0 -f Dockerfile.enclave .
echo "[*] Building Enclave Image File (EIF)..."
# This produces 'enclave-service.eif' and prints PCR measurements to stdout.
nitro-cli build-enclave \
--docker-uri enclave-service:v1.0.0 \
--output-file enclave-service.eif > measurements.json
echo "[*] EIF Generation complete. Measurements saved to measurements.json."
cat measurements.json | grep -A 6 "Measurements"
package enclave
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"fmt"
"os"
"syscall"
"unsafe"
)
const (
NsmDevicePath = "/dev/nsm"
NsmIoctlMagic = 0x0A
// IOCTL code to request attestation document from the Nitro Security Module
NsmRequestAttestation = 3224373763
)
type NsmAttestationRequest struct {
UserTagRaw uintptr
UserTagLen uint32
NonceRaw uintptr
NonceLen uint32
PubKeyRaw uintptr
PubKeyLen uint32
ResponseRaw uintptr
ResponseLen uint32
}
// GenerateEphemeralKeyPair generates an RSA-2048 key pair in memory.
// The private key must never write to disk or exit the enclave.
func GenerateEphemeralKeyPair() (*rsa.PrivateKey, []byte, error) {
privKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, nil, fmt.Errorf("failed to generate ephemeral key: %w", err)
}
pubKeyBytes, err := x509.MarshalPKIXPublicKey(&privKey.PublicKey)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal public key: %w", err)
}
return privKey, pubKeyBytes, nil
}
// FetchAttestationDocument queries the /dev/nsm device to generate a hardware-signed document.
func FetchAttestationDocument(pubKeyBytes []byte, nonce []byte) ([]byte, error) {
file, err := os.OpenFile(NsmDevicePath, os.O_RDWR, 0)
if err != nil {
return nil, fmt.Errorf("unable to open NSM device: %w", err)
}
defer file.Close()
// Pre-allocate a buffer for the response (typically 4-8KB)
responseBuffer := make([]byte, 16384)
req := NsmAttestationRequest{
PubKeyRaw: uintptr(unsafe.Pointer(&pubKeyBytes[0])),
PubKeyLen: uint32(len(pubKeyBytes)),
ResponseRaw: uintptr(unsafe.Pointer(&responseBuffer[0])),
ResponseLen: uint32(len(responseBuffer)),
}
if len(nonce) > 0 {
req.NonceRaw = uintptr(unsafe.Pointer(&nonce[0]))
req.NonceLen = uint32(len(nonce))
}
_, _, errno := syscall.Syscall(
syscall.SYS_IOCTL,
file.Fd(),
uintptr(NsmRequestAttestation),
uintptr(unsafe.Pointer(&req)),
)
if errno != 0 {
return nil, fmt.Errorf("ioctl NSM_REQUEST_ATT_DOC failed: %w", errno)
}
return responseBuffer[:req.ResponseLen], nil
}
{
"Version": "2012-10-17",
"Id": "enclave-kms-key-policy",
"Statement": [
{
"Sid": "AllowAdministrationAndManagement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/DevSecOpsAdmin"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "RestrictDecryptionToSpecificNitroEnclave",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/microservice-parent-role"
},
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:RecipientEquals:pcr0": "8e3c12f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8",
"kms:RecipientEquals:pcr1": "2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e",
"kms:RecipientEquals:pcr2": "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}
}
}
]
}
package enclave
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
"net"
"net/http"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/kms"
"github.com/aws/aws-sdk-go-v2/service/kms/types"
)
// DecryptEnclavePayload sends the ciphertext and attestation document to KMS.
// It decrypts the re-encrypted response using the private key.
func DecryptEnclavePayload(
ctx context.Context,
kmsKeyID string,
encryptedSecret []byte,
attestationDoc []byte,
privateKey *rsa.PrivateKey,
) ([]byte, error) {
// Configure custom HTTP client to route over vsock proxy
dialer := &net.Dialer{}
customTransport := &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
// Redirect all KMS API requests to the vsock proxy on the parent host
return dialer.DialContext(ctx, "tcp", "127.0.0.1:8000")
},
}
cfg, err := config.LoadDefaultConfig(ctx,
config.WithHTTPClient(&http.Client{Transport: customTransport}),
config.WithRegion("us-east-1"),
)
if err != nil {
return nil, fmt.Errorf("failed to initialize AWS config: %w", err)
}
kmsClient := kms.NewFromConfig(cfg)
input := &kms.DecryptInput{
CiphertextBlob: encryptedSecret,
KeyId: aws.String(kmsKeyID),
Recipient: &types.RecipientInfo{
AttestationDocument: attestationDoc,
KeyEncryptionAlgorithm: types.KeyEncryptionAlgorithmSpecRsaesOaepSha256,
},
}
output, err := kmsClient.Decrypt(ctx, input)
if err != nil {
return nil, fmt.Errorf("kms.Decrypt execution failed: %w", err)
}
if len(output.CiphertextBlob) == 0 {
return nil, fmt.Errorf("empty ciphertext blob returned from KMS")
}
// Decrypt the re-encrypted ciphertext using the enclave's ephemeral private key
hash := sha256.New()
plaintext, err := rsa.DecryptOAEP(hash, rand.Reader, privateKey, output.CiphertextBlob, nil)
if err != nil {
return nil, fmt.Errorf("failed to decrypt envelope payload: %w", err)
}
return plaintext, nil
}
{
"Sid": "AllowSignedEnclaveDecryptionOnly",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/microservice-parent-role"
},
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:RecipientEquals:pcr4": "ab89ef0123cd45ef678901abcdef2345678901abcdef2345678901abcdef2345"
}
}
}
package enclave
import (
"crypto/rand"
"fmt"
"os"
)
// NSMProvider provides an interface abstraction over hardware-level attestation.
type NSMProvider interface {
GetAttestationDoc(userData, nonce, publicKey []byte) ([]byte, error)
Close()
}
type LiveNSMProvider struct {
fd int
}
func NewLiveNSMProvider() (*LiveNSMProvider, error) {
// Custom implementation or wrapper to open `/dev/nsm`
return &LiveNSMProvider{fd: 1}, nil
}
func (l *LiveNSMProvider) GetAttestationDoc(userData, nonce, publicKey []byte) ([]byte, error) {
return FetchAttestationDocument(publicKey, nonce)
}
func (l *LiveNSMProvider) Close() {}
// MockNSMProvider is instantiated when running on local workstations or testing environments.
type MockNSMProvider struct{}
func (m *MockNSMProvider) GetAttestationDoc(userData, nonce, publicKey []byte) ([]byte, error) {
// Return a dummy base64/cbor payload. Your testing mock in AWS KMS must recognize this pattern.
fmt.Printf("[MOCK] NSM invoked. Generating mock attestation document. UserData size: %d\n", len(userData))
dummyDoc := make([]byte, 1024)
if _, err := rand.Read(dummyDoc); err != nil {
return nil, err
}
return dummyDoc, nil
}
func (m *MockNSMProvider) Close() {}
// ResolveNSMProvider evaluates environment variables to select live or mock attestation.
func ResolveNSMProvider() NSMProvider {
if _, err := os.Stat(NsmDevicePath); os.IsNotExist(err) {
fmt.Println("[!] /dev/nsm device not found. Initializing Mock NSM Provider.")
return &MockNSMProvider{}
}
prov, err := NewLiveNSMProvider()
if err != nil {
fmt.Printf("[!] Failed to initialize Live NSM: %v. Falling back to Mock.\n", err)
return &MockNSMProvider{}
}
return prov
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment