chore(e2e): Use public version of enos (#4872)
* chore(e2e): Use public version of enos * chore(e2e): Move vault module to this repo terraform-enos-aws-vault is no longer supported
This commit is contained in:
1 parent
d408f65519
commit
333b9e855d
39 files changed
+1046
-44
No files matched your search
@@ -0,0 +1,52 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
data "aws_iam_policy_document" "vault_instance_role" {
|
||||
statement {
|
||||
actions = ["sts:AssumeRole"]
|
||||
|
||||
principals {
|
||||
type = "Service"
|
||||
identifiers = ["ec2.amazonaws.com"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "vault_profile" {
|
||||
statement {
|
||||
resources = ["*"]
|
||||
|
||||
actions = [
|
||||
"ec2:DescribeInstances",
|
||||
"secretsmanager:*"
|
||||
]
|
||||
}
|
||||
|
||||
statement {
|
||||
resources = [var.kms_key_arn]
|
||||
|
||||
actions = [
|
||||
"kms:DescribeKey",
|
||||
"kms:ListKeys",
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:GenerateDataKey"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "vault_instance_role" {
|
||||
name = "vault_instance_role-${random_string.cluster_id.result}"
|
||||
assume_role_policy = data.aws_iam_policy_document.vault_instance_role.json
|
||||
}
|
||||
|
||||
resource "aws_iam_instance_profile" "vault_profile" {
|
||||
name = "vault_instance_profile-${random_string.cluster_id.result}"
|
||||
role = aws_iam_role.vault_instance_role.name
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "vault_policy" {
|
||||
name = "vault_policy-${random_string.cluster_id.result}"
|
||||
role = aws_iam_role.vault_instance_role.id
|
||||
policy = data.aws_iam_policy_document.vault_profile.json
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
data "aws_vpc" "infra" {
|
||||
id = var.vpc_id
|
||||
}
|
||||
|
||||
data "aws_subnets" "infra" {
|
||||
filter {
|
||||
name = "vpc-id"
|
||||
values = [var.vpc_id]
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_caller_identity" "current" {}
|
||||
|
||||
data "aws_kms_key" "kms_key" {
|
||||
key_id = var.kms_key_arn
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
locals {
|
||||
consul_bin_path = "${var.consul_install_dir}/consul"
|
||||
key_shares = {
|
||||
"awskms" = null
|
||||
"shamir" = 5
|
||||
}
|
||||
key_threshold = {
|
||||
"awskms" = null
|
||||
"shamir" = 3
|
||||
}
|
||||
followers = toset(slice(local.instances, 1, length(local.instances)))
|
||||
instances = [for idx in range(var.instance_count) : tostring(idx)]
|
||||
leader = toset(slice(local.instances, 0, 1))
|
||||
name_suffix = "${var.project_name}-${var.environment}"
|
||||
recovery_shares = {
|
||||
"awskms" = 5
|
||||
"shamir" = null
|
||||
}
|
||||
recovery_threshold = {
|
||||
"awskms" = 3
|
||||
"shamir" = null
|
||||
}
|
||||
seal = {
|
||||
"awskms" = {
|
||||
type = "awskms"
|
||||
attributes = {
|
||||
kms_key_id = var.kms_key_arn
|
||||
}
|
||||
}
|
||||
"shamir" = {
|
||||
type = "shamir"
|
||||
attributes = null
|
||||
}
|
||||
}
|
||||
storage_config = [for idx in local.vault_instances : (var.storage_backend == "raft" ?
|
||||
merge(
|
||||
{
|
||||
node_id = "${var.vault_node_prefix}_${idx}"
|
||||
},
|
||||
var.storage_backend_addl_config
|
||||
) :
|
||||
{
|
||||
address = "127.0.0.1:8500"
|
||||
path = "vault"
|
||||
})
|
||||
]
|
||||
vault_bin_path = "${var.vault_install_dir}/vault"
|
||||
vault_cluster_tag = coalesce(var.vault_cluster_tag, "vault-server-${random_string.cluster_id.result}")
|
||||
vault_instances = toset(local.instances)
|
||||
audit_device_file_path = "/var/log/vault/vault_audit.log"
|
||||
vault_service_user = "vault"
|
||||
enable_audit_device = var.enable_file_audit_device && var.vault_init
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
enos = {
|
||||
source = "registry.terraform.io/hashicorp-forge/enos"
|
||||
version = ">= 0.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data "enos_environment" "localhost" {}
|
||||
|
||||
resource "random_string" "cluster_id" {
|
||||
length = 8
|
||||
lower = true
|
||||
upper = false
|
||||
numeric = false
|
||||
special = false
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
output "instance_ids" {
|
||||
description = "IDs of Vault instances"
|
||||
value = [for instance in aws_instance.vault_instance : instance.id]
|
||||
}
|
||||
|
||||
output "instance_public_ips" {
|
||||
description = "Public IPs of Vault instances"
|
||||
value = [for instance in aws_instance.vault_instance : instance.public_ip]
|
||||
}
|
||||
|
||||
output "instance_private_ips" {
|
||||
description = "Private IPs of Vault instances"
|
||||
value = [for instance in aws_instance.vault_instance : instance.private_ip]
|
||||
}
|
||||
|
||||
output "key_id" {
|
||||
value = data.aws_kms_key.kms_key.id
|
||||
}
|
||||
|
||||
output "vault_instances" {
|
||||
description = "The vault cluster instances that were created"
|
||||
|
||||
value = {
|
||||
for instance in aws_instance.vault_instance : instance.id => {
|
||||
public_ip = instance.public_ip
|
||||
private_ip = instance.private_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output "vault_root_token" {
|
||||
value = coalesce(var.vault_root_token, try(enos_vault_init.leader[0].root_token, null), "none")
|
||||
}
|
||||
|
||||
output "vault_unseal_keys_b64" {
|
||||
value = try(enos_vault_init.leader[0].unseal_keys_b64, [])
|
||||
}
|
||||
|
||||
output "vault_unseal_keys_hex" {
|
||||
value = try(enos_vault_init.leader[0].unseal_keys_hex, null)
|
||||
}
|
||||
|
||||
output "vault_unseal_shares" {
|
||||
value = try(enos_vault_init.leader[0].unseal_keys_shares, -1)
|
||||
}
|
||||
|
||||
output "vault_unseal_threshold" {
|
||||
value = try(enos_vault_init.leader[0].unseal_keys_threshold, -1)
|
||||
}
|
||||
|
||||
output "vault_recovery_keys_b64" {
|
||||
value = try(enos_vault_init.leader[0].recovery_keys_b64, [])
|
||||
}
|
||||
|
||||
output "vault_recovery_keys_hex" {
|
||||
value = try(enos_vault_init.leader[0].recovery_keys_hex, [])
|
||||
}
|
||||
|
||||
output "vault_recovery_key_shares" {
|
||||
value = try(enos_vault_init.leader[0].recovery_keys_shares, -1)
|
||||
}
|
||||
|
||||
output "vault_recovery_threshold" {
|
||||
value = try(enos_vault_init.leader[0].recovery_keys_threshold, -1)
|
||||
}
|
||||
|
||||
output "vault_cluster_tag" {
|
||||
description = "Cluster tag for Vault cluster"
|
||||
value = local.vault_cluster_tag
|
||||
}
|
||||
|
||||
output "audit_device_log_file_path" {
|
||||
description = "The path of the file audit device path, if enabled"
|
||||
value = var.enable_file_audit_device ? local.audit_device_file_path : "no audit devices enabled"
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
set -eux
|
||||
|
||||
LOG_DIR=$(dirname "$LOG_FILE_PATH")
|
||||
|
||||
function retry {
|
||||
local retries=$1
|
||||
shift
|
||||
local count=0
|
||||
|
||||
until "$@"; do
|
||||
exit=$?
|
||||
wait=10
|
||||
count=$((count + 1))
|
||||
|
||||
if [ "$count" -lt "$retries" ]; then
|
||||
sleep "$wait"
|
||||
else
|
||||
return "$exit"
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Strangely, sometimes the service user has not been created yet. This retry awaits the creation of the user
|
||||
retry 7 id -a "$SERVICE_USER"
|
||||
|
||||
sudo mkdir -p "$LOG_DIR"
|
||||
sudo chown -R "$SERVICE_USER":"$SERVICE_USER" "$LOG_DIR"
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/env sh
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
set -eux
|
||||
|
||||
$VAULT_BIN_PATH audit enable file file_path="$LOG_FILE_PATH"
|
||||
@@ -0,0 +1,74 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
resource "aws_security_group" "enos_vault_sg" {
|
||||
name = "vault-sg-${random_string.cluster_id.result}"
|
||||
description = "SSH and Vault Traffic"
|
||||
vpc_id = var.vpc_id
|
||||
|
||||
# SSH
|
||||
ingress {
|
||||
from_port = 22
|
||||
to_port = 22
|
||||
protocol = "tcp"
|
||||
cidr_blocks = flatten([
|
||||
formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
|
||||
join(",", data.aws_vpc.infra.cidr_block_associations.*.cidr_block),
|
||||
])
|
||||
}
|
||||
|
||||
# Vault traffic
|
||||
ingress {
|
||||
from_port = 8200
|
||||
to_port = 8201
|
||||
protocol = "tcp"
|
||||
cidr_blocks = flatten([
|
||||
formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
|
||||
join(",", data.aws_vpc.infra.cidr_block_associations.*.cidr_block),
|
||||
formatlist("%s/32", var.sg_additional_ips),
|
||||
])
|
||||
}
|
||||
|
||||
# Consul Agent traffic
|
||||
ingress {
|
||||
from_port = 8301
|
||||
to_port = 8301
|
||||
protocol = "tcp"
|
||||
cidr_blocks = flatten([
|
||||
formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
|
||||
join(",", data.aws_vpc.infra.cidr_block_associations.*.cidr_block),
|
||||
])
|
||||
}
|
||||
|
||||
ingress {
|
||||
from_port = 8301
|
||||
to_port = 8301
|
||||
protocol = "udp"
|
||||
cidr_blocks = flatten([
|
||||
formatlist("%s/32", data.enos_environment.localhost.public_ipv4_addresses),
|
||||
join(",", data.aws_vpc.infra.cidr_block_associations.*.cidr_block),
|
||||
])
|
||||
}
|
||||
|
||||
# Internal Traffic
|
||||
ingress {
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
self = true
|
||||
}
|
||||
|
||||
egress {
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
tags = merge(
|
||||
var.common_tags,
|
||||
{
|
||||
Name = "${local.name_suffix}-vault-sg"
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
set -ex -o pipefail
|
||||
|
||||
deps="${dependencies}"
|
||||
|
||||
if [ "$deps" == "" ]
|
||||
then
|
||||
echo "No dependencies to install."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
function retry {
|
||||
local retries=$1
|
||||
shift
|
||||
local count=0
|
||||
|
||||
until "$@"; do
|
||||
exit=$?
|
||||
wait=$((2 ** count))
|
||||
count=$((count + 1))
|
||||
if [ "$count" -lt "$retries" ]; then
|
||||
sleep "$wait"
|
||||
else
|
||||
return "$exit"
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
echo "Installing Dependencies: $deps"
|
||||
if [ -f /etc/debian_version ]; then
|
||||
# Make sure cloud-init is not modifying our sources list while we're trying
|
||||
# to install.
|
||||
retry 7 grep ec2 /etc/apt/sources.list
|
||||
|
||||
cd /tmp
|
||||
retry 5 sudo apt update
|
||||
retry 5 sudo apt install -y $${deps[@]}
|
||||
else
|
||||
cd /tmp
|
||||
retry 7 sudo yum -y install $${deps[@]}
|
||||
fi
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
license='${vault_license}'
|
||||
if test $license = "none"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
function retry {
|
||||
local retries=$1
|
||||
shift
|
||||
local count=0
|
||||
|
||||
until "$@"; do
|
||||
exit=$?
|
||||
wait=$((2 ** count))
|
||||
count=$((count + 1))
|
||||
|
||||
if [ "$count" -lt "$retries" ]; then
|
||||
sleep "$wait"
|
||||
else
|
||||
return "$exit"
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
export VAULT_ADDR=http://localhost:8200
|
||||
export VAULT_TOKEN='${vault_root_token}'
|
||||
|
||||
# Temporary hack until we can make the unseal resource handle legacy license
|
||||
# setting. If we're running 1.8 and above then we shouldn't try to set a license.
|
||||
ver=$(${vault_bin_path} version)
|
||||
if [[ "$(echo "$ver" |awk '{print $2}' |awk -F'.' '{print $2}')" -ge 8 ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
retry 5 ${vault_bin_path} write /sys/license text="$license"
|
||||
@@ -0,0 +1,255 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
variable "ami_id" {
|
||||
description = "AMI from enos-infra"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "common_tags" {
|
||||
description = "Tags to set for all resources"
|
||||
type = map(string)
|
||||
default = { "Project" : "Enos" }
|
||||
}
|
||||
|
||||
variable "consul_cluster_tag" {
|
||||
type = string
|
||||
description = "cluster tag for consul cluster"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "consul_data_dir" {
|
||||
type = string
|
||||
description = "The directory where the consul will store data"
|
||||
default = "/opt/consul/data"
|
||||
}
|
||||
|
||||
variable "consul_install_dir" {
|
||||
type = string
|
||||
description = "The directory where the consul binary will be installed"
|
||||
default = "/opt/consul/bin"
|
||||
}
|
||||
|
||||
variable "consul_license" {
|
||||
type = string
|
||||
description = "The license to use for Consul Enterprise"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "consul_log_dir" {
|
||||
type = string
|
||||
description = "The directory where the consul will write log output"
|
||||
default = "/var/log/consul.d"
|
||||
}
|
||||
|
||||
variable "consul_log_level" {
|
||||
type = string
|
||||
description = "The consul service log level"
|
||||
default = "INFO"
|
||||
}
|
||||
|
||||
variable "consul_release" {
|
||||
type = object({
|
||||
version = string
|
||||
edition = string
|
||||
})
|
||||
description = "Consul release version and edition to install from releases.hashicorp.com"
|
||||
default = {
|
||||
version = "1.15.3"
|
||||
edition = "oss"
|
||||
}
|
||||
}
|
||||
|
||||
variable "dependencies_to_install" {
|
||||
type = list(string)
|
||||
description = "A list of dependencies to install"
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "environment" {
|
||||
description = "Name of the environment."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "instance_count" {
|
||||
description = "Number of EC2 instances in each subnet"
|
||||
type = number
|
||||
default = 3
|
||||
}
|
||||
|
||||
variable "instance_type" {
|
||||
description = "EC2 Instance"
|
||||
type = string
|
||||
default = "t2.micro"
|
||||
}
|
||||
|
||||
variable "kms_key_arn" {
|
||||
type = string
|
||||
description = "ARN of KMS Key from enos-infra"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "manage_service" {
|
||||
type = bool
|
||||
description = "Manage the service users and systemd"
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "project_name" {
|
||||
description = "Name of the project."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "sg_additional_ips" {
|
||||
description = "A list of additional IPs to allow by Vault security groups (use with caution)"
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "ssh_aws_keypair" {
|
||||
description = "SSH keypair used to connect to EC2 instances"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "storage_backend" {
|
||||
type = string
|
||||
description = "The type of Vault storage backend which will be used"
|
||||
default = "raft"
|
||||
|
||||
validation {
|
||||
condition = contains(["raft", "consul"], var.storage_backend)
|
||||
error_message = "The \"storage_backend\" must be one of: [raft|consul]."
|
||||
}
|
||||
}
|
||||
|
||||
variable "storage_backend_addl_config" {
|
||||
type = map(any)
|
||||
description = "A set of key value pairs to inject into the storage block"
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "unseal_method" {
|
||||
type = string
|
||||
description = "The method by which to unseal the Vault cluster"
|
||||
default = "awskms"
|
||||
|
||||
validation {
|
||||
condition = contains(["awskms", "shamir"], var.unseal_method)
|
||||
error_message = "The unseal_method must be one of 'awskms or 'shamir'."
|
||||
}
|
||||
}
|
||||
|
||||
variable "vault_artifactory_release" {
|
||||
type = object({
|
||||
username = string
|
||||
token = string
|
||||
url = string
|
||||
sha256 = string
|
||||
})
|
||||
description = "Vault release version and edition to install from artifactory.hashicorp.engineering"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "vault_cluster_tag" {
|
||||
type = string
|
||||
description = "Cluster tag for Vault cluster"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "vault_config_dir" {
|
||||
type = string
|
||||
description = "The directory to use for Vault configuration"
|
||||
default = "/etc/vault.d"
|
||||
}
|
||||
|
||||
variable "vault_init" {
|
||||
type = bool
|
||||
description = "Initialize the Vault cluster"
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "vault_install_dir" {
|
||||
type = string
|
||||
description = "The directory where the vault binary will be installed"
|
||||
default = "/opt/vault/bin"
|
||||
}
|
||||
|
||||
variable "vault_license" {
|
||||
type = string
|
||||
sensitive = true
|
||||
description = "vault license"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "vault_local_artifact_path" {
|
||||
type = string
|
||||
description = "The path to a locally built vault artifact to install"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "vault_log_dir" {
|
||||
type = string
|
||||
description = "The directory to use for Vault logs"
|
||||
default = "/var/log/vault.d"
|
||||
}
|
||||
|
||||
variable "vault_log_level" {
|
||||
type = string
|
||||
description = "The vault service log level"
|
||||
default = "info"
|
||||
|
||||
validation {
|
||||
condition = contains(["trace", "debug", "info", "warn", "error"], var.vault_log_level)
|
||||
error_message = "The vault_log_level must be one of 'trace', 'debug', 'info', 'warn', or 'error'."
|
||||
}
|
||||
}
|
||||
|
||||
variable "vault_node_prefix" {
|
||||
type = string
|
||||
description = "The vault node prefix"
|
||||
default = "node"
|
||||
}
|
||||
|
||||
variable "vault_release" {
|
||||
type = object({
|
||||
version = string
|
||||
edition = string
|
||||
})
|
||||
description = "Vault release version and edition to install from releases.hashicorp.com"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "vault_root_token" {
|
||||
type = string
|
||||
description = "Vault root token"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "vault_unseal_when_no_init" {
|
||||
type = bool
|
||||
description = "Unseal the Vault manually even if we're not initializing it"
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "vault_unseal_keys" {
|
||||
type = list(string)
|
||||
description = "Vault unseal keys to use for shamir unseal, usually only for already initialized clusters"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "vpc_id" {
|
||||
description = "VPC ID from enos-infra"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "vault_environment" {
|
||||
description = "Optional environment variables to set when running the vault service"
|
||||
type = map(string)
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "enable_file_audit_device" {
|
||||
description = "If true the file audit device will be enabled at the path /var/log/vault/vault_audit.log"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
resource "aws_instance" "vault_instance" {
|
||||
for_each = local.vault_instances
|
||||
ami = var.ami_id
|
||||
instance_type = var.instance_type
|
||||
vpc_security_group_ids = [aws_security_group.enos_vault_sg.id]
|
||||
subnet_id = tolist(data.aws_subnets.infra.ids)[each.key % length(data.aws_subnets.infra.ids)]
|
||||
key_name = var.ssh_aws_keypair
|
||||
iam_instance_profile = aws_iam_instance_profile.vault_profile.name
|
||||
tags = merge(
|
||||
var.common_tags,
|
||||
{
|
||||
Name = "${local.name_suffix}-vault-${var.vault_node_prefix}-${each.key}"
|
||||
Type = local.vault_cluster_tag
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
resource "enos_remote_exec" "install_dependencies" {
|
||||
depends_on = [aws_instance.vault_instance]
|
||||
for_each = toset([
|
||||
for idx in local.vault_instances : idx
|
||||
if length(var.dependencies_to_install) > 0
|
||||
])
|
||||
|
||||
content = templatefile("${path.module}/templates/install-dependencies.sh", {
|
||||
dependencies = join(" ", var.dependencies_to_install)
|
||||
})
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[each.value].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_bundle_install" "consul" {
|
||||
for_each = {
|
||||
for idx, instance in aws_instance.vault_instance : idx => instance
|
||||
if var.storage_backend == "consul"
|
||||
}
|
||||
|
||||
destination = var.consul_install_dir
|
||||
release = merge(var.consul_release, { product = "consul" })
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = each.value.public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_bundle_install" "vault" {
|
||||
for_each = aws_instance.vault_instance
|
||||
|
||||
destination = var.vault_install_dir
|
||||
release = var.vault_release == null ? var.vault_release : merge({ product = "vault" }, var.vault_release)
|
||||
artifactory = var.vault_artifactory_release
|
||||
path = var.vault_local_artifact_path
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = each.value.public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_consul_start" "consul" {
|
||||
for_each = enos_bundle_install.consul
|
||||
|
||||
bin_path = local.consul_bin_path
|
||||
data_dir = var.consul_data_dir
|
||||
config = {
|
||||
data_dir = var.consul_data_dir
|
||||
datacenter = "dc1"
|
||||
retry_join = ["provider=aws tag_key=Type tag_value=${var.consul_cluster_tag}"]
|
||||
server = false
|
||||
bootstrap_expect = 0
|
||||
license = var.consul_license
|
||||
log_level = var.consul_log_level
|
||||
log_file = var.consul_log_dir
|
||||
}
|
||||
license = var.consul_license
|
||||
unit_name = "consul"
|
||||
username = "consul"
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[each.key].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_vault_start" "leader" {
|
||||
depends_on = [
|
||||
enos_consul_start.consul,
|
||||
enos_bundle_install.vault,
|
||||
]
|
||||
for_each = local.leader
|
||||
|
||||
bin_path = local.vault_bin_path
|
||||
config_dir = var.vault_config_dir
|
||||
manage_service = var.manage_service
|
||||
config = {
|
||||
api_addr = "http://${aws_instance.vault_instance[each.key].private_ip}:8200"
|
||||
cluster_addr = "http://${aws_instance.vault_instance[each.key].private_ip}:8201"
|
||||
cluster_name = local.vault_cluster_tag
|
||||
listener = {
|
||||
type = "tcp"
|
||||
attributes = {
|
||||
address = "0.0.0.0:8200"
|
||||
tls_disable = "true"
|
||||
}
|
||||
}
|
||||
log_level = var.vault_log_level
|
||||
storage = {
|
||||
type = var.storage_backend
|
||||
attributes = ({ for key, value in local.storage_config[each.key] : key => value })
|
||||
}
|
||||
seal = local.seal[var.unseal_method]
|
||||
ui = true
|
||||
}
|
||||
license = var.vault_license
|
||||
unit_name = "vault"
|
||||
username = local.vault_service_user
|
||||
|
||||
environment = var.vault_environment
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[each.key].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_vault_start" "followers" {
|
||||
depends_on = [
|
||||
enos_vault_start.leader,
|
||||
]
|
||||
for_each = local.followers
|
||||
|
||||
bin_path = local.vault_bin_path
|
||||
config_dir = var.vault_config_dir
|
||||
manage_service = var.manage_service
|
||||
config = {
|
||||
api_addr = "http://${aws_instance.vault_instance[each.key].private_ip}:8200"
|
||||
cluster_addr = "http://${aws_instance.vault_instance[each.key].private_ip}:8201"
|
||||
cluster_name = local.vault_cluster_tag
|
||||
log_level = var.vault_log_level
|
||||
listener = {
|
||||
type = "tcp"
|
||||
attributes = {
|
||||
address = "0.0.0.0:8200"
|
||||
tls_disable = "true"
|
||||
}
|
||||
}
|
||||
storage = {
|
||||
type = var.storage_backend
|
||||
attributes = { for key, value in local.storage_config[each.key] : key => value }
|
||||
}
|
||||
seal = local.seal[var.unseal_method]
|
||||
ui = true
|
||||
}
|
||||
license = var.vault_license
|
||||
unit_name = "vault"
|
||||
username = local.vault_service_user
|
||||
|
||||
environment = var.vault_environment
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[each.key].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_vault_init" "leader" {
|
||||
depends_on = [enos_vault_start.followers]
|
||||
for_each = toset([
|
||||
for idx in local.leader : idx
|
||||
if var.vault_init
|
||||
])
|
||||
|
||||
bin_path = local.vault_bin_path
|
||||
vault_addr = enos_vault_start.leader[0].config.api_addr
|
||||
|
||||
key_shares = local.key_shares[var.unseal_method]
|
||||
key_threshold = local.key_threshold[var.unseal_method]
|
||||
|
||||
recovery_shares = local.recovery_shares[var.unseal_method]
|
||||
recovery_threshold = local.recovery_threshold[var.unseal_method]
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[0].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_vault_unseal" "leader" {
|
||||
depends_on = [
|
||||
enos_vault_start.followers,
|
||||
enos_vault_init.leader,
|
||||
]
|
||||
for_each = enos_vault_init.leader // only unseal the leader if we initialized it
|
||||
bin_path = local.vault_bin_path
|
||||
vault_addr = enos_vault_start.leader[each.key].config.api_addr
|
||||
seal_type = var.unseal_method
|
||||
unseal_keys = var.unseal_method != "shamir" ? null : coalesce(var.vault_unseal_keys, enos_vault_init.leader[0].unseal_keys_hex)
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[0].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# We need to ensure that the directory used for audit logs is present and accessible to the vault
|
||||
# user on all nodes, since logging will only happen on the leader.
|
||||
resource "enos_remote_exec" "create_audit_log_dir" {
|
||||
depends_on = [
|
||||
enos_vault_unseal.leader,
|
||||
]
|
||||
for_each = toset([
|
||||
for idx in local.vault_instances : idx
|
||||
if var.enable_file_audit_device
|
||||
])
|
||||
|
||||
environment = {
|
||||
LOG_FILE_PATH = local.audit_device_file_path
|
||||
SERVICE_USER = local.vault_service_user
|
||||
}
|
||||
|
||||
scripts = [abspath("${path.module}/scripts/create_audit_log_dir.sh")]
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[each.value].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_remote_exec" "init_audit_device" {
|
||||
depends_on = [
|
||||
enos_remote_exec.create_audit_log_dir,
|
||||
enos_vault_unseal.leader,
|
||||
]
|
||||
for_each = toset([
|
||||
for idx in local.leader : idx
|
||||
if local.enable_audit_device
|
||||
])
|
||||
|
||||
environment = {
|
||||
VAULT_TOKEN = enos_vault_init.leader[each.key].root_token
|
||||
VAULT_ADDR = "http://127.0.0.1:8200"
|
||||
VAULT_BIN_PATH = local.vault_bin_path
|
||||
LOG_FILE_PATH = local.audit_device_file_path
|
||||
SERVICE_USER = local.vault_service_user
|
||||
}
|
||||
|
||||
scripts = [
|
||||
abspath("${path.module}/scripts/enable_audit_logging.sh"),
|
||||
]
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[each.key].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_vault_unseal" "followers" {
|
||||
depends_on = [
|
||||
enos_vault_init.leader,
|
||||
enos_vault_unseal.leader,
|
||||
]
|
||||
// Only unseal followers if we're not using an auto-unseal method and we've
|
||||
// initialized the cluster
|
||||
for_each = {
|
||||
for idx, follower in local.followers : idx => follower
|
||||
if var.unseal_method == "shamir" && var.vault_init
|
||||
}
|
||||
bin_path = local.vault_bin_path
|
||||
vault_addr = enos_vault_start.followers[each.key].config.api_addr
|
||||
seal_type = var.unseal_method
|
||||
unseal_keys = var.unseal_method != "shamir" ? null : coalesce(var.vault_unseal_keys, enos_vault_init.leader[0].unseal_keys_hex)
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[0].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unseal everything when we're not initializing and unseal when not init is set.
|
||||
// This flag is intended to handle cases when you're adding additional nodes to
|
||||
// an existing cluster to use auto-pilot to upgrade them and they're not using
|
||||
// an auto-unseal method.
|
||||
resource "enos_vault_unseal" "when_vault_unseal_when_no_init_is_set" {
|
||||
depends_on = [enos_vault_start.followers]
|
||||
for_each = toset([
|
||||
for idx in local.instances : idx
|
||||
if var.vault_unseal_when_no_init && !var.vault_init
|
||||
])
|
||||
|
||||
bin_path = local.vault_bin_path
|
||||
vault_addr = "http://localhost:8200"
|
||||
seal_type = var.unseal_method
|
||||
unseal_keys = coalesce(
|
||||
var.vault_unseal_keys,
|
||||
try(enos_vault_init.leader[0].unseal_keys_hex, null),
|
||||
)
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[each.key].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_remote_exec" "vault_write_license" {
|
||||
count = var.vault_init ? 1 : 0
|
||||
depends_on = [
|
||||
enos_vault_unseal.leader,
|
||||
enos_vault_unseal.when_vault_unseal_when_no_init_is_set,
|
||||
]
|
||||
|
||||
content = templatefile("${path.module}/templates/vault-write-license.sh", {
|
||||
vault_bin_path = local.vault_bin_path,
|
||||
vault_root_token = coalesce(var.vault_root_token, try(enos_vault_init.leader[0].root_token, null), "none")
|
||||
vault_license = coalesce(var.vault_license, "none")
|
||||
})
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = aws_instance.vault_instance[0].public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user