# frozen_string_literal: true require 'yaml' require 'fileutils' require 'json' CONFIG_FILE = 'config/1password-secrets.yml' class SecretsFetcher 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 def elaborate_item(item) private_link = item[:private_link] files = item[:files] default_folder = item[:default_folder] item_id = extract_item_id(private_link) item = get_item(item_id) return if item.nil? files.each do |file| process_files(file[:folder] || default_folder, file[:name], item, item_id) end end 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 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 def extract_item_id(private_link) /&i=([^&]+)/.match(private_link)[1] end def process_files(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 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 end