install.fairie/.config/taskfiles/security/Taskfile-yubikey.yml

324 lines
11 KiB
YAML
Raw Normal View History

2022-12-24 12:04:59 -08:00
---
version: '3'
todo: Collect YUBI_USER_PIN, YUBI_ADMIN_PIN, YUBI_LAST_NAME, YUBI_EMAIL, YUBI_FIRST_NAME, YUBI_TITLE (Principal Software Engineer), YUBI_ALT_NAME, YUBI_ALT_EMAIL, YUBI_ALT_TITLE
vars:
YUBI_MASTER_EMAIL: no-reply@megabyte.space
YUBI_MASTER_NAME: Megabyte Labs
env:
GNUPGHOME:
sh: echo "$HOME/.gnupghome"
MASTER_KEY:
sh: |
if [ -f .yubi-masterkey ]; then
cat .yubi-masterkey
else
LC_ALL=C tr -dc '[:upper:]' < /dev/urandom | fold -w 30 | head -n1
fi
tasks:
add:identities:
env:
KEYID: '{{.KEYID}}'
YUBI_ALT_EMAIL:
sh: jq -r '.YUBI_ALT_EMAIL' .yubi.json
YUBI_ALT_NAME:
sh: jq -r '.YUBI_ALT_NAME' .yubi.json
YUBI_ALT_TITLE:
sh: jq -r '.YUBI_ALT_TITLE' .yubi.json
YUBI_EMAIL:
sh: jq -r '.YUBI_EMAIL' .yubi.json
YUBI_FIRST_NAME:
sh: jq -r '.YUBI_FIRST_NAME' .yubi.json
YUBI_LAST_NAME:
sh: jq -r '.YUBI_LAST_NAME' .yubi.json
YUBI_TITLE:
sh: jq -r '.YUBI_TITLE' .yubi.json
cmds:
- echo -e "${YUBI_FIRST_NAME} ${YUBI_LAST_NAME}\n${YUBI_EMAIL}\n${YUBI_TITLE}\n" | gpg --command-fd 0 --pinentry-mode loopback
--passphrase "$MASTER_KEY" --expert --edit-key "$KEYID" adduid save
- echo -e "${YUBI_ALT_NAME}\n${YUBI_ALT_EMAIL}\n${YUBI_ALT_TITLE}\n" | gpg --command-fd 0 --pinentry-mode loopback
--passphrase "$MASTER_KEY" --expert --edit-key "$KEYID" adduid save
card:
vars:
KEYID:
sh: gpg --keyid-format long --list-keys {{.YUBI_MASTER_EMAIL}} | grep "pub rsa" | sed 's/pub rsa4096\///' | sed 's/^\([^ ]*\).*/\1/'
env:
KEYID: '{{.KEYID}}'
YUBI_ADMIN_PIN:
sh: jq -r '.YUBI_ADMIN_PIN' .yubi.json
YUBI_EMAIL:
sh: jq -r '.YUBI_EMAIL' .yubi.json
YUBI_FIRST_NAME:
sh: jq -r '.YUBI_FIRST_NAME' .yubi.json
YUBI_LAST_NAME:
sh: jq -r '.YUBI_LAST_NAME' .yubi.json
YUBI_USER_PIN:
sh: jq -r '.YUBI_USER_PIN' .yubi.json
cmds:
- cp -rf ~/.gnupg ~/.gnupg.bak
- task: card:reset
- echo -e "admin\nkdf-setup\n12345678\n" | gpg --command-fd 0 --pinentry-mode loopback --card-edit
- echo -e "admin\npasswd\n1\n123456\n${YUBI_USER_PIN}\n${YUBI_USER_PIN}\nq\n" | gpg --command-fd 0 --pinentry-mode loopback --card-edit
- echo -e "admin\npasswd\n3\n12345678\n${YUBI_ADMIN_PIN}\n${YUBI_ADMIN_PIN}\nq\n" | gpg --command-fd 0 --pinentry-mode loopback --card-edit
- echo -e "admin\nname\n${YUBI_LAST_NAME}\n${YUBI_FIRST_NAME}\n${YUBI_ADMIN_PIN}\nlang\nen\nlogin\n${YUBI_EMAIL}\nquit" | gpg --command-fd 0 --pinentry-mode loopback --card-edit
- task: card:keys
vars:
KEYID: '{{.KEYID}}'
# - gpg --delete-secret-key "$KEYID"
# - mv ~/.gnupg ~/.gnupg-generated # TODO
# - rm -rf ~/.gnupg
# - mv ~/.gnupg.bak ~/.gnupg
card:keys:
env:
KEYID: '{{.KEYID}}'
YUBI_ADMIN_PIN:
sh: jq -r '.YUBI_ADMIN_PIN' .yubi.json
cmds:
- echo -e "key 1\nkeytocard\n1\n${MASTER_KEY}\n${YUBI_ADMIN_PIN}\n" | gpg --command-fd 0 --pinentry-mode loopback --edit-key "$KEYID"
- echo -e "key 2\nkeytocard\n2\n${MASTER_KEY}\n${YUBI_ADMIN_PIN}\n" | gpg --command-fd 0 --pinentry-mode loopback --edit-key "$KEYID"
- echo -e "key 3\nkeytocard\n3\n${MASTER_KEY}\n${YUBI_ADMIN_PIN}\n" | gpg --command-fd 0 --pinentry-mode loopback --edit-key "$KEYID"
card:reset:
cmds:
- echo -e "admin\nfactory-reset\ny\nyes\n" | gpg --command-fd 0 --pinentry-mode loopback --card-edit
status:
- '[ -n "$DONT_RESET_YUBIKEY" ]'
check:entropy:
vars:
ENTROPY_AVAIL:
sh: |
if [ -f /proc/sys/kernel/random/entropy_avail ]; then
cat /proc/sys/kernel/random/entropy_avail
fi
cmds:
- |
if [ '{{.ENTROPY_AVAIL}}' -lt '2000' ]; then
.config/log error 'The entropy pool value is not high enough. It must be greater than 2000!' && exit 1
fi
status:
- '[ "{{OS}}" != "linux" ]'
export:
vars:
KEYID:
sh: gpg --keyid-format long --list-keys {{.YUBI_MASTER_EMAIL}} | grep "pub rsa" | sed 's/pub rsa4096\///' | sed 's/^\([^ ]*\).*/\1/'
cmds:
- task: public:export
vars:
KEYID: '{{.KEYID}}'
# - task: revocation:export
# vars:
# KEYID: '{{.KEYID}}'
- task: secrets:export
vars:
KEYID: '{{.KEYID}}'
- task: public:upload
vars:
KEYID: '{{.KEYID}}'
# - task: usb
- task: card
# - task: usb:unmount
generate:authentication:
env:
KEYID: '{{.KEYID}}'
cmds:
- echo -e "8\nS\nE\nA\nQ\n4096\n1y\n" | gpg --command-fd 0 --pinentry-mode loopback --passphrase "$MASTER_KEY"
--expert --edit-key "$KEYID" addkey save
status:
- '[ -n "$YUBIKEY_BACKUP" ]'
generate:encryption:
env:
KEYID: '{{.KEYID}}'
cmds:
- echo -e "6\n4096\n1y\n" | gpg --command-fd 0 --pinentry-mode loopback --passphrase "$MASTER_KEY" --expert --edit-key "$KEYID" addkey save
status:
- '[ -n "$YUBIKEY_BACKUP" ]'
generate:master:
cmds:
- mkdir -p "$GNUPGHOME" && chmod 700 "$GNUPGHOME"
- mkdir -p "$GNUPGHOME/private-keys-v1.d"
- chmod 700 "$GNUPGHOME/private-keys-v1.d"
# Original: echo -e "8\nE\nS\nQ\n4096\n0\ny\n{{.YUBI_MASTER_NAME}}\n{{.YUBI_MASTER_EMAIL}}\n\no\n" -- removed \ny for macOS
- echo -e "8\nE\nS\nQ\n4096\n0\n{{.YUBI_MASTER_NAME}}\n{{.YUBI_MASTER_EMAIL}}\n\no\n" | gpg --expert --command-fd 0
--pinentry-mode loopback --passphrase "$MASTER_KEY" --full-generate-key
status:
- '[ -n "$YUBIKEY_BACKUP" ]'
generate:signing:
env:
KEYID: '{{.KEYID}}'
cmds:
- echo -e "4\n4096\n1y\n" | gpg --command-fd 0 --pinentry-mode loopback --passphrase "$MASTER_KEY" --expert --edit-key "$KEYID" addkey save
status:
- '[ -n "$YUBIKEY_BACKUP" ]'
generate:subkeys:
vars:
KEYID:
sh: gpg --keyid-format long --list-keys {{.YUBI_MASTER_EMAIL}} | grep "pub rsa" | sed 's/pub rsa4096\///' | sed 's/^\([^ ]*\).*/\1/'
cmds:
- task: generate:signing
vars:
KEYID: '{{.KEYID}}'
- task: generate:encryption
vars:
KEYID: '{{.KEYID}}'
- task: generate:authentication
vars:
KEYID: '{{.KEYID}}'
- task: add:identities
vars:
KEYID: '{{.KEYID}}'
prepare:
desc: Prepares an environment by provisioning all the required software / preliminary steps
cmds:
- mkdir -p "$GNUPGHOME" && chmod 700 "$GNUPGHOME"
- echo '{{.MASTER_KEY}}' > .yubi-masterkey
- task: prepare:init
- task: :install:service:start
vars:
SERVICE: pcscd
- task: check:entropy
- task: generate:master
- task: generate:subkeys
vars:
KEYID:
sh: gpg --keyid-format long --list-keys {{.YUBI_MASTER_EMAIL}} | grep "pub rsa" | sed 's/pub rsa4096\///' | sed 's/^\([^ ]*\).*/\1/'
- task: export
- task: :security:ssh:yubikey
prepare:init:
cmds:
- task: prepare:init:continue
status:
- '[ -n "$YUBIKEY_BACKUP" ]'
prepare:init:continue:
deps:
- :install:requirements:yubikey
- :security:gpg:conf
- task: :security:gpg:conf
vars:
CONFIG_DIR_PATH:
sh: echo "$GNUPGHOME"
- :security:gpg:conf:agent
- task: :security:gpg:conf:agent
vars:
CONFIG_DIR_PATH:
sh: echo "$GNUPGHOME"
public:export:
todo: This differs from guide
env:
KEYID: '{{.KEYID}}'
cmds:
- mkdir -p "$GNUPGHOME" && chmod 700 "$GNUPGHOME"
- gpg --armor --export "$KEYID" > "$GNUPGHOME/gpg-$KEYID-$(date +%F).asc"
status:
- '[ -n "$YUBIKEY_BACKUP" ]'
public:upload:
cmds:
- gpg --send-key "$KEYID"
- gpg --keyserver pgp.mit.edu --send-key "$KEYID"
- gpg --keyserver keys.gnupg.net --send-key "$KEYID"
- gpg --keyserver hkps://keyserver.ubuntu.com:443 --send-key "$KEYID"
status:
- |
[ "$(echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1)" != "0" ] || [ -n "$YUBIKEY_BACKUP" ]
revocation:export:
env:
KEYID: '{{.KEYID}}'
cmds:
- mkdir -p "$GNUPGHOME" && chmod 700 "$GNUPGHOME"
- gpg --output $GNUPGHOME/revoke.asc --gen-revoke "$KEYID"
status:
- '[ -n "$YUBIKEY_BACKUP" ]'
secrets:export:
env:
KEYID: '{{.KEYID}}'
cmds:
- mkdir -p "$GNUPGHOME" && chmod 700 "$GNUPGHOME"
- gpg --armor --export-secret-keys --command-fd 0 --pinentry-mode loopback
--passphrase "$MASTER_KEY" --expert "$KEYID" > $GNUPGHOME/mastersub.key
- gpg --armor --export-secret-subkeys --command-fd 0 --pinentry-mode loopback
--passphrase "$MASTER_KEY" --expert "$KEYID" > $GNUPGHOME/sub.key
status:
- '[ -n "$YUBIKEY_BACKUP" ]'
secure:delete:
env:
KEYID: '{{.KEYID}}'
cmds:
- sudo srm -rf "$GNUPGHOME" || sudo rm -rf "$GNUPGHOME"
- gpg --delete-secret-key "$KEYID"
stub:
summary: |
Run this to re-stub the GPG files to point to the current YubiKey.
cmds:
- gpg-connect-agent "scd serialno" "learn --force" /bye
usb:
summary: |
# Backup Keys (Including Master) to USB and Encrypt
This task will partition a USB with two partitions. One partition will
be encrypted and contain your GPG keys (including the master key). The other
partition will not be encrypted and contain your public key.
cmds:
- task: usb:create
- task: usb:mount
- mkdir ~/.gpg-encrypted-storage && cp -rf $GNUPGHOME ~/.gpg-encrypted-storage # TODO /mnt/gpg-encrypted-storage
- mkdir ~/.gpg-public && cp $GNUPGHOME/gpg-$KEYID* ~/.gpg-public # TODO /mnt/gpg-public
status:
- '[ -n "$YUBIKEY_BACKUP" ]'
usb:create:
deps:
- :security:disk:encrypt:create
- :security:disk:unencrypted:create
usb:mount:
deps:
- :security:disk:encrypt:mount
- :security:disk:unencrypted:mount
usb:unmount:
deps:
- :security:disk:encrypt:unmount
- :security:disk:unencrypted:unmount
status:
- '[ -n "$YUBIKEY_BACKUP" ]'
yubikey-agent:
deps:
- :install:software:yubikey-agent
summary: |
# Sets Up Resident SSH Key
According to [this guide](https://github.com/jamesog/yubikey-ssh), the yubikey-agent
package is a simplest, best way of utilizing a YubiKey for SSH by leveraging
YubiKey's onboard SSH key generator. By using this method, the private key never leaves
the YubiKey which increases security tremendously.
See: https://github.com/FiloSottile/yubikey-agent
A new method is detailed here: https://www.yubico.com/blog/github-now-supports-ssh-security-keys/
It may be worth migrating to that approach.
cmds:
- brew services start yubikey-agent
- yubikey-agent -setup