hiera-eyaml-vault 0.0.1

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 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,3 @@
1
+ require 'hiera/backend/eyaml/encryptors/vault'
2
+
3
+ Hiera::Backend::Eyaml::Encryptors::Vault.register
@@ -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: []