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:
Michael Li authored and GitHub committed 2024-06-10 11:13:09 -04:00
1 parent d408f65519
commit 333b9e855d
39 files changed
+1046 -44

No files matched your search

+1 -7
View File
@@ -13,17 +13,12 @@ for further information regarding installation, execution or composing Enos scen
## Requirements
* AWS access. HashiCorp Boundary developers should use Doormat.
* Terraform >= 1.0
* Enos >= v0.0.10. You can [install it from a release channel](https://github.com/hashicorp/Enos-Docs/blob/main/installation.md) or use `make tools` install it into `$GOBIN`.
* Access to the QTI org in Terraform Cloud. HashiCorp Boundary developers can
access this token in 1Password or request their own in #team-quality on slack.
* Enos >= v0.0.28 (`brew tap hashicorp/tap && brew update && brew install hashicorp/tap/enos`)
* An SSH keypair in the AWS region you wish to run the scenario. You can use
doormat to login to the AWS console to create or upload an existing keypair.
* Boundary installed locally. `make install` will put it in `$GOPATH/bin`, which
you can use with the `local_boundary_dir` variable, e.g.
`local_boundary_dir = /Users/<user>/.go/bin`.
* For the Bats CLI UI scenarios, you'll need `bats`, `jq` and a valid keychain
configured. Windows and macOS will use the system keychains by default. If
you're using Linux it will default to [pass](https://www.passwordstore.org/).
## Scenarios Variables
In CI, each scenario is executed via Github Actions and has been configured using
@@ -33,7 +28,6 @@ For local execution you can specify all the required variables using environment
variables, or you can update `enos.vars.hcl` with values and uncomment the lines.
Variables that are required:
- `tfc_api_token`
- `aws_ssh_private_key_path`
- `aws_ssh_keypair_name`
- `enos_user`
+1 -1
View File
@@ -104,7 +104,7 @@ module "aws_target" {
}
module "vault" {
source = "app.terraform.io/hashicorp-qti/aws-vault/enos"
source = "./modules/aws_vault"
project_name = "qti-enos-boundary"
environment = var.environment
@@ -161,6 +161,7 @@ scenario "e2e_aws_base_with_vault" {
vault_addr = step.create_vault_cluster.instance_public_ips[0]
vault_root_token = step.create_vault_cluster.vault_root_token
aws_region = var.aws_region
max_page_size = step.create_boundary_cluster.max_page_size
}
}
-5
View File
@@ -119,11 +119,6 @@ variable "boundary_install_dir" {
default = "/opt/boundary/bin"
}
variable "tfc_api_token" {
description = "The Terraform Cloud QTI Organization API token."
type = string
}
variable "vault_instance_type" {
description = "Instance type for test target nodes"
type = string
+1 -5
View File
@@ -3,10 +3,6 @@
terraform_cli "default" {
plugin_cache_dir = abspath("./terraform-plugin-cache")
credentials "app.terraform.io" {
token = var.tfc_api_token
}
}
terraform "default" {
@@ -14,7 +10,7 @@ terraform "default" {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
aws = {
-5
View File
@@ -19,11 +19,6 @@
// the workflow will be used automatically in the CI.
// enos_user = "enos"
// The app.terraform.io API token for the QTI organization. There is a shared
// token for the Boundary team in 1Password, or you can request access to the
// organization by reaching out to the members of #team-quality.
// tfc_api_token = "xxxxxxxx.atlasv1.xxx...."
// The directory that contains the copy of boundary you want to local execution
// from. `make install` should install it into the $GOBIN, which is usually
// similar to what is listed below.
+1 -1
View File
@@ -6,7 +6,7 @@ terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
version = ">= 0.3.25"
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+52
View File
@@ -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
}
+19
View File
@@ -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
}
+56
View File
@@ -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
}
+21
View File
@@ -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
}
+78
View File
@@ -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
View File
@@ -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"
+74
View File
@@ -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"
},
)
}
+46
View File
@@ -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
View File
@@ -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"
+255
View File
@@ -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
}
+341
View File
@@ -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
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
@@ -4,7 +4,7 @@
terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
@@ -4,7 +4,7 @@
terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ terraform {
}
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ terraform {
}
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ terraform {
}
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ terraform {
}
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
@@ -14,7 +14,7 @@ terraform {
}
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ terraform {
}
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ terraform {
}
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ terraform {
}
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ terraform {
}
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
terraform {
required_providers {
enos = {
source = "app.terraform.io/hashicorp-qti/enos"
source = "registry.terraform.io/hashicorp-forge/enos"
}
}
}