class Sekrets

Constants

Version

Public Class Methods

ask(question) click to toggle source
# File lib/sekrets.rb, line 126
def Sekrets.ask(question)
  @highline ||= HighLine.new
  @highline.ask(prompt_for(question))
end
binstub() click to toggle source
# File lib/sekrets.rb, line 269
  def Sekrets.binstub
    @binstub ||= (
      unindent(
        <<-'_v_'
          #! /usr/bin/env ruby

          require 'pathname'
          ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
            Pathname.new(__FILE__).realpath)

          require 'rubygems'
          require 'bundler/setup'

          dirname = File.dirname(__FILE__)

          root = File.dirname(dirname)

          ciphertext = File.expand_path('ciphertext', dirname)

          case ARGV.size
            when 0
              ENV['SEKRETS_ARGV'] = "edit #{ ciphertext }"
            when 1
              ENV['SEKRETS_ARGV'] = "#{ ARGV[0] } #{ ciphertext }"
          end

          key = File.join(root, '.sekrets.key')

          if test(?s, key)
            ENV['SEKRETS_KEY'] = IO.binread(key).strip
          end

          exec(Gem.bin_path('sekrets', 'sekrets'))
        _v_
      )
    )
  end
console?() click to toggle source
# File lib/sekrets.rb, line 132
def Sekrets.console?
  STDIN.tty?
end
dependencies() click to toggle source
# File lib/sekrets.rb, line 382
def dependencies
  {
    'openssl'  => [ 'openssl'  , ' ~> 3.2'   ] ,
    'highline' => [ 'highline' , ' ~> 1.7'   ] ,
    'map'      => [ 'map'      , ' ~> 6.6'   ] ,
    'fattr'    => [ 'fattr'    , ' ~> 2.4'   ] ,
    'coerce'   => [ 'coerce'   , ' ~> 0.0.8' ] ,
    'main'     => [ 'main'     , ' ~> 6.3'   ] ,
  }
