├── AmazonLinux2-former2.yaml ├── AmazonLinux2023-former2.yaml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── THIRD_PARTY_LICENSES └── images ├── README.md ├── credentials.png └── ec2.png /AmazonLinux2-former2.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Description: Former2 (https://github.com/aws-samples/ec2-former2) (uksb-1nfhpgkj2i) (tag:AL2) 3 | Transform: "AWS::LanguageExtensions" 4 | 5 | Metadata: 6 | License: 7 | Description: > 8 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 9 | SPDX-License-Identifier: MIT-0 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 12 | software and associated documentation files (the "Software"), to deal in the Software 13 | without restriction, including without limitation the rights to use, copy, modify, 14 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 15 | permit persons to whom the Software is furnished to do so. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 18 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 19 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | AWS::CloudFormation::Interface: 24 | ParameterGroups: 25 | - Label: 26 | default: EC2 27 | Parameters: 28 | - ec2Name 29 | - processorArchitecture 30 | - instanceType 31 | - Label: 32 | default: Network 33 | Parameters: 34 | - vpcID 35 | - subnetID 36 | - displayPublicIP 37 | - assignStaticIP 38 | - Label: 39 | default: Remote access 40 | Parameters: 41 | - ingressIPv4 42 | - ingressIPv6 43 | - Label: 44 | default: EBS volume 45 | Parameters: 46 | - volumeSize 47 | - volumeType 48 | 49 | ParameterLabels: 50 | ec2Name: 51 | default: "EC2 instance name" 52 | processorArchitecture: 53 | default: "OS version and processor architecture" 54 | instanceType: 55 | default: "Instance type (x86_64 or arm64)" 56 | 57 | vpcID: 58 | default: "VPC with outbound internet connectivity" 59 | subnetID: 60 | default: "Subnet with outbound internet connectivity" 61 | displayPublicIP: 62 | default: "EC2 in public subnet with public IP assigned?" 63 | assignStaticIP: 64 | default: "Elastic IP: assign static public internet IPv4 address" 65 | 66 | ingressIPv4: 67 | default: "Allowed source prefix (IPv4)" 68 | ingressIPv6: 69 | default: "Allowed source prefix (IPv6)" 70 | 71 | volumeSize: 72 | default: "Volume size (GiB)" 73 | volumeType: 74 | default: "Volume type" 75 | 76 | Parameters: 77 | ec2Name: 78 | Description: EC2 instance name 79 | Type: String 80 | Default: AL2 with Former2 81 | processorArchitecture: 82 | Type: String 83 | Description: Processor architecture 84 | AllowedValues: 85 | - Amazon Linux 2 (arm64) 86 | - Amazon Linux 2 (x86_64) 87 | Default: Amazon Linux 2 (arm64) 88 | instanceType: 89 | Type: String 90 | Description: https://console.aws.amazon.com/ec2/#InstanceTypes 91 | AllowedPattern: "^[a-z\\-\\d\\.]+$" 92 | Default: t4g.xlarge 93 | 94 | vpcID: 95 | Type: AWS::EC2::VPC::Id 96 | Description: "https://console.aws.amazon.com/vpcconsole/home#vpcs:" 97 | AllowedPattern: .+ 98 | ConstraintDescription: Select a VPC 99 | subnetID: 100 | Type: AWS::EC2::Subnet::Id 101 | Description: "https://console.aws.amazon.com/vpcconsole/home#subnets:" 102 | AllowedPattern: .+ 103 | ConstraintDescription: Select a Subnet 104 | displayPublicIP: 105 | Type: String 106 | Description: Select No if EC2 has no public IP 107 | AllowedValues: 108 | - "Yes" 109 | - "No" 110 | Default: "Yes" 111 | assignStaticIP: 112 | Type: String 113 | Description: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html 114 | AllowedValues: 115 | - "Yes" 116 | - "No" 117 | Default: "Yes" 118 | 119 | ingressIPv4: 120 | Type: String 121 | Description: e.g. 1.2.3.4/32, get your internet IPv4 address from https://checkip.amazonaws.com 122 | AllowedPattern: "^\\d+\\.\\d+\\.\\d+\\.\\d+\\/\\d+$" 123 | ConstraintDescription: Specify valid IPv4 prefix 124 | Default: 0.0.0.0/0 125 | ingressIPv6: 126 | Type: String 127 | Description: e.g. 1:2:3:4::/64, get your internet IPv6 address (if any) with tools such as https://ifconfig.co 128 | AllowedPattern: .+ 129 | ConstraintDescription: Specify valid IPv6 prefix 130 | Default: ::/0 131 | 132 | volumeSize: 133 | Type: Number 134 | Description: https://docs.aws.amazon.com/ebs/latest/userguide/volume_constraints.html 135 | MinValue: 10 136 | MaxValue: 16384 137 | Default: 10 138 | volumeType: 139 | Type: String 140 | Description: https://docs.aws.amazon.com/ebs/latest/userguide/ebs-volume-types.html 141 | AllowedValues: 142 | - gp3 143 | - gp2 144 | Default: gp3 145 | 146 | Conditions: 147 | useARM64: !Equals [!Ref processorArchitecture, "Amazon Linux 2 (arm64)"] 148 | useElasticIP: !Equals [!Ref assignStaticIP, "Yes"] 149 | displayPublicIP: !Equals [!Ref displayPublicIP, "Yes"] 150 | hasEIC: 151 | !Not [ 152 | !Equals [ 153 | !FindInMap [ 154 | EICprefixMap, 155 | !Ref AWS::Region, 156 | IpPrefix, 157 | DefaultValue: 127.0.0.1/32, 158 | ], 159 | 127.0.0.1/32, 160 | ], 161 | ] 162 | createSgEIC: !And [!Condition hasEIC, !Condition displayPublicIP] 163 | 164 | Mappings: 165 | EICprefixMap: # EC2 instance connect: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-connect-prerequisites.html#ec2-instance-connect-setup-security-group 166 | af-south-1: 167 | IpPrefix: 13.244.121.196/30 168 | Ipv6Prefix: 2406:da11:700:3b00::/56 169 | ap-east-1: 170 | IpPrefix: 43.198.192.104/29 171 | Ipv6Prefix: 2406:da1e:da1:3c00::/56 172 | ap-northeast-1: 173 | IpPrefix: 3.112.23.0/29 174 | Ipv6Prefix: 2406:da14:1c18:2100::/56 175 | ap-northeast-2: 176 | IpPrefix: 13.209.1.56/29 177 | Ipv6Prefix: 2406:da12:1e1:d900::/56 178 | ap-northeast-3: 179 | IpPrefix: 15.168.105.160/29 180 | Ipv6Prefix: 2406:da16:856:a500::/56 181 | ap-south-1: 182 | IpPrefix: 13.233.177.0/29 183 | Ipv6Prefix: 2406:da1a:74a:4b00::/56 184 | ap-south-2: 185 | IpPrefix: 18.60.252.248/29 186 | Ipv6Prefix: 2406:da1b:d1d:8800::/56 187 | ap-southeast-1: 188 | IpPrefix: 3.0.5.32/29 189 | Ipv6Prefix: 2406:da18:752:6600::/56 190 | ap-southeast-2: 191 | IpPrefix: 13.239.158.0/29 192 | Ipv6Prefix: 2406:da1c:90e:4a00::/56 193 | ap-southeast-3: 194 | IpPrefix: 43.218.193.64/29 195 | Ipv6Prefix: 2406:da19:14b:8c00::/56 196 | ap-southeast-4: 197 | IpPrefix: 16.50.248.80/29 198 | Ipv6Prefix: 2406:da1f:b4f:4600::/56 199 | ap-southeast-5: 200 | IpPrefix: 43.216.87.48/29 201 | Ipv6Prefix: 2406:da10:84f9:9e00::/56 202 | ca-central-1: 203 | IpPrefix: 35.183.92.176/29 204 | Ipv6Prefix: 2600:1f11:ae3:700::/56 205 | ca-west-1: 206 | IpPrefix: 40.176.213.168/29 207 | Ipv6Prefix: 2600:1f1a:4ff6:d500::/56 208 | cn-north-1: 209 | IpPrefix: 43.196.20.40/29 210 | Ipv6Prefix: 2400:7fc0:86fd:e00::/56 211 | cn-northwest-1: 212 | IpPrefix: 43.192.155.8/29 213 | Ipv6Prefix: 2404:c2c0:87aa:4800::/56 214 | eu-central-1: 215 | IpPrefix: 3.120.181.40/29 216 | Ipv6Prefix: 2a05:d014:17a8:8b00::/56 217 | eu-central-2: 218 | IpPrefix: 16.63.77.8/29 219 | Ipv6Prefix: 2a05:d019:1d6:2100::/56 220 | eu-north-1: 221 | IpPrefix: 13.48.4.200/30 222 | Ipv6Prefix: 2a05:d016:494:f00::/56 223 | eu-south-1: 224 | IpPrefix: 15.161.135.164/30 225 | Ipv6Prefix: 2a05:d01a:c03:4a00::/56 226 | eu-south-2: 227 | IpPrefix: 18.101.90.48/29 228 | Ipv6Prefix: 2a05:d011:cbe:f700::/56 229 | eu-west-1: 230 | IpPrefix: 18.202.216.48/29 231 | Ipv6Prefix: 2a05:d018:403:4e00::/56 232 | eu-west-2: 233 | IpPrefix: 3.8.37.24/29 234 | Ipv6Prefix: 2a05:d01c:4ac:3100::/56 235 | eu-west-3: 236 | IpPrefix: 35.180.112.80/29 237 | Ipv6Prefix: 2a05:d012:c9e:d600::/56 238 | il-central-1: 239 | IpPrefix: 51.16.183.224/29 240 | Ipv6Prefix: 2a05:d025:451:7d00::/56 241 | me-central-1: 242 | IpPrefix: 3.29.147.40/29 243 | Ipv6Prefix: 2406:da17:1db:b00::/56 244 | me-south-1: 245 | IpPrefix: 16.24.46.56/29 246 | Ipv6Prefix: 2a05:d01e:27f:ac00::/56 247 | sa-east-1: 248 | IpPrefix: 18.228.70.32/29 249 | Ipv6Prefix: 2600:1f1e:d1d:e700::/56 250 | us-east-1: 251 | IpPrefix: 18.206.107.24/29 252 | Ipv6Prefix: 2600:1f18:6fe3:8c00::/56 253 | us-east-2: 254 | IpPrefix: 3.16.146.0/29 255 | Ipv6Prefix: 2600:1f16:138f:cf00::/56 256 | us-gov-east-1: 257 | IpPrefix: 18.252.4.0/30 258 | Ipv6Prefix: 2600:1f15:d63:bd00::/56 259 | us-gov-west-1: 260 | IpPrefix: 15.200.28.80/30 261 | Ipv6Prefix: 2600:1f12:fa9:5100::/56 262 | us-west-1: 263 | IpPrefix: 13.52.6.112/29 264 | Ipv6Prefix: 2600:1f1c:12d:e900::/56 265 | us-west-2: 266 | IpPrefix: 18.237.140.160/29 267 | Ipv6Prefix: 2600:1f13:a0d:a700::/56 268 | 269 | ConsoleUrl: 270 | aws: 271 | url: console.aws.amazon.com 272 | aws-cn: 273 | url: console.amazonaws.cn 274 | aws-gov: 275 | url: console.amazonaws-us-gov.com 276 | 277 | Resources: 278 | instanceIamRole: 279 | Type: AWS::IAM::Role 280 | Properties: 281 | AssumeRolePolicyDocument: 282 | Statement: 283 | - Effect: Allow 284 | Principal: 285 | Service: [ec2.amazonaws.com] 286 | Action: [sts:AssumeRole] 287 | Path: / 288 | Policies: 289 | - PolicyName: dcvLicensing 290 | PolicyDocument: # https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-license.html 291 | Version: "2012-10-17" 292 | Statement: 293 | - Effect: Allow 294 | Action: 295 | - s3:GetObject 296 | Resource: !Sub arn:aws:s3:::dcv-license.${AWS::Region}/* 297 | - PolicyName: DenyIfNotIPprefix 298 | PolicyDocument: # https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws_deny-ip.html 299 | Version: "2012-10-17" 300 | Statement: 301 | - Effect: Deny 302 | Action: "*" 303 | Resource: "*" 304 | Condition: 305 | NotIpAddress: 306 | aws:SourceIp: 0.0.0.0/0 307 | ManagedPolicyArns: 308 | - !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore" 309 | - !Sub "arn:${AWS::Partition}:iam::aws:policy/ReadOnlyAccess" 310 | Tags: 311 | - Key: StackName 312 | Value: !Ref AWS::StackName 313 | - Key: StackId 314 | Value: !Ref AWS::StackId 315 | - Key: GitHub 316 | Value: https://github.com/aws-samples/ec2-former2 317 | 318 | instanceProfile: 319 | Type: AWS::IAM::InstanceProfile 320 | Properties: 321 | Path: / 322 | Roles: 323 | - !Ref instanceIamRole 324 | 325 | securityGroup: 326 | Type: AWS::EC2::SecurityGroup 327 | Properties: 328 | GroupDescription: Allow inbound DCV 329 | VpcId: !Ref vpcID 330 | SecurityGroupIngress: 331 | - !If 332 | - createSgEIC 333 | - Description: EC2 Instance Connect (IPv4) 334 | IpProtocol: tcp 335 | FromPort: 22 336 | ToPort: 22 337 | CidrIp: !FindInMap [EICprefixMap, !Ref AWS::Region, IpPrefix] 338 | - !Ref AWS::NoValue 339 | - !If 340 | - createSgEIC 341 | - Description: EC2 Instance Connect (IPv6) 342 | IpProtocol: tcp 343 | FromPort: 22 344 | ToPort: 22 345 | CidrIpv6: !FindInMap [EICprefixMap, !Ref AWS::Region, Ipv6Prefix] 346 | - !Ref AWS::NoValue 347 | - Description: DCV (IPv4) 348 | IpProtocol: tcp 349 | FromPort: 8443 350 | ToPort: 8443 351 | CidrIp: !Ref ingressIPv4 352 | - Description: DCV QUIC (IPv4) 353 | IpProtocol: udp 354 | FromPort: 8443 355 | ToPort: 8443 356 | CidrIp: !Ref ingressIPv4 357 | - Description: DCV (IPv6) 358 | IpProtocol: tcp 359 | FromPort: 8443 360 | ToPort: 8443 361 | CidrIpv6: !Ref ingressIPv6 362 | - Description: DCV QUIC (IPv6) 363 | IpProtocol: udp 364 | FromPort: 8443 365 | ToPort: 8443 366 | CidrIpv6: !Ref ingressIPv6 367 | SecurityGroupEgress: 368 | - Description: Allow all outbound traffic (IPv4) 369 | IpProtocol: "-1" 370 | CidrIp: 0.0.0.0/0 371 | - Description: Allow all outbound traffic (IPv6) 372 | IpProtocol: "-1" 373 | CidrIpv6: ::/0 374 | Tags: 375 | - Key: StackName 376 | Value: !Ref AWS::StackName 377 | - Key: StackId 378 | Value: !Ref AWS::StackId 379 | - Key: Name 380 | Value: !Sub 381 | - "${AWS::StackName}-securityGroup-${UID}" 382 | - UID: 383 | !Select [ 384 | 3, 385 | !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], 386 | ] 387 | - Key: GitHub 388 | Value: https://github.com/aws-samples/ec2-former2 389 | 390 | ec2Instance: 391 | Type: AWS::EC2::Instance 392 | CreationPolicy: 393 | ResourceSignal: 394 | Timeout: PT90M 395 | Metadata: 396 | Comment: Install Update files 397 | AWS::CloudFormation::Init: 398 | configSets: 399 | setup: 400 | - 00_setup 401 | dcv_install: 402 | - 00_dcv_install 403 | 00_setup: # in the following order: packages, groups, users, sources, files, commands, and then services. 404 | files: 405 | "/var/www/THIRD_PARTY_LICENSES": 406 | content: | 407 | ** Former2; version 1.0 -- https://github.com/iann0036/former2 408 | MIT License 409 | 410 | Copyright (c) 2019 Ian Mckay 411 | 412 | Permission is hereby granted, free of charge, to any person obtaining a copy 413 | of this software and associated documentation files (the "Software"), to deal 414 | in the Software without restriction, including without limitation the rights 415 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 416 | copies of the Software, and to permit persons to whom the Software is 417 | furnished to do so, subject to the following conditions: 418 | 419 | The above copyright notice and this permission notice shall be included in all 420 | copies or substantial portions of the Software. 421 | 422 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 423 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 424 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 425 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 426 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 427 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 428 | SOFTWARE. 429 | 430 | MIT License 431 | 432 | Copyright (c) 2019 Ian Mckay 433 | 434 | Permission is hereby granted, free of charge, to any person obtaining a copy 435 | of this software and associated documentation files (the "Software"), to deal 436 | in the Software without restriction, including without limitation the rights 437 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 438 | copies of the Software, and to permit persons to whom the Software is 439 | furnished to do so, subject to the following conditions: 440 | 441 | The above copyright notice and this permission notice shall be included in all 442 | copies or substantial portions of the Software. 443 | 444 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 445 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 446 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 447 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 448 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 449 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 450 | SOFTWARE. 451 | mode: "000444" 452 | owner: "root" 453 | group: "root" 454 | "/home/ec2-user/update-former2": 455 | content: | 456 | #!/bin/bash 457 | cd /var/www/html 458 | sudo git pull 459 | mode: "000755" 460 | owner: "ec2-user" 461 | group: "users" 462 | "/home/ec2-user/update-dcv": 463 | content: | 464 | #!/bin/bash 465 | cd /tmp 466 | sudo rm -f /tmp/nice-dcv-amzn2-$(arch).tgz 467 | wget https://d1uj6qtbmh3dt5.cloudfront.net/nice-dcv-amzn2-$(arch).tgz 468 | tar -xvzf nice-dcv-amzn2-$(arch).tgz && cd nice-dcv-*-amzn2-$(arch) 469 | sudo yum install -y ./nice-dcv-server-*.rpm 470 | sudo yum install -y ./nice-dcv-web-viewer-*.rpm 471 | sudo yum install -y ./nice-xdcv-*.rpm 472 | sudo systemctl daemon-reload 473 | mode: "000755" 474 | owner: "ec2-user" 475 | group: "ec2-user" 476 | "/home/ec2-user/update-awscli": 477 | content: | 478 | #!/bin/bash 479 | cd /tmp 480 | sudo rm -f /tmp/awscliv2.zip 481 | curl https://awscli.amazonaws.com/awscli-exe-linux-$(arch).zip -o awscliv2.zip 482 | unzip -q -o awscliv2.zip 483 | /usr/bin/aws --version 484 | sudo ./aws/install --update -b /usr/bin 485 | /usr/bin/aws --version 486 | mode: "000755" 487 | owner: "ec2-user" 488 | group: "ec2-user" 489 | "/home/ec2-user/get-iam-creds.sh": 490 | content: !Sub | 491 | #!/bin/bash 492 | TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 30"` && curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/${instanceIamRole} 493 | 494 | mode: "000740" 495 | owner: "ec2-user" 496 | group: "ec2-user" 497 | "/etc/systemd/system/dcv-virtual-session.service": 498 | content: | 499 | [Unit] 500 | Description=Create DCV virtual session 501 | After=default.target network.target 502 | 503 | [Service] 504 | ExecStart=/opt/dcv-virtual-session.sh 505 | 506 | [Install] 507 | WantedBy=default.target 508 | mode: "000644" 509 | owner: "root" 510 | group: "root" 511 | "/opt/dcv-virtual-session.sh": 512 | content: | 513 | #!/bin/bash 514 | dcvUsers=( "ec2-user" ) 515 | while true; 516 | do 517 | for dcvUser in "${dcvUsers[@]}" 518 | do 519 | if (! /usr/bin/dcv list-sessions | grep -q $dcvUser); then 520 | /usr/bin/dcv create-session $dcvUser --owner $dcvUser --storage-root %home% --type virtual 521 | fi 522 | done 523 | date 524 | /usr/bin/dcv list-sessions 525 | sleep 5 526 | done 527 | mode: "000744" 528 | owner: "root" 529 | group: "root" 530 | "/etc/systemd/system/dcv-post-reboot.service": 531 | content: | 532 | [Unit] 533 | Description=Post install tasks 534 | After=default.target network.target 535 | 536 | [Service] 537 | ExecStart=/bin/sh -c "/opt/dcv-post-reboot.sh 2>&1 | tee -a /var/log/install-sw.log" 538 | 539 | [Install] 540 | WantedBy=default.target 541 | mode: "000644" 542 | owner: "root" 543 | group: "root" 544 | "/opt/dcv-post-reboot.sh": 545 | content: !Sub | 546 | #!/bin/bash 547 | #sysctl -w net.ipv6.conf.all.disable_ipv6=1 548 | #sysctl -w net.ipv6.conf.default.disable_ipv6=1 549 | 550 | /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ec2Instance --region ${AWS::Region} 551 | 552 | yum update -q -y 553 | 554 | #sysctl -w net.ipv6.conf.all.disable_ipv6=0 555 | #sysctl -w net.ipv6.conf.default.disable_ipv6=0 556 | 557 | systemctl enable dcv-virtual-session && systemctl restart dcv-virtual-session 558 | systemctl enable dcvserver && systemctl restart dcvserver 559 | 560 | rm -f /etc/systemd/system/dcv-post-reboot.service 561 | rm -f ${!0} 562 | systemctl daemon-reload 563 | mode: "000755" 564 | owner: "root" 565 | group: "root" 566 | "/root/install-sw.sh": 567 | content: !Sub | 568 | #!/bin/bash 569 | mkdir -p /tmp/cfn 570 | cd /tmp/cfn 571 | 572 | # EPEL: https://docs.fedoraproject.org/en-US/epel/ 573 | amazon-linux-extras install -y epel 574 | 575 | # Update OS 576 | yum clean all 577 | yum update -q -y 578 | sleep 10 579 | pkill "^yum$" 580 | 581 | # yum-cron 582 | yum install -q -y yum-cron 583 | sed -i 's/apply_updates = no/apply_updates = yes/g' /etc/yum/yum-cron.conf 584 | systemctl enable yum-cron 585 | 586 | # USB and GPU driver DKMS 587 | yum install -q -y dkms 588 | systemctl enable dkms 589 | 590 | # Kernel headers for GPU and USB remotization 591 | yum install -q -y kernel-devel 592 | yum install -q -y usbutils 593 | 594 | # AWS CLI: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html 595 | yum remove -q -y awscli 596 | cd /tmp/cfn 597 | # AWS CLI v2: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html 598 | curl -s https://awscli.amazonaws.com/awscli-exe-linux-$(arch).zip -o awscliv2.zip 599 | unzip -q -o awscliv2.zip 600 | ./aws/install -b /usr/bin 601 | echo "export AWS_CLI_AUTO_PROMPT=on-partial" >> /home/ec2-user/.bashrc 602 | 603 | rm -f ${!0} 604 | mode: "000740" 605 | owner: "root" 606 | group: "root" 607 | commands: 608 | install: 609 | command: "/root/install-sw.sh >> /var/log/install-sw.log 2>&1" 610 | ignoreErrors: "true" 611 | 00_dcv_install: 612 | files: 613 | "/root/install-dcv.sh": 614 | content: !Sub | 615 | #!/bin/bash 616 | mkdir -p /tmp/cfn 617 | cd /tmp/cfn 618 | 619 | # Update OS 620 | yum update -q -y 621 | 622 | # DCV prereq: https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-installing-linux-prereq.html 623 | yum install -q -y gdm gnome-session gnome-classic-session gnome-session-xsession 624 | yum install -q -y xorg-x11-server-Xorg xorg-x11-fonts-Type1 xorg-x11-drivers 625 | yum install -q -y gnome-terminal gnu-free-fonts-common gnu-free-mono-fonts gnu-free-sans-fonts gnu-free-serif-fonts 626 | 627 | # Microphone redirection: https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-installing-linux-server.html 628 | yum install -q -y pulseaudio pulseaudio-utils 629 | amazon-linux-extras install -y firefox 630 | 631 | # Disable the Wayland protocol: https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-installing-linux-prereq.html#linux-prereq-wayland 632 | sed -i '/^\[daemon\]/a WaylandEnable=false' /etc/gdm/custom.conf 633 | 634 | # DCV: https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-installing-linux-server.html 635 | rpm --import https://d1uj6qtbmh3dt5.cloudfront.net/NICE-GPG-KEY 636 | curl -s -L -O https://d1uj6qtbmh3dt5.cloudfront.net/nice-dcv-amzn2-$(arch).tgz 637 | tar -xvzf nice-dcv-amzn2-$(arch).tgz && cd nice-dcv-*-amzn2-$(arch) 638 | yum install -q -y ./nice-dcv-server-*.rpm 639 | yum install -q -y ./nice-dcv-web-viewer-*.rpm 640 | yum install -q -y ./nice-xdcv-*.rpm 641 | 642 | # Printer redirection: https://docs.aws.amazon.com/dcv/latest/adminguide/manage-printer.html 643 | yum install -q -y cups 644 | GROUP=$(cat /etc/cups/cups-files.conf | grep -oP "SystemGroup\s\K\w+") 645 | usermod -a -G $GROUP dcv 646 | systemctl enable cups 647 | 648 | # glxinfo : https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-installing-linux-prereq.html#linux-prereq-tools 649 | yum install -q -y glx-utils 650 | yum install -q -y vulkan clinfo 651 | 652 | # QUIC: https://docs.aws.amazon.com/dcv/latest/adminguide/enable-quic.html 653 | cp /etc/dcv/dcv.conf /etc/dcv/dcv.conf."`date +"%Y-%m-%d"`" 654 | sed -i "s/^#enable-quic-frontend=true/enable-quic-frontend=true/g" /etc/dcv/dcv.conf 655 | 656 | # Higher web client max resolution: https://docs.aws.amazon.com/dcv/latest/adminguide/config-param-ref.html 657 | sed -i "/^\[display/a web-client-max-head-resolution=(4096, 2160)" /etc/dcv/dcv.conf 658 | # Console session support 659 | sed -i "/^\[session-management\/automatic-console-session/a owner=\"ec2-user\"\nstorage-root=\"%home%\"" /etc/dcv/dcv.conf 660 | 661 | # 662 | systemctl daemon-reload 663 | systemctl enable dcv-virtual-session 664 | systemctl enable dcvserver 665 | 666 | # Firefox homepage 667 | cd /usr/lib64/firefox/browser/defaults/preferences/ 668 | sed -i "s/https:\/\/amazonlinux.com/http:\/\/localhost/g" all-amazonlinux.js 669 | sed -i "s/https:\/\/aws.amazon.com/http:\/\/localhost/g" all-amazonlinux.js 670 | 671 | mode: "000740" 672 | owner: "root" 673 | group: "root" 674 | commands: 675 | install: 676 | command: "/root/install-dcv.sh > /var/log/install-dcv.log 2>&1" 677 | ignoreErrors: "true" 678 | Properties: 679 | ImageId: 680 | !If [ 681 | useARM64, 682 | "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-arm64-gp2}}", 683 | "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-x86_64-gp2}}", 684 | ] 685 | InstanceType: !Ref instanceType 686 | IamInstanceProfile: !Ref instanceProfile 687 | SubnetId: !Ref subnetID 688 | Monitoring: true 689 | EbsOptimized: true 690 | SecurityGroupIds: 691 | - !Ref securityGroup 692 | BlockDeviceMappings: 693 | - DeviceName: /dev/xvda 694 | Ebs: 695 | VolumeType: !Ref volumeType 696 | VolumeSize: !Ref volumeSize 697 | DeleteOnTermination: true 698 | Encrypted: true 699 | UserData: 700 | Fn::Base64: !Sub | 701 | #!/bin/bash 702 | mkdir -p /tmp/cfn 703 | cd /tmp/cfn 704 | 705 | # disable IPv6 during setup 706 | #sysctl -w net.ipv6.conf.all.disable_ipv6=1 707 | #sysctl -w net.ipv6.conf.default.disable_ipv6=1 708 | 709 | yum clean all 710 | yum update -q -y 711 | yum install -q -y deltarpm wget tmux unzip tar curl sed 712 | 713 | export CFN_INIT="/opt/aws/bin/cfn-init" 714 | 715 | $CFN_INIT -v --stack ${AWS::StackName} --resource ec2Instance --region ${AWS::Region} -c setup 716 | 717 | $CFN_INIT -v --stack ${AWS::StackName} --resource ec2Instance --region ${AWS::Region} -c dcv_install 718 | 719 | # Setup Former2 720 | yum install -q -y httpd git 721 | cd /var/www/ 722 | git clone https://github.com/iann0036/former2 723 | mv html html.bak 724 | mv former2 html 725 | systemctl enable httpd 726 | 727 | # Change permissions and ownership 728 | usermod -a -G apache ec2-user 729 | chown -R ec2-user:apache /var/www/html 730 | chmod -R 2775 /var/www/html 731 | find /var/www/html -type d -exec sudo chmod 2775 {} \; 732 | find /var/www/html -type f -exec sudo chmod 0664 {} \; 733 | 734 | # Update OS 735 | yum update -q -y 736 | 737 | # yum-cron 738 | yum install -q -y yum-cron 739 | sed -i 's/apply_updates = no/apply_updates = yes/g' /etc/yum/yum-cron.conf 740 | systemctl enable yum-cron 741 | 742 | # 743 | systemctl set-default multi-user.target 744 | systemctl daemon-reload 745 | systemctl enable dcv-post-reboot 746 | 747 | # enable back IPv6 748 | #sysctl -w net.ipv6.conf.all.disable_ipv6=0 749 | #sysctl -w net.ipv6.conf.default.disable_ipv6=0 750 | 751 | sleep 1 && reboot 752 | Tags: 753 | - Key: Name 754 | Value: !Ref ec2Name 755 | - Key: StackName 756 | Value: !Ref AWS::StackName 757 | - Key: StackId 758 | Value: !Ref AWS::StackId 759 | - Key: GitHub 760 | Value: https://github.com/aws-samples/ec2-former2 761 | 762 | elasticIP: 763 | Condition: useElasticIP 764 | Type: AWS::EC2::EIP 765 | Properties: 766 | Domain: vpc 767 | NetworkBorderGroup: !Ref AWS::Region 768 | InstanceId: !Ref ec2Instance 769 | Tags: 770 | - Key: StackName 771 | Value: !Ref AWS::StackName 772 | - Key: StackId 773 | Value: !Ref AWS::StackId 774 | - Key: Name 775 | Value: !Sub 776 | - "${AWS::StackName}-elasticIP-${UID}" 777 | - UID: 778 | !Select [ 779 | 3, 780 | !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], 781 | ] 782 | - Key: GitHub 783 | Value: https://github.com/aws-samples/ec2-former2 784 | 785 | Outputs: 786 | EC2console: 787 | Description: EC2 console 788 | Value: !Sub 789 | - "https://${AWS::Region}.${url}/ec2/home?region=${AWS::Region}#Instances:search=${ec2Instance}" 790 | - url: 791 | !FindInMap [ 792 | ConsoleUrl, 793 | !Ref "AWS::Partition", 794 | url, 795 | DefaultValue: "console.aws.amazon.com", 796 | ] 797 | 798 | EC2instanceConnect: 799 | Condition: createSgEIC 800 | Description: EC2 Instance Connect 801 | Value: !Sub 802 | - "https://${AWS::Region}.${url}/ec2-instance-connect/ssh?connType=standard&instanceId=${ec2Instance}&osUser=ec2-user&sshPort=22#/" 803 | - url: 804 | !FindInMap [ 805 | ConsoleUrl, 806 | !Ref "AWS::Partition", 807 | url, 808 | DefaultValue: "console.aws.amazon.com", 809 | ] 810 | 811 | EC2serialConsole: 812 | Description: EC2 Serial Console 813 | Value: !Sub 814 | - "https://${AWS::Region}.${url}/ec2-instance-connect/ssh?connType=serial&instanceId=${ec2Instance}&serialPort=0#/" 815 | - url: 816 | !FindInMap [ 817 | ConsoleUrl, 818 | !Ref "AWS::Partition", 819 | url, 820 | DefaultValue: "console.aws.amazon.com", 821 | ] 822 | 823 | EC2iamRole: 824 | Description: EC2 IAM role 825 | Value: !Sub 826 | - "https://${url}/iam/home#/roles/details/${role}" 827 | - { 828 | role: !Select [1, !Split ["/", !GetAtt instanceIamRole.Arn]], 829 | url: 830 | !FindInMap [ 831 | ConsoleUrl, 832 | !Ref "AWS::Partition", 833 | url, 834 | DefaultValue: "console.aws.amazon.com", 835 | ], 836 | } 837 | 838 | SSMsessionManager: 839 | Description: SSM Session Manager ("sudo passwd ec2-user" to change password) 840 | Value: !Sub 841 | - "https://${AWS::Region}.${url}/systems-manager/session-manager/${ec2Instance}" 842 | - url: 843 | !FindInMap [ 844 | ConsoleUrl, 845 | !Ref "AWS::Partition", 846 | url, 847 | DefaultValue: "console.aws.amazon.com", 848 | ] 849 | 850 | DCVwebConsole: 851 | Description: DCV web browser client (login as ec2-user) 852 | Value: !Sub 853 | - "https://${IpAddress}:8443" 854 | - IpAddress: 855 | !If [ 856 | displayPublicIP, 857 | !GetAtt ec2Instance.PublicIp, 858 | !GetAtt ec2Instance.PrivateIp, 859 | ] 860 | 861 | GetIAMcreds: 862 | Description: Command to retrieve IAM credentials for http://localhost/#section-setup-credentials 863 | Value: !Sub 'TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 30"` && curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/${instanceIamRole}' 864 | -------------------------------------------------------------------------------- /AmazonLinux2023-former2.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Description: Former2 (https://github.com/aws-samples/ec2-former2) (uksb-1nfhpgkj2i) (tag:AL2023) 3 | Transform: "AWS::LanguageExtensions" 4 | 5 | Metadata: 6 | License: 7 | Description: > 8 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 9 | SPDX-License-Identifier: MIT-0 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 12 | software and associated documentation files (the "Software"), to deal in the Software 13 | without restriction, including without limitation the rights to use, copy, modify, 14 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 15 | permit persons to whom the Software is furnished to do so. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 18 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 19 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | AWS::CloudFormation::Interface: 24 | ParameterGroups: 25 | - Label: 26 | default: EC2 27 | Parameters: 28 | - ec2Name 29 | - processorArchitecture 30 | - instanceType 31 | - Label: 32 | default: Network 33 | Parameters: 34 | - vpcID 35 | - subnetID 36 | - displayPublicIP 37 | - assignStaticIP 38 | - Label: 39 | default: Remote access 40 | Parameters: 41 | - ingressIPv4 42 | - ingressIPv6 43 | - Label: 44 | default: EBS volume 45 | Parameters: 46 | - volumeSize 47 | - volumeType 48 | 49 | ParameterLabels: 50 | ec2Name: 51 | default: "EC2 instance name" 52 | processorArchitecture: 53 | default: "OS version and processor architecture" 54 | instanceType: 55 | default: "Instance type (x86_64 or arm64)" 56 | 57 | vpcID: 58 | default: "VPC with outbound internet connectivity" 59 | subnetID: 60 | default: "Subnet with outbound internet connectivity" 61 | displayPublicIP: 62 | default: "EC2 in public subnet with public IP assigned?" 63 | assignStaticIP: 64 | default: "Elastic IP: assign static public internet IPv4 address" 65 | 66 | ingressIPv4: 67 | default: "Allowed source prefix (IPv4)" 68 | ingressIPv6: 69 | default: "Allowed source prefix (IPv6)" 70 | 71 | volumeSize: 72 | default: "Volume size (GiB)" 73 | volumeType: 74 | default: "Volume type" 75 | 76 | Parameters: 77 | ec2Name: 78 | Description: EC2 instance name 79 | Type: String 80 | Default: AL2023 with Former2 81 | processorArchitecture: 82 | Type: String 83 | Description: Processor architecture 84 | AllowedValues: 85 | - Amazon Linux 2023 (arm64) 86 | - Amazon Linux 2023 (x86_64) 87 | Default: Amazon Linux 2023 (arm64) 88 | instanceType: 89 | Type: String 90 | Description: https://console.aws.amazon.com/ec2/#InstanceTypes 91 | AllowedPattern: "^[a-z\\-\\d\\.]+$" 92 | Default: t4g.xlarge 93 | 94 | vpcID: 95 | Type: AWS::EC2::VPC::Id 96 | Description: "https://console.aws.amazon.com/vpcconsole/home#vpcs:" 97 | AllowedPattern: .+ 98 | ConstraintDescription: Select a VPC 99 | subnetID: 100 | Type: AWS::EC2::Subnet::Id 101 | Description: "https://console.aws.amazon.com/vpcconsole/home#subnets:" 102 | AllowedPattern: .+ 103 | ConstraintDescription: Select a Subnet 104 | displayPublicIP: 105 | Type: String 106 | Description: Select No if EC2 has no public IP 107 | AllowedValues: 108 | - "Yes" 109 | - "No" 110 | Default: "Yes" 111 | assignStaticIP: 112 | Type: String 113 | Description: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html 114 | AllowedValues: 115 | - "Yes" 116 | - "No" 117 | Default: "Yes" 118 | 119 | ingressIPv4: 120 | Type: String 121 | Description: e.g. 1.2.3.4/32, get your internet IPv4 address from https://checkip.amazonaws.com 122 | AllowedPattern: "^\\d+\\.\\d+\\.\\d+\\.\\d+\\/\\d+$" 123 | ConstraintDescription: Specify valid IPv4 prefix 124 | Default: 0.0.0.0/0 125 | ingressIPv6: 126 | Type: String 127 | Description: e.g. 1:2:3:4::/64, get your internet IPv6 address (if any) with tools such as https://ifconfig.co 128 | AllowedPattern: .+ 129 | ConstraintDescription: Specify valid IPv6 prefix 130 | Default: ::/0 131 | 132 | volumeSize: 133 | Type: Number 134 | Description: https://docs.aws.amazon.com/ebs/latest/userguide/volume_constraints.html 135 | MinValue: 10 136 | MaxValue: 16384 137 | Default: 10 138 | volumeType: 139 | Type: String 140 | Description: https://docs.aws.amazon.com/ebs/latest/userguide/ebs-volume-types.html 141 | AllowedValues: 142 | - gp3 143 | - gp2 144 | Default: gp3 145 | 146 | Conditions: 147 | useARM64: !Equals [!Ref processorArchitecture, "Amazon Linux 2023 (arm64)"] 148 | useElasticIP: !Equals [!Ref assignStaticIP, "Yes"] 149 | displayPublicIP: !Equals [!Ref displayPublicIP, "Yes"] 150 | hasEIC: 151 | !Not [ 152 | !Equals [ 153 | !FindInMap [ 154 | EICprefixMap, 155 | !Ref AWS::Region, 156 | IpPrefix, 157 | DefaultValue: 127.0.0.1/32, 158 | ], 159 | 127.0.0.1/32, 160 | ], 161 | ] 162 | createSgEIC: !And [!Condition hasEIC, !Condition displayPublicIP] 163 | 164 | Mappings: 165 | EICprefixMap: # EC2 instance connect: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-connect-prerequisites.html#ec2-instance-connect-setup-security-group 166 | af-south-1: 167 | IpPrefix: 13.244.121.196/30 168 | Ipv6Prefix: 2406:da11:700:3b00::/56 169 | ap-east-1: 170 | IpPrefix: 43.198.192.104/29 171 | Ipv6Prefix: 2406:da1e:da1:3c00::/56 172 | ap-northeast-1: 173 | IpPrefix: 3.112.23.0/29 174 | Ipv6Prefix: 2406:da14:1c18:2100::/56 175 | ap-northeast-2: 176 | IpPrefix: 13.209.1.56/29 177 | Ipv6Prefix: 2406:da12:1e1:d900::/56 178 | ap-northeast-3: 179 | IpPrefix: 15.168.105.160/29 180 | Ipv6Prefix: 2406:da16:856:a500::/56 181 | ap-south-1: 182 | IpPrefix: 13.233.177.0/29 183 | Ipv6Prefix: 2406:da1a:74a:4b00::/56 184 | ap-south-2: 185 | IpPrefix: 18.60.252.248/29 186 | Ipv6Prefix: 2406:da1b:d1d:8800::/56 187 | ap-southeast-1: 188 | IpPrefix: 3.0.5.32/29 189 | Ipv6Prefix: 2406:da18:752:6600::/56 190 | ap-southeast-2: 191 | IpPrefix: 13.239.158.0/29 192 | Ipv6Prefix: 2406:da1c:90e:4a00::/56 193 | ap-southeast-3: 194 | IpPrefix: 43.218.193.64/29 195 | Ipv6Prefix: 2406:da19:14b:8c00::/56 196 | ap-southeast-4: 197 | IpPrefix: 16.50.248.80/29 198 | Ipv6Prefix: 2406:da1f:b4f:4600::/56 199 | ap-southeast-5: 200 | IpPrefix: 43.216.87.48/29 201 | Ipv6Prefix: 2406:da10:84f9:9e00::/56 202 | ca-central-1: 203 | IpPrefix: 35.183.92.176/29 204 | Ipv6Prefix: 2600:1f11:ae3:700::/56 205 | ca-west-1: 206 | IpPrefix: 40.176.213.168/29 207 | Ipv6Prefix: 2600:1f1a:4ff6:d500::/56 208 | cn-north-1: 209 | IpPrefix: 43.196.20.40/29 210 | Ipv6Prefix: 2400:7fc0:86fd:e00::/56 211 | cn-northwest-1: 212 | IpPrefix: 43.192.155.8/29 213 | Ipv6Prefix: 2404:c2c0:87aa:4800::/56 214 | eu-central-1: 215 | IpPrefix: 3.120.181.40/29 216 | Ipv6Prefix: 2a05:d014:17a8:8b00::/56 217 | eu-central-2: 218 | IpPrefix: 16.63.77.8/29 219 | Ipv6Prefix: 2a05:d019:1d6:2100::/56 220 | eu-north-1: 221 | IpPrefix: 13.48.4.200/30 222 | Ipv6Prefix: 2a05:d016:494:f00::/56 223 | eu-south-1: 224 | IpPrefix: 15.161.135.164/30 225 | Ipv6Prefix: 2a05:d01a:c03:4a00::/56 226 | eu-south-2: 227 | IpPrefix: 18.101.90.48/29 228 | Ipv6Prefix: 2a05:d011:cbe:f700::/56 229 | eu-west-1: 230 | IpPrefix: 18.202.216.48/29 231 | Ipv6Prefix: 2a05:d018:403:4e00::/56 232 | eu-west-2: 233 | IpPrefix: 3.8.37.24/29 234 | Ipv6Prefix: 2a05:d01c:4ac:3100::/56 235 | eu-west-3: 236 | IpPrefix: 35.180.112.80/29 237 | Ipv6Prefix: 2a05:d012:c9e:d600::/56 238 | il-central-1: 239 | IpPrefix: 51.16.183.224/29 240 | Ipv6Prefix: 2a05:d025:451:7d00::/56 241 | me-central-1: 242 | IpPrefix: 3.29.147.40/29 243 | Ipv6Prefix: 2406:da17:1db:b00::/56 244 | me-south-1: 245 | IpPrefix: 16.24.46.56/29 246 | Ipv6Prefix: 2a05:d01e:27f:ac00::/56 247 | sa-east-1: 248 | IpPrefix: 18.228.70.32/29 249 | Ipv6Prefix: 2600:1f1e:d1d:e700::/56 250 | us-east-1: 251 | IpPrefix: 18.206.107.24/29 252 | Ipv6Prefix: 2600:1f18:6fe3:8c00::/56 253 | us-east-2: 254 | IpPrefix: 3.16.146.0/29 255 | Ipv6Prefix: 2600:1f16:138f:cf00::/56 256 | us-gov-east-1: 257 | IpPrefix: 18.252.4.0/30 258 | Ipv6Prefix: 2600:1f15:d63:bd00::/56 259 | us-gov-west-1: 260 | IpPrefix: 15.200.28.80/30 261 | Ipv6Prefix: 2600:1f12:fa9:5100::/56 262 | us-west-1: 263 | IpPrefix: 13.52.6.112/29 264 | Ipv6Prefix: 2600:1f1c:12d:e900::/56 265 | us-west-2: 266 | IpPrefix: 18.237.140.160/29 267 | Ipv6Prefix: 2600:1f13:a0d:a700::/56 268 | 269 | ConsoleUrl: 270 | aws: 271 | url: console.aws.amazon.com 272 | aws-cn: 273 | url: console.amazonaws.cn 274 | aws-gov: 275 | url: console.amazonaws-us-gov.com 276 | 277 | Resources: 278 | instanceIamRole: 279 | Type: AWS::IAM::Role 280 | Properties: 281 | AssumeRolePolicyDocument: 282 | Statement: 283 | - Effect: Allow 284 | Principal: 285 | Service: [ec2.amazonaws.com] 286 | Action: [sts:AssumeRole] 287 | Path: / 288 | Policies: 289 | - PolicyName: dcvLicensing 290 | PolicyDocument: # https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-license.html 291 | Version: "2012-10-17" 292 | Statement: 293 | - Effect: Allow 294 | Action: 295 | - s3:GetObject 296 | Resource: !Sub arn:aws:s3:::dcv-license.${AWS::Region}/* 297 | - PolicyName: DenyIfNotIPprefix 298 | PolicyDocument: # https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws_deny-ip.html 299 | Version: "2012-10-17" 300 | Statement: 301 | - Effect: Deny 302 | Action: "*" 303 | Resource: "*" 304 | Condition: 305 | NotIpAddress: 306 | aws:SourceIp: 0.0.0.0/0 307 | ManagedPolicyArns: 308 | - !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore" 309 | - !Sub "arn:${AWS::Partition}:iam::aws:policy/ReadOnlyAccess" 310 | Tags: 311 | - Key: StackName 312 | Value: !Ref AWS::StackName 313 | - Key: StackId 314 | Value: !Ref AWS::StackId 315 | - Key: GitHub 316 | Value: https://github.com/aws-samples/ec2-former2 317 | 318 | instanceProfile: 319 | Type: AWS::IAM::InstanceProfile 320 | Properties: 321 | Path: / 322 | Roles: 323 | - !Ref instanceIamRole 324 | 325 | securityGroup: 326 | Type: AWS::EC2::SecurityGroup 327 | Properties: 328 | GroupDescription: Allow inbound DCV 329 | VpcId: !Ref vpcID 330 | SecurityGroupIngress: 331 | - !If 332 | - createSgEIC 333 | - Description: EC2 Instance Connect (IPv4) 334 | IpProtocol: tcp 335 | FromPort: 22 336 | ToPort: 22 337 | CidrIp: !FindInMap [EICprefixMap, !Ref AWS::Region, IpPrefix] 338 | - !Ref AWS::NoValue 339 | - !If 340 | - createSgEIC 341 | - Description: EC2 Instance Connect (IPv6) 342 | IpProtocol: tcp 343 | FromPort: 22 344 | ToPort: 22 345 | CidrIpv6: !FindInMap [EICprefixMap, !Ref AWS::Region, Ipv6Prefix] 346 | - !Ref AWS::NoValue 347 | - Description: DCV (IPv4) 348 | IpProtocol: tcp 349 | FromPort: 8443 350 | ToPort: 8443 351 | CidrIp: !Ref ingressIPv4 352 | - Description: DCV QUIC (IPv4) 353 | IpProtocol: udp 354 | FromPort: 8443 355 | ToPort: 8443 356 | CidrIp: !Ref ingressIPv4 357 | - Description: DCV (IPv6) 358 | IpProtocol: tcp 359 | FromPort: 8443 360 | ToPort: 8443 361 | CidrIpv6: !Ref ingressIPv6 362 | - Description: DCV QUIC (IPv6) 363 | IpProtocol: udp 364 | FromPort: 8443 365 | ToPort: 8443 366 | CidrIpv6: !Ref ingressIPv6 367 | SecurityGroupEgress: 368 | - Description: Allow all outbound traffic (IPv4) 369 | IpProtocol: "-1" 370 | CidrIp: 0.0.0.0/0 371 | - Description: Allow all outbound traffic (IPv6) 372 | IpProtocol: "-1" 373 | CidrIpv6: ::/0 374 | Tags: 375 | - Key: StackName 376 | Value: !Ref AWS::StackName 377 | - Key: StackId 378 | Value: !Ref AWS::StackId 379 | - Key: Name 380 | Value: !Sub 381 | - "${AWS::StackName}-securityGroup-${UID}" 382 | - UID: 383 | !Select [ 384 | 3, 385 | !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], 386 | ] 387 | - Key: GitHub 388 | Value: https://github.com/aws-samples/ec2-former2 389 | 390 | ec2Instance: 391 | Type: AWS::EC2::Instance 392 | CreationPolicy: 393 | ResourceSignal: 394 | Timeout: PT90M 395 | Metadata: 396 | Comment: Install Update files 397 | AWS::CloudFormation::Init: 398 | configSets: 399 | setup: 400 | - 00_setup 401 | dcv_install: 402 | - 00_dcv_install 403 | 00_setup: # in the following order: packages, groups, users, sources, files, commands, and then services. 404 | files: 405 | "/var/www/THIRD_PARTY_LICENSES": 406 | content: | 407 | ** Former2; version 1.0 -- https://github.com/iann0036/former2 408 | MIT License 409 | 410 | Copyright (c) 2019 Ian Mckay 411 | 412 | Permission is hereby granted, free of charge, to any person obtaining a copy 413 | of this software and associated documentation files (the "Software"), to deal 414 | in the Software without restriction, including without limitation the rights 415 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 416 | copies of the Software, and to permit persons to whom the Software is 417 | furnished to do so, subject to the following conditions: 418 | 419 | The above copyright notice and this permission notice shall be included in all 420 | copies or substantial portions of the Software. 421 | 422 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 423 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 424 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 425 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 426 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 427 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 428 | SOFTWARE. 429 | 430 | MIT License 431 | 432 | Copyright (c) 2019 Ian Mckay 433 | 434 | Permission is hereby granted, free of charge, to any person obtaining a copy 435 | of this software and associated documentation files (the "Software"), to deal 436 | in the Software without restriction, including without limitation the rights 437 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 438 | copies of the Software, and to permit persons to whom the Software is 439 | furnished to do so, subject to the following conditions: 440 | 441 | The above copyright notice and this permission notice shall be included in all 442 | copies or substantial portions of the Software. 443 | 444 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 445 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 446 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 447 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 448 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 449 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 450 | SOFTWARE. 451 | mode: "000444" 452 | owner: "root" 453 | group: "root" 454 | "/home/ec2-user/update-former2": 455 | content: | 456 | #!/bin/bash 457 | cd /var/www/html 458 | sudo git pull 459 | mode: "000755" 460 | owner: "ec2-user" 461 | group: "users" 462 | "/home/ec2-user/update-dcv": 463 | content: | 464 | #!/bin/bash 465 | cd /tmp 466 | sudo rm -f /tmp/nice-dcv-amzn2023-$(arch).tgz 467 | wget https://d1uj6qtbmh3dt5.cloudfront.net/nice-dcv-amzn2023-$(arch).tgz 468 | tar -xvzf nice-dcv-amzn2023-$(arch).tgz && cd nice-dcv-*-amzn2023-$(arch) 469 | sudo dnf install -y ./nice-dcv-server-*.rpm 470 | sudo dnf install -y ./nice-dcv-web-viewer-*.rpm 471 | sudo dnf install -y ./nice-xdcv-*.rpm 472 | sudo systemctl daemon-reload 473 | mode: "000755" 474 | owner: "ec2-user" 475 | group: "ec2-user" 476 | "/home/ec2-user/get-iam-creds.sh": 477 | content: !Sub | 478 | #!/bin/bash 479 | TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 30"` && curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/${instanceIamRole} 480 | 481 | mode: "000740" 482 | owner: "ec2-user" 483 | group: "ec2-user" 484 | "/etc/systemd/system/dcv-virtual-session.service": 485 | content: | 486 | [Unit] 487 | Description=Create DCV virtual session 488 | After=default.target network.target 489 | 490 | [Service] 491 | ExecStart=/opt/dcv-virtual-session.sh 492 | 493 | [Install] 494 | WantedBy=default.target 495 | mode: "000644" 496 | owner: "root" 497 | group: "root" 498 | "/opt/dcv-virtual-session.sh": 499 | content: | 500 | #!/bin/bash 501 | dcvUsers=( "ec2-user" ) 502 | while true; 503 | do 504 | for dcvUser in "${dcvUsers[@]}" 505 | do 506 | if (! /usr/bin/dcv list-sessions | grep -q $dcvUser); then 507 | /usr/bin/dcv create-session $dcvUser --owner $dcvUser --storage-root %home% --type virtual 508 | fi 509 | done 510 | date 511 | /usr/bin/dcv list-sessions 512 | sleep 5 513 | done 514 | mode: "000744" 515 | owner: "root" 516 | group: "root" 517 | "/etc/systemd/system/dcv-post-reboot.service": 518 | content: | 519 | [Unit] 520 | Description=Post install tasks 521 | After=default.target network.target 522 | 523 | [Service] 524 | ExecStart=/bin/sh -c "/opt/dcv-post-reboot.sh 2>&1 | tee -a /var/log/install-sw.log" 525 | 526 | [Install] 527 | WantedBy=default.target 528 | mode: "000644" 529 | owner: "root" 530 | group: "root" 531 | "/opt/dcv-post-reboot.sh": 532 | content: !Sub | 533 | #!/bin/bash 534 | #sysctl -w net.ipv6.conf.all.disable_ipv6=1 535 | #sysctl -w net.ipv6.conf.default.disable_ipv6=1 536 | 537 | /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ec2Instance --region ${AWS::Region} 538 | 539 | dnf update -q -y 540 | 541 | # https://docs.aws.amazon.com/linux/al2023/ug/managing-repos-os-updates.html#automatic-restart-services 542 | dnf install -q -y smart-restart 543 | touch /etc/smart-restart-conf.d/0-pre-restart 544 | chmod +x /etc/smart-restart-conf.d/0-pre-restart 545 | touch /etc/smart-restart-conf.d/0-post-restart 546 | chmod +x /etc/smart-restart-conf.d/0-post-restart 547 | 548 | #sysctl -w net.ipv6.conf.all.disable_ipv6=0 549 | #sysctl -w net.ipv6.conf.default.disable_ipv6=0 550 | 551 | systemctl enable dcv-virtual-session && systemctl restart dcv-virtual-session 552 | systemctl enable dcvserver && systemctl restart dcvserver 553 | 554 | rm -f /etc/systemd/system/dcv-post-reboot.service 555 | rm -f ${!0} 556 | systemctl daemon-reload 557 | mode: "000755" 558 | owner: "root" 559 | group: "root" 560 | "/root/install-sw.sh": 561 | content: !Sub | 562 | #!/bin/bash 563 | mkdir -p /tmp/cfn 564 | cd /tmp/cfn 565 | 566 | # Update OS 567 | dnf clean all 568 | dnf update -q -y 569 | sleep 10 570 | pkill "^dnf$" 571 | 572 | # dnf-automatic: https://dnf.readthedocs.io/en/latest/automatic.html 573 | dnf install -q -y dnf-automatic 574 | sed -i 's/apply_updates = no/apply_updates = yes/g' /etc/dnf/automatic.conf 575 | sed -i 's/emit_via = stdio/emit_via = motd/g' /etc/dnf/automatic.conf 576 | systemctl enable dnf-automatic-install.timer 577 | 578 | # https://docs.aws.amazon.com/linux/al2023/ug/deterministic-upgrades-usage.html#deterministic-upgrade-override-persist 579 | echo latest | sudo tee /etc/dnf/vars/releasever 580 | 581 | # Enable crontab 582 | dnf install -q -y cronie 583 | systemctl enable --now crond 584 | 585 | # USB and GPU driver DKMS 586 | dnf install -q -y dkms 587 | systemctl enable dkms 588 | 589 | # Kernel headers for GPU and USB remotization 590 | dnf install -q -y kernel-devel-$(uname -r) 591 | if (uname -r | grep -q ^6.12.); then 592 | dnf install -q -y kernel6.12-modules-extra 593 | else 594 | dnf install -q -y kernel-modules-extra 595 | fi 596 | 597 | # AWS CLI: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html 598 | echo "export AWS_CLI_AUTO_PROMPT=on-partial" >> /home/ec2-user/.bashrc 599 | 600 | rm -f ${!0} 601 | mode: "000740" 602 | owner: "root" 603 | group: "root" 604 | commands: 605 | install: 606 | command: "/root/install-sw.sh >> /var/log/install-sw.log 2>&1" 607 | ignoreErrors: "true" 608 | 00_dcv_install: 609 | files: 610 | "/root/install-dcv.sh": 611 | content: !Sub | 612 | #!/bin/bash 613 | mkdir -p /tmp/cfn 614 | cd /tmp/cfn 615 | 616 | # Update OS 617 | dnf update -q -y 618 | 619 | # DCV prereq: https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-installing-linux-prereq.html 620 | dnf groupinstall "Desktop" -y -q 621 | 622 | # Disable the Wayland protocol: https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-installing-linux-prereq.html#linux-prereq-wayland 623 | sed -i '/^\[daemon\]/a WaylandEnable=false' /etc/gdm/custom.conf 624 | 625 | # DCV: https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-installing-linux-server.html 626 | rpm --import https://d1uj6qtbmh3dt5.cloudfront.net/NICE-GPG-KEY 627 | curl -s -L -O https://d1uj6qtbmh3dt5.cloudfront.net/nice-dcv-amzn2023-$(arch).tgz 628 | tar -xvzf nice-dcv-amzn2023-$(arch).tgz && cd nice-dcv-*-amzn2023-$(arch) 629 | dnf install -q -y ./nice-dcv-server-*.rpm 630 | dnf install -q -y ./nice-dcv-web-viewer-*.rpm 631 | dnf install -q -y ./nice-xdcv-*.rpm 632 | 633 | # Printer redirection: https://docs.aws.amazon.com/dcv/latest/adminguide/manage-printer.html 634 | dnf install -q -y cups 635 | GROUP=$(cat /etc/cups/cups-files.conf | grep -oP "SystemGroup\s\K\w+") 636 | usermod -a -G $GROUP dcv 637 | systemctl enable cups 638 | 639 | # glxinfo : https://docs.aws.amazon.com/dcv/latest/adminguide/setting-up-installing-linux-prereq.html#linux-prereq-tools 640 | dnf install -q -y glx-utils 641 | dnf install -q -y vulkan-tools 642 | 643 | # QUIC: https://docs.aws.amazon.com/dcv/latest/adminguide/enable-quic.html 644 | cp /etc/dcv/dcv.conf /etc/dcv/dcv.conf."`date +"%Y-%m-%d"`" 645 | sed -i "s/^#enable-quic-frontend=true/enable-quic-frontend=true/g" /etc/dcv/dcv.conf 646 | 647 | # Higher web client max resolution: https://docs.aws.amazon.com/dcv/latest/adminguide/config-param-ref.html 648 | sed -i "/^\[display/a web-client-max-head-resolution=(4096, 2160)" /etc/dcv/dcv.conf 649 | # Console session support 650 | sed -i "/^\[session-management\/automatic-console-session/a owner=\"ec2-user\"\nstorage-root=\"%home%\"" /etc/dcv/dcv.conf 651 | 652 | # 653 | systemctl daemon-reload 654 | systemctl enable dcv-virtual-session 655 | systemctl enable dcvserver 656 | 657 | # Firefox homepage 658 | cd /usr/lib64/firefox/browser/defaults/preferences/ 659 | sed -i "s/https:\/\/aws.amazon.com\/linux\/amazon-linux-2023/http:\/\/localhost/g" all-amazonlinux.js 660 | sed -i "s/https:\/\/aws.amazon.com/http:\/\/localhost/g" all-amazonlinux.js 661 | 662 | mode: "000740" 663 | owner: "root" 664 | group: "root" 665 | commands: 666 | install: 667 | command: "/root/install-dcv.sh > /var/log/install-dcv.log 2>&1" 668 | ignoreErrors: "true" 669 | Properties: 670 | ImageId: 671 | !If [ 672 | useARM64, 673 | "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.12-arm64}}", 674 | "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.12-x86_64}}", 675 | ] 676 | InstanceType: !Ref instanceType 677 | IamInstanceProfile: !Ref instanceProfile 678 | SubnetId: !Ref subnetID 679 | Monitoring: true 680 | EbsOptimized: true 681 | SecurityGroupIds: 682 | - !Ref securityGroup 683 | BlockDeviceMappings: 684 | - DeviceName: /dev/xvda 685 | Ebs: 686 | VolumeType: !Ref volumeType 687 | VolumeSize: !Ref volumeSize 688 | DeleteOnTermination: true 689 | Encrypted: true 690 | UserData: 691 | Fn::Base64: !Sub | 692 | #!/bin/bash 693 | mkdir -p /tmp/cfn 694 | cd /tmp/cfn 695 | 696 | # disable IPv6 during setup 697 | #sysctl -w net.ipv6.conf.all.disable_ipv6=1 698 | #sysctl -w net.ipv6.conf.default.disable_ipv6=1 699 | 700 | dnf clean all 701 | dnf install -q -y wget tmux unzip tar curl-minimal sed 702 | 703 | export CFN_INIT="/opt/aws/bin/cfn-init" 704 | 705 | $CFN_INIT -v --stack ${AWS::StackName} --resource ec2Instance --region ${AWS::Region} -c setup 706 | 707 | $CFN_INIT -v --stack ${AWS::StackName} --resource ec2Instance --region ${AWS::Region} -c dcv_install 708 | 709 | # Setup Former2 710 | dnf install -q -y httpd git 711 | cd /var/www/ 712 | git clone https://github.com/iann0036/former2 713 | mv html html.bak 714 | mv former2 html 715 | systemctl enable httpd 716 | 717 | # Change permissions and ownership 718 | usermod -a -G apache ec2-user 719 | chown -R ec2-user:apache /var/www/html 720 | chmod -R 2775 /var/www/html 721 | find /var/www/html -type d -exec sudo chmod 2775 {} \; 722 | find /var/www/html -type f -exec sudo chmod 0664 {} \; 723 | 724 | # Update OS 725 | yum update -q -y 726 | 727 | # yum-cron 728 | yum install -q -y yum-cron 729 | sed -i 's/apply_updates = no/apply_updates = yes/g' /etc/yum/yum-cron.conf 730 | systemctl enable yum-cron 731 | 732 | # 733 | systemctl set-default multi-user.target 734 | systemctl daemon-reload 735 | systemctl enable dcv-post-reboot 736 | 737 | # enable back IPv6 738 | #sysctl -w net.ipv6.conf.all.disable_ipv6=0 739 | #sysctl -w net.ipv6.conf.default.disable_ipv6=0 740 | 741 | sleep 1 && reboot 742 | Tags: 743 | - Key: Name 744 | Value: !Ref ec2Name 745 | - Key: StackName 746 | Value: !Ref AWS::StackName 747 | - Key: StackId 748 | Value: !Ref AWS::StackId 749 | - Key: GitHub 750 | Value: https://github.com/aws-samples/ec2-former2 751 | 752 | elasticIP: 753 | Condition: useElasticIP 754 | Type: AWS::EC2::EIP 755 | Properties: 756 | Domain: vpc 757 | NetworkBorderGroup: !Ref AWS::Region 758 | InstanceId: !Ref ec2Instance 759 | Tags: 760 | - Key: StackName 761 | Value: !Ref AWS::StackName 762 | - Key: StackId 763 | Value: !Ref AWS::StackId 764 | - Key: Name 765 | Value: !Sub 766 | - "${AWS::StackName}-elasticIP-${UID}" 767 | - UID: 768 | !Select [ 769 | 3, 770 | !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], 771 | ] 772 | - Key: GitHub 773 | Value: https://github.com/aws-samples/ec2-former2 774 | 775 | Outputs: 776 | EC2console: 777 | Description: EC2 console 778 | Value: !Sub 779 | - "https://${AWS::Region}.${url}/ec2/home?region=${AWS::Region}#Instances:search=${ec2Instance}" 780 | - url: 781 | !FindInMap [ 782 | ConsoleUrl, 783 | !Ref "AWS::Partition", 784 | url, 785 | DefaultValue: "console.aws.amazon.com", 786 | ] 787 | 788 | EC2instanceConnect: 789 | Condition: createSgEIC 790 | Description: EC2 Instance Connect 791 | Value: !Sub 792 | - "https://${AWS::Region}.${url}/ec2-instance-connect/ssh?connType=standard&instanceId=${ec2Instance}&osUser=ec2-user&sshPort=22#/" 793 | - url: 794 | !FindInMap [ 795 | ConsoleUrl, 796 | !Ref "AWS::Partition", 797 | url, 798 | DefaultValue: "console.aws.amazon.com", 799 | ] 800 | 801 | EC2serialConsole: 802 | Description: EC2 Serial Console 803 | Value: !Sub 804 | - "https://${AWS::Region}.${url}/ec2-instance-connect/ssh?connType=serial&instanceId=${ec2Instance}&serialPort=0#/" 805 | - url: 806 | !FindInMap [ 807 | ConsoleUrl, 808 | !Ref "AWS::Partition", 809 | url, 810 | DefaultValue: "console.aws.amazon.com", 811 | ] 812 | 813 | EC2iamRole: 814 | Description: EC2 IAM role 815 | Value: !Sub 816 | - "https://${url}/iam/home#/roles/details/${role}" 817 | - { 818 | role: !Select [1, !Split ["/", !GetAtt instanceIamRole.Arn]], 819 | url: 820 | !FindInMap [ 821 | ConsoleUrl, 822 | !Ref "AWS::Partition", 823 | url, 824 | DefaultValue: "console.aws.amazon.com", 825 | ], 826 | } 827 | 828 | SSMsessionManager: 829 | Description: SSM Session Manager ("sudo passwd ec2-user" to change password) 830 | Value: !Sub 831 | - "https://${AWS::Region}.${url}/systems-manager/session-manager/${ec2Instance}" 832 | - url: 833 | !FindInMap [ 834 | ConsoleUrl, 835 | !Ref "AWS::Partition", 836 | url, 837 | DefaultValue: "console.aws.amazon.com", 838 | ] 839 | 840 | DCVwebConsole: 841 | Description: DCV web browser client (login as ec2-user) 842 | Value: !Sub 843 | - "https://${IpAddress}:8443" 844 | - IpAddress: 845 | !If [ 846 | displayPublicIP, 847 | !GetAtt ec2Instance.PublicIp, 848 | !GetAtt ec2Instance.PrivateIp, 849 | ] 850 | 851 | GetIAMcreds: 852 | Description: Command to retrieve IAM credentials for http://localhost/#section-setup-credentials 853 | Value: !Sub 'TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 30"` && curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/${instanceIamRole}' 854 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT No Attribution 2 | 3 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 14 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 15 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ec2-former2 2 | 3 | [Former2](https://former2.com/) allows you to generate IaC ([Infrastructure as Code](https://docs.aws.amazon.com/whitepapers/latest/introduction-devops-aws/infrastructure-as-code.html)) (such as [CloudFormation](https://docs.aws.amazon.com/whitepapers/latest/introduction-devops-aws/aws-cloudformation.html), [CDK](https://docs.aws.amazon.com/whitepapers/latest/introduction-devops-aws/aws-cdk.html), Terraform, etc) from _existing_ AWS resources and is mentioned on AWS Open Source Blog ([Accelerate infrastructure as code development with open source Former2](https://aws.amazon.com/blogs/opensource/accelerate-infrastructure-as-code-development-with-open-source-former2/) and [How DNAnexus used the open source Former2 project to create infrastructure as code templates for their disaster recovery pipeline](https://aws.amazon.com/blogs/opensource/how-dnanexus-used-the-open-source-former2-project-to-create-infrastructure-as-code-templates-for-their-disaster-recovery-pipeline/)). 4 | 5 | Some users have challenges creating [access keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html) while others express security concerns about entering AWS security credentials on a public website, and would prefer a private web instance. However, Former2 requires [browser helper extension](https://github.com/iann0036/former2-helper) that only works with websites that has domain names 127.0.0.1, localhost, former2.com and www.former2.com. 6 | 7 | This CloudFormation template creates an EC2 instance hosting Former2 in your AWS account. You can connect to the instance with [Amazon DCV](https://aws.amazon.com/hpc/dcv/) remote display protocol to generate and download IaC templates using [temporary security credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html). 8 | 9 | ## About CloudFormation templates 10 | EC2 instances must be provisioned in a subnet with IPv4 internet connectivity. 11 | 12 | 13 | ## Getting started 14 | 15 | ### Provision EC2 with CloudFormation 16 | Download the CloudFormation template([AL2023](AmazonLinux2023-former2.yaml) or [AL2](AmazonLinux2-former2.yaml)). Login to your [CloudFormation console](https://console.aws.amazon.com/cloudformation/home#/stacks/create/template). Choose **Create Stack**, **Upload a template file**, **Choose File**, select your .yaml file and choose **Next**. Enter a **Stack name** and specify parameters values. 17 | 18 | 19 | EC2 20 | - `ec2Name`: EC2 instance name 21 | - `processorArchitecture`: Intel/AMD x86_64 or Graviton arm64. Default is `Graviton (arm64)` 22 | - `instanceType`: EC2 [instance types](https://aws.amazon.com/ec2/instance-types/). Do ensure type matches processor architecture. 23 | 24 | Network 25 | - `vpcID`: [VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) with internet connectivity. Select [default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) if unsure 26 | - `subnetID`: subnet with internet connectivity. Select subnet in default VPC if unsure 27 | - `displayPublicIP`: set this to `No` if your EC2 instance will not receive [public IP address](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-instance-addressing.html#concepts-public-addresses). EC2 private IP will be displayed in CloudFormation Outputs section instead. Default is `Yes` 28 | - `assignStaticIP`: associates a static public IPv4 address using [Elastic IP address](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html). Default is `Yes` 29 | 30 | Remote Access 31 | - `ingressIPv4`: allowed IPv4 source prefix to your EC2 instance, e.g. `1.2.3.4/32`. You can get your source IP from [https://checkip.amazonaws.com](https://checkip.amazonaws.com) 32 | - `ingressIPv6`: allowed IPv6 source prefix to your EC2 instance. Use `::1/128` to block all incoming IPv6 access. Default is `::/0` 33 | 34 | EBS 35 | - `volumeSize`: [Amazon EBS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEBS.html) volume size 36 | - `volumeType`: [EBS General Purpose Volume](https://aws.amazon.com/ebs/general-purpose/) type 37 | 38 | 39 | Continue **Next** with [Configure stack options](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-add-tags.html), [Review Stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-using-console-create-stack-review.html), and click **Submit** to launch your stack. After your stack has been successfully created, its status changes to **CREATE_COMPLETE**. 40 | 41 | ## Using 42 | 43 | Once provisioned, go to CloudFormation stack **Outputs** section and use the **Values** associated with the following **Keys** 44 | 45 | ### Set login password 46 | - `SSMSessionManager`: open URL in a new browser tab for [shell access](https://aws.amazon.com/blogs/aws/new-session-manager/). 47 | 48 | *From session manager terminal, set your ec2-user password with the command `sudo passwd ec2-user`* 49 | 50 | ### Connect 51 | - `DCVwebConsole`: open URL in a new browser tab, and [connect](https://docs.aws.amazon.com/dcv/latest/userguide/using-connecting-browser-connect.html) to your EC2 instance 52 | 53 | *Login as **ec2-user** and your configured password* 54 | 55 | Launch `Firefox` and navigate to Former2 site at `http://localhost`. Install [Former 2 Helper for Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/former2-helper/) 56 | 57 | ![ec2.png](./images/ec2.png) 58 | 59 | 60 | ### Credentials 61 | - In your DCV session, launch `Terminal` and run the command `/home/ec2-user/get-iam-creds`. 62 | 63 | *Use these values to enter IAM credentials (Access Key ID, Secret Access Key, Session Token) at http://localhost/#section-setup-credentials* 64 | 65 | ![ec2.png](./images/credentials.png) 66 | 67 | ### Using Former2 68 | Refer to [Accelerate infrastructure as code development with open source Former2](https://aws.amazon.com/blogs/opensource/accelerate-infrastructure-as-code-development-with-open-source-former2/) blog post for usage guidance. 69 | 70 | ## Attribution 71 | CloudFormation template downloads Former2 web codes from [Ian Mckay](https://github.com/iann0036)'s [GitHub repo](https://github.com/iann0036/former2) which are released under [MIT license](https://github.com/iann0036/former2/blob/master/LICENSE). 72 | 73 | ## Updating web codes 74 | Former2 is under active development. To download latest codes, login to EC2 instance and run `/home/ec2-user/update-former2` script. 75 | 76 | ## About DCV web console 77 | [DCV](https://aws.amazon.com/hpc/dcv/) supports [file transfer](https://docs.aws.amazon.com/dcv/latest/userguide/using-transfer-web.html). 78 | [Native clients](https://docs.aws.amazon.com/dcv/latest/userguide/client-features.html) can be downloaded from [Amazon DCV site](https://download.nice-dcv.com/) 79 | 80 | ![file transfer](https://docs.aws.amazon.com/images/dcv/latest/userguide/images/web-storage.png) 81 | 82 | Usage indicates acceptance of [DCV EULA](https://www.amazondcv.com/eula.html). 83 | 84 | 85 | ## Clean Up 86 | To remove created resources, [delete](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html) your created CloudFormation stack 87 | 88 | 89 | ## Security 90 | 91 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 92 | 93 | ## License 94 | 95 | This library is licensed under the MIT-0 License. See the LICENSE file. 96 | -------------------------------------------------------------------------------- /THIRD_PARTY_LICENSES: -------------------------------------------------------------------------------- 1 | 2 | 3 | ** Former2; version 1.0 -- https://github.com/iann0036/former2 4 | MIT License 5 | 6 | Copyright (c) 2019 Ian Mckay 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | 26 | MIT License 27 | 28 | Copyright (c) 2019 Ian Mckay 29 | 30 | Permission is hereby granted, free of charge, to any person obtaining a copy 31 | of this software and associated documentation files (the "Software"), to deal 32 | in the Software without restriction, including without limitation the rights 33 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | copies of the Software, and to permit persons to whom the Software is 35 | furnished to do so, subject to the following conditions: 36 | 37 | The above copyright notice and this permission notice shall be included in all 38 | copies or substantial portions of the Software. 39 | 40 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 45 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 46 | SOFTWARE. 47 | 48 | -------------------------------------------------------------------------------- /images/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /images/credentials.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/ec2-former2/6b6bae9030a2c15987036e6cf5f06b5ccf9f561f/images/credentials.png -------------------------------------------------------------------------------- /images/ec2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/ec2-former2/6b6bae9030a2c15987036e6cf5f06b5ccf9f561f/images/ec2.png --------------------------------------------------------------------------------