committed dynamic-roles.sh (#11833) (#12356)

* Dynamic-roles:updated with review comments

* Fix enos formatting: align variable assignments in scenario files

* Fix terraform formatting in LDAP modules

* Fix shell script formatting: add newlines and fix indentation

* Fix shellcheck warnings: quote variables to prevent globbing

* Change LDAP secrets engine verification to true

* Add variable for LDAP static role verification

* Configure SSH transport for LDAP dynamic roles

Added SSH transport configuration for LDAP dynamic roles.

* Fix formatting in ldap.tf

* Change LDAP secrets engine verification to false

---------

Co-authored-by: Amala Mathew <amala.mathew@hashicorp.com>
Co-authored-by: mathew-amala <amala.mathew1@ibm.com>
Co-authored-by: Luis (LT) Carbonell <lt.carbonell@hashicorp.com>
This commit is contained in:
Vault Automation 2026-02-18 08:36:34 -05:00 committed by GitHub
parent 504334f8bb
commit ccceb19d02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 628 additions and 49 deletions

View file

@ -624,13 +624,14 @@ scenario "agent" {
]
variables {
create_state = step.verify_secrets_engines_create.state
hosts = step.get_vault_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
create_state = step.verify_secrets_engines_create.state
hosts = step.get_vault_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
vault_audit_log_path = step.create_vault_cluster.audit_device_file_path
}
}

View file

@ -635,13 +635,14 @@ scenario "autopilot" {
]
variables {
create_state = step.verify_secrets_engines_create.state
hosts = step.get_updated_vault_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_vault_cluster.root_token
create_state = step.verify_secrets_engines_create.state
hosts = step.get_updated_vault_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.upgrade_vault_cluster_with_autopilot.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = local.vault_install_dir
vault_root_token = step.create_vault_cluster.root_token
vault_audit_log_path = step.create_vault_cluster.audit_device_file_path
}
}

View file

@ -1163,6 +1163,7 @@ scenario "dr_replication" {
verify_pki_certs = false
verify_aws_engine_creds = false
verify_ssh_secrets = false
vault_audit_log_path = step.create_secondary_cluster.audit_device_file_path
}
}
@ -1306,6 +1307,7 @@ scenario "dr_replication" {
verify_pki_certs = false
verify_aws_engine_creds = false
verify_ssh_secrets = false
vault_audit_log_path = step.create_secondary_cluster.audit_device_file_path
}
}

View file

@ -995,6 +995,7 @@ scenario "pr_replication" {
verify_pki_certs = false
verify_aws_engine_creds = false
verify_ssh_secrets = false
vault_audit_log_path = step.create_secondary_cluster.audit_device_file_path
}
}

View file

@ -600,13 +600,14 @@ scenario "proxy" {
]
variables {
create_state = step.verify_secrets_engines_create.state
hosts = step.get_vault_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
create_state = step.verify_secrets_engines_create.state
hosts = step.get_vault_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
vault_audit_log_path = step.create_vault_cluster.audit_device_file_path
}
}

View file

@ -850,13 +850,14 @@ scenario "seal_ha" {
]
variables {
create_state = step.verify_secrets_engines_create.state
hosts = step.get_updated_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
create_state = step.verify_secrets_engines_create.state
hosts = step.get_updated_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
vault_audit_log_path = step.create_vault_cluster.audit_device_file_path
}
}

View file

@ -683,13 +683,14 @@ scenario "smoke" {
]
variables {
create_state = step.verify_secrets_engines_create.state
hosts = step.get_vault_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
create_state = step.verify_secrets_engines_create.state
hosts = step.get_vault_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
vault_audit_log_path = step.create_vault_cluster.audit_device_file_path
}
}

View file

@ -711,14 +711,14 @@ scenario "upgrade" {
]
variables {
create_state = step.verify_secrets_engines_create.state
hosts = step.get_updated_vault_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
create_state = step.verify_secrets_engines_create.state
hosts = step.get_updated_vault_cluster_ips.follower_hosts
ip_version = matrix.ip_version
vault_addr = step.create_vault_cluster.api_addr_localhost
vault_edition = matrix.edition
vault_install_dir = global.vault_install_dir[matrix.artifact_type]
vault_root_token = step.create_vault_cluster.root_token
vault_audit_log_path = step.create_vault_cluster.audit_device_file_path
}
}

