forked from naps-product-sa/ocp4-disconnected-workshop
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcloudformation.yaml
More file actions
980 lines (845 loc) · 32 KB
/
cloudformation.yaml
File metadata and controls
980 lines (845 loc) · 32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
Description: >
This template is used to simulate a disconnected environment. It deploys a
VPC with a single public subnet and three (3) private subnets, spread across
three (3) Availability Zones. It deploys an internet gateway, with a default
route on the public subnet. A NAT instance running a Squid proxy is deployed
in the public subnet and is configured to block all traffic except for access
to the AWS APIs. The NAT instance is configured as the default route for the
private subnets, which effectively makes the private subnets simulate a
disconnected environment. A jump host is also deployed in the public subnet
and is configured to allow access to the VPC.
Parameters:
VpcCidr:
Description: The IP range (CIDR notation) for this VPC
Type: String
Default: 10.0.0.0/16
Password:
Description: The password for the lab-user account on the instances
Type: String
S3TransferBucketName:
Description: The name of the S3 bucket that will be used to transfer files
Type: String
Default: autogenerate
NatInstanceType:
Description: The instance type to use for the NAT instance
Type: String
Default: m5a.large
AllowedValues:
- t3.small
- t3.medium
- t3.large
- m4.large
- m4.xlarge
- m5.large
- m5a.large
- m5.xlarge
- c4.large
- c4.xlarge
- c5.large
- c5.xlarge
JumpInstanceType:
Description: The instance type to use for the Jump instance
Type: String
Default: m5a.large
AllowedValues:
- t3.small #2vCPU & 2GiB - too small for GNOME + VNC + Firefox
- t3.medium #2vCPU & 4GiB
- t3.large #2vCPU & 8GiB
- m4.large
- m4.xlarge
- m5.large
- m5.xlarge
- m5a.large
- c4.large
- c4.xlarge
- c5.large
- c5.xlarge
HighSideInstanceType:
Description: The instance type to use for the High Side instance
Type: String
Default: m5a.large
AllowedValues:
- t3.large
- t3.xlarge
- m4.large
- m4.xlarge
- m5.large
- m5a.large
- m5.xlarge
- c4.large
- c4.xlarge
- c5.large
- c5.xlarge
JumpInstanceDataVolumeSize:
Description: The size of the data volume to attach to the Jump instance
Type: Number
Default: 150
HighSideInstanceDataVolumeSize:
Description: The size of the data volume to attach to the High Side instance
Type: Number
Default: 300
AccessKey:
Type: String
SecretKey:
Type: String
PullSecret:
Description: Base64 of the pull secret
Type: String
Mappings:
RegionMap:
ap-south-1:
ami: ami-0c0c57e3703b50314
eu-north-1:
ami: ami-078433bb440ad8323
eu-west-3:
ami: ami-0f2a71b6170e045d8
eu-west-2:
ami: ami-070e87281ec7b1a4d
eu-west-1:
ami: ami-008609c5b9c86c915
ap-northeast-3:
ami: ami-00f970067534af873
ap-northeast-2:
ami: ami-08c3474db131766ea
ap-northeast-1:
ami: ami-01b760eab729a9f4c
ca-central-1:
ami: ami-05eeb0575804a82d2
sa-east-1:
ami: ami-02c7c2dafbcfda401
ap-southeast-1:
ami: ami-0cef209741bb92e90
ap-southeast-2:
ami: ami-03a01cc2ae9bd8483
eu-central-1:
ami: ami-029d7f7f77709899f
us-east-1:
ami: ami-033d3612433d4049b
us-east-2:
ami: ami-05e5be364adedee9c #Use RHEL9.3 instead of RHEL8 at ami-04617ae0baf90b791
us-west-1:
ami: ami-09b6a34cb89a8c924
us-west-2:
ami: ami-08e6ba516533a3ce8
Conditions:
GenerateS3BucketName: !Equals [!Ref S3TransferBucketName, autogenerate]
Resources:
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCidr
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-vpc
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-igw
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref Vpc
#############################################################################
# Public Subnet
#############################################################################
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
AvailabilityZone: !Select [0, !GetAZs '']
CidrBlock: !Select [0, !Cidr [!Ref VpcCidr, 6, 12]]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-public
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-public
DefaultPublicRoute:
Type: AWS::EC2::Route
DependsOn: InternetGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet
#############################################################################
# Private Subnets
#############################################################################
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
AvailabilityZone: !Select [0, !GetAZs '']
CidrBlock: !Select [3, !Cidr [!Ref VpcCidr, 6, 12]]
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Join ["-", [!Ref AWS::StackName, "private", !Select [0, !GetAZs '']]]
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
Tags:
- Key: Name
Value: !Join ["-", [!Ref AWS::StackName, "private", !GetAtt PrivateSubnet1.AvailabilityZone]]
DefaultPrivateRoute1:
Type: AWS::EC2::Route
DependsOn: NatInstance
Properties:
RouteTableId: !Ref PrivateRouteTable1
DestinationCidrBlock: 0.0.0.0/0
InstanceId: !Ref NatInstance
PrivateSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable1
SubnetId: !Ref PrivateSubnet1
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
AvailabilityZone: !Select [1, !GetAZs '']
CidrBlock: !Select [4, !Cidr [!Ref VpcCidr, 6, 12]]
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Join ["-", [!Ref AWS::StackName, "private", !Select [1, !GetAZs '']]]
PrivateRouteTable2:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
Tags:
- Key: Name
Value: !Join ["-", [!Ref AWS::StackName, "private", !GetAtt PrivateSubnet2.AvailabilityZone]]
DefaultPrivateRoute2:
Type: AWS::EC2::Route
DependsOn: NatInstance
Properties:
RouteTableId: !Ref PrivateRouteTable2
DestinationCidrBlock: 0.0.0.0/0
InstanceId: !Ref NatInstance
PrivateSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable2
SubnetId: !Ref PrivateSubnet2
PrivateSubnet3:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
AvailabilityZone: !Select [2, !GetAZs '']
CidrBlock: !Select [5, !Cidr [!Ref VpcCidr, 6, 12]]
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Join ["-", [!Ref AWS::StackName, "private", !Select [2, !GetAZs '']]]
PrivateRouteTable3:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
Tags:
- Key: Name
Value: !Join ["-", [!Ref AWS::StackName, "private", !GetAtt PrivateSubnet3.AvailabilityZone]]
DefaultPrivateRoute3:
Type: AWS::EC2::Route
DependsOn: NatInstance
Properties:
RouteTableId: !Ref PrivateRouteTable3
DestinationCidrBlock: 0.0.0.0/0
InstanceId: !Ref NatInstance
PrivateSubnetRouteTableAssociation3:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable3
SubnetId: !Ref PrivateSubnet3
DefaultInstanceRole:
Type: AWS::IAM::Role
DependsOn: InstallIamUser
Properties:
RoleName: !Sub ${AWS::StackName}-default-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: root
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:*
Resource:
- !Join
- ""
- - "arn:aws:s3:::"
- !If [GenerateS3BucketName, !Sub "ocp4-disconnected-${AWS::AccountId}-${AWS::Region}", !Ref S3TransferBucketName]
- Effect: Allow
Action:
- s3:*
Resource:
- !Join
- ""
- - "arn:aws:s3:::"
- !If [GenerateS3BucketName, !Sub "ocp4-disconnected-${AWS::AccountId}-${AWS::Region}", !Ref S3TransferBucketName]
- "/*"
- Effect: Allow
Action:
- iam:CreateAccessKey
Resource:
- !GetAtt InstallIamUser.Arn
- Effect: Allow
Action:
- cloudformation:DescribeStacks
- ec2:DescribeSubnets
Resource: "*"
DefaultInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
InstanceProfileName: !Sub ${AWS::StackName}-default-profile
Path: /
Roles:
- !Ref DefaultInstanceRole
InstallIamUser:
Type: AWS::IAM::User
Properties:
UserName: !Sub ${AWS::StackName}-install-user
Policies:
- PolicyName: AdministratorAccess
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: "*"
Resource: "*"
#############################################################################
# NAT Instance
#############################################################################
NatInstanceRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${AWS::StackName}-nat-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
- arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
Policies:
- PolicyName: root
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- ec2:ModifyInstanceAttribute
Resource: "*"
NatInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
InstanceProfileName: !Sub ${AWS::StackName}-nat-profile
Path: /
Roles:
- !Ref NatInstanceRole
NatInstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${AWS::StackName}-nat-sg
GroupDescription: Allow HTTP and HTTPS from VPC to NAT instance
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: icmp
FromPort: -1
ToPort: -1
CidrIp: !Ref VpcCidr
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: !Ref VpcCidr
Description: HTTP
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: !Ref VpcCidr
Description: HTTPS
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref VpcCidr
Description: SSH
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-nat-sg
NatInstanceWaitHandle:
Type: AWS::CloudFormation::WaitConditionHandle
Properties: {}
NatInstanceWaitCondition:
Type: AWS::CloudFormation::WaitCondition
DependsOn: NatInstance
Properties:
Handle: !Ref NatInstanceWaitHandle
Timeout: 900
NatInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap ["RegionMap", !Ref "AWS::Region", "ami"]
InstanceType: !Ref NatInstanceType
IamInstanceProfile: !Ref NatInstanceProfile
NetworkInterfaces:
- DeviceIndex: 0
AssociatePublicIpAddress: true
GroupSet:
- !Ref NatInstanceSecurityGroup
SubnetId: !Ref PublicSubnet
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-nat
- Key: AnsibleGroup
Value: nat
- Key: DnsName
Value: nat
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
# Redirect the user-data output to the console logs
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
echo "PasswordAuthentication yes" > /etc/ssh/sshd_config.d/01-disco-workshop.conf
systemctl restart sshd
useradd -G systemd-journal lab-user
echo "${Password}" | passwd --stdin lab-user
echo "lab-user ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/50-lab-user
rm -f /etc/motd.d/insights-client
# Display a friendly name in bash
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-hostname.html#set-hostname-shell
sed -i 's/\([[:blank:]]*\[[[:blank:]]"\$PS1"[[:blank:]]*=[[:blank:]]*".*\)\(\\h\)\(.*\)/\1$NICKNAME\3/g' /etc/bashrc
echo "export NICKNAME=nat" > /etc/profile.d/friendly_prompt.sh
# Apply the latest security patches
yum update -y --security
yum install -y unzip vim firewalld
# Install the AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip
unzip -q -d /tmp /tmp/awscliv2.zip && rm -f /tmp/awscliv2.zip && /tmp/aws/install && rm -rf /tmp/aws
# Disable source / destination check. It cannot be disabled from the launch configuration
region=${AWS::Region}
instanceid=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
aws ec2 modify-instance-attribute --no-source-dest-check --instance-id $instanceid --region $region
# Add RHUI cert to trust bundle
trust anchor /etc/pki/rhui/cdn.redhat.com-chain.crt
update-ca-trust
# Install and start Squid
yum install -y squid
/usr/lib64/squid/security_file_certgen -c -s /var/spool/squid/ssl_db -M 4MB
systemctl enable --now squid
sleep 5
cp -a /etc/squid /etc/squid_orig
# Create a SSL certificate for the SslBump Squid module
mkdir /etc/squid/ssl
pushd /etc/squid/ssl
openssl genrsa -out squid.key 4096
openssl req -new -key squid.key -out squid.csr -subj "/C=US/ST=VA/L=squid/O=squid/CN=squid"
openssl x509 -req -days 3650 -in squid.csr -signkey squid.key -out squid.crt
cat squid.key squid.crt >> squid.pem
echo '.amazonaws.com' > /etc/squid/whitelist.txt
echo '.cloudfront.net' >> /etc/squid/whitelist.txt
echo '.aws.ce.redhat.com' >> /etc/squid/whitelist.txt
cat > /etc/squid/squid.conf << 'EOF'
visible_hostname squid
cache deny all
# Log format and rotation
logformat squid %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %ssl::>sni %Sh/%<a %mt
logfile_rotate 10
debug_options rotate=10
# Handle HTTP requests
http_port 3128
http_port 3129 intercept
# Handle HTTPS requests
https_port 3130 cert=/etc/squid/ssl/squid.pem ssl-bump intercept
acl SSL_port port 443
http_access allow SSL_port
acl step1 at_step SslBump1
acl step2 at_step SslBump2
acl step3 at_step SslBump3
ssl_bump peek step1 all
# Deny requests to proxy instance metadata
acl instance_metadata dst 169.254.169.254
http_access deny instance_metadata
# Filter HTTP requests based on the whitelist
acl allowed_http_sites dstdomain "/etc/squid/whitelist.txt"
http_access allow allowed_http_sites
# Filter HTTPS requests based on the whitelist
acl allowed_https_sites ssl::server_name "/etc/squid/whitelist.txt"
ssl_bump peek step2 allowed_https_sites
ssl_bump splice step3 allowed_https_sites
ssl_bump terminate step2 all
http_access deny all
EOF
/usr/sbin/squid -k parse && /usr/sbin/squid -k reconfigure
# Configure firewalld
sysctl -w net.ipv4.ip_forward=1 >> /etc/sysctl.d/10-custom.conf
firewall-offline-cmd --add-forward-port=port=80:proto=tcp:toport=3129
firewall-offline-cmd --add-forward-port=port=443:proto=tcp:toport=3130
firewall-offline-cmd --add-masquerade
systemctl enable --now firewalld
curl -X PUT -H 'Content-Type:' --data-binary '{"Status" : "SUCCESS","Reason" : "Configuration Complete","UniqueId" : "8675309","Data" : "Application has completed configuration."}' "${NatInstanceWaitHandle}"
#############################################################################
# Jump Instance
#############################################################################
JumpInstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${AWS::StackName}-jump-sg
GroupDescription: Allow SSH from everywhere to Jump instance
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: icmp
FromPort: -1
ToPort: -1
CidrIp: !Ref VpcCidr
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Description: SSH
- IpProtocol: tcp
FromPort: 5900
ToPort: 5900
CidrIp: 0.0.0.0/0
Description: VNC
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-jump-sg
JumpInstance:
Type: AWS::EC2::Instance
DependsOn: InternetGatewayAttachment
Properties:
ImageId: !FindInMap ["RegionMap", !Ref "AWS::Region", "ami"]
InstanceType: !Ref JumpInstanceType
IamInstanceProfile: !Ref DefaultInstanceProfile
NetworkInterfaces:
- DeviceIndex: 0
AssociatePublicIpAddress: true
GroupSet:
- !Ref JumpInstanceSecurityGroup
SubnetId: !Ref PublicSubnet
BlockDeviceMappings:
- DeviceName: /dev/sda1
Ebs:
DeleteOnTermination: true
VolumeSize: !Ref JumpInstanceDataVolumeSize
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-jump
- Key: AnsibleGroup
Value: bastions
- Key: DnsName
Value: jump
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
# Redirect the user-data output to the console logs
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
cat <<EOF > /etc/ssh/sshd_config.d/01-disco-workshop.conf
PasswordAuthentication yes
ClientAliveInterval 15
ClientAliveCountMax 3
EOF
systemctl restart sshd
useradd -G systemd-journal lab-user
echo "${Password}" | passwd --stdin lab-user
echo "lab-user ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/50-lab-user
rm -f /etc/motd.d/insights-client
# Display a friendly name in bash
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-hostname.html#set-hostname-shell
sed -i 's/\([[:blank:]]*\[[[:blank:]]"\$PS1"[[:blank:]]*=[[:blank:]]*".*\)\(\\h\)\(.*\)/\1$NICKNAME\3/g' /etc/bashrc
echo "export NICKNAME=jump" > /etc/profile.d/friendly_prompt.sh
# Apply the latest security patches
yum update -y --security
yum install -y unzip vim lvm2 git podman tmux jq
echo "set -g mouse on" >> /etc/tmux.conf
# # Partition and mount data disk
# pvcreate /dev/nvme1n1
# vgcreate data /dev/nvme1n1
# lvcreate --name ocp --extents 100%VG data
# mkfs.xfs /dev/mapper/data-ocp
# mkdir /mnt/low-side-data
# echo '/dev/mapper/data-ocp /mnt/low-side-data xfs defaults 0 0' >> /etc/fstab
# systemctl daemon-reload
# mount /mnt/low-side-data
mkdir /mnt/low-side-data
chown lab-user:lab-user /mnt/low-side-data
# Install the AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip
unzip -q -d /tmp /tmp/awscliv2.zip && rm -f /tmp/awscliv2.zip && /tmp/aws/install && rm -rf /tmp/aws
# Setup VNC
yum -y install "@GNOME" firefox tigervnc-server
# disable search functionality in firefox address bar
echo 'pref("browser.urlbar.suggest.searches", false);' >> /usr/lib64/firefox/defaults/preferences/all-redhat.js
echo 'pref("keyword.enabled", false);' >> /usr/lib64/firefox/defaults/preferences/all-redhat.js
firewall-cmd --add-service vnc-server --permanent && firewall-cmd --reload || echo "firewalld not installed"
export USER=lab-user #USER=ec2-user
export DISPLAY=:0
export VNCPASSWD=${Password}
mkdir -pv /home/$USER/.config
echo "yes" > /home/$USER/.config/gnome-initial-setup-done
chown -vR $USER:$USER /home/$USER/.config
sudo -u $USER dbus-launch --exit-with-session gsettings set org.gnome.shell welcome-dialog-last-shown-version '40.10'
echo "$DISPLAY=$USER" >> /etc/tigervnc/vncserver.users
mkdir -pv /home/$USER/.vnc
echo $VNCPASSWD | vncpasswd -f > /home/$USER/.vnc/passwd
echo "session=gnome-classic" >> /home/$USER/.vnc/config
chmod -v 0600 /home/$USER/.vnc/passwd
chown -vR $USER:$USER /home/$USER/.vnc
systemctl --global mask org.gnome.SettingsDaemon.Subscription.service
mkdir -pv /home/$USER/.config/autostart
cp -v /usr/share/applications/firefox.desktop /home/$USER/.config/autostart/
chown -vR $USER:$USER /home/$USER/.config/autostart
mkdir -pv /etc/systemd/system/vncserver\@.service.d
echo -e "[Service]\nRestart=always\n" >> /etc/systemd/system/vncserver\@.service.d/override.conf
systemctl enable --now vncserver@$DISPLAY
loginctl enable-linger lab-user
JumpInstanceEip:
Type: AWS::EC2::EIP
DependsOn: JumpInstance
Properties:
InstanceId: !Ref JumpInstance
#############################################################################
# High Side Instance
#############################################################################
HighSideInstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${AWS::StackName}-highside-sg
GroupDescription: Allow SSH from VPC to High Side instance
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: icmp
FromPort: -1
ToPort: -1
CidrIp: !Ref VpcCidr
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref VpcCidr
Description: SSH
- IpProtocol: tcp
FromPort: 8443
ToPort: 8443
CidrIp: !Ref VpcCidr
Description: Mirror Registry
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-highside-sg
HighSideInstance:
Type: AWS::EC2::Instance
DependsOn: NatInstanceWaitCondition
Properties:
ImageId: !FindInMap ["RegionMap", !Ref "AWS::Region", "ami"]
InstanceType: !Ref HighSideInstanceType
IamInstanceProfile: !Ref DefaultInstanceProfile
NetworkInterfaces:
- DeviceIndex: 0
AssociatePublicIpAddress: false
GroupSet:
- !Ref HighSideInstanceSecurityGroup
SubnetId: !Ref PrivateSubnet1
BlockDeviceMappings:
- DeviceName: /dev/sda1
Ebs:
DeleteOnTermination: true
VolumeSize: !Ref HighSideInstanceDataVolumeSize
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-highside
- Key: AnsibleGroup
Value: highside
- Key: DnsName
Value: highside
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
# Redirect the user-data output to the console logs
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
echo "PasswordAuthentication yes" > /etc/ssh/sshd_config.d/01-disco-workshop.conf
systemctl restart sshd
useradd -G systemd-journal lab-user
echo "${Password}" | passwd --stdin lab-user
echo "lab-user ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/50-lab-user
rm -f /etc/motd.d/insights-client
# Display a friendly name in bash
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-hostname.html#set-hostname-shell
sed -i 's/\([[:blank:]]*\[[[:blank:]]"\$PS1"[[:blank:]]*=[[:blank:]]*".*\)\(\\h\)\(.*\)/\1$NICKNAME\3/g' /etc/bashrc
echo "export NICKNAME=highside" > /etc/profile.d/friendly_prompt.sh
# Apply the latest security patches
yum update -y --security
yum install -y unzip vim lvm2 podman tmux jq
echo "set -g mouse on" >> /etc/tmux.conf
# # Partition and mount data disk
# pvcreate /dev/nvme1n1
# vgcreate data /dev/nvme1n1
# lvcreate --name ocp --extents 100%VG data
# mkfs.xfs /dev/mapper/data-ocp
# mkdir /mnt/high-side-data
# echo '/dev/mapper/data-ocp /mnt/high-side-data xfs defaults 0 0' >> /etc/fstab
# systemctl daemon-reload
# mount /mnt/high-side-data
mkdir /mnt/high-side-data
chown lab-user:lab-user /mnt/high-side-data
# Install the AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip
unzip -q -d /tmp /tmp/awscliv2.zip && rm -f /tmp/awscliv2.zip && /tmp/aws/install && rm -rf /tmp/aws
loginctl enable-linger lab-user
#############################################################################
# Salsa Cluster Registry
#############################################################################
SalsaImageRegistrySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub ${AWS::StackName}-salsaregistry-sg
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: icmp
FromPort: -1
ToPort: -1
CidrIp: !Ref VpcCidr
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref VpcCidr
Description: SSH
- IpProtocol: tcp
FromPort: 8443
ToPort: 8443
CidrIp: !Ref VpcCidr
Description: Mirror Registry
SalsaImageRegistryInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap ["RegionMap", !Ref "AWS::Region", "ami"]
InstanceType: !Ref HighSideInstanceType
IamInstanceProfile: !Ref DefaultInstanceProfile
BlockDeviceMappings:
- DeviceName: /dev/sda1
Ebs:
DeleteOnTermination: true
VolumeSize: !Ref HighSideInstanceDataVolumeSize
NetworkInterfaces:
- DeviceIndex: 0
AssociatePublicIpAddress: true
GroupSet:
- !Ref SalsaImageRegistrySecurityGroup
SubnetId: !Ref PublicSubnet
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-salsaregistry
- Key: AnsibleGroup
Value: salsa
- Key: DnsName
Value: salsa-registry
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
# Redirect the user-data output to the console logs
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
echo "PasswordAuthentication yes" > /etc/ssh/sshd_config.d/01-disco-workshop.conf
systemctl restart sshd
useradd -G systemd-journal lab-user
echo "${Password}" | passwd --stdin lab-user
echo "lab-user ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/50-lab-user
loginctl enable-linger lab-user
rm -f /etc/motd.d/insights-client
# Display a friendly name in bash
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-hostname.html#set-hostname-shell
sed -i 's/\([[:blank:]]*\[[[:blank:]]"\$PS1"[[:blank:]]*=[[:blank:]]*".*\)\(\\h\)\(.*\)/\1$NICKNAME\3/g' /etc/bashrc
echo "export NICKNAME=salsa-registry" > /etc/profile.d/friendly_prompt.sh
cat <<EOF > /etc/motd.d/salsa-cluster
This instance manages the mirror registry and install of the salsa cluster. You can check the progress with:
systemctl status mirror-registry-init.service cluster-init.service cloud-final.service
journalctl -f -u mirror-registry-init.service -u cluster-init.service -u cloud-final.service
EOF
# Apply the latest security patches
yum update -y --security
yum install -y unzip vim git podman tmux jq ansible-core python3-pip httpd-tools
mkdir /home/lab-user/.aws
cat <<EOF > /home/lab-user/.aws/config
[default]
aws_access_key_id=${AccessKey}
aws_secret_access_key=${SecretKey}
region=us-east-2
EOF
chown -R lab-user:lab-user /home/lab-user/.aws
mkdir /home/lab-user/.docker
echo ${PullSecret} | base64 -d | tr "'" '"' > /home/lab-user/.docker/config.json
podman logout --authfile /home/lab-user/.docker/config.json cloud.openshift.com
chown -R lab-user:lab-user /home/lab-user/.docker
echo ${PrivateSubnet1} > /home/lab-user/private-subnet-id
chown -R lab-user:lab-user /home/lab-user/private-subnet-id
curl -Lo /root/playbook.yaml https://raw.githubusercontent.com/naps-product-sa/ocp4-disconnected-workshop/main/playbook-imageregistry.yaml
ansible-playbook -v /root/playbook.yaml
#############################################################################
# S3 Transfer Bucket
#############################################################################
S3TransferBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
Properties:
BucketName: !If [GenerateS3BucketName, !Sub "${AWS::StackName}-${AWS::AccountId}-${AWS::Region}", !Ref S3TransferBucketName]
Outputs:
Vpc:
Description: A reference to the created VPC
Value: !Ref Vpc
PrivateSubnets:
Description: A list of the private subnets
Value: !Join [",", [!Ref PrivateSubnet1, !Ref PrivateSubnet2, !Ref PrivateSubnet3]]
PublicSubnet1:
Description: A reference to the public subnet
Value: !Ref PublicSubnet
PrivateSubnet1:
Description: A reference to the private subnet in the 1st Availability Zone
Value: !Ref PrivateSubnet1
PrivateSubnet2:
Description: A reference to the private subnet in the 2nd Availability Zone
Value: !Ref PrivateSubnet2
PrivateSubnet3:
Description: A reference to the private subnet in the 3rd Availability Zone
Value: !Ref PrivateSubnet3
S3TransferBucket:
Description: A reference to the S3 transfer bucket
Value: !Ref S3TransferBucket
JumpInstancePublicIp:
Description: A reference to the public EIP allocated to the Jump instance
Value: !Ref JumpInstanceEip
HighSideInstancePrivateIp:
Description: A reference to the private IP to the High Side instance
Value: !GetAtt HighSideInstance.PrivateIp
InstallIamUser:
Description: A reference to the IAM User to use for installing OpenShift
Value: !Ref InstallIamUser
SalsaImageRegistryPublicIp:
Value: !GetAtt SalsaImageRegistryInstance.PublicIp