class TerraspacePluginAzurerm::Interfaces::Helper::Secret::Fetcher
Public Class Methods
new()
click to toggle source
# File lib/terraspace_plugin_azurerm/interfaces/helper/secret/fetcher.rb, line 11 def initialize o = base_client_options @client_id = o[:client_id] @client_secret = o[:client_secret] @tenant_id = o[:tenant_id] end
Public Instance Methods
fetch(name, opts={})
click to toggle source
# File lib/terraspace_plugin_azurerm/interfaces/helper/secret/fetcher.rb, line 18 def fetch(name, opts={}) opts[:vault] ||= TerraspacePluginAzurerm.config.secrets.vault get_secret(name, opts) end
get_secret(name, vault: nil, version: nil)
click to toggle source
# File lib/terraspace_plugin_azurerm/interfaces/helper/secret/fetcher.rb, line 23 def get_secret(name, vault: nil, version: nil) unless token return "ERROR: Unable to authorize and get the temporary token. Double check your ARM_ env variables." end version = "/#{version}" if version vault_subdomain = vault.downcase # Using Azure REST API since the old gem doesnt support secrets https://github.com/Azure/azure-sdk-for-ruby # https://docs.microsoft.com/en-us/rest/api/keyvault/getsecret/getsecret url = "https://#{vault_subdomain}.vault.azure.net/secrets/#{name}#{version}?api-version=7.1" uri = URI(url) req = Net::HTTP::Get.new(uri) req["Authorization"] = token req["Content-Type"] = "application/json" resp = nil begin resp = send_request(uri, req) rescue VaultNotFoundError message = "WARN: Vault not found #{vault}" logger.info message.color(:yellow) return message end case resp.code.to_s when /^2/ data = JSON.load(resp.body) data['value'] else message = standard_error_message(resp) logger.info "WARN: #{message}".color(:yellow) message end end
send_request(uri, req)
click to toggle source
# File lib/terraspace_plugin_azurerm/interfaces/helper/secret/fetcher.rb, line 58 def send_request(uri, req) http = Net::HTTP.new(uri.host, uri.port) http.open_timeout = http.read_timeout = 30 http.use_ssl = true if uri.scheme == 'https' begin http.request(req) # response rescue SocketError => e # SocketError: Failed to open TCP connection to MISSING-VAULT.vault.azure.net:443 (getaddrinfo: Name or service not known) if e.message.include?("vault.azure.net") raise VaultNotFoundError.new(e) else raise end end end
standard_error_message(resp)
click to toggle source
Secret
error handling: 1. network 2. json parse 3. missing secret
Azure API responses with decent error message when
403 Forbidden - KeyVault Access Policy needs to be set up 404 Not Found - Secret name is incorrect
# File lib/terraspace_plugin_azurerm/interfaces/helper/secret/fetcher.rb, line 81 def standard_error_message(resp) data = JSON.load(resp.body) data['error']['message'] rescue JSON::ParserError resp.body end
token()
click to toggle source
# File lib/terraspace_plugin_azurerm/interfaces/helper/secret/fetcher.rb, line 89 def token return @@token unless @@token.nil? url = "https://login.microsoftonline.com/#{@tenant_id}/oauth2/token" uri = URI(url) req = Net::HTTP::Get.new(uri) req.set_form_data( grant_type: "client_credentials", client_id: @client_id, client_secret: @client_secret, resource: "https://vault.azure.net", ) resp = send_request(uri, req) data = JSON.load(resp.body) if resp.code =~ /^2/ @@token = "Bearer #{data['access_token']}" if data else logger.info "WARN: #{data['error_description']}".color(:yellow) # return false otherwise error message is used as the bearer toke and get this error: # ArgumentError: header field value cannot include CR/LF @@token = false end end