Skip to content
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
9 changes: 7 additions & 2 deletions terraform/aws/modules/composition/jump-host/data.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@ data "aws_region" "current" {}

data "aws_caller_identity" "current" {}

data "aws_ami" "amazon_linux_2" {
data "aws_ami" "amazon_linux_2023" {
count = var.external_jump_ami_id == null || var.internal_jump_ami_id == null ? 1 : 0
most_recent = true
owners = ["amazon"]

filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
values = ["al2023-ami-2023.*-x86_64"]
}

filter {
name = "virtualization-type"
values = ["hvm"]
}

filter {
name = "block-device-mapping.volume-type"
values = ["gp3"]
}

filter {
name = "state"
values = ["available"]
Expand Down
5 changes: 3 additions & 2 deletions terraform/aws/modules/composition/jump-host/locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ locals {
}
)

external_ami_id = var.external_jump_ami_id != null ? var.external_jump_ami_id : data.aws_ami.amazon_linux_2[0].id
internal_ami_id = var.internal_jump_ami_id != null ? var.internal_jump_ami_id : data.aws_ami.amazon_linux_2[0].id
external_ami_id = var.external_jump_ami_id != null ? var.external_jump_ami_id : data.aws_ami.amazon_linux_2023[0].id
internal_ami_id = var.internal_jump_ami_id != null ? var.internal_jump_ami_id : data.aws_ami.amazon_linux_2023[0].id

userdata_internal = templatefile("${path.module}/templates/userdata.sh", {
jump_type = "internal"
environment = var.environment
cloudwatch_region = data.aws_region.current.id
internal_jump_ip = "" # Not used for internal jump
os_username = "ec2-user"
})
}
1 change: 1 addition & 0 deletions terraform/aws/modules/composition/jump-host/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ module "external_jump_instance" {
environment = var.environment
cloudwatch_region = data.aws_region.current.id
internal_jump_ip = module.internal_jump_instance.private_ip
os_username = var.ssm_os_username
}))

# Root volume configuration
Expand Down
9 changes: 5 additions & 4 deletions terraform/aws/modules/composition/jump-host/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -91,21 +91,22 @@ output "connection_guide" {
1. Connect to External Jump Host (via Session Manager):
aws ssm start-session --target ${module.external_jump_instance.id}

${var.enable_internal_jump_ssm ? "2. Connect to Internal Jump Host (via Session Manager):\n aws ssm start-session --target ${module.internal_jump_instance.id}\n\n 3. From External Jump, SSH to Internal Jump (alternative method):\n ssh internal-jump\n (SSH key is automatically configured in ec2-user's home directory)\n\n 4. Manual SSH to Internal Jump (if needed):\n ssh -i /home/ec2-user/.ssh/internal_jump_key ec2-user@${module.internal_jump_instance.private_ip}" : "2. From External Jump, SSH to Internal Jump:\n ssh internal-jump\n (SSH key is automatically configured in ec2-user's home directory)\n\n 3. Manual SSH to Internal Jump (if needed):\n ssh -i /home/ec2-user/.ssh/internal_jump_key ec2-user@${module.internal_jump_instance.private_ip}"}
${var.enable_internal_jump_ssm ? "2. Connect to Internal Jump Host (via Session Manager):\n aws ssm start-session --target ${module.internal_jump_instance.id}\n\n a. From External Jump, SSH to Internal Jump (alternative method):\n ssh internal-jump\n (SSH key is automatically configured in ${var.ssm_os_username}'s home directory)\n\n b. Manual SSH to Internal Jump (if needed):\n ssh -i /home/${var.ssm_os_username}/.ssh/internal_jump_key ec2-user@${module.internal_jump_instance.private_ip}" : "2. From External Jump, SSH to Internal Jump:\n ssh internal-jump\n (SSH key is automatically configured in ${var.ssm_os_username}'s home directory)\n\n a. Manual SSH to Internal Jump (if needed):\n ssh -i /home/${var.ssm_os_username}/.ssh/internal_jump_key ec2-user@${module.internal_jump_instance.private_ip}"}

${var.enable_internal_jump_ssm ? "5." : "4."} Retrieve Internal Jump SSH Key (from your local machine):
3. Retrieve Internal Jump SSH Key (from your local machine):
${module.internal_jump_ssh_key_parameter.ssm_parameter_name}
aws ssm get-parameter --name ${module.internal_jump_ssh_key_parameter.ssm_parameter_name} --with-decryption --query 'Parameter.Value' --output text > internal_jump_key.pem
chmod 400 internal_jump_key.pem

${var.enable_internal_jump_ssm ? "6." : "5."} View Logs:
4. View Logs:
External: aws logs tail ${aws_cloudwatch_log_group.jump_host["external"].name} --follow
Internal: aws logs tail ${aws_cloudwatch_log_group.jump_host["internal"].name} --follow

IMPORTANT NOTES:
- External Jump: Accessible via Session Manager (IAM-based auth)
- Default user: ${var.ssm_os_username} (Amazon Linux 2023 via SSM)
- Internal Jump: ${var.enable_internal_jump_ssm ? "Accessible via Session Manager AND SSH from external jump" : "NO Session Manager access (must SSH from external jump)"}
- Default user: ec2-user (Amazon Linux 2)
- Default user: ec2-user (Amazon Linux 2023)
- SSH key stored in SSM Parameter Store: ${module.internal_jump_ssh_key_parameter.ssm_parameter_name}

Prerequisites:
Expand Down
39 changes: 28 additions & 11 deletions terraform/aws/modules/composition/jump-host/templates/userdata.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set -e
JUMP_TYPE="${jump_type}"
ENVIRONMENT="${environment}"
CLOUDWATCH_REGION="${cloudwatch_region}"
OS_USERNAME="${os_username}"
%{ if jump_type == "external" ~}
INTERNAL_JUMP_IP="${internal_jump_ip}"
%{ endif ~}
Expand All @@ -25,6 +26,17 @@ systemctl restart sshd

# Type-specific configuration
if [ "$JUMP_TYPE" = "external" ]; then
# Check to see whether SSM access username exists, creating it and its similarly named group, and home directory if not.
if ! id -u $OS_USERNAME >/dev/null 2>&1; then
useradd --create-home --user-group --shell /bin/bash $OS_USERNAME

# Create sudoers file to allow SSM access username to execute commands as root without password, same as SSM Agent would have.
cat > /etc/sudoers.d/ssm-agent-users <<SUDOEOF
# User rules for $OS_USERNAME
$OS_USERNAME ALL=(ALL) NOPASSWD:ALL
SUDOEOF
fi

# External jump - retrieve internal jump SSH key from SSM
# This works because external jump has IAM permissions to read from SSM
INTERNAL_SSH_KEY_OUTPUT=$(aws ssm get-parameter \
Expand All @@ -41,37 +53,42 @@ if [ "$JUMP_TYPE" = "external" ]; then
fi
INTERNAL_SSH_KEY="$INTERNAL_SSH_KEY_OUTPUT"

# Store SSH key for ec2-user
mkdir -p /home/ec2-user/.ssh
echo "$INTERNAL_SSH_KEY" > /home/ec2-user/.ssh/internal_jump_key
chmod 600 /home/ec2-user/.ssh/internal_jump_key
chown ec2-user:ec2-user /home/ec2-user/.ssh/internal_jump_key
# Store SSH key for OS user
mkdir -p /home/$OS_USERNAME/.ssh
chmod 700 /home/$OS_USERNAME/.ssh
echo "$INTERNAL_SSH_KEY" > /home/$OS_USERNAME/.ssh/internal_jump_key
chmod 600 /home/$OS_USERNAME/.ssh/internal_jump_key

# Create SSH config for easy connection
cat > /home/ec2-user/.ssh/config <<SSHEOF
cat > /home/$OS_USERNAME/.ssh/config <<SSHEOF
Host internal-jump
HostName $INTERNAL_JUMP_IP
User ec2-user
IdentityFile ~/.ssh/internal_jump_key
StrictHostKeyChecking no
SSHEOF
chmod 600 /home/ec2-user/.ssh/config
chown ec2-user:ec2-user /home/ec2-user/.ssh/config
chmod 600 /home/$OS_USERNAME/.ssh/config

# Finally, recursively set ownership of the entire home directory
chown -R $OS_USERNAME:$OS_USERNAME /home/$OS_USERNAME

echo "External jump configured. Internal jump: $INTERNAL_JUMP_IP"
fi

# Create MOTD
cat > /etc/motd <<EOF
# Create custom MOTD in a way it won't be overwritten by cloud-init or other services and is shown at the end of the default MOTD content.
# Note that motd doesn't get shown when logging in via SSM Session Manager, but it will if logging in via SSH
cat > /etc/motd.d/40-hyperswitch <<EOF
================================================================================
$JUMP_TYPE Jump Host - $ENVIRONMENT Environment

Default User: ec2-user
Default User: $OS_USERNAME
Access: AWS Systems Manager Session Manager
$([ "$JUMP_TYPE" = "external" ] && echo " SSH to Internal: ssh internal-jump")

Managed by Terraform
================================================================================
EOF

update-motd

echo "Jump host setup complete for $JUMP_TYPE in $ENVIRONMENT"
6 changes: 6 additions & 0 deletions terraform/aws/modules/composition/jump-host/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,10 @@ variable "enable_internal_jump_ssm" {
description = "Enable SSM Session Manager access for internal jump host. When true, adds SSM policies to internal jump IAM role"
type = bool
default = false
}

variable "ssm_os_username" {
description = "OS username for SSM Session Manager access. Defaults to the standard username used by SSM Agent. Can be overridden based on your environment and SSM config."
type = string
default = "ssm-user"
}