hiera-eyaml-vault 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2500c39c866bab8c7403755030356b0fcecaa9cd433157e961e6a4e7f87d7d8a
|
4
|
+
data.tar.gz: 44966b8d2fba03c146d9f8835893f4c5245bd0655bc4db6667f708e25f78ce63
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d8e4f2a4655ec04907d4ca9f1687123eea7b106b669a6fdd90c341acb23f6e693071a1026172b25c964928cc956e9d2a476781185f7569010984349938d99f6d
|
7
|
+
data.tar.gz: caddceb7edacdaf8a3f00a2b63bf5de647df5b54613aef49d54b74f5c62e7f510e4f3b205849740715bb605347e377a7d0c1f85c5b5fb17214cb5c78dbbc5445
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'hiera/backend/eyaml/encryptor'
|
3
|
+
require 'hiera/backend/eyaml/encryptors/vault/httphandler'
|
4
|
+
require 'hiera/backend/eyaml/utils'
|
5
|
+
require 'hiera/backend/eyaml/plugins'
|
6
|
+
require 'hiera/backend/eyaml/options'
|
7
|
+
|
8
|
+
class Hiera
|
9
|
+
module Backend
|
10
|
+
module Eyaml
|
11
|
+
module Encryptors
|
12
|
+
class Vault < Encryptor
|
13
|
+
class AuthenticationError < Exception
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
VERSION = "0.0.1"
|
18
|
+
HTTP_HANDLER = Hiera::Backend::Eyaml::Encryptors::Vault::Httphandler
|
19
|
+
|
20
|
+
self.tag = 'VAULT'
|
21
|
+
|
22
|
+
self.options = {
|
23
|
+
:addr => {
|
24
|
+
desc: "Address of the vault server",
|
25
|
+
type: :string,
|
26
|
+
default: "https://127.0.0.1:8200"
|
27
|
+
},
|
28
|
+
|
29
|
+
:role_id => {
|
30
|
+
desc: "role_id for the Approle",
|
31
|
+
type: :string,
|
32
|
+
},
|
33
|
+
|
34
|
+
:secret_id => {
|
35
|
+
desc: "secret_id for the Approle",
|
36
|
+
type: :string,
|
37
|
+
},
|
38
|
+
|
39
|
+
:use_ssl => {
|
40
|
+
desc: "Use SSL to connect to vault",
|
41
|
+
type: :boolean,
|
42
|
+
default: true
|
43
|
+
},
|
44
|
+
|
45
|
+
:ssl_verify => {
|
46
|
+
desc: "Verify SSL certs",
|
47
|
+
type: :boolean,
|
48
|
+
default: true
|
49
|
+
},
|
50
|
+
|
51
|
+
:keyname => {
|
52
|
+
desc: "Vault transit key name (default 'hiera')",
|
53
|
+
type: :string,
|
54
|
+
default: 'hiera'
|
55
|
+
},
|
56
|
+
|
57
|
+
:api_version => {
|
58
|
+
desc: "API version to use",
|
59
|
+
type: :integer,
|
60
|
+
default: 1
|
61
|
+
}
|
62
|
+
}
|
63
|
+
class << self
|
64
|
+
|
65
|
+
def create_keys
|
66
|
+
diagnostic_message = self.option :diagnostic_message
|
67
|
+
puts "Create_keys: #{diagnostic_message}"
|
68
|
+
end
|
69
|
+
|
70
|
+
#### BEGIN IMPORT
|
71
|
+
|
72
|
+
def vault_url(endpoint)
|
73
|
+
uri = []
|
74
|
+
uri << option(:addr)
|
75
|
+
uri << "v#{option :api_version}"
|
76
|
+
uri << endpoint
|
77
|
+
uri.flatten.join("/")
|
78
|
+
end
|
79
|
+
|
80
|
+
def login
|
81
|
+
role_id = option :role_id
|
82
|
+
secret_id = option :secret_id
|
83
|
+
|
84
|
+
login_data = { "role_id" => role_id }
|
85
|
+
login_data['secret_id'] = secret_id unless secret_id.nil?
|
86
|
+
|
87
|
+
response = vault_post(login_data, :login, false)
|
88
|
+
@approle_token = response['auth']['client_token']
|
89
|
+
end
|
90
|
+
|
91
|
+
def ssl?
|
92
|
+
option :use_ssl
|
93
|
+
end
|
94
|
+
|
95
|
+
def read_file(file)
|
96
|
+
raise Exception, "Cannot read #{file}" unless File.exists?(file)
|
97
|
+
File.read(file)
|
98
|
+
end
|
99
|
+
|
100
|
+
def ssl_key
|
101
|
+
return nil if option(:ssl_key).nil?
|
102
|
+
@vault_ssl_key ||= read_file(option :ssl_key)
|
103
|
+
@vault_ssl_key
|
104
|
+
end
|
105
|
+
|
106
|
+
def ssl_cert
|
107
|
+
return nil if option(:ssl_cert).nil?
|
108
|
+
@vault_ssl_cert ||= read_file(option :ssl_cert)
|
109
|
+
@vault_ssl_cert
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
def token_configured?
|
114
|
+
not option(:token).nil?
|
115
|
+
end
|
116
|
+
|
117
|
+
def token
|
118
|
+
authenticate
|
119
|
+
option(:token) || @approle_token
|
120
|
+
end
|
121
|
+
|
122
|
+
def authenticate
|
123
|
+
unless token_configured?
|
124
|
+
login if @approle_token.nil?
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def endpoint(action)
|
129
|
+
{
|
130
|
+
:decrypt => "transit/decrypt/#{option :keyname}",
|
131
|
+
:encrypt => "transit/encrypt/#{option :keyname}",
|
132
|
+
:login => "auth/approle/login"
|
133
|
+
}[action]
|
134
|
+
end
|
135
|
+
|
136
|
+
def url_path(action)
|
137
|
+
vault_url(endpoint(action))
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
def parse_response(response)
|
143
|
+
body = JSON.load(response.body)
|
144
|
+
if response.code_type == Net::HTTPOK
|
145
|
+
return body
|
146
|
+
else
|
147
|
+
if response.code == "403"
|
148
|
+
raise AuthenticationError, body
|
149
|
+
end
|
150
|
+
if body['errors'].is_a?(Array)
|
151
|
+
message = body['errors'].join("\n")
|
152
|
+
else
|
153
|
+
message = "Failed to decrypt entry #{body}"
|
154
|
+
end
|
155
|
+
raise Exception, "Error decrypting data from Vault: #{message}"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def vault_post(data, action, use_token=true, headers={})
|
160
|
+
url = url_path(action)
|
161
|
+
http_options = {}
|
162
|
+
|
163
|
+
if ssl?
|
164
|
+
http_options = {
|
165
|
+
:ssl => true,
|
166
|
+
:ssl_verify => option(:ssl_verify),
|
167
|
+
:ssl_cert => ssl_cert,
|
168
|
+
:ssl_key => ssl_key,
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
172
|
+
begin
|
173
|
+
tries ||= 0
|
174
|
+
headers['X-Vault-Token'] = token if use_token
|
175
|
+
parse_response HTTP_HANDLER.post(url, data, headers, http_options)
|
176
|
+
rescue AuthenticationError => e
|
177
|
+
login
|
178
|
+
retry if (tries += 1) < 2
|
179
|
+
raise
|
180
|
+
rescue HTTPError => e
|
181
|
+
raise Exception, "HTTP Error: #{e}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def decrypt(string)
|
186
|
+
response = vault_post({ 'ciphertext' => string}, :decrypt)
|
187
|
+
response_data=response['data']
|
188
|
+
Base64.decode64(response_data['plaintext'])
|
189
|
+
end
|
190
|
+
|
191
|
+
def encrypt(plain)
|
192
|
+
encoded = Base64.encode64(plain)
|
193
|
+
response = vault_post({ 'plaintext' => encoded}, :encrypt)
|
194
|
+
response_data=response['data']
|
195
|
+
response_data['ciphertext']
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
class Hiera
|
6
|
+
module Backend
|
7
|
+
module Eyaml
|
8
|
+
module Encryptors
|
9
|
+
class Vault < Encryptor
|
10
|
+
class HTTPError < Exception
|
11
|
+
end
|
12
|
+
class Httphandler
|
13
|
+
class << self
|
14
|
+
|
15
|
+
def post(uri_str, data={}, headers={}, options={})
|
16
|
+
uri = URI.parse(uri_str)
|
17
|
+
request = Net::HTTP::Post.new(uri.path)
|
18
|
+
request.body = data.to_json
|
19
|
+
http_send(uri, request, headers, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def put(uri_str, data={}, headers={}, options={})
|
23
|
+
uri = URI.parse(uri_str)
|
24
|
+
request = Net::HTTP::Put.new(uri.path)
|
25
|
+
request.body = data.to_json
|
26
|
+
http_send(uri, request, headers, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def http_send(uri, request, headers={}, options={})
|
31
|
+
request.add_field('Content-Type', options[:content_type]) if options[:content_type]
|
32
|
+
|
33
|
+
headers.each do |header, value|
|
34
|
+
request.add_field(header, value)
|
35
|
+
end
|
36
|
+
|
37
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
38
|
+
if options[:ssl]
|
39
|
+
http.use_ssl = true
|
40
|
+
http.verify_mode = options[:ssl_verify] ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
41
|
+
http.cert = OpenSSL::X509::Certificate.new(options[:ssl_cert]) if options[:ssl_cert]
|
42
|
+
http.key = OpenSSL::PKey::RSA.new(options[:ssl_key]) if options[:ssl_key]
|
43
|
+
end
|
44
|
+
|
45
|
+
begin
|
46
|
+
response = http.request(request)
|
47
|
+
return response
|
48
|
+
rescue => e
|
49
|
+
raise HTTPError, e.message
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hiera-eyaml-vault
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Craig Dunn
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-11-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hiera-http
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "<"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "<"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.0.0
|
27
|
+
description: Eyaml plugin for Vault transit secrets engine
|
28
|
+
email:
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/hiera/backend/eyaml/encryptors/vault.rb
|
34
|
+
- lib/hiera/backend/eyaml/encryptors/vault/eyaml_init.rb
|
35
|
+
- lib/hiera/backend/eyaml/encryptors/vault/httphandler.rb
|
36
|
+
homepage: http://github.com/crayfishx/hiera-eyaml-vault
|
37
|
+
licenses:
|
38
|
+
- Apache-2.0
|
39
|
+
metadata: {}
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 2.7.6.2
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Encryption plugin for hiera-eyaml to use Vault's transit secrets engine
|
60
|
+
test_files: []
|