In addition to SSH certificate signing (CA mode), the SSH secrets engine supports the one-time password (OTP) mode. In this mode, Stronghold issues a client a one-time password for logging in to a specific host, and an agent on the remote host verifies the password against Stronghold when the user logs in.

OTP mode properties:

  • a password is valid for a single login and a single IP address;
  • every remote host needs an agent that verifies OTPs via the verify endpoint of the SSH secrets engine;
  • Stronghold does not store or distribute SSH keys.

OTP mode requires an agent on remote hosts that is compatible with the ssh/verify endpoint (for example, an SSH helper integrated with PAM). Installing and configuring the agent is out of scope of this documentation.

Setup

  1. Enable the SSH secrets engine if it is not enabled yet:

    d8 stronghold secrets enable ssh
  2. Create a role with the otp key type:

    d8 stronghold write ssh/roles/otp-role key_type=otp default_user=ubuntu cidr_list=10.0.0.0/24 exclude_cidr_list=10.0.0.1/32 allowed_users="ubuntu,deploy" port=22

    Role parameters for OTP mode:

    ParameterDescription
    key_typeKey type: otp or ca. Use otp for this mode.
    default_userDefault username on the remote host. Required for the otp type.
    cidr_listComma-separated list of CIDR blocks the role applies to.
    exclude_cidr_listComma-separated list of CIDR blocks whose IP addresses the role does not accept.
    allowed_usersUsers an OTP can be requested for. * allows any user.
    portSSH port returned to the client together with the OTP. It does not affect OTP generation. Defaults to 22.
  3. If the role must issue OTPs for any IP address, add it to the zero-address role list. CIDR blocks previously set for these roles are ignored:

    d8 stronghold write ssh/config/zeroaddress roles="otp-role"
  4. Configure an agent on the remote hosts that verifies OTPs against Stronghold.

Usage

  1. Request a one-time password for a host:

    d8 stronghold write ssh/creds/otp-role ip=10.0.0.15 username=ubuntu

    If username is omitted, the role’s default_user is used. The response contains the one-time password, the username, the IP address, and the port.

  2. Connect to the host over SSH and enter the OTP as the password. The agent on the host verifies it via the ssh/verify endpoint, after which the password becomes invalid.

To find out which roles apply to an IP address, use the lookup endpoint:

d8 stronghold write ssh/lookup ip=10.0.0.15

Policy example

A policy that only allows requesting OTPs for the otp-role role:

path "ssh/creds/otp-role" {
  capabilities = ["create", "update"]
}

For the full list of endpoints and parameters, see the secrets engines API reference.