yaml_vault 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40d3decc007bc319e9a1a735ccf599dd706ddc5c
4
- data.tar.gz: 3f3c1c587bb2e0d9e401a5d9348f5904df040b63
3
+ metadata.gz: 2a0bdfb9602aac1932efba9fd68eab1083ed2c32
4
+ data.tar.gz: 2e8f8caede77d7f49d50f0354a39d9809b9cfbe5
5
5
  SHA512:
6
- metadata.gz: 23bf5c76edb6852b819c8e89cab6325b7ae77b88a4f729e4cb73f04cef470083318929993e9667fedc5aebfe61e8c594d126f4887f6182be0f8d048e6b7638f3
7
- data.tar.gz: f01be0901bc36145ac4d05eecc704c72822c5c9e8a570c644064365aae0bf17f5fce6f6b09ab5ccaa6afbec5db0ed53c1cd023428e7a7ebde5a2e99fdc64256d
6
+ metadata.gz: 1b994e252cb2d603a1bc69944a0d5d575ad1c10e51b10ff834024f6ffe939c935a7483bc8cdd258651b734fcddc394e193f957d351021de0b8ca0f9372daaeec
7
+ data.tar.gz: 7e2893a031100688009d2a71ac912b816cd85cc45c2bc802bd581aa29728a5f69d6a436d7d3b86515cdb3f065fcdbfae4471aa3431fed61e2912ed15d2ced025
data/.gitignore CHANGED
@@ -7,3 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+
11
+ .envrc
data/README.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # YamlVault
2
+ [![Gem Version](https://badge.fury.io/rb/yaml_vault.svg)](https://badge.fury.io/rb/yaml_vault)
2
3
 
3
- Yaml file encryption/decription helper.
4
+ Yaml file encryption/decryption helper.
5
+
6
+ ## Encryption Algorithm
7
+
8
+ yaml_vault uses ActiveSupport::MessageEncryptor.
9
+
10
+ Default cipher is `aes-256-cbc`.
11
+ Default sign digest is `SHA256`.
4
12
 
5
13
  ## Installation
6
14
 
data/exe/yaml_vault CHANGED
@@ -7,35 +7,83 @@ require 'thor'
7
7
  class YamlVault::Cli < Thor
8
8
  include Thor::Actions
9
9
 
10
+ class_option :key, aliases: "-k", type: :string, banner: "KEYNAME (format: \"KEY1.INNER_KEY,KEY2\")", desc: "target key", default: "vault"
11
+ class_option :cryptor, type: :string, enum: %w(simple aws-kms), default: "simple"
12
+
13
+ class_option :salt, aliases: "-s", type: :string
14
+ class_option :cipher, type: :string, desc: "Encrypt cipher (see. OpenSSL::Cipher.ciphers)", default: "aes-256-cbc"
15
+ class_option :digest, type: :string, desc: "Sign digest algorithm (see. OpenSSL::Digest.constants)", default: "SHA256"
16
+ class_option :use_sign_passphrase, type: :boolean, default: false
17
+
18
+ class_option :aws_kms_key_id, type: :string
19
+ class_option :aws_region, type: :string
20
+ class_option :aws_access_key_id, type: :string
21
+ class_option :aws_secret_access_key, type: :string
22
+
10
23
  desc "encrypt YAML_FILE", "Encrypt yaml file"
11
24
  method_option :output, aliases: "-o", type: :string, required: true
12
- method_option :key, aliases: "-k", type: :string, desc: "target key (format: \"KEY1.INNER_KEY,KEY2\")", default: "vault"
13
- method_option :salt, aliases: "-s", type: :string
14
- method_option :passphrase, aliases: "-p", type: :string
15
- method_option :cipher, type: :string
16
25
  def encrypt(yaml_file)
17
- passphrase = ENV["YAML_VAULT_PASSPHRASE"] || options[:passphrase] || ask("Enter passphrase:", echo: false)
18
- raise "Please input passphrase" if passphrase.blank?
19
- keys = options[:key] ? options[:key].split(/,\s?/).map { |k| k.split(".") } : ["vault"]
20
- encrypted_yaml = YamlVault.encrypt_yaml(passphrase, yaml_file, keys, salt: options[:salt], cipher: options[:cipher])
26
+ passphrase, sign_passphrase = get_passphrase
27
+ encrypted_yaml = YamlVault::Main.new(
28
+ yaml_file,
29
+ target_keys,
30
+ options[:cryptor],
31
+ passphrase: passphrase,
32
+ sign_passphrase: sign_passphrase,
33
+ salt: options[:salt], cipher: options[:cipher], digest: options[:digest],
34
+ aws_kms_key_id: options[:aws_kms_key_id],
35
+ aws_region: options[:aws_region],
36
+ aws_access_key_id: options[:aws_access_key_id],
37
+ aws_secret_access_key: options[:aws_secret_access_key]
38
+ ).encrypt_yaml
21
39
  puts "encrypted #{yaml_file} -> #{options[:output]}"
22
40
  File.open(options[:output], "w") { |f| f.write encrypted_yaml }
23
41
  end
24
42
 
25
43
  desc "decrypt YAML_FILE", "Decrypt yaml file"
26
44
  method_option :output, aliases: "-o", type: :string, required: true
27
- method_option :key, aliases: "-k", type: :string, desc: "target key (format: \"KEY1.INNER_KEY,KEY2\")", default: "vault"
28
- method_option :salt, aliases: "-s", type: :string
29
- method_option :passphrase, aliases: "-p", type: :string
30
- method_option :cipher, type: :string
31
45
  def decrypt(yaml_file)
32
- passphrase = ENV["YAML_VAULT_PASSPHRASE"] || options[:passphrase] || ask("Enter passphrase:", echo: false)
33
- raise "Please input passphrase" if passphrase.blank?
34
- keys = options[:key] ? options[:key].split(/,\s?/).map { |k| k.split(".") } : ["vault"]
35
- decrypted_yaml = YamlVault.decrypt_yaml(passphrase, yaml_file, keys, salt: options[:salt], cipher: options[:cipher])
46
+ passphrase, sign_passphrase = get_passphrase
47
+ decrypted_yaml = YamlVault::Main.new(
48
+ yaml_file,
49
+ target_keys,
50
+ options[:cryptor],
51
+ passphrase: passphrase,
52
+ sign_passphrase: sign_passphrase,
53
+ salt: options[:salt], cipher: options[:cipher], digest: options[:digest],
54
+ aws_kms_key_id: options[:aws_kms_key_id],
55
+ aws_region: options[:aws_region],
56
+ aws_access_key_id: options[:aws_access_key_id],
57
+ aws_secret_access_key: options[:aws_secret_access_key]
58
+ ).decrypt_yaml
36
59
  puts "decrypted #{yaml_file} -> #{options[:output]}"
37
60
  File.open(options[:output], "w") { |f| f.write decrypted_yaml }
38
61
  end
62
+
63
+ private
64
+
65
+ def get_passphrase
66
+ return nil, nil unless options[:cryptor] == "simple"
67
+
68
+ passphrase = ENV["YAML_VAULT_PASSPHRASE"] || ask("Enter passphrase:", echo: false)
69
+ puts "\n"
70
+ if ENV["YAML_VAULT_SIGN_PASSPHRASE"]
71
+ sign_passphrase = ENV["YAML_VAULT_SIGN_PASSPHRASE"]
72
+ elsif options[:use_sign_passphrase]
73
+ sign_passphrase = ask("Enter sign passphrase:", echo: false)
74
+ puts "\n"
75
+ else
76
+ sign_passphrase = nil
77
+ end
78
+
79
+ raise "Please input passphrase" if passphrase.blank?
80
+
81
+ return passphrase, sign_passphrase
82
+ end
83
+
84
+ def target_keys
85
+ options[:key] ? options[:key].split(/,\s?/).map { |k| k.split(".") } : ["vault"]
86
+ end
39
87
  end
40
88
 
41
89
  YamlVault::Cli.start
@@ -1,3 +1,3 @@
1
1
  module YamlVault
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/yaml_vault.rb CHANGED
@@ -1,33 +1,65 @@
1
1
  require 'yaml_vault/version'
2
2
  require 'yaml'
3
+ require 'base64'
3
4
  require 'erb'
4
5
  require 'active_support'
5
6
 
6
7
  module YamlVault
7
- class << self
8
- def encrypt_yaml(passphrase, yaml, keys, salt: nil, cipher: nil)
9
- process_yaml(passphrase, yaml, keys, salt: salt.to_s, cipher: cipher) do |cryptor, data|
10
- do_process(cryptor, data, :encrypt)
8
+ class Main
9
+ def initialize(
10
+ yaml, keys, cryptor_name = nil,
11
+ passphrase: nil, sign_passphrase: nil, salt: nil, cipher: "aes-256-cbc", digest: "SHA256",
12
+ aws_kms_key_id: nil, aws_region: nil, aws_access_key_id: nil, aws_secret_access_key: nil
13
+ )
14
+ @yaml = yaml
15
+ @keys = keys
16
+
17
+ @passphrase = passphrase
18
+ @sign_passphrase = sign_passphrase
19
+ @salt = salt.to_s
20
+ @cipher = cipher
21
+ @digest = digest
22
+
23
+ @aws_kms_key_id = aws_kms_key_id
24
+ @aws_region = aws_region
25
+ @aws_access_key_id = aws_access_key_id
26
+ @aws_secret_access_key = aws_secret_access_key
27
+
28
+ @cryptor = get_cryptor(cryptor_name)
29
+ end
30
+
31
+ def encrypt_yaml
32
+ process_yaml do |data|
33
+ do_process(data, :encrypt)
11
34
  end
12
35
  end
13
36
 
14
- def decrypt_yaml(passphrase, yaml, keys, salt: nil, cipher: nil)
15
- process_yaml(passphrase, yaml, keys, salt: salt.to_s, cipher: cipher) do |cryptor, data|
16
- do_process(cryptor, data, :decrypt)
37
+ def decrypt_yaml
38
+ process_yaml do |data|
39
+ do_process(data, :decrypt)
17
40
  end
18
41
  end
19
42
 
20
43
  private
21
44
 
22
- def process_yaml(passphrase, yaml, keys, salt:, cipher:)
23
- cryptor = ValueCryptor.new(passphrase, salt, cipher)
24
- data = YAML.load(ERB.new(File.read(yaml)).result)
25
- keys.each do |key|
45
+ def get_cryptor(name)
46
+ if name == "simple"
47
+ ValueCryptor::Simple.new(@passphrase, @sign_passphrase, @salt, @cipher, @digest)
48
+ elsif name == "aws-kms"
49
+ ValueCryptor::KMS.new(@aws_kms_key_id, region: @aws_region, aws_access_key_id: @aws_access_key_id, aws_secret_access_key: @aws_secret_access_key)
50
+ else
51
+ ValueCryptor::Simple.new(@passphrase, @sign_passphrase, @salt, @cipher, @digest)
52
+ end
53
+ end
54
+
55
+ def process_yaml
56
+ data = YAML.load(ERB.new(File.read(@yaml)).result)
57
+ @keys.each do |key|
26
58
  target = key.inject(data) do |t, part|
27
59
  t[part]
28
60
  end
29
61
 
30
- vault_data = yield cryptor, target
62
+ vault_data = yield target
31
63
 
32
64
  target_parent = key[0..-2].inject(data) do |t, part|
33
65
  t[part]
@@ -37,42 +69,74 @@ module YamlVault
37
69
  data.to_yaml
38
70
  end
39
71
 
40
- def do_process(cryptor, data, method)
72
+ def do_process(data, method)
41
73
  case data
42
74
  when Hash
43
75
  data.each do |k, v|
44
76
  if v.is_a?(Hash) || v.is_a?(Array)
45
- do_process(cryptor, v, method)
77
+ do_process(v, method)
46
78
  else
47
- data[k] = cryptor.send(method, v)
79
+ data[k] = @cryptor.send(method, v)
48
80
  end
49
81
  end
50
82
  when Array
51
83
  data.each_with_index do |v, i|
52
84
  if v.is_a?(Hash) || v.is_a?(Array)
53
- do_process(cryptor, v, method)
85
+ do_process(v, method)
54
86
  else
55
- data[i] = cryptor.send(method, v)
87
+ data[i] = @cryptor.send(method, v)
56
88
  end
57
89
  end
58
90
  else
59
- cryptor.send(method, data)
91
+ @cryptor.send(method, data)
60
92
  end
61
93
  end
62
- end
63
94
 
64
- class ValueCryptor
65
- def initialize(passphrase, salt, cipher)
66
- key = ActiveSupport::KeyGenerator.new(passphrase, cipher: cipher || 'aes-256-cbc').generate_key(salt)
67
- @cryptor = ActiveSupport::MessageEncryptor.new(key)
68
- end
95
+ module ValueCryptor
96
+ class Simple
97
+ def initialize(passphrase, sign_passphrase, salt, cipher, digest, key_size = 64)
98
+ key = ActiveSupport::KeyGenerator.new(passphrase).generate_key(salt, key_size)
99
+ signature_key = ActiveSupport::KeyGenerator.new(sign_passphrase).generate_key(salt, key_size) if sign_passphrase
69
100
 
70
- def encrypt(value)
71
- @cryptor.encrypt_and_sign(value)
72
- end
101
+ if signature_key
102
+ @cryptor = ActiveSupport::MessageEncryptor.new(key, signature_key, cipher: cipher, digest: digest)
103
+ else
104
+ @cryptor = ActiveSupport::MessageEncryptor.new(key, cipher: cipher, digest: digest)
105
+ end
106
+ end
107
+
108
+ def encrypt(value)
109
+ @cryptor.encrypt_and_sign(value)
110
+ end
73
111
 
74
- def decrypt(value)
75
- @cryptor.decrypt_and_verify(value)
112
+ def decrypt(value)
113
+ @cryptor.decrypt_and_verify(value)
114
+ end
115
+ end
116
+
117
+ class KMS
118
+ def initialize(key_id, region: nil, aws_access_key_id: nil, aws_secret_access_key: nil)
119
+ require 'aws-sdk'
120
+ options = {}
121
+ options[:region] = region if region
122
+ options[:access_key_id] = aws_access_key_id if aws_access_key_id
123
+ options[:secret_access_key] = aws_secret_access_key if aws_secret_access_key
124
+ @client = Aws::KMS::Client.new(options)
125
+ @key_id = key_id
126
+ end
127
+
128
+ def encrypt(value)
129
+ resp = @client.encrypt(key_id: @key_id, plaintext: YAML.dump(value))
130
+ Base64.strict_encode64(resp.ciphertext_blob)
131
+ end
132
+
133
+ def decrypt(value)
134
+ resp = @client.decrypt(ciphertext_blob: Base64.strict_decode64(value))
135
+ YAML.load(resp.plaintext)
136
+ end
137
+ end
76
138
  end
139
+
140
+ private_constant :ValueCryptor
77
141
  end
78
142
  end
data/yaml_vault.gemspec CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_runtime_dependency "activesupport", ">= 4"
22
22
  spec.add_runtime_dependency "thor"
23
23
 
24
+ spec.add_development_dependency "aws-sdk", "~> 2.0"
24
25
  spec.add_development_dependency "bundler", "~> 1.11"
25
26
  spec.add_development_dependency "rake", "~> 10.0"
26
27
  spec.add_development_dependency "rspec", "~> 3.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yaml_vault
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - joker1007
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-30 00:00:00.000000000 Z
11
+ date: 2016-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: aws-sdk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement