Skip to content

Instantly share code, notes, and snippets.

@artyom
Created May 11, 2023 21:30
Show Gist options
  • Save artyom/e700298c834e5ab7d06dcdca470778bf to your computer and use it in GitHub Desktop.
Save artyom/e700298c834e5ab7d06dcdca470778bf to your computer and use it in GitHub Desktop.
Tailscale SSH session recorder setup https://tailscale.com/blog/session-recording-beta/
Description: Tailscale SSH sessions recorder
Parameters:
VPC:
Type: AWS::EC2::VPC::Id
Description: VPC ID
Subnets:
Type: List<AWS::EC2::Subnet::Id>
Description: VPC subnets
Resources:
TailscaleKey:
Type: AWS::SecretsManager::Secret
Properties:
SecretString: '{"TS_AUTHKEY": "FIXME-AFTER-PROVISIONING"}'
Bucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
LifecycleConfiguration:
Rules:
- Id: ia-transition
Status: Enabled
Transitions:
- StorageClass: STANDARD_IA
TransitionInDays: 30
AbortIncompleteMultipartUpload:
DaysAfterInitiation: 1
ExpiredObjectDeleteMarker: true
NoncurrentVersionExpiration:
NewerNoncurrentVersions: 5
NoncurrentDays: 7
Service:
Type: AWS::ECS::Service
Properties:
DesiredCount: 1
DeploymentConfiguration:
MaximumPercent: 100
MinimumHealthyPercent: 0
DeploymentCircuitBreaker:
Enable: true
Rollback: true
LaunchType: FARGATE
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!Ref SecurityGroup]
Subnets: !Ref Subnets
PropagateTags: SERVICE
TaskDefinition: !Ref TaskDefinition
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
NetworkMode: awsvpc
TaskRoleArn: !Ref RoleTask
ExecutionRoleArn: !Ref RoleTaskExecution
Cpu: "512"
Memory: "1024"
ContainerDefinitions:
- Name: tsrecorder
Image: tailscale/tsrecorder:stable
Command:
- /tsrecorder
- !Sub "--dst=s3://s3.${AWS::Region}.${AWS::URLSuffix}"
- !Sub "--bucket=${Bucket}"
- "--ui"
- "--statedir=/data" # TODO: maybe put on AWS::EFS::FileSystem ?
Secrets:
- Name: TS_AUTHKEY
ValueFrom: !Sub "${TailscaleKey}:TS_AUTHKEY::"
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref CloudWatchLogsGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: ecs
RoleTaskExecution:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service: ecs-tasks.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Policies:
- PolicyName: environment-variable-secrets
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action: secretsmanager:GetSecretValue
Effect: Allow
Resource: !Ref TailscaleKey
RoleTask:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service: ecs-tasks.amazonaws.com
Policies:
- PolicyName: s3access
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetBucketLocation
- s3:GetObject
- s3:ListBucket
Resource:
- !Sub "arn:aws:s3:::${Bucket}"
- !Sub "arn:aws:s3:::${Bucket}/*"
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Tailscale SSH recorder
VpcId: !Ref VPC
SecurityGroupIngress:
# optional, but almost guarantees direct connectivity per
# https://tailscale.com/kb/1082/firewall-ports#my-devices-are-using-a-relay-what-can-i-do-to-help-them-connect-peer-to-peer
- IpProtocol: udp
FromPort: 41641
ToPort: 41641
CidrIp: 0.0.0.0/0
Description: Tailscale
CloudWatchLogsGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/ecs/${AWS::StackName}"
RetentionInDays: 7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment