DEV Community

πŸ¦„N BπŸ›‘
πŸ¦„N BπŸ›‘

Posted on • Updated on

Get a Root Token for HashiCorp Vault

Sometimes, in an emergency (or, more likely in my case, I forgot something important) I'll need to generate a Vault Root Token, as a sort of "break glass" procedure.

Both https://www.vaultproject.io/docs/commands/operator/generate-root.html and https://learn.hashicorp.com/vault/operations/ops-generate-root seem to either be missing steps or doubling steps, respectively.

So, to add to the confusion, I've decided to write my own "guide", hastily copied from my favorite documentation generation tool,
history | grep vault >> post-this-somewhere.md.

NOTE: This assumes you already have a test Vault running and unsealed,
and that it uses a single Unseal key. Using a single Unseal key is unsafe and, frankly, a bit embarrassing. Don't let your mother or your lead SysAdmin watch you doing this. If you are the lead SysAdmin, just close your eyes for the entirety of this exercise.

Make a Test Vault if you don't have one already

File Backend with Open Source Vault

Create a test-vault.hcl config file to work with.

mkdir test
cd test
vi test-vault.hcl
Enter fullscreen mode Exit fullscreen mode

Contents of test-vault.hcl should be:

storage "file" {
  path = "./test-vault/data"
}


disable_mlock = true

listener "tcp" {
  address = "127.0.0.1:8200"
  tls_disable = true
}

ui = true
Enter fullscreen mode Exit fullscreen mode

Run a Test Vault from the above configuration file:

wget 'https://releases.hashicorp.com/vault/1.1.2/vault_1.1.2_linux_amd64.zip'
unzip vault_1.1.2_linux_amd64.zip
./vault server -config-file=test-vault.hcl
cd ../
export VAULT_ADDR=http://127.0.0.1:8200
Enter fullscreen mode Exit fullscreen mode

Get the Vault Help for Generating Vault Root Tokens

generate-root-test1$ vault operator generate-root --help
Usage: vault operator generate-root [options] [KEY]

  Generates a new root token by combining a quorum of share holders. One of
  the following must be provided to start the root token generation:

    - A base64-encoded one-time-password (OTP) provided via the "-otp" flag.
      Use the "-generate-otp" flag to generate a usable value. The resulting
      token is XORed with this value when it is returned. Use the "-decode"
      flag to output the final value.

    - A file containing a PGP key or a keybase username in the "-pgp-key"
      flag. The resulting token is encrypted with this public key.

  An unseal key may be provided directly on the command line as an argument to
  the command. If key is specified as "-", the command will read from stdin. If
  a TTY is available, the command will prompt for text.

  Generate an OTP code for the final token:

      $ vault operator generate-root -generate-otp

  Start a root token generation:

      $ vault operator generate-root -init -otp="..."
      $ vault operator generate-root -init -pgp-key="..."

  Enter an unseal key to progress root token generation:

      $ vault operator generate-root -otp="..."

HTTP Options:

  -address=<string>
      Address of the Vault server. The default is https://127.0.0.1:8200. This
      can also be specified via the VAULT_ADDR environment variable.

  -agent-address=<string>
      Address of the Agent. This can also be specified via the
      VAULT_AGENT_ADDR environment variable.

  -ca-cert=<string>
      Path on the local disk to a single PEM-encoded CA certificate to verify
      the Vault server's SSL certificate. This takes precedence over -ca-path.
      This can also be specified via the VAULT_CACERT environment variable.

  -ca-path=<string>
      Path on the local disk to a directory of PEM-encoded CA certificates to
      verify the Vault server's SSL certificate. This can also be specified
      via the VAULT_CAPATH environment variable.

  -client-cert=<string>
      Path on the local disk to a single PEM-encoded CA certificate to use
      for TLS authentication to the Vault server. If this flag is specified,
      -client-key is also required. This can also be specified via the
      VAULT_CLIENT_CERT environment variable.

  -client-key=<string>
      Path on the local disk to a single PEM-encoded private key matching the
      client certificate from -client-cert. This can also be specified via the
      VAULT_CLIENT_KEY environment variable.

  -mfa=<string>
      Supply MFA credentials as part of X-Vault-MFA header. This can also be
      specified via the VAULT_MFA environment variable.

  -namespace=<string>
      The namespace to use for the command. Setting this is not necessary
      but allows using relative paths. -ns can be used as shortcut. The
      default is (not set). This can also be specified via the VAULT_NAMESPACE
      environment variable.

  -output-curl-string
      Instead of executing the request, print an equivalent cURL command
      string and exit. The default is false.

  -policy-override
      Override a Sentinel policy that has a soft-mandatory enforcement_level
      specified The default is false.

  -tls-server-name=<string>
      Name to use as the SNI host when connecting to the Vault server via TLS.
      This can also be specified via the VAULT_TLS_SERVER_NAME environment
      variable.

  -tls-skip-verify
      Disable verification of TLS certificates. Using this option is highly
      discouraged as it decreases the security of data transmissions to and
      from the Vault server. The default is false. This can also be specified
      via the VAULT_SKIP_VERIFY environment variable.

  -wrap-ttl=<duration>
      Wraps the response in a cubbyhole token with the requested TTL. The
      response is available via the "vault unwrap" command. The TTL is
      specified as a numeric string with suffix like "30s" or "5m". This can
      also be specified via the VAULT_WRAP_TTL environment variable.

Output Options:

  -format=<string>
      Print the output in the given format. Valid formats are "table", "json",
      or "yaml". The default is table. This can also be specified via the
      VAULT_FORMAT environment variable.

Command Options:

  -cancel
      Reset the root token generation progress. This will discard any
      submitted unseal keys or configuration. The default is false.

  -decode=<string>
      The value to decode; setting this triggers a decode operation.

  -dr-token
      Set this flag to do generate root operations on DR Operational tokens.
      The default is false.

  -generate-otp
      Generate and print a high-entropy one-time-password (OTP) suitable for
      use with the "-init" flag. The default is false.

  -init
      Start a root token generation. This can only be done if there is not
      currently one in progress. The default is false.

  -nonce=<string>
      Nonce value provided at initialization. The same nonce value must be
      provided with each unseal key.

  -otp=<string>
      OTP code to use with "-decode" or "-init".

  -pgp-key=<keybase:user>
      Path to a file on disk containing a binary or base64-encoded public GPG
      key. This can also be specified as a Keybase username using the format
      "keybase:<username>". When supplied, the generated root token will be
      encrypted and base64-encoded with the given public key.

  -status
      Print the status of the current attempt without providing an unseal key.
      The default is false.
generate-root-test$
Enter fullscreen mode Exit fullscreen mode

Generate a Generic OTP for Root Token Generation

generate-root-test1$ vault operator generate-root -generate-otp > otp.txt
Enter fullscreen mode Exit fullscreen mode

Start the Root Token Geneneration

Yeah, it takes multiple steps. Deal.

generate-root-test1$ vault operator generate-root -init -otp=$(cat otp.txt)
Nonce         8c386f85-ba37-c74b-4ebc-436ec341dbca
Started       true
Progress      0/1
Complete      false
OTP Length    26
generate-root-test$ 
Enter fullscreen mode Exit fullscreen mode

Generate Root Token incorrectly

generate-root-test$ vault operator generate-root
Operation nonce: 8c386f85-ba37-c74b-4ebc-436ec341dbca
Unseal Key (will be hidden): 
Error posting unseal key: Error making API request.

URL: PUT http://127.0.0.1:8200/v1/sys/generate-root/update
Code: 400. Errors:

* 'key' must be a valid hex or base64 string

NOTE: Turns out I copied the unseal key incorrectly
Enter fullscreen mode Exit fullscreen mode

Get an Encoded Token Correctly this time

generate-root-test1$ vault operator generate-root
Operation nonce: 8c386f85-ba37-c74b-4ebc-436ec341dbca
Unseal Key (will be hidden): 
Nonce            8c386f85-ba37-c74b-4ebc-436ec341dbca
Started          true
Progress         1/1
Complete         true
Encoded Token    K3okGaAYO2w4nATeFawgA0T9LQM7zZioNWw
Enter fullscreen mode Exit fullscreen mode

Attempt to Decode the Encoded Token Incorrectly

generate-root-test1$ vault operator generate-root -decode=K3okGaAYO2w4nATeFawgA0T9LQM7zZioNWw  ##  Forgot to supply OTP

generate-root-test1$ vault operator generate-root -decode=K3okGaAYO2w4nATeFawgA0T9LQM7zZioNWw -otp=8c386f85-ba37-c74b-4ebc-436ec341dbca  ## Supplied nonce instead of otp


generate-root-test1$ vault operator generate-root --help

generate-root-test1$ vault operator generate-root --help
Usage: vault operator generate-root [options] [KEY]

  Generates a new root token by combining a quorum of share holders. One of
  the following must be provided to start the root token generation:

    - A base64-encoded one-time-password (OTP) provided via the "-otp" flag.
      Use the "-generate-otp" flag to generate a usable value. The resulting
      token is XORed with this value when it is returned. Use the "-decode"
      flag to output the final value.

    - A file containing a PGP key or a keybase username in the "-pgp-key"
      flag. The resulting token is encrypted with this public key.

  An unseal key may be provided directly on the command line as an argument to
  the command. If key is specified as "-", the command will read from stdin. If
  a TTY is available, the command will prompt for text.

  Generate an OTP code for the final token:

      $ vault operator generate-root -generate-otp

  Start a root token generation:

      $ vault operator generate-root -init -otp="..."
      $ vault operator generate-root -init -pgp-key="..."

  Enter an unseal key to progress root token generation:

      $ vault operator generate-root -otp="..."

HTTP Options:

  -address=<string>
      Address of the Vault server. The default is https://127.0.0.1:8200. This
      can also be specified via the VAULT_ADDR environment variable.

  -agent-address=<string>
      Address of the Agent. This can also be specified via the
      VAULT_AGENT_ADDR environment variable.

  -ca-cert=<string>
      Path on the local disk to a single PEM-encoded CA certificate to verify
      the Vault server's SSL certificate. This takes precedence over -ca-path.
      This can also be specified via the VAULT_CACERT environment variable.

  -ca-path=<string>
      Path on the local disk to a directory of PEM-encoded CA certificates to
      verify the Vault server's SSL certificate. This can also be specified
      via the VAULT_CAPATH environment variable.

  -client-cert=<string>
      Path on the local disk to a single PEM-encoded CA certificate to use
      for TLS authentication to the Vault server. If this flag is specified,
      -client-key is also required. This can also be specified via the
      VAULT_CLIENT_CERT environment variable.

  -client-key=<string>
      Path on the local disk to a single PEM-encoded private key matching the
      client certificate from -client-cert. This can also be specified via the
      VAULT_CLIENT_KEY environment variable.

  -mfa=<string>
      Supply MFA credentials as part of X-Vault-MFA header. This can also be
      specified via the VAULT_MFA environment variable.

  -namespace=<string>
      The namespace to use for the command. Setting this is not necessary
      but allows using relative paths. -ns can be used as shortcut. The
      default is (not set). This can also be specified via the VAULT_NAMESPACE
      environment variable.

  -output-curl-string
      Instead of executing the request, print an equivalent cURL command
      string and exit. The default is false.

  -policy-override
      Override a Sentinel policy that has a soft-mandatory enforcement_level
      specified The default is false.

  -tls-server-name=<string>
      Name to use as the SNI host when connecting to the Vault server via TLS.
      This can also be specified via the VAULT_TLS_SERVER_NAME environment
      variable.

  -tls-skip-verify
      Disable verification of TLS certificates. Using this option is highly
      discouraged as it decreases the security of data transmissions to and
      from the Vault server. The default is false. This can also be specified
      via the VAULT_SKIP_VERIFY environment variable.

  -wrap-ttl=<duration>
      Wraps the response in a cubbyhole token with the requested TTL. The
      response is available via the "vault unwrap" command. The TTL is
      specified as a numeric string with suffix like "30s" or "5m". This can
      also be specified via the VAULT_WRAP_TTL environment variable.

Output Options:

  -format=<string>
      Print the output in the given format. Valid formats are "table", "json",
      or "yaml". The default is table. This can also be specified via the
      VAULT_FORMAT environment variable.

Command Options:

  -cancel
      Reset the root token generation progress. This will discard any
      submitted unseal keys or configuration. The default is false.

  -decode=<string>
      The value to decode; setting this triggers a decode operation.

  -dr-token
      Set this flag to do generate root operations on DR Operational tokens.
      The default is false.

  -generate-otp
      Generate and print a high-entropy one-time-password (OTP) suitable for
      use with the "-init" flag. The default is false.

  -init
      Start a root token generation. This can only be done if there is not
      currently one in progress. The default is false.

  -nonce=<string>
      Nonce value provided at initialization. The same nonce value must be
      provided with each unseal key.

  -otp=<string>
      OTP code to use with "-decode" or "-init".

  -pgp-key=<keybase:user>
      Path to a file on disk containing a binary or base64-encoded public GPG
      key. This can also be specified as a Keybase username using the format
      "keybase:<username>". When supplied, the generated root token will be
      encrypted and base64-encoded with the given public key.

  -status
      Print the status of the current attempt without providing an unseal key.
      The default is false.
generate-root-test$
Enter fullscreen mode Exit fullscreen mode

Correctly Decode the Encoded Token

vault operator generate-root -decode=K3okGkAYO2w4BwEPFywJA0M9LQM7DzZNQWw -otp=$(cat otp.txt)  ##  Finally used it correctly.
s.Tt2ya8Yo56YitsN0tbuTTeRU
Enter fullscreen mode Exit fullscreen mode

And, Finally, We're Done Here

export VAULT_TOKEN=s.Tt2ya8Yo56YitsN0tbuTTeRU  ##  To be quickly replaced by a token with admin privileges
Enter fullscreen mode Exit fullscreen mode

Now you can Use the Vault Token

curl --header "X-Vault-Token: ${VAULT_TOKEN}" "$VAULT_ADDR/v1/sys/policies/acl"  ##  Get a list of the names of your Vault Policies
Enter fullscreen mode Exit fullscreen mode

Questions? Hit the comments. This is mostly for my own reference, but if anyone finds it useful I can improve it.

Discussion (0)