diff --git a/template/.gitignore b/template/.gitignore new file mode 100644 index 0000000..d3b8bac --- /dev/null +++ b/template/.gitignore @@ -0,0 +1,28 @@ +# Terraform files +*.tfstate +*.tfstate.* +*.tfvars +*.tfvars.json +.terraform/ +.terraform.lock.hcl +terraform.log + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Temporary files +*.tmp +*.temp diff --git a/template/README.md b/template/README.md new file mode 100644 index 0000000..8617bf5 --- /dev/null +++ b/template/README.md @@ -0,0 +1,220 @@ +--- +display_name: Jail Development Environment (AWS EC2) +description: AWS EC2 Linux VM optimized for developing the coder/jail network isolation tool +icon: ../docs/images/logo.png +verified: false +tags: [vm, linux, aws, jail, go, networking, namespaces] +--- + +# Jail Development Environment on AWS EC2 + +This Coder template provisions AWS EC2 VMs specifically configured for developing the [coder/jail](https://github.com/coder/jail) network isolation tool. The template sets up a complete development environment with all necessary dependencies, tools, and configurations. + +## What is Jail? + +Jail is a network isolation tool for monitoring and restricting HTTP/HTTPS requests from processes. It creates isolated network environments for target processes using Linux namespaces and intercepts traffic through a transparent proxy. + +## Features + +- **Linux VM Environment**: Full Linux VM (not containers) required for namespace syscalls +- **Go 1.24+ Development**: Latest Go toolchain automatically installed +- **Network Tools**: iptables, netfilter, and networking utilities pre-configured +- **Development Tools**: Build essentials, debugging tools, and utilities +- **Jail Pre-installed**: Repository cloned, built, and ready to use +- **Code Server & JetBrains**: Web-based development environments +- **Network Configuration**: Proper kernel settings for namespace operations + +## Prerequisites + +### Authentication + +By default, this template authenticates to AWS using the provider's default [authentication methods](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication-and-configuration). + +The simplest way is via environment variables (e.g. `AWS_ACCESS_KEY_ID`) or a [credentials file](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html#cli-configure-files-format). If you are running Coder on a VM, this file must be in `/home/coder/aws/credentials`. + +### Required AWS Permissions + +The following sample policy allows Coder to create EC2 instances and modify instances provisioned by Coder: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "ec2:GetDefaultCreditSpecification", + "ec2:DescribeIamInstanceProfileAssociations", + "ec2:DescribeTags", + "ec2:DescribeInstances", + "ec2:DescribeInstanceTypes", + "ec2:DescribeInstanceStatus", + "ec2:CreateTags", + "ec2:RunInstances", + "ec2:DescribeInstanceCreditSpecifications", + "ec2:DescribeImages", + "ec2:ModifyDefaultCreditSpecification", + "ec2:DescribeVolumes" + ], + "Resource": "*" + }, + { + "Sid": "CoderResources", + "Effect": "Allow", + "Action": [ + "ec2:DescribeInstanceAttribute", + "ec2:UnmonitorInstances", + "ec2:TerminateInstances", + "ec2:StartInstances", + "ec2:StopInstances", + "ec2:DeleteTags", + "ec2:MonitorInstances", + "ec2:CreateTags", + "ec2:RunInstances", + "ec2:ModifyInstanceAttribute", + "ec2:ModifyInstanceCreditSpecification" + ], + "Resource": "arn:aws:ec2:*:*:instance/*", + "Condition": { + "StringEquals": { + "aws:ResourceTag/Coder_Provisioned": "true" + } + } + } + ] +} +``` + +## Architecture + +This template provisions the following resources: + +- **AWS EC2 Instance**: Ubuntu 22.04 LTS with 20GB storage +- **Network Configuration**: Properly configured for namespace operations +- **Development Environment**: Complete Go development setup +- **Jail Installation**: Pre-built and system-wide accessible + +## Software Installed + +### Core Development +- **Go 1.24+**: Latest Go compiler and tools +- **Build Tools**: gcc, make, git, and build-essential +- **Jail**: Pre-compiled and installed system-wide + +### Network Tools +- **iptables**: Netfilter administration tool +- **iproute2**: Advanced IP routing utilities +- **tcpdump/wireshark**: Network packet analysis +- **net-tools**: Basic network utilities + +### Development Tools +- **Code Server**: Web-based VS Code editor +- **JetBrains**: IDE support for Go development +- **Debug Tools**: gdb, strace, ltrace for troubleshooting +- **System Tools**: htop, tree, jq for system management + +## Getting Started + +After your workspace is created: + +1. **Access your workspace** via Code Server or JetBrains +2. **Navigate to jail directory**: `cd ~/jail` +3. **Build jail**: `make build` +4. **Run tests**: `make test` (requires sudo for E2E tests) +5. **Try jail**: `jail --help` + +### Example Usage + +```bash +# Test jail with a simple HTTP request +jail --allow "github.com" -- curl https://github.com + +# Monitor all network requests +jail --log-level info --allow "*" -- your-application + +# Block all requests (default deny-all) +jail -- curl https://example.com # This will be blocked +``` + +### Development Workflow + +```bash +# Make changes to jail source code +vim ~/jail/jail.go + +# Rebuild +make build + +# Test your changes +./jail --allow "example.com" -- curl https://example.com + +# Run full test suite +sudo make test +``` + +## Network Namespace Requirements + +This template configures the system for network namespace operations: + +- **IP Forwarding**: Enabled for network isolation +- **Netfilter**: Configured for traffic interception +- **User Permissions**: Coder user has sudo access for namespace operations +- **Kernel Features**: Modern Ubuntu 22.04 kernel with namespace support + +## Instance Sizing + +Default instance size is `t3.medium` (2 vCPU, 4GB RAM) which provides adequate resources for jail development. For intensive development or testing, consider `t3.large` or larger. + +## Persistent Storage + +This template uses persistent EBS storage. Your development work, built binaries, and git history will persist across workspace restarts. + +## Security Considerations + +- **Sudo Access**: The coder user has passwordless sudo access required for namespace operations +- **Network Tools**: Various network administration tools are installed +- **Kernel Features**: Network forwarding and netfilter capabilities are enabled + +This configuration is necessary for jail development but should only be used in trusted environments. + +## Troubleshooting + +### Jail Binary Not Found +If jail isn't in PATH, it should be at `/usr/local/bin/jail` or you can rebuild: +```bash +cd ~/jail && make build && sudo cp jail /usr/local/bin/ +``` + +### Network Namespace Issues +Ensure you're using sudo for operations that require network namespaces: +```bash +sudo jail --allow "example.com" -- curl https://example.com +``` + +### Go Module Issues +If Go modules aren't working, ensure GOPATH is set: +```bash +export GOPATH=$HOME/go +export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin +``` + +## Contributing to Jail + +This environment is set up for contributing to the jail project: + +1. Make your changes in `~/jail/` +2. Test thoroughly with the test suite +3. Ensure all tests pass: `sudo make test` +4. Submit pull requests to the main jail repository + +## Template Customization + +This template can be modified to: +- Change instance sizes or storage +- Add additional development tools +- Modify network configurations +- Install different Go versions +- Add custom startup scripts + +Edit `main.tf` and the cloud-init templates to customize the environment. diff --git a/template/cloud-init/cloud-config.yaml.tftpl b/template/cloud-init/cloud-config.yaml.tftpl new file mode 100644 index 0000000..b8b01da --- /dev/null +++ b/template/cloud-init/cloud-config.yaml.tftpl @@ -0,0 +1,20 @@ +#cloud-config +cloud_final_modules: + - [scripts-user, always] +hostname: ${hostname} +users: + - name: ${linux_user} + sudo: ALL=(ALL) NOPASSWD:ALL + shell: /bin/bash + groups: sudo,netdev +# Enable IP forwarding and other network features needed for jail +write_files: + - path: /etc/sysctl.d/99-jail.conf + content: | + # Network settings for jail development + net.ipv4.ip_forward = 1 + net.ipv4.conf.all.route_localnet = 1 + net.netfilter.nf_conntrack_helper = 0 + permissions: '0644' +runcmd: + - sysctl --system diff --git a/template/cloud-init/userdata.sh.tftpl b/template/cloud-init/userdata.sh.tftpl new file mode 100644 index 0000000..2070bc4 --- /dev/null +++ b/template/cloud-init/userdata.sh.tftpl @@ -0,0 +1,2 @@ +#!/bin/bash +sudo -u '${linux_user}' sh -c '${init_script}' diff --git a/template/main.tf b/template/main.tf new file mode 100644 index 0000000..8cfd6e3 --- /dev/null +++ b/template/main.tf @@ -0,0 +1,392 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + } + cloudinit = { + source = "hashicorp/cloudinit" + } + aws = { + source = "hashicorp/aws" + } + } +} + +# Last updated 2023-03-14 +# aws ec2 describe-regions | jq -r '[.Regions[].RegionName] | sort' +data "coder_parameter" "region" { + name = "region" + display_name = "Region" + description = "The region to deploy the workspace in." + default = "us-east-1" + mutable = false + option { + name = "Asia Pacific (Tokyo)" + value = "ap-northeast-1" + icon = "/emojis/1f1ef-1f1f5.png" + } + option { + name = "Asia Pacific (Seoul)" + value = "ap-northeast-2" + icon = "/emojis/1f1f0-1f1f7.png" + } + option { + name = "Asia Pacific (Osaka)" + value = "ap-northeast-3" + icon = "/emojis/1f1ef-1f1f5.png" + } + option { + name = "Asia Pacific (Mumbai)" + value = "ap-south-1" + icon = "/emojis/1f1ee-1f1f3.png" + } + option { + name = "Asia Pacific (Singapore)" + value = "ap-southeast-1" + icon = "/emojis/1f1f8-1f1ec.png" + } + option { + name = "Asia Pacific (Sydney)" + value = "ap-southeast-2" + icon = "/emojis/1f1e6-1f1fa.png" + } + option { + name = "Canada (Central)" + value = "ca-central-1" + icon = "/emojis/1f1e8-1f1e6.png" + } + option { + name = "EU (Frankfurt)" + value = "eu-central-1" + icon = "/emojis/1f1ea-1f1fa.png" + } + option { + name = "EU (Stockholm)" + value = "eu-north-1" + icon = "/emojis/1f1ea-1f1fa.png" + } + option { + name = "EU (Ireland)" + value = "eu-west-1" + icon = "/emojis/1f1ea-1f1fa.png" + } + option { + name = "EU (London)" + value = "eu-west-2" + icon = "/emojis/1f1ea-1f1fa.png" + } + option { + name = "EU (Paris)" + value = "eu-west-3" + icon = "/emojis/1f1ea-1f1fa.png" + } + option { + name = "South America (São Paulo)" + value = "sa-east-1" + icon = "/emojis/1f1e7-1f1f7.png" + } + option { + name = "US East (N. Virginia)" + value = "us-east-1" + icon = "/emojis/1f1fa-1f1f8.png" + } + option { + name = "US East (Ohio)" + value = "us-east-2" + icon = "/emojis/1f1fa-1f1f8.png" + } + option { + name = "US West (N. California)" + value = "us-west-1" + icon = "/emojis/1f1fa-1f1f8.png" + } + option { + name = "US West (Oregon)" + value = "us-west-2" + icon = "/emojis/1f1fa-1f1f8.png" + } +} + +data "coder_parameter" "instance_type" { + name = "instance_type" + display_name = "Instance type" + description = "What instance type should your workspace use?" + default = "t3.medium" + mutable = false + option { + name = "2 vCPU, 1 GiB RAM" + value = "t3.micro" + } + option { + name = "2 vCPU, 2 GiB RAM" + value = "t3.small" + } + option { + name = "2 vCPU, 4 GiB RAM" + value = "t3.medium" + } + option { + name = "2 vCPU, 8 GiB RAM" + value = "t3.large" + } + option { + name = "4 vCPU, 16 GiB RAM" + value = "t3.xlarge" + } + option { + name = "8 vCPU, 32 GiB RAM" + value = "t3.2xlarge" + } +} + +provider "aws" { + region = data.coder_parameter.region.value +} + +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +# Use Ubuntu 22.04 LTS for better Go support and newer kernel features +data "aws_ami" "ubuntu" { + most_recent = true + filter { + name = "name" + values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] + } + filter { + name = "virtualization-type" + values = ["hvm"] + } + owners = ["099720109477"] # Canonical +} + +resource "coder_agent" "dev" { + count = data.coder_workspace.me.start_count + arch = "amd64" + auth = "aws-instance-identity" + os = "linux" + startup_script = <<-EOT + set -e + + # Update system packages + sudo apt-get update + + # Install development essentials + sudo apt-get install -y \ + build-essential \ + curl \ + wget \ + git \ + unzip \ + software-properties-common \ + apt-transport-https \ + ca-certificates \ + gnupg \ + lsb-release + + # Install Go 1.24+ (latest) + cd /tmp + GO_VERSION=$(curl -s https://go.dev/VERSION?m=text) + wget "https://golang.org/dl/$${GO_VERSION}.linux-amd64.tar.gz" + sudo rm -rf /usr/local/go + sudo tar -C /usr/local -xzf "$${GO_VERSION}.linux-amd64.tar.gz" + + # Add Go to PATH for all users + echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee /etc/profile.d/go.sh + echo 'export GOPATH=$HOME/go' | sudo tee -a /etc/profile.d/go.sh + echo 'export PATH=$PATH:$GOPATH/bin' | sudo tee -a /etc/profile.d/go.sh + sudo chmod +x /etc/profile.d/go.sh + + # Apply Go environment for current session + export PATH=$PATH:/usr/local/go/bin + export GOPATH=$HOME/go + export PATH=$PATH:$GOPATH/bin + + # Install network tools needed for jail (network isolation/proxy functionality) + sudo apt-get install -y \ + iptables \ + netfilter-persistent \ + iptables-persistent \ + iproute2 \ + net-tools \ + tcpdump \ + wireshark-common \ + dnsutils + + # Install additional tools for development + sudo apt-get install -y \ + vim \ + nano \ + htop \ + tree \ + jq \ + strace \ + ltrace \ + gdb + + # Clone jail repository to workspace + if [ ! -d "/home/coder/jail" ]; then + sudo -u coder git clone https://github.com/coder/jail.git /home/coder/jail + sudo chown -R coder:coder /home/coder/jail + fi + + # Build jail + cd /home/coder/jail + sudo -u coder /usr/local/go/bin/go mod download + sudo -u coder make build + + # Install jail binary system-wide for easy access + if [ -f "/home/coder/jail/jail" ]; then + sudo cp /home/coder/jail/jail /usr/local/bin/ + sudo chmod +x /usr/local/bin/jail + fi + + # Create Go workspace directory + sudo -u coder mkdir -p /home/coder/go/{bin,pkg,src} + + # Set proper ownership + sudo chown -R coder:coder /home/coder/go + sudo chown -R coder:coder /home/coder/jail + + echo "Jail development environment setup complete!" + echo "Go version: $(go version)" + echo "Jail binary: $(which jail)" + EOT + + metadata { + key = "cpu" + display_name = "CPU Usage" + interval = 5 + timeout = 5 + script = "coder stat cpu" + } + metadata { + key = "memory" + display_name = "Memory Usage" + interval = 5 + timeout = 5 + script = "coder stat mem" + } + metadata { + key = "disk" + display_name = "Disk Usage" + interval = 600 # every 10 minutes + timeout = 30 # df can take a while on large filesystems + script = "coder stat disk --path $HOME" + } + metadata { + key = "jail" + display_name = "Jail Version" + interval = 0 # static + timeout = 5 + script = "jail --version 2>/dev/null || echo 'Not installed'" + } + metadata { + key = "go" + display_name = "Go Version" + interval = 0 # static + timeout = 5 + script = "go version 2>/dev/null || echo 'Not installed'" + } +} + +# See https://registry.coder.com/modules/coder/code-server +module "code-server" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/modules/code-server/coder" + + # This ensures that the latest non-breaking version of the module gets downloaded, you can also pin the module version to prevent breaking changes in production. + version = "~> 1.0" + + agent_id = coder_agent.dev[0].id + agent_name = "dev" + order = 1 +} + +# See https://registry.coder.com/modules/coder/jetbrains +module "jetbrains" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/modules/coder/jetbrains/coder" + version = "~> 1.0" + agent_id = coder_agent.dev[0].id + agent_name = "dev" + folder = "/home/coder" +} + +locals { + hostname = lower(data.coder_workspace.me.name) + linux_user = "coder" +} + +data "cloudinit_config" "user_data" { + gzip = false + base64_encode = false + + boundary = "//" + + part { + filename = "cloud-config.yaml" + content_type = "text/cloud-config" + + content = templatefile("${path.module}/cloud-init/cloud-config.yaml.tftpl", { + hostname = local.hostname + linux_user = local.linux_user + }) + } + + part { + filename = "userdata.sh" + content_type = "text/x-shellscript" + + content = templatefile("${path.module}/cloud-init/userdata.sh.tftpl", { + linux_user = local.linux_user + + init_script = try(coder_agent.dev[0].init_script, "") + }) + } +} + +resource "aws_instance" "dev" { + ami = data.aws_ami.ubuntu.id + availability_zone = "${data.coder_parameter.region.value}a" + instance_type = data.coder_parameter.instance_type.value + + user_data = data.cloudinit_config.user_data.rendered + + # Increase root volume size for development work + root_block_device { + volume_size = 20 + volume_type = "gp3" + } + + tags = { + Name = "coder-${data.coder_workspace_owner.me.name}-${data.coder_workspace.me.name}" + # Required if you are using our example policy, see template README + Coder_Provisioned = "true" + Project = "jail" + } + lifecycle { + ignore_changes = [ami] + } +} + +resource "coder_metadata" "workspace_info" { + resource_id = aws_instance.dev.id + item { + key = "region" + value = data.coder_parameter.region.value + } + item { + key = "instance type" + value = aws_instance.dev.instance_type + } + item { + key = "disk" + value = "${aws_instance.dev.root_block_device[0].volume_size} GiB" + } +} + +resource "aws_ec2_instance_state" "dev" { + instance_id = aws_instance.dev.id + state = data.coder_workspace.me.transition == "start" ? "running" : "stopped" +} diff --git a/template/validate.sh b/template/validate.sh new file mode 100755 index 0000000..fc74c69 --- /dev/null +++ b/template/validate.sh @@ -0,0 +1,127 @@ +#!/bin/bash + +# Template validation script for coder/jail development environment + +set -e + +echo "🔍 Validating Coder template for jail development..." + +# Check if we're in the right directory +if [ ! -f "main.tf" ]; then + echo "❌ Error: main.tf not found. Run this script from the template directory." + exit 1 +fi + +echo "✅ Found main.tf" + +# Check if cloud-init directory exists +if [ ! -d "cloud-init" ]; then + echo "❌ Error: cloud-init directory not found." + exit 1 +fi + +echo "✅ Found cloud-init directory" + +# Check required cloud-init files +if [ ! -f "cloud-init/cloud-config.yaml.tftpl" ]; then + echo "❌ Error: cloud-config.yaml.tftpl not found." + exit 1 +fi + +echo "✅ Found cloud-config.yaml.tftpl" + +if [ ! -f "cloud-init/userdata.sh.tftpl" ]; then + echo "❌ Error: userdata.sh.tftpl not found." + exit 1 +fi + +echo "✅ Found userdata.sh.tftpl" + +# Check if terraform is available (if running in development environment) +if command -v terraform >/dev/null 2>&1; then + echo "🔧 Terraform found, validating syntax..." + + # Initialize terraform (without remote state) + terraform init -backend=false >/dev/null 2>&1 || { + echo "❌ Terraform init failed" + exit 1 + } + + # Validate terraform syntax + terraform validate >/dev/null 2>&1 || { + echo "❌ Terraform validation failed" + terraform validate + exit 1 + } + + echo "✅ Terraform syntax validation passed" +else + echo "⚠️ Terraform not found, skipping syntax validation" +fi + +# Basic syntax checks +echo "🔍 Checking template content..." + +# Check that jail-specific packages are included in startup script +if ! grep -q "iptables" main.tf; then + echo "❌ Error: iptables not found in startup script (required for jail)" + exit 1 +fi + +echo "✅ Found iptables installation" + +# Check for Go installation +if ! grep -q "golang.org/dl" main.tf; then + echo "❌ Error: Go installation not found (required for jail development)" + exit 1 +fi + +echo "✅ Found Go installation" + +# Check for jail repository cloning +if ! grep -q "github.com/coder/jail" main.tf; then + echo "❌ Error: jail repository cloning not found" + exit 1 +fi + +echo "✅ Found jail repository setup" + +# Check Ubuntu version (should be 22.04 for better kernel support) +if ! grep -q "ubuntu-jammy-22.04" main.tf; then + echo "⚠️ Warning: Not using Ubuntu 22.04 LTS (recommended for jail development)" +else + echo "✅ Using Ubuntu 22.04 LTS" +fi + +# Check default instance size (should be at least t3.medium for development) +if grep -q 'default.*=.*"t3.micro"' main.tf; then + echo "⚠️ Warning: Default instance size is t3.micro, consider t3.medium for better performance" +elif grep -q 'default.*=.*"t3.medium"' main.tf; then + echo "✅ Default instance size is appropriate for development" +fi + +# Check for network configuration +if ! grep -q "net.ipv4.ip_forward" cloud-init/cloud-config.yaml.tftpl; then + echo "❌ Error: IP forwarding not enabled (required for jail network operations)" + exit 1 +fi + +echo "✅ Found network configuration for jail" + +echo "" +echo "🎉 Template validation completed successfully!" +echo "" +echo "📋 Summary:" +echo " - Terraform template: ✅ Valid" +echo " - Cloud-init files: ✅ Present" +echo " - Jail dependencies: ✅ Configured" +echo " - Network settings: ✅ Configured" +echo " - Go development: ✅ Configured" +echo "" +echo "🚀 Template is ready for use with Coder!" +echo "" +echo "Next steps:" +echo "1. Add this template to your Coder deployment" +echo "2. Configure AWS credentials for your Coder instance" +echo "3. Create a workspace using this template" +echo "4. Start developing jail!"