lib/app-rb/cli.rb in app-rb-0.6.0 vs lib/app-rb/cli.rb in app-rb-0.7.0

- old
+ new

@@ -1,6 +1,7 @@ require 'yaml' +require 'openssl' module AppRb class Cli def initialize(args) @args = args @@ -10,53 +11,128 @@ def run if @args.count < 2 usage exit end - config = Config.new(YAML.load(File.read(@args[0]))) - command = @args[1] + if File.exists?(@args[0]) + config_path = @args.shift + end - if AppRb::Util.compare_versions(config.tool_version, AppRb::VERSION) > 0 + if @args[0] == "--vault" && File.exists?(@args[1]) + @args.shift + @vault_file = @args.shift + elsif File.exists?(File.join(Dir.pwd, "vault.key")) + @vault_file = File.join(Dir.pwd, "vault.key") + else + @vault_file = nil + end + + command = @args.shift + config = Config.new(read_yaml(config_path)) if config_path + + if config && AppRb::Util.compare_versions(config.tool_version, AppRb::VERSION) > 0 puts "FATAL: need at least '#{config.tool_version}' tool version but current version is '#{AppRb::VERSION}'" exit -1 end - if command == "deploy" || command == "d" + if %w[deploy d].index(command) Command.new(config).deploy(@args[2]) - elsif command == "status" || command == "s" + elsif %w[status s].index(command) Command.new(config).status elsif command == "redeploy" Command.new(config).redeploy elsif command == "clean" Command.new(config).clean elsif command == "stop" Command.new(config).stop - elsif command == "run" || command == "r" + elsif %w[run r].index(command) Command.new(config).run(@args[2..-1].join(" ")) elsif command == "cd" Command.new(config).cd + elsif %w[encrypt en e].index(command) + puts encrypt(@args.shift) + elsif %w[decrypt de].index(command) + puts decrypt(@args.shift) else puts "FATAL: unknown command '#{command}'" exit -1 end end private + MARKER = "__VAULT:" + def read_yaml(file) + unvault = proc { |o| + if o.is_a?(Array) + o.map { |i| unvault.call(i) } + elsif o.is_a?(Hash) + o.map { |k, v| [k, unvault.call(v)] }.to_h + elsif o.is_a?(String) && o.index(MARKER) == 0 + decrypt(o) + else + o + end + } + unvault.call(YAML.load(File.read(file))) + end + + def die(msg = nil) + if msg + puts "FATAL: #{msg}" + else + puts "exit with status code -1" + end + exit -1 + end + + def bin_to_hex(s) + s.unpack('H*').first + end + + def hex_to_bin(s) + s.scan(/../).map { |x| x.hex }.pack('c*') + end + + def encrypt(string) + die "missed vault file" unless @vault_file + die "string encrypted yet" if string.index(MARKER) == 0 + cipher = OpenSSL::Cipher::AES256.new :CBC + cipher.encrypt + iv = cipher.random_iv + cipher.key = Digest::SHA256.digest(File.read(@vault_file).strip) + MARKER + bin_to_hex(cipher.update(string) + cipher.final) + ":" + bin_to_hex(iv) + end + + def decrypt(string) + die "missed vault file" unless @vault_file + die "string not encrypted" unless string.index(MARKER) == 0 + cipher = OpenSSL::Cipher::AES256.new :CBC + cipher.decrypt + cipher.iv = hex_to_bin(string.sub(MARKER, "").split(":")[1]) + cipher.key = Digest::SHA256.digest(File.read(@vault_file).strip) + cipher.update(hex_to_bin(string.sub(MARKER, "").split(":")[0])) + cipher.final + end + def usage puts "Just deploy your apps with docker and consul. Nothing else." puts "Version: #{AppRb::VERSION}" puts "" - puts " app-rb <yml> <command>" + puts " app-rb <yml> [options] <command>" puts "" - puts "Usage:" + puts "Options:" + puts " --vault <vault-file> - vault file (<pwd>/vault.key by default)" + puts "" + puts "Commands:" puts " deploy [hash] - deploy new version of app" puts " status - status of app" - puts " stop - stop app" + puts " stop - stop app completely" puts " run <cmd> [args] - one time command" puts " cd - go to run node" + puts " encrypt <string> - encrypt script using vault-file" + puts " decrypt <string> - decrypt script using vault-file" puts "" - puts "Advanced:" + puts "Advanced commands:" puts " redeploy - redeploy app" puts " clean - stop and remove not current containers" end end end