cloudformation/proxy/proxy.yaml (311 lines of code) (raw):

AWSTemplateFormatVersion: 2010-09-09 Description: AWS ParallelCluster Proxy Environment Parameters: Keypair: Description: EC2 Keypair to access management instance. Type: AWS::EC2::KeyPair::KeyName VpcCidr: Description: CIDR for the VPC Type: String Default: 10.0.0.0/16 SSHCidr: Description: CIDR to allow SSH traffic from Type: String Default: 0.0.0.0/0 Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Networking Parameters: - VpcCidr - SSHCidr - Label: default: Permissions Parameters: - Keypair cfn-lint: config: ignore_checks: - E1152 Resources: # VPC Vpc: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCidr EnableDnsHostnames: true EnableDnsSupport: true InstanceTenancy: default Tags: - Key: Name Value: ProxyVPC # INTERNET GATEWAY VpcIGW: Type: AWS::EC2::InternetGateway VpcGWA: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref VpcIGW VpcId: !Ref Vpc # PUBLIC SUBNET PublicSubnet: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Sub ${AWS::Region}a CidrBlock: !Select [ 0, !Cidr [ !GetAtt Vpc.CidrBlock, 2, 8 ]] MapPublicIpOnLaunch: true VpcId: !Ref Vpc Tags: - Key: Name Value: ProxyVPC/Public PublicSubnetRT: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref Vpc PublicSubnetRTA: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PublicSubnetRT SubnetId: !Ref PublicSubnet PublicSubnetRoute: Type: AWS::EC2::Route DependsOn: - VpcGWA Properties: DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref VpcIGW RouteTableId: !Ref PublicSubnetRT # PRIVATE SUBNET PrivateSubnet: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Sub ${AWS::Region}b CidrBlock: !Select [ 1, !Cidr [ !GetAtt Vpc.CidrBlock, 2, 8 ]] MapPublicIpOnLaunch: false VpcId: !Ref Vpc Tags: - Key: Name Value: ProxyVPC/Private PrivateSubnetRT: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref Vpc PrivateSubnetRTA: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateSubnetRT SubnetId: !Ref PrivateSubnet PrivateSubnetRoute: Type: AWS::EC2::Route DependsOn: - Proxy Properties: DestinationCidrBlock: 0.0.0.0/0 InstanceId: !Ref Proxy RouteTableId: !Ref PrivateSubnetRT # SECURITY GROUPS ProxySecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Security Group for the proxy node SecurityGroupIngress: - CidrIp: !GetAtt PrivateSubnet.CidrBlock Description: Allow all inbound traffic from private subnet IpProtocol: -1 - CidrIp: !Ref SSHCidr Description: Allow SSH access from specified CIDR IpProtocol: tcp FromPort: 22 ToPort: 22 SecurityGroupEgress: - CidrIp: 0.0.0.0/0 Description: Allow all outbound traffic IpProtocol: -1 VpcId: !Ref Vpc ProxyClientSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Security Group for proxy clients SecurityGroupIngress: - CidrIp: !Sub [ "${ProxyPrivateIp}/32", {ProxyPrivateIp: !GetAtt Proxy.PrivateIp}] Description: Allow all inbound traffic from proxy IpProtocol: -1 SecurityGroupEgress: - CidrIp: 0.0.0.0/0 Description: Allow all outbound traffic IpProtocol: -1 VpcId: !Ref Vpc # IAM PERMISSIONS ProxyInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Roles: - !Ref ProxyRole ProxyRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: !Sub ec2.${AWS::URLSuffix} Version: 2012-10-17 ManagedPolicyArns: - !Sub arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore ProxyClientNodeInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Roles: - !Ref ProxyClientNodeRole ProxyClientNodeRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: !Sub ec2.${AWS::URLSuffix} Version: 2012-10-17 ManagedPolicyArns: - !Sub arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore Imdsv2LaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateData: MetadataOptions: HttpEndpoint: enabled HttpPutResponseHopLimit: 4 HttpTokens: required # PROXY Proxy: Type: AWS::EC2::Instance DependsOn: # Dependencies required to support ENI updates when VPC, IGW and instance are defined in the same template. # See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-instance.html#cfn-ec2-instance-networkinterfaces - VpcIGW - ProxyENI Properties: IamInstanceProfile: !Ref ProxyInstanceProfile ImageId: resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id InstanceType: t3.medium KeyName: !Ref Keypair NetworkInterfaces: - DeviceIndex: 0 NetworkInterfaceId: !Ref ProxyENI LaunchTemplate: LaunchTemplateId: !Ref Imdsv2LaunchTemplate Version: !GetAtt Imdsv2LaunchTemplate.LatestVersionNumber UserData: Fn::Base64: | #!/bin/bash -ex set -o pipefail exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1 apt-get update -y apt-get install -y tinyproxy redsocks cat << EOF > /etc/tinyproxy/tinyproxy.conf User tinyproxy Group tinyproxy Port 8888 Timeout 3600 DefaultErrorFile "/usr/share/tinyproxy/default.html" StatFile "/usr/share/tinyproxy/stats.html" Logfile "/var/log/tinyproxy/tinyproxy.log" LogLevel Info PidFile "/run/tinyproxy/tinyproxy.pid" MaxClients 500 MinSpareServers 20 MaxSpareServers 100 StartServers 20 MaxRequestsPerChild 0 ViaProxyName "tinyproxy" ConnectPort 443 ConnectPort 563 EOF /etc/init.d/tinyproxy restart cat << EOF > /etc/redsocks.conf base { log_debug = off; log_info = on; log = "file:/var/log/redsocks"; daemon = on; user = redsocks; group = redsocks; redirector = iptables; } redsocks { local_ip = 0.0.0.0; local_port = 8889; ip = localhost; port = 8888; type = http-connect; } EOF /etc/init.d/redsocks restart iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8888 iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8889 mkdir -p /etc/iptables/ iptables-save > /etc/iptables/rules.v4 # Installing iptables-persistent without manual prompt # https://gist.github.com/alonisser/a2c19f5362c2091ac1e7 echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections apt-get install -y iptables-persistent Tags: - Key: Name Value: !Sub [ "Proxy-${StackIdSuffix}", {StackIdSuffix: !Select [1, !Split ['/', !Ref 'AWS::StackId']]}] ProxyENI: Type: AWS::EC2::NetworkInterface Properties: GroupSet: - !Ref ProxySecurityGroup SourceDestCheck: false SubnetId: !Ref PublicSubnet # PROXY Client ProxyClient: Type: AWS::EC2::Instance DependsOn: - Proxy Properties: IamInstanceProfile: !Ref ProxyClientNodeInstanceProfile ImageId: resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id InstanceType: t3.medium KeyName: !Ref Keypair SecurityGroupIds: - !Ref ProxyClientSecurityGroup SubnetId: !Ref PrivateSubnet LaunchTemplate: LaunchTemplateId: !Ref Imdsv2LaunchTemplate Version: !GetAtt Imdsv2LaunchTemplate.LatestVersionNumber UserData: Fn::Base64: !Sub - | #!/bin/bash -ex set -o pipefail exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1 apt-get update -y apt-get -y install python3-pip pip3 install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz cat >> /home/ubuntu/test-proxy.sh <<TEST http_proxy="http://${ProxyPrivateIp}:${ProxyPort}" wget https://github.com/aws/aws-parallelcluster/archive/refs/heads/develop.zip wget https://github.com/aws/aws-parallelcluster/archive/refs/heads/develop.zip TEST chmod +x /home/ubuntu/test-proxy.sh bash -ex /home/ubuntu/test-proxy.sh /usr/local/bin/cfn-signal --exit-code 0 --stack "${AWS::StackName}" --region "${AWS::Region}" "${ProxyVerificationWaitConditionHandle}" - { ProxyPrivateIp: !GetAtt Proxy.PrivateIp, ProxyPort: 8888, ProxyVerificationWaitConditionHandle: !Ref ProxyVerificationWaitConditionHandle } Tags: - Key: Name Value: !Sub [ "ProxyClient-${StackIdSuffix}", { StackIdSuffix: !Select [ 1, !Split [ '/', !Ref 'AWS::StackId' ] ] } ] ProxyVerificationWaitConditionHandle: Type: AWS::CloudFormation::WaitConditionHandle ProxyVerificationWaitCondition: Type: AWS::CloudFormation::WaitCondition Properties: Count: 1 Handle: !Ref ProxyVerificationWaitConditionHandle Timeout: 600 Outputs: VpcId: Value: !Ref Vpc PublicSubnet: Value: !Ref PublicSubnet PrivateSubnet: Value: !Ref PrivateSubnet ProxyAddress: Value: !Sub [ "http://${ProxyPrivateIp}:8888", { ProxyPrivateIp: !GetAtt Proxy.PrivateIp } ] ProxyClientSecurityGroup: Value: !Ref ProxyClientSecurityGroup