The userpass auth method allows users to authenticate in Deckhouse Stronghold using a username and password.

Method features

When using the userpass method, keep the following features in mind:

  • Usernames and passwords are specified directly in the authentication method at the path auth/userpass/users/.
  • The userpass method cannot read usernames and passwords from an external source.
  • Entered usernames are converted to lowercase. For example, Mary and mary are equivalent entries.

Configuration

To allow users to authenticate, configure the userpass method. These steps are usually completed by an operator or configuration management tool.

To configure authentication using the userpass method, follow these steps:

  1. Enable the userpass auth method:

    • Stronghold in Deckhouse Platform
    • Stronghold in Linux
    d8 stronghold auth enable userpass
    stronghold auth enable userpass

    The method will be enabled at the auth/userpass path.

    To enable the method at a different path, use the -path flag:

    • Stronghold in Deckhouse Platform
    • Stronghold in Linux
    d8 stronghold auth enable -path=<MOUNT_PATH> userpass
    stronghold auth enable -path=<MOUNT_PATH> userpass

    Where <MOUNT_PATH> is the path to enable the method at, for example, my-userpass.

  2. If necessary, create a user who is allowed to authenticate:

    • Stronghold in Deckhouse Platform
    • Stronghold in Linux
    d8 stronghold write auth/<MOUNT_PATH>/users/alice password=Pass-123! token_policies=admins
    stronghold write auth/<MOUNT_PATH>/users/alice password=Pass-123! token_policies=admins

This creates user alice with password Pass-123! and the admins policy.

User authentication using the userpass method

Example command for user authentication using the userpass method:

  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold login -method=userpass username=alice password="Pass-123!"
stronghold login -method=userpass username=alice password="Pass-123!"

User lockout

If a user provides incorrect credentials several times in a row, Stronghold stops validating them for a while and returns an access denied error. This behavior is called user lockout (user_lockout).

The time for which a user is locked out is called lockout duration (lockout_duration). After this time expires, the user can log in again.

The number of failed login attempts after which a user is locked out is called lockout threshold (lockout_threshold). The lockout threshold counter resets after a few minutes without login attempts or after a successful login. The interval after which the counter resets when there are no login attempts is called lockout counter reset (lockout_counter_reset).

User lockout helps reduce the risk of password guessing attacks.

The user lockout feature is enabled by default. Default values:

  • lockout_threshold: 5 attempts.
  • lockout_duration: 15 minutes.
  • lockout_counter_reset: 15 minutes.

You can disable user lockout with the auth tune command by setting the disable_lockout parameter to true:

  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold auth tune -user-lockout-disable=true userpass
stronghold auth tune -user-lockout-disable=true userpass

User lockout is supported only by the userpass, ldap, and approle auth methods.

Changing your own password

You can allow a user to change their own password in the userpass method. To do this, create a policy where the path to the user’s password is formed based on the authenticated user’s name.

Creating a policy

Use the following policy template:

path "auth/userpass/users/{{identity.entity.aliases.<ACCESSOR>.name}}/password" {
  capabilities = ["update"]
}

Get the <ACCESSOR> value with the command:

  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold read -field=accessor sys/auth/userpass
stronghold read -field=accessor sys/auth/userpass

The {{identity.entity.aliases.<ACCESSOR>.name}} template automatically substitutes the authenticated user’s name. Therefore, the path always points only to the current user’s password.

The template works after logging in via the userpass method.

Allowing a user to change their own password

