class Sanctum::Command::Push

Public Instance Methods

build_local_secrets(local_paths, transit_key) click to toggle source
# File lib/sanctum/command/push.rb, line 77
def build_local_secrets(local_paths, transit_key)
  # Read each local file
  local_secrets = read_local_files(local_paths)
  # Decrypt local secrets
  local_secrets = VaultTransit.decrypt(vault_client, local_secrets, transit_key)
end
build_vault_secrets(local_paths, target_prefix, target_path, secrets_version) click to toggle source
# File lib/sanctum/command/push.rb, line 84
def build_vault_secrets(local_paths, target_prefix, target_path, secrets_version)
  # Map local_paths into vault_paths
  vault_paths = local_paths.map{|x| x.gsub(File.join(File.dirname(config_file), target_path), "")}

  # Get vault secrets (if they exist) for each vault prefix specified in sanctum.yaml that also maps to a local path
  # This means that we will only compare secrets/paths that exist both locally and in vault.
  # We will not for example, see differences if a secret exists in vault but not locally.

  # Read secrets from vault
  vault_secrets = read_remote(vault_paths, target_prefix, secrets_version)

  # To make comparing a bit easier map vault_secrets prefixs back local_paths
  # Convert to json, then read, to make keys strings vs symbols
  vault_secrets = JSON(map_local_path(vault_secrets, target_path).to_json)
end
map_local_path(secrets_hash, local_path) click to toggle source
# File lib/sanctum/command/push.rb, line 66
def map_local_path(secrets_hash, local_path)
  config_path = Pathname.new(config_file)
  tmp_hash = Hash.new

  secrets_hash.map do |p, v|
    p = config_path.dirname + Pathname.new(File.join(local_path, p))
    tmp_hash["#{p}"] = v
  end
  tmp_hash
end
read_remote(paths, prefix, secrets_version) click to toggle source

Right now this duplicates a bit of logic that already exists in VaultSecrets client. TODO: remove this method once code is rearranged

# File lib/sanctum/command/push.rb, line 52
def read_remote(paths, prefix, secrets_version)
  tmp_hash = Hash.new
  paths.each do |k,v|
    p = File.join(prefix, k)
    unless vault_client.logical.read(p).nil?
      v = secrets_version == "2" ? vault_client.logical.read(p).data[:data] : vault_client.logical.read(p).data
      tmp_hash["#{k}"] = v
    else
      next
    end
  end
  tmp_hash
end
run() click to toggle source
# File lib/sanctum/command/push.rb, line 8
def run
  puts yellow("Running `push` for the following targets: \n#{targets.map{ |h| h.dig(:name)}.to_yaml.gsub("---\n", '')}")
  targets.each do |target|
    # Use command line if force: true
    if options[:cli][:force]
      force = options[:cli][:force]
    else
      force = target.fetch(:force) {options[:sanctum][:force]}
    end

    # Build array of local paths by recursively searching for local files for each path specified in sanctum.yaml
    local_paths = get_local_paths(File.join(File.dirname(config_file), target[:path]))

    local_secrets = build_local_secrets(local_paths, target[:transit_key])
    vault_secrets = build_vault_secrets(local_paths, target[:prefix], target[:path], target[:secrets_version])

    # Compare secrets
    # vault_secrets prefix have been mapped to local_paths to make comparison easier
    differences = compare_secrets(vault_secrets, local_secrets, target[:name], "push")
    next if differences.nil?

    # Get uniq array of Hashdiff returned paths
    diff_paths = differences.map{|x| x[1][0]}.uniq

    # Only write changes
    vault_secrets = only_changes(diff_paths, local_secrets)

    #Convert paths back to vault prefix so we can sync
    vault_secrets = vault_secrets.map {|k, v| [k.gsub(File.join(File.dirname(config_file), target[:path]), target[:prefix]), v] }.to_h

    if force
      warn red("#{target[:name]}: Forcefully writing differences to vault(push)")
      VaultTransit.write_to_vault(vault_client, vault_secrets, target[:secrets_version])
    else
      #Confirm with user, and write to local file if approved
      next unless confirmed_with_user?
      VaultTransit.write_to_vault(vault_client, vault_secrets, target[:secrets_version])
    end
  end
end