Link Search Menu Expand Document

aws

== AWS Examples

Examples of AWS Terraform modules.

Each module corresponds to a module that uses that resource, eg aws_vpc.

aws_db_cluster_snapshot/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create a snapshot of an RDS Aurora MySQL 1 Cluster instance

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region  = "us-east-1"
  profile = "terraform-examples"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_db_cluster_snapshot/simple"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_aurora_cluster_username" {
  description = "the username for the login credentials to your db"
  default     = "username_example"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_aurora_cluster_password" {
  description = "the password, which must be more than 8 characters long"
  default     = "password_example"
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster
resource "aws_rds_cluster" "changeme_aws_aurora_cluster_instance" {
  # The login credentials are stored as plain-text in the state files
  # https://www.terraform.io/docs/language/state/sensitive-data.html
  # For security, use a secrets manager
  # https://registry.terraform.io/modules/yurymkomarov/rds-aurora-cluster/aws/latest#secretsmanager_secret
  master_username     = var.changeme_aws_aurora_cluster_username
  master_password     = var.changeme_aws_aurora_cluster_password
  skip_final_snapshot = true
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_cluster_snapshot
resource "aws_db_cluster_snapshot" "changeme_aws_aurora_snapshot" {
  db_cluster_identifier          = aws_rds_cluster.changeme_aws_aurora_cluster_instance.id
  db_cluster_snapshot_identifier = "changeme-snapshot-identifier"
}
  

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_db_instance/postgres/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create a simple AWS RDS DB Instance with Postgresql 

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_db_instance/postgres"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance
# Explanation: This resource creates the DB Instance. This Example creates a Postgresql Server version 9.6.9 as a Managed RDS Service.
# Allocates a Postgres Database service version 9.6.9 in a t3.micro instance with a database name 'changeme_simple_postgresql_instance', username 'changeme_username' and passwd 'changeme_password'
resource "aws_db_instance" "changeme_simple_postgresql_instance" {
  allocated_storage   = 5
  engine              = "postgres"
  engine_version      = "12.5"
  instance_class      = "db.t3.micro"
  name                = "changeme_simple_postgresql_instance"
  username            = "changeme_username"
  password            = "changeme_password"
  skip_final_snapshot = true
  storage_encrypted   = false
}

##Explanation:
# Details on Arguments:
# Required Argument -  allocated_storage: How Much storage will be allocated for the Database in Gbi
# Required Argument -             engine: Engines Types like MySql, Postgres, MariaDB....
# Required Argument -     engine_version: The above choosen version of Engine. For ex:  MySQL version 5.7
# Required Argument -     instance_class: The size of the Instance (VM)
# Required Argument -           username: The Master DB-User username
# Required Argument -            passord: The master DB-User password
# Optional Argument -               name: The Name of the Instance
# Optional Argument -  skip_final_snapshot: It's needed for destroying the instance with Terraform Destroy
# Optional Argument -  storage_encrypted: If data is going to be encrypted at rest or not
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_db_instance/restore_db_from_snapshot/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create a DB Instance PROD. Takes a snapshot (latest), and with the latest snapshot,creates a new DEV Instance. 

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_db_instance/mount_db_snapshot"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance
# See also: (aws/aws_db_instance/simple)
# Explanation: This resource creates the DB Instance. This Example creates a MySQL  version 5.7 as a Managed RDS Service.
resource "aws_db_instance" "changeme_aws_db_instance_prod" {
  allocated_storage         = 10
  engine                    = "mysql"
  engine_version            = "5.7"
  instance_class            = "db.t2.micro"
  name                      = "changeme_db_prod"
  identifier                = "changeme-db-identifier"
  username                  = "changeme_username_prod"
  password                  = "changeme_password_prod"
  final_snapshot_identifier = "changeme-final-snapshot"
  skip_final_snapshot       = true # change to false if you want to keep snapshot after deleting the instance
}


# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_snapshot
# Explanation: Run a backup snapshot from prod Database. It uses timeouts for waiting until the snapshot operation complete
resource "aws_db_snapshot" "changeme_db_prod_snapshot" {
  db_instance_identifier = aws_db_instance.changeme_aws_db_instance_prod.id
  db_snapshot_identifier = "changeme-prod-snapshot"
  timeouts {
    read = "10m"
  }

  depends_on = [
    aws_db_instance.changeme_aws_db_instance_prod
  ]

}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/db_snapshot
# Explanation: Data Source, reads the latest snapshot from the prod Database and gets its id
data "aws_db_snapshot" "changeme_latest_prod_snapshot" {
  depends_on = [
    aws_db_snapshot.changeme_db_prod_snapshot
  ]
  db_instance_identifier = aws_db_instance.changeme_aws_db_instance_prod.id
  most_recent            = true

}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance
# Explanation: Use the latest production snapshot to create a DEV instance DB.
resource "aws_db_instance" "changeme_db_dev" {
  instance_class      = "db.t2.micro"
  identifier          = "changeme-db-from-backup"
  snapshot_identifier = data.aws_db_snapshot.changeme_latest_prod_snapshot.id
  skip_final_snapshot = true

  lifecycle {
    ignore_changes = [snapshot_identifier]
  }
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_db_instance/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create a simple AWS RDS DB Instance with MySQL 

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_db_instance/simple"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance
# Explanation: This resource creates the DB Instance. This Example creates a MySql Server version 5.7 as a Managed RDS Service.
# Allocates a MySQl version 5.7 in a t3.micro instance with a database name 'changeme_simple_aws_db_instance', username 'changeme_username' and passwd 'changeme_password'
resource "aws_db_instance" "changeme_simple_aws_db_instance" {
  allocated_storage   = 5
  engine              = "mysql"
  engine_version      = "5.7"
  instance_class      = "db.t3.micro"
  name                = "changeme_simple_aws_db_instance"
  username            = "changemeusername"
  password            = "changeme_password"
  skip_final_snapshot = true
}

##Explanation:
# Details on Arguments:
# Required Argument -  allocated_storage: How Much storage will be allocated for the Database in Gbi
# Required Argument -             engine: Engines Types like MySql, Postgres, MariaDB....
# Required Argument -     engine_version: The above choosen version of Engine. For ex:  MySQL version 5.7
# Required Argument -     instance_class: The size of the Instance (VM)
# Required Argument -           username: The Master DB-User username
# Required Argument -            passord: The master DB-User password
# Optional Argument -               name: The Name of the Instance
# Optional Argument -  skip_final_snapshot: It's needed for destroying the instance with Terraform Destroy
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_dynamodb_table/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create an empty table in AWS DynamoDB

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region  = "us-east-1"
  profile = "terraform-examples"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_dynamodb_table/simple"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_hash_key" {
  description = "the hash key that's also defined as an attribute"
  default     = "example_hash_key"
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table#argument-reference
resource "aws_dynamodb_table" "changeme_aws_dynamodb_table" {
  name           = "changeme_table_name" # Explanation: the table's name, which needs to be unique to a region
  read_capacity  = 10                    # Explanation: the number of read units for the table
  write_capacity = 10                    # Explanation: the number of write units for the table
  hash_key       = var.changeme_hash_key

  attribute {
    name = var.changeme_hash_key # Explanation: the attribute must be of type [S]tring, [N]umber, or [B]inary
    type = "S"
  }
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_dynamodb_table_item/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create a table with one item in AWS DynamoDB

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region  = "us-east-1"
  profile = "terraform-examples"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_dynamodb_table_item/simple"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_item_hash_key" {
  description = "the hash key that's also defined as an attribute"
  default     = "example_hash_key"
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item
resource "aws_dynamodb_table_item" "changeme_dynamodb_table_item" {
  table_name = aws_dynamodb_table.changeme_aws_dynamodb_table_resource.name
  hash_key   = aws_dynamodb_table.changeme_aws_dynamodb_table_resource.hash_key

  item = <<ITEM
{
  "example_hash_key": {"S": "something"},
  "example_attribute": {"N": "11111"}
}
ITEM
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table
resource "aws_dynamodb_table" "changeme_aws_dynamodb_table_resource" {
  name           = "changeme_dynamodb_table_name" # Explanation: the table's name, which needs to be unique to a region
  read_capacity  = 10                             # Explanation: the number of read units for the table
  write_capacity = 10                             # Explanation: the number of write units for the table
  hash_key       = var.changeme_item_hash_key

  attribute {
    name = var.changeme_item_hash_key # Explanation: the attribute must be of type [S]tring, [N]umber, or [B]inary
    type = "S"
  }
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_ebs_volume/ebs_snapshot/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create a Snapshot for a Given EBS Volume 

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_ebs_volume/ebs_snapshot"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones
data "aws_availability_zones" "changeme_az_list_ebs_snapshot" {
  state = "available"
}


# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume
# Explanation: The AWS 'aws_ebs_volume' resource is responsible for creating the EBS volume. The only required field is Availability Zone
# where the EBS vol is going to be created. Some optional arguments are Size in GBi, encryption(TRUE/FALSE) and he type of EBS volume. Can be "standard", "gp2", "io1", "sc1" or "st1" (Default: "standard").
resource "aws_ebs_volume" "changeme_ebs_volume_snapshot" {
  availability_zone = data.aws_availability_zones.changeme_az_list_ebs_snapshot.names[0]
  size              = 10
  type              = "standard"
  encrypted         = false
  tags = {
    Name = "changeme_ebs_volume_tag"
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_snapshot
# Explanation: Takes a Snapshot from the EBS Volume created Above 
resource "aws_ebs_snapshot" "changeme_ebs_snapshot" {
  volume_id = aws_ebs_volume.changeme_ebs_volume_snapshot.id

  tags = {
    Name = "Hello_CS_snap"
  }
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_ebs_volume/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create an EBS volume in AWS 

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_ebs_volume/simple"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones
data "aws_availability_zones" "changeme_available_az_list" {
  state = "available"
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume
# Explanation: The AWS 'aws_ebs_volume' resource is responsible for creating the EBS volume. The only required field is Availability Zone
# where the EBS vol is going to be created. Some optional arguments are Size in GBi, encryption(TRUE/FALSE) and he type of EBS volume. Can be "standard", "gp2", "io1", "sc1" or "st1" (Default: "standard").
resource "aws_ebs_volume" "changeme_simple_aws_ebs_volume" {
  availability_zone = data.aws_availability_zones.changeme_available_az_list.names[0]
  size              = 10
  type              = "standard"
  encrypted         = false
  tags = {
    Name = "changeme_ebs_volume_tag"
  }
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_ebs_volume/volume_attachment/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create an EBS volume in AWS and attach to EC2 instance

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_ebs_volume/volume_attachment"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones
data "aws_availability_zones" "changeme_az_list" {
  state = "available"
}


# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/volume_attachment
# Explanation: Provide the attachment between the extra EBS external volume and the Ec2 Instance 
resource "aws_volume_attachment" "changeme_aws_volume_attachment" {
  device_name = "/dev/sdh"
  volume_id   = aws_ebs_volume.changeme_aws_ebs_volume.id
  instance_id = aws_instance.changeme_aws_instance.id
}


# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume
# Explanation: The AWS 'aws_ebs_volume' resource is responsible for creating the EBS volume. The only required field is Availability Zone
# where the EBS vol is going to be created. Some optional arguments are Size in GBi, encryption(TRUE/FALSE) and he type of EBS volume. Can be "standard", "gp2", "io1", "sc1" or "st1" (Default: "standard").
resource "aws_ebs_volume" "changeme_aws_ebs_volume" {
  availability_zone = data.aws_availability_zones.changeme_az_list.names[0]
  size              = 5
  type              = "standard"
  encrypted         = false
  tags = {
    Name = "changeme_ebs_volume_tag"
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
# Explanation: The AWS 'aws_instance' resource is responsible for allocating an EC2 instance. It's needed as we want to deliver the 
# the EBS volume to it. 
resource "aws_instance" "changeme_aws_instance" {
  instance_type = "t2.micro"

  # Explanation: AMI IDs are region-specific. This AMI ID is specific to the `us-east-1` region. If you use a different region, you will need to change this ID.
  ami               = "ami-0c2b8ca1dad447f8a" # us-east-1 / Amazon Linux
  availability_zone = data.aws_availability_zones.changeme_az_list.names[0]
  tags = {
    Name = "changeme_aws_instance_tag"
  }
  user_data = <<-EOF
            #!/bin/bash
            echo "Hello_Example!"
            EOF
}

 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_eks/fargate/spot_and_fargate/

Spot instances + fargate EKS cluster

This example sets the cluster control plane on SPOT instances (for test purposes, and saving credits) and normal workloads on Fargate (Pay per Pod). To make the control plane use normal instances you just need to comment the line with capacity_type = "SPOT" main.tf.

destroy.sh

            #!/bin/bash
../../../../bin/destroy.sh aws
 

main.tf

            # Summary: See README.md

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    local = {
      version = "~> 1.4"
    }
    external = {
      version = "~> 1.2"
    }
    kubernetes = {
      version = "~> 1.10"
    }
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_eks/fargate/spot_and_fargate"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "kubernetes" {
  host                   = data.aws_eks_cluster.changeme_spot_and_fargate_eks_cluster_data.endpoint
  load_config_file       = false
  cluster_ca_certificate = base64decode(data.aws_eks_cluster.changeme_spot_and_fargate_eks_cluster_data.certificate_authority[0].data)
  token                  = data.aws_eks_cluster_auth.changeme_spot_and_fargate_eks_cluster_auth_data.token
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_name" {
  description = "the name of your stack, e.g. \"demo\""
  default     = "eks-example"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_environment" {
  description = "the name of your environment, e.g. \"prod\""
  default     = "prod"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_region" {
  description = "the AWS region in which resources are created, you must set the availability_zones variable as well if you define this value to something other than the default"
  default     = "us-east-1"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_availability_zones" {
  description = "a comma-separated list of availability zones, defaults to all AZ of the region, if set to something other than the defaults, both private_subnets and public_subnets have to be defined as well"
  default     = ["us-east-1a", "us-east-1b", "us-east-1c"]
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_cidr" {
  description = "The CIDR block for the VPC."
  default     = "10.0.0.0/16"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_private_subnets" {
  description = "a list of CIDRs for private subnets in your VPC, must be set if the cidr variable is defined, needs to have as many elements as there are availability zones"
  default     = ["10.0.0.0/20", "10.0.32.0/20", "10.0.64.0/20"]
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_public_subnets" {
  description = "a list of CIDRs for public subnets in your VPC, must be set if the cidr variable is defined, needs to have as many elements as there are availability zones"
  default     = ["10.0.16.0/20", "10.0.48.0/20", "10.0.80.0/20"]
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_k8s_version" {
  description = "kubernetes version"
  default     = ""
}

# Documentation: https://www.terraform.io/docs/language/data-sources/index.html
data "aws_eks_cluster" "changeme_spot_and_fargate_eks_cluster_data" {
  name = aws_eks_cluster.changeme_spot_and_fargate_eks_cluster.id
}

# Documentation: https://www.terraform.io/docs/language/data-sources/index.html
data "aws_eks_cluster_auth" "changeme_spot_and_fargate_eks_cluster_auth_data" {
  name = aws_eks_cluster.changeme_spot_and_fargate_eks_cluster.id
}

# Fetch OIDC provider thumbprint for root CA
# Documentation: https://www.terraform.io/docs/language/data-sources/index.html
data "external" "changeme_external_thumbprint_data" {
  program    = ["${path.module}/oidc_thumbprint.sh", var.changeme_spot_and_fargate_region]
  depends_on = [aws_eks_cluster.changeme_spot_and_fargate_eks_cluster]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc
resource "aws_vpc" "changeme_spot_and_fargate_vpc" {
  cidr_block           = var.changeme_spot_and_fargate_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway
resource "aws_internet_gateway" "changeme_spot_and_fargate_internet_gateway" {
  vpc_id = aws_vpc.changeme_spot_and_fargate_vpc.id
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway
resource "aws_nat_gateway" "changeme_spot_and_fargate_nat_gateway" {
  count         = length(var.changeme_spot_and_fargate_private_subnets)
  allocation_id = element(aws_eip.changeme_spot_and_fargate_eip.*.id, count.index)
  subnet_id     = element(aws_subnet.changeme_spot_and_fargate_subnet_public.*.id, count.index)
  depends_on    = [aws_internet_gateway.changeme_spot_and_fargate_internet_gateway]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip
resource "aws_eip" "changeme_spot_and_fargate_eip" {
  count = length(var.changeme_spot_and_fargate_private_subnets)
  vpc   = true
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet
resource "aws_subnet" "changeme_spot_and_fargate_subnet_private" {
  vpc_id            = aws_vpc.changeme_spot_and_fargate_vpc.id
  cidr_block        = element(var.changeme_spot_and_fargate_private_subnets, count.index)
  availability_zone = element(var.changeme_spot_and_fargate_availability_zones, count.index)
  count             = length(var.changeme_spot_and_fargate_private_subnets)
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet
resource "aws_subnet" "changeme_spot_and_fargate_subnet_public" {
  vpc_id                  = aws_vpc.changeme_spot_and_fargate_vpc.id
  cidr_block              = element(var.changeme_spot_and_fargate_public_subnets, count.index)
  availability_zone       = element(var.changeme_spot_and_fargate_availability_zones, count.index)
  count                   = length(var.changeme_spot_and_fargate_public_subnets)
  map_public_ip_on_launch = true
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table
resource "aws_route_table" "changeme_spot_and_fargate_route_table_public" {
  vpc_id = aws_vpc.changeme_spot_and_fargate_vpc.id
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route
resource "aws_route" "changeme_spot_and_fargate_aws_route_public" {
  route_table_id         = aws_route_table.changeme_spot_and_fargate_route_table_public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.changeme_spot_and_fargate_internet_gateway.id
  timeouts {
    create = "5m"
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table
resource "aws_route_table" "changeme_spot_and_fargate_route_table_private" {
  count  = length(var.changeme_spot_and_fargate_private_subnets)
  vpc_id = aws_vpc.changeme_spot_and_fargate_vpc.id
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route
resource "aws_route" "changeme_spot_and_fargate_route_private" {
  count                  = length(compact(var.changeme_spot_and_fargate_private_subnets))
  route_table_id         = element(aws_route_table.changeme_spot_and_fargate_route_table_private.*.id, count.index)
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = element(aws_nat_gateway.changeme_spot_and_fargate_nat_gateway.*.id, count.index)
  timeouts {
    create = "5m"
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association
resource "aws_route_table_association" "changeme_spot_and_fargate_route_table_association_private" {
  count          = length(var.changeme_spot_and_fargate_private_subnets)
  subnet_id      = element(aws_subnet.changeme_spot_and_fargate_subnet_private.*.id, count.index)
  route_table_id = element(aws_route_table.changeme_spot_and_fargate_route_table_private.*.id, count.index)
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association
resource "aws_route_table_association" "changeme_spot_and_fargate_route_table_association_public" {
  count          = length(var.changeme_spot_and_fargate_public_subnets)
  subnet_id      = element(aws_subnet.changeme_spot_and_fargate_subnet_public.*.id, count.index)
  route_table_id = aws_route_table.changeme_spot_and_fargate_route_table_public.id
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role
resource "aws_iam_role" "changeme_spot_and_fargate_iam_role_cluster" {
  name                  = "${var.changeme_spot_and_fargate_name}-eks-cluster-role"
  force_detach_policies = true

  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "eks.amazonaws.com",
          "eks-fargate-pods.amazonaws.com"
          ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "changeme_spot_and_fargate_AmazonEKSClusterPolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
  role       = aws_iam_role.changeme_spot_and_fargate_iam_role_cluster.name
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "changeme_spot_and_fargate_AmazonEKSServicePolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSServicePolicy"
  role       = aws_iam_role.changeme_spot_and_fargate_iam_role_cluster.name
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster
resource "aws_eks_cluster" "changeme_spot_and_fargate_eks_cluster" {
  name     = "${var.changeme_spot_and_fargate_name}-${var.changeme_spot_and_fargate_environment}"
  role_arn = aws_iam_role.changeme_spot_and_fargate_iam_role_cluster.arn

  vpc_config {
    subnet_ids = concat(aws_subnet.changeme_spot_and_fargate_subnet_public.*.id, aws_subnet.changeme_spot_and_fargate_subnet_private.*.id)
  }

  timeouts {
    delete = "30m"
  }

  depends_on = [
    aws_iam_role_policy_attachment.changeme_spot_and_fargate_AmazonEKSClusterPolicy,
    aws_iam_role_policy_attachment.changeme_spot_and_fargate_AmazonEKSServicePolicy
  ]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider
resource "aws_iam_openid_connect_provider" "changeme_iam_openid_connect_provider" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.external.changeme_external_thumbprint_data.result.thumbprint]
  url             = data.aws_eks_cluster.changeme_spot_and_fargate_eks_cluster_data.identity[0].oidc[0].issuer

  lifecycle {
    ignore_changes = [thumbprint_list]
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role
resource "aws_iam_role" "changeme_spot_and_fargate_iam_role_node_group" {
  name                  = "${var.changeme_spot_and_fargate_name}-eks-node-group-role"
  force_detach_policies = true

  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "ec2.amazonaws.com"
          ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "changeme_spot_and_fargate_AmazonEKSWorkerNodePolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
  role       = aws_iam_role.changeme_spot_and_fargate_iam_role_node_group.name
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "changeme_spot_and_fargate_AmazonEKS_CNI_Policy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
  role       = aws_iam_role.changeme_spot_and_fargate_iam_role_node_group.name
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "changeme_spot_and_fargate_AmazonEC2ContainerRegistryReadOnly" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
  role       = aws_iam_role.changeme_spot_and_fargate_iam_role_node_group.name
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group
resource "aws_eks_node_group" "changeme_spot_and_fargate_eks_node_group" {
  cluster_name    = aws_eks_cluster.changeme_spot_and_fargate_eks_cluster.name
  node_group_name = "changeme-eks-cluster-kube-system"
  node_role_arn   = aws_iam_role.changeme_spot_and_fargate_iam_role_node_group.arn
  subnet_ids      = aws_subnet.changeme_spot_and_fargate_subnet_private.*.id
  capacity_type   = "SPOT"

  scaling_config {
    desired_size = 1
    max_size     = 1
    min_size     = 1
  }

  instance_types = ["t2.micro"]

  version = var.changeme_spot_and_fargate_k8s_version

  # Ensure that IAM Role permissions are created before and deleted after EKS Node Group handling.
  # Otherwise, EKS will not be able to properly delete EC2 Instances and Elastic Network Interfaces.
  depends_on = [
    aws_iam_role_policy_attachment.changeme_spot_and_fargate_AmazonEKSWorkerNodePolicy,
    aws_iam_role_policy_attachment.changeme_spot_and_fargate_AmazonEKS_CNI_Policy,
    aws_iam_role_policy_attachment.changeme_spot_and_fargate_AmazonEC2ContainerRegistryReadOnly,
  ]
}

# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "cluster_id" {
  description = "ID of the created cluster"
  value       = aws_eks_cluster.changeme_spot_and_fargate_eks_cluster.id
}
 

oidc_thumbprint.sh

            #!/bin/bash

# source: https://github.com/terraform-providers/terraform-provider-aws/issues/10104

THUMBPRINT=$(echo | openssl s_client -servername oidc.eks."${1}".amazonaws.com -showcerts -connect oidc.eks."${1}".amazonaws.com:443 2>&- | tac | sed -n '/-----END CERTIFICATE-----/,/-----BEGIN CERTIFICATE-----/p; /-----BEGIN CERTIFICATE-----/q' | tac | openssl x509 -fingerprint -noout | sed 's/://g' | awk -F= '{print tolower($2)}')
THUMBPRINT_JSON="{\"thumbprint\": \"${THUMBPRINT}\"}"
echo "$THUMBPRINT_JSON" 

run.sh

            #!/bin/bash
../../../../bin/apply.sh aws
 

aws_elb/classic_elb/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Creates a simple Classic Elastic Load Balancer with two EC2 Instances 
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-2"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_elb/classic_elb"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
# See also: [aws/aws_security_group/ssh](https://github.com/ContainerSolutions/terraform-examples/tree/main/aws/aws_security_group/ssh)
resource "aws_security_group" "changeme_aws_security_group" {
  name        = "changeme-aws-security-group-classic-elb-name"
  description = "Allow HTTP 8080 inbound traffic"
  ingress {
    from_port   = 8080
    to_port     = 8080
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
# Explanation: Deploys the first Server in us-east-2a
resource "aws_instance" "changeme_first_aws_instance" {
  ami                    = "ami-0c55b159cbfafe1f0"
  instance_type          = "t2.micro"
  availability_zone      = "us-east-2a"
  vpc_security_group_ids = [aws_security_group.changeme_aws_security_group.id]
  user_data              = <<-EOF
              #!/bin/bash
              echo "Hello, World from Host1" > index.html
              nohup busybox httpd -f -p 8080 &
              EOF
  tags = {
    Name = "changeme_first_aws_instance_tag"
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
# Explanation: Deploys the second Server in us-east-2b 
resource "aws_instance" "changeme_second_aws_instance" {
  ami                    = "ami-0c55b159cbfafe1f0"
  instance_type          = "t2.micro"
  availability_zone      = "us-east-2b"
  vpc_security_group_ids = [aws_security_group.changeme_aws_security_group.id]
  user_data              = <<-EOF
              #!/bin/bash
              echo "Hello, World from Host2" > index.html
              nohup busybox httpd -f -p 8080 &
              EOF
  tags = {
    Name = "changeme_second_aws_instance_tag"
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elb
# Explanation: Deploys the Classic Load Balancer, allows traffic in 8080 ports 
resource "aws_elb" "changeme_simple_aws_elb" {
  name               = "changeme-simple-aws-elb"
  availability_zones = ["us-east-2a", "us-east-2b"]



  listener {
    instance_port     = 8080
    instance_protocol = "http"
    lb_port           = 8080
    lb_protocol       = "http"
  }

  health_check {
    healthy_threshold   = 10
    unhealthy_threshold = 2
    timeout             = 5
    target              = "HTTP:8080/"
    interval            = 10
  }

  instances                   = [aws_instance.changeme_first_aws_instance.id, aws_instance.changeme_second_aws_instance.id]
  cross_zone_load_balancing   = true
  idle_timeout                = 400
  connection_draining         = true
  connection_draining_timeout = 400

  tags = {
    Name = "changeme_simple_aws_elb_tag"
  }
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_iam/groups/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create a two users in two groups

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_iam/groups"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_iam_groups_groups" {
  type = list(any)
  default = [
    "Dev",
    "Infra"
  ]
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_iam_groups_users" {
  type = map(any)
  default = {
    "jane.doe" = {
      "groups" = [
        "Dev"
      ],
    },
    "john.doe" = {
      "groups" = [
        "Infra"
      ],
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group
resource "aws_iam_group" "changeme_iam_groups_groups" {
  count = length(var.changeme_iam_groups_groups)
  name  = var.changeme_iam_groups_groups[count.index]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy_attachment
resource "aws_iam_group_policy_attachment" "changeme_iam_group_policy_attachment_administrators" {
  group      = aws_iam_group.changeme_iam_groups_groups[1].name
  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy
resource "aws_iam_group_policy" "changeme_iam_group_policy_dev" {
  name   = "changeme-iam-group-policy-dev"
  group  = aws_iam_group.changeme_iam_groups_groups[1].id
  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*"
    }
  ]
}
EOF
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy
resource "aws_iam_group_policy" "changeme_iam_group_policy_dev_assumerole" {
  name   = "changeme-iam-group-policy-devsecops-assumerole"
  group  = aws_iam_group.changeme_iam_groups_groups[1].id
  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*"
    }
  ]
}
EOF
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user
resource "aws_iam_user" "changeme_iam_user_users" {
  for_each = var.changeme_iam_groups_users
  name     = each.key
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_group_membership
resource "aws_iam_user_group_membership" "changeme_iam_user_group_membership_user_groups" {
  for_each = var.changeme_iam_groups_users
  user     = each.key
  groups   = each.value["groups"]
  # This manual dependency is required, else Terraform complains the users do not exist yet.
  depends_on = [
    aws_iam_user.changeme_iam_user_users,
    aws_iam_group.changeme_iam_groups_groups
  ]
}

 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_instance/ami_lookup/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Data Source for getting latest getting AMI Linux Imagehttps://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html

# Documentation: https://www.tserraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_instance/ami_lookup"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami
# Explanation: Get most_recent version of Ubuntu Image 
data "aws_ami" "changeme_aws_ami" {
  most_recent = true

  # Explanation: Canonical now publishes  official Ubuntu images on the Amazon cloud.
  # Check supported versions here : https://uec-images.ubuntu.com/locator/
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-hirsute-21.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  # Explanation: There are different Public providers (owners), like Canonical, AWS and others . Check here: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html
  # Some examples of owners:   099720109477 - Canonical and 679593333241 - AWS
  owners = ["099720109477"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_ami_lookup_aws_instance" {
  ami           = data.aws_ami.changeme_aws_ami.id
  instance_type = "t3.micro"

  tags = {
    Name = "changeme_ami_lookup_aws_instance"
  }
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_instance/count/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Uses the 'count' feature to create multiple EC2 instances.

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_instance/count"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_aws_instance_count_count" {
  # Documentation: https://www.terraform.io/docs/language/meta-arguments/count.html
  count         = 2
  instance_type = "t2.nano"
  ami           = "ami-0ddbdea833a8d2f0d"
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_instance/for_each/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Example of 'for_each' usage.

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_instance/for_each"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_aws_instance_count_foreach" {
  # Documentation: https://www.terraform.io/docs/language/meta-arguments/for_each.html
  for_each = {
    "a" = "1"
    "b" = "2"
  }

  tags = {
    Name = "aws_resource_count_${each.key}${each.value}"
  }
  instance_type = "t2.nano"
  ami           = "ami-0ddbdea833a8d2f0d"
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_instance/remote-exec/inline/

To run this:

../../../../bin/apply_aws.sh

destroy.sh

            #!/bin/bash
../../../../bin/destroy.sh aws
 

main.tf

            # Summary: Remote execution using default expected location of your ssh keys,
# and setup of provider connection.

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_instance/remote-exec/inline"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/data-sources/index.html
data "aws_vpc" "changeme_aws_vpc_default" {
  default = true
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_ssh_private_key_path" {
  description = "SSH private key file path"
  default     = "~/.ssh/id_rsa"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_ssh_public_key_path" {
  description = "SSH public key file path"
  default     = "~/.ssh/id_rsa.pub"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_ssh_username" {
  description = "Default username built into the AMI"
  default     = "ubuntu"
}

# Explanation: Create an SSH key pair for accessing the EC2 instance
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair
resource "aws_key_pair" "changeme_remote_exec_inline_aws_key_pair" {
  public_key = file(var.changeme_aws_instance_remote_exec_inline_ssh_public_key_path)
}

# Explanation: Create our default security group to access the instance, over specific protocols
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_remote_exec_inline_security_group" {
  vpc_id = data.aws_vpc.changeme_aws_vpc_default.id
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_security_group_rule_outgoing_any" {
  security_group_id = aws_security_group.changeme_remote_exec_inline_security_group.id
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_security_group_rule_incoming_ssh" {
  security_group_id = aws_security_group.changeme_remote_exec_inline_security_group.id
  type              = "ingress"
  from_port         = 22
  to_port           = 22
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_remote_exec_inline_aws_instance" {
  # Documentation: https://www.terraform.io/docs/language/meta-arguments/count.html
  count = 2

  instance_type          = "t2.nano"
  ami                    = "ami-0ddbdea833a8d2f0d"
  key_name               = aws_key_pair.changeme_remote_exec_inline_aws_key_pair.id # the name of the SSH keypair to use for provisioning
  vpc_security_group_ids = [aws_security_group.changeme_remote_exec_inline_security_group.id]

  # Documentation: https://www.terraform.io/docs/language/resources/provisioners/connection.html
  connection {
    host        = self.public_ip
    user        = var.changeme_aws_instance_remote_exec_inline_ssh_username
    private_key = file(var.changeme_aws_instance_remote_exec_inline_ssh_private_key_path)
    agent       = false # don't use SSH agent because we have the private key right here
  }

  # Documentation: https://www.terraform.io/docs/language/resources/provisioners/remote-exec.html
  provisioner "remote-exec" {
    inline = [
      "echo ${self.ami}"
    ]
  }
}
 

run.sh

            #!/bin/bash
../../../../bin/check_or_create_ssh_key.sh
../../../../bin/apply.sh aws
 

Connection to Windows instances should be done using WinRM. In this example WinRM is enabled in the instance’s user_data.

After that, the assigned password is retrieved using the get_password_data argument and the private key. We use the Administrator user and its retrieved password to connect to the instance, copy the hello.ps1 script and execute it.

To run this:

../../../../../bin/apply_aws.sh

destroy.sh

            #!/bin/bash
../../../../../bin/destroy.sh aws
 

main.tf

            # Summary: Run a command in a newly-created Windows machine

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_instance/remote-exec/inline/windows"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc
data "aws_vpc" "changeme_aws_vpc" {
  default = true
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path" {
  description = "SSH private key file path"
  default     = "~/.ssh/id_rsa"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_windows_ssh_public_key_path" {
  description = "SSH public key file path"
  default     = "~/.ssh/id_rsa.pub"
}

# Explanation: Create an SSH key pair for accessing the EC2 instance
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair
resource "aws_key_pair" "changeme_remote_exec_inline_windows_key_pair" {
  public_key = file(var.changeme_aws_instance_remote_exec_inline_windows_ssh_public_key_path)
}

# Explanation: Create our default security group to access the instance, over specific protocols
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_remote_exec_inline_windows_security_group" {
  vpc_id = data.aws_vpc.changeme_aws_vpc.id
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_windows_security_group_rule_outgoing_any" {
  security_group_id = aws_security_group.changeme_remote_exec_inline_windows_security_group.id
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_security_group_rule_incoming_rdp" {
  security_group_id = aws_security_group.changeme_remote_exec_inline_windows_security_group.id
  type              = "ingress"
  from_port         = 3389
  to_port           = 3389
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_incoming_winrm" {
  security_group_id = aws_security_group.changeme_remote_exec_inline_windows_security_group.id
  type              = "ingress"
  from_port         = 5986
  to_port           = 5986
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_remote_exec_inline_windows_aws_instance" {
  instance_type          = "t2.micro"
  ami                    = "ami-0f93c815788872c5d"
  key_name               = aws_key_pair.changeme_remote_exec_inline_windows_key_pair.id # the name of the SSH keypair to use for provisioning
  vpc_security_group_ids = [aws_security_group.changeme_remote_exec_inline_windows_security_group.id]
  user_data              = file("scripts/user_data.txt")
  get_password_data      = true
  tags                   = { Name = "terraform-examples" }
}

# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_admin_password" {
  value = rsadecrypt(aws_instance.changeme_remote_exec_inline_windows_aws_instance.password_data, file(var.changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path))
}

# Documentation: https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource
resource "null_resource" "changeme_provision_files" {
  # Documentation: https://www.terraform.io/docs/language/resources/provisioners/connection.html
  connection {
    host     = aws_instance.changeme_remote_exec_inline_windows_aws_instance.public_ip
    type     = "winrm"
    user     = "Administrator"
    password = rsadecrypt(aws_instance.changeme_remote_exec_inline_windows_aws_instance.password_data, file(var.changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path))
    https    = true
    insecure = true
    port     = 5986
    timeout  = "1m"
  }

  # Documentation https://www.terraform.io/docs/language/resources/provisioners/index.html
  provisioner "file" {
    source      = "scripts/hello.ps1"
    destination = "C:/hello.ps1"
  }

  # Documentation: https://www.terraform.io/docs/language/resources/provisioners/remote-exec.html
  provisioner "remote-exec" {
    inline = [
      "powershell.exe -ExecutionPolicy Bypass -File C:/hello.ps1"
    ]
  }
}
 

run.sh

            #!/bin/bash
../../../../../bin/check_or_create_ssh_key.sh
../../../../../bin/apply.sh aws
 

hello.ps1

            $hello = "Hello " + $env:COMPUTERNAME
Write-Host $hello

Set-Content "hello.txt" $hello -Force 

user_data.txt

            <powershell>
#https://github.com/sdu-rds/beagile-frontera-golden-image/blob/master/packer/scripts/bootstrap.txt
write-output "Running User Data Script"
write-host "(host) Running User Data Script"
Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore
# Don't set this before Set-ExecutionPolicy as it throws an error
$ErrorActionPreference = "stop"
# Remove HTTP listener
Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse
# Create a self-signed certificate to let ssl work
$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer"
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force
# WinRM
write-output "Setting up WinRM"
write-host "(host) setting up WinRM"
cmd.exe /c winrm quickconfig -q
cmd.exe /c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}'
cmd.exe /c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}'
cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}"
cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
cmd.exe /c netsh advfirewall firewall set rule name="WinRM-HTTPS" new action=allow
cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986"
cmd.exe /c net stop winrm
cmd.exe /c sc config winrm start= auto
cmd.exe /c net start winrm
</powershell>
 

aws_instance/remote-exec/inline/windows/

Connection to Windows instances should be done using WinRM. In this example WinRM is enabled in the instance’s user_data.

After that, the assigned password is retrieved using the get_password_data argument and the private key. We use the Administrator user and its retrieved password to connect to the instance, copy the hello.ps1 script and execute it.

To run this:

../../../../../bin/apply_aws.sh

destroy.sh

            #!/bin/bash
../../../../../bin/destroy.sh aws
 

main.tf

            # Summary: Run a command in a newly-created Windows machine

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_instance/remote-exec/inline/windows"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc
data "aws_vpc" "changeme_aws_vpc" {
  default = true
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path" {
  description = "SSH private key file path"
  default     = "~/.ssh/id_rsa"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_windows_ssh_public_key_path" {
  description = "SSH public key file path"
  default     = "~/.ssh/id_rsa.pub"
}

# Explanation: Create an SSH key pair for accessing the EC2 instance
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair
resource "aws_key_pair" "changeme_remote_exec_inline_windows_key_pair" {
  public_key = file(var.changeme_aws_instance_remote_exec_inline_windows_ssh_public_key_path)
}

# Explanation: Create our default security group to access the instance, over specific protocols
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_remote_exec_inline_windows_security_group" {
  vpc_id = data.aws_vpc.changeme_aws_vpc.id
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_windows_security_group_rule_outgoing_any" {
  security_group_id = aws_security_group.changeme_remote_exec_inline_windows_security_group.id
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_security_group_rule_incoming_rdp" {
  security_group_id = aws_security_group.changeme_remote_exec_inline_windows_security_group.id
  type              = "ingress"
  from_port         = 3389
  to_port           = 3389
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_incoming_winrm" {
  security_group_id = aws_security_group.changeme_remote_exec_inline_windows_security_group.id
  type              = "ingress"
  from_port         = 5986
  to_port           = 5986
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_remote_exec_inline_windows_aws_instance" {
  instance_type          = "t2.micro"
  ami                    = "ami-0f93c815788872c5d"
  key_name               = aws_key_pair.changeme_remote_exec_inline_windows_key_pair.id # the name of the SSH keypair to use for provisioning
  vpc_security_group_ids = [aws_security_group.changeme_remote_exec_inline_windows_security_group.id]
  user_data              = file("scripts/user_data.txt")
  get_password_data      = true
  tags                   = { Name = "terraform-examples" }
}

# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_admin_password" {
  value = rsadecrypt(aws_instance.changeme_remote_exec_inline_windows_aws_instance.password_data, file(var.changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path))
}

# Documentation: https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource
resource "null_resource" "changeme_provision_files" {
  # Documentation: https://www.terraform.io/docs/language/resources/provisioners/connection.html
  connection {
    host     = aws_instance.changeme_remote_exec_inline_windows_aws_instance.public_ip
    type     = "winrm"
    user     = "Administrator"
    password = rsadecrypt(aws_instance.changeme_remote_exec_inline_windows_aws_instance.password_data, file(var.changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path))
    https    = true
    insecure = true
    port     = 5986
    timeout  = "1m"
  }

  # Documentation https://www.terraform.io/docs/language/resources/provisioners/index.html
  provisioner "file" {
    source      = "scripts/hello.ps1"
    destination = "C:/hello.ps1"
  }

  # Documentation: https://www.terraform.io/docs/language/resources/provisioners/remote-exec.html
  provisioner "remote-exec" {
    inline = [
      "powershell.exe -ExecutionPolicy Bypass -File C:/hello.ps1"
    ]
  }
}
 

run.sh

            #!/bin/bash
../../../../../bin/check_or_create_ssh_key.sh
../../../../../bin/apply.sh aws
 

hello.ps1

            $hello = "Hello " + $env:COMPUTERNAME
Write-Host $hello

Set-Content "hello.txt" $hello -Force 

user_data.txt

            <powershell>
#https://github.com/sdu-rds/beagile-frontera-golden-image/blob/master/packer/scripts/bootstrap.txt
write-output "Running User Data Script"
write-host "(host) Running User Data Script"
Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore
# Don't set this before Set-ExecutionPolicy as it throws an error
$ErrorActionPreference = "stop"
# Remove HTTP listener
Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse
# Create a self-signed certificate to let ssl work
$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer"
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force
# WinRM
write-output "Setting up WinRM"
write-host "(host) setting up WinRM"
cmd.exe /c winrm quickconfig -q
cmd.exe /c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}'
cmd.exe /c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}'
cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}"
cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
cmd.exe /c netsh advfirewall firewall set rule name="WinRM-HTTPS" new action=allow
cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986"
cmd.exe /c net stop winrm
cmd.exe /c sc config winrm start= auto
cmd.exe /c net start winrm
</powershell>
 

aws_instance/remote-exec/inline/windows/scripts/

hello.ps1

            $hello = "Hello " + $env:COMPUTERNAME
Write-Host $hello

Set-Content "hello.txt" $hello -Force 

user_data.txt

            <powershell>
#https://github.com/sdu-rds/beagile-frontera-golden-image/blob/master/packer/scripts/bootstrap.txt
write-output "Running User Data Script"
write-host "(host) Running User Data Script"
Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore
# Don't set this before Set-ExecutionPolicy as it throws an error
$ErrorActionPreference = "stop"
# Remove HTTP listener
Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse
# Create a self-signed certificate to let ssl work
$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer"
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force
# WinRM
write-output "Setting up WinRM"
write-host "(host) setting up WinRM"
cmd.exe /c winrm quickconfig -q
cmd.exe /c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}'
cmd.exe /c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}'
cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}"
cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
cmd.exe /c netsh advfirewall firewall set rule name="WinRM-HTTPS" new action=allow
cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986"
cmd.exe /c net stop winrm
cmd.exe /c sc config winrm start= auto
cmd.exe /c net start winrm
</powershell>
 

aws_instance/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Simplest example of an aws_instance resource
#
# Note: This example simply creates the VM, but does not set up a keypair,
#       or networking such that you can ssh into it from the internet.
#       For a more complete example, see `aws/aws_instance/remote_exec/inline`.

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_instance/simple"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_aws_resource_simple" {
  instance_type = "t2.nano"
  ami           = "ami-0ddbdea833a8d2f0d"
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_instance/simple_ssh_access/

To run this:

../../../../bin/apply_aws.sh

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Remote execution using default expected location of your ssh keys,
# and setup of provider connection.
#
# Note: assumes you have a keypair set up in the location specified in
#       `changeme_aws_instance_simple_ssh_access_ssh_private_key_path.default` below.
#       This has been set to a useful default of `~/.ssh/id_rsa`.
#       You can retrieve the public IP address by looking at the output of `terraform show`,
#       eg `terraform show | grep public_ip`.
#       You should then be able to log in with, eg: `ssh -i ~/.ssh/id_rsa ubuntu@<<PUBLIC IP ADDRESS>>`.

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_instance/simple_ssh_access"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/data-sources/index.html
data "aws_vpc" "changeme_aws_simple_ssh_access_vpc_default" {
  default = true
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_simple_ssh_access_ssh_private_key_path" {
  description = "SSH private key file path"
  default     = "~/.ssh/id_rsa"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_simple_ssh_access_ssh_public_key_path" {
  description = "SSH public key file path"
  default     = "~/.ssh/id_rsa.pub"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_simple_ssh_access_ssh_username" {
  description = "Default username built into the AMI"
  default     = "ubuntu"
}

# Explanation: Create an SSH key pair for accessing the EC2 instance
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair
resource "aws_key_pair" "changeme_simple_ssh_access_aws_key_pair" {
  public_key = file(var.changeme_aws_instance_simple_ssh_access_ssh_public_key_path)
}

# Explanation: Create our default security group to access the instance, over specific protocols
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_simple_ssh_access_security_group" {
  vpc_id = data.aws_vpc.changeme_aws_simple_ssh_access_vpc_default.id
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_simple_ssh_access_security_group_rule_outgoing_any" {
  security_group_id = aws_security_group.changeme_simple_ssh_access_security_group.id
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_simple_ssh_access_security_group_rule_incoming_ssh" {
  security_group_id = aws_security_group.changeme_simple_ssh_access_security_group.id
  type              = "ingress"
  from_port         = 22
  to_port           = 22
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_simple_ssh_access_aws_instance" {
  # Documentation: https://www.terraform.io/docs/language/meta-arguments/count.html
  instance_type          = "t2.nano"
  ami                    = "ami-0ddbdea833a8d2f0d"
  key_name               = aws_key_pair.changeme_simple_ssh_access_aws_key_pair.id # the name of the SSH keypair to use for provisioning
  vpc_security_group_ids = [aws_security_group.changeme_simple_ssh_access_security_group.id]
}
 

run.sh

            #!/bin/bash
../../../bin/check_or_create_ssh_key.sh
../../../bin/apply.sh aws
 

aws_lambda_function/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create a lambda function in AWS

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region  = "us-east-1"
  profile = "terraform-examples"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_lambda_function/simple"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_lambda_function_name" {
  description = "the name of your stack, e.g. \"demo\""
  default     = "lambda-example"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_lambda_function_runtime" {
  description = "the runtime environment of your function"
  default     = "nodejs12.x"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_lambda_function_zip" {
  description = "the zip file containing your code for your lambda function"
  default     = "lambda_function_payload.zip"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_lambda_function_handler" {
  description = "the name of the handler function"
  default     = "main.handler"
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role
resource "aws_iam_role" "changeme_lambda_function_iam_role" {
  name = "${var.changeme_lambda_function_name}-lambda-role"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_lambda_function" "changeme_lambda_function" {
  filename      = var.changeme_lambda_function_zip
  function_name = var.changeme_lambda_function_name
  role          = aws_iam_role.changeme_lambda_function_iam_role.arn
  handler       = var.changeme_lambda_function_handler

  # The filebase64sha256() function is available in Terraform 0.11.12 and later
  # For Terraform 0.11.11 and earlier, use the base64sha256() function and the file() function:
  # source_code_hash = "${base64sha256(file("lambda_function_payload.zip"))}"
  source_code_hash = filebase64sha256("${var.changeme_lambda_function_zip}")

  runtime = var.changeme_lambda_function_runtime
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_rds_cluster/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create an RDS Aurora MySQL 1 Cluster instance that does not inherit configuration from the cluster

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region  = "us-east-1"
  profile = "terraform-examples"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_rds_cluster/simple"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_aurora_username" {
  description = "the username for the login credentials to your db"
  default     = "username_example"
}

# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_aurora_password" {
  description = "the password, which must be more than 8 characters long"
  default     = "password_example"
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster
resource "aws_rds_cluster" "changeme_aws_aurora_cluster" {
  # The login credentials are stored as plain-text in the state files
  # https://www.terraform.io/docs/language/state/sensitive-data.html
  # For security, use a secrets manager
  # https://registry.terraform.io/modules/yurymkomarov/rds-aurora-cluster/aws/latest#secretsmanager_secret
  master_username     = var.changeme_aws_aurora_username
  master_password     = var.changeme_aws_aurora_password
  skip_final_snapshot = true
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_route53/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create a simple route53 zone and TXT record

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_route53/simple"
    }
  }
}


# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone
resource "aws_route53_zone" "changeme_aws_route53_simple_zone" {
  name = "changeme.com"
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record
resource "aws_route53_record" "changeme_aws_route53_simple_record" {
  zone_id = aws_route53_zone.changeme_aws_route53_simple_zone.zone_id
  name    = "changeme.com"
  type    = "TXT"
  ttl     = "300"
  records = ["changeme"]
}

 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_s3_bucket/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Create an S3 bucket

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_s3_bucket/simple"
    }
  }
}

# Explanation: This resource is not necessary for the creation of an S3 bucket, but is here to ensure that
# the S3 bucket name is unique.
#
# Documentation: https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id
resource "random_id" "changeme_bucket_name" {
  byte_length = 16
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket
resource "aws_s3_bucket" "changeme_aws_s3_bucket_simple" {
  bucket = "te-${random_id.changeme_bucket_name.hex}"
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_security_group/dynamic/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Uses 'dynamic' to create multiple 'ingress' blocks within an 'aws_security_group' resource.

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_security_group/dynamic"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/values/locals.html
locals {
  ports = [80, 443, 8080]
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_aws_security_group_dynamic" {
  name = "changeme-aws-security-group-dynamic"

  # Documentation: https://www.terraform.io/docs/language/expressions/dynamic-blocks.html
  dynamic "ingress" {
    for_each = local.ports
    content {
      description = "changeme-aws-security-group-dynamic-ingress-${ingress.key}"
      from_port   = ingress.value
      to_port     = ingress.value
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  }
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_security_group/open/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: A completely open security group

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_secrurity_group/open"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_aws_security_group_open" {
  name        = "changeme_aws_security_group_open_name"
  description = "Allow all traffic"
  ingress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_security_group/ssh/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

main.tf

            # Summary: Security group that allows SSH connections

# https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_security_group/ssh"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_aws_security_group_ssh" {
  name        = "changeme_aws_security_group_ssh_name"
  description = "Allow SSH inbound traffic"
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_vpc/count/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

import.sh

            #!/bin/bash

cd "${0%/*}" || exit 1

echo '================================================================================'
echo "In $(pwd), running $0"
echo '================================================================================'

INIT_DONE="N"
VPC_IDS=$(aws ec2 describe-vpcs | jq -r '.Vpcs[] | select(.Tags and .Tags[].Key=="cs_terraform_examples" and .Tags[].Value=="aws_vpc/count") | .VpcId')
count=0
for vpc_id in $VPC_IDS
do
  if [[ ${INIT_DONE} == "N" ]]
  then
    INIT_DONE="Y"
    terraform init
  fi
  terraform import "aws_vpc.changeme_aws_vpc_count[${count}]" "$vpc_id"
  ((count++))
done
 

main.tf

            # Summary: Example of 'for' block

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_vpc/count"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc
resource "aws_vpc" "changeme_aws_vpc_count" {
  count      = 3
  cidr_block = format("172.%d.0.0/16", 16 + count.index)
}

# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_aws_vpc_count_splat" {
  value = aws_vpc.changeme_aws_vpc_count[*].cidr_block
}

# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_aws_vpc_count_for" {
  # Documentation: https://www.terraform.io/docs/language/expressions/for.html
  value = [
    for vpc in aws_vpc.changeme_aws_vpc_count :
    vpc.cidr_block
  ]
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_vpc/for/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

import.sh

            #!/bin/bash

cd "${0%/*}" || exit 1

echo '================================================================================'
echo "In $(pwd), running $0"
echo '================================================================================'

INIT_DONE="N"
VPC_IDS=$(aws ec2 describe-vpcs | jq -r '.Vpcs[] | select(.Tags and .Tags[].Key=="cs_terraform_examples" and .Tags[].Value=="aws_vpc/for") | .VpcId')
count=0
for vpc_id in $VPC_IDS
do
  if [[ ${INIT_DONE} == "N" ]]
  then
    INIT_DONE="Y"
    terraform init
  fi
  terraform import "aws_vpc.changeme_aws_vpc_for[${count}]" "$vpc_id"
  ((count++))
done
 

main.tf

            # Summary: Simple example of a 'for' expression in Terraform

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_vpc/for"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc
resource "aws_vpc" "changeme_aws_vpc_for" {
  # Documentation: https://www.terraform.io/docs/language/meta-arguments/count.html
  count      = 3
  cidr_block = format("172.%d.0.0/16", 16 + count.index)
}

# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_aws_vpc_for_output" {
  # Documentation: https://www.terraform.io/docs/language/expressions/for.html
  value = [
    for vpc in aws_vpc.changeme_aws_vpc_for :
    vpc.cidr_block
  ]
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_vpc/simple/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

import.sh

            #!/bin/bash

cd "${0%/*}" || exit 1

echo '================================================================================'
echo "In $(pwd), running $0"
echo '================================================================================'

INIT_DONE="N"
VPC_IDS=$(aws ec2 describe-vpcs | jq -r '.Vpcs[] | select(.Tags and .Tags[].Key=="cs_terraform_examples" and .Tags[].Value=="aws_vpc/simple") | .VpcId')
count=0
for vpc_id in $VPC_IDS
do
  if [[ ${INIT_DONE} == "N" ]]
  then
    INIT_DONE="Y"
    terraform init
  fi
  terraform import "aws_vpc.changeme_aws_vpc_simple" "$vpc_id"
  ((count++))
done
 

main.tf

            # Summary: Create an AWS VPC

# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_vpc/simple"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc
resource "aws_vpc" "changeme_aws_vpc_simple" {
  cidr_block = "10.1.0.0/16"
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws
 

aws_vpc/splat/

destroy.sh

            #!/bin/bash
../../../bin/destroy.sh aws
 

import.sh

            #!/bin/bash

cd "${0%/*}" || exit 1

echo '================================================================================'
echo "In $(pwd), running $0"
echo '================================================================================'

INIT_DONE="N"
VPC_IDS=$(aws ec2 describe-vpcs | jq -r '.Vpcs[] | select(.Tags and .Tags[].Key=="cs_terraform_examples" and .Tags[].Value=="aws_vpc/splat") | .VpcId')
count=0
for vpc_id in $VPC_IDS
do
  if [[ ${INIT_DONE} == "N" ]]
  then
    INIT_DONE="Y"
    terraform init
  fi
  terraform import "aws_vpc.changeme_aws_vpc_splat[${count}]" "$vpc_id"
  ((count++))
done
 

main.tf

            # Summary: Uses the 'count' feature to create multiple EC2 instances.
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.38"
    }
  }
}

# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = {
      cs_terraform_examples = "aws_vpc/splat"
    }
  }
}

# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc
resource "aws_vpc" "changeme_aws_vpc_splat" {
  # Documentation: # Documentation: https://www.terraform.io/docs/language/meta-arguments/count.html
  count      = 3
  cidr_block = format("172.%d.0.0/16", 16 + count.index)
}

# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_cidr_block_full_splat" {
  # Documentation: https://www.terraform.io/docs/language/expressions/splat.html
  value = aws_vpc.changeme_aws_vpc_splat[*].cidr_block
}
 

run.sh

            #!/bin/bash
../../../bin/apply.sh aws