55set -e
66
77fail () {
8- echo " $1 " 1>&2
9- exit 1
8+ echo " $1 " 1>&2
9+ exit 1
1010}
1111
1212# Function to generate LDIF files with DN
1313generate_ldif () {
14- local filename=" $1 "
15- local content=" $2 "
16- local ou=" ${3:- users} "
14+ local filename=" $1 "
15+ local content=" $2 "
16+ local ou=" ${3:- users} "
1717
18- cat << EOF > "${filename} "
18+ cat << EOF > "${filename} "
1919dn: cn={{.Username}},ou=${ou} ,dc=${LDAP_USERNAME} ,dc=com
2020${content}
2121EOF
2222}
2323
24+ # Function to create a password policy in Vault
25+ create_password_policy () {
26+ local policy_name=" $1 "
27+ local length=" $2 "
28+ local lowercase_min=" $3 "
29+ local uppercase_min=" $4 "
30+ local digit_min=" $5 "
31+ local special_chars=" $6 "
32+ local special_min=" $7 "
33+
34+ echo " Vault: Creating ${policy_name} password policy"
35+ cat > " ${policy_name} .hcl" << EOF
36+ length = ${length}
37+
38+ rule "charset" {
39+ charset = "abcdefghijklmnopqrstuvwxyz"
40+ min-chars = ${lowercase_min}
41+ }
42+
43+ rule "charset" {
44+ charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
45+ min-chars = ${uppercase_min}
46+ }
47+
48+ rule "charset" {
49+ charset = "0123456789"
50+ min-chars = ${digit_min}
51+ }
52+
53+ rule "charset" {
54+ charset = "${special_chars} "
55+ min-chars = ${special_min}
56+ }
57+ EOF
58+
59+ " $binpath " write sys/policies/password/" ${policy_name} " policy=@" ${policy_name} .hcl"
60+ echo " Password policy '${policy_name} ' created"
61+ }
62+
2463# Validate required environment variables
64+ [[ -z " $MOUNT " ]] && fail " MOUNT env variable has not been set"
2565[[ -z " $LDAP_SERVER " ]] && fail " LDAP_SERVER env variable has not been set"
2666[[ -z " $LDAP_PORT " ]] && fail " LDAP_PORT env variable has not been set"
2767[[ -z " $LDAP_USERNAME " ]] && fail " LDAP_USERNAME env variable has not been set"
@@ -35,14 +75,34 @@ test -x "$binpath" || fail "unable to locate vault binary at $binpath"
3575
3676export VAULT_FORMAT=json
3777
78+ CREDENTIAL_TTL_BUFFER=${CREDENTIAL_TTL_BUFFER:- 80}
79+ DYNAMIC_ROLE_NAME=" dynamic-role"
80+ INVALID_ROLE_NAME=" invalid-role"
81+
82+ # Define password policy constants
83+ readonly DEFAULT_POLICY=" default-policy"
84+ readonly STRONG_POLICY=" strong-policy"
85+ readonly DEFAULT_LENGTH=20
86+ readonly DEFAULT_MIN_CHARS=1
87+ readonly STRONG_POLICY_LENGTH=24
88+ readonly SPECIAL_CHARS=" !@#\$ %^&*"
89+
90+ # Create password policy for LDAP
91+ create_password_policy " $DEFAULT_POLICY " " $DEFAULT_LENGTH " " $DEFAULT_MIN_CHARS " " $DEFAULT_MIN_CHARS " " $DEFAULT_MIN_CHARS " " $SPECIAL_CHARS " " $DEFAULT_MIN_CHARS "
92+
3893# Set LDAP bind DN, password, and server URL for Vault's LDAP secrets engine
3994echo " Vault: Configuring LDAP secrets engine"
40- " $binpath " write ldap /config \
95+ " $binpath " write " ${MOUNT} /config" \
4196 binddn=" cn=admin,dc=${LDAP_USERNAME} ,dc=com" \
4297 bindpass=" ${LDAP_ADMIN_PW} " \
43- url=" ldap://${LDAP_SERVER} :${LDAP_PORT} "
98+ url=" ldap://${LDAP_SERVER} :${LDAP_PORT} " \
99+ userdn=" ou=users,dc=${LDAP_USERNAME} ,dc=com" \
100+ schema=" openldap" \
101+ password_policy=" $DEFAULT_POLICY "
102+
103+ echo " LDAP config written with $DEFAULT_POLICY "
44104
45- # Create the LDIF template that Vault will use to generate dynamic LDAP users
105+ # Create LDIF files for dynamic LDAP role
46106echo " Vault: Creating creation.ldif for dynamic LDAP role"
47107CREATION_LDIF=" creation.ldif"
48108generate_ldif " ${CREATION_LDIF} " " objectClass: person
@@ -51,87 +111,152 @@ cn: {{.Username}}
51111sn: {{.Password | utf16le | base64}}
52112userPassword: {{.Password}}" " users"
53113
54- # Create the LDIF template used by Vault to delete dynamic LDAP user entries
55114echo " Vault: Creating deletion.ldif for dynamic LDAP role"
56115DELETION_LDIF=" deletion.ldif"
57116generate_ldif " ${DELETION_LDIF} " " changetype: delete" " users"
58117
59- # Create the LDIF template used by Vault to roll back user creation if an error occurs
60118echo " Vault: Creating rollback.ldif for dynamic LDAP role"
61119ROLLBACK_LDIF=" rollback.ldif"
62120generate_ldif " ${ROLLBACK_LDIF} " " changetype: delete" " users"
63121
64122# Create the dynamic LDAP role in Vault using the LDIF templates
65- echo " Vault: Creating dynamic LDAP role dynamic-role "
66- " $binpath " write ldap /role/dynamic-role \
123+ echo " Vault: Creating dynamic LDAP role ${DYNAMIC_ROLE_NAME} "
124+ " $binpath " write " ${MOUNT} /role/${DYNAMIC_ROLE_NAME} " \
67125 creation_ldif=@${CREATION_LDIF} \
68126 deletion_ldif=@${DELETION_LDIF} \
69127 rollback_ldif=@${ROLLBACK_LDIF} \
70128 default_ttl=" ${DEFAULT_TTL} " \
71129 max_ttl=" ${MAX_TTL} "
72130
73- # Generating dynamic LDAP credentials from role dynamic-role
74- echo " Vault: Generating dynamic LDAP credentials from role dynamic-role"
131+ # Test1: Read Root Credential Config - Verify password is excluded
132+ test_read_config_password_exclusion () {
133+ echo " Test: Reading LDAP config to verify password exclusion"
134+ CONFIG_OUTPUT=$( " $binpath " read " ${MOUNT} /config" )
75135
76- DYNAMIC_CREDS=$( " $binpath " read ldap/creds/dynamic-role)
136+ BIND_DN=$( jq -r ' .data.binddn' <<< " $CONFIG_OUTPUT" )
137+ URL=$( jq -r ' .data.url' <<< " $CONFIG_OUTPUT" )
138+ SCHEMA=$( jq -r ' .data.schema' <<< " $CONFIG_OUTPUT" )
139+ PASSWORD_POLICY=$( jq -r ' .data.password_policy' <<< " $CONFIG_OUTPUT" )
77140
78- DYNAMIC_PASSWORD=$( echo " $DYNAMIC_CREDS " | jq -r ' .data.password' )
79- DYN_DN=$( echo " $DYNAMIC_CREDS " | jq -r ' .data.distinguished_names[0]' )
141+ # Verify bindpass is NOT returned (should not exist in the response)
142+ if ! jq -e ' .data.bindpass' <<< " $CONFIG_OUTPUT" > /dev/null 2>&1 ; then
143+ echo " SUCCESS: bindpass is excluded from config read"
144+ else
145+ fail " ERROR: bindpass was returned in config"
146+ fi
80147
81- if [[ -z " $DYN_DN " || " $DYN_DN " == " null" ]]; then
82- fail " Vault did not return a distinguished_name for dynamic LDAP user"
83- fi
148+ # Verify other expected fields are present
149+ if [[ -n " $BIND_DN " ]] && [[ -n " $URL " ]] && [[ -n " $SCHEMA " ]]; then
150+ echo " SUCCESS: All config fields are present when reading config"
151+ else
152+ fail " ERROR: Some config fields are missing when reading config"
153+ fi
84154
85- # Verify Dynamic Credentials
86- if ldapwhoami -x -H " ldap://${LDAP_SERVER} :${LDAP_PORT} " -D " ${DYN_DN} " -w " ${DYNAMIC_PASSWORD} " > /dev/null 2>&1 ; then
87- echo " LDAP dynamic credentials valid"
88- else
89- fail " Error: LDAP dynamic credentials validation failed"
90- fi
155+ # Verify password policy is set
156+ if [[ " $PASSWORD_POLICY " == " $DEFAULT_POLICY " ]]; then
157+ echo " SUCCESS: Password policy '$DEFAULT_POLICY ' is configured"
158+ else
159+ fail " ERROR: Password policy not set correctly. Expected: $DEFAULT_POLICY , Got: $PASSWORD_POLICY "
160+ fi
161+ }
91162
92- # Attempt to use expired credentials — verify LDAP authentication fails.
93- CREDENTIAL_TTL_BUFFER=${CREDENTIAL_TTL_BUFFER:- 80}
94- sleep " $CREDENTIAL_TTL_BUFFER "
163+ # Test: Update Root Credentials Config - Update with different password policy
164+ test_update_password_policy () {
165+ echo " Test: Updating LDAP config with different password policy"
166+
167+ # Create a different password policy (strong-policy)
168+ create_password_policy " $STRONG_POLICY " " $STRONG_POLICY_LENGTH " " $DEFAULT_MIN_CHARS " " $DEFAULT_MIN_CHARS " " $DEFAULT_MIN_CHARS " " $SPECIAL_CHARS " " $DEFAULT_MIN_CHARS "
95169
96- if ldapwhoami -x -H " ldap://${LDAP_SERVER} :${LDAP_PORT} " -D " $DYN_DN " -w " $DYNAMIC_PASSWORD " & > /dev/null; then
97- fail " Error: Dynamic credentials still valid — TTL did NOT expire"
98- else
99- echo " Dynamic credentials expired as expected"
100- fi
170+ " $binpath " write " ${MOUNT} /config" \
171+ password_policy=" $STRONG_POLICY "
101172
102- # Testing invalid dynamic LDAP role configuration by giving an invalid OU.
173+ echo " Updated LDAP config with $STRONG_POLICY "
103174
104- INVALID_CREATION_LDIF=" invalid_creation.ldif"
105- INVALID_DELETION_LDIF=" invalid_deletion.ldif"
175+ # Verify the update by reading config again
176+ UPDATED_CONFIG=$( " $binpath " read " ${MOUNT} /config" )
177+ UPDATED_POLICY=$( jq -r ' .data.password_policy' <<< " $UPDATED_CONFIG" )
106178
107- generate_ldif " ${INVALID_CREATION_LDIF} " " objectClass: person
179+ if [[ " $UPDATED_POLICY " == " $STRONG_POLICY " ]]; then
180+ echo " SUCCESS: Password policy updated to '$STRONG_POLICY '"
181+ else
182+ fail " ERROR: Password policy not updated. Expected: $STRONG_POLICY , Got: $UPDATED_POLICY "
183+ fi
184+ }
185+
186+ # Test: Generate and verify dynamic LDAP credentials
187+ test_dynamic_credentials () {
188+
189+ # Generating dynamic LDAP credentials from role ${DYNAMIC_ROLE_NAME}
190+ echo " Vault: Generating dynamic LDAP credentials from role ${DYNAMIC_ROLE_NAME} "
191+
192+ DYNAMIC_CREDS=$( " $binpath " read " ${MOUNT} /creds/${DYNAMIC_ROLE_NAME} " )
193+
194+ DYNAMIC_PASSWORD=$( jq -r ' .data.password' <<< " $DYNAMIC_CREDS" )
195+ DYN_DN=$( jq -r ' .data.distinguished_names[0]' <<< " $DYNAMIC_CREDS" )
196+
197+ if [[ -z " $DYN_DN " || " $DYN_DN " == " null" ]]; then
198+ fail " Vault did not return a distinguished_name for dynamic LDAP user"
199+ fi
200+
201+ # Verify Dynamic Credentials
202+ if ldapwhoami -x -H " ldap://${LDAP_SERVER} :${LDAP_PORT} " -D " ${DYN_DN} " -w " ${DYNAMIC_PASSWORD} " > /dev/null 2>&1 ; then
203+ echo " LDAP dynamic credentials valid"
204+ else
205+ fail " Error: LDAP dynamic credentials validation failed"
206+ fi
207+ }
208+
209+ # Test: Verify credentials expire after TTL
210+ test_credential_expiration () {
211+
212+ sleep " $CREDENTIAL_TTL_BUFFER "
213+
214+ if ldapwhoami -x -H " ldap://${LDAP_SERVER} :${LDAP_PORT} " -D " $DYN_DN " -w " $DYNAMIC_PASSWORD " & > /dev/null; then
215+ fail " Error: Dynamic credentials still valid — TTL did NOT expire"
216+ else
217+ echo " Dynamic credentials expired as expected"
218+ fi
219+ }
220+
221+ # Test: Invalid dynamic LDAP role configuration
222+ test_invalid_role_configuration () {
223+ echo " Test: Testing invalid dynamic LDAP role configuration"
224+
225+ INVALID_CREATION_LDIF=" invalid_creation.ldif"
226+ INVALID_DELETION_LDIF=" invalid_deletion.ldif"
227+
228+ generate_ldif " ${INVALID_CREATION_LDIF} " " objectClass: person
108229objectClass: top
109230cn: {{.Username}}
110231sn: {{.Password}}
111232userPassword: {{.Password}}" " invalid_ou"
112233
113- generate_ldif " ${INVALID_DELETION_LDIF} " " changetype: delete" " invalid_ou"
234+ generate_ldif " ${INVALID_DELETION_LDIF} " " changetype: delete" " invalid_ou"
114235
115- echo " Vault: Attempting to create invalid-role (should fail)..."
236+ echo " Vault: Attempting to create ${INVALID_ROLE_NAME} (should fail)..."
116237
117- " $binpath " write ldap/role/invalid-role \
118- creation_ldif=@${INVALID_CREATION_LDIF} \
119- deletion_ldif=@${INVALID_DELETION_LDIF} \
120- rollback_ldif=@${INVALID_DELETION_LDIF} \
121- default_ttl=" ${DEFAULT_TTL} " \
122- max_ttl=" ${MAX_TTL} " || true
123-
124- echo " Attempting to read creds from invalid-role"
125-
126- INVALID_CREDS_OUTPUT=$(
127- " $binpath " read ldap/creds/invalid-role 2>&1 || true
128- )
129- echo " $INVALID_CREDS_OUTPUT "
130-
131- # check for error message indicating invalid DN/OU.
132- if echo " $INVALID_CREDS_OUTPUT " | grep -qi " No Such Object" ; then
133- echo " SUCCESS: Vault failed dynamic credential creation due to invalid OU/DN."
134- " $binpath " delete ldap/role/invalid-role
135- else
136- fail " ERROR: Vault did NOT fail when invalid DN/OU was used!"
137- fi
238+ " $binpath " write " ${MOUNT} /role/${INVALID_ROLE_NAME} " \
239+ creation_ldif=@${INVALID_CREATION_LDIF} \
240+ deletion_ldif=@${INVALID_DELETION_LDIF} \
241+ rollback_ldif=@${INVALID_DELETION_LDIF} \
242+ default_ttl=" ${DEFAULT_TTL} " \
243+ max_ttl=" ${MAX_TTL} " || true
244+
245+ echo " Attempting to read creds from ${INVALID_ROLE_NAME} "
246+
247+ if ! " $binpath " read " ${MOUNT} /creds/${INVALID_ROLE_NAME} " > /dev/null 2>&1 ; then
248+ echo " SUCCESS: Vault failed dynamic credential creation due to invalid OU/DN."
249+ " $binpath " delete " ${MOUNT} /role/${INVALID_ROLE_NAME} "
250+ else
251+ fail " ERROR: Vault did NOT fail when invalid DN/OU was used!"
252+ fi
253+ }
254+
255+ # Run test cases
256+ test_read_config_password_exclusion
257+ test_update_password_policy
258+ test_dynamic_credentials
259+ test_credential_expiration
260+ test_invalid_role_configuration
261+
262+ echo " All tests completed successfully!"
0 commit comments