# Setting up a gaia validator using tmkms + yubikey ---- High Level Todo DEADLINE: Thursday 27th of October ✅ Figure out how to become a validator on mainnet (probobly the same as testnet) ✅ Get node running on testnet ✅ Get node using YubiHSM 2 on testnet ✅ Promote to Validator on Test Net ✅ Get validator proposing blocks ✅ Reset HSM Reset HSM Re-Provision Keys Confirm blocks are being signed ✅ (Re) Deploy Production/Staging Env ✅ Re-Deploy Clean Test Net server ✅ Re-Deploy Clean main net server ✅ cloned existing node to gaia-test.stg.hypha.coop (51.222.32.220) kvmid 209 ✅ deployed 2 new machines gaia-1.prod.hypha.coop (51.222.32.210) kvmid 102 gaia-1.stg.hypha.coop (51.222.32.212) kvmid 202 ✅ Install Gaia on STG and Prod @elon ✅ Configure data folder to NVME drive @elon ✅ Sync Theta and Mainnet @elon Milestone - Above done by Tuesday Monday ✅ Move Validator role to new Theda Server ✅ Enable TMKMS on Theta ✅ Move HSM ✅ Have theda start validating blocks ✅ Generate production keys ✅ Generate keys on Air gapped computer ✅ Provision Self Delegating keys on a Ledger ✅ Create paper backups of ✅ Self Delegation Keys ✅ Signing Keys ✅ HSM Keys ✅ Register new credentials on testnet ✅ testnet validator working with newly provisioned HSM keys Milestone - Above done by Wednsday Tuesday Verify offline secrets are available ✅ Move Validator over to Mainnet ✅ Move HSM to other computer ✅ Spin up TMKMS ✅ Register Validator ✅ Start signing blocks Milestone - Above done by Thursday Wednesday ⬜ Replace theda TMKMS with SoftHSM and TEST KEYS ⬜ Figure out how to filter out oneshot in prometheus ✅ Get panic setup (maybe in an ansible role? or a work log) ✅ Add to prometheus ✅ node exporter ✅ gaiad metrics ✅ promtail Check offline backups ✅priv_validator ✅ Encrypted QR ✅ Encrypted Text ✅ Printed Clear Text HSM ✅ 24 Words ✅ Ledger ✅ 24 Words Work Log at : https://hackmd.io/rVHxcNMNTSKmVotcaQ-lZw ## Meeting 2022-22-10 Meeting room in case you get kicked out Join Zoom Meeting https://us02web.zoom.us/j/3101837052?pwd=WFlUOVk4QUNiYVR2bUJiQ0duTEo1QT09 Meeting ID: 310 183 7052 Passcode: c1WFzz One tap mobile +12042727920,,3101837052#,,,,*438272# Canada +14388097799,,3101837052#,,,,*438272# Canada ---- References: - https://docs.osmosis.zone/osmosis-core/keys/tmkms - https://github.com/iqlusioninc/tmkms/blob/main/README.yubihsm.md - https://hub.cosmos.network/main/validators/kms/kms_ledger.html - https://github.com/hyphacoop/cosmos-ansible/blob/feature/163-kms-local/roles/kms/tasks/main.yml - https://github.com/hyphacoop/cosmos-configurations-private/wiki/Create-Validator ### Install tmkms * Use the [ansible role](https://github.com/hyphacoop/cosmos-ansible/blob/feature/163-kms-local/roles/kms/tasks/main.yml) that Yurko build for installing * Creates kms user * Generates tmks binary * Creates secret file (this is used for communication with the YubiKey) * Creates service * Starts up service ### Setup YubiKey 1. Run setup `tmkms yubihsm setup` This generates 4 authentication keys: - admin (authentication key 0x0001): full access to all HSM capabilities - operator (authentication key 0x0002): ability to generate new signing keys, export/import encrypted backups of keys, and view the audit log - auditor (authentication key 0x0003): ability to view and consume the audit log - validator (authentication key 0x0004): ability to generate signatures using signing keys loaded within the device **Note** - none of these keys the actual validator signing keys. - these keys are limited to access various other keys that can be stored on the YubiKey ## Generate signing key for Hypha validator `tmkms yubihsm keys generate 1 -p cosmosvalconspub -b hypha-1.enc` ### Setup tmkms ``` # Tendermint KMS configuration file ## Chain Configuration ### Cosmos Hub Network [[chain]] id = "theta-testnet-001" # ??? what are these values key_format = { type = "bech32", account_key_prefix = "cosmospub", consensus_key_prefix = "cosmosvalconspub" } state_file = "/home/kms/.tmkms/config/state/priv_validator_state.json" ## Signing Provider Configuration ### Software-based Signer Configuration ### KMS Signer Configuration [[providers.yubihsm]] adapter = { type = "usb" } #auth = { key = 4, password = "kms-validator-password-1md4czuye5zq56cmz35rkee0dhsmgm602" } auth = { key = 1, password = "password" } keys = [ { key = 1, type = "consensus", chain_ids = ["theta-testnet-001"] }, ] ## Validator Configuration [[validator]] chain_id = "theta-testnet-001" addr = "tcp://127.0.0.1:26659" secret_key = "/home/kms/.tmkms/config/secrets/kms-identity.key" protocol_version = "v0.34" reconnect = true ``` ### create new key gaiad keys add new-valildator request from testnet faucet to address `cosmos13mddt6wv2l5lsk9f7d83vtuv580lsqvdhhe5td` cosmosvalconspub1zcjduepqm5680numd9pvz20vp0p6yjvx0nls82ltgx8f8vmd3tdpsylgqg6st70n5k ### parsing keys ``` gaiad keys parse cosmosvalconspub1zcjduepqm5680numd9pvz20vp0p6yjvx0nls82ltgx8f8vmd3tdpsylgqg6st70n5k human: cosmosvalconspub bytes: 1624DE6420DD3477CF9B6942C129EC0BC3A249867CFF03ABEB418E93B36D8ADA1813E80235 ``` ``` import base64 b= bytes.fromhex("1624DE6420DD3477CF9B6942C129EC0BC3A249867CFF03ABEB418E93B36D8ADA1813E80235") base64EncodedStr = base64.b64encode(b) print(base64EncodedStr) ``` `FiTeZCDdNHfPm2lCwSnsC8OiSYZ8/wOr60GOk7NtitoYE+gCNQ==` `d1pQSuSH52WmU7gqiFgI0kuIgU8=` Udit's local version gaiad tendermint show-validator {"@type":"/cosmos.crypto.ed25519.PubKey","key":"9QIo4gEbSEBoOapeO2fasRqCxu2TBmZ33upUqNd+1Ks="} Hex Version of key: f50228e2011b48406839aa5e3b67dab11a82c6ed93066677deea54a8d77ed4ab gaiad tendermint show-address cosmosvalcons1wad9qjhyslnktfjnhq4gskqg6f9c3q20cq5e3k gaiad keys parse cosmosvalcons1wad9qjhyslnktfjnhq4gskqg6f9c3q20cq5e3k human: cosmosvalcons bytes: 775A504AE487E765A653B82A885808D24B88814F gaiad keys parse 775A504AE487E765A653B82A885808D24B88814F formats: - cosmos1wad9qjhyslnktfjnhq4gskqg6f9c3q20f8ns3y - cosmospub1wad9qjhyslnktfjnhq4gskqg6f9c3q20kplrgp - cosmosvaloper1wad9qjhyslnktfjnhq4gskqg6f9c3q20vn89ah - cosmosvaloperpub1wad9qjhyslnktfjnhq4gskqg6f9c3q207s7xlj - cosmosvalcons1wad9qjhyslnktfjnhq4gskqg6f9c3q20cq5e3k - cosmosvalconspub1wad9qjhyslnktfjnhq4gskqg6f9c3q20059w4r ### Importing key to KMS setup key tmkms use OP key in config copy validator_key.json to kms home tmkms import json tmkms key list to verify tmkms switch to validator key in config tmkms test 1 to see if signing works use gaiad to save show validator and show address before deleting files add tokens to account and verify make validator with gaiad tx staking create-validator ## Re-Provisioning Work 2022-23-10 - Cloned testing gaia over to vmid 209. - Deleted old one - Provisioned `gaia-1.prod.hypha.coop` and `gaia-2.prod.hypha.coop` - Updted DNS - Ansible for deployment: https://github.com/hyphacoop/ansible-provision-vm/blob/main/inventory.yml - Installed standard ansibles on both servers: Inventory ``` all: vars: # Sensible defaults ansible_user: sysadmin ansible_python_interpreter: /usr/bin/python3 # Set root and sysadmin passwords on all servers root_password: "{{ secret_root_password }}" sysadmin_password: "{{ secret_root_password }}" # Keys to add to all servers ssh_user_keys: - name: yurko key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCtv4I2W8TlVsWKKHwASF78cGrn06BJi9dGQQQksW0Ke9ED/KJG2pvG4GXnh57/AOuJtUaS3gXBEj/knE3t/qtvO2cUg1EufnkItzNLdY1B0Hwm98I8O7JdhE> - name: "elon" key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCt7N4cJCFFmetGyDo2giMdPlHOBOdEJt8DnidBTMxevlGi02YVLwdYwbPtdoSHJKRlY4boV80sPOhMI3Im2TXNXHQIhO2LWKdSUTdfFU5ul+ySeZlUm3eDpt> monitor_server: monitor.prod.hypha.coop loki_url: "{{monitor_server}}:443/loki/api/v1/push" loki_protocol: "https" loki_username: loki loki_password: "{{secret_loki_password}}" # cadvisor_exporter_port: 9110 children: gaiad: vars: monitor_job: "production" firewall_ports: - "ssh": port: 22 - "tendermint": port: 26656 # - "nodeexporter": # port: 9100 # source: "{{ monitor_server }}" # sourceIPv6: "2604:a880:cad:d0::f49:4001" hosts: gaia-1.prod.hypha.coop: gaia-1.stg.hypha.coop: ``` Inventory: ``` - hosts: gaiad become: true gather_facts: true roles: - hypha.common.provision_ssh_keys - hypha.common.harden_ssh - hypha.common.setup - hypha.common.unattended_upgrades # - geerlingguy.docker - hypha.common.firewall # - hypha.common.node_exporter # - hypha.common.prometheus_exporter_addnode # - hypha.common.prometheus_exporter_docker # - hypha.common.promtail ``` ## Co-Work with elon 2022-23-10 ### Factory Rest and Re-Provision HSM - Factory Rest HSM - Updated TMKMS to use default password - Run Setup ``` kms@gaia-test:~$ tmkms yubihsm setup -c .tmkms/config/tmkms.toml This process will *ERASE* the configured YubiHSM2 and reinitialize it: - YubiHSM serial: 0020780003 Authentication keys with the following IDs and passwords will be created: - key 0x0001: admin: mouse spider donkey media nest casino inflict shaft feed differ father away glass husband gap galaxy choose patrol romance inject rhythm useless dawn satoshi - authkey 0x0002 [operator]: kms-operator-password-1l5mzau8pnxeheydw27y7x86z0q6u3c6p - authkey 0x0003 [auditor]: kms-auditor-password-1r7ssmvdnkgeek4aa3fetn5jccsypukxr - authkey 0x0004 [validator]: kms-validator-password-1jmu34jezw9fks0p27sk7vsnqvvstmuq0 - wrapkey 0x0001 [primary]: f44a30b4be80a9a14df0a2bfc78e04cd19fa94cc074e2c6c332295a0a21bb00a *** Are you SURE you want erase and reinitialize this HSM? (y/N): y 2022-10-23T16:55:56.258697Z WARN yubihsm::client: factory resetting HSM device! all data will be lost! 2022-10-23T16:55:57.287690Z INFO yubihsm::client: waiting for device reset to complete 2022-10-23T16:56:02.735374Z INFO yubihsm::setup: installed temporary setup authentication key into slot 65534 2022-10-23T16:56:02.755526Z WARN yubihsm::setup: deleting default authentication key from slot 1 2022-10-23T16:56:02.782396Z INFO yubihsm::setup::profile: installing role: admin:2022-10-23T16:55:44Z 2022-10-23T16:56:02.806398Z INFO yubihsm::setup::profile: installing role: operator:2022-10-23T16:55:44Z 2022-10-23T16:56:02.826939Z INFO yubihsm::setup::profile: installing role: auditor:2022-10-23T16:55:44Z 2022-10-23T16:56:02.847402Z INFO yubihsm::setup::profile: installing role: validator:2022-10-23T16:55:44Z 2022-10-23T16:56:02.867951Z INFO yubihsm::setup::profile: installing wrap key: primary:2022-10-23T16:55:44Z 2022-10-23T16:56:02.891375Z INFO yubihsm::setup::profile: storing provisioning report in opaque object 0xfffe 2022-10-23T16:56:02.917028Z WARN yubihsm::setup: deleting temporary setup authentication key from slot 65534 Success reinitialized YubiHSM (serial: 0020780003) kms@gaia-test:~$ ``` Imported `priv_validator_key.json` `tmkms yubihsm keys import -t json -i 1 priv_validator_key.json -c .tmkms/config/tmkms.toml` Checked Key `tmkms yubihsm keys list -c .tmkms/config/tmkms.toml` ### Moved HSM to target server: On target srever edit tmkms.conf to update key Update gaiad confg: ``` # Comment out these two lines # Path to the JSON file containing the private key to use as a validator in the consensus protocol # priv_validator_key_file = "config/priv_validator_key.json" # Path to the JSON file containing the last sign state of a validator # priv_validator_state_file = "data/priv_validator_state.json" # Change this line (or add it if not exists) priv_validator_laddr = "tcp://127.0.0.1:26659" ``` UPDATE ANSIBLE add to tmkms template ``` keys = [ { key = 1, type = "consensus", chain_ids = ["theta-testnet-001"] }, ] ``` ### Possible airgap HSM provisioning Require `gaiad`,`tmkms` binaries and `tmkms.yml` file ``` ./gaiad init Solidarity --home . mv ~/.gaia/config/priv_validator_key.json . ./tmkms yubihsm setup # update tmkms with operator key tmkms yubihsm keys import -t json -i 1 priv_validator_key.json # Backup - priv_validator_key.json - yubikey output ``` ## Produciton key Generatiosn ```shell mkdir home mount -t tmpfs tmpfs home cd home cp ../gaia . cp ../tmkms . cp ../tmkms.conf . ./gaiad init Solidarity --home . mv config/priv_validator_key.json . ./tmkms yubihsm setup # Convert output to PDF then print tmkms yubihsm keys import -t json -i 1 priv_validator_key.json #Encrypt priv_validator_key openssl aes-256-cbc -a -salt -pbkdf2 -pass pass:<REDACTED> -in priv_validator_key.json -out priv_validator_key.enc # Decrypt test openssl aes-256-cbc -d -a -salt -pbkdf2 -in priv_validator_key.enc # convert priv_validator_key.enc to pdf # print both PDFs ``` ## Production key on Theda test ```bash ./gaiad tx staking create-validator \ --amount 1000000uatom \ --pubkey '{"@type":"/cosmos.crypto.ed25519.PubKey","key":"qRzITWr/nQ+J31ODy8fZDD/SvUorYZaH5C786x5VQ9k="}' \ --moniker "Validator5000" \ --chain-id "theta-testnet-001" \ --commission-rate "0.10" \ --commission-max-rate "0.20" \ --commission-max-change-rate "0.01" \ --min-self-delegation "1000000" \ --gas "auto" --fees 100uatom \ --from validator_hypha \ --sign-mode amino-json \ --node http://sentry-01.theta-testnet.polypore.xyz:26657 \ --home . ``` ```json { "body": { "messages": [ { "@type": "/cosmos.staking.v1beta1.MsgCreateValidator", "description": { "moniker": "Validator5000", "identity": "", "website": "", "security_contact": "", "details": "" }, "commission": { "rate": "0.100000000000000000", "max_rate": "0.200000000000000000", "max_change_rate": "0.010000000000000000" }, "min_self_delegation": "1000000", "delegator_address": "cosmos1mt6mf0ny6cstytjz00kz3h7cyyrh9m5sllef6r", "validator_address": "cosmosvaloper1mt6mf0ny6cstytjz00kz3h7cyyrh9m5s6tduks", "pubkey": { "@type": "/cosmos.crypto.ed25519.PubKey", "key": "qRzITWr/nQ+J31ODy8fZDD/SvUorYZaH5C786x5VQ9k=" }, "value": { "denom": "uatom", "amount": "1000000" } } ], "memo": "", "timeout_height": "0", "extension_options": [], "non_critical_extension_options": [] }, "auth_info": { "signer_infos": [], "fee": { "amount": [ { "denom": "uatom", "amount": "100" } ], "gas_limit": "173697", "payer": "", "granter": "" } }, "signatures": [] } ``` ## Production key on mainnet ```bash #Add hypha validator ledger to daiaga ./gaiad keys add hypha_validator --ledger --home . #Create validator ./gaiad tx staking create-validator \ --amount 1000000uatom \ --pubkey '{"@type":"/cosmos.crypto.ed25519.PubKey","key":"qRzITWr/nQ+J31ODy8fZDD/SvUorYZaH5C786x5VQ9k="}' \ --moniker " hypha-coo �" \ --chain-id "cosmoshub-4" \ --commission-rate "0.08" \ --commission-max-rate "0.20" \ --commission-max-change-rate "0.01" \ --min-self-delegation "1000000" \ --gas "auto" --fees 100uatom \ --from validator_hypha \ --sign-mode amino-json \ --node http://one.cosmos-mainnet.polypore.xyz:26657 \ --home . ```