To allow a user to change their own password using the userpass method, follow these steps:

  • If the userpass method is already enabled
  • If the userpass method is not enabled
  1. Get the unique method identifier:

    • Stronghold in Deckhouse Platform
    • Stronghold in Linux
    ACCESSOR=$(d8 stronghold read -field=accessor sys/auth/userpass)
    ACCESSOR=$(stronghold read -field=accessor sys/auth/userpass)
  2. Create a policy that allows a user authenticated via userpass to change their password:

    • Stronghold in Deckhouse Platform
    • Stronghold in Linux
    d8 stronghold policy write self-change-password - <<EOF
    path "auth/userpass/users/{{identity.entity.aliases.${ACCESSOR}.name}}/password" {
      capabilities = ["update"]
    }
    EOF
    stronghold policy write self-change-password - <<EOF
    path "auth/userpass/users/{{identity.entity.aliases.${ACCESSOR}.name}}/password" {
      capabilities = ["update"]
    }
    EOF
  3. Assign the policy to the user you want to allow to change their password:

  • If the user exists
  • If the user does not exist
  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold write auth/userpass/users/alice/policies token_policies="self-change-password"
stronghold write auth/userpass/users/alice/policies token_policies="self-change-password"

This example will apply the self-change-password policy to the existing user alice.

  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold write auth/userpass/users/alice password="OldPass-123!" token_policies="self-change-password"
stronghold write auth/userpass/users/alice password="OldPass-123!" token_policies="self-change-password"

This example will create a user named alice, grant them authentication via userpass, and assign the self-change-password policy to them.

  1. Enable the userpass method:

    • Stronghold in Deckhouse Platform
    • Stronghold in Linux
    d8 stronghold auth enable userpass
    stronghold auth enable userpass
  2. Get the unique method identifier:

    • Stronghold in Deckhouse Platform
    • Stronghold in Linux
    ACCESSOR=$(d8 stronghold read -field=accessor sys/auth/userpass)
    ACCESSOR=$(stronghold read -field=accessor sys/auth/userpass)
  3. Create a policy that allows a user authenticated via userpass to change their password:

    • Stronghold in Deckhouse Platform
    • Stronghold in Linux
    d8 stronghold policy write self-change-password - <<EOF
    path "auth/userpass/users/{{identity.entity.aliases.${ACCESSOR}.name}}/password" {
      capabilities = ["update"]
    }
    EOF
    stronghold policy write self-change-password - <<EOF
    path "auth/userpass/users/{{identity.entity.aliases.${ACCESSOR}.name}}/password" {
      capabilities = ["update"]
    }
    EOF
  4. Assign the policy to the user you want to allow to change their password:

  • If the user exists
  • If the user does not exist
  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold write auth/userpass/users/alice/policies token_policies="self-change-password"
stronghold write auth/userpass/users/alice/policies token_policies="self-change-password"

This example will apply the self-change-password policy to the existing user alice

  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold write auth/userpass/users/alice password="OldPass-123!" token_policies="self-change-password"
stronghold write auth/userpass/users/alice password="OldPass-123!" token_policies="self-change-password"

This example will create a user named alice, grant them authentication via userpass, and assign the self-change-password policy to them.

Changing password as a user

After authentication, a user can change their password if they are allowed to do so.

Example command for a user to change their password:

  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold write auth/userpass/users/alice/password password="NewPass-456!"
stronghold write auth/userpass/users/alice/password password="NewPass-456!"

If the user tries to change someone else’s password, Stronghold returns a permission denied error. If a user enters incorrect login credentials when changing their password, their account may be locked.

Default password policy

If no custom password policy is assigned to the userpass method, Stronghold uses the default policy when creating a user or changing a user’s password.

The default policy for the userpass method requires:

  • 8 characters in the password
  • At least one uppercase letter
  • At least one lowercase letter
  • At least one digit
  • At least one special character from the set !@#$%^&*()-_=+[]{}|;:,.<>/?

The default policy does not limit the password lifetime (password_max_age_days = 0) and does not check the password history (password_history_depth = 0).

To use a custom policy instead of the default password policy for the userpass method, run the following command (replace policy_name with the name of the desired policy):

  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold write auth/userpass/password-policy/{policy_name}
stronghold write auth/userpass/password-policy/{policy_name}

Password expiry

The userpass method can limit the lifetime of passwords. Expiry is configured in the password policy bound to the method (or in the default policy, if no policy is bound) with the following keys:

