mirror of
https://github.com/hashicorp/vault.git
synced 2026-03-27 08:21:21 +01:00
Merge remote-tracking branch 'remotes/from/ce/main'
This commit is contained in:
commit
9c5d1a5cc6
@ -517,7 +517,8 @@ scenario "agent" {
|
||||
module = module.vault_verify_secrets_engines_create
|
||||
depends_on = [
|
||||
step.verify_vault_unsealed,
|
||||
step.get_vault_cluster_ips
|
||||
step.get_vault_cluster_ips,
|
||||
step.set_up_external_integration_target,
|
||||
]
|
||||
|
||||
providers = {
|
||||
|
||||
@ -472,7 +472,8 @@ scenario "seal_ha" {
|
||||
depends_on = [
|
||||
step.create_vault_cluster,
|
||||
step.get_vault_cluster_ips,
|
||||
step.verify_vault_unsealed
|
||||
step.verify_vault_unsealed,
|
||||
step.set_up_external_integration_target,
|
||||
]
|
||||
|
||||
providers = {
|
||||
@ -862,34 +863,6 @@ scenario "seal_ha" {
|
||||
}
|
||||
}
|
||||
|
||||
step "verify_log_secrets" {
|
||||
skip_step = !var.vault_enable_audit_devices || !var.verify_log_secrets
|
||||
|
||||
description = global.description.verify_log_secrets
|
||||
module = module.verify_log_secrets
|
||||
depends_on = [
|
||||
step.verify_secrets_engines_read,
|
||||
]
|
||||
|
||||
providers = {
|
||||
enos = local.enos_provider[matrix.distro]
|
||||
}
|
||||
|
||||
verifies = [
|
||||
quality.vault_audit_log_secrets,
|
||||
quality.vault_journal_secrets,
|
||||
quality.vault_radar_index_create,
|
||||
quality.vault_radar_scan_file,
|
||||
]
|
||||
|
||||
variables {
|
||||
audit_log_file_path = step.create_vault_cluster.audit_device_file_path
|
||||
leader_host = step.get_updated_cluster_ips.leader_host
|
||||
vault_addr = step.create_vault_cluster.api_addr_localhost
|
||||
vault_root_token = step.create_vault_cluster.root_token
|
||||
}
|
||||
}
|
||||
|
||||
step "verify_ui" {
|
||||
description = global.description.verify_ui
|
||||
module = module.vault_verify_ui
|
||||
@ -937,7 +910,6 @@ scenario "seal_ha" {
|
||||
depends_on = [
|
||||
step.wait_for_seal_rewrap,
|
||||
step.verify_secrets_engines_read,
|
||||
step.verify_log_secrets,
|
||||
]
|
||||
|
||||
providers = {
|
||||
@ -1140,6 +1112,34 @@ scenario "seal_ha" {
|
||||
}
|
||||
}
|
||||
|
||||
step "verify_log_secrets" {
|
||||
skip_step = !var.vault_enable_audit_devices || !var.verify_log_secrets
|
||||
|
||||
description = global.description.verify_log_secrets
|
||||
module = module.verify_log_secrets
|
||||
depends_on = [
|
||||
step.verify_secrets_engines_read_after_migration
|
||||
]
|
||||
|
||||
providers = {
|
||||
enos = local.enos_provider[matrix.distro]
|
||||
}
|
||||
|
||||
verifies = [
|
||||
quality.vault_audit_log_secrets,
|
||||
quality.vault_journal_secrets,
|
||||
quality.vault_radar_index_create,
|
||||
quality.vault_radar_scan_file,
|
||||
]
|
||||
|
||||
variables {
|
||||
audit_log_file_path = step.create_vault_cluster.audit_device_file_path
|
||||
leader_host = step.get_updated_cluster_ips.leader_host
|
||||
vault_addr = step.create_vault_cluster.api_addr_localhost
|
||||
vault_root_token = step.create_vault_cluster.root_token
|
||||
}
|
||||
}
|
||||
|
||||
output "audit_device_file_path" {
|
||||
description = "The file path for the file audit device, if enabled"
|
||||
value = step.create_vault_cluster.audit_device_file_path
|
||||
|
||||
89
enos/modules/ldap_wait_for_search/main.tf
Normal file
89
enos/modules/ldap_wait_for_search/main.tf
Normal file
@ -0,0 +1,89 @@
|
||||
# Copyright IBM Corp. 2016, 2025
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
enos = {
|
||||
source = "registry.terraform.io/hashicorp-forge/enos"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "hosts" {
|
||||
description = "The target machines to run the test query from"
|
||||
type = map(object({
|
||||
ipv6 = string
|
||||
private_ip = string
|
||||
public_ip = string
|
||||
}))
|
||||
}
|
||||
|
||||
variable "ldap_base_dn" {
|
||||
type = string
|
||||
description = "The LDAP base dn to search from"
|
||||
}
|
||||
|
||||
variable "ldap_bind_dn" {
|
||||
type = string
|
||||
description = "The LDAP bind dn"
|
||||
}
|
||||
|
||||
variable "ldap_host" {
|
||||
type = object({
|
||||
ipv6 = string
|
||||
private_ip = string
|
||||
public_ip = string
|
||||
})
|
||||
description = "The LDAP host"
|
||||
}
|
||||
|
||||
variable "ldap_password" {
|
||||
type = string
|
||||
description = "The LDAP password"
|
||||
}
|
||||
|
||||
variable "ldap_port" {
|
||||
type = string
|
||||
description = "The LDAP port"
|
||||
}
|
||||
|
||||
variable "ldap_query" {
|
||||
type = string
|
||||
description = "The LDAP query to use when testing the connection"
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "retry_interval" {
|
||||
type = number
|
||||
description = "How many seconds to wait between each retry"
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable "timeout" {
|
||||
type = number
|
||||
description = "The max number of seconds to wait before timing out"
|
||||
default = 60
|
||||
}
|
||||
|
||||
# Wait for the search to succeed
|
||||
resource "enos_remote_exec" "wait_for_search" {
|
||||
for_each = var.hosts
|
||||
|
||||
environment = {
|
||||
LDAP_BASE_DN = var.ldap_base_dn
|
||||
LDAP_BIND_DN = var.ldap_bind_dn
|
||||
LDAP_HOST = var.ldap_host.public_ip
|
||||
LDAP_PASSWORD = var.ldap_password
|
||||
LDAP_PORT = var.ldap_port
|
||||
LDAP_QUERY = var.ldap_query == null ? "" : var.ldap_query
|
||||
RETRY_INTERVAL = var.retry_interval
|
||||
TIMEOUT_SECONDS = var.timeout
|
||||
}
|
||||
scripts = [abspath("${path.module}/scripts/wait-for-search.sh")]
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = each.value.public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
46
enos/modules/ldap_wait_for_search/scripts/wait-for-search.sh
Executable file
46
enos/modules/ldap_wait_for_search/scripts/wait-for-search.sh
Executable file
@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright IBM Corp. 2026
|
||||
# SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
fail() {
|
||||
echo "$1" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ -z "$LDAP_BASE_DN" ]] && fail "LDAP_BASE_DN env variable has not been set"
|
||||
[[ -z "$LDAP_BIND_DN" ]] && fail "LDAP_BIND_DN env variable has not been set"
|
||||
[[ -z "$LDAP_HOST" ]] && fail "LDAP_HOST env variable has not been set"
|
||||
[[ -z "$LDAP_PORT" ]] && fail "LDAP_PORT env variable has not been set"
|
||||
[[ -z "$LDAP_PASSWORD" ]] && fail "LDAP_PASSWORD env variable has not been set"
|
||||
[[ -z "$RETRY_INTERVAL" ]] && fail "RETRY_INTERVAL env variable has not been set"
|
||||
[[ -z "$TIMEOUT_SECONDS" ]] && fail "TIMEOUT_SECONDS env variable has not been set"
|
||||
|
||||
# NOTE: An LDAP_QUERY is not technically required here as long as we have a base
|
||||
# DN and bind DN to search and bind to.
|
||||
|
||||
search="ldap://${LDAP_HOST}:${LDAP_PORT} -b ${LDAP_BASE_DN} -D ${LDAP_BIND_DN} -w ${LDAP_PASSWORD} -s base ${LDAP_QUERY}"
|
||||
safe_search="ldap://${LDAP_HOST}:${LDAP_PORT} -b ${LDAP_BASE_DN} -D ${LDAP_BIND_DN} -s base ${LDAP_QUERY}"
|
||||
echo "Running test search: ${safe_search}"
|
||||
|
||||
begin_time=$(date +%s)
|
||||
end_time=$((begin_time + TIMEOUT_SECONDS))
|
||||
test_search_out=""
|
||||
test_search_res=""
|
||||
declare -i tries=0
|
||||
while [ "$(date +%s)" -lt "$end_time" ]; do
|
||||
tries+=1
|
||||
if test_search_out=$(eval "ldapsearch -x -H ${search}" 2>&1); then
|
||||
test_search_res=0
|
||||
break
|
||||
fi
|
||||
|
||||
test_search_res=$?
|
||||
echo "Test search failed!, search: ${safe_search}, attempt: ${tries}, exit code: ${test_search_res}, error: ${test_search_out}, retrying..."
|
||||
sleep "$RETRY_INTERVAL"
|
||||
done
|
||||
|
||||
if [ "$test_search_res" -ne 0 ]; then
|
||||
echo "Timed out waiting for search!, search: ${safe_search}, attempt: ${tries}, exit code: ${test_search_res}, error: ${test_search_out}" 2>&1
|
||||
# Exit with the ldapsearch exit code so we bubble that up to error diagnostic
|
||||
exit "$test_search_res"
|
||||
fi
|
||||
@ -11,8 +11,10 @@ terraform {
|
||||
|
||||
locals {
|
||||
test_server_address = var.ip_version == "6" ? var.hosts[0].ipv6 : var.hosts[0].public_ip
|
||||
ldap_base_dn = join(",", formatlist("dc=%s", split(".", var.ldap_domain)))
|
||||
ldap_server = {
|
||||
domain = "enos.com"
|
||||
domain = var.ldap_domain
|
||||
base_dn = local.ldap_base_dn
|
||||
org = "hashicorp"
|
||||
admin_pw = "password1"
|
||||
version = var.ldap_version
|
||||
@ -66,19 +68,30 @@ resource "enos_remote_exec" "setup_openldap" {
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the base DN to be available before we populate it
|
||||
module "wait_for_ldap_base_dn" {
|
||||
depends_on = [enos_remote_exec.setup_openldap]
|
||||
source = "../ldap_wait_for_search"
|
||||
|
||||
hosts = var.hosts
|
||||
ldap_base_dn = local.ldap_base_dn
|
||||
ldap_bind_dn = "cn=admin,${local.ldap_base_dn}"
|
||||
ldap_host = local.ldap_server.host
|
||||
ldap_password = local.ldap_server.admin_pw
|
||||
ldap_port = local.ldap_server.port
|
||||
}
|
||||
|
||||
# Populate LDAP server with required users and organizational units
|
||||
resource "enos_remote_exec" "populate_ldap" {
|
||||
depends_on = [enos_remote_exec.setup_openldap]
|
||||
depends_on = [module.wait_for_ldap_base_dn]
|
||||
|
||||
scripts = [abspath("${path.module}/scripts/populate-ldap.sh")]
|
||||
|
||||
environment = {
|
||||
LDAP_SERVER = local.ldap_server.host.private_ip
|
||||
LDAP_PORT = local.ldap_server.port
|
||||
LDAP_ADMIN_PW = local.ldap_server.admin_pw
|
||||
LDAP_DOMAIN = local.ldap_server.domain
|
||||
RETRY_INTERVAL = var.retry_interval
|
||||
TIMEOUT_SECONDS = var.timeout
|
||||
LDAP_SERVER = local.ldap_server.host.private_ip
|
||||
LDAP_PORT = local.ldap_server.port
|
||||
LDAP_ADMIN_PW = local.ldap_server.admin_pw
|
||||
LDAP_BASE_DN = local.ldap_server.base_dn
|
||||
}
|
||||
|
||||
transport = {
|
||||
|
||||
@ -12,68 +12,32 @@ fail() {
|
||||
[[ -z "$LDAP_SERVER" ]] && fail "LDAP_SERVER env variable has not been set"
|
||||
[[ -z "$LDAP_PORT" ]] && fail "LDAP_PORT env variable has not been set"
|
||||
[[ -z "$LDAP_ADMIN_PW" ]] && fail "LDAP_ADMIN_PW env variable has not been set"
|
||||
[[ -z "$LDAP_DOMAIN" ]] && fail "LDAP_DOMAIN env variable has not been set"
|
||||
[[ -z "$RETRY_INTERVAL" ]] && fail "RETRY_INTERVAL env variable has not been set"
|
||||
[[ -z "$TIMEOUT_SECONDS" ]] && fail "TIMEOUT_SECONDS env variable has not been set"
|
||||
|
||||
# Extract domain components from LDAP_DOMAIN (e.g., "enos.com" -> "dc=enos,dc=com")
|
||||
IFS='.' read -ra DOMAIN_PARTS <<< "$LDAP_DOMAIN"
|
||||
DOMAIN_DN=""
|
||||
for part in "${DOMAIN_PARTS[@]}"; do
|
||||
if [[ -n "$DOMAIN_DN" ]]; then
|
||||
DOMAIN_DN="${DOMAIN_DN},dc=${part}"
|
||||
else
|
||||
DOMAIN_DN="dc=${part}"
|
||||
fi
|
||||
done
|
||||
[[ -z "$LDAP_BASE_DN" ]] && fail "LDAP_BASE_DN env variable has not been set"
|
||||
|
||||
echo "OpenLDAP: Checking for OpenLDAP Server Connection: ${LDAP_SERVER}:${LDAP_PORT}"
|
||||
echo "OpenLDAP: Using domain DN: ${DOMAIN_DN}"
|
||||
echo "OpenLDAP: Using base DN: ${LDAP_BASE_DN}"
|
||||
echo "OpenLDAP: Testing connection with admin credentials"
|
||||
|
||||
begin_time=$(date +%s)
|
||||
end_time=$((begin_time + TIMEOUT_SECONDS))
|
||||
test_conn_out=""
|
||||
test_conn_res=""
|
||||
declare -i tries=0
|
||||
while [ "$(date +%s)" -lt "$end_time" ]; do
|
||||
# Test connection
|
||||
tries+=1
|
||||
if test_conn_out=$(ldapsearch -x -H "ldap://${LDAP_SERVER}:${LDAP_PORT}" -b "${DOMAIN_DN}" -D "cn=admin,${DOMAIN_DN}" -w "${LDAP_ADMIN_PW}" -s base 2>&1); then
|
||||
test_conn_res=0
|
||||
break
|
||||
fi
|
||||
|
||||
test_conn_res=$?
|
||||
echo "Unable to connect to ldap://${LDAP_SERVER}:${LDAP_PORT} cn=admin,${DOMAIN_DN}, attempt: ${tries}, exit code: ${test_conn_res}, error: ${test_conn_out}, retrying..."
|
||||
sleep "$RETRY_INTERVAL"
|
||||
done
|
||||
|
||||
if [ "$test_conn_res" -ne 0 ]; then
|
||||
echo "Timed out waiting to connect to ldap://${LDAP_SERVER}:${LDAP_PORT} cn=admin,${DOMAIN_DN}, attempt: ${tries}, exit code: ${test_conn_res}, error: ${test_conn_out}" 2>&1
|
||||
exit "$test_conn_res"
|
||||
fi
|
||||
|
||||
echo "OpenLDAP: Creating organizational units"
|
||||
# Creating Users and Groups Org Units LDIF file
|
||||
OU_LDIF="ou.ldif"
|
||||
cat << EOF > "${OU_LDIF}"
|
||||
dn: ou=users,${DOMAIN_DN}
|
||||
dn: ou=users,${LDAP_BASE_DN}
|
||||
objectClass: organizationalUnit
|
||||
ou: users
|
||||
|
||||
dn: ou=groups,${DOMAIN_DN}
|
||||
dn: ou=groups,${LDAP_BASE_DN}
|
||||
objectClass: organizationalUnit
|
||||
ou: groups
|
||||
EOF
|
||||
|
||||
ldapadd -x -H "ldap://${LDAP_SERVER}:${LDAP_PORT}" -D "cn=admin,${DOMAIN_DN}" -w "${LDAP_ADMIN_PW}" -f "${OU_LDIF}" || echo "OUs may already exist"
|
||||
ldapadd -x -H "ldap://${LDAP_SERVER}:${LDAP_PORT}" -D "cn=admin,${LDAP_BASE_DN}" -w "${LDAP_ADMIN_PW}" -f "${OU_LDIF}" || echo "OUs may already exist"
|
||||
|
||||
echo "OpenLDAP: Creating test users"
|
||||
USER_LDIF="users.ldif"
|
||||
cat << EOF > "${USER_LDIF}"
|
||||
# User: enos
|
||||
dn: uid=enos,ou=users,${DOMAIN_DN}
|
||||
dn: uid=enos,ou=users,${LDAP_BASE_DN}
|
||||
objectClass: inetOrgPerson
|
||||
sn: enos
|
||||
cn: enos user
|
||||
@ -81,7 +45,7 @@ uid: enos
|
||||
userPassword: ${LDAP_ADMIN_PW}
|
||||
|
||||
# Static-role test user (for LDAP verification tests)
|
||||
dn: uid=vault-static-user,ou=users,${DOMAIN_DN}
|
||||
dn: uid=vault-static-user,ou=users,${LDAP_BASE_DN}
|
||||
objectClass: inetOrgPerson
|
||||
sn: vault-static-user
|
||||
cn: Vault Static User
|
||||
@ -89,21 +53,21 @@ uid: vault-static-user
|
||||
userPassword: ${LDAP_ADMIN_PW}
|
||||
|
||||
# Service accounts for library tests
|
||||
dn: uid=svc-account-1,ou=users,${DOMAIN_DN}
|
||||
dn: uid=svc-account-1,ou=users,${LDAP_BASE_DN}
|
||||
objectClass: inetOrgPerson
|
||||
sn: svc-account-1
|
||||
cn: Service Account 1
|
||||
uid: svc-account-1
|
||||
userPassword: ${LDAP_ADMIN_PW}
|
||||
|
||||
dn: uid=svc-account-2,ou=users,${DOMAIN_DN}
|
||||
dn: uid=svc-account-2,ou=users,${LDAP_BASE_DN}
|
||||
objectClass: inetOrgPerson
|
||||
sn: svc-account-2
|
||||
cn: Service Account 2
|
||||
uid: svc-account-2
|
||||
userPassword: ${LDAP_ADMIN_PW}
|
||||
|
||||
dn: uid=svc-delete,ou=users,${DOMAIN_DN}
|
||||
dn: uid=svc-delete,ou=users,${LDAP_BASE_DN}
|
||||
objectClass: inetOrgPerson
|
||||
sn: svc-delete
|
||||
cn: Service Account Delete
|
||||
@ -111,6 +75,6 @@ uid: svc-delete
|
||||
userPassword: ${LDAP_ADMIN_PW}
|
||||
EOF
|
||||
|
||||
ldapadd -x -H "ldap://${LDAP_SERVER}:${LDAP_PORT}" -D "cn=admin,${DOMAIN_DN}" -w "${LDAP_ADMIN_PW}" -f "${USER_LDIF}" || echo "Users may already exist"
|
||||
ldapadd -x -H "ldap://${LDAP_SERVER}:${LDAP_PORT}" -D "cn=admin,${LDAP_BASE_DN}" -w "${LDAP_ADMIN_PW}" -f "${USER_LDIF}" || echo "Users may already exist"
|
||||
|
||||
echo "LDAP population completed successfully."
|
||||
|
||||
@ -16,6 +16,12 @@ variable "ip_version" {
|
||||
default = "4"
|
||||
}
|
||||
|
||||
variable "ldap_domain" {
|
||||
type = string
|
||||
description = "The name of the domain"
|
||||
default = "enos.com"
|
||||
}
|
||||
|
||||
variable "ldap_version" {
|
||||
type = string
|
||||
description = "OpenLDAP Server Version to use"
|
||||
@ -35,15 +41,3 @@ variable "ports" {
|
||||
description = string
|
||||
}))
|
||||
}
|
||||
|
||||
variable "retry_interval" {
|
||||
type = number
|
||||
description = "How many seconds to wait between each retry"
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable "timeout" {
|
||||
type = number
|
||||
description = "The max number of seconds to wait before timing out"
|
||||
default = 60
|
||||
}
|
||||
|
||||
@ -52,14 +52,10 @@ locals {
|
||||
domain_dn = try(local.ldap_config.domain, "") != "" ? join(",", [for part in split(".", local.ldap_config.domain) : "dc=${part}"]) : ""
|
||||
|
||||
# Set up LDAP environment variables when LDAP integration is available
|
||||
# LDAP_SERVER uses private_ip for Vault operations (runs on Vault leader host)
|
||||
# LDAP_SERVER_PUBLIC uses public_ip for test setup operations (runs from GitHub runner)
|
||||
ldap_environment = try(local.ldap_config.domain, "") != "" ? {
|
||||
LDAP_SERVER = local.ldap_config.host.private_ip
|
||||
LDAP_SERVER_PUBLIC = local.ldap_config.host.public_ip
|
||||
LDAP_PORT = tostring(local.ldap_config.port)
|
||||
LDAP_BIND_DN = "cn=admin,${local.domain_dn}"
|
||||
LDAP_BIND_PASS = local.ldap_config.admin_pw
|
||||
LDAP_SERVER = "ldap://${local.ldap_config.host.private_ip}:${local.ldap_config.port}"
|
||||
LDAP_BIND_DN = "cn=admin,${local.domain_dn}"
|
||||
LDAP_BIND_PASS = local.ldap_config.admin_pw
|
||||
} : {}
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ fail() {
|
||||
[[ -z "${VAULT_TOKEN}" ]] && fail "VAULT_TOKEN env variable has not been set"
|
||||
[[ -z "${VAULT_ADDR}" ]] && fail "VAULT_ADDR env variable has not been set"
|
||||
[[ -z "${VAULT_TEST_PACKAGE}" ]] && fail "VAULT_TEST_PACKAGE env variable has not been set"
|
||||
[[ -z "${VAULT_EDITION}" ]] && fail "VAULT_EDITION env variable has not been set"
|
||||
|
||||
# Check required dependencies
|
||||
echo "Checking required dependencies..."
|
||||
@ -76,6 +77,18 @@ echo "Running tests..."
|
||||
echo "Vault environment variables:"
|
||||
env | grep VAULT | sed 's/VAULT_TOKEN=.*/VAULT_TOKEN=***REDACTED***/'
|
||||
|
||||
case $VAULT_EDITION in
|
||||
ent | ent.hsm | ent.hsm.fips1402 | ent.hsm.fips1403 | ent.fips1403 | ent.fips1402)
|
||||
tags="-tags=ent,enterprise"
|
||||
;;
|
||||
ce)
|
||||
tags=""
|
||||
;;
|
||||
*)
|
||||
fail "unknown VAULT_EDITION: $VAULT_EDITION"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Build gotestsum command based on whether we have specific tests
|
||||
set -x # Show commands being executed
|
||||
set +e # Temporarily disable exit on error
|
||||
@ -84,10 +97,10 @@ if [ -n "$VAULT_TEST_MATRIX" ] && [ -f "$VAULT_TEST_MATRIX" ]; then
|
||||
# Extract test names from matrix and create regex pattern
|
||||
test_pattern=$(jq -r '.include[].test' "$VAULT_TEST_MATRIX" | paste -sd '|' -)
|
||||
echo "Running specific tests: $test_pattern"
|
||||
gotestsum --junitfile="$junit_output" --format=standard-verbose --jsonfile="$json_output" -- -count=1 -run="$test_pattern" "$VAULT_TEST_PACKAGE"
|
||||
gotestsum --junitfile="$junit_output" --format=standard-verbose --jsonfile="$json_output" -- -count=1 "${tags}" -run="$test_pattern" "$VAULT_TEST_PACKAGE"
|
||||
else
|
||||
echo "Running all tests in package"
|
||||
gotestsum --junitfile="$junit_output" --format=standard-verbose --jsonfile="$json_output" -- -count=1 "$VAULT_TEST_PACKAGE"
|
||||
gotestsum --junitfile="$junit_output" --format=standard-verbose --jsonfile="$json_output" -- -count=1 "${tags}" "$VAULT_TEST_PACKAGE"
|
||||
fi
|
||||
test_exit_code=$?
|
||||
set -e # Re-enable exit on error
|
||||
|
||||
@ -79,8 +79,25 @@ output "ldap" {
|
||||
value = local.ldap_output
|
||||
}
|
||||
|
||||
# Ensure that our base DN is available on the LDAP server before we attempt to
|
||||
# to mount the engine.
|
||||
module "wait_for_ldap_base_dn" {
|
||||
source = "../../../../ldap_wait_for_search"
|
||||
|
||||
hosts = { 0 : var.leader_host }
|
||||
ldap_base_dn = var.integration_host_state.ldap.base_dn
|
||||
ldap_bind_dn = "cn=admin,${var.integration_host_state.ldap.base_dn}"
|
||||
ldap_host = var.integration_host_state.ldap.host
|
||||
ldap_password = var.integration_host_state.ldap.admin_pw
|
||||
ldap_port = var.integration_host_state.ldap.port
|
||||
}
|
||||
|
||||
# Enable LDAP secrets engine
|
||||
resource "enos_remote_exec" "secrets_enable_ldap_secret" {
|
||||
depends_on = [
|
||||
module.wait_for_ldap_base_dn,
|
||||
]
|
||||
|
||||
environment = {
|
||||
ENGINE = local.ldap_output.ldap_mount
|
||||
MOUNT = local.ldap_output.ldap_mount
|
||||
@ -98,7 +115,7 @@ resource "enos_remote_exec" "secrets_enable_ldap_secret" {
|
||||
}
|
||||
}
|
||||
|
||||
# Setup OpenLDAP infrastructure
|
||||
# Setup OpenLDAP infrastructure
|
||||
resource "enos_remote_exec" "ldap_setup" {
|
||||
depends_on = [
|
||||
enos_remote_exec.secrets_enable_ldap_secret
|
||||
@ -151,11 +168,38 @@ resource "enos_remote_exec" "ldap_secrets_config" {
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_remote_exec" "ldap_password_policy" {
|
||||
depends_on = [
|
||||
enos_remote_exec.secrets_enable_ldap_secret,
|
||||
enos_remote_exec.ldap_setup
|
||||
]
|
||||
|
||||
environment = {
|
||||
MOUNT = local.ldap_output.ldap_mount
|
||||
LDAP_SERVER = local.ldap_output.host.private_ip
|
||||
LDAP_PORT = local.ldap_output.port
|
||||
LDAP_USERNAME = local.ldap_output.username
|
||||
LDAP_ADMIN_PW = local.ldap_output.pw
|
||||
VAULT_ADDR = var.vault_addr
|
||||
VAULT_INSTALL_DIR = var.vault_install_dir
|
||||
VAULT_TOKEN = var.vault_root_token
|
||||
}
|
||||
|
||||
scripts = [abspath("${path.module}/../../../scripts/ldap/add-ldap-password-policy.sh")]
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = var.leader_host.public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Create a new Library set of service accounts
|
||||
# Test Case: Service Account Library - Create a new Library set of service accounts
|
||||
resource "enos_remote_exec" "ldap_library_set_create" {
|
||||
depends_on = [
|
||||
enos_remote_exec.ldap_secrets_config,
|
||||
enos_remote_exec.ldap_password_policy,
|
||||
]
|
||||
|
||||
environment = {
|
||||
@ -352,28 +396,3 @@ resource "enos_remote_exec" "ldap_library_self_checkin" {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "enos_remote_exec" "ldap_password_policy" {
|
||||
depends_on = [
|
||||
enos_remote_exec.secrets_enable_ldap_secret
|
||||
]
|
||||
|
||||
environment = {
|
||||
MOUNT = local.ldap_output.ldap_mount
|
||||
LDAP_SERVER = local.ldap_output.host.private_ip
|
||||
LDAP_PORT = local.ldap_output.port
|
||||
LDAP_USERNAME = local.ldap_output.username
|
||||
LDAP_ADMIN_PW = local.ldap_output.pw
|
||||
VAULT_ADDR = var.vault_addr
|
||||
VAULT_INSTALL_DIR = var.vault_install_dir
|
||||
VAULT_TOKEN = var.vault_root_token
|
||||
}
|
||||
|
||||
scripts = [abspath("${path.module}/../../../scripts/ldap/add-ldap-password-policy.sh")]
|
||||
|
||||
transport = {
|
||||
ssh = {
|
||||
host = var.leader_host.public_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"slices"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -19,11 +20,24 @@ import (
|
||||
// Session holds the test context and Vault client
|
||||
type Session struct {
|
||||
t *testing.T
|
||||
NoCleanup bool
|
||||
Client *api.Client
|
||||
Namespace string
|
||||
}
|
||||
|
||||
func New(t *testing.T) *Session {
|
||||
func (s *Session) T() *testing.T {
|
||||
return s.t
|
||||
}
|
||||
|
||||
type SessionOpts func(s *Session)
|
||||
|
||||
func WithNoCleanup() SessionOpts {
|
||||
return func(s *Session) {
|
||||
s.NoCleanup = true
|
||||
}
|
||||
}
|
||||
|
||||
func New(t *testing.T, opts ...SessionOpts) *Session {
|
||||
t.Helper()
|
||||
|
||||
addr := os.Getenv("VAULT_ADDR")
|
||||
@ -50,12 +64,6 @@ func New(t *testing.T) *Session {
|
||||
_, err = privClient.Logical().Write(nsURLPath, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
_, err = privClient.Logical().Delete(nsURLPath)
|
||||
require.NoError(t, err)
|
||||
t.Logf("Cleaned up namespace %s", nsName)
|
||||
})
|
||||
|
||||
// session client should get the full namespace of parent + test
|
||||
fullNSPath := nsName
|
||||
if parentNS != "" {
|
||||
@ -74,6 +82,20 @@ func New(t *testing.T) *Session {
|
||||
Namespace: nsName,
|
||||
}
|
||||
|
||||
for opt := range slices.Values(opts) {
|
||||
opt(session)
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
if session.NoCleanup {
|
||||
t.Logf("WARN: NoDebug has been set, not cleaning up namespace")
|
||||
return
|
||||
}
|
||||
_, err = privClient.Logical().Delete(nsURLPath)
|
||||
require.NoError(t, err)
|
||||
t.Logf("Cleaned up namespace %s", nsName)
|
||||
})
|
||||
|
||||
// make sure the namespace has been created
|
||||
session.Eventually(func() error {
|
||||
// this runs inside the new namespace, so if it succeeds, we're good
|
||||
|
||||
@ -4,17 +4,43 @@
|
||||
package blackbox
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/hashicorp/vault/sdk/helper/testcluster/blackbox"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// requireLDAPAvailable verifies LDAP server connectivity using testify Eventually
|
||||
func requireLDAPAvailable(t *testing.T, timeout, interval time.Duration) {
|
||||
t.Helper()
|
||||
|
||||
// Use public IP for external connectivity testing
|
||||
ldapServerPublic := os.Getenv("LDAP_URL_PUBLIC")
|
||||
require.NotEmpty(t, ldapServerPublic, "LDAP_URL_PUBLIC environment variable not set")
|
||||
|
||||
u, err := url.Parse(ldapServerPublic)
|
||||
require.NoError(t, err, "Failed to parse LDAP URL: %s", ldapServerPublic)
|
||||
|
||||
require.EventuallyWithT(t, func(ct *assert.CollectT) {
|
||||
d := &net.Dialer{}
|
||||
conn, err := d.DialContext(t.Context(), "tcp", u.Host)
|
||||
require.NoError(ct, err)
|
||||
require.NoError(ct, conn.Close())
|
||||
}, timeout, interval, "LDAP server not available at %s", u.Host)
|
||||
|
||||
t.Logf("LDAP server connectivity verified at %s", u.Host)
|
||||
}
|
||||
|
||||
// testLDAPSecretsCreate tests LDAP secrets engine creation
|
||||
func testLDAPSecretsCreate(t *testing.T, v *blackbox.Session) {
|
||||
// Check if LDAP server configuration is available from integration host
|
||||
ldapServer := os.Getenv("LDAP_SERVER")
|
||||
ldapServer := os.Getenv("LDAP_URL_PRIVATE")
|
||||
ldapBindDN := os.Getenv("LDAP_BIND_DN")
|
||||
ldapBindPass := os.Getenv("LDAP_BIND_PASS")
|
||||
|
||||
@ -22,6 +48,9 @@ func testLDAPSecretsCreate(t *testing.T, v *blackbox.Session) {
|
||||
t.Skip("LDAP server configuration not available - skipping LDAP secrets engine test")
|
||||
}
|
||||
|
||||
// Verify LDAP server is ready before proceeding
|
||||
requireLDAPAvailable(t, 1*time.Minute, 2*time.Second)
|
||||
|
||||
// Enable LDAP secrets engine
|
||||
v.MustEnableSecretsEngine("ldap-create", &api.MountInput{Type: "ldap"})
|
||||
|
||||
@ -53,7 +82,7 @@ func testLDAPSecretsCreate(t *testing.T, v *blackbox.Session) {
|
||||
// testLDAPSecretsRead tests LDAP secrets engine read operations
|
||||
func testLDAPSecretsRead(t *testing.T, v *blackbox.Session) {
|
||||
// Check if LDAP server configuration is available from integration host
|
||||
ldapServer := os.Getenv("LDAP_SERVER")
|
||||
ldapServer := os.Getenv("LDAP_URL_PRIVATE")
|
||||
ldapBindDN := os.Getenv("LDAP_BIND_DN")
|
||||
ldapBindPass := os.Getenv("LDAP_BIND_PASS")
|
||||
|
||||
@ -61,6 +90,10 @@ func testLDAPSecretsRead(t *testing.T, v *blackbox.Session) {
|
||||
t.Skip("LDAP server configuration not available - skipping LDAP secrets engine test")
|
||||
}
|
||||
|
||||
// Verify LDAP server is ready before proceeding
|
||||
requireLDAPAvailable(t, 1*time.Minute, 2*time.Second)
|
||||
serviceAccounts := []string{"svc-account-1", "svc-account-2"}
|
||||
|
||||
// Enable LDAP secrets engine
|
||||
v.MustEnableSecretsEngine("ldap-read", &api.MountInput{Type: "ldap"})
|
||||
|
||||
@ -75,7 +108,7 @@ func testLDAPSecretsRead(t *testing.T, v *blackbox.Session) {
|
||||
|
||||
// Create a library set for service account management
|
||||
v.MustWrite("ldap-read/library/test-set", map[string]any{
|
||||
"service_account_names": []string{"svc-account-1", "svc-account-2"},
|
||||
"service_account_names": serviceAccounts,
|
||||
"ttl": "10h",
|
||||
"max_ttl": "20h",
|
||||
"disable_check_in_enforcement": false,
|
||||
@ -106,7 +139,7 @@ func testLDAPSecretsRead(t *testing.T, v *blackbox.Session) {
|
||||
// testLDAPSecretsDelete tests LDAP secrets engine delete operations
|
||||
func testLDAPSecretsDelete(t *testing.T, v *blackbox.Session) {
|
||||
// Check if LDAP server configuration is available from integration host
|
||||
ldapServer := os.Getenv("LDAP_SERVER")
|
||||
ldapServer := os.Getenv("LDAP_URL_PRIVATE")
|
||||
ldapBindDN := os.Getenv("LDAP_BIND_DN")
|
||||
ldapBindPass := os.Getenv("LDAP_BIND_PASS")
|
||||
|
||||
@ -114,6 +147,10 @@ func testLDAPSecretsDelete(t *testing.T, v *blackbox.Session) {
|
||||
t.Skip("LDAP server configuration not available - skipping LDAP secrets engine test")
|
||||
}
|
||||
|
||||
// Verify LDAP server is ready before proceeding
|
||||
requireLDAPAvailable(t, 1*time.Minute, 2*time.Second)
|
||||
serviceAccounts := []string{"svc-delete"}
|
||||
|
||||
// Enable LDAP secrets engine
|
||||
v.MustEnableSecretsEngine("ldap-delete", &api.MountInput{Type: "ldap"})
|
||||
|
||||
@ -128,7 +165,7 @@ func testLDAPSecretsDelete(t *testing.T, v *blackbox.Session) {
|
||||
|
||||
// Create a library set
|
||||
v.MustWrite("ldap-delete/library/delete-set", map[string]any{
|
||||
"service_account_names": []string{"svc-delete"},
|
||||
"service_account_names": serviceAccounts,
|
||||
"ttl": "1h",
|
||||
})
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user