diff --git a/CHANGELOG.md b/CHANGELOG.md index 092bd274..bdcf72a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Modules +* `iam-instance-profile`: Abstract the usage pattern of IAM instance profile. + ### Examples @@ -40,7 +42,6 @@ * `load-asg`: updated to use new `autoscaling-policy-metric-alarm-pair` module - # v0.9.0 ### Summary diff --git a/examples/bastion-test/tester.tf b/examples/bastion-test/tester.tf new file mode 100644 index 00000000..785f6521 --- /dev/null +++ b/examples/bastion-test/tester.tf @@ -0,0 +1,37 @@ +variable "region" { + description = "The region to put resources in" + default = "us-east-1" +} + +variable "az" { + description = "The availability zone to put resources in" + default = "us-east-1c" +} + +variable "key_name" { + description = "The keypair used to ssh into the asg intances" + default = "shida-east-1" +} + +provider "aws" { + region = var.region +} + +module "vpc" { + source = "../../modules/vpc-scenario-1" + azs = [var.az] + name_prefix = "bastion-test" + cidr = "192.168.0.0/16" + public_subnet_cidrs = ["192.168.0.0/16"] + region = var.region + map_on_launch = false +} + +module "bastion" { + source = "../../modules/bastion" + region = var.region + key_name = var.key_name + public_subnet_id = module.vpc.public_subnet_ids[0] + identifier = "test" + vpc_id = module.vpc.vpc_id +} diff --git a/examples/nexus-asg/nexus.tf b/examples/nexus-asg/nexus.tf index c6fdaef5..2254b70c 100644 --- a/examples/nexus-asg/nexus.tf +++ b/examples/nexus-asg/nexus.tf @@ -16,16 +16,17 @@ variable "region" { description = "The region to put resources in" - default = "us-east-1" + default = "us-east-2" } variable "az" { description = "The availability zone to put resources in" - default = "us-east-1a" + default = "us-east-2b" } variable "key_name" { description = "The keypair used to ssh into the asg intances" + default = "shida-east-2" } module "vpc" { diff --git a/examples/single-node-asg-test/tester.tf b/examples/single-node-asg-test/tester.tf new file mode 100644 index 00000000..e17bb05a --- /dev/null +++ b/examples/single-node-asg-test/tester.tf @@ -0,0 +1,65 @@ +variable "region" { + description = "The region to put resources in" + default = "us-east-1" +} + +variable "az" { + description = "The availability zone to put resources in" + default = "us-east-1c" +} + +variable "key_name" { + description = "The keypair used to ssh into the asg intances" + default = "shida-east-1" +} + +provider "aws" { + region = var.region +} + +module "vpc" { + source = "../../modules/vpc-scenario-1" + azs = [var.az] + name_prefix = "eiptest" + cidr = "192.168.0.0/16" + public_subnet_cidrs = ["192.168.0.0/16"] + region = var.region + map_on_launch = false +} + +module "snasg" { + source = "../../modules/single-node-asg" + name_prefix = "unit" + name_suffix = "eiptest" + ami = module.ubuntu-ami.id + instance_type = "t2.micro" + region = var.region + key_name = var.key_name + subnet_id = module.vpc.public_subnet_ids[0] + security_group_ids = [aws_security_group.eiptest.id] + assign_eip = false # true case is tested in bastion-test example +} + +module "ubuntu-ami" { + source = "../../modules/ami-ubuntu" + release = "16.04" +} + +resource "aws_security_group" "eiptest" { + name = "eiptest" + vpc_id = module.vpc.vpc_id + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} diff --git a/modules/bastion/README.md b/modules/bastion/README.md new file mode 100644 index 00000000..db23197a --- /dev/null +++ b/modules/bastion/README.md @@ -0,0 +1,3 @@ +# SSH Bastion + +This is a module to provide a bastion to access the inside of a VPC from Internet. diff --git a/modules/bastion/main.tf b/modules/bastion/main.tf new file mode 100644 index 00000000..8f75333d --- /dev/null +++ b/modules/bastion/main.tf @@ -0,0 +1,73 @@ +variable "vpc_id" { + type = string + description = "ID of the VPC." +} + +variable "identifier" { + type = string + description = "Identifier of related resources." +} + +variable "region" { + type = string + description = "AWS region for this bastion to be in." +} + +variable "key_name" { + type = string + description = "SSH key pair name for the bastion." +} + +variable "public_subnet_id" { + type = string + description = "The subnet for the bastion. The subnet must be able to access Internet." +} + +variable "instance_type" { + type = string + default = "t2.nano" + description = "Bastion instance type." +} + +variable "egress_cidrs" { + type = list(string) + default = ["0.0.0.0/0"] + description = "Egress subnets that bastion can access." +} + +module "instance" { + source = "../single-node-asg" + name_prefix = var.identifier + name_suffix = "bastion" + ami = module.ubuntu-ami.id + instance_type = var.instance_type + region = var.region + key_name = var.key_name + subnet_id = var.public_subnet_id + security_group_ids = [aws_security_group.bastion.id] + assign_eip = true +} + +resource "aws_security_group" "bastion" { + name = "${var.identifier}-bastion" + vpc_id = var.vpc_id + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = var.egress_cidrs + } +} + +module "ubuntu-ami" { + source = "../../modules/ami-ubuntu" + release = "18.04" +} diff --git a/modules/iam-instance-profile/README.md b/modules/iam-instance-profile/README.md new file mode 100644 index 00000000..e1d2db4d --- /dev/null +++ b/modules/iam-instance-profile/README.md @@ -0,0 +1,21 @@ +# IAM Instance Profile + +This module abstracts the useage pattern of IAM instance profile. The caller provides role/policy, and gets profile id to assign to instance. + +Sample usgae: + +``` +module "iam_instance_profile" { + source = "../iam-instance-profile" + assume_role_policy = "${data.aws_iam_policy_document.attach_ebs.json}" + policy = "${data.aws_iam_policy_document.attach_ebs_policy.json}" + name_prefix = "persistent-ebs" +} + +module "server" { + source = "../asg" + iam_profile = "${module.iam_instance_profile.iam_profile_id}" + + # other things here is ignored +} +``` diff --git a/modules/iam-instance-profile/main.tf b/modules/iam-instance-profile/main.tf new file mode 100644 index 00000000..b8178e70 --- /dev/null +++ b/modules/iam-instance-profile/main.tf @@ -0,0 +1,38 @@ +variable "name_prefix" { + description = "Creates a unique name beginning with the specified prefix." +} + +resource "aws_iam_instance_profile" "profile" { + name_prefix = var.name_prefix + role = aws_iam_role.role.name +} + +resource "aws_iam_role" "role" { + name = var.name_prefix + path = "/" + assume_role_policy = <<-EOF + { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Principal": { + "Service": "ec2.amazonaws.com" + }, + "Effect": "Allow", + "Sid": "" + } + ] + } +EOF + +} + +output "iam_role_name" { + value = aws_iam_role.role.name +} + +output "iam_profile_id" { + value = aws_iam_instance_profile.profile.id +} + diff --git a/modules/iam-instance-profile/versions.tf b/modules/iam-instance-profile/versions.tf new file mode 100644 index 00000000..ac97c6ac --- /dev/null +++ b/modules/iam-instance-profile/versions.tf @@ -0,0 +1,4 @@ + +terraform { + required_version = ">= 0.12" +} diff --git a/modules/persistent-ebs/data.tf b/modules/persistent-ebs/data.tf index d82c7d89..c10dc27c 100644 --- a/modules/persistent-ebs/data.tf +++ b/modules/persistent-ebs/data.tf @@ -4,21 +4,7 @@ data "aws_caller_identity" "current" { data "aws_partition" "current" { } -data "aws_iam_policy_document" "attach_ebs" { - statement { - sid = "" - effect = "Allow" - - principals { - type = "Service" - identifiers = ["ec2.amazonaws.com"] - } - - actions = ["sts:AssumeRole"] - } -} - -data "aws_iam_policy_document" "attach_ebs_policy" { +data "aws_iam_policy_document" "attach_ebs_policy_doc" { statement { sid = "" effect = "Allow" @@ -35,3 +21,7 @@ data "aws_iam_policy_document" "attach_ebs_policy" { } } +resource "aws_iam_policy" "attach_ebs_policy" { + name = "attach_ebs" + policy = data.aws_iam_policy_document.attach_ebs_policy_doc.json +} diff --git a/modules/persistent-ebs/iam.tf b/modules/persistent-ebs/iam.tf deleted file mode 100644 index 916432b1..00000000 --- a/modules/persistent-ebs/iam.tf +++ /dev/null @@ -1,19 +0,0 @@ -resource "aws_iam_instance_profile" "attach_ebs" { - name = "${var.name_prefix}-${var.az}-attach-ebs" - role = aws_iam_role.attach_ebs.name -} - -# -resource "aws_iam_role" "attach_ebs" { - name = "${var.name_prefix}-${var.az}-attach-ebs" - path = "/" - assume_role_policy = data.aws_iam_policy_document.attach_ebs.json -} - -# -resource "aws_iam_role_policy" "attach_ebs" { - name = "${var.name_prefix}-${var.az}-attach-ebs-${aws_ebs_volume.main.id}" - role = aws_iam_role.attach_ebs.id - policy = data.aws_iam_policy_document.attach_ebs_policy.json -} - diff --git a/modules/persistent-ebs/main.tf b/modules/persistent-ebs/main.tf index 3ae00a09..9020f723 100644 --- a/modules/persistent-ebs/main.tf +++ b/modules/persistent-ebs/main.tf @@ -25,29 +25,9 @@ resource "aws_ebs_volume" "main" { ) } -output "iam_profile_id" { - value = aws_iam_instance_profile.attach_ebs.id - description = "`id` exported from the `aws_iam_instance_profile`" -} - -output "iam_profile_arn" { - value = aws_iam_instance_profile.attach_ebs.arn - description = "`arn` exported from the `aws_iam_instance_profile`" -} - -output "iam_profile_policy_document" { - value = aws_iam_role_policy.attach_ebs.policy - description = "`policy` exported from the `aws_iam_role_policy`" -} - -output "iam_role_arn" { - value = aws_iam_role.attach_ebs.arn - description = "`arn` exported from the `aws_iam_role`" -} - -output "iam_role_name" { - value = aws_iam_role.attach_ebs.name - description = "`name` exported from the `aws_iam_role`" +resource "aws_iam_role_policy_attachment" "attach_ebs" { + role = var.iam_instance_profile_role_name + policy_arn = aws_iam_policy.attach_ebs_policy.arn } output "volume_id" { diff --git a/modules/persistent-ebs/variables.tf b/modules/persistent-ebs/variables.tf index 1e1e9be7..1f70f89a 100644 --- a/modules/persistent-ebs/variables.tf +++ b/modules/persistent-ebs/variables.tf @@ -56,3 +56,7 @@ variable "extra_tags" { type = map(string) } +variable "iam_instance_profile_role_name" { + description = "The role to attach policy needed by this module." + type = string +} diff --git a/modules/single-node-asg/main.tf b/modules/single-node-asg/main.tf index 9e70c6d6..e53f9c48 100644 --- a/modules/single-node-asg/main.tf +++ b/modules/single-node-asg/main.tf @@ -11,17 +11,27 @@ * */ +resource "aws_eip" "eip" { + count = var.assign_eip ? 1 : 0 +} + module "service-data" { - source = "../persistent-ebs" - name_prefix = "${var.name_prefix}-${var.name_suffix}-data" - region = var.region - az = data.aws_subnet.server-subnet.availability_zone - size = var.data_volume_size - iops = var.data_volume_iops - volume_type = var.data_volume_type - encrypted = var.data_volume_encrypted - kms_key_id = var.data_volume_kms_key_id - snapshot_id = var.data_volume_snapshot_id + source = "../persistent-ebs" + name_prefix = "${var.name_prefix}-${var.name_suffix}-data" + region = var.region + az = data.aws_subnet.server-subnet.availability_zone + size = var.data_volume_size + iops = var.data_volume_iops + volume_type = var.data_volume_type + encrypted = var.data_volume_encrypted + kms_key_id = var.data_volume_kms_key_id + snapshot_id = var.data_volume_snapshot_id + iam_instance_profile_role_name = module.instance_profile.iam_role_name +} + +module "instance_profile" { + source = "../iam-instance-profile" + name_prefix = "${var.name_prefix}-${var.name_suffix}" } module "server" { @@ -36,21 +46,21 @@ module "server" { ami = var.ami subnet_ids = [var.subnet_id] azs = [data.aws_subnet.server-subnet.availability_zone] - public_ip = var.public_ip key_name = var.key_name elb_names = var.load_balancers max_nodes = 1 min_nodes = 1 root_volume_type = var.root_volume_type root_volume_size = var.root_volume_size - - # - iam_profile = module.service-data.iam_profile_id + iam_profile = module.instance_profile.iam_profile_id user_data = <