Vault SSH signed key from PKCS11 or Yubikey?

Hi!
One of my customers is running a Vault enterprise instance.
I am currently looking into using the ‘SSH CA’ functionality of Vault which is linked to an IDP, allowing me to get a short-lived signed public key which I can use for SSH.

Looking at the following resources, this seems possible:

So in my head, the following would need to happen:

  1. Create a keypair on the YubiKey or other PKCS11 device
  2. Retrieve the public key from yubikey/pkcs11
  3. Trigger logon onto vault server with SSO
  4. Get the PKCS11 public key signed by vaults SSH CA secrets engine
  5. Add the signed public key and private key to the SSH agent
  6. Connect to the git instance over SSH

Is there a way to instruct the vault cli to store/use keys on a PKCS11/YubiKey?
How would the vault command look like?
Thank you!

Regards

I’m always interested in ways to use my YubiKey with Vault. Have you found a method for signed SSH certificates?

I don’t think the Vault CLI tool can help out here, but you can accomplish this with curl by using the proper REST calls. You can use the API guide and/or the Vault CLI -output-curl-string argument to help piece together the commands.

For example, I use my YubiKey for Vault PKI logins that signs my SSH public key. It’s just a bash script and it’s by no means optimal nor finished.

#!/bin/bash
set -e

VAULT_UNAME=foo
SSH_USER=root
ROLE=adminrole
SSH_CA_CSR=${HOME}/.ssh/ssh-ca.json
VAULT_ADDR=${VAULT_ADDR:-https://active.vault.service.consul:8200}
PUBLIC_KEY=$(cat ${HOME}/.ssh/id_ed25519.pub)
SSH_USER_CERT=${HOME}/.ssh/id_ed25519-cert.pub
HWTOKEN_CERT="pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=00000000;token=foo%example.com"
TOKEN_TTL="30"

VAULT_TOKEN=$(curl --silent \
                   --cert ${HWTOKEN_CERT} \
                   --request POST \
                   --data '{"name": "'${VAULT_UNAME}'","ttl": "'${TOKEN_TTL}'"}' \
                   ${VAULT_ADDR}/v1/auth/cert/login | \
                   jq --raw-output .auth.client_token)

vault_hwtoken_login() {
  curl --silent \
       --cert ${HWTOKEN_CERT} \
       --request POST \
       --data '{"name": "'${VAULT_UNAME}'","ttl": "'${TOKEN_TTL}'"}' \
       ${VAULT_ADDR}/v1/auth/cert/login | \
       jq --raw-output .auth.client_token
}

sshca_csr() {
cat <<EOF > ${SSH_CA_CSR}
  {
      "public_key": "${PUBLIC_KEY}",
      "valid_principals": "${SSH_USER}",
      "ttl": "1h"
  }
EOF
}

sshca_sign() {
  curl --silent \
       --header "X-Vault-Token: ${VAULT_TOKEN}" \
       --request POST \
       --data @${SSH_CA_CSR} \
       ${VAULT_ADDR}/v1/ssh-client-signer/sign/"${ROLE}" | \
       jq --join-output .data.signed_key \
       > ${SSH_USER_CERT}
}

sshca_csr
sshca_sign

echo -e "Your signed public key: $(head ${SSH_USER_CERT} -c 50) ..."

echo -e "Your token is: ${VAULT_TOKEN}"

@drdukes: The problem with that approach is that -you- decide what SSH user is going to be used/signed. I started looking at smallstep.

Yeah I know. This was an initial script to demonstrate functionality since the Vault cli can’t interact with the yubikey.

You should be able to put something similar together for ssh public key signing with these steps:

https://developers.yubico.com/PIV/Guides/SSH_with_PIV_and_PKCS11.html