From 021a5b336a99621ad8d7333d0a189c1f712c1bd6 Mon Sep 17 00:00:00 2001 From: matthieu42morin Date: Fri, 1 Mar 2024 03:33:04 +0100 Subject: [PATCH] test implementation --- main.tf | 28 +++++ modules/vpc-secrets/README.md | 33 ++++++ modules/vpc-secrets/aws-vpc/main.tf | 21 ++++ modules/vpc-secrets/aws-vpc/outputs.tf | 17 +++ modules/vpc-secrets/aws-vpc/variables.tf | 48 ++++++++ modules/vpc-secrets/main.tf | 25 ++++ modules/vpc-secrets/outputs.tf | 32 +++++ modules/vpc-secrets/secrets/acm.tf | 12 ++ modules/vpc-secrets/secrets/main.tf | 20 ++++ modules/vpc-secrets/secrets/outputs.tf | 21 ++++ modules/vpc-secrets/secrets/tls.tf | 95 +++++++++++++++ modules/vpc-secrets/secrets/variables.tf | 39 ++++++ modules/vpc-secrets/variables.tf | 32 +++++ modules/vpc-secrets/versions.tf | 15 +++ providers.tf | 13 ++ variables.tf | 144 +++++++++++++++++++++++ 16 files changed, 595 insertions(+) create mode 100644 main.tf create mode 100644 modules/vpc-secrets/README.md create mode 100644 modules/vpc-secrets/aws-vpc/main.tf create mode 100644 modules/vpc-secrets/aws-vpc/outputs.tf create mode 100644 modules/vpc-secrets/aws-vpc/variables.tf create mode 100644 modules/vpc-secrets/main.tf create mode 100644 modules/vpc-secrets/outputs.tf create mode 100644 modules/vpc-secrets/secrets/acm.tf create mode 100644 modules/vpc-secrets/secrets/main.tf create mode 100644 modules/vpc-secrets/secrets/outputs.tf create mode 100644 modules/vpc-secrets/secrets/tls.tf create mode 100644 modules/vpc-secrets/secrets/variables.tf create mode 100644 modules/vpc-secrets/variables.tf create mode 100644 modules/vpc-secrets/versions.tf create mode 100644 providers.tf create mode 100644 variables.tf diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..df8309a --- /dev/null +++ b/main.tf @@ -0,0 +1,28 @@ +module "vpc-secrets" { + source = "./modules/vpc-secrets" + version = "1.0.0" + resource_name_prefix = var.resource_name_prefix +} +module "vault-starter" { + source = "hashicorp/vault-starter/aws" + version = "1.0.0" + vpc_id = var.vpc_id + allowed_inbound_cidrs_lb = var.allowed_inbound_cidrs_lb + allowed_inbound_cidrs_ssh = var.allowed_inbound_cidrs_ssh + vault_version = var.vault_version + leader_tls_servername = var.leader_tls_servername + node_count = var.node_count + kms_key_deletion_window = var.kms_key_deletion_window + user_supplied_iam_role_name = var.user_supplied_iam_role_name + user_supplied_ami_id = var.user_supplied_ami_id + user_supplied_kms_key_arn = var.user_supplied_kms_key_arn + user_supplied_userdata_path = var.user_supplied_userdata_path + lb_certificate_arn = var.lb_certificate_arn + lb_type = var.lb_type + lb_health_check_path = var.lb_health_check_path + resource_name_prefix = var.resource_name_prefix + secrets_manager_arn = var.secrets_manager_arn + private_subnet_tags = var.private_subnet_ids + instance_type = var.instance_type + ssl_policy = var.ssl_policy +} \ No newline at end of file diff --git a/modules/vpc-secrets/README.md b/modules/vpc-secrets/README.md new file mode 100644 index 0000000..7fdf791 --- /dev/null +++ b/modules/vpc-secrets/README.md @@ -0,0 +1,33 @@ +# EXAMPLE: Prerequisite Configuration (VPC and Secrets) + +## About This Example + +In order to deploy the Vault module, you must have an AWS VPC that +meets the requirements [listed in the main +README](../../README.md#how-to-use-this-module) along with TLS certs that can be +used with the Vault nodes and load balancer. If you do not already have these +resources, you can use the code provided in this directory to provision them. + +## How to Use This Module + +1. Ensure your AWS credentials are [configured + correctly](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html) +2. Configure required (and optional if desired) variables +3. Run `terraform init` and `terraform apply` + +## Required variables + +* `resource_name_prefix` - string value to use as base for resource names + +## Note + +- The default AWS region is `us-east-1` (as specified by the `aws_region` + variable). You may change this if wish to deploy Vault elsewhere, but please + be sure to change the value for the `azs` variable as well and specify the + appropriate availability zones for your new region. + +### Security Note: +- The [Terraform State](https://www.terraform.io/docs/language/state/index.html) + produced by this code has sensitive data (cert private keys) stored in it. + Please secure your Terraform state using the [recommendations listed + here](https://www.terraform.io/docs/language/state/sensitive-data.html#recommendations). diff --git a/modules/vpc-secrets/aws-vpc/main.tf b/modules/vpc-secrets/aws-vpc/main.tf new file mode 100644 index 0000000..dcb6670 --- /dev/null +++ b/modules/vpc-secrets/aws-vpc/main.tf @@ -0,0 +1,21 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +module "vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "3.0.0" + name = "${var.resource_name_prefix}-vault" + cidr = var.vpc_cidr + azs = var.azs + enable_nat_gateway = true + one_nat_gateway_per_az = true + private_subnets = var.private_subnet_cidrs + public_subnets = var.public_subnet_cidrs + + tags = var.common_tags +} + diff --git a/modules/vpc-secrets/aws-vpc/outputs.tf b/modules/vpc-secrets/aws-vpc/outputs.tf new file mode 100644 index 0000000..725e7c4 --- /dev/null +++ b/modules/vpc-secrets/aws-vpc/outputs.tf @@ -0,0 +1,17 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +output "private_subnet_ids" { + description = "Private subnet IDs" + value = module.vpc.private_subnets +} + +output "vpc_id" { + description = "The ID of the VPC" + value = module.vpc.vpc_id +} + diff --git a/modules/vpc-secrets/aws-vpc/variables.tf b/modules/vpc-secrets/aws-vpc/variables.tf new file mode 100644 index 0000000..8a672b8 --- /dev/null +++ b/modules/vpc-secrets/aws-vpc/variables.tf @@ -0,0 +1,48 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +variable "azs" { + description = "availability zones to use in AWS region" + type = list(string) +} + +variable "common_tags" { + type = map(string) + description = "Tags for VPC resources" +} + +variable "resource_name_prefix" { + description = "Prefix for resource names (e.g. \"prod\")" + type = string +} + +variable "private_subnet_cidrs" { + description = "CIDR blocks for private subnets" + type = list(string) + default = [ + "10.0.0.0/19", + "10.0.32.0/19", + "10.0.64.0/19", + ] +} + +variable "public_subnet_cidrs" { + description = "CIDR blocks for public subnets" + type = list(string) + default = [ + "10.0.128.0/20", + "10.0.144.0/20", + "10.0.160.0/20", + ] +} + +variable "vpc_cidr" { + description = "CIDR block for VPC" + type = string + default = "10.0.0.0/16" +} + diff --git a/modules/vpc-secrets/main.tf b/modules/vpc-secrets/main.tf new file mode 100644 index 0000000..7d14b18 --- /dev/null +++ b/modules/vpc-secrets/main.tf @@ -0,0 +1,25 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +provider "aws" { + region = var.aws_region +} + +module "vpc" { + source = "./aws-vpc/" + + azs = var.azs + common_tags = var.tags + resource_name_prefix = var.resource_name_prefix +} + +module "secrets" { + source = "./secrets/" + + resource_name_prefix = var.resource_name_prefix +} + diff --git a/modules/vpc-secrets/outputs.tf b/modules/vpc-secrets/outputs.tf new file mode 100644 index 0000000..9865dd5 --- /dev/null +++ b/modules/vpc-secrets/outputs.tf @@ -0,0 +1,32 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +output "lb_certificate_arn" { + description = "ARN of ACM cert to use with Vault LB listener" + value = module.secrets.lb_certificate_arn +} + +output "leader_tls_servername" { + description = "Shared SAN that will be given to the Vault nodes configuration for use as leader_tls_servername" + value = module.secrets.leader_tls_servername +} + +output "private_subnet_ids" { + description = "Private subnet IDs" + value = module.vpc.private_subnet_ids +} + +output "secrets_manager_arn" { + description = "ARN of secrets_manager secret" + value = module.secrets.secrets_manager_arn +} + +output "vpc_id" { + description = "The ID of the VPC" + value = module.vpc.vpc_id +} + diff --git a/modules/vpc-secrets/secrets/acm.tf b/modules/vpc-secrets/secrets/acm.tf new file mode 100644 index 0000000..e43d724 --- /dev/null +++ b/modules/vpc-secrets/secrets/acm.tf @@ -0,0 +1,12 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +resource "aws_acm_certificate" "vault" { + private_key = tls_private_key.server.private_key_pem + certificate_body = tls_locally_signed_cert.server.cert_pem + certificate_chain = tls_self_signed_cert.ca.cert_pem +} diff --git a/modules/vpc-secrets/secrets/main.tf b/modules/vpc-secrets/secrets/main.tf new file mode 100644 index 0000000..57dbc99 --- /dev/null +++ b/modules/vpc-secrets/secrets/main.tf @@ -0,0 +1,20 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +resource "aws_secretsmanager_secret" "tls" { + name = "${var.resource_name_prefix}-tls-secret" + description = "contains TLS certs and private keys" + kms_key_id = var.kms_key_id + recovery_window_in_days = var.recovery_window + tags = var.tags +} + +resource "aws_secretsmanager_secret_version" "tls" { + secret_id = aws_secretsmanager_secret.tls.id + secret_string = local.secret +} + diff --git a/modules/vpc-secrets/secrets/outputs.tf b/modules/vpc-secrets/secrets/outputs.tf new file mode 100644 index 0000000..7a8b181 --- /dev/null +++ b/modules/vpc-secrets/secrets/outputs.tf @@ -0,0 +1,21 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +output "lb_certificate_arn" { + description = "ARN of ACM cert to use with Vault LB listener" + value = aws_acm_certificate.vault.arn +} + +output "leader_tls_servername" { + description = "Shared SAN that will be given to the Vault nodes configuration for use as leader_tls_servername" + value = var.shared_san +} + +output "secrets_manager_arn" { + description = "ARN of secrets_manager secret" + value = aws_secretsmanager_secret.tls.arn +} diff --git a/modules/vpc-secrets/secrets/tls.tf b/modules/vpc-secrets/secrets/tls.tf new file mode 100644 index 0000000..2873839 --- /dev/null +++ b/modules/vpc-secrets/secrets/tls.tf @@ -0,0 +1,95 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +# Generate a private key so you can create a CA cert with it. +resource "tls_private_key" "ca" { + algorithm = "RSA" + rsa_bits = 2048 +} + +# Create a CA cert with the private key you just generated. +resource "tls_self_signed_cert" "ca" { + private_key_pem = tls_private_key.ca.private_key_pem + + subject { + common_name = "ca.vault.server.com" + } + + validity_period_hours = 720 # 30 days + + allowed_uses = [ + "cert_signing", + "crl_signing", + ] + + is_ca_certificate = true + + # provisioner "local-exec" { + # command = "echo '${tls_self_signed_cert.ca.cert_pem}' > ./vault-ca.pem" + # } +} + +# Generate another private key. This one will be used +# To create the certs on your Vault nodes +resource "tls_private_key" "server" { + algorithm = "RSA" + rsa_bits = 2048 + + # provisioner "local-exec" { + # command = "echo '${tls_private_key.server.private_key_pem}' > ./vault-key.pem" + # } +} + +resource "tls_cert_request" "server" { + private_key_pem = tls_private_key.server.private_key_pem + + subject { + common_name = "vault.server.com" + } + + dns_names = [ + var.shared_san, + "localhost", + ] + + ip_addresses = [ + "127.0.0.1", + ] +} + +resource "tls_locally_signed_cert" "server" { + cert_request_pem = tls_cert_request.server.cert_request_pem + ca_private_key_pem = tls_private_key.ca.private_key_pem + ca_cert_pem = tls_self_signed_cert.ca.cert_pem + + validity_period_hours = 720 # 30 days + + allowed_uses = [ + "client_auth", + "digital_signature", + "key_agreement", + "key_encipherment", + "server_auth", + ] + + # provisioner "local-exec" { + # command = "echo '${tls_locally_signed_cert.server.cert_pem}' > ./vault-crt.pem" + # } +} + +locals { + tls_data = { + vault_ca = base64encode(tls_self_signed_cert.ca.cert_pem) + vault_cert = base64encode(tls_locally_signed_cert.server.cert_pem) + vault_pk = base64encode(tls_private_key.server.private_key_pem) + } +} + +locals { + secret = jsonencode(local.tls_data) +} + diff --git a/modules/vpc-secrets/secrets/variables.tf b/modules/vpc-secrets/secrets/variables.tf new file mode 100644 index 0000000..991f6ea --- /dev/null +++ b/modules/vpc-secrets/secrets/variables.tf @@ -0,0 +1,39 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +variable "kms_key_id" { + type = string + description = "Specifies the ARN or ID of the AWS KMS customer master key (CMK) to be used to encrypt the secret values in the versions stored in this secret. If you don't specify this value, then Secrets Manager defaults to using the AWS account's default CMK (the one named aws/secretsmanager" + default = null +} + +variable "recovery_window" { + type = number + description = "Specifies the number of days that AWS Secrets Manager waits before it can delete the secret" + default = 0 +} + +variable "resource_name_prefix" { + type = string + description = "Prefix for resource names (e.g. \"prod\")" +} + +# variable related to TLS cert generation +variable "shared_san" { + type = string + description = "This is a shared server name that the certs for all Vault nodes contain. This is the same value you will supply as input to the Vault installation module for the leader_tls_servername variable." + default = "vault.server.com" +} + +variable "tags" { + type = map(string) + description = "Tags for secrets manager secret" + default = { + Vault = "tls-data" + } +} + diff --git a/modules/vpc-secrets/variables.tf b/modules/vpc-secrets/variables.tf new file mode 100644 index 0000000..90dc12d --- /dev/null +++ b/modules/vpc-secrets/variables.tf @@ -0,0 +1,32 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +variable "aws_region" { + description = "AWS region to deploy resources into" + type = string + default = "eu-north-1" +} + +variable "azs" { + description = "availability zones to use in AWS region" + type = list(string) + default = [ + "eu-north-1a", + "eu-north-1b", + ] +} + +variable "tags" { + type = map(string) + description = "Tags for VPC resources" + default = {} +} + +variable "resource_name_prefix" { + description = "Prefix for resource names in VPC infrastructure" +} + diff --git a/modules/vpc-secrets/versions.tf b/modules/vpc-secrets/versions.tf new file mode 100644 index 0000000..5567e85 --- /dev/null +++ b/modules/vpc-secrets/versions.tf @@ -0,0 +1,15 @@ +/** + * Copyright © 2014-2022 HashiCorp, Inc. + * + * This Source Code is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this project, you can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +terraform { + required_version = ">= 1.2.1" + + required_providers { + aws = ">= 3.0.0, < 4.0.0" + tls = ">= 3.0.0, < 4.0.0" + } +} diff --git a/providers.tf b/providers.tf new file mode 100644 index 0000000..bb73aeb --- /dev/null +++ b/providers.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.38.0" + } + } +} +provider "aws" { + region = var.aws_region + profile = var.aws_profile +} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..75f00e2 --- /dev/null +++ b/variables.tf @@ -0,0 +1,144 @@ +# === General === + +variable "resource_name_prefix" { + type = string + description = "Resource name prefix used for tagging and naming AWS resources" +} + +variable "vault_version" { + type = string + description = "Vault version" + default = "1.15.5" +} + +variable "aws_region" { + type = string + description = "AWS region where Vault will be deployed" + default = "eu-north-1" +} + +variable "aws_profile" { + type = string + description = "The AWS Profile to use for this project." + default = "tf_dev" + +} + + +# === config === + +variable "ami_id" { + type = string + description = "The AMI ID to use for Vault instances" + default = "value" +} +variable "instance_type" { + type = string + description = "The instance type to use for Vault nodes" + default = "t3.micro" +} +variable "lb_type" { + description = "The type of load balancer to provision: network or application." + type = string +} + +variable "node_count" { + type = number + description = "Number of Vault nodes to deploy in ASG" + default = 2 +} + +# === Certs === +variable "ssl_policy" { + type = string + description = "The SSL policy to use for the load balancer" + default = "ELBSecurityPolicy-TLS-1-2-2017-01" +} +variable "secrets_manager_arn" { + type = string + description = "Secrets manager ARN where TLS cert info is stored" +} + +variable "leader_tls_servername" { + type = string + description = "One of the shared DNS SAN used to create the certs use for mTLS" +} + +variable "lb_certificate_arn" { + type = string + description = "ARN of TLS certificate imported into ACM for use with LB listener" +} + +variable "kms_key_deletion_window" { + type = number + description = "The duration in days after which the key is deleted after destruction of the resource" + default = 7 +} + +variable "lb_health_check_path" { + type = string + description = "The path to use for the health check" + default = "/v1/sys/health" +} + +# === VPC === + +variable "allowed_inbound_cidrs_lb" { + type = list(string) + description = "CIDR blocks to allow inbound traffic to the load balancer" + default = ["0.0.0.0/0"] +} + +variable "allowed_inbound_cidrs_ssh" { + type = list(string) + description = "CIDR blocks to allow inbound SSH traffic to the Vault instances" + default = ["0.0.0.0/0"] +} + +variable "vpc_id" { + type = string + description = "VPC ID where Vault will be deployed" +} + +variable "private_subnet_ids" { + type = list(string) + description = "Subnet IDs to deploy Vault into" +} + + + + + + + + + + + + + +# === user supplied variables === + +variable "user_supplied_ami_id" { + type = string + description = "(Optional) User-provided AMI ID to use with Vault instances. If you provide this value, please ensure it will work with the default userdata script (assumes latest version of Ubuntu LTS). Otherwise, please provide your own userdata script using the user_supplied_userdata_path variable." + default = null +} + +variable "user_supplied_iam_role_name" { + type = string + description = "(Optional) User-provided IAM role name. This will be used for the instance profile provided to the AWS launch configuration. The minimum permissions must match the defaults generated by the IAM submodule for cloud auto-join and auto-unseal." + default = null +} + +variable "user_supplied_kms_key_arn" { + type = string + description = "(Optional) User-provided KMS key ARN. Providing this will disable the KMS submodule from generating a KMS key used for Vault auto-unseal" + default = null +} + +variable "user_supplied_userdata_path" { + type = string + description = "(Optional) File path to custom userdata script being supplied by the user" + default = null +}