Skip to main content

Terraform for Confidential Computing: Deploy Nitro Enclaves and TEEs on AWS

Key Takeaway

Deploy confidential computing with Terraform on AWS. Provision Nitro Enclaves for data-in-use protection, configure KMS attestation policies, and isolate sensitive AI workloads.

Table of Contents

Confidential computing protects data while it’s being processed — not just at rest or in transit. Gartner highlights it as a 2026 strategic trend as sensitive AI and analytics workloads move to shared cloud infrastructure. AWS Nitro Enclaves provide hardware-isolated environments where even AWS operators can’t access your data during processing.

Why Confidential Computing Matters

Traditional encryption protects data at rest (S3, EBS) and in transit (TLS), but data must be decrypted for processing. Confidential computing closes this gap:

Data StateProtectionAWS Service
At restAES-256 encryptionKMS, S3 SSE, EBS
In transitTLS 1.3ALB, CloudFront, VPN
In useHardware isolationNitro Enclaves

EC2 with Nitro Enclaves

resource "aws_instance" "confidential" {
  ami           = data.aws_ami.al2023.id
  instance_type = "m5.2xlarge"  # Must support Nitro Enclaves
  subnet_id     = var.private_subnet_id

  enclave_options {
    enabled = true  # Enable Nitro Enclaves on this instance
  }

  # Allocate resources for the enclave
  user_data = base64encode(<<-EOF
    #!/bin/bash
    # Install Nitro Enclaves CLI
    amazon-linux-extras install aws-nitro-enclaves-cli -y
    yum install aws-nitro-enclaves-cli-devel -y

    # Configure enclave allocator
    cat > /etc/nitro_enclaves/allocator.yaml <<'ALLOC'
    memory_mib: 4096
    cpu_count: 2
    ALLOC

    # Start the allocator service
    systemctl enable nitro-enclaves-allocator
    systemctl start nitro-enclaves-allocator
    systemctl enable docker
    systemctl start docker
  EOF
  )

  metadata_options {
    http_endpoint = "enabled"
    http_tokens   = "required"  # IMDSv2 only
  }

  root_block_device {
    encrypted   = true
    volume_size = 50
    volume_type = "gp3"
  }

  tags = {
    Name      = "confidential-compute"
    Component = "confidential-computing"
  }
}

# Instance types that support Nitro Enclaves
# m5.xlarge, m5.2xlarge, m5.4xlarge, m5.8xlarge, m5.12xlarge, m5.16xlarge, m5.24xlarge
# c5.xlarge+, r5.xlarge+, c6i.xlarge+, m6i.xlarge+, r6i.xlarge+

KMS Key with Attestation Policy

KMS can restrict key access to only verified Nitro Enclaves:

resource "aws_kms_key" "enclave_only" {
  description = "Key accessible only from verified Nitro Enclaves"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "RootAccess"
        Effect    = "Allow"
        Principal = { AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" }
        Action    = "kms:*"
        Resource  = "*"
      },
      {
        Sid       = "EnclaveDecrypt"
        Effect    = "Allow"
        Principal = { AWS = aws_iam_role.enclave.arn }
        Action    = ["kms:Decrypt", "kms:GenerateDataKey"]
        Resource  = "*"
        Condition = {
          StringEqualsIgnoreCase = {
            # Only allow decryption from a specific enclave image
            "kms:RecipientAttestation:PCR0" = var.enclave_pcr0_hash
          }
        }
      }
    ]
  })

  tags = {
    Component = "confidential-computing"
    KeyUsage  = "enclave-only"
  }
}

resource "aws_kms_alias" "enclave" {
  name          = "alias/enclave-key"
  target_key_id = aws_kms_key.enclave_only.id
}

IAM Role for Enclave Workloads

resource "aws_iam_role" "enclave" {
  name = "enclave-workload"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "ec2.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })
}

resource "aws_iam_role_policy" "enclave_kms" {
  name = "enclave-kms-access"
  role = aws_iam_role.enclave.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect   = "Allow"
        Action   = ["kms:Decrypt", "kms:GenerateDataKey"]
        Resource = aws_kms_key.enclave_only.arn
      },
      {
        Effect   = "Allow"
        Action   = ["s3:GetObject"]
        Resource = "${aws_s3_bucket.encrypted_data.arn}/*"
      }
    ]
  })
}

resource "aws_iam_instance_profile" "enclave" {
  name = "enclave-workload"
  role = aws_iam_role.enclave.name
}

Encrypted Data Pipeline

# S3 bucket for encrypted input data
resource "aws_s3_bucket" "encrypted_data" {
  bucket = "confidential-data-${data.aws_caller_identity.current.account_id}"
}

resource "aws_s3_bucket_server_side_encryption_configuration" "encrypted" {
  bucket = aws_s3_bucket.encrypted_data.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.enclave_only.arn
    }
    bucket_key_enabled = true
  }
}

# VPC endpoint — data never leaves AWS network
resource "aws_vpc_endpoint" "s3" {
  vpc_id       = var.vpc_id
  service_name = "com.amazonaws.${var.region}.s3"
  route_table_ids = var.private_route_table_ids
}

resource "aws_vpc_endpoint" "kms" {
  vpc_id              = var.vpc_id
  service_name        = "com.amazonaws.${var.region}.kms"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = var.private_subnet_ids
  security_group_ids  = [aws_security_group.endpoints.id]
  private_dns_enabled = true
}

Network Isolation

resource "aws_security_group" "enclave_instance" {
  name_prefix = "enclave-"
  vpc_id      = var.vpc_id

  # No inbound from internet
  # Only outbound to VPC endpoints
  egress {
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    security_groups = [aws_security_group.endpoints.id]
    description     = "HTTPS to VPC endpoints only"
  }

  tags = { Component = "confidential-computing" }
}

Use Cases for Confidential Computing

Use CaseWhat’s ProtectedWhy Enclave
AI model inference on private dataPatient records, financial dataData decrypted only inside enclave
Multi-party computationCombined datasets from multiple orgsNo party sees the other’s raw data
Private key operationsTLS private keys, signing keysKeys never exist in main memory
Regulated data processingHIPAA, PCI, GDPR workloadsProvable isolation for compliance
Secure credential managementAPI keys, database passwordsCredentials isolated from host OS

Hands-On Courses

Conclusion

Confidential computing closes the last encryption gap — protecting data while it’s being processed. Use Terraform to provision Nitro Enclave-enabled EC2 instances, KMS keys with attestation policies that only allow decryption from verified enclaves, and network isolation via VPC endpoints. Essential for AI inference on sensitive data, multi-party analytics, and regulated workloads.

🚀

Level Up Your Terraform Skills

Hands-on courses, books, and resources from Luca Berton

Luca Berton
Written by

Luca Berton

DevOps Engineer, AWS Partner, Terraform expert, and author. Creator of Ansible Pilot, Terraform Pilot, and CopyPasteLearn.