Describe the bug
By default, using the userpass auth method, a user cannot update their own password
To Reproduce
Steps to reproduce the behavior:
vault server -devexport VAULT_ADDR='http://127.0.0.1:8200'vault auth enable userpassvault write auth/userpass/users/testuser password=testvault login -method=userpass username=testuser password=testvault write auth/userpass/users/testuser password=newpassExpected behavior
I would think a sane default would allow users to update their own passwords. If there is a way to do this with policies, I've been unable to determine how. I have tried using something like the following, but it allows all users to update all other users' passwords (expected, because of the wildcard). Also, seems the policy paths for userpass don't support identity.entity.{name,id}
path "auth/userpass/users/*" {
capabilities = ["update"]
}
Environment:
vault status): 1.1.0vault version): Vault v1.1.0 ('36aa8c8dd1936e10ebd7a4c1d412ae0e6f7900bd+CHANGES')Hi @jrdemasi,
policies are deny by default. So in my opinion, the behavior you experienced is correct.
You can and should use ACL Templating (https://learn.hashicorp.com/vault/identity-access-management/policy-templating) to allow every user to change its own password:
path "auth/userpass/users/{{identity.entity.aliases.auth_userpass_6671d643.name}}" {
capabilities = [ "update" ]
allowed_parameters = {
"password" = []
}
}
Make sure that you change the userpass mount accessor. You can read the mount accessor via vault auth list or the sys/auth API endpoint.
I will close this issue for now since I don't think that this is a bug. Feel free to reopen the issue if you have any other questions.
Cheers,
Michel
@michelvocks Thanks for the info -- I had tried that, but apparently didn't get it quite right. Really appreciate the response!
I had similar issues and the documentation didn't hold my hand enough.
Since the accessor string is different per instance, it could be difficult to pre-write this policy. I wonder if it's possible to simply allow all userpass entities to have the access to manage their own password without knowing the specific accessor strings.
This was my workaround, mostly step 4 and getting the userpass accessor string for this instance.
vault server -devexport VAULT_ADDR='http://127.0.0.1:8200'vault auth enable userpassuserpass.hcl# Get this userpass instance accessor string
userpass_accessor="$(vault auth list | awk '/^userpass/ {print $3}')"
# Create the userpass policy using this instance accessor string
cat > userpass.hcl << EOF
path "auth/userpass/users/{{identity.entity.aliases.${userpass_accessor}.name}}" {
capabilities = [ "update" ]
allowed_parameters = {
"password" = []
}
}
EOF
vault policy write userpass userpass.hclvault write auth/userpass/users/testuser password=test policies=userpassvault login -method=userpass username=testuservault write auth/userpass/users/testuser password=newpassAllowed parameters is fragile. You're better off using the endpoint designed for exactly this: https://www.vaultproject.io/api/auth/userpass/index.html#update-password-on-user
Thanks for the input, I was able to create the recommended policy:
# Get this userpass instance accessor string
userpass_accessor="$(vault auth list | awk '/^userpass/ {print $3}')"
# Create the userpass policy using this instance accessor string
cat > userpass.hcl << EOF
path "auth/userpass/users/{{identity.entity.aliases.${userpass_accessor}.name}}/password" {
capabilities = [ "update" ]
}
EOF
Then confirmed users could update their own password via HTTP API:
# Login and get token
token="$(vault login -token-only -method=userpass username=testuser)"
# Change password with user token / curl
curl \
--header "X-Vault-Token: ${token}" \
--request POST \
--data '{"username":"testuser","password":"newpassword"}' \
http://127.0.0.1:8200/v1/auth/userpass/users/testuser/password
This method doesn't seem possible through the vault CLI tool. I'll keep in mind that the HTTP API might have features unavailable to the CLI tool.
It's possible via vault write
Thanks, this did it:
vault write auth/userpass/users/testuser/password password=newpass
vault write auth/userpass/users/testuser/password password=newpass
This seems an insecure way of resetting password as the password is now available in command history
There are ways of ensuring a command doesn't appear in command history. For example, in bash you can set HISTCONTROL=ignoreboth and then start your command with a leading space.
agreed but vault provides a login mechanism that does not require this workaround - i think password reset security is fundamental to a product that is about the security of secrets - just my 2 cents
I had similar issues and the documentation didn't hold my hand enough.
Since the accessor string is different per instance, it could be difficult to pre-write this policy. I wonder if it's possible to simply allow all userpass entities to have the access to manage their own password without knowing the specific accessor strings.
This was my workaround, mostly step 4 and getting the userpass accessor string for this instance.
- Start Vault:
vault server -dev- Use Vault:
export VAULT_ADDR='http://127.0.0.1:8200'- Enable userpass:
vault auth enable userpass- Create userpass policy:
userpass.hcl# Get this userpass instance accessor string userpass_accessor="$(vault auth list | awk '/^userpass/ {print $3}')" # Create the userpass policy using this instance accessor string cat > userpass.hcl << EOF path "auth/userpass/users/{{identity.entity.aliases.${userpass_accessor}.name}}" { capabilities = [ "update" ] allowed_parameters = { "password" = [] } } EOF
- Add userpass policy:
vault policy write userpass userpass.hcl- Create a testuser:
vault write auth/userpass/users/testuser password=test policies=userpass- Login as testuser:
vault login -method=userpass username=testuser- Change password:
vault write auth/userpass/users/testuser password=newpass
I tried in my server, the policy works when it wrote like:
path "auth/userpass/users/{{identity.entity.aliases.${userpass_accessor}.name}}/password" {
capabilities = [ "update" ]
}
And it would not work if the policy like :
path "auth/userpass/users/{{identity.entity.aliases.${userpass_accessor}.name}}" {
capabilities = [ "update" ]
allowed_parameters = {
"password" = []
}
}
For me, all the password updating via api is not working, only the cli command works
vault write auth/userpass/users/testuser password=newpass
After several tries, I fixed it. You must follow the steps: create entity and get entityID > create alias according to the entityID > create the user according to the alias name, then it works fine.
Doesn't this give you permissions to update any user's password? I think this would be a security risk, considering you could update an admin's password and login using their account/ permissions.
@lrbnew, allowed_parameters would work, but @jefferai mentioned it could be fragile.
@mennlo if you follow the steps I've outlined. The "testuser" will only have access to change it's own password. I've tested creating a second "testuser2" and the original "testuser" could not modify the second users password.
After the original 8 steps:
$ vault login -method=userpass username=testuser
Success! You are now authenticated....
$ vault write auth/userpass/users/testuser password=newpass
Success! Data written to: auth/userpass/users/testuser
$ vault write auth/userpass/users/testuser2 password=newpass
Error writing data to auth/userpass/users/testuser2: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/auth/userpass/users/testuser2
Code: 403. Errors:
* 1 error occurred:
* permission denied
@cheyngoodman Thanks I realized I was getting auth/* permissions from a different policy.
I'm having an issue getting this to work, still getting permission denied.
[vault@vault-0 ~]$ userpass_accessor="$(vault auth list | awk '/^userpass/ {print $3}')"
[vault@vault-0 ~]$ cat > userpass.hcl << EOF
> path "auth/userpass/users/{{identity.entity.aliases.${userpass_accessor}.name}}/password" {
> capabilities = [ "update" ]
> }
> EOF
[vault@vault-0 ~]$ vault policy write userpass userpass.hcl
Success! Uploaded policy: userpass
[vault@vault-0 ~]$ vault write auth/userpass/users/testuser password=test policies=userpass
Success! Data written to: auth/userpass/users/testuser
[vault@vault-0 ~]$ vault login -method=userpass username=testuser
Password (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token s.UJ38gyvpdy3aVRxt2A5Wtem8
token_accessor M5IPmYddzODsxQhv7UIfdRLo
token_duration 768h
token_renewable true
token_policies ["default" "userpass"]
identity_policies []
policies ["default" "userpass"]
token_meta_username testuser
[vault@vault-0 ~]$ vault write auth/userpass/users/testuser password=newpass
Error writing data to auth/userpass/users/testuser: Error making API request.
URL: PUT https://vault-0.xyz.com:8200/v1/auth/userpass/users/testuser
Code: 403. Errors:
* 1 error occurred:
* permission denied
Can anyone help me diagnose my issue?
have the same issue as @mennlo
@mennlo @mshivanna can you verify that the variable is getting expanded and your policy doesn't have ${userpass_accessor} in it?
Edit, here is my full working "userpass.hcl":
path "auth/userpass/users/{{identity.entity.aliases.auth_userpass_MY_ACCESSOR.name}}" {
capabilities = [ "update" ]
allowed_parameters = {
"password" = []
}
}
ah works now. thanks @jrdemasi
i had missed this userpass_accessor="$(vault auth list | awk '/^userpass/ {print $3}')"
only cli works rest api does not work.
curl --header "X-Vault-Token: ${token}" --request POST --data '{"username":"mshivanna","password":"mynewpassword"}' https://ourvaultserver.com/v1/auth/userpass/users/mshivanna/password
{"errors":["1 error occurred:\n\t* permission denied\n\n"]}
I think your endpoint is wrong - it should just be auth/userpass/users/mshivanna
thank you it works now :)
Still having an issue with version 1.5.3. Have I applied the policy correctly?
GUI
It is a credential management solution so very frustrating this is not supported in the GUI as a standard option.
CLI
vault write auth/userpass/users/bobmarley password=jammingwithyou
Error writing data to auth/userpass/users/bobmarley: Error making API request.
URL: PUT https://vault.acme.com:8200/v1/auth/userpass/users/bobmarley
Code: 403. Errors:
* 1 error occurred:
* permission denied
HTTPS
curl --header "X-Vault-Token: s.wH5rfaWhateverTokenfb8fa" --request POST --data '{"username":"bobmarley","password":"jammingwithyou"}' https://vault.acme.com:8200/auth/userpass/users/bobmarley
_`{"errors":[]}`_
curl -k --header "X-Vault-Token: s.wH5rfaWhateverTokenfb8fa" --request POST --data '{"username":"bobmarley","password":"jammingwithyou"}' https://vault.acme.com:8200/v1/auth/userpass/users/bobmarley/password
_{"errors":["1 error occurred:\n\t* permission denied\n\n"]}_
Then I tried to login to GUI, login failed new with password, didn't work.
Added to bottom 'Default' Policy (/ui/vault/policy/acl/default)
Everything above indicates permission error, here is the policy:
# Allow User Password Resets
path "auth/userpass/users/{{identity.entity.aliases.auth_userpass_b6245263d.name}}" {
capabilities = [ "update" ]
allowed_parameters = {
"password" = []
}
}
Notes
Most helpful comment
agreed but vault provides a login mechanism that does not require this workaround - i think password reset security is fundamental to a product that is about the security of secrets - just my 2 cents