Skip to content

Instantly share code, notes, and snippets.

@pstaender
Created July 2, 2018 08:35
Show Gist options
  • Save pstaender/0f6662079b5d0fcb6ca148885fef699a to your computer and use it in GitHub Desktop.
Save pstaender/0f6662079b5d0fcb6ca148885fef699a to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# optional: install oathtool
require 'json'
require 'yaml'
require 'open3'
require 'mkmf'
cmd_list_items = 'op list items'
stdout, stderr, status = Open3.capture3(cmd_list_items)
scope = 'my'
token_key = "OP_SESSION_#{scope}"
env_cmd = ''
def look_for_field(fields, field)
founds = []
fields.each { |a|
if a.is_a?(Array)
founds += look_for_field(a, field)
elsif a['name'] && a['name'].downcase == field.downcase
founds << a['value']
end
}
founds.reject(&:nil?)
end
def look_for_tbpw_and_extract_shared_secret(fields)
founds = []
fields.flatten.each { |a|
if a['v'] && a['v'].start_with?('otpauth://')
founds << (a['v'].sub(/^.+?\?.*secret\=/,'')).sub(/\&.*$/, '')
end
}
founds
end
if stderr.include?('(ERROR) You are not currently signed in')
token = `op signin #{scope} --output=raw`
raise 'could not authenticate' if token.empty?
token.strip!
puts "hint: use `eval $(op signin #{scope})` before 1passw to memorize login for the whole cli session"
env_command = "export #{token_key}=#{token};"
items = `#{env_command}#{cmd_list_items}`
else
items = stdout
end
map = []
choice = ARGV.first
choice = nil if choice == '-'
field = ARGV[1]
menu = JSON.parse(items).each_with_index.map {|o, i|
map << o['uuid']
if !choice.to_s.match(/^\d+$/) && choice && File.fnmatch(choice.downcase, o['overview']['title'].downcase)
choice = i
end
"#{i}: #{o['overview']['title']}"
}.join("\n")
choice = nil if !choice.to_s.match(/^\d+$/)
unless choice
puts menu
choice = gets.chomp
end
item = JSON.parse(`#{env_command}op get item #{map[choice.to_i]}`)
if field
if field == 'otp'
fields_to_search = []
if item['details'] && item['details']['sections'] && item['details']['sections'].any?
item['details']['sections'].each { |subitem|
fields_to_search << subitem['fields'] if subitem && subitem['fields']
}
end
founds = look_for_tbpw_and_extract_shared_secret(fields_to_search)
if founds.any? && find_executable('oathtool')
founds.each { |otp| puts `oathtool --base32 --totp #{otp}` }
exit
end
else
fields_to_search = []
fields_to_search << item['details']['fields'] if item['details'] && item['details']['fields']
fields_to_search << item['details'] if item['details']
founds = look_for_field(fields_to_search, field)
end
puts founds.join("\n")
else
puts item.to_yaml
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment