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 +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
|
+
[![Gem Version](https://badge.fury.io/rb/yaml_vault.svg)](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
|