Class: Bolt::Plugin::Vault
- Inherits:
-
Object
- Object
- Bolt::Plugin::Vault
- Defined in:
- lib/bolt/plugin/vault.rb
Defined Under Namespace
Classes: VaultHTTPError
Constant Summary collapse
- TOKEN_HEADER =
All requests for secrets must have a token in the request header
"X-Vault-Token"- DEFAULT_HEADER =
Default header for all requests, including auth methods
{ "Content-Type" => "application/json", "Accept" => "application/json" }.freeze
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
Instance Method Summary collapse
-
#auth_token(auth) ⇒ Object
Authenticate with Vault using the ‘Token’ auth method.
-
#auth_userpass(auth, opts) ⇒ Object
Authenticate with Vault using the ‘Userpass’ auth method.
-
#client(uri, opts) ⇒ Object
Configure the http/s client.
- #hooks ⇒ Object
-
#initialize(config:, **_opts) ⇒ Vault
constructor
A new instance of Vault.
- #name ⇒ Object
- #parse_response(response, opts) ⇒ Object
- #request(verb, uri, opts, data, header = {}) ⇒ Object
-
#request_token(auth, opts) ⇒ Object
Request a token from Vault using one of the auth methods.
- #resolve_reference(opts) ⇒ Object
-
#token(opts) ⇒ Object
Auth token to vault server.
-
#uri(opts, path = nil) ⇒ Object
Request uri - built up from Vault server url and secrets path.
- #validate_auth(auth, required_keys) ⇒ Object
-
#validate_config(config) ⇒ Object
Make sure no unexpected keys are in the config.
-
#validate_options(opts) ⇒ Object
Make sure no unexpected keys are in the inventory config and that required keys are present.
Constructor Details
#initialize(config:, **_opts) ⇒ Vault
Returns a new instance of Vault.
61 62 63 64 65 |
# File 'lib/bolt/plugin/vault.rb', line 61 def initialize(config:, **_opts) validate_config(config) @config = config @logger = Logging.logger[self] end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
15 16 17 |
# File 'lib/bolt/plugin/vault.rb', line 15 def config @config end |
Instance Method Details
#auth_token(auth) ⇒ Object
Authenticate with Vault using the ‘Token’ auth method
190 191 192 193 |
# File 'lib/bolt/plugin/vault.rb', line 190 def auth_token(auth) validate_auth(auth, %w[token]) auth['token'] end |
#auth_userpass(auth, opts) ⇒ Object
Authenticate with Vault using the ‘Userpass’ auth method
196 197 198 199 200 201 202 203 |
# File 'lib/bolt/plugin/vault.rb', line 196 def auth_userpass(auth, opts) validate_auth(auth, %w[user pass]) path = "auth/userpass/login/#{auth['user']}" uri = uri(opts, path) data = { "password" => auth['pass'] }.to_json request(:Post, uri, opts, data)['auth']['client_token'] end |
#client(uri, opts) ⇒ Object
Configure the http/s client
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/bolt/plugin/vault.rb', line 95 def client(uri, opts) client = Net::HTTP.new(uri.host, uri.port) if uri.scheme == 'https' cacert = opts['cacert'] || config['cacert'] || ENV['VAULT_CACERT'] unless cacert raise Bolt::ValidationError, "Expected cacert to be set when using https" end client.use_ssl = true client.ssl_version = :TLSv1_2 client.ca_file = cacert client.verify_mode = OpenSSL::SSL::VERIFY_PEER end client end |
#hooks ⇒ Object
57 58 59 |
# File 'lib/bolt/plugin/vault.rb', line 57 def hooks [:resolve_reference] end |
#name ⇒ Object
53 54 55 |
# File 'lib/bolt/plugin/vault.rb', line 53 def name 'vault' end |
#parse_response(response, opts) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/bolt/plugin/vault.rb', line 152 def parse_response(response, opts) data = case opts['version'] when 2 response['data']['data'] else response['data'] end if opts['field'] unless data[opts['field']] raise Bolt::ValidationError, "Unknown secrets field: #{opts['field']}" end data[opts['field']] else data end end |
#request(verb, uri, opts, data, header = {}) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/bolt/plugin/vault.rb', line 123 def request(verb, uri, opts, data, header = {}) # Add on any header options header = DEFAULT_HEADER.merge(header) # Create the HTTP request client = client(uri, opts) request = Net::HTTP.const_get(verb).new(uri.request_uri, header) # Attach any data request.body = data if data # Send the request begin response = client.request(request) rescue StandardError => e raise Bolt::Error.new( "Failed to connect to #{uri}: #{e.}", 'CONNECT_ERROR' ) end case response when Net::HTTPOK JSON.parse(response.body) else raise VaultHTTPError, response end end |
#request_token(auth, opts) ⇒ Object
Request a token from Vault using one of the auth methods
171 172 173 174 175 176 177 178 179 180 |
# File 'lib/bolt/plugin/vault.rb', line 171 def request_token(auth, opts) case auth['method'] when 'token' auth_token(auth) when 'userpass' auth_userpass(auth, opts) else raise Bolt::ValidationError, "Unknown auth method: #{auth['method']}" end end |
#resolve_reference(opts) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/bolt/plugin/vault.rb', line 67 def resolve_reference(opts) (opts) header = { TOKEN_HEADER => token(opts) } response = request(:Get, uri(opts), opts, nil, header) parse_response(response, opts) end |
#token(opts) ⇒ Object
Auth token to vault server
115 116 117 118 119 120 121 |
# File 'lib/bolt/plugin/vault.rb', line 115 def token(opts) if (auth = opts['auth'] || config['auth']) request_token(auth, opts) else ENV['VAULT_TOKEN'] end end |
#uri(opts, path = nil) ⇒ Object
Request uri - built up from Vault server url and secrets path
80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/bolt/plugin/vault.rb', line 80 def uri(opts, path = nil) url = opts['server_url'] || config['server_url'] || ENV['VAULT_ADDR'] # Handle the different versions of the API if opts['version'] == 2 mount, store = opts['path'].split('/', 2) opts['path'] = [mount, 'data', store].join('/') end path ||= opts['path'] URI.parse(File.join(url, "v1", path)) end |
#validate_auth(auth, required_keys) ⇒ Object
182 183 184 185 186 187 |
# File 'lib/bolt/plugin/vault.rb', line 182 def validate_auth(auth, required_keys) required_keys.each do |key| next if auth[key] raise Bolt::ValidationError, "Expected key in #{auth['method']} auth method: #{key}" end end |
#validate_config(config) ⇒ Object
Make sure no unexpected keys are in the config
27 28 29 30 31 32 33 34 |
# File 'lib/bolt/plugin/vault.rb', line 27 def validate_config(config) known_keys = %w[server_url auth cacert] config.each do |key, _v| next if known_keys.include?(key) raise Bolt::ValidationError, "Unexpected key in Vault plugin config: #{key}" end end |
#validate_options(opts) ⇒ Object
Make sure no unexpected keys are in the inventory config and that required keys are present
38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/bolt/plugin/vault.rb', line 38 def (opts) known_keys = %w[_plugin server_url auth path field version cacert] required_keys = %w[path] opts.each do |key, _v| next if known_keys.include?(key) raise Bolt::ValidationError, "Unexpected key in inventory config: #{key}" end required_keys.each do |key| next if opts[key] raise Bolt::ValidationError, "Expected key in inventory config: #{key}" end end |