Skip to content

Commit ea57725

Browse files
committed
[CoudFormation] Add 1-click template to deploy a proxy environment for ParallelCluster.
Signed-off-by: Giacomo Marciani <mgiacomo@amazon.com>
1 parent 2490e98 commit ea57725

File tree

1 file changed

+355
-0
lines changed

1 file changed

+355
-0
lines changed

cloudformation/proxy/proxy.yaml

Lines changed: 355 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,355 @@
1+
AWSTemplateFormatVersion: 2010-09-09
2+
Description: AWS ParallelCluster Proxy Environment
3+
4+
Parameters:
5+
Keypair:
6+
Description: EC2 Keypair to access management instance.
7+
Type: AWS::EC2::KeyPair::KeyName
8+
9+
VpcCidr:
10+
Description: CIDR for the VPC
11+
Type: String
12+
Default: 10.0.0.0/16
13+
14+
Metadata:
15+
AWS::CloudFormation::Interface:
16+
ParameterGroups:
17+
- Label:
18+
default: Networking
19+
Parameters:
20+
- VpcCidr
21+
- Label:
22+
default: Permissions
23+
Parameters:
24+
- Keypair
25+
26+
Resources:
27+
28+
# VPC
29+
Vpc:
30+
Type: AWS::EC2::VPC
31+
Properties:
32+
CidrBlock: !Ref VpcCidr
33+
EnableDnsHostnames: true
34+
EnableDnsSupport: true
35+
InstanceTenancy: default
36+
Tags:
37+
- Key: Name
38+
Value: ProxyVPC
39+
40+
# INTERNET GATEWAY
41+
VpcIGW:
42+
Type: AWS::EC2::InternetGateway
43+
44+
VpcGWA:
45+
Type: AWS::EC2::VPCGatewayAttachment
46+
Properties:
47+
InternetGatewayId: !Ref VpcIGW
48+
VpcId: !Ref Vpc
49+
50+
# PUBLIC SUBNET
51+
PublicSubnet:
52+
Type: AWS::EC2::Subnet
53+
Properties:
54+
AvailabilityZone: !Sub ${AWS::Region}a
55+
CidrBlock: !Select [ 0, !Cidr [ !GetAtt Vpc.CidrBlock, 2, 8 ]]
56+
MapPublicIpOnLaunch: true
57+
VpcId: !Ref Vpc
58+
Tags:
59+
- Key: Name
60+
Value: ProxyVPC/Public
61+
62+
PublicSubnetRT:
63+
Type: AWS::EC2::RouteTable
64+
Properties:
65+
VpcId: !Ref Vpc
66+
67+
PublicSubnetRTA:
68+
Type: AWS::EC2::SubnetRouteTableAssociation
69+
Properties:
70+
RouteTableId: !Ref PublicSubnetRT
71+
SubnetId: !Ref PublicSubnet
72+
73+
PublicSubnetRoute:
74+
Type: AWS::EC2::Route
75+
DependsOn:
76+
- VpcGWA
77+
Properties:
78+
DestinationCidrBlock: 0.0.0.0/0
79+
GatewayId: !Ref VpcIGW
80+
RouteTableId: !Ref PublicSubnetRT
81+
82+
# PRIVATE SUBNET
83+
PrivateSubnet:
84+
Type: AWS::EC2::Subnet
85+
Properties:
86+
AvailabilityZone: !Sub ${AWS::Region}b
87+
CidrBlock: !Select [ 1, !Cidr [ !GetAtt Vpc.CidrBlock, 2, 8 ]]
88+
MapPublicIpOnLaunch: false
89+
VpcId: !Ref Vpc
90+
Tags:
91+
- Key: Name
92+
Value: ProxyVPC/Private
93+
94+
PrivateSubnetRT:
95+
Type: AWS::EC2::RouteTable
96+
Properties:
97+
VpcId: !Ref Vpc
98+
99+
PrivateSubnetRTA:
100+
Type: AWS::EC2::SubnetRouteTableAssociation
101+
Properties:
102+
RouteTableId: !Ref PrivateSubnetRT
103+
SubnetId: !Ref PrivateSubnet
104+
105+
PrivateSubnetRoute:
106+
Type: AWS::EC2::Route
107+
DependsOn:
108+
- Proxy
109+
Properties:
110+
DestinationCidrBlock: 0.0.0.0/0
111+
InstanceId: !Ref Proxy
112+
RouteTableId: !Ref PrivateSubnetRT
113+
114+
# SECURITY GROUPS
115+
ProxySecurityGroup:
116+
Type: AWS::EC2::SecurityGroup
117+
Properties:
118+
GroupDescription: Security Group for the proxy node
119+
SecurityGroupIngress:
120+
- CidrIp: !GetAtt PrivateSubnet.CidrBlock
121+
Description: Allow all inbound traffic from private subnet
122+
IpProtocol: -1
123+
SecurityGroupEgress:
124+
- CidrIp: 0.0.0.0/0
125+
Description: Allow all outbound traffic
126+
IpProtocol: -1
127+
VpcId: !Ref Vpc
128+
129+
ProxyClientSecurityGroup:
130+
Type: AWS::EC2::SecurityGroup
131+
Properties:
132+
GroupDescription: Security Group for proxy clients
133+
SecurityGroupIngress:
134+
- CidrIp: !Sub [ "${ProxyPrivateIp}/32", {ProxyPrivateIp: !GetAtt Proxy.PrivateIp}]
135+
Description: Allow all inbound traffic from proxy
136+
IpProtocol: -1
137+
SecurityGroupEgress:
138+
- CidrIp: 0.0.0.0/0
139+
Description: Allow all outbound traffic
140+
IpProtocol: -1
141+
VpcId: !Ref Vpc
142+
143+
# IAM PERMISSIONS
144+
ProxyInstanceProfile:
145+
Type: AWS::IAM::InstanceProfile
146+
Properties:
147+
Roles:
148+
- !Ref ProxyRole
149+
150+
ProxyRole:
151+
Type: AWS::IAM::Role
152+
Properties:
153+
AssumeRolePolicyDocument:
154+
Statement:
155+
- Action: sts:AssumeRole
156+
Effect: Allow
157+
Principal:
158+
Service: ec2.amazonaws.com
159+
Version: 2012-10-17
160+
ManagedPolicyArns:
161+
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
162+
163+
ProxyClientNodeInstanceProfile:
164+
Type: AWS::IAM::InstanceProfile
165+
Properties:
166+
Roles:
167+
- !Ref ProxyClientNodeRole
168+
169+
ProxyClientNodeRole:
170+
Type: AWS::IAM::Role
171+
Properties:
172+
AssumeRolePolicyDocument:
173+
Statement:
174+
- Action: sts:AssumeRole
175+
Effect: Allow
176+
Principal:
177+
Service: ec2.amazonaws.com
178+
Version: 2012-10-17
179+
ManagedPolicyArns:
180+
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
181+
182+
Imdsv2LaunchTemplate:
183+
Type: AWS::EC2::LaunchTemplate
184+
Properties:
185+
LaunchTemplateData:
186+
MetadataOptions:
187+
HttpEndpoint: enabled
188+
HttpPutResponseHopLimit: 4
189+
HttpTokens: required
190+
191+
# PROXY
192+
Proxy:
193+
Type: AWS::EC2::Instance
194+
DependsOn:
195+
# Dependencies required to support ENI updates when VPC, IGW and instance are defined in the same template.
196+
# See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-instance.html#cfn-ec2-instance-networkinterfaces
197+
- VpcIGW
198+
- ProxyENI
199+
Properties:
200+
IamInstanceProfile: !Ref ProxyInstanceProfile
201+
ImageId: resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id
202+
InstanceType: t2.medium
203+
KeyName: !Ref Keypair
204+
NetworkInterfaces:
205+
- DeviceIndex: 0
206+
NetworkInterfaceId: !Ref ProxyENI
207+
LaunchTemplate:
208+
LaunchTemplateId: !Ref Imdsv2LaunchTemplate
209+
Version: !GetAtt Imdsv2LaunchTemplate.LatestVersionNumber
210+
UserData:
211+
Fn::Base64: |
212+
#!/bin/bash -ex
213+
set -o pipefail
214+
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
215+
apt-get update -y
216+
apt-get install -y tinyproxy redsocks
217+
218+
cat << EOF > /etc/tinyproxy/tinyproxy.conf
219+
User tinyproxy
220+
Group tinyproxy
221+
Port 8888
222+
Timeout 3600
223+
DefaultErrorFile "/usr/share/tinyproxy/default.html"
224+
StatFile "/usr/share/tinyproxy/stats.html"
225+
Logfile "/var/log/tinyproxy/tinyproxy.log"
226+
LogLevel Info
227+
PidFile "/run/tinyproxy/tinyproxy.pid"
228+
MaxClients 500
229+
MinSpareServers 20
230+
MaxSpareServers 100
231+
StartServers 20
232+
MaxRequestsPerChild 0
233+
ViaProxyName "tinyproxy"
234+
ConnectPort 443
235+
ConnectPort 563
236+
EOF
237+
238+
/etc/init.d/tinyproxy restart
239+
240+
cat << EOF > /etc/redsocks.conf
241+
base {
242+
log_debug = off;
243+
log_info = on;
244+
log = "file:/var/log/redsocks";
245+
daemon = on;
246+
user = redsocks;
247+
group = redsocks;
248+
redirector = iptables;
249+
}
250+
251+
redsocks {
252+
local_ip = 0.0.0.0;
253+
local_port = 8889;
254+
ip = localhost;
255+
port = 8888;
256+
type = http-connect;
257+
}
258+
EOF
259+
260+
/etc/init.d/redsocks restart
261+
262+
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8888
263+
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8889
264+
265+
mkdir -p /etc/iptables/
266+
iptables-save > /etc/iptables/rules.v4
267+
268+
# Installing iptables-persistent without manual prompt
269+
# https://gist.github.com/alonisser/a2c19f5362c2091ac1e7
270+
echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections
271+
echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections
272+
apt-get install -y iptables-persistent
273+
Tags:
274+
- Key: Name
275+
Value: !Sub [ "Proxy-${StackIdSuffix}", {StackIdSuffix: !Select [1, !Split ['/', !Ref 'AWS::StackId']]}]
276+
277+
ProxyENI:
278+
Type: AWS::EC2::NetworkInterface
279+
Properties:
280+
GroupSet:
281+
- !Ref ProxySecurityGroup
282+
InterfaceType: interface
283+
SourceDestCheck: false
284+
SubnetId: !Ref PublicSubnet
285+
286+
# PROXY Client
287+
ProxyClient:
288+
Type: AWS::EC2::Instance
289+
DependsOn:
290+
- Proxy
291+
Properties:
292+
IamInstanceProfile: !Ref ProxyClientNodeInstanceProfile
293+
ImageId: resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id
294+
InstanceType: t2.medium
295+
KeyName: !Ref Keypair
296+
SecurityGroupIds:
297+
- !Ref ProxyClientSecurityGroup
298+
SubnetId: !Ref PrivateSubnet
299+
LaunchTemplate:
300+
LaunchTemplateId: !Ref Imdsv2LaunchTemplate
301+
Version: !GetAtt Imdsv2LaunchTemplate.LatestVersionNumber
302+
UserData:
303+
Fn::Base64:
304+
!Sub
305+
- |
306+
#!/bin/bash -ex
307+
set -o pipefail
308+
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
309+
310+
apt-get update -y
311+
apt-get -y install python3-pip
312+
pip3 install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz
313+
314+
cat >> /home/ubuntu/test-proxy.sh <<TEST
315+
http_proxy="http://${ProxyPrivateIp}:${ProxyPort}" wget https://github.com/aws/aws-parallelcluster/archive/refs/heads/develop.zip
316+
wget https://github.com/aws/aws-parallelcluster/archive/refs/heads/develop.zip
317+
TEST
318+
319+
chmod +x /home/ubuntu/test-proxy.sh
320+
321+
bash -ex /home/ubuntu/test-proxy.sh
322+
323+
/usr/local/bin/cfn-signal --exit-code 0 --stack "${AWS::StackName}" --region "${AWS::Region}" "${ProxyVerificationWaitConditionHandle}"
324+
325+
- {
326+
ProxyPrivateIp: !GetAtt Proxy.PrivateIp,
327+
ProxyPort: 8888,
328+
ProxyVerificationWaitConditionHandle: !Ref ProxyVerificationWaitConditionHandle
329+
}
330+
Tags:
331+
- Key: Name
332+
Value: !Sub [ "ProxyClient-${StackIdSuffix}", { StackIdSuffix: !Select [ 1, !Split [ '/', !Ref 'AWS::StackId' ] ] } ]
333+
334+
ProxyVerificationWaitConditionHandle:
335+
Type: AWS::CloudFormation::WaitConditionHandle
336+
337+
ProxyVerificationWaitCondition:
338+
Type: AWS::CloudFormation::WaitCondition
339+
Properties:
340+
Count: 1
341+
Handle: !Ref ProxyVerificationWaitConditionHandle
342+
Timeout: 600
343+
344+
345+
Outputs:
346+
VpcId:
347+
Value: !Ref Vpc
348+
PublicSubnet:
349+
Value: !Ref PublicSubnet
350+
PrivateSubnet:
351+
Value: !Ref PrivateSubnet
352+
ProxyAddress:
353+
Value: !Sub [ "http://${ProxyPrivateIp}:8888", { ProxyPrivateIp: !GetAtt Proxy.PrivateIp } ]
354+
ProxyClientSecurityGroup:
355+
Value: !Ref ProxyClientSecurityGroup

0 commit comments

Comments
 (0)