Skip to content

Instantly share code, notes, and snippets.

@ProbablyRusty
Last active February 21, 2024 00:00
Show Gist options
  • Save ProbablyRusty/2e83a48b6a3bae686142b024ab899a3f to your computer and use it in GitHub Desktop.
Save ProbablyRusty/2e83a48b6a3bae686142b024ab899a3f to your computer and use it in GitHub Desktop.
Example of using Terraform to automate ZeroTier installation and network joins for Windows EC2 instances
# I recently needed to automate the process of spinning up Windows EC2 instances
# in AWS, installing ZeroTier, and then joining them to a ZeroTier network. I
# used Terraform to do this. This example might help others. If you provide an
# existing subnet, security group, ZeroTier network ID, and a few other details
# via Terraform variables, this template will create one demo Windows instance
# in AWS, install ZeroTier, and join the instance to the specified ZeroTier
# network.
variable "aws_region" {
description = "AWS Region where this instance will be deployed (ie: us-east-1)"
}
variable "demo_instance_windows_ami" {
description = "Windows AMI ID in the same AWS Region"
}
variable "demo_instance_type" {
description = "EC2 instance type for the demo instance (ie: t2.medium)"
}
variable "demo_instance_subnet_id" {
description = "ID of existing Subnet in VPC where instance will be deployed (ie: subnet-abcd1234)"
}
variable "demo_instance_security_group" {
description = "ID of existing Security Group in VPC where instance will be deployed (ie: sg-abcd1234)"
}
variable "demo_instance_key_name" {
description = "Name of public SSH key to use for the demo instance (must already exist in the same AWS Region)"
}
variable "zerotier_network" {
description = "ZeroTier network which the demo instance should join (ie: 12345678abcdabcd)"
}
provider "aws" {
shared_credentials_file = "${pathexpand("~/.aws/credentials")}"
region = "${var.aws_region}"
}
resource "aws_iam_role" "ssm_role" {
name = "ssm_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "ssm_role_policy" {
role = "${aws_iam_role.ssm_role.name}"
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
}
resource "aws_iam_instance_profile" "ssm_instance_profile" {
name = "ssm_instance_profile"
role = "${aws_iam_role.ssm_role.name}"
}
resource "aws_ssm_document" "zerotier" {
name = "zerotier"
document_type = "Command"
content = <<EOF
{
"schemaVersion": "1.0",
"description": "Install ZeroTier",
"runtimeConfig": {
"aws:runPowerShellScript": {
"properties": [
{
"description": "Install ZeroTier",
"runCommand": [
"$b64 = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZKVENDQkEyZ0F3SUJBZ0lRQnd3UjV2Qk5QSk51QjA2MDhYRGp0akFOQmdrcWhraUc5dzBCQVFVRkFEQnoKTVFzd0NRWURWUVFHRXdKVlV6RVZNQk1HQTFVRUNoTU1SR2xuYVVObGNuUWdTVzVqTVJrd0Z3WURWUVFMRXhCMwpkM2N1WkdsbmFXTmxjblF1WTI5dE1USXdNQVlEVlFRREV5bEVhV2RwUTJWeWRDQklhV2RvSUVGemMzVnlZVzVqClpTQkRiMlJsSUZOcFoyNXBibWNnUTBFdE1UQWVGdzB4TlRBME1qVXdNREF3TURCYUZ3MHhOakEwTURFeE1qQXcKTURCYU1IY3hDekFKQmdOVkJBWVRBbFZUTVJFd0R3WURWUVFJRXdoTmFXTm9hV2RoYmpFVk1CTUdBMVVFQnhNTQpSV0YwYjI0Z1VtRndhV1J6TVI0d0hBWURWUVFLRXhWYVpYSnZWR2xsY2lCT1pYUjNiM0pyY3lCTVRFTXhIakFjCkJnTlZCQU1URlZwbGNtOVVhV1Z5SUU1bGRIZHZjbXR6SUV4TVF6Q0NBU0l3RFFZSktvWklodmNOQVFFQkJRQUQKZ2dFUEFEQ0NBUW9DZ2dFQkFOQ3NKZlh2OUl1eFg0U0d0YkI0Q2RBZkpGR0RSbTRXV3NvazRnQ1piOTV5cy9tNAo4WitvMEkwL3l0NG45UTduc1duYitOSGhtMUFVS2hxNk4wY1BidlJjd2dPcW5CdDJNbE9GT0w1SVNmRFExZTV5CjZHczk2TnNycjJTbFFkeCtOaSs3dmU4Z3BkcklUNVhxRENCQUxCVG1XR0RNQkxpZWN1MVBEYzEyUDlQUm1EaXMKemNQMlpMc05JcmVRN29hcHhXQ2IxWFdtZFFtNFRGZ1p6UWczS0tlQjl6Mkt2TmNlMXVxeTlMQldmbE9uZzdFdwpJa1dZVTBCZEpUbXVGci80Q0FvZDRLTHJGNVc4cmcwZXpKZW1Gd1lVcSt6REdTWEZYVjhLSDVqcGR3aThKRTM0CnNmNmNiL3BnTGgzZ2ZXN1VMeldSRUFiRGpna3hTTklBTlVrRnNZTUNBd0VBQWFPQ0FhOHdnZ0dyTUI4R0ExVWQKSXdRWU1CYUFGSmRJQStzVkNHdTVzbGdqekpRdThjWmwwbVNPTUIwR0ExVWREZ1FXQkJRSllYclNUZ3JOMVFRcApQVGpPWFd1YjJ2K21jVEFPQmdOVkhROEJBZjhFQkFNQ0I0QXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUhBd013CmFRWURWUjBmQkdJd1lEQXVvQ3lnS29Zb2FIUjBjRG92TDJOeWJETXVaR2xuYVdObGNuUXVZMjl0TDJoaExXTnoKTFRJd01URmhMbU55YkRBdW9DeWdLb1lvYUhSMGNEb3ZMMk55YkRRdVpHbG5hV05sY25RdVkyOXRMMmhoTFdOegpMVEl3TVRGaExtTnliREJDQmdOVkhTQUVPekE1TURjR0NXQ0dTQUdHL1d3REFUQXFNQ2dHQ0NzR0FRVUZCd0lCCkZoeG9kSFJ3Y3pvdkwzZDNkeTVrYVdkcFkyVnlkQzVqYjIwdlExQlRNSUdHQmdnckJnRUZCUWNCQVFSNk1IZ3cKSkFZSUt3WUJCUVVITUFHR0dHaDBkSEE2THk5dlkzTndMbVJwWjJsalpYSjBMbU52YlRCUUJnZ3JCZ0VGQlFjdwpBb1pFYUhSMGNEb3ZMMk5oWTJWeWRITXVaR2xuYVdObGNuUXVZMjl0TDBScFoybERaWEowU0dsbmFFRnpjM1Z5CllXNWpaVU52WkdWVGFXZHVhVzVuUTBFdE1TNWpjblF3REFZRFZSMFRBUUgvQkFJd0FEQU5CZ2txaGtpRzl3MEIKQVFVRkFBT0NBUUVBY1JGV3k3T2VmZ0RmTEJJMDFRQVhCYWtCUU1XNVA1dHBZY1hJR3hpYW4xSXRtMUdQTkZJZQpZKzBXQ3RtYUVrNkdOM2ZYZlRiVVRwTWFpeDdITklSL2dTenJOSEw5WjE2UWZKL0lJTGpuUUVjZ2FybDlKK1FDCjVjSDVTcCtrSDU4MkNET3Z6Yjd2dlUrMjFvNDhXUHdrODVFVDYxTzc0MFpucUF3T2pjcDVRZCtrazFjSVdDbXUKYVlGS3F3Q3h1bGxpTFVTVG5vSzAvSGI2MUplcE02cTUxbk5QaE9EY2w0RnhTL0traXFOUU1hQ0tUdFp0d1lWSgphSDhwY3RUeXJjaGpjLzUrV0lEenJHbElrVUhwelNScWpOWVV5cVpFTitEcCtwUDRpYVYwc1RVRmlIKzlDR3RtCmdIcTNiRTBSUGQveDNjSDA3a05RMkdlREdrVmdDQVZhS1E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=='",
"$filename = 'C:\\ProgramData\\zerotier.cer'",
"$bytes = [Convert]::FromBase64String($b64)",
"[IO.File]::WriteAllBytes($filename, $bytes)",
"certutil -addstore 'TrustedPublisher' C:\\ProgramData\\zerotier.cer",
"Invoke-WebRequest -Uri 'https://download.zerotier.com/dist/ZeroTier%20One.msi' -OutFile 'C:\\ProgramData\\zerotier.msi'",
"Start-Process 'msiexec.exe' -ArgumentList '/i C:\\ProgramData\\zerotier.msi','/qn' -wait -passthru",
"Start-Process 'C:\\ProgramData\\ZeroTier\\One\\zerotier-one_x64.exe' -ArgumentList '-q','join','${var.zerotier_network}' -wait -passthru",
"rm 'C:\\ProgramData\\zerotier.msi'",
"rm 'C:\\ProgramData\\zerotier.cer'"
]
}
]
}
}
}
EOF
}
resource "aws_ssm_association" "zerotier" {
name = "${aws_ssm_document.zerotier.name}"
instance_id = "${aws_instance.demo_instance.id}"
}
resource "aws_instance" "demo_instance" {
depends_on = ["aws_ssm_document.zerotier"]
ami = "${var.demo_instance_windows_ami}"
instance_type = "${var.demo_instance_type}"
vpc_security_group_ids = ["${var.demo_instance_security_group}"]
subnet_id = "${var.demo_instance_subnet_id}"
iam_instance_profile = "${aws_iam_instance_profile.ssm_instance_profile.name}"
key_name = "${var.demo_instance_key_name}"
tags {
Name = "demo_instance"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment