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