Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save beastycoding/97c5d31db5807ed0f7ec3590ce808933 to your computer and use it in GitHub Desktop.
Save beastycoding/97c5d31db5807ed0f7ec3590ce808933 to your computer and use it in GitHub Desktop.
How to use use Bitwarden CLI for SSH-Keys in macOS

How to use use Bitwarden CLI for SSH-Keys in macOS

If you want to use Touch ID have a look at: How to use use Bitwarden CLI with macOS Touch ID

Wirtten and tested on macOS Ventura

Add SSH-Keys to Bitwarden

Before you can use Bitwarden CLI for your SSH private keys you have to add them to your Bitwarden account. Just create a normal login. The name, username and URI fields doesn't matter for my functions.

What madders is that you add your private SSH-Key as attachment (If your key is encrypted add type the password in the password field) and add a new custom field of type bool:

Name the custom field ssh, it doesn't matter if you check the box or not:

Afterwards your new login should look simmilar to this:

Reapeat this for every key you want to add.

Use Bitwarden CLI to ssh into servers

Add the following code to your .zshrc:

ssh-add-with-passphrase () {
    key_file="$(mktemp)"
    echo "${1}" > ${key_file}
    chmod 600 ${key_file}
    if [ -z "${2}" ]; then
        ssh-add ${key_file}
    else
        expect << EOF
            spawn ssh-add ${key_file}
            expect "Enter passphrase"
            send "${2}\n"
            expect eof
EOF
    fi 
    rm -rf ${key_file}
}

ssh-add-bw-keys () {
    bw_status=$(bw status | jq -r '.status')
    if [[ ${bw_status} != 'unlocked' ]]; then 
        echo "Bitwarden Vault: ${bw_status}"
        echo "Please login:"
        bw --regenerate-session-key
    fi
    bw sync &> /dev/null
    bw list items | jq -c '.[] | select(.fields[0].name=="ssh" and .attachments != null)' | while read key; do
        local key_pw=$(printf '%q' $(jq -r '.login.password' <<< "${key}"))
        local key_id=$(jq -r '.id' <<< "${key}")
        local key_file_name=$(jq -r '.attachments[].fileName' <<< "${key}")
        local id_ssh=$(bw get attachment ${key_file_name} --itemid ${key_id} --raw)
        ssh-add-with-passphrase "${id_ssh}" "${key_pw}" &> /dev/null
    done
}

ssh () {
    echo "Temporary adding keys from bitwarden..."
    ssh_exec=$(sh -c "which ssh")
    ssh-add-bw-keys
    nohup bash -c 'sleep 10; ssh-add -D &> /dev/null' </dev/null >/dev/null 2>&1 &
    disown
    echo -e '\e[1A\e[KSuccessfull!'
    ${ssh_exec} $@
}

If you're using ansible also add:

ansible () {
    ansible_exec=$(sh -c "which ansible")
    ssh-add-bw-keys
    ${ansible_exec} $@
    ssh-add -D &> /dev/null
}

Afterwards reopen the Terminal or type exec zsh.

With this function wrapper, you will be prompted for your Bitwarden masterkey everytime you use ssh. If you rather want to use your sudopassword or Touch ID have look here. What happens here, is that we query all SHH-Keys know to bitwarden and add them to our SSH-Agent. For me it takes about 2 seconds to find and add all my SSH-Keys. After 10 seconds all keys are deleted again.

Adding all Keys migth not be the most elegant way and writting the ssh-key temporaly to disk not the most secure way. But I hope to see a officail solution soon™.

Meanwhile if you have a better solution, feel free to leave a comment! I already tried SSH-ASKPASS and injecting a variable into spawn but failed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment