Vaultx.Sys.Unseal (Vaultx v0.7.0)

View Source

HashiCorp Vault unseal operations.

This module provides unseal capabilities for Vault, allowing you to submit unseal keys to progress the unsealing process. Vault uses Shamir's Secret Sharing to require a threshold number of key shares to unseal.

Unseal Operations

Core Functionality

  • Submit Unseal Key: Provide a single unseal key share
  • Reset Process: Clear previously submitted keys and restart
  • Migration Support: Handle seal migration between Shamir and auto-seal
  • Progress Tracking: Monitor unsealing progress

Unsealing Process

  • Threshold-based: Requires minimum number of key shares
  • Progressive: Each key submission advances progress
  • Stateful: Maintains progress across multiple submissions
  • Secure: Keys are processed and discarded immediately

Important Security Notes

Restricted Endpoint

  • Must be called from the root namespace
  • No authentication required (Vault is sealed)
  • Keys are sensitive and should be handled securely

Key Management

  • Each key can only be used once per unseal attempt
  • Keys should be distributed among trusted operators
  • Reset clears all previously submitted keys

Migration Considerations

  • Migration flag must be consistent across all key submissions
  • Used for transitioning between Shamir and auto-seal
  • Requires careful coordination during migration

API Compliance

Fully implements HashiCorp Vault Unseal API:

Usage Examples

Submit Unseal Key

{:ok, status} = Vaultx.Sys.Unseal.submit_key("abcd1234...")

if status.sealed do
  IO.puts("Progress: #{status.progress}/#{status.t}")
else
  IO.puts("Vault unsealed successfully!")
end

Reset Unseal Process

{:ok, status} = Vaultx.Sys.Unseal.reset()
IO.puts("Unseal process reset, progress: #{status.progress}")

Migration Unseal

{:ok, status} = Vaultx.Sys.Unseal.submit_key("abcd1234...", migrate: true)

Batch Unseal Operation

keys = ["key1", "key2", "key3"]
{:ok, final_status} = Vaultx.Sys.Unseal.submit_keys(keys)

Unseal Status Response

The unseal operations return status information:

  • sealed: Whether Vault is still sealed
  • t: Threshold number of keys required
  • n: Total number of key shares
  • progress: Number of keys submitted so far
  • version: Vault version
  • cluster_name: Cluster name (when unsealed)
  • cluster_id: Cluster ID (when unsealed)

Error Handling

Common error scenarios:

  • Invalid or malformed keys
  • Duplicate key submission
  • Network connectivity issues
  • Vault configuration problems

Summary

Types

Unseal status information.

Functions

Reset the unseal process by discarding previously submitted keys.

Submit an unseal key to progress the unsealing process.

Submit multiple unseal keys in sequence.

Types

unseal_status()

@type unseal_status() :: %{
  :sealed => boolean(),
  :t => integer(),
  :n => integer(),
  :progress => integer(),
  :version => String.t(),
  optional(:cluster_name) => String.t(),
  optional(:cluster_id) => String.t()
}

Unseal status information.

Functions

reset(opts \\ [])

@spec reset(Vaultx.Types.options()) ::
  {:ok, unseal_status()} | {:error, Vaultx.Base.Error.t()}

Reset the unseal process by discarding previously submitted keys.

This operation clears all previously submitted unseal keys and resets the progress counter to zero.

Parameters

  • opts - Request options (optional)

Returns

Returns {:ok, unseal_status()} with reset status, or {:error, Error.t()} on failure.

Examples

{:ok, status} = Vaultx.Sys.Unseal.reset()
IO.puts("Unseal process reset, progress: #{status.progress}")

submit_key(key, opts \\ [])

@spec submit_key(String.t(), Vaultx.Types.options()) ::
  {:ok, unseal_status()} | {:error, Vaultx.Base.Error.t()}

Submit an unseal key to progress the unsealing process.

This endpoint is used to enter a single root key share to progress the unsealing of the Vault. If the threshold number of root key shares is reached, Vault will attempt to unseal. Otherwise, this API must be called multiple times until that threshold is met.

Parameters

  • key - A single root key share (required unless reset is true)
  • opts - Options for the unseal operation
    • :reset - Discard previously-provided keys and reset (default: false)
    • :migrate - Used for seal migration between Shamir and auto-seal (default: false)
    • Other HTTP request options

Returns

Returns {:ok, unseal_status()} with current unseal status, or {:error, Error.t()} on failure.

Examples

# Submit a single unseal key
{:ok, status} = Vaultx.Sys.Unseal.submit_key("abcd1234...")

# Check if more keys are needed
if status.sealed do
  IO.puts("Need #{status.t - status.progress} more keys")
else
  IO.puts("Vault is now unsealed!")
end

# Submit key with migration flag
{:ok, status} = Vaultx.Sys.Unseal.submit_key("abcd1234...", migrate: true)

submit_keys(keys, opts \\ [])

@spec submit_keys([String.t()], Vaultx.Types.options()) ::
  {:ok, unseal_status()} | {:error, Vaultx.Base.Error.t()}

Submit multiple unseal keys in sequence.

This is a convenience function that submits multiple keys one by one until the Vault is unsealed or all keys are exhausted.

Parameters

  • keys - List of unseal key shares
  • opts - Options for the unseal operations
    • :migrate - Used for seal migration (default: false)
    • :stop_on_unseal - Stop when Vault is unsealed (default: true)
    • Other HTTP request options

Returns

Returns {:ok, unseal_status()} with final status, or {:error, Error.t()} on failure.

Examples

keys = ["key1", "key2", "key3"]
{:ok, final_status} = Vaultx.Sys.Unseal.submit_keys(keys)

if final_status.sealed do
  IO.puts("Still need #{final_status.t - final_status.progress} more keys")
else
  IO.puts("Vault successfully unsealed!")
end