yaml_vault 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +9 -1
- data/exe/yaml_vault +64 -16
- data/lib/yaml_vault/version.rb +1 -1
- data/lib/yaml_vault.rb +93 -29
- data/yaml_vault.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a0bdfb9602aac1932efba9fd68eab1083ed2c32
|
4
|
+
data.tar.gz: 2e8f8caede77d7f49d50f0354a39d9809b9cfbe5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b994e252cb2d603a1bc69944a0d5d575ad1c10e51b10ff834024f6ffe939c935a7483bc8cdd258651b734fcddc394e193f957d351021de0b8ca0f9372daaeec
|
7
|
+
data.tar.gz: 7e2893a031100688009d2a71ac912b816cd85cc45c2bc802bd581aa29728a5f69d6a436d7d3b86515cdb3f065fcdbfae4471aa3431fed61e2912ed15d2ced025
|
data/README.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
# YamlVault
|
2
|
+
[](https://badge.fury.io/rb/yaml_vault)
|
2
3
|
|
3
|
-
Yaml file encryption/
|
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 =
|
18
|
-
|
19
|
-
|
20
|
-
|
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 =
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
data/lib/yaml_vault/version.rb
CHANGED
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
|
8
|
-
def
|
9
|
-
|
10
|
-
|
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
|
15
|
-
process_yaml
|
16
|
-
do_process(
|
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
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
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(
|
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(
|
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(
|
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
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
75
|
-
|
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.
|
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-
|
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
|