Skip to content
This repository was archived by the owner on Jul 30, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
277 changes: 277 additions & 0 deletions tee/tf/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
terraform {
backend "s3" {
bucket = "proving-server-tf-state"
key = "terraform/tee/terraform.tfstate"
region = "eu-north-1"
}
}

variable "aws_region" {
description = "AWS region to deploy to"
type = string
default = "eu-north-1"
}

variable "instance_type" {
description = "EC2 instance type for Nitro Enclave"
type = string
default = "c5.xlarge"
}

variable "key_name" {
description = "(Optional) EC2 key pair name for SSH access"
type = string
default = ""
}

variable "eif_url" {
description = "Public URL of the Enclave Image File (EIF)"
type = string
}

variable "proxy_image" {
description = "Public ECR URI of the proxy Docker image"
type = string
}

variable "debug_mode" {
description = "Enable debug mode for the Nitro Enclave"
type = bool
default = false
}


provider "aws" {
region = var.aws_region
}

data "aws_vpc" "default" {
default = true
}
# Fetch default VPC's public subnets
data "aws_subnets" "public" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default.id]
}
filter {
name = "default-for-az"
values = ["true"]
}
}

# Latest Amazon Linux 2023 AMI
data "aws_ami" "al2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-2023.*-x86_64"]
}
}

# Security Group allowing direct access to proxy port
resource "aws_security_group" "proxy_sg" {
name = "proxy-sg"
description = "Allow direct access to proxy port 3000"
vpc_id = data.aws_vpc.default.id

# Allow direct access to proxy port 3000 from anywhere
ingress {
from_port = 3000
to_port = 3000
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

# Allow SSH if key is provided
dynamic "ingress" {
for_each = length(var.key_name) > 0 ? [1] : []
content {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

# IAM Role/Profile for EC2
resource "aws_iam_role" "ec2_role" {
name = "ec2-nitro-role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Action = "sts:AssumeRole",
Effect = "Allow",
Principal = { Service = "ec2.amazonaws.com" }
}]
})
}

resource "aws_iam_instance_profile" "ec2_profile" {
name = "ec2-nitro-profile"
role = aws_iam_role.ec2_role.name
}


# EC2 Instance for Nitro Enclave + Proxy
resource "aws_instance" "proxy_instance" {
ami = data.aws_ami.al2023.id
instance_type = var.instance_type
key_name = length(var.key_name) > 0 ? var.key_name : null
vpc_security_group_ids = [aws_security_group.proxy_sg.id]
subnet_id = data.aws_subnets.public.ids[0]

iam_instance_profile = aws_iam_instance_profile.ec2_profile.name
associate_public_ip_address = true

enclave_options {
enabled = true
}

user_data = base64encode(<<-EOF
#!/bin/bash
set -eux

# Log everything to a file for debugging
exec > >(tee /var/log/user-data.log) 2>&1

echo "Starting Shielder Prover Server setup..."

# Update system and install required packages
dnf update -y
dnf install -y aws-nitro-enclaves-cli aws-nitro-enclaves-cli-devel docker jq --allowerasing

# Add ec2-user to required groups
usermod -aG ne ec2-user
usermod -aG docker ec2-user

# Configure Nitro Enclaves allocator
cat > /etc/nitro_enclaves/allocator.yaml << 'EOL'
---
# Enclave configuration file
#
# How much memory to allocate for enclaves (in MiB).
memory_mib: 2048
#
# How many CPUs to reserve for enclaves.
cpu_count: 2
EOL

# Enable and start services
systemctl enable nitro-enclaves-allocator.service
systemctl start nitro-enclaves-allocator.service
systemctl enable docker
systemctl start docker

# Wait for services to be ready
sleep 10

# Download the enclave image
echo "Downloading enclave image from ${var.eif_url}"
curl -sSL "${var.eif_url}" -o /home/ec2-user/image.eif
chown ec2-user:ec2-user /home/ec2-user/image.eif

# Set TEE_CID
export TEE_CID=16

# Run the enclave
echo "Starting Nitro Enclave with CID=$${TEE_CID}"
nitro-cli run-enclave --cpu-count 2 --memory 2048 --enclave-cid $${TEE_CID} --eif-path /home/ec2-user/image.eif${var.debug_mode ? " --debug-mode" : ""}

# Wait for enclave to start
sleep 5

# Verify enclave is running
nitro-cli describe-enclaves

# Get the actual enclave CID (should be 16, but let's be safe)
ACTUAL_CID=$(nitro-cli describe-enclaves | jq -r '.[0].EnclaveCID // empty')
if [ -z "$ACTUAL_CID" ]; then
echo "ERROR: Failed to get enclave CID"
exit 1
fi

echo "Enclave running with CID=$${ACTUAL_CID}"

# Start the proxy Docker container
echo "Starting proxy container with image ${var.proxy_image}"
docker run -d \
--name shielder-prover-proxy \
--restart always \
-p 3000:3000 \
--security-opt seccomp=unconfined \
-e ENCLAVE_CID="$${ACTUAL_CID}" \
-e RUST_LOG=debug \
"${var.proxy_image}" \
--tee-cid "$${ACTUAL_CID}" \
--bind-address 0.0.0.0

# Wait for container to start
sleep 5

# Check if container is running
docker ps -a

echo "Setup complete! Shielder Prover Server should be accessible on port 3000"
EOF
)

tags = {
Name = "proxy-instance"
}
}

# Wait for the proxy service to be healthy
resource "null_resource" "wait_for_proxy" {
provisioner "local-exec" {
command = <<-EOF
echo "Waiting for proxy service to be healthy..."
for i in {1..60}; do
if curl -f -s "http://${aws_instance.proxy_instance.public_ip}:3000/health" > /dev/null 2>&1; then
echo "Proxy service is healthy!"
exit 0
fi
echo "Attempt $i/60: Proxy not ready yet, waiting 30 seconds..."
sleep 30
done
echo "ERROR: Proxy service did not become healthy within 30 minutes"
exit 1
EOF
}

depends_on = [aws_instance.proxy_instance]
}

output "proxy_url" {
description = "Public URL of the proxy (direct EC2 access)"
value = "http://${aws_instance.proxy_instance.public_ip}:3000"
}

output "health_check_url" {
description = "Health check endpoint URL"
value = "http://${aws_instance.proxy_instance.public_ip}:3000/health"
}

output "instance_id" {
description = "EC2 Instance ID"
value = aws_instance.proxy_instance.id
}

output "public_ip" {
description = "Public IP address of the EC2 instance"
value = aws_instance.proxy_instance.public_ip
}

output "security_group_id" {
description = "Security Group ID for the proxy"
value = aws_security_group.proxy_sg.id
}
5 changes: 5 additions & 0 deletions tee/tf/terraform.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
aws_region = "eu-north-1"
instance_type = "c5.xlarge"
key_name = "" # or "" if you don’t need SSH
eif_url = "https://github.com/Cardinal-Cryptography/zkOS-monorepo/releases/download/prover-server-v0.1.0/shielder-prover-tee-837095f.eif"
proxy_image = "public.ecr.aws/p5g6f1p8/shielder-prover:837095f"
Loading