Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 49 additions & 36 deletions cft-templates/Rstudio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,19 @@ Parameters:
Description: >-
An S3 URI (starting with "s3://") that specifies the location of files to be copied to
the environment instance, including any bootstrap scripts
EBSVolumeSize:
Description: The initial size of the volume (in GBs) EBS will use for storage.
Type: Number
Default: 8
InstanceType:
Type: String
Description: Choose the instance type e.g t3.medium (2vCPU , 2GiB RAM), t3.large (2vCPU, 8GiB RAM), t3.xlarge(4vCPU, 16GiB RAM)
AllowedValues:
- t3.medium
- t3.large
- t3.xlarge
Description: Instance type for RStudio.
ConstraintDescription: Valid instance type in the t3 families
Default: t3.medium
EBSVolumeSize:
Description: The initial size of the volume (in GBs) EBS will use for storage.
Type: Number
Default: 32
InitialUser:
Type: String
Description: User Name for RStudio. Do not use 'root' and 'ec2-user'
Default: rstudio
KeyPair:
Type: "AWS::EC2::KeyPair::KeyName"
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance. If no key pairs exist, please create one from the button next to the dropdown. Please contact your Administrator if you are unable to create one.
AvailabilityZone:
Description: Select the availability zone in which to create the instance. If you plan to attach a secondary volume to the instance, create this instance in the same AvailabilityZone as the volume you created.
Type: AWS::EC2::AvailabilityZone::Name


Conditions:
IamPolicyEmpty: !Equals [!Ref IamPolicyDocument, '{}']

