[CRITICAL BUG] Vault 2.0.4 LDAP bindpass not persisting
- Dominant language
- Go
- Stars
- 36.3k
- Forks
- 4.8k
- PR merge metrics
- PR metrics pending
Description
# [BUG] Vault 2.0.4: LDAP auth method bindpass not persisting to Raft storage
**Severity:** CRITICAL (LDAP authentication completely non-functional)
**Affected Version:** Vault 2.0.4 Community Edition
**Environment:** Ubuntu 24.04 LTS, Raft storage, HA enabled
**Report Date:** August 19, 2026
---
## EXECUTIVE SUMMARY
In Vault 2.0.4 with Raft storage, the LDAP auth method's `bindpass` parameter is accepted during configuration but **NOT persisted to storage**. This causes all LDAP authentication attempts to fail with "invalid credentials" despite the bind account credentials being correct.
**Key Evidence:**
- ✅ `vault write` returns "Success! Data written"
- ✅ Credentials verified working externally with `ldapsearch`
- ❌ `vault read` returns `null` for bindpass
- ❌ No sub-endpoint exists for bindpass (unlike AppRole's `/role-id`)
- ❌ LDAP login fails due to missing bindpass in storage
---
## REPRODUCTION STEPS
### Step 1: Configure LDAP auth method
```bash
export VAULT_ADDR="https://192.168.37.61:8200"
export VAULT_SKIP_VERIFY=true
vault auth enable ldap -path=ldap-test
vault write auth/ldap-test/config \
url="ldap://192.168.37.30:389" \
binddn="CN=vault-service,OU=Cuentas de Servicio,OU=DETACOOP,DC=detacoop,DC=org" \
bindpass="TestPassword123!" \
userdn="DC=detacoop,DC=org" \
userattr="samaccountname" \
schema="ad"
```
**Output:** `Success! Data written to: auth/ldap-test/config`
### Step 2: Verify bindpass was written
```bash
vault write auth/ldap-test/config bindpass="TestPassword123!"
```
**Output:** `Success! Data written to: auth/ldap-test/config`
### Step 3: Read bindpass value
```bash
vault read -format=json auth/ldap-test/config | jq '.data.bindpass'
```
**Actual Output:** `null`
**Expected Output:** `"TestPassword123!"`
### Step 4: Check if bindpass exists in config keys
```bash
vault read -format=json auth/ldap-test/config | jq '.data | keys' | grep bindpass
```
**Actual Output:** (no results - bindpass NOT in keys)
**Expected Output:** `"bindpass"` should be in the list
### Step 5: Attempt LDAP login
```bash
vault login -method=ldap -path=ldap-test username=testuser
```
**Actual Output:** `Error authenticating: Error making API request... Code: 400. Errors: * LDAP bind (service) failed`
**Expected Output:** Successful authentication
---
## DETAILED ANALYSIS
### Symptoms
- Vault accepts `bindpass` in write operations with "Success! Data written"
- No error messages logged
- `vault read` returns `null` for bindpass
- No separate endpoint exists for bindpass retrieval
- LDAP authentication fails due to missing credentials
- External LDAP tools work correctly with same credentials
### System Verification
- ✓ Raft storage permissions: `0700 vault:vault`
- ✓ Vault database permissions: `0600 vault:vault`
- ✓ SELinux: Not installed
- ✓ AppArmor: Installed but Vault has no profile (full access)
- ✓ LDAP connectivity: Verified with external tools
- ✓ NTP sync: Both Vault and DC synchronized
- ✓ Credentials: Verified working with external LDAP client
### Key Finding: AppRole Works, LDAP Doesn't
**AppRole role_id (WORKS):**
```bash
$ vault read -format=json auth/approle/role/test-role/role-id
→ {"data": {"role_id": "39d99cf4-4e30-40c1-3cb6-1c15b9a75d61"}}
→ AppRole login: SUCCESS
```
**LDAP bindpass (BROKEN):**
```bash
$ vault read -format=json auth/ldap-test/config | jq '.data.bindpass'
→ null
→ LDAP login: FAILS with "invalid credentials"
```
**Architectural Difference:**
- AppRole has separate endpoints (`/role-id`, `/secret-id`) for credentials
- LDAP stores everything in single `/config` path
- AppRole credentials persist; LDAP bindpass does not
---
## ROOT CAUSE ANALYSIS
**Vault 2.0 architectural change:**
- Vault 2.0 refactored credential handling (Issue #1263 - bindpass obfuscation)
- Secrets marked as "hidden" should not appear in reads but should persist
- **BUG:** In LDAP auth method, hidden secrets are NOT persisted to Raft storage
- AppRole handles this correctly with separate endpoints
- LDAP method stores everything in `/config`, causing persistence to be skipped
---
## ENVIRONMENTAL DETAILS
- **Vault Version:** 2.0.4 Community Edition
- **Storage:** Raft (integrated)
- **OS:** Ubuntu 24.04 LTS
- **LDAP Server:** Active Directory (Windows Server 2016)
- **TLS:** Enabled
- **HA:** Enabled
---
## RELATED ISSUES
**Possible regression from Issue #2104:**
- Nov 2016: "LDAP insecure_tls resets to false, forgets bindpass on 0.6.0 -> 0.6.{1,2} update"
- Fix: Commit 0f53aa8 (migration of LDAP config storage schema)
- Current: Similar pattern - bindpass not persisting but in Vault 2.0
---
## IMPACT
**Severity: CRITICAL**
- LDAP authentication completely non-functional
- Blocks regulatory compliance requirements
- Workaround (AppRole) exists but doesn't fulfill compliance needs
---
## WORKAROUND
Use AppRole until LDAP is fixed:
```bash
vault auth enable approle
vault write auth/approle/role/detacoop-role token_ttl=1h token_max_ttl=4h
vault read -format=json auth/approle/role/detacoop-role/role-id
vault write auth/approle/login role_id="..." secret_id="..."
```
**Note:** AppRole does not satisfy LDAP regulatory requirements.
---
Contributor guide
Research direction
Start by reproducing the `auth/ldap-test/config` write and read commands, then trace the LDAP configuration path and Raft storage handling for `bindpass`. Use the LDAP login command to verify the failure and confirm the fix when the bindpass is retained internally and LDAP authentication succeeds.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- authentication, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100