class SecretsFetcher

Public Instance Methods

run() click to toggle source
# File lib/renuo/cli/app/secrets_fetcher.rb, line 10
def run
  system("which op > /dev/null") || abort("op is not installed. Please install it (e.g. brew install 1password-cli).")

  abort("Config file #{CONFIG_FILE} not found.") unless File.exist?(CONFIG_FILE)
  config = YAML.load_file(CONFIG_FILE).deep_symbolize_keys

  config[:items].each do |item|
    elaborate_item(item)
  end
end

Private Instance Methods

download_file_from_item(files, vault_id, item_id, filename, output_path) click to toggle source
# File lib/renuo/cli/app/secrets_fetcher.rb, line 107
def download_file_from_item(files, vault_id, item_id, filename, output_path)
  item_file = files&.find { |tmp_file_config| tmp_file_config["name"].eql?(filename) }
  if item_file.nil?
    warn "File `#{filename}` not found in item #{item_id}. Check the file name in your #{CONFIG_FILE} file."
    return
  end
  execute_command(command: "op read \"op://#{vault_id}/#{item_id}/#{item_file["id"]}\" --out-file #{output_path}",
                  success_message: "Successfully fetched #{filename} and saved to #{output_path}",
                  error_message: "Error fetching #{filename}.")
end
elaborate_item(item) click to toggle source
# File lib/renuo/cli/app/secrets_fetcher.rb, line 23
def elaborate_item(item) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  private_link = item[:private_link]
  if private_link.nil?
    warn "Private link not found in your config file."
    return
  elsif private_link.include?("share.1password.com")
    warn "Please use a private link, not a share link."
    return
  end

  item_id = extract_item_id(private_link)
  item_json = get_item(item_id)
  return if item_json.nil?

  item[:env_variables]&.each do |env_variable|
    process_env_variable(env_variable[:name], item_id, item_json)
  end

  item[:files]&.each do |file|
    process_file(file[:folder] || item[:default_folder], file[:name], item_json, item_id)
  end
end
execute_command(command:, success_message:, error_message:) click to toggle source
# File lib/renuo/cli/app/secrets_fetcher.rb, line 84
def execute_command(command:, success_message:, error_message:)
  output = `#{command}`
  if $CHILD_STATUS.success?
    puts success_message unless success_message.empty?
    output
  else
    warn error_message
  end
end
extract_item_id(private_link) click to toggle source
# File lib/renuo/cli/app/secrets_fetcher.rb, line 94
def extract_item_id(private_link)
  /&i=([^&]+)/.match(private_link)[1]
end
get_item(item_id) click to toggle source
# File lib/renuo/cli/app/secrets_fetcher.rb, line 76
def get_item(item_id)
  output = execute_command(command: "op item get #{item_id} --format json",
                           success_message: "",
                           error_message: "Error fetching item #{item_id}." \
                                          "Check `private_link` in  your #{CONFIG_FILE} file.")
  JSON.parse(output) if output
end
process_env_variable(name, item_id, item_json) click to toggle source
# File lib/renuo/cli/app/secrets_fetcher.rb, line 46
def process_env_variable(name, item_id, item_json)
  env_json = item_json["fields"].find { |field| field["label"] == name }
  if env_json.nil?
    warn "Field `#{name}` not found in item #{item_id}. Check the field name in your #{CONFIG_FILE} file."
  else
    value = env_json["value"]
    update_or_add_variable(".env", name, /^#{name}=/, "#{name}=#{value}")
    update_or_add_variable("config/application.yml", name, /^#{name}:.*$/, "#{name}: \"#{value}\"")

  end
end
process_file(output_folder, filename, item, item_id) click to toggle source
# File lib/renuo/cli/app/secrets_fetcher.rb, line 98
def process_file(output_folder, filename, item, item_id)
  FileUtils.mkdir_p(output_folder)
  output_path = File.join(output_folder, filename)

  vault_id = item.dig("vault", "id")
  download_file_from_item(item["files"], vault_id, item_id, filename, output_path)
  puts "\n\n"
end
update_or_add_variable(file_path, name, pattern, replacement) click to toggle source
# File lib/renuo/cli/app/secrets_fetcher.rb, line 58
def update_or_add_variable(file_path, name, pattern, replacement) # rubocop:disable Metrics/MethodLength
  return unless File.exist?(file_path)

  file_contents = File.read(file_path)
  updated_contents = file_contents

  if file_contents.match(pattern)
    if ask("Do you want to update the value of #{name} in #{file_path}? (y/n)", "y") == "y"
      updated_contents = file_contents.gsub(pattern, replacement)
    end
  else
    puts "Added environment variable #{name} to #{file_path}"
    updated_contents = "#{file_contents}#{replacement}\n"
  end

  File.write(file_path, updated_contents)
end