Root Credential Rotation Workflows (#11647) (#11996)

* Verify vault can generate dynamic credentials and rotate root password

* Added new line at end of the script file

* Remove extra space in sh script

* Remove extra space in sh script

* Created modular structure and other fixes

* linting issues

* lint issues

* Linting issue in verify-secrets.sh

* Linting issue in verify-secrets.sh

* Linting issues in verify-secrets.sh and verify-rotation.sh

* Linting issues

* Linting issues

* Linting issues

* Reverted the changes made to ldap-configs.sh and ldap-verify-configs

* Fix missing newline at end of ldap-verify-configs

Add a newline at the end of the ldap-verify-configs script.

* test ldap changes

* test ldap changes

* reverted the configuration for testing ldap [ci skip]

* reverted the configuration for testing ldap [ci skip]

* Refactoring

* Update ldap.tf

* Update ldap.tf [ci skip]

* Update ldap.tf

* Adding Password policy in ldap secret engine config

* Root credential rotation workflows

* linting issues

* Update test-run-enos-scenario-matrix.yml to check ldap changes

* Update test-run-enos-scenario-matrix.yml reverted

* conflicts resolved

* changes

* Update test-run-enos-scenario-matrix.yml to test ldap changes

* Update test-run-enos-scenario-matrix.yml reverted

* added functions

* linting issues

* linting issues

* linting issues

* Update test-run-enos-scenario-matrix.yml to tst ldap

* Update test-run-enos-scenario-matrix.yml reverted

* review changes

* Update test-run-enos-scenario-matrix.yml to test ldap

* lint issue

* reverted Update test-run-enos-scenario-matrix.yml

* refactor

* Update test-run-enos-scenario-matrix.yml test ldap

* Update verify-rotation.sh

* Update verify-rotation.sh

* Update test-run-enos-scenario-matrix.yml reverted

---------

Co-authored-by: pranaya092000 <pranaya.p@hashicorp.com>
Co-authored-by: Pranaya <Pranaya.P@ibm.com>
Co-authored-by: Luis (LT) Carbonell <lt.carbonell@hashicorp.com>
This commit is contained in:
Vault Automation 2026-01-27 02:47:18 -05:00 committed by GitHub
parent 5a54a1bb41
commit 852ac403bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -9,6 +9,20 @@ fail() {
exit 1
}
# Function to perform root rotation
rotate_root() {
"$binpath" write -f "${MOUNT}/rotate-root" 2>&1
}
# Function to get userPassword from LDAP
get_ldap_password() {
local user_dn="$1"
ldapsearch -x -LLL -H "ldap://${LDAP_SERVER}:${LDAP_PORT}" \
-b "${user_dn}" \
-D "cn=admin,dc=${LDAP_USERNAME},dc=com" \
-w "${LDAP_ADMIN_PW}" userPassword 2> /dev/null | grep "userPassword::" | awk '{print $2}'
}
[[ -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"
@ -22,6 +36,8 @@ binpath=${VAULT_INSTALL_DIR}/vault
test -x "$binpath" || fail "unable to locate vault binary at $binpath"
export VAULT_FORMAT=json
AUDIT_LOG="${VAULT_AUDIT_LOG:-/var/log/vault/vault_audit.log}"
ROLE_NAME="dynamic-role"
# Verifying LDAP Server Configs
LDAP_UID=$(ldapsearch -x -LLL -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=${LDAP_USERNAME})" 2> /dev/null)
@ -40,19 +56,124 @@ VAULT_POLICY_COUNT=$(echo "$VAULT_LDAP_LOGIN" | jq -r ".auth.policies | length")
echo "${VAULT_LDAP_LOGIN}"
#Attempting to rotate root with root token--should pass.
if "$binpath" write -f "${MOUNT}/rotate-root" > /dev/null 2>&1; then
echo "SUCCESS:rotate-root write passed (permissions OK)"
else
# Test1: Attempting to rotate root with root token--should pass
test_root_rotation_permissions() {
if rotate_root > /dev/null; then
echo "SUCCESS: rotate-root succeeded"
else
fail "Error: rotate-root write failed even though token had permissions"
fi
fi
}
#Attempting to rotate root with LDAP token--should fail as the policy does not allow it.
# Test2: Checking if last_bind_password_rotation field is present
test_rotation_field_presence() {
if "$binpath" read "${MOUNT}/config" | jq -e '.data.last_bind_password_rotation' > /dev/null; then
echo "Rotation success: last_bind_password_rotation field is present"
else
fail "Field is NOT present"
fi
}
ROOT_ROTATE=$(VAULT_TOKEN="$VAULT_LDAP_TOKEN" "$binpath" write -f "${MOUNT}/rotate-root" 2>&1 || true)
if echo "$ROOT_ROTATE" | grep -qi "permission denied"; then
# Test3: Attempting to rotate root with LDAP token--should fail as the policy does not allow it
test_ldap_token_permissions() {
if ! VAULT_TOKEN="$VAULT_LDAP_TOKEN" "$binpath" write -f "${MOUNT}/rotate-root" > /dev/null 2>&1; then
echo "SUCCESS: Vault correctly denied root rotation for LDAP token as policy does not allow."
else
else
fail "ERROR: LDAP token does not have permission to rotate, still rotation succeeded"
fi
fi
}
# Test4: Rotation with Invalid Config
test_invalid_config_rotation() {
echo "Test 4: Rotation with Invalid Config"
# Get password before attempting rotation with invalid config
PASSWORD_BEFORE=$(get_ldap_password "cn=admin,dc=${LDAP_USERNAME},dc=com")
if [[ -z "$PASSWORD_BEFORE" ]]; then
fail "ERROR: Could not retrieve password before rotation attempt"
fi
# Attempt to configure with invalid credentials
"$binpath" write "${MOUNT}/config" \
binddn="cn=invalid,dc=invalid,dc=com" \
bindpass="wrongpassword" > /dev/null 2>&1 || true
# Try to rotate with invalid config: should fail
if ! rotate_root > /dev/null 2>&1; then
echo "SUCCESS: Rotation correctly failed with invalid configuration"
else
fail "ERROR: Rotation should have failed with invalid configuration"
fi
# Restore valid config first
"$binpath" write "${MOUNT}/config" \
binddn="cn=admin,dc=${LDAP_USERNAME},dc=com" \
bindpass="${LDAP_ADMIN_PW}"
# Get password after failed rotation attempt
PASSWORD_AFTER=$(get_ldap_password "cn=admin,dc=${LDAP_USERNAME},dc=com")
if [[ -z "$PASSWORD_AFTER" ]]; then
fail "ERROR: Could not retrieve password after rotation attempt"
fi
# Verify password remains unchanged
if [[ "$PASSWORD_BEFORE" == "$PASSWORD_AFTER" ]]; then
echo "SUCCESS: User password remains unchanged after failed rotation with invalid config"
else
fail "ERROR: User password was modified despite rotation failure"
fi
# Verify credentials work for LDAP required operations by testing dynamic credential generation
if "$binpath" read "${MOUNT}/creds/${ROLE_NAME}" > /dev/null 2>&1; then
echo "SUCCESS: LDAP operations work correctly after restoring valid config"
else
fail "ERROR: LDAP operations failed after restoring valid config"
fi
}
# Test5: Rotate root twice and check if password changed
test_password_change_verification() {
echo "Performing first root rotation"
rotate_root > /dev/null
# Get password after first rotation, this will return the userPassword of the binddn.
echo "Getting password after first rotation"
FIRST_ROTATED_PASSWORD=$(get_ldap_password "cn=admin,dc=${LDAP_USERNAME},dc=com")
if [[ -z "$FIRST_ROTATED_PASSWORD" ]]; then
fail "ERROR: Could not retrieve password after first rotation from LDAP"
fi
echo "First rotated password retrieved"
# Second rotation
echo "Performing second root rotation"
rotate_root > /dev/null
# Get password after second rotation
echo "Getting password after second rotation"
SECOND_ROTATED_PASSWORD=$(get_ldap_password "cn=admin,dc=${LDAP_USERNAME},dc=com")
if [[ -z "$SECOND_ROTATED_PASSWORD" ]]; then
fail "ERROR: Could not retrieve password after second rotation from LDAP"
fi
# Compare passwords to ensure Userpassword is different after rotation
if [[ "$FIRST_ROTATED_PASSWORD" == "$SECOND_ROTATED_PASSWORD" ]]; then
fail "ERROR: Second rotation did not change the password! First and second rotated passwords are the same."
fi
# Check audit logs for rotation and generation events
echo "Checking audit logs for rotation and credential generation events"
sudo grep -E "rotate-root" "$AUDIT_LOG" > /dev/null 2>&1 && echo "Audit log updated"
}
# Running all tests
test_root_rotation_permissions
test_rotation_field_presence
test_ldap_token_permissions
test_invalid_config_rotation
test_password_change_verification
echo "All rotation tests passed successfully!"