class InspecPlugins::Vault::Input

Attributes

input_name[R]
logger[R]
mount_point[R]
path_prefix[R]
plugin_conf[R]
priority[R]
vault[R]

Public Class Methods

new() click to toggle source
# File lib/inspec-vault/input.rb, line 16
def initialize
  @plugin_conf = Inspec::Config.cached.fetch_plugin_config("inspec-vault")

  @logger = Inspec::Log
  logger.debug format("Inspec-Vault plugin version %s", VERSION)

  @mount_point = fetch_plugin_setting("mount_point", "secret")
  @path_prefix = fetch_plugin_setting("path_prefix", "inspec")

  # We need priority to be numeric; even though env vars or JSON may present it as string - hence the to_i
  @priority = fetch_plugin_setting("priority", 60).to_i

  @vault = Vault::Client.new(
    address: fetch_vault_setting("vault_addr"),
    token: fetch_vault_setting("vault_token")
  )
end

Public Instance Methods

default_priority() click to toggle source

What priority should an input value recieve from us? This plgin does not currently allow setting this on a per-input basis, so they all recieve the same “default” value. Implements github.com/inspec/inspec/blob/master/docs/dev/plugins.md#default_priority

# File lib/inspec-vault/input.rb, line 38
def default_priority
  priority
end
fetch(profile_name, input_name) click to toggle source

Fetch a value of a single input from Vault TODO we should probably cache these - github.com/inspec/inspec-vault/issues/15

# File lib/inspec-vault/input.rb, line 55
def fetch(profile_name, input_name)
  @input_name = input_name

  path = logical_path_for_profile(profile_name)
  item = input_name

  if absolute_path?
    _empty, *path, item = input_name.split("/")
    path = logical_path path.join("/")
  end

  logger.info format("Reading Vault secret from %s", path)
  vault.with_retries(Vault::HTTPConnectionError) do
    doc = vault.logical.read(path)
    # Keys from vault are always symbolized
    return doc.data[:data][item.to_sym] if doc
  end
end
list_inputs(profile_name) click to toggle source

returns Array of input names as strings

# File lib/inspec-vault/input.rb, line 43
def list_inputs(profile_name)
  vault.with_retries(Vault::HTTPConnectionError) do
    path = logical_path_for_profile(profile_name)
    doc = vault.logical.read(path)
    return [] unless doc

    return doc.data[:data].keys.map(&:to_s)
  end
end

Private Instance Methods

absolute_path?() click to toggle source
# File lib/inspec-vault/input.rb, line 96
def absolute_path?
  input_name.start_with?("/")
end
fetch_plugin_setting(setting_name, default = nil) click to toggle source
# File lib/inspec-vault/input.rb, line 100
def fetch_plugin_setting(setting_name, default = nil)
  env_var_name = "INSPEC_VAULT_#{setting_name.upcase}"
  ENV[env_var_name] || plugin_conf[setting_name] || default
end
fetch_vault_setting(setting_name) click to toggle source
# File lib/inspec-vault/input.rb, line 105
def fetch_vault_setting(setting_name)
  ENV[setting_name.upcase] || plugin_conf[setting_name]
end
logical_path(relative_path) click to toggle source
# File lib/inspec-vault/input.rb, line 82
def logical_path(relative_path)
  # When you actually read a value, on the KV2 backend you must
  # read secret/data/path, not secret/path (as on the CLI)
  # https://www.vaultproject.io/api/secret/kv/kv-v2.html#read-secret-version
  # Is this true for all backends?
  "#{mount_point}/data/#{prefix}#{relative_path}"
end
logical_path_for_profile(profile_name) click to toggle source

Assumption for profile based lookups: inputs have been stored on documents named for their profiles, and each input has a key-value pair in the document.

# File lib/inspec-vault/input.rb, line 78
def logical_path_for_profile(profile_name)
  logical_path(profile_name)
end
prefix() click to toggle source
# File lib/inspec-vault/input.rb, line 90
def prefix
  return "#{path_prefix}/" unless absolute_path?

  ""
end