KeyTypeDefault valueDescription
password_max_age_daysint0Number of days a password stays valid. 0 disables expiry. Allowed values: 0-3650
password_expiry_warning_daysint3Number of days before expiry, starting from which a successful login returns a warning. 0 disables warnings. Must not be negative

Example of a policy with a 90-day password lifetime and a 14-day warning:

length = 12
password_max_age_days = 90
password_expiry_warning_days = 14

rule "charset" {
  charset = "abcdefghijklmnopqrstuvwxyz"
  min-chars = 1
}

rule "charset" {
  charset = "0123456789"
  min-chars = 1
}

The password age is counted from the moment the password was last set: when creating a user, when changing the password via users/<USERNAME> or users/<USERNAME>/password, or via login/<USERNAME>/change-password. For users whose passwords were set before expiry tracking was introduced, the set time is unknown. Such passwords are counted from the reference point (epoch) that Stronghold records for the mount when expiry becomes enabled. Thus, enabling expiry does not expire existing passwords immediately. The reference point is recorded by a periodic check (up to about one minute after the policy is changed) and is deleted when expiry is disabled. Until the reference point is recorded, such passwords are considered valid.

Behavior of the method when expiry is enabled:

  • If the password has expired, the login request is rejected with a permission denied error. The error message contains the expiry date and a hint to use login/<USERNAME>/change-password. The expiry is checked only after the password itself has been verified, so the message does not reveal whether a user exists. A login attempt with an expired password is not counted as a failed attempt and does not contribute to user lockout.
  • If the password is about to expire (the current time is within password_expiry_warning_days of the expiry date), a successful login returns a warning in the warnings field of the response with the expiry date.
  • A token renewal is rejected if the user’s password has expired by that time.
  • Reading auth/<MOUNT_PATH>/users/<USERNAME> additionally returns the password_set_time and password_expires_at fields (RFC 3339 format). They are empty if the set time is unknown or expiry is disabled.

Reading the expiry settings

To get the expiry settings in force for the mount, use the GET method on auth/<MOUNT_PATH>/password-expiry. The request requires a token with the appropriate access policy.

The response contains the following fields:

  • max_age_days — password lifetime in days, 0 if expiry is disabled;
  • warning_days — number of days before expiry at which warnings start;
  • epoch — the reference point in RFC 3339 format, or an empty string if it is not recorded.
  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold read auth/userpass/password-expiry
stronghold read auth/userpass/password-expiry

Changing the password with the current password

The login/<USERNAME>/change-password endpoint allows a user to change their own password without a token by presenting the current password. It works even if the current password has expired, when it is impossible to log in and obtain a token.

Request: POST auth/<MOUNT_PATH>/login/<USERNAME>/change-password.

Parameters:

  • current_password (string, required) — the current user password.
  • new_password (string, required) — the new password. It is checked against the password policy bound to the method, including the password history (password_history_depth).
  • Stronghold in Deckhouse Platform
  • Stronghold in Linux
d8 stronghold write auth/userpass/login/alice/change-password current_password="OldPass-123!" new_password="NewPass-456!"
stronghold write auth/userpass/login/alice/change-password current_password="OldPass-123!" new_password="NewPass-456!"

Features of the endpoint:

  • The endpoint is unauthenticated (it is located under the login/ prefix), so no access policy is needed. No token is issued in response: on success, an empty response is returned.
  • If the current_password or new_password parameter is missing, or the new password does not meet the policy requirements, the request fails with a 400 error.
  • If the current password is incorrect or the user does not exist, the same invalid username or password error is returned. For an existing user, a failed attempt counts toward the user lockout threshold in the same way as a failed login. A locked-out user cannot change their password with this endpoint until the lockout ends.
  • If token_bound_cidrs is set for the user, the request is accepted only from the allowed addresses.
  • Login MFA is not applied to this endpoint, since it does not issue a token.
  • A successful change updates the password set time, and the user’s password expiry count starts over.

Additional resources