diff --git a/e2b-setup-env-existing-vpc.yml b/e2b-setup-env-existing-vpc.yml new file mode 100644 index 0000000..1f3f3fc --- /dev/null +++ b/e2b-setup-env-existing-vpc.yml @@ -0,0 +1,1008 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: >- + E2B Infrastructure CloudFormation Template (Existing VPC) - Deploys core infrastructure components for E2B platform + using existing VPC including IAM Roles, PostgreSQL Database, and S3 Buckets. + +# =================================================================================================== +# Metadata - Organizes template parameters into logical groups in the CloudFormation console +# =================================================================================================== +Metadata: + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: Existing VPC Configuration + Parameters: + - ExistingVpcId + - ExistingPrivateSubnet1Id + - ExistingPrivateSubnet2Id + - ExistingPublicSubnet1Id + - ExistingPublicSubnet2Id + - PublicAccess + - Label: + default: Security Configuration + Parameters: + - AllowRemoteSSHIPs + - Label: + default: E2B Environment + Parameters: + - Environment + - Label: + default: Architecture Configuration + Parameters: + - Architecture + - Label: + default: Domain Configuration + Parameters: + - BaseDomain + - Label: + default: Bastion Configuration + Parameters: + - KeyName + - Label: + default: Database Configuration + Parameters: + - DBInstanceIdentifier + - DBName + - DBUsername + - DBPassword + +# =================================================================================================== +# Parameters - Input values required for the E2B infrastructure deployment +# =================================================================================================== +Parameters: + # E2B Environment Configuration + Environment: + Description: "E2B Environment" + Type: String + AllowedValues: + - prod + - dev + Default: prod + + # Architecture Configuration - Choose CPU architecture + Architecture: + Description: "Choose between x86_64 (Intel/AMD compatible) and arm64 (AWS Graviton) processor architectures." + Type: String + AllowedValues: + - x86_64 + - arm64 + + # Domain Configuration - Settings for SSL certificate and DNS + BaseDomain: + Type: String + Description: >- + Base domain name (e.g. domain.com or sub.domain.com). + Wildcard certificate will be issued for *.{BaseDomain} + AllowedPattern: '^([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$' + ConstraintDescription: Must be a valid domain (e.g. sub.domain.com) + + # Existing VPC Configuration + ExistingVpcId: + Type: AWS::EC2::VPC::Id + Description: ID of the existing VPC where E2B infrastructure will be deployed + + ExistingPrivateSubnet1Id: + Type: AWS::EC2::Subnet::Id + Description: ID of existing private subnet in first availability zone + + ExistingPrivateSubnet2Id: + Type: AWS::EC2::Subnet::Id + Description: ID of existing private subnet in second availability zone + + ExistingPublicSubnet1Id: + Type: AWS::EC2::Subnet::Id + Description: ID of existing public subnet in first availability zone(not available in private access mode) + + ExistingPublicSubnet2Id: + Type: AWS::EC2::Subnet::Id + Description: ID of existing public subnet in second availability zone(not available in private access mode) + + PublicAccess: + Type: String + Description: Specify whether public or private access to E2B + AllowedValues: + - public + - private + Default: public + + # Bastion Configuration - Settings for the deployment and management server + KeyName: + Description: EC2 Key Pair name for SSH access to the bastion host (deployment server) + Type: AWS::EC2::KeyPair::KeyName + ConstraintDescription: Must be the name of an existing EC2 KeyPair in this region. + + # Security Configuration - Access control settings + AllowRemoteSSHIPs: + Description: IP address range allowed for SSH (port 22) access to the bastion host (CIDR format), if you want to allow all IPs, please set it to '0.0.0.0/0' + Type: String + Default: "0.0.0.0/0" + + # Database Configuration - PostgreSQL settings for E2B platform + DBInstanceIdentifier: + Type: String + Default: e2b-aurora-db + Description: Unique identifier for the Aurora PostgreSQL database cluster + DBName: + Type: String + Default: e2b + Description: Initial database name for E2B application data (must be characters with letters and numbers) + DBUsername: + Type: String + NoEcho: true + Description: Master username for PostgreSQL database (will not be displayed in console) + DBPassword: + Type: String + NoEcho: true + Description: Master password for PostgreSQL database (must be 8-30 characters with letters and numbers) + AllowedPattern: ^(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z0-9]{8,30}$ + ConstraintDescription: Password must be 8-30 characters and contain at least one letter and one number + +# =================================================================================================== +# Conditions - Conditional logic for resource creation +# =================================================================================================== +Conditions: + IsX64: !Equals [!Ref Architecture, x86_64] + IsArm64: !Equals [!Ref Architecture, arm64] + IsProd: !Equals [!Ref Environment, prod] + +# =================================================================================================== +# Resources - AWS resources to be provisioned for the E2B infrastructure +# =================================================================================================== +Resources: + # ------------------------------------------------------------------------------------------------ + # VPC CIDR Lookup - Custom resource to automatically retrieve VPC CIDR block + # ------------------------------------------------------------------------------------------------ + VpcLookupRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: VpcDescribePolicy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - ec2:DescribeVpcs + Resource: "*" + + VpcLookupFunction: + Type: AWS::Lambda::Function + Properties: + FunctionName: !Sub "${AWS::StackName}-vpc-lookup" + Runtime: python3.9 + Handler: index.handler + Role: !GetAtt VpcLookupRole.Arn + Timeout: 60 + Code: + ZipFile: | + import boto3 + import json + import cfnresponse + + def handler(event, context): + try: + if event['RequestType'] == 'Delete': + cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) + return + + ec2 = boto3.client('ec2') + vpc_id = event['ResourceProperties']['VpcId'] + + response = ec2.describe_vpcs(VpcIds=[vpc_id]) + + if not response['Vpcs']: + raise Exception(f'VPC {vpc_id} not found') + + vpc = response['Vpcs'][0] + cidr_block = vpc['CidrBlock'] + + response_data = {'CidrBlock': cidr_block} + cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data) + + except Exception as e: + print(f'Error: {str(e)}') + cfnresponse.send(event, context, cfnresponse.FAILED, {}) + + VpcCidrLookup: + Type: AWS::CloudFormation::CustomResource + Properties: + ServiceToken: !GetAtt VpcLookupFunction.Arn + VpcId: !Ref ExistingVpcId + + # ------------------------------------------------------------------------------------------------ + # VPC Endpoint - Provides private access to S3 without traversing the public internet + # ------------------------------------------------------------------------------------------------ + S3VPCEndpoint: + Type: AWS::EC2::VPCEndpoint + Properties: + ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3" + VpcId: !Ref ExistingVpcId + VpcEndpointType: Gateway + # Note: You may need to specify existing route table IDs for your VPC + # RouteTableIds: + # - existing-route-table-id-1 + # - existing-route-table-id-2 + + # ------------------------------------------------------------------------------------------------ + # Security Groups - Network access control for different infrastructure tiers + # ------------------------------------------------------------------------------------------------ + BastionSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Security group allowing SSH connections to the bastion host from specified IP ranges + VpcId: !Ref ExistingVpcId + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: "22" + ToPort: "22" + CidrIp: !Ref AllowRemoteSSHIPs + SecurityGroupEgress: + - IpProtocol: "-1" + CidrIp: "0.0.0.0/0" + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-bastion-sg" + + DBSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Security group controlling access to the PostgreSQL database (port 5432) + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 5432 + ToPort: 5432 + CidrIp: !GetAtt VpcCidrLookup.CidrBlock + SecurityGroupEgress: + - IpProtocol: "-1" + CidrIp: "0.0.0.0/0" + VpcId: !Ref ExistingVpcId + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-db-sg" + + RedisSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Security group controlling access to the Redis cache (port 6379) + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 6379 + ToPort: 6379 + CidrIp: !GetAtt VpcCidrLookup.CidrBlock + SecurityGroupEgress: + - IpProtocol: "-1" + CidrIp: "0.0.0.0/0" + VpcId: !Ref ExistingVpcId + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-redis-sg" + + # ------------------------------------------------------------------------------------------------ + # IAM - Identity and Access Management roles and policies for secure resource access + # ------------------------------------------------------------------------------------------------ + EC2ServiceRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: + - ec2.amazonaws.com + Action: + - sts:AssumeRole + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore + Policies: + - PolicyName: E2BDeploymentPolicy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: S3Access + Effect: Allow + Action: + - s3:CreateBucket + - s3:DeleteBucket + - s3:GetObject + - s3:PutObject + - s3:DeleteObject + - s3:ListBucket + - s3:GetBucketLocation + - s3:GetBucketVersioning + - s3:PutBucketVersioning + - s3:PutBucketPolicy + - s3:GetBucketPolicy + - s3:PutBucketTagging + - s3:GetBucketTagging + - s3:PutEncryptionConfiguration + - s3:GetEncryptionConfiguration + - s3:PutBucketPublicAccessBlock + - s3:GetBucketPublicAccessBlock + - s3:GetBucketAcl + - s3:PutBucketAcl + - s3:GetBucketCors + - s3:PutBucketCors + - s3:GetBucketWebsite + - s3:PutBucketWebsite + - s3:GetAccelerateConfiguration + - s3:PutAccelerateConfiguration + - s3:GetBucketRequestPayment + - s3:PutBucketRequestPayment + - s3:GetBucketLogging + - s3:PutBucketLogging + - s3:GetLifecycleConfiguration + - s3:PutLifecycleConfiguration + - s3:GetReplicationConfiguration + - s3:PutReplicationConfiguration + - s3:GetBucketObjectLockConfiguration + - s3:PutBucketObjectLockConfiguration + - s3:GetObjectTagging + - s3:PutObjectTagging + Resource: + - "arn:aws:s3:::*e2b*" + - "arn:aws:s3:::*e2b*/*" + - "arn:aws:s3:::terraform-*" + - "arn:aws:s3:::terraform-*/*" + - "arn:aws:s3:::software-*" + - "arn:aws:s3:::software-*/*" + - Sid: SecretsManagerAccess + Effect: Allow + Action: + - secretsmanager:CreateSecret + - secretsmanager:GetSecretValue + - secretsmanager:PutSecretValue + - secretsmanager:DeleteSecret + - secretsmanager:DescribeSecret + - secretsmanager:GetResourcePolicy + - secretsmanager:TagResource + - secretsmanager:UntagResource + - secretsmanager:UpdateSecret + Resource: !Sub "arn:aws:secretsmanager:*:${AWS::AccountId}:secret:*e2b*" + - Sid: EC2PackerAccess + Effect: Allow + Action: + - ec2:AttachVolume + - ec2:AuthorizeSecurityGroupIngress + - ec2:AuthorizeSecurityGroupEgress + - ec2:CopyImage + - ec2:CreateImage + - ec2:CreateKeypair + - ec2:CreateSecurityGroup + - ec2:CreateSnapshot + - ec2:CreateTags + - ec2:CreateVolume + - ec2:CreateLaunchTemplate + - ec2:CreateLaunchTemplateVersion + - ec2:CreateNetworkInterface + - ec2:DeleteKeyPair + - ec2:DeleteSecurityGroup + - ec2:DeleteSnapshot + - ec2:DeleteVolume + - ec2:DeleteLaunchTemplate + - ec2:DeleteNetworkInterface + - ec2:DeregisterImage + - ec2:DescribeImageAttribute + - ec2:DescribeImages + - ec2:DescribeInstances + - ec2:DescribeInstanceStatus + - ec2:DescribeRegions + - ec2:DescribeSecurityGroups + - ec2:DescribeSnapshots + - ec2:DescribeSubnets + - ec2:DescribeTags + - ec2:DescribeVolumes + - ec2:DescribeLaunchTemplates + - ec2:DescribeLaunchTemplateVersions + - ec2:DescribeVpcs + - ec2:DescribeAvailabilityZones + - ec2:DescribeKeyPairs + - ec2:DescribeNetworkInterfaces + - ec2:DetachVolume + - ec2:GetPasswordData + - ec2:ModifyImageAttribute + - ec2:ModifyInstanceAttribute + - ec2:ModifySnapshotAttribute + - ec2:ModifyLaunchTemplate + - ec2:RegisterImage + - ec2:RunInstances + - ec2:StopInstances + - ec2:TerminateInstances + - ec2:RevokeSecurityGroupIngress + - ec2:RevokeSecurityGroupEgress + Resource: "*" + - Sid: AutoScalingAndELB + Effect: Allow + Action: + - autoscaling:* + - elasticloadbalancing:* + Resource: "*" + - Sid: ECRAccess + Effect: Allow + Action: + - ecr:GetAuthorizationToken + - ecr:BatchCheckLayerAvailability + - ecr:GetDownloadUrlForLayer + - ecr:BatchGetImage + - ecr:PutImage + - ecr:InitiateLayerUpload + - ecr:UploadLayerPart + - ecr:CompleteLayerUpload + - ecr:CreateRepository + - ecr:DeleteRepository + - ecr:DescribeRepositories + - ecr:ListImages + - ecr:DescribeImages + - ecr:TagResource + Resource: + - "*" + - !Sub "arn:aws:ecr:*:${AWS::AccountId}:repository/e2b-*" + - Sid: IAMAccess + Effect: Allow + Action: + - iam:CreateRole + - iam:DeleteRole + - iam:GetRole + - iam:ListRoles + - iam:UpdateRole + - iam:TagRole + - iam:UntagRole + - iam:CreateInstanceProfile + - iam:DeleteInstanceProfile + - iam:GetInstanceProfile + - iam:ListInstanceProfiles + - iam:ListInstanceProfilesForRole + - iam:AddRoleToInstanceProfile + - iam:RemoveRoleFromInstanceProfile + - iam:CreatePolicy + - iam:DeletePolicy + - iam:GetPolicy + - iam:GetPolicyVersion + - iam:ListPolicies + - iam:ListPolicyVersions + - iam:ListAttachedRolePolicies + - iam:AttachRolePolicy + - iam:DetachRolePolicy + - iam:PutRolePolicy + - iam:GetRolePolicy + - iam:DeleteRolePolicy + - iam:ListRolePolicies + - iam:TagPolicy + - iam:UntagPolicy + Resource: + - !Sub "arn:aws:iam::${AWS::AccountId}:role/*e2b*" + - !Sub "arn:aws:iam::${AWS::AccountId}:instance-profile/*e2b*" + - !Sub "arn:aws:iam::${AWS::AccountId}:policy/*e2b*" + - Sid: IAMAttachAWSManagedPolicy + Effect: Allow + Action: + - iam:AttachRolePolicy + - iam:DetachRolePolicy + Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/*e2b*" + Condition: + ArnEquals: + iam:PolicyARN: + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly + - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy + - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore + - arn:aws:iam::aws:policy/AmazonEC2FullAccess + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess + - arn:aws:iam::aws:policy/AmazonS3FullAccess + - arn:aws:iam::aws:policy/SecretsManagerReadWrite + - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role + - Sid: IAMPassRole + Effect: Allow + Action: + - iam:PassRole + Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/*e2b*" + Condition: + StringEquals: + iam:PassedToService: + - ec2.amazonaws.com + - ecs-tasks.amazonaws.com + - Sid: LogsAndMonitoring + Effect: Allow + Action: + - logs:* + - cloudwatch:* + Resource: "*" + - Sid: ElastiCacheAccess + Effect: Allow + Action: + - elasticache:DescribeCacheClusters + - elasticache:DescribeServerlessCaches + Resource: "*" + - Sid: CloudFormation + Effect: Allow + Action: + - cloudformation:DescribeStacks + - cloudformation:ListStacks + Resource: "*" + - Sid: SSMAccess + Effect: Allow + Action: + - ssm:GetParameter* + - ssm:PutParameter + - ssm:DeleteParameter + - ssm:DescribeParameters + Resource: !Sub "arn:aws:ssm:*:${AWS::AccountId}:parameter/*e2b*" + - Sid: STSAccess + Effect: Allow + Action: + - sts:GetCallerIdentity + Resource: "*" + Description: IAM role with complete permissions for E2B infrastructure deployment including Packer and Terraform + + EC2InstanceProfile: + Type: AWS::IAM::InstanceProfile + Properties: + Path: / + Roles: + - !Ref EC2ServiceRole + + # ------------------------------------------------------------------------------------------------ + # Parameter Store - Secure storage for sensitive configuration values + # ------------------------------------------------------------------------------------------------ + DBPasswordParameter: + Type: AWS::SSM::Parameter + Properties: + Name: !Sub "e2b-${AWS::StackName}-db-password" + Type: String + Value: !Ref DBPassword + Description: PostgreSQL database password stored securely in AWS Systems Manager Parameter Store + + # ------------------------------------------------------------------------------------------------ + # Certificate - SSL/TLS certificate for secure HTTPS communication + # ------------------------------------------------------------------------------------------------ + WildcardCertificate: + Type: AWS::CertificateManager::Certificate + Properties: + DomainName: !Sub "*.${BaseDomain}" + ValidationMethod: DNS + DomainValidationOptions: + - DomainName: !Sub "*.${BaseDomain}" + ValidationDomain: !Ref BaseDomain + + # ------------------------------------------------------------------------------------------------ + # S3 Buckets - Object storage for Terraform state files and software artifacts + # ------------------------------------------------------------------------------------------------ + TerraformS3Bucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub "terraform-${AWS::StackName}-${AWS::Region}-${AWS::AccountId}" + VersioningConfiguration: + Status: Suspended + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + AccessControl: Private + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-terraform-bucket" + + SoftwareS3Bucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub "software-${AWS::StackName}-${AWS::Region}-${AWS::AccountId}" + VersioningConfiguration: + Status: Suspended + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + AccessControl: Private + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-software-bucket" + + # ------------------------------------------------------------------------------------------------ + # RDS Database - PostgreSQL database for E2B platform data persistence + # ------------------------------------------------------------------------------------------------ + DBSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: Subnet group defining which private subnets can host the PostgreSQL database + SubnetIds: + - !Ref ExistingPrivateSubnet1Id + - !Ref ExistingPrivateSubnet2Id + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-postgres-subnet-group" + + AuroraCluster: + Type: AWS::RDS::DBCluster + Properties: + Engine: aurora-postgresql + EngineVersion: 16.8 + Port: 5432 + DBClusterIdentifier: + Fn::Join: + - "-" + - - Ref: "AWS::StackName" + - Ref: "DBInstanceIdentifier" + DBClusterParameterGroupName: default.aurora-postgresql16 + DBSubnetGroupName: !Ref DBSubnetGroup + DatabaseName: !Ref DBName + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + ServerlessV2ScalingConfiguration: + MinCapacity: 0.5 + MaxCapacity: 4 + StorageEncrypted: true + DeletionProtection: !If [IsProd, true, false] + VpcSecurityGroupIds: + - !GetAtt DBSecurityGroup.GroupId + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-aurora" + + AuroraInstance: + Type: AWS::RDS::DBInstance + Properties: + Engine: aurora-postgresql + DBInstanceIdentifier: + Fn::Join: + - "-" + - - Ref: "AWS::StackName" + - Ref: "DBInstanceIdentifier" + DBClusterIdentifier: !Ref AuroraCluster + DBInstanceClass: db.serverless + PubliclyAccessible: false + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-aurora-instance" + + # ------------------------------------------------------------------------------------------------ + # ElastiCache Redis - Redis cache for E2B platform + # ------------------------------------------------------------------------------------------------ + RedisSubnetGroup: + Type: AWS::ElastiCache::SubnetGroup + Properties: + Description: Subnet group for Redis cache + SubnetIds: + - !Ref ExistingPrivateSubnet1Id + - !Ref ExistingPrivateSubnet2Id + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-redis-subnet-group" + + RedisServerless: + Type: AWS::ElastiCache::ServerlessCache + Properties: + Engine: redis + ServerlessCacheName: !Sub "${AWS::StackName}-redis" + SecurityGroupIds: + - !GetAtt RedisSecurityGroup.GroupId + SubnetIds: + - !Ref ExistingPrivateSubnet1Id + - !Ref ExistingPrivateSubnet2Id + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-redis" + + # ------------------------------------------------------------------------------------------------ + # EC2 Instance - Terraform Bastion Host for infrastructure management + # ------------------------------------------------------------------------------------------------ + BastionInstance: + Type: AWS::EC2::Instance + Metadata: + Comment: "Terraform Bastion Host for deploying and managing E2B infrastructure components" + Properties: + InstanceType: !If + - IsX64 + - c6i.xlarge + - c7g.xlarge + KeyName: !Ref KeyName + IamInstanceProfile: !Ref EC2InstanceProfile + SubnetId: !Ref ExistingPrivateSubnet1Id + SourceDestCheck: false + EbsOptimized: true + Monitoring: true + ImageId: !If + - IsX64 + - "{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}" + - "{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}" + BlockDeviceMappings: + - DeviceName: /dev/sda1 + Ebs: + VolumeSize: 40 + VolumeType: gp3 + Encrypted: true + SecurityGroupIds: + - !Ref BastionSecurityGroup + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-bastion" + UserData: !Base64 + Fn::Join: + - "" + - - | + #!/bin/bash -v + set -e + - | + # Update system packages to latest versions + apt update -y + - | + # Install Go programming language for building E2B components + snap install go --classic + - | + # Install essential development and deployment tools + apt install unzip docker.io make jq postgresql-client-common -y + - | + # Install PostgreSQL client for database management + apt install postgresql-client -y + - | + # Setup Docker buildx for multi-architecture container builds + mkdir -p /root/.docker/cli-plugins + - !If + - IsX64 + - | + wget -O /root/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.21.1/buildx-v0.21.1.linux-amd64 + wget -O /opt/awscli.zip https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip + wget -O /opt/packer.zip https://releases.hashicorp.com/packer/1.12.0/packer_1.12.0_linux_amd64.zip + wget -O /opt/terraform.zip https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_amd64.zip + wget -O /opt/nomad.zip https://releases.hashicorp.com/nomad/1.6.2/nomad_1.6.2_linux_amd64.zip + - | + wget -O /root/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.21.1/buildx-v0.21.1.linux-arm64 + wget -O /opt/awscli.zip https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip + wget -O /opt/packer.zip https://releases.hashicorp.com/packer/1.12.0/packer_1.12.0_linux_arm64.zip + wget -O /opt/terraform.zip https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_arm64.zip + wget -O /opt/nomad.zip https://releases.hashicorp.com/nomad/1.6.2/nomad_1.6.2_linux_arm64.zip + - | + chmod +x /root/.docker/cli-plugins/docker-buildx + - | + cd /opt + - | + # Install AWS CLI for infrastructure management + unzip awscli.zip && ./aws/install && rm awscli.zip + - !Sub | + # Configure AWS CLI default region + aws configure set region ${AWS::Region} + - | + # Install HashiCorp Packer for creating machine images + unzip packer.zip && mv packer /usr/local/bin/packer && rm packer.zip + - | + # Install HashiCorp Terraform for infrastructure as code + unzip terraform.zip && mv terraform /usr/local/bin/terraform && rm terraform.zip + - | + # Install HashiCorp Nomad for workload orchestration + unzip nomad.zip && mv nomad /usr/local/bin/ && rm nomad.zip + - | + # Create directory for E2B infrastructure code + mkdir -p /opt/infra/ && cd /opt/infra/ + git clone https://github.com/aws-samples/sample-e2b-on-aws.git && cd sample-e2b-on-aws + git checkout existing-vpc + - !Sub | + # Initialize Configuration + touch /tmp/e2b.log + echo "StackName=${AWS::StackName}" >> /tmp/e2b.log + BUILD=$(git rev-parse --short HEAD) + echo "BUILD=$BUILD" >> /tmp/e2b.log + while true; do + STACK_STATUS=$(aws cloudformation describe-stacks --stack-name ${AWS::StackName} --query "Stacks[0].StackStatus" --output text) + echo "$(date '+%Y-%m-%d %H:%M:%S') - Stack current state: $STACK_STATUS" >> /tmp/e2b.log + case $STACK_STATUS in + CREATE_COMPLETE) + echo "========================================" >> /tmp/e2b.log + echo "Start to execute init.sh" >> /tmp/e2b.log + echo "========================================" >> /tmp/e2b.log + bash infra-iac/init.sh >> /tmp/e2b.log 2>&1 + echo "========================================" >> /tmp/e2b.log + echo "Start to execute packer.sh" >> /tmp/e2b.log + echo "========================================" >> /tmp/e2b.log + HOME=/root bash -l infra-iac/packer/packer.sh >> /tmp/e2b.log 2>&1 + echo "========================================" >> /tmp/e2b.log + echo "Start to execute terraform" >> /tmp/e2b.log + echo "========================================" >> /tmp/e2b.log + bash infra-iac/terraform/start.sh >> /tmp/e2b.log 2>&1 + echo "========================================" >> /tmp/e2b.log + echo "Start to execute init-db.sh" >> /tmp/e2b.log + echo "========================================" >> /tmp/e2b.log + bash infra-iac/db/init-db.sh >> /tmp/e2b.log 2>&1 + echo "========================================" >> /tmp/e2b.log + echo "Start to execute build.sh" >> /tmp/e2b.log + echo "========================================" >> /tmp/e2b.log + HOME=/root bash packages/build.sh >> /tmp/e2b.log 2>&1 + echo "========================================" >> /tmp/e2b.log + echo "Start to execute nomad.sh" >> /tmp/e2b.log + echo "========================================" >> /tmp/e2b.log + source nomad/nomad.sh >> /tmp/e2b.log 2>&1 + echo "========================================" >> /tmp/e2b.log + echo "Start to execute prepare.sh" >> /tmp/e2b.log + echo "========================================" >> /tmp/e2b.log + bash nomad/prepare.sh >> /tmp/e2b.log 2>&1 + echo "========================================" >> /tmp/e2b.log + echo "Start to execute deploy.sh" >> /tmp/e2b.log + echo "========================================" >> /tmp/e2b.log + bash nomad/deploy.sh >> /tmp/e2b.log 2>&1 + echo "========================================" >> /tmp/e2b.log + echo "Start to execute create_template.sh" >> /tmp/e2b.log + echo "========================================" >> /tmp/e2b.log + bash packages/create_template.sh >> /tmp/e2b.log 2>&1 + echo "========================================" >> /tmp/e2b.log + echo "E2B Deploy Done!" >> /tmp/e2b.log + echo "========================================" >> /tmp/e2b.log + break + ;; + CREATE_FAILED|ROLLBACK_COMPLETE|ROLLBACK_FAILED|UPDATE_ROLLBACK_COMPLETE|UPDATE_ROLLBACK_FAILED|DELETE_FAILED) + echo "exit with error cloudformation state: $STACK_STATUS" >> /tmp/e2b.log + exit 1 + ;; + *) + sleep 10 + ;; + esac + done + +# =================================================================================================== +# Outputs - Values exported after stack creation for reference by other stacks +# =================================================================================================== +Outputs: + # Database outputs + DBEndpoint: + Description: Aurora PostgreSQL database connection endpoint address + Value: !GetAtt AuroraCluster.Endpoint.Address + + DBReaderEndpoint: + Description: Aurora PostgreSQL database reader endpoint address + Value: !GetAtt AuroraCluster.ReadEndpoint.Address + + # Stack information + CFNSTACKNAME: + Description: CloudFormation stack name for reference in other templates + Value: !Ref AWS::StackName + Export: + Name: CFNSTACKNAME + + # VPC outputs + CFNVPCID: + Description: VPC ID for the E2B infrastructure network + Value: !Ref ExistingVpcId + Export: + Name: CFNVPCID + + CFNVPCCIDR: + Description: VPC CIDR Block defining the overall network address space (automatically retrieved) + Value: !GetAtt VpcCidrLookup.CidrBlock + Export: + Name: CFNVPCCIDR + + # Public Access Configuration + CFNPUBLICACCESS: + Description: Public or Private access configuration + Value: !Ref PublicAccess + Export: + Name: CFNPUBLICACCESS + + # Subnet outputs + CFNPRIVATESUBNET1: + Description: Private Subnet ID in first availability zone for secure resources + Value: !Ref ExistingPrivateSubnet1Id + Export: + Name: CFNPRIVATESUBNET1 + + CFNPRIVATESUBNET2: + Description: Private Subnet ID in second availability zone for secure resources + Value: !Ref ExistingPrivateSubnet2Id + Export: + Name: CFNPRIVATESUBNET2 + + CFNPUBLICSUBNET1: + Description: Public Subnet ID in first availability zone for internet-facing resources + Value: !Ref ExistingPublicSubnet1Id + Export: + Name: CFNPUBLICSUBNET1 + + CFNPUBLICSUBNET2: + Description: Public Subnet ID in second availability zone for internet-facing resources + Value: !Ref ExistingPublicSubnet2Id + Export: + Name: CFNPUBLICSUBNET2 + + # S3 bucket outputs + CFNTERRAFORMBUCKET: + Description: S3 bucket name for storing Terraform state files + Value: !Ref TerraformS3Bucket + Export: + Name: CFNTERRAFORMBUCKET + + CFNSOFTWAREBUCKET: + Description: S3 bucket name for storing E2B software artifacts + Value: !Ref SoftwareS3Bucket + Export: + Name: CFNSOFTWAREBUCKET + + # SSH key output + CFNSSHKEY: + Description: EC2 SSH Key Name for bastion host access + Value: !Ref KeyName + Export: + Name: CFNSSHKEY + + # Database connection string + CFNDBURL: + Description: Complete PostgreSQL connection string for application configuration + Value: !Sub + - "postgresql://${DBUsername}:${DBPassword}@${DBEndpoint}/${DBName}" + - DBEndpoint: !GetAtt AuroraCluster.Endpoint.Address + Export: + Name: CFNDBURL + + # Domain and certificate outputs + CFNDOMAIN: + Description: Base domain name for E2B services + Value: !Ref BaseDomain + Export: + Name: CFNDOMAIN + + CFNCERTARN: + Description: SSL Certificate ARN for HTTPS endpoints + Value: !Ref WildcardCertificate + Export: + Name: CFNCERTARN + + # Redis outputs + REDISNAME: + Description: Redis cache name + Value: !Sub "${AWS::StackName}-redis" + Export: + Name: CFNREDISNAME + + REDISENDPOINT: + Description: Complete Redis connection string for application configuration + Value: !GetAtt RedisServerless.Endpoint.Address + Export: + Name: CFNREDISURL + + ENVIRONMENT: + Description: E2B Environment + Value: !Ref Environment + Export: + Name: CFNENVIRONMENT + + ARCHITECTURE: + Description: E2B Cluster CPU Architecture + Value: !Ref Architecture + Export: + Name: CFNARCHITECTURE + + REGION: + Description: E2B Cluster Deployment Region + Value: !Ref AWS::Region + Export: + Name: AWSREGION + + STACKNAME: + Description: CloudFormation Stack Name + Value: !Ref AWS::StackName + Export: + Name: AWSSTACKNAME + + # Bastion Host information + # BASTIONPUBLICDNS: + # Description: Public DNS name of the Bastion Host for SSH access + # Value: !GetAtt BastionInstance.PublicDnsName + + # BASTIONPUBLICIP: + # Description: Public IP address of the Bastion Host for SSH access + # Value: !GetAtt BastionInstance.PublicIp diff --git a/e2b-setup-env.yml b/e2b-setup-env.yml index f0e4f49..b054e59 100644 --- a/e2b-setup-env.yml +++ b/e2b-setup-env.yml @@ -17,6 +17,7 @@ Metadata: - PublicSubnet2Block - PrivateSubnet1Block - PrivateSubnet2Block + - PublicAccess - Label: default: Security Configuration Parameters: @@ -49,7 +50,7 @@ Metadata: # Parameters - Input values required for the E2B infrastructure deployment # =================================================================================================== Parameters: - # Architecture Configuration - Choose CPU architecture + # E2B Environment Configuration Environment: Description: "E2B Environment" Type: String @@ -101,6 +102,14 @@ Parameters: Default: 10.0.48.0/20 Description: CIDR block for private subnet in Availability Zone 2 (provides 4,096 IP addresses for internal resources) + PublicAccess: + Type: String + Description: Specify whether public or private access to E2B + AllowedValues: + - Public + - Private + Default: Public + # Bastion Configuration - Settings for the deployment and management server KeyName: Description: EC2 Key Pair name for SSH access to the bastion host (deployment server) @@ -378,9 +387,245 @@ Resources: Action: - sts:AssumeRole ManagedPolicyArns: - - arn:aws:iam::aws:policy/PowerUserAccess - - arn:aws:iam::aws:policy/IAMFullAccess - Description: IAM role granting EC2 instances permissions to manage E2B infrastructure resources + - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore + Policies: + - PolicyName: E2BDeploymentPolicy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: S3Access + Effect: Allow + Action: + - s3:CreateBucket + - s3:DeleteBucket + - s3:GetObject + - s3:PutObject + - s3:DeleteObject + - s3:ListBucket + - s3:GetBucketLocation + - s3:GetBucketVersioning + - s3:PutBucketVersioning + - s3:PutBucketPolicy + - s3:GetBucketPolicy + - s3:PutBucketTagging + - s3:GetBucketTagging + - s3:PutEncryptionConfiguration + - s3:GetEncryptionConfiguration + - s3:PutBucketPublicAccessBlock + - s3:GetBucketPublicAccessBlock + - s3:GetBucketAcl + - s3:PutBucketAcl + - s3:GetBucketCors + - s3:PutBucketCors + - s3:GetBucketWebsite + - s3:PutBucketWebsite + - s3:GetAccelerateConfiguration + - s3:PutAccelerateConfiguration + - s3:GetBucketRequestPayment + - s3:PutBucketRequestPayment + - s3:GetBucketLogging + - s3:PutBucketLogging + - s3:GetLifecycleConfiguration + - s3:PutLifecycleConfiguration + - s3:GetReplicationConfiguration + - s3:PutReplicationConfiguration + - s3:GetBucketObjectLockConfiguration + - s3:PutBucketObjectLockConfiguration + - s3:GetObjectTagging + - s3:PutObjectTagging + Resource: + - "arn:aws:s3:::*e2b*" + - "arn:aws:s3:::*e2b*/*" + - "arn:aws:s3:::terraform-*" + - "arn:aws:s3:::terraform-*/*" + - "arn:aws:s3:::software-*" + - "arn:aws:s3:::software-*/*" + - Sid: SecretsManagerAccess + Effect: Allow + Action: + - secretsmanager:CreateSecret + - secretsmanager:GetSecretValue + - secretsmanager:PutSecretValue + - secretsmanager:DeleteSecret + - secretsmanager:DescribeSecret + - secretsmanager:GetResourcePolicy + - secretsmanager:TagResource + - secretsmanager:UntagResource + - secretsmanager:UpdateSecret + Resource: !Sub "arn:aws:secretsmanager:*:${AWS::AccountId}:secret:*e2b*" + - Sid: EC2PackerAccess + Effect: Allow + Action: + - ec2:AttachVolume + - ec2:AuthorizeSecurityGroupIngress + - ec2:AuthorizeSecurityGroupEgress + - ec2:CopyImage + - ec2:CreateImage + - ec2:CreateKeypair + - ec2:CreateSecurityGroup + - ec2:CreateSnapshot + - ec2:CreateTags + - ec2:CreateVolume + - ec2:CreateLaunchTemplate + - ec2:CreateLaunchTemplateVersion + - ec2:CreateNetworkInterface + - ec2:DeleteKeyPair + - ec2:DeleteSecurityGroup + - ec2:DeleteSnapshot + - ec2:DeleteVolume + - ec2:DeleteLaunchTemplate + - ec2:DeleteNetworkInterface + - ec2:DeregisterImage + - ec2:DescribeImageAttribute + - ec2:DescribeImages + - ec2:DescribeInstances + - ec2:DescribeInstanceStatus + - ec2:DescribeRegions + - ec2:DescribeSecurityGroups + - ec2:DescribeSnapshots + - ec2:DescribeSubnets + - ec2:DescribeTags + - ec2:DescribeVolumes + - ec2:DescribeLaunchTemplates + - ec2:DescribeLaunchTemplateVersions + - ec2:DescribeVpcs + - ec2:DescribeAvailabilityZones + - ec2:DescribeKeyPairs + - ec2:DescribeNetworkInterfaces + - ec2:DetachVolume + - ec2:GetPasswordData + - ec2:ModifyImageAttribute + - ec2:ModifyInstanceAttribute + - ec2:ModifySnapshotAttribute + - ec2:ModifyLaunchTemplate + - ec2:RegisterImage + - ec2:RunInstances + - ec2:StopInstances + - ec2:TerminateInstances + - ec2:RevokeSecurityGroupIngress + - ec2:RevokeSecurityGroupEgress + Resource: "*" + - Sid: AutoScalingAndELB + Effect: Allow + Action: + - autoscaling:* + - elasticloadbalancing:* + Resource: "*" + - Sid: ECRAccess + Effect: Allow + Action: + - ecr:GetAuthorizationToken + - ecr:BatchCheckLayerAvailability + - ecr:GetDownloadUrlForLayer + - ecr:BatchGetImage + - ecr:PutImage + - ecr:InitiateLayerUpload + - ecr:UploadLayerPart + - ecr:CompleteLayerUpload + - ecr:CreateRepository + - ecr:DeleteRepository + - ecr:DescribeRepositories + - ecr:ListImages + - ecr:DescribeImages + - ecr:TagResource + Resource: + - "*" + - !Sub "arn:aws:ecr:*:${AWS::AccountId}:repository/e2b-*" + - Sid: IAMAccess + Effect: Allow + Action: + - iam:CreateRole + - iam:DeleteRole + - iam:GetRole + - iam:ListRoles + - iam:UpdateRole + - iam:TagRole + - iam:UntagRole + - iam:CreateInstanceProfile + - iam:DeleteInstanceProfile + - iam:GetInstanceProfile + - iam:ListInstanceProfiles + - iam:ListInstanceProfilesForRole + - iam:AddRoleToInstanceProfile + - iam:RemoveRoleFromInstanceProfile + - iam:CreatePolicy + - iam:DeletePolicy + - iam:GetPolicy + - iam:GetPolicyVersion + - iam:ListPolicies + - iam:ListPolicyVersions + - iam:ListAttachedRolePolicies + - iam:AttachRolePolicy + - iam:DetachRolePolicy + - iam:PutRolePolicy + - iam:GetRolePolicy + - iam:DeleteRolePolicy + - iam:ListRolePolicies + - iam:TagPolicy + - iam:UntagPolicy + Resource: + - !Sub "arn:aws:iam::${AWS::AccountId}:role/*e2b*" + - !Sub "arn:aws:iam::${AWS::AccountId}:instance-profile/*e2b*" + - !Sub "arn:aws:iam::${AWS::AccountId}:policy/*e2b*" + - Sid: IAMAttachAWSManagedPolicy + Effect: Allow + Action: + - iam:AttachRolePolicy + - iam:DetachRolePolicy + Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/*e2b*" + Condition: + ArnEquals: + iam:PolicyARN: + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly + - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy + - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore + - arn:aws:iam::aws:policy/AmazonEC2FullAccess + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess + - arn:aws:iam::aws:policy/AmazonS3FullAccess + - arn:aws:iam::aws:policy/SecretsManagerReadWrite + - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role + - Sid: IAMPassRole + Effect: Allow + Action: + - iam:PassRole + Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/*e2b*" + Condition: + StringEquals: + iam:PassedToService: + - ec2.amazonaws.com + - ecs-tasks.amazonaws.com + - Sid: LogsAndMonitoring + Effect: Allow + Action: + - logs:* + - cloudwatch:* + Resource: "*" + - Sid: ElastiCacheAccess + Effect: Allow + Action: + - elasticache:DescribeCacheClusters + - elasticache:DescribeServerlessCaches + Resource: "*" + - Sid: CloudFormation + Effect: Allow + Action: + - cloudformation:DescribeStacks + - cloudformation:ListStacks + Resource: "*" + - Sid: SSMAccess + Effect: Allow + Action: + - ssm:GetParameter* + - ssm:PutParameter + - ssm:DeleteParameter + - ssm:DescribeParameters + Resource: !Sub "arn:aws:ssm:*:${AWS::AccountId}:parameter/*e2b*" + - Sid: STSAccess + Effect: Allow + Action: + - sts:GetCallerIdentity + Resource: "*" + Description: IAM role with complete permissions for E2B infrastructure deployment including Packer and Terraform EC2InstanceProfile: Type: AWS::IAM::InstanceProfile @@ -550,7 +795,7 @@ Resources: Properties: InstanceType: !If - IsX64 - - c7i.xlarge + - c6i.xlarge - c7g.xlarge KeyName: !Ref KeyName IamInstanceProfile: !Ref EC2InstanceProfile @@ -697,25 +942,6 @@ Resources: # Outputs - Values exported after stack creation for reference by other stacks # =================================================================================================== Outputs: - # Availability Zone outputs - CFNAZ1: - Description: First Availability Zone used for high availability deployment - Value: !Select - - "0" - - !GetAZs - Ref: AWS::Region - Export: - Name: CFNAZ1 - - CFNAZ2: - Description: Second Availability Zone used for high availability deployment - Value: !Select - - "1" - - !GetAZs - Ref: AWS::Region - Export: - Name: CFNAZ2 - # Database outputs DBEndpoint: Description: Aurora PostgreSQL database connection endpoint address @@ -745,6 +971,13 @@ Outputs: Export: Name: CFNVPCCIDR + # Public Access Configuration + CFNPUBLICACCESS: + Description: Public or Private access configuration + Value: !Ref PublicAccess + Export: + Name: CFNPUBLICACCESS + # Subnet outputs CFNPRIVATESUBNET1: Description: Private Subnet ID in first availability zone for secure resources diff --git a/infra-iac/init.sh b/infra-iac/init.sh index a197bc4..7d82a23 100644 --- a/infra-iac/init.sh +++ b/infra-iac/init.sh @@ -34,6 +34,14 @@ setup_environment() { REGION=$(aws configure get region) echo "AWSREGION=$REGION" >> /opt/config.properties + + SUBNET1=$(grep "^CFNPRIVATESUBNET1=" /opt/config.properties | cut -d= -f2) + SUBNET2=$(grep "^CFNPRIVATESUBNET2=" /opt/config.properties | cut -d= -f2) + AZ1=$(aws ec2 describe-subnets --subnet-ids $SUBNET1 --query 'Subnets[*].[AvailabilityZone]' --output text) + AZ2=$(aws ec2 describe-subnets --subnet-ids $SUBNET2 --query 'Subnets[*].[AvailabilityZone]' --output text) + echo "CFNAZ1=$AZ1" >> /opt/config.properties + echo "CFNAZ2=$AZ2" >> /opt/config.properties + # Verification output echo "=== Exported Variables ===" cat /opt/config.properties diff --git a/infra-iac/packer/main.pkr.hcl b/infra-iac/packer/main.pkr.hcl index c58a63f..5a8dd35 100644 --- a/infra-iac/packer/main.pkr.hcl +++ b/infra-iac/packer/main.pkr.hcl @@ -12,6 +12,8 @@ source "amazon-ebs" "orch" { ami_name = "e2b-ubuntu-ami-${formatdate("YYYY-MM-DD-hh-mm-ss", timestamp())}" instance_type = var.architecture == "x86_64" ? "t3.xlarge" : "t4g.xlarge" region = var.aws_region + vpc_id = var.vpc_id + subnet_id = var.subnet_id source_ami_filter { filters = { diff --git a/infra-iac/packer/packer.sh b/infra-iac/packer/packer.sh index 0efd0e8..60aee9d 100644 --- a/infra-iac/packer/packer.sh +++ b/infra-iac/packer/packer.sh @@ -50,4 +50,8 @@ sleep 10 echo "Starting Packer build with architecture: ${ARCHITECTURE}" -packer build -only=amazon-ebs.orch -var "aws_region=${AWS_REGION}" -var "architecture=${ARCHITECTURE}" . \ No newline at end of file +VPC_ID=$(grep "^CFNVPCID=" "$CONFIG_FILE" | cut -d'=' -f2) +SUBNET_ID=$(grep "^CFNPRIVATESUBNET1=" "$CONFIG_FILE" | cut -d'=' -f2) +echo "Using VPC: ${VPC_ID}" +echo "Using Subnet: ${SUBNET_ID}" +packer build -only=amazon-ebs.orch -var "aws_region=${AWS_REGION}" -var "architecture=${ARCHITECTURE}" -var "vpc_id=${VPC_ID}" -var "subnet_id=${SUBNET_ID}" . \ No newline at end of file diff --git a/infra-iac/packer/variables.pkr.hcl b/infra-iac/packer/variables.pkr.hcl index 4356784..c8e4481 100644 --- a/infra-iac/packer/variables.pkr.hcl +++ b/infra-iac/packer/variables.pkr.hcl @@ -36,6 +36,16 @@ variable "image_family" { default = "e2b-orch" } +variable "vpc_id" { + type = string + default = "" +} + +variable "subnet_id" { + type = string + default = "" +} + variable "consul_version" { type = string default = "1.16.2" diff --git a/infra-iac/terraform/main.tf b/infra-iac/terraform/main.tf index acd7e84..0a29a4a 100644 --- a/infra-iac/terraform/main.tf +++ b/infra-iac/terraform/main.tf @@ -43,7 +43,6 @@ locals { common_tags = { Environment = var.environment Project = "E2B" - Owner = "AWS" ManagedBy = "Terraform" } @@ -416,6 +415,13 @@ resource "aws_launch_template" "server" { name = aws_iam_instance_profile.ec2_instance_profile.name } + metadata_options { + http_endpoint = "enabled" + http_tokens = "required" + http_put_response_hop_limit = 1 + instance_metadata_tags = "enabled" + } + block_device_mappings { device_name = "/dev/sda1" @@ -428,7 +434,7 @@ resource "aws_launch_template" "server" { } network_interfaces { - associate_public_ip_address = true + associate_public_ip_address = false security_groups = [aws_security_group.server_sg.id] } @@ -451,7 +457,12 @@ resource "aws_launch_template" "server" { local.common_tags, { Name = "server-cluster", - ec2-e2b-key = "ec2-e2b-value" + ec2-e2b-key = "ec2-e2b-value", + team = "GENAI", + service = "GENAI", + owner = "GENAI", + cost_center = "GENAI", + component = "GENAI" } ) } @@ -462,7 +473,7 @@ resource "aws_launch_template" "server" { # Create server auto scaling group resource "aws_autoscaling_group" "server" { name = "${var.prefix}-server-asg" - vpc_zone_identifier = var.VPC.public_subnets + vpc_zone_identifier = var.VPC.private_subnets desired_capacity = local.clusters.server.desired_capacity max_size = local.clusters.server.max_size min_size = local.clusters.server.min_size @@ -547,7 +558,7 @@ resource "aws_launch_template" "client" { metadata_options { http_endpoint = "enabled" - http_tokens = "optional" + http_tokens = "required" http_put_response_hop_limit = 1 instance_metadata_tags = "enabled" } @@ -575,7 +586,7 @@ resource "aws_launch_template" "client" { } network_interfaces { - associate_public_ip_address = true + associate_public_ip_address = false security_groups = [aws_security_group.client_sg.id] } @@ -602,7 +613,12 @@ resource "aws_launch_template" "client" { local.common_tags, { Name = "client-cluster", - ec2-e2b-key = "ec2-e2b-value" + ec2-e2b-key = "ec2-e2b-value", + team = "GENAI", + service = "GENAI", + owner = "GENAI", + cost_center = "GENAI", + component = "GENAI" } ) } @@ -613,7 +629,7 @@ resource "aws_launch_template" "client" { # Create client auto scaling group resource "aws_autoscaling_group" "client" { name = "${var.prefix}-client-asg" - vpc_zone_identifier = var.VPC.public_subnets + vpc_zone_identifier = var.VPC.private_subnets # desired_capacity = var.client_asg_desired_capacity # max_size = max(var.client_asg_max_size, var.client_asg_desired_capacity) # min_size = var.client_asg_desired_capacity @@ -712,27 +728,27 @@ resource "aws_security_group" "api_sg" { ) } -# Create public-facing Application Load Balancer -resource "aws_lb" "publicalb" { - name = "${var.prefix}-public-alb" - internal = false +# Create Application Load Balancer +resource "aws_lb" "alb" { + name = "${var.prefix}-alb" + internal = var.publicaccess == "private" ? true : false load_balancer_type = "application" - security_groups = [aws_security_group.public_alb_sg.id] - subnets = var.VPC.public_subnets + security_groups = [aws_security_group.alb_sg.id] + subnets = var.publicaccess == "private" ? var.VPC.private_subnets : var.VPC.public_subnets enable_deletion_protection = var.environment == "prod" ? true : false tags = merge( local.common_tags, { - Name = "${var.prefix}-public-alb" + Name = "${var.prefix}-alb" } ) } -# Security group for public ALB -resource "aws_security_group" "public_alb_sg" { - name = "${var.prefix}-public-alb-sg" - description = "Security group for public ALB" +# Security group for ALB +resource "aws_security_group" "alb_sg" { + name = "${var.prefix}-alb-sg" + description = "Security group for ALB" vpc_id = var.VPC.id # HTTP @@ -762,7 +778,7 @@ resource "aws_security_group" "public_alb_sg" { tags = merge( local.common_tags, { - Name = "${var.prefix}-public-alb-sg" + Name = "${var.prefix}-alb-sg" } ) } @@ -892,9 +908,9 @@ resource "aws_autoscaling_attachment" "docker-proxy" { lb_target_group_arn = aws_lb_target_group.docker-proxy.arn } -# Create HTTP listener for public ALB with default action to client-proxy +# Create HTTP listener for ALB with default action to client-proxy resource "aws_lb_listener" "http" { - load_balancer_arn = aws_lb.publicalb.arn + load_balancer_arn = aws_lb.alb.arn port = 443 protocol = "HTTPS" ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06" @@ -905,9 +921,9 @@ resource "aws_lb_listener" "http" { } } -# Create HTTPS listener for public ALB (commented out as it requires a certificate) +# Create HTTPS listener for ALB (commented out as it requires a certificate) # resource "aws_lb_listener" "https" { -# load_balancer_arn = aws_lb.publicalb.arn +# load_balancer_arn = aws_lb.alb.arn # port = 443 # protocol = "HTTPS" # ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06" @@ -982,6 +998,13 @@ resource "aws_launch_template" "api" { name = aws_iam_instance_profile.ec2_instance_profile.name } + metadata_options { + http_endpoint = "enabled" + http_tokens = "required" + http_put_response_hop_limit = 1 + instance_metadata_tags = "enabled" + } + block_device_mappings { device_name = "/dev/sda1" @@ -994,7 +1017,7 @@ resource "aws_launch_template" "api" { } network_interfaces { - associate_public_ip_address = true + associate_public_ip_address = false security_groups = [aws_security_group.api_sg.id] } @@ -1021,7 +1044,12 @@ resource "aws_launch_template" "api" { local.common_tags, { Name = "api-cluster", - ec2-e2b-key = "ec2-e2b-value" + ec2-e2b-key = "ec2-e2b-value", + team = "GENAI", + service = "GENAI", + owner = "GENAI", + cost_center = "GENAI", + component = "GENAI" } ) } @@ -1032,7 +1060,7 @@ resource "aws_launch_template" "api" { # Create API auto scaling group resource "aws_autoscaling_group" "api" { name = "${var.prefix}-api-asg" - vpc_zone_identifier = var.VPC.public_subnets + vpc_zone_identifier = var.VPC.private_subnets # desired_capacity = var.api_asg_desired_capacity # max_size = var.api_asg_desired_capacity # min_size = var.api_asg_desired_capacity @@ -1130,6 +1158,13 @@ resource "aws_launch_template" "build" { name = aws_iam_instance_profile.ec2_instance_profile.name } + metadata_options { + http_endpoint = "enabled" + http_tokens = "required" + http_put_response_hop_limit = 1 + instance_metadata_tags = "enabled" + } + block_device_mappings { device_name = "/dev/sda1" @@ -1142,7 +1177,7 @@ resource "aws_launch_template" "build" { } network_interfaces { - associate_public_ip_address = true + associate_public_ip_address = false security_groups = [aws_security_group.build_sg.id] } @@ -1169,7 +1204,12 @@ resource "aws_launch_template" "build" { local.common_tags, { Name = "build-cluster", - ec2-e2b-key = "ec2-e2b-value" + ec2-e2b-key = "ec2-e2b-value", + team = "GENAI", + service = "GENAI", + owner = "GENAI", + cost_center = "GENAI", + component = "GENAI" } ) } @@ -1180,7 +1220,7 @@ resource "aws_launch_template" "build" { # Create build auto scaling group resource "aws_autoscaling_group" "build" { name = "${var.prefix}-build-asg" - vpc_zone_identifier = var.VPC.public_subnets + vpc_zone_identifier = var.VPC.private_subnets # desired_capacity = var.build_asg_desired_capacity # max_size = var.build_asg_desired_capacity # min_size = var.build_asg_desired_capacity diff --git a/infra-iac/terraform/var.tf.tpl b/infra-iac/terraform/var.tf.tpl index 38f83cf..b065849 100644 --- a/infra-iac/terraform/var.tf.tpl +++ b/infra-iac/terraform/var.tf.tpl @@ -65,3 +65,9 @@ variable "architecture" { type = string default = "${CFNARCHITECTURE}" } + +variable "publicaccess" { + description = "Specify whether public or private access to E2B" + type = string + default = "${CFNPUBLICACCESS}" +} \ No newline at end of file diff --git a/packages/create_template.sh b/packages/create_template.sh index 048f547..906e957 100644 --- a/packages/create_template.sh +++ b/packages/create_template.sh @@ -223,11 +223,19 @@ while true; do if [ "$STATUS" != "building" ]; then echo "Build is no longer in 'building' state. Final status: $STATUS" - echo "Done!" break fi sleep 10 done -echo "Building completed successfully!" \ No newline at end of file +# Check final build status +if [ "$STATUS" = "error" ] || [ "$STATUS" = "failed" ]; then + echo "Building failed with status: $STATUS" + exit 1 +elif [ "$STATUS" = "ready" ] || [ "$STATUS" = "success" ]; then + echo "Building completed successfully!" +else + echo "Building finished with unknown status: $STATUS" + exit 1 +fi \ No newline at end of file diff --git a/packages/upload.sh b/packages/upload.sh index da11350..f331783 100644 --- a/packages/upload.sh +++ b/packages/upload.sh @@ -66,7 +66,7 @@ if [ "$ARCHITECTURE" = "arm64" ]; then rm -rf release-${latest_version}-aarch64 else # Download kernel - curl -L https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/$CI_VERSION/x86_64/vmlinux-$KERNEL_VERSION -o ${TEMP_DIR}/kernels/${KERNEL_FOLDER}/vmlinux.bin + curl -L https://storage.googleapis.com/e2b-prod-public-builds/kernels/vmlinux-6.1.102/vmlinux.bin -o ${TEMP_DIR}/kernels/${KERNEL_FOLDER}/vmlinux.bin # Download firecracker curl -L ${fc_url}/download/${FC_VERSION}/firecracker-${FC_VERSION}-x86_64.tgz | tar -xz mv release-${FC_VERSION}-x86_64/firecracker-${FC_VERSION}-x86_64 \