end
key_for(*args) click to toggle source
# File lib/sekrets.rb, line 17
def Sekrets.key_for(*args)
  options = Map.options_for!(args)
  path = args.shift || options[:path]

  if options.has_key?(:key)
    key = options[:key]
    return(key)
  end

  path = path_for(path)

  if path
    dirname, basename = File.split(path)

    keyfiles =
      Coerce.list_of_strings(
        [:keyfile, :keyfiles].map{|k| options[k]},
        %W[ #{ dirname }/.#{ basename }.key #{ dirname }/.#{ basename }.k ]
      )

    keyfiles.each do |file|
      if test(?s, file)
        key = IO.binread(file).strip
        return(key)
      end
    end
  end

  if Sekrets.project_key and test(?s, Sekrets.project_key)
    return IO.binread(Sekrets.project_key).strip
  end

  env_key = (options[:env] || Sekrets.env).to_s
  if ENV.has_key?(env_key)
    key = ENV[env_key]
    return(key)
  end

  if Sekrets.global_key and test(?s, Sekrets.global_key)
    return IO.binread(Sekrets.global_key).strip
  end

  unless options[:prompt] == false
    if console?
      key = Sekrets.ask(path)
      return(key)
    end
  end

  return nil
end
key_for!(*args, &block) click to toggle source
# File lib/sekrets.rb, line 70
def Sekrets.key_for!(*args, &block)
  key = Sekrets.key_for(*args, &block)
  raise(ArgumentError, 'no key!') unless key
  key
end
libdir(*args, &block) click to toggle source
# File lib/sekrets.rb, line 393
def libdir(*args, &block)
  @libdir ||= File.expand_path(__FILE__).sub(/\.rb$/,'')
  args.empty? ? @libdir : File.join(@libdir, *args)
ensure
  if block
    begin
      $LOAD_PATH.unshift(@libdir)
      block.call()
    ensure
      $LOAD_PATH.shift()
    end
  end
end
load(*libs) click to toggle source
# File lib/sekrets.rb, line 407
def load(*libs)
  libs = libs.join(' ').scan(/[^\s+]+/)
  Sekrets.libdir{ libs.each{|lib| Kernel.load(lib) } }
end
openr(arg, &block) click to toggle source
# File lib/sekrets.rb, line 220
def Sekrets.openr(arg, &block)
  opened = false

  io =
    case
      when arg.respond_to?(:read)
        arg
      when arg.to_s.strip == '-'
        STDIN
      else
        opened = true
        open(arg, 'rb+')
    end

  close =
    proc do
      io.close if opened
    end

  if block
    begin
      block.call(io)
    ensure
      close.call
    end
  else
    at_exit{ close.call }
    io
  end
end
openw(arg, &block) click to toggle source
# File lib/sekrets.rb, line 180
def Sekrets.openw(arg, &block)
  opened = false
  atomic_move = proc{}

  io =
    case
      when arg.respond_to?(:read)
        arg
      when arg.to_s.strip == '-'
        STDOUT
      else
        opened = true
        path = File.expand_path(arg.to_s)
        dirname, basename = File.split(path)
        FileUtils.mkdir_p(dirname)
        tmp = path + ".sekrets.tmp.#{ Process.ppid }.#{ Process.pid }"
        at_exit{ FileUtils.rm_f(tmp) }
        atomic_move = proc{ FileUtils.mv(tmp, path) }
        open(tmp, 'wb+')
    end

  close =
    proc do
      io.close if opened
      atomic_move.call
    end

  if block
    begin
      block.call(io)
    ensure
      close.call
    end
  else
    at_exit{ close.call }
    io
  end
end
path_for(object) click to toggle source
# File lib/sekrets.rb, line 252
def Sekrets.path_for(object)
  path = nil

  if object.is_a?(String) or object.is_a?(Pathname)
    return(path = object.to_s)
  end

  [:original_path, :original_filename, :path, :filename, :pathname].each do |msg|
    if object.respond_to?(msg)
      path = object.send(msg)
      break
    end
  end

  path
end
prompt_for(*words) click to toggle source
# File lib/sekrets.rb, line 121
def Sekrets.prompt_for(*words)
  ["sekrets:", words, "> "].flatten.compact.join(' ')
end
read(*args, &block) click to toggle source
# File lib/sekrets.rb, line 77
def Sekrets.read(*args, &block)
  options = Map.options_for!(args)
  path = args.shift || options[:path]
  key = args.shift || Sekrets.key_for!(path, options)

  return nil unless test(?s, path)

  encrypted = IO.binread(path)
  decrypted = Sekrets.decrypt(key, encrypted)
  new(decrypted)
end
settings_for(*args, &block) click to toggle source
# File lib/sekrets.rb, line 110
def Sekrets.settings_for(*args, &block)
  decrypted = read(*args, &block)

  if decrypted
    expanded = ERB.new(decrypted).result(TOPLEVEL_BINDING)
    object = YAML.load(expanded)
    object.is_a?(Hash) ? Map.for(object) : object
  end
end
system(command) click to toggle source
# File lib/sekrets.rb, line 168
def Sekrets.system(command)
  if defined?(Bundler)
    msg = (Bundler.respond_to?('with_original_env') ? 'with_original_env' : 'with_clean_env')
    Bundler.send(msg){ Kernel.system(command) }
  else
    Kernel.system(command)
  end

  return $?.exitstatus
end
tmpdir(&block) click to toggle source
# File lib/sekrets.rb, line 137
def Sekrets.tmpdir(&block)
  dirname = File.join(Dir.tmpdir, 'sekrets', Process.ppid.to_s, Process.pid.to_s, rand.to_s)

  FileUtils.mkdir_p(dirname)

  cleanup = proc do
    if dirname and test(?d, dirname)
      FileUtils.rm_rf(dirname)
    end
  end

  if block
    begin
      Dir.chdir(dirname) do
        block.call(dirname)
      end
    ensure
      cleanup.call
    end
  else
    at_exit{ cleanup.call }
    dirname
  end
end
tmpfile_for(basename, data) click to toggle source
# File lib/sekrets.rb, line 162
def Sekrets.tmpfile_for(basename, data)
  tmpfile = File.join(Sekrets.tmpdir, basename)
  IO.binwrite(tmpfile, data)
  tmpfile
end
unindent(string) click to toggle source
# File lib/sekrets.rb, line 307
def Sekrets.unindent(string)
  indent = string.split("\n").select {|line| !line.strip.empty? }.map {|line| line.index(/[^\s]/) }.compact.min || 0
  string.gsub(/^[[:blank:]]{#{indent}}/, '')
end
unindent!(string) click to toggle source
# File lib/sekrets.rb, line 312
def Sekrets.unindent!(string)
  string.replace(string.unindent)
end
version() click to toggle source
# File lib/sekrets.rb, line 378
def version
  Sekrets::Version
end
write(*args, &block) click to toggle source
# File lib/sekrets.rb, line 90
def Sekrets.write(*args, &block)
  options = Map.options_for!(args)
  path = args.shift || options[:path]
  content = args.shift || options[:content]
  key = args.shift || Sekrets.key_for!(path, options)

  dirname, basename = File.split(File.expand_path(path))
  FileUtils.mkdir_p(dirname)

  encrypted = Sekrets.encrypt(key, content)

  tmp = path + '.tmp'
  IO.binwrite(tmp, encrypted)
  FileUtils.mv(tmp, path)

  encrypted
  new(encrypted)
end