Skip to content

Instantly share code, notes, and snippets.

@Franetse7
Forked from yorickdowne/README.md
Created October 4, 2021 07:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Franetse7/32115dc335d0bb9749f370796d606b48 to your computer and use it in GitHub Desktop.
Save Franetse7/32115dc335d0bb9749f370796d606b48 to your computer and use it in GitHub Desktop.
Take over BloxStaking KeyVault instance

/u/settleddown posted some excellent instructions on how to create your own BloxStaking KeyVault instance in AWS and keep it updated yourself.

I've adjusted these instructions to "take over" the existing instance, without needing to spin up an entirely new one. The Python script now prompts the user for the password.

NB: pip3 is very slow on WSL2. This can be resolved by running pip3 install -U keyring, and then mkdir -p ~/.config/python_keyring/ and edit vi ~/.config/python_keyring/keyringrc.cfg and paste into it:

[backend]
default-keyring=keyring.backends.null.Keyring

Get SSH key to be able to log into your KeyVault

After installing KeyVault via Blox Staking app, on the machine that Blox Staking app runs on, you can get the SSH key for the KeyVault, which is in your AWS account, us-west-1 region.

Copy paste the contents of the script into a file extract-blox-key.py

import base64
import binascii
import json
import hashlib
import getpass
import sys
from Crypto.Cipher import AES

def get_json_value(json,key,file,abort):
    try:
        value=json[key]
        return value
    except Exception as e:
        print("Could not find",key,"in file",file)
        print("Exception:",e)
        if abort:
            exit()

def main():
    blox_ip=None
    blox_port=None
    if len(sys.argv) != 2:
        print("Please give the path to the blox-github-ID.json file as a parameter:")
        print("  python3 extract-blox-key.py /path/to/blox-github-ID.json")
        print("If in WSL2, the path would be /mnt/c/Users/USER/AppData/Roaming/blox-live-desktop-app/blox-github-ID.json")
        exit()
    try:
        blox_file = open(sys.argv[1],"r")
    except Exception as e:
        print("Unable to open file",sys.argv[1])
        print("Exception:",e)
        exit()
    try:
        blox_json=json.load(blox_file)
    except Exception as e:
        print("Unable to parse file",sys.argv[1])
        print("Was it the right file?")
        print("Exception:",e)
        exit()
    blox_key=get_json_value(blox_json,'keyPair',sys.argv[1],True)
    blox_ip=get_json_value(blox_json,'publicIp',sys.argv[1],False)
    blox_port=get_json_value(blox_json,'port',sys.argv[1],False)
    blox_password=getpass.getpass(prompt="Please enter your Blox password: ")
    encodedpass=base64.b64encode(hashlib.sha256(blox_password.encode()).digest())[:32]
    try:
        unhexed = binascii.unhexlify(blox_key.strip())
    except Exception as e:
        print("The keyPair value wasn't formatted as expected - please check the input file")
        print("Exception:",e)
        exit()
    try:
        keydict = json.loads(base64.b64decode(AES.new(encodedpass,AES.MODE_ECB).decrypt(unhexed)))
    except Exception as e:
        print("Unable to decrypt the private key. Was the password correct?")
        print("Exception:",e)
        exit()
    print()
    print(keydict['privateKey'])
    print()
    print("Next, paste this private key into ~/.ssh/blox-key")
    print("Then give it a strong passphrase with 'ssh-keygen -f ~/.ssh/blox-key -p'")
    print("Change its permissions with 'chmod 600 ~/.ssh/blox-key'")
    if blox_ip and blox_port:
        print("And finally, connect to your KeyVault server with 'ssh -i ~/.ssh/blox-key -p ",blox_port," ec2-user@",blox_ip,"'",sep='')
    else:
        print("And finally, connect to your KeyVault server with 'ssh -i ~/.ssh/blox-key -p 2200 ec2-user@KEYVAULT_IP'")

if __name__ == "__main__":
    main()

Install the pycryptodome Python library: pip3 install pycryptodome

Then run the script to extract the key: python3 extract-blox-key.py /path/to/blox-LOGINMETHOD-ID.json

LOGINMETHOD would be github, google-oauth2 or windowslive; and ID is your specific ID assigned to you.

On WSL2 for example, with Github login, this would be python3 extract-blox-key.py /mnt/c/Users/USER/AppData/Roaming/blox-live-desktop-app/blox-github-ID.json

On MacOS with Google login, this would be python3 extract-blox-key.py "/Users/USER/Library/Application Support/blox-live-desktop-app/blox-google-oauth2-ID.json"

Take the resulting RSA PRIVATE KEY text and put it into a file ~/.ssh/blox-key, and set file permissions for the user only - file explorer in Windows or chmod 600 ~/.ssh/blox-key in WSL2. Set a strong passphrase for the key: ssh-keygen -f ~/.ssh/blox-key -p

Then connect to your blox instance via ssh -i ~/.ssh/blox-key -p 2200 ec2-user@VAULT-IP

Change KeyVault to use docker-compose

If you'd like to make updating KeyVault seamless, you can create a docker-compose for it. The following instructions are inside the KeyVault, using your SSH session.

First install docker-compose, paste these one line at a time:

sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
   
sudo chmod +x /usr/local/bin/docker-compose
    
docker-compose version

Create a keyvault.env file in ~ that contains your actual public IP (AWS instance elastic IP) instead of x.x.x.x:

VAULT_EXTERNAL_ADDRESS=x.x.x.x

Create a docker-compose.yml file in ~ containing this:

version: "3"
services:
  key_vault:
  restart: unless-stopped
  container_name: key_vault
  image: bloxstaking/key-vault:latest
  environment:
    - UNSEAL=true
    - VAULT_CLIENT_TIMEOUT=30s
  env_file: keyvault.env
  volumes:
    - ~/data:/data
    - ~/policies:/policies
  ports:
    - 8200:8200/tcp
  cap_add:
    - IPC_LOCK

Lastly, test that this is working with the following steps:

Stop running container:

docker stop key_vault
docker container rm key_vault

Start with docker-compose: docker-compose up -d

Followed by: docker ps

Check the logs: docker-compose logs -f key_vault

Check https://beaconcha.in/ . You may miss one attestation, but expect the next one to be successful.

Updating the vault is then as easy as: docker-compose pull and docker-compose down && docker-compose up -d

Optional: Remove seed from Blox Live

Blox Live keeps an encrypted copy of your seed on your desktop machine. That's only necessary for creating validators and recreating KeyVault through Blox Live. It can be very desirable to remove this seed from your desktop so that it can't be compromised.

Find the blox-LOGINMETHOD-ID.json, which on Windows is in C:\Users\USER\AppData\Roaming\blox-live-desktop-app and on MacOS in /Users/USER/Library/Application Support/blox-live-desktop-app/. You could make a copy of it on an encrypted USB key, or if you prefer, not do that, and just set up Blox Live from scratch if you ever want to add another validator. LOGINMETHOD can be one of github, google-oauth2 or windowslive, depending on how you log in.

Edit this file and remove the value for seed so it looks like this:

"seed": "",

Save the file. That's it. Blox Live will now be able to monitor your vault, but won't be able to add new validators or recreate the KeyVault, without being given that seed again.

@Franetse7
Copy link
Author

Merci pour le code

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