View file

@ -6,11 +6,11 @@ module "verify_ldap_secret_engine" {
count = var.ldap_enabled ? 1 : 0
source = "./ldap"
create_state = var.create_state
vault_addr = var.vault_addr
vault_root_token = var.vault_root_token
vault_install_dir = var.vault_install_dir
hosts = var.hosts
create_state = var.create_state
vault_addr = var.vault_addr
vault_root_token = var.vault_root_token
vault_install_dir = var.vault_install_dir
hosts = var.hosts
vault_audit_log_path = var.vault_audit_log_path
}

View file

@ -8,6 +8,9 @@ terraform {
}
}
}
locals {
dynamic_role_name = "dynamic-role"
}
variable "hosts" {
type = map(object({
@ -80,6 +83,17 @@ variable "enable_rollback_verification" {
default = true
}
variable "enable_dynamic_role_verification" {
type = bool
description = "Enable LDAP secrets engine dynamic role"
default = true
}
variable "vault_audit_log_path" {
type = string
description = "The file path for the audit device"
}
variable "enable_static_role_verification" {
type = bool
description = "Enable LDAP secrets engine static role verification"
@ -307,6 +321,43 @@ resource "enos_remote_exec" "ldap_library_checkout_lease_renew" {
}
}
}
# Configure and verify LDAP secrets engine rollback behavior
resource "enos_remote_exec" "verify_dynamic_role" {
count = var.enable_dynamic_role_verification ? 1 : 0
depends_on = [
enos_remote_exec.ldap_verify_secrets,
enos_remote_exec.ldap_verify_rotation
]
environment = {
MOUNT = var.create_state.ldap.ldap_mount
LDAP_SERVER = var.create_state.ldap.host.private_ip
LDAP_PORT = var.create_state.ldap.port
LDAP_USERNAME = var.create_state.ldap.username
LDAP_ADMIN_PW = var.create_state.ldap.pw
VAULT_ADDR = var.vault_addr
VAULT_INSTALL_DIR = var.vault_install_dir
VAULT_TOKEN = var.vault_root_token
ROLE_NAME = local.dynamic_role_name
DEFAULT_TTL = tostring(var.default_ttl)
MAX_TTL = tostring(var.max_ttl)
}
scripts = [
abspath("${path.module}/../../../scripts/ldap/Dynamic-roles/dynamic-roles.sh"),
abspath("${path.module}/../../../scripts/ldap/Dynamic-roles/dynamic-roles-validation.sh"),
abspath("${path.module}/../../../scripts/ldap/Dynamic-roles/dynamic-roles-listing.sh"),
abspath("${path.module}/../../../scripts/ldap/Dynamic-roles/dynamic-roles-audit.sh"),
abspath("${path.module}/../../../scripts/ldap/Dynamic-roles/dynamic-roles-rollback.sh"),
abspath("${path.module}/../../../scripts/ldap/Dynamic-roles/dynamic-roles-deletion.sh")
]
transport = {
ssh = {
host = var.hosts[0].public_ip
}
}
}
# Verify Static role
resource "enos_remote_exec" "ldap_static_roles" {
@ -333,3 +384,4 @@ resource "enos_remote_exec" "ldap_static_roles" {
}
}
}

View file

@ -50,6 +50,12 @@ variable "vault_root_token" {
default = null
}
variable "vault_audit_log_path" {
type = string
description = "The file path for the audit device"
default = null
}
variable "aws_enabled" {
type = bool
description = <<-EOF

View file

@ -0,0 +1,63 @@
#!/usr/bin/env bash
# Copyright IBM Corp. 2016, 2025
# SPDX-License-Identifier: BUSL-1.1
set -e
fail() {
echo "$1" 1>&2
exit 1
}
[[ -z "$MOUNT" ]] && fail "MOUNT env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
AUDIT_LOG="${VAULT_AUDIT_LOG:-/var/log/vault/vault_audit.log}"
ROLE_NAME="${ROLE_NAME:-dynamic-role}"
echo "Test: Audit Trail Verification for Dynamic Role Operations"
echo "Audit log path: $AUDIT_LOG"
echo "Role name: $ROLE_NAME"
if ! sudo test -f "$AUDIT_LOG"; then
fail "Audit log file not found at $AUDIT_LOG"
fi
echo "Test 1: Checking if role creation was audited..."
if ! sudo grep -q "\"path\":\"${MOUNT}/role/${ROLE_NAME}\"" "$AUDIT_LOG"; then
fail "ERROR: Role path not found in audit log"
fi
if sudo grep "\"path\":\"${MOUNT}/role/${ROLE_NAME}\"" "$AUDIT_LOG" | sudo grep -q "\"operation\":\"create\""; then
echo "SUCCESS: Role creation activity found in audit log"
elif sudo grep "\"path\":\"${MOUNT}/role/${ROLE_NAME}\"" "$AUDIT_LOG" | sudo grep -q "\"operation\":\"update\""; then
echo "SUCCESS: Role creation activity found in audit log (as update)"
else
fail "ERROR: Role creation/update operation not found in audit log"
fi
echo "Test 2: Checking if role update was audited..."
role_entries=$(sudo grep "\"path\":\"${MOUNT}/role/${ROLE_NAME}\"" "$AUDIT_LOG")
if echo "$role_entries" | sudo grep -q "\"default_ttl\""; then
echo "SUCCESS: Role update activity (default_ttl modification) found in audit log."
echo "$role_entries"
elif echo "$role_entries" | sudo grep -q "\"max_ttl\""; then
echo "SUCCESS: Role update activity (max_ttl modification) found in audit log"
else
echo "$role_entries"
fail "WARNING: Role update activity not clearly identified in audit log"
fi
echo "Test 3: Checking if role read was audited..."
if echo "$role_entries" | sudo grep -q "\"operation\":\"read\""; then
echo "SUCCESS: Role read activity found in audit log"
else
fail "ARNING: Role read activity not found in audit log"
fi
echo "All audit tests passed successfully."

View file

@ -0,0 +1,145 @@
#!/usr/bin/env bash
# Copyright IBM Corp. 2016, 2025
# SPDX-License-Identifier: BUSL-1.1
set -e
fail() {
echo "$1" 1>&2
exit 1
}
retry() {
local retries=$1
shift
local count=0
until "$@"; do
exit=$?
wait=$((2 ** count))
count=$((count + 1))
if [ "$count" -lt "$retries" ]; then
sleep "$wait"
echo "retry $count"
else
return "$exit"
fi
done
return 0
}
[[ -z "$MOUNT" ]] && fail "MOUNT env variable has not been set"
[[ -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_USERNAME" ]] && fail "LDAP_USERNAME env variable has not been set"
[[ -z "$LDAP_ADMIN_PW" ]] && fail "LDAP_ADMIN_PW env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
binpath=${VAULT_INSTALL_DIR}/vault
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
export VAULT_FORMAT=json
ROLE_NAME="${ROLE_NAME:-dynamic-role}"
# Test Case: Delete a dynamic role
test_delete_nonexistent_role() {
echo "Test Case: Delete a nonexistent dynamic role"
local test_role="${ROLE_NAME}_deletion"
if "$binpath" read "${MOUNT}/role/${test_role}" > /dev/null 2>&1; then
fail "ERROR: Role '$test_role' unexpectedly exists."
fi
echo "Confirmed: Role '$test_role' does not exist."
"$binpath" delete "${MOUNT}/role/${test_role}" > /dev/null 2>&1
if "$binpath" read "${MOUNT}/role/${test_role}" > /dev/null 2>&1; then
fail "FAIL: Role unexpectedly exists after deletion command!"
fi
echo "PASS: Role deleted successfully. Read returned error as expected."
}
# Test Case: Role Deleted with Active Leases
test_role_deletion_with_active_leases() {
echo "TEST CASE: Role Deleted with Active Leases (Cleanup)"
local lease_role="${ROLE_NAME}_lease_cleanup"
if ! output=$("$binpath" write "${MOUNT}/role/${lease_role}" \
creation_ldif=@creation.ldif \
deletion_ldif=@deletion.ldif \
rollback_ldif=@rollback.ldif \
username_template="v-lease-{{random 5}}" \
default_ttl=3600s 2>&1); then
fail "ERROR: Failed to create role: ${output}"
fi
echo "Role '$lease_role' created."
if ! creds_output=$("$binpath" read -format=json "${MOUNT}/creds/${lease_role}" 2>&1); then
fail "ERROR: Failed to generate credentials: ${creds_output}"
fi
lease_user=$(echo "$creds_output" | jq -r .data.username)
if [[ -z "$lease_user" || "$lease_user" == "null" ]]; then
fail "ERROR: Could not generate a user: ${creds_output}"
fi
echo "Generated dynamic user: '$lease_user'"
"$binpath" delete "${MOUNT}/role/${lease_role}" > /dev/null 2>&1
echo "Deleted role '$lease_role'. Waiting for cleanup..."
"$binpath" lease revoke -prefix "${MOUNT}/creds/${lease_role}" > /dev/null 2>&1
# Define the check function
wait_for_user_deletion() {
check_user=$(ldapsearch -x -H "ldap://${LDAP_SERVER}:${LDAP_PORT}" \
-b "dc=${LDAP_USERNAME},dc=com" \
-D "cn=admin,dc=${LDAP_USERNAME},dc=com" \
-w "${LDAP_ADMIN_PW}" \
"(uid=$lease_user)" dn 2>&1)
! grep -q "^dn:" <<< "$check_user"
}
# Use retry to poll (6 attempts = ~63 seconds max)
if retry 6 wait_for_user_deletion; then
echo "SUCCESS: User '$lease_user' deleted!"
else
fail "ERROR: User still exists after cleanup timeout"
fi
}
# Test Case: Invalid LDIF Template
test_invalid_ldif_template() {
echo "--- TEST CASE: Invalid LDIF Template (Negative Input) ---"
local bad_role="${ROLE_NAME}_invalid_ldif"
echo "Attempting to write invalid LDIF..."
set +e
output=$("$binpath" write "${MOUNT}/role/${bad_role}" \
creation_ldif="dn: this-is-total-garbage" \
deletion_ldif=@delete.ldif 2>&1)
ret_code=$?
set -e
if [ $ret_code -ne 0 ]; then
if grep -iq "invalid\|failed to parse" <<< "$output"; then
echo "SUCCESS: System correctly rejected invalid LDIF."
echo "Error Message: ${output}"
else
echo "SUCCESS: System rejected invalid LDIF (generic error)."
echo "Error Message: ${output}"
fi
else
fail "FAIL: System accepted invalid data: ${output}"
fi
}

View file

@ -0,0 +1,62 @@
#!/usr/bin/env bash
# Copyright IBM Corp. 2016, 2025
# SPDX-License-Identifier: BUSL-1.1
set -e
fail() {
echo "$1" 1>&2
exit 1
}
[[ -z "$MOUNT" ]] && fail "MOUNT env variable has not been set"
[[ -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_USERNAME" ]] && fail "LDAP_USERNAME env variable has not been set"
[[ -z "$LDAP_ADMIN_PW" ]] && fail "LDAP_ADMIN_PW env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
binpath=${VAULT_INSTALL_DIR}/vault
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
export VAULT_FORMAT=json
ROLE_NAME="${ROLE_NAME:-dynamic-role}"
# Test Case: Validate dynamic role Schema
test_validate_schema() {
echo "Test: Validate dynamic role schema"
if ! output=$("$binpath" write "${MOUNT}/role/${ROLE_NAME}_schema" \
creation_ldif=@creation.ldif \
deletion_ldif=@deletion.ldif \
rollback_ldif=@rollback.ldif \
username_template="v-schema-{{random 5}}" 2>&1); then
fail "ERROR: Schema validation failed: ${output}"
fi
echo "SUCCESS: Schema validation successful."
}
# Test Case: Listing Dynamic Roles
test_list_dynamic_roles() {
echo "Test: List Dynamic Roles"
if ! list_output=$("$binpath" list "${MOUNT}/role" 2>&1); then
fail "ERROR: Failed to list roles: ${list_output}"
fi
if ! grep -q "$ROLE_NAME" <<< "$list_output"; then
fail "ERROR: Role not found in list: ${list_output}"
fi
echo "SUCCESS: Role '$ROLE_NAME' found in list."
echo "$list_output"
}
test_validate_schema
test_list_dynamic_roles
echo "All validation and listing tests passed successfully."

View file

@ -0,0 +1,87 @@
#!/usr/bin/env bash
# Copyright IBM Corp. 2016, 2025
# SPDX-License-Identifier: BUSL-1.1
set -e
fail() {
echo "$1" 1>&2
exit 1
}
[[ -z "$MOUNT" ]] && fail "MOUNT env variable has not been set"
[[ -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_USERNAME" ]] && fail "LDAP_USERNAME env variable has not been set"
[[ -z "$LDAP_ADMIN_PW" ]] && fail "LDAP_ADMIN_PW env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
binpath=${VAULT_INSTALL_DIR}/vault
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
export VAULT_FORMAT=json
ROLE_NAME="${ROLE_NAME:-dynamic-role}"
# Advanced LDAP dynamic role tests: Rollback, Deletion, Negative scenarios
# Test Case: Rollback on Creation Failure
test_rollback_on_creation_failure() {
echo "Test Case: Rollback on Creation Failure (Negative Scenario)"
FAIL_ROLE_NAME="rollback-test-role"
FIXED_USER="rb_user_verify"
cat << EOF > create_for_rollback.ldif
dn: uid={{.Username}},ou=users,dc=$LDAP_USERNAME,dc=com
objectClass: inetOrgPerson
sn: {{.Username}}
cn: {{.Username}}
uid: {{.Username}}
userPassword: {{.Password}}
dn: uid=fail-{{.Username}},ou=users,dc=$LDAP_USERNAME,dc=com
objectClass: THIS_CLASS_DOESNOT_EXIST
sn: fail-user
cn: fail-user
EOF
cat << EOF > rollback.ldif
dn: uid={{.Username}},ou=users,dc=$LDAP_USERNAME,dc=com
changetype: delete
EOF
"$binpath" write ldap/role/$FAIL_ROLE_NAME \
creation_ldif=@create_for_rollback.ldif \
deletion_ldif=@deletion.ldif \
rollback_ldif=@rollback.ldif \
username_template="$FIXED_USER" \
default_ttl=3600s > /dev/null
echo "Triggering credential generation for $FAIL_ROLE_NAME (Expected to FAIL)..."
if "$binpath" read ldap/creds/$FAIL_ROLE_NAME > /dev/null 2>&1; then
fail "ERROR: API succeeded unexpectedly. The invalid LDIF should have caused a failure."
else
echo "SUCCESS: API returned error as expected (simulated partial failure)."
fi
echo "Verifying Rollback: Checking if '$FIXED_USER' was properly cleaned up..."
SEARCH_RES=$(ldapsearch -x -H "ldap://${LDAP_SERVER}:${LDAP_PORT}" \
-b "ou=users,dc=${LDAP_USERNAME},dc=com" \
-D "cn=admin,dc=${LDAP_USERNAME},dc=com" \
-w "${LDAP_ADMIN_PW}" \
"(uid=$FIXED_USER)" 2>&1)
if grep -q "^dn:" <<< "$SEARCH_RES"; then
fail "ERROR: user $FIXED_USER found in ldap."
else
echo "SUCCESS: User not found! Rollback successful"
fi
}
test_rollback_on_creation_failure
echo "Rollback tests passed successfully."

View file

@ -0,0 +1,74 @@
#!/usr/bin/env bash
# Copyright IBM Corp. 2016, 2025
# SPDX-License-Identifier: BUSL-1.1
set -e
fail() {
echo "$1" 1>&2
exit 1
}
[[ -z "$MOUNT" ]] && fail "MOUNT env variable has not been set"
[[ -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_USERNAME" ]] && fail "LDAP_USERNAME env variable has not been set"
[[ -z "$LDAP_ADMIN_PW" ]] && fail "LDAP_ADMIN_PW env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
binpath=${VAULT_INSTALL_DIR}/vault
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
export VAULT_FORMAT=json
ROLE_NAME="${ROLE_NAME:-dynamic-role}"
# Test Case: Template Validation - Valid Syntax
test_valid_template_syntax() {
echo "Test Case: Template Validation (Valid Syntax)"
if ! output=$("$binpath" write "${MOUNT}/role/${ROLE_NAME}_valid" \
creation_ldif=@creation.ldif \
deletion_ldif=@deletion.ldif \
rollback_ldif=@rollback.ldif \
username_template="v-temp-{{random 10}}" 2>&1); then
fail "ERROR: Vault rejected valid template at role creation: ${output}"
fi
echo "SUCCESS: Vault accepted valid template (200 OK)"
}
# Type 2: Negative Test - Invalid Template
test_invalid_template_syntax() {
echo "Test Case: Template Validation (Invalid Syntax)"
set +e
output=$("$binpath" write "${MOUNT}/role/${ROLE_NAME}_invalid" \
creation_ldif=@creation.ldif \
deletion_ldif=@deletion.ldif \
rollback_ldif=@rollback.ldif \
username_template="{{.Invalid_Syntax}}" 2>&1)
set +e
output=$("$binpath" read "${MOUNT}/creds/${ROLE_NAME}_invalid" 2>&1)
ret_code=$?
set -e
if [ $ret_code -eq 0 ]; then
fail "ERROR: Vault accepted invalid template and generated credentials! Output: ${output}"
fi
if echo "$output" | grep -q "can't evaluate field Invalid_Syntax"; then
echo "SUCCESS: Vault correctly rejected invalid template at credential generation"
echo "Error message: ${output}"
else
echo "Debug Output: ${output}"
fail "ERROR: Expected template validation error but got different error"
fi
}
test_valid_template_syntax
test_invalid_template_syntax
echo "All template validation tests passed successfully."

View file

@ -0,0 +1,82 @@
#!/usr/bin/env bash
# Copyright IBM Corp. 2016, 2025
# SPDX-License-Identifier: BUSL-1.1
set -e
fail() {
echo "$1" 1>&2
exit 1
}
[[ -z "$MOUNT" ]] && fail "MOUNT env variable has not been set"
[[ -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_USERNAME" ]] && fail "LDAP_USERNAME env variable has not been set"
[[ -z "$LDAP_ADMIN_PW" ]] && fail "LDAP_ADMIN_PW env variable has not been set"
[[ -z "$VAULT_ADDR" ]] && fail "VAULT_ADDR env variable has not been set"
[[ -z "$VAULT_INSTALL_DIR" ]] && fail "VAULT_INSTALL_DIR env variable has not been set"
[[ -z "$VAULT_TOKEN" ]] && fail "VAULT_TOKEN env variable has not been set"
binpath=${VAULT_INSTALL_DIR}/vault
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
export VAULT_FORMAT=json
ROLE_NAME="${ROLE_NAME:-dynamic-role}"
# Test Case: create a dynamic role
test_create_dynamic_role() {
echo "Test Case: Create Dynamic Role ($ROLE_NAME)"
if ! output=$("$binpath" write "${MOUNT}/role/${ROLE_NAME}" \
username_template="v-temp-{{random 10}}" \
default_ttl=3200s \
max_ttl=7200s 2>&1); then
fail "ERROR: Failed to create Dynamic Role: ${output}"
fi
echo "SUCCESS: Dynamic Role created."
}
# Test Case: Read a newly created dynamic role
test_read_dynamic_role() {
echo "Test Case: Read newly created dynamic role"
if ! read_output=$("$binpath" read "${MOUNT}/role/${ROLE_NAME}" 2>&1); then
fail "ERROR: Failed to read role: ${read_output}"
fi
if ! grep -q "v-temp" <<< "$read_output"; then
echo "Debug Output: $read_output"
fail "ERROR: Role read succeeded but creation_ldif not found."
else
echo "Debug Output: $read_output"
fi
echo "SUCCESS: Role is readable and configuration matches."
}
# Test Case: Update existing dynamic role
test_update_dynamic_role() {
echo "Test case: Update existing dynamic role TTL"
if ! output=$("$binpath" write "${MOUNT}/role/${ROLE_NAME}" default_ttl=7200s 2>&1); then
fail "ERROR: Failed to update role: ${output}"
fi
if ! updated_ttl=$("$binpath" read -field=default_ttl "${MOUNT}/role/${ROLE_NAME}" 2>&1); then
fail "ERROR: Failed to read updated TTL: ${updated_ttl}"
fi
if echo "$updated_ttl" | grep -q "7200"; then
echo "SUCCESS: Role updated successfully (TTL=7200)."
else
echo "Debug Output: $updated_ttl"
fail "ERROR: Update mismatch. Expected 7200, got $updated_ttl"
fi
}
test_create_dynamic_role
test_read_dynamic_role
test_update_dynamic_role
echo "All basic dynamic role tests passed successfully."