Expand All @@ -61,12 +50,31 @@ Resources:
- 'sts:AssumeRole'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
- arn:aws:iam::aws:policy/AmazonS3FilesClientFullAccess
Policies:
- !If
- IamPolicyEmpty
- !Ref 'AWS::NoValue'
- PolicyName: !Join ['-', [Ref: Namespace, 's3-studydata-policy']]
PolicyDocument: !Ref IamPolicyDocument
- PolicyName: !Join ['-', [Ref: Namespace, 'Product-policy']]
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- 's3:*'
- 'sts:*'
- 'kms:*'
- 'ssm:*'
- 'cloudwatch:*'
- 'ec2:*'
- 'logs:*'
- 'xray:*'
- 'ssmmessages:*'
- 'ec2messages:*'
- 's3files:*'
Resource: "*"
- PolicyName: param-store-access
PolicyDocument:
Version: '2012-10-17'
Expand All @@ -75,7 +83,11 @@ Resources:
Action:
- 'ssm:GetParameter'
- 'ssm:PutParameter'
Resource: !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/*'
Resource: !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/*'
- Effect: 'Allow'
Action:
- 'kms:Decrypt'
Resource: '*'

InstanceProfile:
Type: 'AWS::IAM::InstanceProfile'
Expand Down Expand Up @@ -103,7 +115,7 @@ Resources:
Type: AWS::EC2::Instance
CreationPolicy:
ResourceSignal:
Timeout: PT10M
Timeout: PT15M
Metadata:
AWS::CloudFormation::Init:
configSets:
Expand All @@ -125,16 +137,13 @@ Resources:
group: 'root'
content: !Sub |
#!/usr/bin/env bash
# Get the session token
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# Get the region to build the parameter name
instance_region=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/region)
echo "Retrieved region ${instance_region} from metadata service"

# Get the instance id to build the parameter name
instance_id=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id)
set -euo pipefail
# Get IMDSv2 token
TOKEN=$(curl -s --fail \
-X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

instance_id=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" "http://169.254.169.254/latest/meta-data/instance-id")
secret=`uuidgen`
echo "setting ${InitialUser} password and starting rstudio"
password=$(echo -n "$instance_id$secret" | sha256sum | awk '{print $1}')
Expand All @@ -143,8 +152,9 @@ Resources:

sleep 10
public_key=$(curl http://localhost:8787/auth-public-key)

aws ssm put-parameter --name "/RL/RG/rstudio/public-key/$instance_id" --value '{"secret":"'$secret'","public_key":"'$public_key'"}' --region $instance_region --type SecureString --overwrite
# instance_region=$(curl -s "http://169.254.169.254/latest/meta-data/placement/region
instance_region=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/region)
aws ssm put-parameter --name "/RL/RG/rstudio/public-key/$instance_id" --value '{"secret":"'$secret'","public_key":"'$public_key'"}' --region $instance_region --type SecureString --overwrite
echo "Stored rstudio public key in SSM"
'/var/log/rstudio.log':
content: "\n"
Expand All @@ -164,9 +174,7 @@ Resources:
Properties:
ImageId : '{{resolve:ssm:/RL/RG/StandardCatalog/RStudio}}'
InstanceType: !Ref 'InstanceType'
AvailabilityZone: !Ref AvailabilityZone
SecurityGroups: [!Ref 'RstudioEC2SecurityGroup']
KeyName: !Ref 'KeyPair'
IamInstanceProfile: !Ref InstanceProfile
PropagateTagsToVolumeOnCreation: true
BlockDeviceMappings:
Expand All @@ -185,9 +193,14 @@ Resources:
Fn::Base64: !Sub |
#!/bin/bash
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
trap '/opt/aws/bin/cfn-signal --exit-code 1 --resource RstudioEC2Instance --region ${AWS::Region} --stack ${AWS::StackName}' ERR
sudo yum update -y --security

#trap '/opt/aws/bin/cfn-signal --exit-code 1 --resource RstudioEC2Instance --region ${AWS::Region} --stack ${AWS::StackName}' ERR
sudo dnf update -y --security
sudo dnf install -y amazon-efs-utils aws-cfn-bootstrap cronie
systemctl enable crond.service
systemctl start crond.service
sudo systemctl status amazon-ssm-agent
ls -l /opt/aws/bin/cfn-signal

#add user(s)
sudo useradd -m -s /bin/bash ${InitialUser}
#Add user to the sudo group
Expand Down Expand Up @@ -221,4 +234,4 @@ Outputs:
Value: '443'
AvailabilityZone:
Description: AvailabilityZone of newly created Rstudio EC2Instance
Value: !Ref AvailabilityZone
Value: !GetAtt [RstudioEC2Instance, AvailabilityZone]
58 changes: 42 additions & 16 deletions cft-templates/ec2-EIP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ Parameters:
An S3 URI (starting with "s3://") that specifies the location of files to be copied to
the environment instance, including any bootstrap scripts
InstanceType:
Description: Choose the instance type e.g t3.small (2vCPU , 2GiB RAM) t3.medium (2vCPU , 4GiB RAM), t3.large (2vCPU, 8GiB RAM).
Description: Choose the instance type # e.g t3.medium (2vCPU , 4GiB RAM), t3.large (2vCPU, 8GiB RAM), t3.xlarge (4vCPU, 16GiB RAM).
Type: String
Default: t3.small
AllowedValues: [t3.small, t3.medium, t3.large]
# Default: t3.medium
# AllowedValues: [t3.medium, t3.large,t3.xlarge]
ConstraintDescription: must be a valid EC2 instance type.
EBSVolumeSize:
Description: The initial size of the volume (in GBs) EBS will use for storage.
Expand All @@ -34,24 +34,48 @@ Parameters:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance. If no key pairs exist, please create one from the button next to the dropdown. Please contact your Administrator if you are unable to create one.
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: must be the name of an existing EC2 KeyPair.
AllowedSSHLocation:
Description: The IP address range that can be used to SSH to the EC2 instances
Type: String
MinLength: '9'
MaxLength: '18'
Default: 0.0.0.0/0
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
# AllowedSSHLocation:
# Description: The IP address range that can be used to SSH to the EC2 instances
# Type: String
# MinLength: '9'
# MaxLength: '18'
# Default: 0.0.0.0/0
# AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
# ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
LatestAmiId:
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
Default: '/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64'
AvailabilityZone:
Description: Select the availability zone in which to create the instance. If you plan to attach a secondary volume to the instance, create this instance in the same AvailabilityZone as the volume you created.
Type: AWS::EC2::AvailabilityZone::Name

Conditions:
IamPolicyEmpty: !Equals [!Ref IamPolicyDocument, '{}']

Resources:
SSMPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: !Join ["-", [Ref: Namespace, "SSM-Policy"]]
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: AllowSSMParamActions
Effect: Allow
Action:
- ssm:GetParameter
- ssm:PutParameter
- ssm:DescribeParameters
- s3files:*
Resource: "*"
- Sid: AllowAccessToEncryptionKeys
Effect: Allow
Action:
- kms:Decrypt
- kms:Encrypt
- kms:GenerateDataKey
- kms:DescribeKey
Resource: "*"
Resources:
IAMRole:
Type: 'AWS::IAM::Role'
Expand All @@ -67,14 +91,16 @@ Resources:
- 'ec2.amazonaws.com'
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Policies:
- !If
- IamPolicyEmpty
- !Ref 'AWS::NoValue'
- PolicyName: !Join ['-', [Ref: Namespace, 's3-studydata-policy']]
PolicyDocument: !Ref IamPolicyDocument
ManagedPolicyArns:
- Ref: SSMPolicy
- arn:aws:iam::aws:policy/amazonSSMManagedInstanceCore
- arn:aws:iam::aws:policy/AmazonS3FilesClientFullAccess

InstanceProfile:
Type: 'AWS::IAM::InstanceProfile'
Expand All @@ -91,6 +117,7 @@ Resources:
Fn::Base64: !Sub |
#!/usr/bin/env bash
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
sudo dnf install -y amazon-efs-utils
# Download and execute bootstrap script
aws s3 cp "${EnvironmentInstanceFiles}/get_bootstrap.sh" "/tmp"
chmod 500 "/tmp/get_bootstrap.sh"
Expand All @@ -99,7 +126,6 @@ Resources:
# Signal result to CloudFormation
/opt/aws/bin/cfn-signal -e $? --stack "${AWS::StackName}" --resource "EC2Instance" --region "${AWS::Region}"
InstanceType: !Ref 'InstanceType'
AvailabilityZone: !Ref AvailabilityZone
SecurityGroups: [!Ref 'InstanceSecurityGroup']
KeyName: !Ref 'KeyPair'
ImageId: !Ref 'LatestAmiId'
Expand All @@ -126,7 +152,7 @@ Resources:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: !Ref 'AllowedSSHLocation'
CidrIp: 0.0.0.0/0

Outputs:
InstanceId:
Expand Down
Loading