AWSTemplateFormatVersion: '2010-09-09'
Description: Multi-region compatible EKS Bastion Host Template

Parameters:
  KeyName:
    Description: Name of an existing EC2 KeyPair
    Type: AWS::EC2::KeyPair::KeyName

  SgIngressSshCidr:
    Description: SSH access CIDR
    Type: String
    MinLength: '9'
    MaxLength: '18'
    Default: 0.0.0.0/0
    AllowedPattern: '(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})'

  MyInstanceType:
    Description: EC2 instance type
    Type: String
    Default: t3.small
    AllowedValues:
      - t3.micro
      - t3.small
      - t3.medium
      - m7i-flex.large

  LatestAmiId:
    Description: Amazon Linux 2 AMI
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'

  ClusterBaseName:
    Type: String
    Default: myeks2
    AllowedPattern: '[a-zA-Z][-a-zA-Z0-9]*'

Resources:
  # VPC
  EksVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 172.30.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub '${ClusterBaseName}-VPC'

  # Public Subnet (동적 가용 영역 선택)
  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      # !GetAZs 를 사용하여 현재 리전의 첫 번째 가용 영역을 자동으로 할당합니다.
      AvailabilityZone: !Select [ 0, !GetAZs '' ]
      CidrBlock: 172.30.1.0/24
      VpcId: !Ref EksVPC
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${ClusterBaseName}-PublicSubnet1'

  InternetGateway:
    Type: AWS::EC2::InternetGateway

  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref EksVPC

  PublicSubnetRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref EksVPC
      Tags:
        - Key: Name
          Value: !Sub '${ClusterBaseName}-PublicSubnetRouteTable'

  PublicSubnetRoute:
    Type: AWS::EC2::Route
    DependsOn: VPCGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicSubnetRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1
      RouteTableId: !Ref PublicSubnetRouteTable

  EKSEC2SG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: eksctl-host Security Group
      VpcId: !Ref EksVPC
      Tags:
        - Key: Name
          Value: !Sub '${ClusterBaseName}-HOST-SG'
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref SgIngressSshCidr

  # IAM
  BastionRole:
    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/AdministratorAccess

  BastionInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref BastionRole

  # Bastion EC2 Instance
  EKSEC2:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref MyInstanceType
      ImageId: !Ref LatestAmiId
      KeyName: !Ref KeyName
      IamInstanceProfile: !Ref BastionInstanceProfile
      Tags:
        - Key: Name
          Value: !Sub '${ClusterBaseName}-bastion-EC2'
      NetworkInterfaces:
        - DeviceIndex: 0
          SubnetId: !Ref PublicSubnet1
          GroupSet:
            - !Ref EKSEC2SG
          AssociatePublicIpAddress: true
          PrivateIpAddress: 172.30.1.100
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeType: gp3
            VolumeSize: 30
            DeleteOnTermination: true
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          hostnamectl --static set-hostname "${ClusterBaseName}-bastion-EC2"

          echo 'alias vi=vim' >> /etc/profile
          echo "sudo su -" >> /home/ec2-user/.bashrc

          # 시간대 설정 (서울 기준)
          ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

          cd /root
          yum -y install tree jq git htop unzip yum-utils

          # Tools 설치
          curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.25.7/2023-03-17/bin/linux/amd64/kubectl
          install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
          curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
          curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
          mv /tmp/eksctl /usr/local/bin
          curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
          unzip -q awscliv2.zip
          ./aws/install

          # 환경 변수 설정
          echo 'export AWS_PAGER=""' >> /etc/profile
          echo 'alias k=kubectl' >> /etc/profile
          echo 'complete -F __start_kubectl k' >> /etc/profile
          echo "export CLUSTER_NAME=${ClusterBaseName}" >> /etc/profile
          # 현재 배포된 리전을 자동으로 환경변수에 등록
          echo "export AWS_DEFAULT_REGION=${AWS::Region}" >> /etc/profile

          # Terraform 설치
          yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
          yum -y install terraform

Outputs:
  eksctlhost:
    Description: Bastion Host Public IP
    Value: !GetAtt EKSEC2.PublicIp