forked from TracecatHQ/tracecat
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ci(infra): Terraform stack for EC2 + SSM port forwarding deployment (T…
…racecatHQ#291) * Add terraform paths to .gitignore * Add single instance EC2 stack * fix: Missing vpc endpoints for ssm in private subset * Missing curl Caddyfile * Add user input for prod / dev mode and public IP * Parameterize tracecat version * fix: tracecat_version * Parameterize disable_ssl for postgres * refactor: Consolidate public and internal api / app urls * Add region to local-exec command * Bump image versions
- Loading branch information
Showing
11 changed files
with
450 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
provider "aws" { | ||
region = var.aws_region | ||
} | ||
|
||
data "aws_ami" "this" { | ||
most_recent = true | ||
owners = ["amazon"] | ||
|
||
filter { | ||
name = "name" | ||
values = ["amzn2-ami-hvm-*-x86_64-gp2"] | ||
} | ||
|
||
filter { | ||
name = "virtualization-type" | ||
values = ["hvm"] | ||
} | ||
} | ||
|
||
locals { | ||
project_tags = { | ||
Project = var.project_name | ||
Environment = var.environment | ||
} | ||
} | ||
|
||
module "vpc" { | ||
source = "terraform-aws-modules/vpc/aws" | ||
version = "~> 5.0" | ||
|
||
name = "${var.project_name}-vpc" | ||
cidr = var.vpc_cidr | ||
|
||
azs = [var.aws_availability_zone] | ||
private_subnets = [var.private_subnet_cidr] | ||
public_subnets = [var.public_subnet_cidr] | ||
|
||
enable_dns_hostnames = true | ||
enable_dns_support = true | ||
enable_nat_gateway = true | ||
single_nat_gateway = true | ||
|
||
tags = merge(local.project_tags, { | ||
Name = "${var.project_name}-vpc" | ||
}) | ||
} | ||
|
||
resource "aws_vpc_endpoint" "ssm" { | ||
vpc_id = module.vpc.vpc_id | ||
service_name = "com.amazonaws.${var.aws_region}.ssm" | ||
vpc_endpoint_type = "Interface" | ||
security_group_ids = [aws_security_group.vpc_endpoints.id] | ||
subnet_ids = module.vpc.private_subnets | ||
private_dns_enabled = true | ||
|
||
tags = merge(local.project_tags, { | ||
Name = "${var.project_name}-ssm-endpoint" | ||
}) | ||
} | ||
|
||
resource "aws_vpc_endpoint" "ec2messages" { | ||
vpc_id = module.vpc.vpc_id | ||
service_name = "com.amazonaws.${var.aws_region}.ec2messages" | ||
vpc_endpoint_type = "Interface" | ||
security_group_ids = [aws_security_group.vpc_endpoints.id] | ||
subnet_ids = module.vpc.private_subnets | ||
private_dns_enabled = true | ||
|
||
tags = merge(local.project_tags, { | ||
Name = "${var.project_name}-ec2messages-endpoint" | ||
}) | ||
} | ||
|
||
resource "aws_vpc_endpoint" "ssmmessages" { | ||
vpc_id = module.vpc.vpc_id | ||
service_name = "com.amazonaws.${var.aws_region}.ssmmessages" | ||
vpc_endpoint_type = "Interface" | ||
security_group_ids = [aws_security_group.vpc_endpoints.id] | ||
subnet_ids = module.vpc.private_subnets | ||
private_dns_enabled = true | ||
|
||
tags = merge(local.project_tags, { | ||
Name = "${var.project_name}-ssmmessages-endpoint" | ||
}) | ||
} | ||
|
||
resource "aws_security_group" "vpc_endpoints" { | ||
name = "${var.project_name}-vpc-endpoints-sg" | ||
description = "Security group for VPC endpoints" | ||
vpc_id = module.vpc.vpc_id | ||
|
||
ingress { | ||
from_port = 443 | ||
to_port = 443 | ||
protocol = "tcp" | ||
cidr_blocks = [var.vpc_cidr] | ||
description = "Allow HTTPS from VPC CIDR" | ||
} | ||
|
||
tags = merge(local.project_tags, { | ||
Name = "${var.project_name}-vpc-endpoints-sg" | ||
}) | ||
} | ||
|
||
resource "aws_security_group" "this" { | ||
name = "${var.project_name}-sg" | ||
description = "Security group for ${var.project_name} EC2 instance" | ||
vpc_id = module.vpc.vpc_id | ||
|
||
egress { | ||
from_port = 0 | ||
to_port = 0 | ||
protocol = "-1" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
description = "Allow all outbound traffic" | ||
} | ||
|
||
ingress { | ||
from_port = 80 | ||
to_port = 80 | ||
protocol = "tcp" | ||
cidr_blocks = [var.vpc_cidr] | ||
description = "Caddy HTTP server" | ||
} | ||
|
||
tags = merge(local.project_tags, { | ||
Name = "${var.project_name}-sg" | ||
}) | ||
} | ||
|
||
resource "aws_iam_role" "this" { | ||
name = "${var.project_name}-role" | ||
|
||
assume_role_policy = jsonencode({ | ||
Version = "2012-10-17" | ||
Statement = [{ | ||
Effect = "Allow" | ||
Principal = { | ||
Service = "ec2.amazonaws.com" | ||
} | ||
Action = "sts:AssumeRole" | ||
}] | ||
}) | ||
|
||
tags = local.project_tags | ||
} | ||
|
||
resource "aws_iam_role_policy_attachment" "ssm" { | ||
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" | ||
role = aws_iam_role.this.name | ||
} | ||
|
||
resource "aws_iam_instance_profile" "this" { | ||
name = "${var.project_name}-profile" | ||
role = aws_iam_role.this.name | ||
|
||
tags = local.project_tags | ||
} | ||
|
||
resource "aws_instance" "this" { | ||
ami = data.aws_ami.this.id | ||
instance_type = var.instance_type | ||
subnet_id = module.vpc.private_subnets[0] | ||
vpc_security_group_ids = [aws_security_group.this.id] | ||
iam_instance_profile = aws_iam_instance_profile.this.name | ||
|
||
metadata_options { | ||
http_endpoint = "enabled" | ||
http_tokens = "required" | ||
http_put_response_hop_limit = 2 | ||
} | ||
|
||
user_data = base64encode(templatefile("${path.module}/user_data.tpl", { | ||
tracecat_version = var.tracecat_version | ||
})) | ||
|
||
provisioner "local-exec" { | ||
command = <<-EOT | ||
aws ec2 wait instance-status-ok --instance-ids ${self.id} --region ${var.aws_region} && \ | ||
sleep 60 && \ | ||
aws ssm send-command \ | ||
--instance-ids ${self.id} \ | ||
--document-name "AWS-RunShellScript" \ | ||
--parameters '{"commands":["cat /var/log/user-data.log"]}' \ | ||
--output text \ | ||
--region ${var.aws_region} \ | ||
--query "Command.CommandId" > ssm_command_id.txt && \ | ||
sleep 10 && \ | ||
aws ssm get-command-invocation \ | ||
--command-id $(cat ssm_command_id.txt) \ | ||
--instance-id ${self.id} \ | ||
--query "StandardOutputContent" \ | ||
--region ${var.aws_region} \ | ||
--output text > user_data_log.txt && \ | ||
if grep -q "ERROR:" user_data_log.txt; then | ||
echo "Error detected in user data log. Log content:" | ||
cat user_data_log.txt | ||
exit 1 | ||
else | ||
echo "User data script completed successfully" | ||
fi | ||
EOT | ||
} | ||
|
||
tags = merge(local.project_tags, { | ||
Name = "${var.project_name}-instance" | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
output "instance_id" { | ||
description = "The ID of the EC2 instance" | ||
value = aws_instance.this.id | ||
} | ||
|
||
output "instance_private_ip" { | ||
description = "The private IP address of the EC2 instance" | ||
value = aws_instance.this.private_ip | ||
} | ||
|
||
output "vpc_id" { | ||
description = "The ID of the VPC" | ||
value = module.vpc.vpc_id | ||
} | ||
|
||
output "security_group_id" { | ||
description = "The ID of the instance security group" | ||
value = aws_security_group.this.id | ||
} | ||
|
||
output "nat_gateway_id" { | ||
value = module.vpc.natgw_ids[0] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#!/bin/bash | ||
# Requires SSM Session Manager plugin to be installed on the local machine: | ||
# https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html | ||
|
||
INSTANCE_ID=$(terraform output -raw instance_id) | ||
LOCAL_PORT=8080 | ||
REMOTE_PORT=80 | ||
|
||
aws ssm start-session \ | ||
--target $INSTANCE_ID \ | ||
--document-name AWS-StartPortForwardingSession \ | ||
--parameters "{\"portNumber\":[\"$REMOTE_PORT\"],\"localPortNumber\":[\"$LOCAL_PORT\"]}" |
Oops, something went wrong.