class Keystorage::Manager

ks = keystorage::Manager.new(:file =>“”,:secret=> “P@ssword”) ks.get(“mygroup”,“mykey”) # => “mysecret”

Attributes

options[R]

Public Class Methods

new(options = {}) click to toggle source
# File lib/keystorage/manager.rb, line 9
def initialize options = {}
  @options = options
end

Public Instance Methods

exec(*cmd) click to toggle source
# File lib/keystorage/manager.rb, line 59
def exec *cmd
  raise SecretMissMatch unless valid?
  system(envs.collect{ |k,v| "#{k}='#{v}'" }.join(' ') + " " + cmd.join(' '))
end
get(group,key) click to toggle source
# File lib/keystorage/manager.rb, line 21
def get(group,key)
  raise SecretMissMatch unless valid?
  decode(file[group][key])
end
groups() click to toggle source
# File lib/keystorage/manager.rb, line 13
def groups
  file.keys.delete_if {|i| i == "@" }
end
keys(group) click to toggle source
# File lib/keystorage/manager.rb, line 17
def keys(group)
  file[group].keys
end
password(new_secret) click to toggle source
# File lib/keystorage/manager.rb, line 42
def password new_secret
  raise SecretMissMatch unless valid?

  # update passwords
  data = file.each { |name,keys|
    next if name == "@"
    keys.each { |key,value|
      keys[key] = encode(decode(value),new_secret)
    }
  }
  # update root group and write to file
  write root!(new_secret,data)
rescue Errno::ENOENT
  write({})
  retry
end
set(group,key,value) click to toggle source
# File lib/keystorage/manager.rb, line 26
def set(group,key,value)
  raise RejectGroupName.new("Cannot use '@' for group name.") if group == "@"
  raise SecretMissMatch unless valid?

  data = file
  data[group] = {} unless data.has_key?(group)
  data[group][key] = {} unless data[group].has_key?(key)
  data[group][key] = encode(value)
  write(data)

  data[group][key]
rescue Errno::ENOENT
  write({})
  retry
end

Private Instance Methods

decode(str,_secret=secret) click to toggle source
# File lib/keystorage/manager.rb, line 110
def decode(str,_secret=secret)
  dec = OpenSSL::Cipher::Cipher.new('aes256')
  dec.decrypt.pkcs5_keyivgen(_secret)
  (dec.update(Array.new([str]).pack("H*")) + dec.final)
end
encode(str,_secret=secret) click to toggle source
# File lib/keystorage/manager.rb, line 104
def encode(str,_secret=secret)
  enc = OpenSSL::Cipher::Cipher.new('aes256')
  enc.encrypt.pkcs5_keyivgen(_secret)
  ((enc.update(str) + enc.final).unpack("H*")).first.to_s
end
envs() click to toggle source
# File lib/keystorage/manager.rb, line 66
def envs
  result = {}
  groups.each { |g|
    keys(g).each { |k|
      result["#{g}_#{k}"] = get(g,k)
    }
  }
  result
end
file() click to toggle source
# File lib/keystorage/manager.rb, line 120
def file
  YAML.load(File.new(path)) || {}
end
path() click to toggle source
# File lib/keystorage/manager.rb, line 116
def path
  options[:file] || ENV['KEYSTORAGE_FILE'] || DEFAULT_FILE
end
root() click to toggle source
# File lib/keystorage/manager.rb, line 85
def root
  raise NoRootGroup unless file.has_key?("@")
  file["@"] || {}
end
root!(_secret=secret,data=file) click to toggle source
# File lib/keystorage/manager.rb, line 90
def root! _secret=secret,data=file
  data["@"] = {}
  data["@"]["token"] = token
  data["@"]["sig"] = sign(data["@"]["token"],_secret)
  data
end
secret() click to toggle source
# File lib/keystorage/manager.rb, line 129
def secret
  options[:secret] || ENV['KEYSTORAGE_SECRET'] || DEFAULT_SECRET
end
sign(message,_secret=secret) click to toggle source
# File lib/keystorage/manager.rb, line 76
def sign message,_secret=secret
  raise NoSecret.new("set env KEYSTORAGE_SECRET") unless _secret
  OpenSSL::HMAC.hexdigest('sha512',_secret, message)
end
token() click to toggle source
# File lib/keystorage/manager.rb, line 81
def token
  SecureRandom.urlsafe_base64(nil, false)
end
valid?() click to toggle source

file validation

# File lib/keystorage/manager.rb, line 98
def valid?
  sign(root["token"]) == root["sig"]
rescue NoRootGroup
  write root! and true
end
write(data) click to toggle source
# File lib/keystorage/manager.rb, line 124
def write data
  FileUtils.mkdir_p(File.dirname(path))
  File.open(path,'w',0600) { |f| YAML.dump(data,f) }
end