Created
May 17, 2024 14:15
-
-
Save 094459/0dc0eefcffbbc2c843e11e96940c2011 to your computer and use it in GitHub Desktop.
This is a Cloudformation template that will deploy a VSCode server running on an EC2 instance with Python, Node, Java, .NET, Rust installed, as well as Amazon Q Developer. Ready to go.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Description: Create a VSCode code-server instance with an Amazon CloudFront distribution. | |
Parameters: | |
EC2KeyPair: | |
Type: AWS::EC2::KeyPair::KeyName | |
Description: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html | |
Default: ws-default-keypair | |
InstanceVolumeSize: | |
Type: Number | |
Description: The volume size in GB | |
Default: 30 | |
InstanceType: | |
Description: Type of EC2 instance to launch | |
Type: String | |
Default: c7i.xlarge | |
AllowedValues: [ | |
c4.large, c4.xlarge, c4.2xlarge, c4.4xlarge, c4.8xlarge, | |
c5.large, c5.xlarge, c5.2xlarge, c5.4xlarge, c5.9xlarge, c5.12xlarge, c5.18xlarge, c5.24xlarge, | |
c5a.large, c5a.xlarge, c5a.2xlarge, c5a.4xlarge, c5a.8xlarge, c5a.12xlarge, c5a.16xlarge, c5a.24xlarge, | |
c5ad.large, c5ad.xlarge, c5ad.2xlarge, c5ad.4xlarge, c5ad.8xlarge, c5ad.12xlarge, c5ad.16xlarge, c5ad.24xlarge, | |
c5d.large, c5d.xlarge, c5d.2xlarge, c5d.4xlarge, c5d.9xlarge, c5d.12xlarge, c5d.18xlarge, c5d.24xlarge, | |
c5n.large, c5n.xlarge, c5n.2xlarge, c5n.4xlarge, c5n.9xlarge, c5n.18xlarge, | |
c6a.large, c6a.xlarge, c6a.2xlarge, c6a.4xlarge, c6a.8xlarge, c6a.12xlarge, c6a.16xlarge, c6a.24xlarge, c6a.32xlarge, c6a.48xlarge, | |
c6g.medium, c6g.large, c6g.xlarge, c6g.2xlarge, c6g.4xlarge, c6g.8xlarge, c6g.12xlarge, c6g.16xlarge, | |
c6gd.medium, c6gd.large, c6gd.xlarge, c6gd.2xlarge, c6gd.4xlarge, c6gd.8xlarge, c6gd.12xlarge, c6gd.16xlarge, | |
c6gn.medium, c6gn.large, c6gn.xlarge, c6gn.2xlarge, c6gn.4xlarge, c6gn.8xlarge, c6gn.12xlarge, c6gn.16xlarge, | |
c6i.large, c6i.xlarge, c6i.2xlarge, c6i.4xlarge, c6i.8xlarge, c6i.12xlarge, c6i.16xlarge, c6i.24xlarge, c6i.32xlarge, | |
c7g.medium, c7g.large, c7g.xlarge, c7g.2xlarge, c7g.4xlarge, c7g.8xlarge, c7g.12xlarge, c7g.16xlarge, | |
c7gd.medium, c7gd.large, c7gd.xlarge, c7gd.2xlarge, c7gd.4xlarge, c7gd.8xlarge, c7gd.12xlarge, c7gd.16xlarge, | |
c7gn.medium, c7gn.large, c7gn.xlarge, c7gn.2xlarge, c7gn.4xlarge, c7gn.8xlarge, c7gn.12xlarge, c7gn.16xlarge, | |
c7i.large, c7i.xlarge, c7i.2xlarge, c7i.4xlarge, c7i.8xlarge, c7i.12xlarge, c7i.16xlarge, c7i.24xlarge, c7i.48xlarge, | |
m4.large, m4.xlarge, m4.2xlarge, m4.4xlarge, m4.10xlarge, m4.16xlarge, | |
m5.large, m5.xlarge, m5.2xlarge, m5.4xlarge, m5.8xlarge, m5.12xlarge, m5.16xlarge, m5.24xlarge, | |
m5a.large, m5a.xlarge, m5a.2xlarge, m5a.4xlarge, m5a.8xlarge, m5a.12xlarge, m5a.16xlarge, m5a.24xlarge, | |
m6a.large, m6a.xlarge, m6a.2xlarge, m6a.4xlarge, m6a.8xlarge, m6a.12xlarge, m6a.16xlarge, m6a.24xlarge, m6a.32xlarge, m6a.48xlarge, | |
m7a.medium, m7a.large, m7a.xlarge, m7a.2xlarge, m7a.4xlarge, m7a.8xlarge, m7a.12xlarge, m7a.16xlarge, m7a.24xlarge, m7a.32xlarge, m7a.48xlarge, | |
t2.nano, t2.micro, t2.small, t2.medium, t2.large, t2.xlarge, t2.2xlarge, | |
t3.nano, t3.micro, t3.small, t3.medium, t3.large, t3.xlarge, t3.2xlarge, | |
t3a.nano, t3a.micro, t3a.small, t3a.medium, t3a.large, t3a.xlarge, t3a.2xlarge, | |
t4g.nano, t4g.micro, t4g.small, t4g.medium, t4g.large, t4g.xlarge, t4g.2xlarge | |
] | |
HomeFolder: | |
Type: String | |
Description: The home folder in the VSCodeInstance | |
Default: /Workshop | |
DevServerBasePath: | |
Type: String | |
Description: The base path for the application to be added to nginx sites-available list for code-server | |
Default: app | |
DevServerPort: | |
Type: Number | |
Description: The port for the DevServer | |
Default: 8081 | |
Metadata: | |
AWS::CloudFormation::Interface: | |
ParameterGroups: | |
- Label: | |
default: Instance Configuration | |
Parameters: | |
- InstanceVolumeSize | |
- EC2KeyPair | |
- Label: | |
default: Code Server Configuration | |
Parameters: | |
- HomeFolder | |
- DevServerBasePath | |
- DevServerPort | |
ParameterLabels: | |
InstanceVolumeSize: | |
default: Attached volume size | |
EC2KeyPair: | |
default: EC2 key pair name | |
HomeFolder: | |
default: Folder to open in code server when launching | |
DevServerBasePath: | |
default: BasePath where the application runs | |
DevServerPort: | |
default: Port where the application runs | |
Mappings: | |
Subnets: | |
VPC: | |
CIDR: 10.0.0.0/16 | |
PublicOne: | |
CIDR: 10.0.1.0/24 | |
PublicTwo: | |
CIDR: 10.0.2.0/24 | |
PrivateOne: | |
CIDR: 10.0.3.0/24 | |
PrivateTwo: | |
CIDR: 10.0.4.0/24 | |
# aws ec2 describe-managed-prefix-lists --region <REGION> | jq -r '.PrefixLists[] | select (.PrefixListName == "com.amazonaws.global.cloudfront.origin-facing") | .PrefixListId' | |
AWSRegions2PrefixListID: | |
ap-northeast-1: | |
PrefixList: pl-58a04531 | |
ap-northeast-2: | |
PrefixList: pl-22a6434b | |
ap-south-1: | |
PrefixList: pl-9aa247f3 | |
ap-southeast-1: | |
PrefixList: pl-31a34658 | |
ap-southeast-2: | |
PrefixList: pl-b8a742d1 | |
ca-central-1: | |
PrefixList: pl-38a64351 | |
eu-central-1: | |
PrefixList: pl-a3a144ca | |
eu-north-1: | |
PrefixList: pl-fab65393 | |
eu-west-1: | |
PrefixList: pl-4fa04526 | |
eu-west-2: | |
PrefixList: pl-93a247fa | |
eu-west-3: | |
PrefixList: pl-75b1541c | |
sa-east-1: | |
PrefixList: pl-5da64334 | |
us-east-1: | |
PrefixList: pl-3b927c52 | |
us-east-2: | |
PrefixList: pl-b6a144df | |
us-west-1: | |
PrefixList: pl-4ea04527 | |
us-west-2: | |
PrefixList: pl-82a045eb | |
Resources: | |
########### VPC Resources ########### | |
VPC: | |
Type: AWS::EC2::VPC | |
Properties: | |
CidrBlock: !FindInMap [Subnets, VPC, CIDR] | |
EnableDnsSupport: true | |
EnableDnsHostnames: true | |
InternetGateway: | |
Type: AWS::EC2::InternetGateway | |
GatewayAttachment: | |
Type: AWS::EC2::VPCGatewayAttachment | |
Properties: | |
VpcId: !Ref VPC | |
InternetGatewayId: !Ref InternetGateway | |
PublicSubnetOne: | |
Type: AWS::EC2::Subnet | |
Properties: | |
CidrBlock: !FindInMap [Subnets, PublicOne, CIDR] | |
VpcId: !Ref VPC | |
MapPublicIpOnLaunch: true | |
AvailabilityZone: !Select [0, !GetAZs ''] | |
PublicOneRouteTable: | |
Type: AWS::EC2::RouteTable | |
Properties: | |
VpcId: !Ref VPC | |
PublicOneRoute: | |
Type: AWS::EC2::Route | |
DependsOn: GatewayAttachment | |
Properties: | |
RouteTableId: !Ref PublicOneRouteTable | |
DestinationCidrBlock: 0.0.0.0/0 | |
GatewayId: !Ref InternetGateway | |
PublicOneRouteTableAssoc: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
Properties: | |
RouteTableId: !Ref PublicOneRouteTable | |
SubnetId: !Ref PublicSubnetOne | |
PublicSubnetTwo: | |
Type: AWS::EC2::Subnet | |
Properties: | |
CidrBlock: !FindInMap [Subnets, PublicTwo, CIDR] | |
VpcId: !Ref VPC | |
MapPublicIpOnLaunch: true | |
AvailabilityZone: !Select [1, !GetAZs ''] | |
PublicTwoRouteTable: | |
Type: AWS::EC2::RouteTable | |
Properties: | |
VpcId: !Ref VPC | |
PublicTwoRoute: | |
Type: AWS::EC2::Route | |
DependsOn: GatewayAttachment | |
Properties: | |
RouteTableId: !Ref PublicTwoRouteTable | |
DestinationCidrBlock: 0.0.0.0/0 | |
GatewayId: !Ref InternetGateway | |
PublicTwoRouteTableAssoc: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
Properties: | |
RouteTableId: !Ref PublicTwoRouteTable | |
SubnetId: !Ref PublicSubnetTwo | |
PrivateSubnetOne: | |
Type: AWS::EC2::Subnet | |
Properties: | |
CidrBlock: !FindInMap [Subnets, PrivateOne, CIDR] | |
VpcId: !Ref VPC | |
MapPublicIpOnLaunch: true | |
AvailabilityZone: !Select [0, !GetAZs ''] | |
PrivateSubnetTwo: | |
Type: AWS::EC2::Subnet | |
Properties: | |
CidrBlock: !FindInMap [Subnets, PrivateTwo, CIDR] | |
VpcId: !Ref VPC | |
MapPublicIpOnLaunch: true | |
AvailabilityZone: !Select [1, !GetAZs ''] | |
SecurityGroup: | |
Type: AWS::EC2::SecurityGroup | |
Properties: | |
GroupDescription: SG for Developer Machine - only allow CloudFront ingress | |
SecurityGroupIngress: | |
- Description: Allow HTTP from com.amazonaws.global.cloudfront.origin-facing | |
IpProtocol: tcp | |
FromPort: 80 | |
ToPort: 80 | |
SourcePrefixListId: !FindInMap [AWSRegions2PrefixListID, !Ref 'AWS::Region', PrefixList] | |
SecurityGroupEgress: | |
- Description: Allow all outbound traffic | |
IpProtocol: -1 | |
CidrIp: 0.0.0.0/0 | |
VpcId: !Ref VPC | |
########### SSM Resources ########### | |
SSMLogBucket: | |
Type: AWS::S3::Bucket | |
Metadata: | |
cfn_nag: | |
rules_to_suppress: | |
- id: W35 | |
reason: Access logs aren't needed for this bucket | |
DeletionPolicy: Delete | |
Properties: | |
AccessControl: Private | |
BucketEncryption: | |
ServerSideEncryptionConfiguration: | |
- ServerSideEncryptionByDefault: | |
SSEAlgorithm: AES256 | |
PublicAccessBlockConfiguration: | |
BlockPublicAcls: true | |
BlockPublicPolicy: true | |
IgnorePublicAcls: true | |
RestrictPublicBuckets: true | |
VSCodeInstanceSSMDoc: | |
Type: AWS::SSM::Document | |
Properties: | |
DocumentType: Command | |
Content: | |
schemaVersion: '2.2' | |
description: Bootstrap VSCode code-server instance | |
parameters: | |
architecture: | |
type: String | |
default: amd64 | |
description: Instance architecture type | |
allowedValues: | |
- arm64 | |
- amd64 | |
ubuntuVersion: | |
type: String | |
default: jammy | |
allowedValues: | |
- focal | |
- bionic | |
- jammy | |
nodeVersion: | |
type: String | |
default: node_20.x | |
allowedValues: | |
- node_21.x | |
- node_20.x | |
- node_19.x | |
dotNetVersion: | |
type: String | |
default: dotnet-sdk-8.0 | |
allowedValues: | |
- dotnet-sdk-8.0 | |
- dotnet-sdk-7.0 | |
- dotnet-sdk-8.0 | |
mainSteps: | |
- action: aws:runShellScript | |
name: InstallAWSCLI | |
inputs: | |
runCommand: | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y curl unzip | |
- curl -fsSL https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip -o /tmp/aws-cli.zip | |
- unzip -q -d /tmp /tmp/aws-cli.zip | |
- sudo /tmp/aws/install | |
- rm -rf /tmp/aws | |
- aws --version | |
- action: aws:runShellScript | |
name: InstallGit | |
inputs: | |
runCommand: | |
- add-apt-repository ppa:git-core/ppa | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y software-properties-common | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y git | |
- sudo -u ubuntu git config --global user.email "participant@workshops.aws" | |
- sudo -u ubuntu git config --global user.name "Workshop Participant" | |
- sudo -u ubuntu git config --global init.defaultBranch "main" | |
- git --version | |
- action: aws:runShellScript | |
name: InstallNode | |
inputs: | |
runCommand: | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y curl | |
- curl -fsSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | gpg --dearmor -o /usr/share/keyrings/nodesource-keyring.gpg | |
- echo "deb [arch={{ architecture }} signed-by=/usr/share/keyrings/nodesource-keyring.gpg] https://deb.nodesource.com/{{ nodeVersion }} {{ ubuntuVersion }} main" >> /etc/apt/sources.list.d/nodesource.list | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs | |
- action: aws:runShellScript | |
name: InstallPython | |
inputs: | |
runCommand: | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y python3-pip python3.10-venv python3-boto3 python3-pytest | |
- echo 'alias pytest=pytest-3' >> /home/ubuntu/.bashrc | |
- ln -s /usr/bin/python3 /usr/bin/python | |
- python3 --version | |
- pip3 --version | |
- action: aws:runShellScript | |
name: InstallPythonRequirements | |
inputs: | |
runCommand: | |
- '#!/bin/bash' | |
- !Sub mkdir -p ${HomeFolder} # should already exist! | |
- !Sub sudo chown ubuntu:ubuntu ${HomeFolder} -R | |
- !Sub | # move to the directory of the repository if it's there | |
cd ${HomeFolder} | |
- python3 -m venv .venv # create a virtual environment | |
- source .venv/bin/activate | |
- | | |
- deactivate | |
- sudo chown ubuntu:ubuntu .venv -R | |
- action: aws:runShellScript | |
name: UpdateProfile | |
inputs: | |
runCommand: | |
- '#!/bin/bash' | |
- echo LANG=en_US.utf-8 >> /etc/environment | |
- echo LC_ALL=en_US.UTF-8 >> /etc/environment | |
- echo 'PATH=$PATH:/home/ubuntu/.local/bin' >> /home/ubuntu/.bashrc | |
- echo 'export PATH' >> /home/ubuntu/.bashrc | |
- !Sub echo 'export AWS_REGION=${AWS::Region}' >> /home/ubuntu/.bashrc | |
- !Sub echo 'export AWS_ACCOUNTID=${AWS::AccountId}' >> /home/ubuntu/.bashrc | |
- echo 'export NEXT_TELEMETRY_DISABLED=1' >> /home/ubuntu/.bashrc | |
- action: aws:runShellScript | |
name: ConfigureCodeServer | |
inputs: | |
runCommand: | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y curl nginx | |
- '#!/bin/bash' | |
- export HOME=/home/ubuntu | |
- curl -fsSL https://code-server.dev/install.sh | sh | |
- sudo systemctl enable --now code-server@ubuntu | |
- !Sub | | |
sudo tee /etc/nginx/sites-available/code-server <<EOF | |
server { | |
listen 80; | |
listen [::]:80; | |
server_name ${CloudFrontDistribution.DomainName}; | |
location / { | |
proxy_pass http://localhost:8080/; | |
proxy_set_header Host \$host; | |
proxy_set_header Upgrade \$http_upgrade; | |
proxy_set_header Connection upgrade; | |
proxy_set_header Accept-Encoding gzip; | |
} | |
location /${DevServerBasePath} { | |
proxy_pass http://localhost:${DevServerPort}/${DevServerBasePath}; | |
proxy_set_header Host \$host; | |
proxy_set_header Upgrade \$http_upgrade; | |
proxy_set_header Connection upgrade; | |
proxy_set_header Accept-Encoding gzip; | |
} | |
} | |
EOF | |
- | | |
sudo tee /home/ubuntu/.config/code-server/config.yaml <<EOF | |
cert: false | |
auth: password | |
hashed-password: "$(echo -n $(aws sts get-caller-identity --query "Account" --output text) | sudo npx argon2-cli -e)" | |
EOF | |
- sudo -u ubuntu --login mkdir -p /home/ubuntu/.local/share/code-server/User/ | |
- sudo -u ubuntu --login touch /home/ubuntu/.local/share/code-server/User/settings.json | |
- !Sub | | |
sudo tee /home/ubuntu/.local/share/code-server/User/settings.json <<EOF | |
{ | |
"extensions.autoUpdate": false, | |
"extensions.autoCheckUpdates": false, | |
"terminal.integrated.cwd": "${HomeFolder}", | |
"telemetry.telemetryLevel": "off", | |
"security.workspace.trust.startupPrompt": "never", | |
"security.workspace.trust.enabled": false, | |
"security.workspace.trust.banner": "never", | |
"security.workspace.trust.emptyWindow": false, | |
"editor.indentSize": "tabSize", | |
"editor.tabSize": 2, | |
"python.testing.pytestEnabled": true, | |
"auto-run-command.rules": [ | |
{ | |
"command": "workbench.action.terminal.new" | |
} | |
] | |
} | |
EOF | |
- sudo systemctl restart code-server@ubuntu | |
- sudo ln -s ../sites-available/code-server /etc/nginx/sites-enabled/code-server | |
- sudo systemctl restart nginx | |
- sudo -u ubuntu --login code-server --install-extension AmazonWebServices.aws-toolkit-vscode --force | |
# - sudo -u ubuntu --login code-server --install-extension AmazonWebServices.aws-toolkit-vscode --force | |
# - sudo -u ubuntu --login code-server --install-extension AmazonWebServices.amazon-q-vscode --force | |
- sudo -u ubuntu --login code-server --install-extension synedra.auto-run-command --force | |
- sudo chown ubuntu:ubuntu /home/ubuntu -R | |
- action: aws:runShellScript | |
name: InstallQDeveloperExtension | |
inputs: | |
runCommand: | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y curl jq | |
- | | |
Q_URL=$(curl -sL https://api.github.com/repos/aws/aws-toolkit-vscode/releases/latest | jq -r '.assets[] | select(.name? | match("amazon-q-vscode-[0-9].[0-9].[0-9]*.vsix$";"g")) | .browser_download_url') | |
if [ -z "$Q_URL" ]; | |
then | |
echo 'No Q url found, using default' | |
Q_URL=https://github.com/aws/aws-toolkit-vscode/releases/download/amazonq/v1.3.0/amazon-q-vscode-1.3.0.vsix | |
fi | |
echo 'Hardcoding add-in version' | |
Q_URL=https://github.com/aws/aws-toolkit-vscode/releases/download/amazonq/v1.3.0/amazon-q-vscode-1.3.0.vsix | |
echo $Q_URL | |
curl -fsSL $Q_URL -o /tmp/AmazonWebServices.amazon-q-vscode.vsix | |
sudo -u ubuntu --login code-server --install-extension /tmp/AmazonWebServices.amazon-q-vscode.vsix --force | |
- action: aws:runShellScript | |
name: InstallAWSToolkit | |
inputs: | |
runCommand: | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y curl jq | |
- | | |
TOOLKIT_URL=$(curl -sL https://api.github.com/repos/aws/aws-toolkit-vscode/releases/latest | jq -r '.assets[] | select(.name? | match("aws-toolkit-vscode-[0-9].[0-9].[0-9]*.vsix$";"g")) | .browser_download_url') | |
if [ -z "$TOOLKIT_URL" ]; | |
then | |
echo 'No toolkit url found, using default' | |
TOOLKIT_URL=https://github.com/aws/aws-toolkit-vscode/releases/download/toolkit/v3.2.0/aws-toolkit-vscode-3.2.0.vsix | |
fi | |
echo $TOOLKIT_URL | |
curl -fsSL $TOOLKIT_URL -o /tmp/AmazonWebServices.amazon-toolkit-vscode.vsix | |
sudo -u ubuntu --login code-server --install-extension /tmp/AmazonWebServices.amazon-toolkit-vscode.vsix --force | |
- action: aws:runShellScript | |
name: InstallCDK | |
inputs: | |
runCommand: | |
- npm install -g aws-cdk | |
- cdk --version | |
- action: aws:runShellScript | |
name: InstallGo | |
inputs: | |
runCommand: | |
- add-apt-repository ppa:longsleep/golang-backports | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y golang-go | |
- sudo chown ubuntu:ubuntu /home/ubuntu -R | |
- go version | |
- action: aws:runShellScript | |
name: InstallRust | |
inputs: | |
runCommand: | |
- add-apt-repository ppa:ubuntu-mozilla-security/rust-next | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y rustc cargo | |
- sudo chown ubuntu:ubuntu /home/ubuntu -R | |
- rustc --version | |
- action: aws:runShellScript | |
name: InstallDocker | |
inputs: | |
runCommand: | |
- apt-get update && apt-get install -y apt-transport-https ca-certificates curl software-properties-common curl gnupg lsb-release | |
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - | |
- add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu jammy stable" | |
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y docker-ce libpq-dev | |
- mkdir -p ~/.docker/cli-plugins/ | |
- curl -SL https://github.com/docker/compose/releases/download/v2.3.3/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose | |
- chmod +x ~/.docker/cli-plugins/docker-compose | |
- docker compose version | |
- usermod -aG docker ubuntu | |
- action: aws:runShellScript | |
name: InstallAmazonCorretto | |
inputs: | |
runCommand: | |
- wget -O - https://apt.corretto.aws/corretto.key | sudo gpg --dearmor -o /usr/share/keyrings/corretto-keyring.gpg | |
- echo "deb [signed-by=/usr/share/keyrings/corretto-keyring.gpg] https://apt.corretto.aws stable main" | tee /etc/apt/sources.list.d/corretto.list | |
- apt-get update && sudo apt-get install -y java-17-amazon-corretto-jdk maven | |
- echo 'export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))' >> /home/ubuntu/.bashrc | |
- echo 'export PATH=$PATH:/usr/share/maven/bin' >> /home/ubuntu/.bashrc | |
- action: aws:runShellScript | |
name: InstallDotnet | |
inputs: | |
runCommand: | |
- apt-get update && DEBIAN_FRONTEND=noninteractive sudo apt-get install -y {{ dotNetVersion }} | |
- dotnet tool install -g Microsoft.Web.LibraryManager.Cli | |
- export PATH="$PATH:/home/ubuntu/.dotnet/tools" | |
- chown ubuntu:ubuntu /home/ubuntu -R | |
- dotnet --list-sdks | |
- action: aws:runShellScript | |
name: InstallVite | |
inputs: | |
runCommand: | |
- apt-get update && DEBIAN_FRONTEND=noninteractive sudo apt-get install -y vite create-vite | |
VSCodeInstanceSSMAssociation: | |
Type: AWS::SSM::Association | |
Properties: | |
Name: !Ref VSCodeInstanceSSMDoc | |
OutputLocation: | |
S3Location: | |
OutputS3BucketName: !Ref SSMLogBucket | |
OutputS3KeyPrefix: bootstrap | |
Targets: | |
- Key: tag:SSMBootstrap | |
Values: [True] | |
### Empty S3 bucket resources ### | |
EmptyS3BucketExecutionRole: | |
Type: AWS::IAM::Role | |
Properties: | |
AssumeRolePolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: lambda.amazonaws.com | |
Action: sts:AssumeRole | |
ManagedPolicyArns: | |
- !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole | |
Policies: | |
- PolicyName: !Sub EmptyS3BucketPolicy-${AWS::Region} | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Action: | |
- s3:ListBucket | |
- s3:DeleteObject | |
Resource: '*' | |
EmptyS3Bucket: | |
Type: AWS::Lambda::Function | |
Metadata: | |
cfn_nag: | |
rules_to_suppress: | |
- id: W58 | |
reason: EmptyS3BucketExecutionRole has the AWSLambdaBasicExecutionRole managed policy attached, allowing writing to CloudWatch logs | |
- id: W89 | |
reason: Bootstrap function does not need the scaffolding of a VPC or provisioned concurrency | |
- id: W92 | |
reason: Bootstrap function does not need provisioned concurrency | |
Properties: | |
Description: Empty S3 bucket CloudFormation custom resource | |
Handler: index.lambda_handler | |
Role: | |
Fn::GetAtt: | |
- EmptyS3BucketExecutionRole | |
- Arn | |
Runtime: python3.11 | |
MemorySize: 1024 | |
Timeout: 400 | |
Code: | |
ZipFile: | | |
import boto3 | |
import cfnresponse | |
import logging | |
logger = logging.getLogger(__name__) | |
logger.setLevel(logging.INFO) | |
def lambda_handler(event, context): | |
logger.info('event: {}'.format(event)) | |
logger.info('context: {}'.format(context)) | |
if event['RequestType'] == 'Delete': | |
try: | |
AssetsBucketName = (event['ResourceProperties']['S3Bucket']) | |
s3 = boto3.resource('s3') | |
logger.info('S3 Object initialized') | |
bucket = s3.Bucket(AssetsBucketName) | |
logger.info('S3 bucket: ' + AssetsBucketName) | |
bucket.objects.all().delete() | |
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}, reason='S3 bucket emptied: ' + AssetsBucketName ) | |
except Exception as e: | |
logger.error(e, exc_info=True) | |
cfnresponse.send(event, context, cfnresponse.FAILED, responseData={}, reason=str(e)) | |
else: | |
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}, reason='No action to take') | |
EmptyS3BucketLogGroup: | |
Metadata: | |
cfn_nag: | |
rules_to_suppress: | |
- id: W84 | |
reason: KMS Key not required for encrypting this non sensitive data | |
Type: AWS::Logs::LogGroup | |
DeletionPolicy: Delete | |
UpdateReplacePolicy: Delete | |
Properties: | |
LogGroupName: !Sub /aws/lambda/${EmptyS3Bucket} | |
RetentionInDays: 7 | |
EmptyS3BucketCustomResource: | |
Type: Custom::EmptyS3Bucket | |
Properties: | |
ServiceToken: !GetAtt EmptyS3Bucket.Arn | |
S3Bucket: !Ref SSMLogBucket | |
########### EC2 Resources ########### | |
VSCodeInstanceRole: | |
Metadata: | |
cfn_nag: | |
rules_to_suppress: | |
- id: W11 | |
reason: CodeWhisperer requires '*' as a resource, reference https://docs.aws.amazon.com/codewhisperer/latest/userguide/cloud9-setup.html#codewhisperer-IAM-policies | |
Type: AWS::IAM::Role | |
Properties: | |
AssumeRolePolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: | |
- ec2.amazonaws.com | |
- ssm.amazonaws.com | |
- codecommit.amazonaws.com | |
Action: | |
- 'sts:AssumeRole' | |
ManagedPolicyArns: | |
- !Sub arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess | |
Policies: | |
- PolicyName: !Sub CDKAssumeRolePolicy-${AWS::Region} | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Action: | |
- sts:AssumeRole | |
Resource: | |
- !Sub arn:${AWS::Partition}:iam::*:role/cdk-* | |
- PolicyName: !Sub Codewhisperer-${AWS::Region} | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Action: | |
- codewhisperer:GenerateRecommendations | |
Resource: '*' | |
VSCodeInstanceProfile: | |
Type: AWS::IAM::InstanceProfile | |
Properties: | |
Roles: | |
- !Ref VSCodeInstanceRole | |
VSCodeInstanceEC2Instance: | |
Type: AWS::EC2::Instance | |
Properties: | |
KeyName: !Ref EC2KeyPair | |
BlockDeviceMappings: | |
- Ebs: | |
VolumeSize: !Ref InstanceVolumeSize | |
VolumeType: gp3 | |
DeleteOnTermination: true | |
Encrypted: true | |
DeviceName: /dev/sda1 | |
Monitoring: true | |
SubnetId: !Ref PublicSubnetOne | |
ImageId: >- | |
{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}} | |
InstanceType: !Ref InstanceType | |
SecurityGroupIds: | |
- !Ref SecurityGroup | |
IamInstanceProfile: !Ref VSCodeInstanceProfile | |
UserData: | |
Fn::Base64: !Sub | | |
#cloud-config | |
hostname: dev | |
runcmd: | |
- mkdir -p ${HomeFolder} && chown ubuntu:ubuntu ${HomeFolder} | |
Tags: | |
- Key: SSMBootstrap | |
Value: True | |
########### CloudFront Resources ########### | |
VSCodeInstanceCachePolicy: | |
Type: AWS::CloudFront::CachePolicy | |
Properties: | |
CachePolicyConfig: | |
DefaultTTL: 86400 | |
MaxTTL: 31536000 | |
MinTTL: 1 | |
Name: !Join ['-', ['VSCodeServer', !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]]] | |
ParametersInCacheKeyAndForwardedToOrigin: | |
CookiesConfig: | |
CookieBehavior: all | |
EnableAcceptEncodingGzip: False | |
HeadersConfig: | |
HeaderBehavior: whitelist | |
Headers: | |
- Accept-Charset | |
- Authorization | |
- Origin | |
- Accept | |
- Referer | |
- Host | |
- Accept-Language | |
- Accept-Encoding | |
- Accept-Datetime | |
QueryStringsConfig: | |
QueryStringBehavior: all | |
CloudFrontDistribution: | |
Type: AWS::CloudFront::Distribution | |
Properties: | |
DistributionConfig: | |
Enabled: True | |
HttpVersion: http2 | |
DefaultCacheBehavior: | |
AllowedMethods: | |
- GET | |
- HEAD | |
- OPTIONS | |
- PUT | |
- PATCH | |
- POST | |
- DELETE | |
CachePolicyId: !Ref VSCodeInstanceCachePolicy | |
OriginRequestPolicyId: 216adef6-5c7f-47e4-b989-5492eafa07d3 # Managed-AllViewer - see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html#:~:text=When%20using%20AWS,47e4%2Db989%2D5492eafa07d3 | |
TargetOriginId: !Sub CloudFront-${AWS::StackName} | |
ViewerProtocolPolicy: allow-all | |
Origins: | |
- DomainName: !GetAtt VSCodeInstanceEC2Instance.PublicDnsName | |
Id: !Sub CloudFront-${AWS::StackName} | |
CustomOriginConfig: | |
OriginProtocolPolicy: http-only | |
Outputs: | |
Password: | |
Description: VSCode-Server Password | |
Value: !Ref AWS::AccountId | |
Export: | |
Name: !Sub ${AWS::StackName}-Password | |
URL: | |
Description: VSCode-Server URL | |
Value: !Sub https://${CloudFrontDistribution.DomainName}/?folder=${HomeFolder} | |
Export: | |
Name: !Sub ${AWS::StackName}-URL |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment