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,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: []