terraspace_plugin_azurerm 0.2.3 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3164712306e20fe0da2192f6e8168e7d19dc773f840f351f351bd3cd0c56fd76
4
- data.tar.gz: 4e3a39f1aacad41a0806f5e9c81013119b58f11dc42b2d0ac791f9e0c4e44814
3
+ metadata.gz: 8704700ce76610490c5f29da3091ea5b9b14489911095418deb51561920f2062
4
+ data.tar.gz: e60b1a62a544c6cbc21838c13c41c93541806786600c85620a650e45a0aa7ae2
5
5
  SHA512:
6
- metadata.gz: 005df536cf5d7b6ed59435e2560bce4924ecc8a0cf4be3a6c2ae294b711c160e435797a62758d476978d3be3914f10336d23c74a681f1b381bc6d820c68dbcae
7
- data.tar.gz: 6c3169184cb1b3de048689ab79c9e860c6f9892c5c6ff74eca63db07010d2c6883e8a24d802d6d0d29d4b69d427243631fb66bc990c1e922fdbe9132cd4095cd
6
+ metadata.gz: f800a5c07d7ce75482b99b7ee459d8a87c9607e99086d149b83cc8cb81618a569906480df8c9b2457a81a4a4374eef0d2bcab7224998c894161f6e041e9444b3
7
+ data.tar.gz: 5ffcda4941b3b43d275d907861606b5c20f6cf76a570169c6369c2093e1a7dc4c0022180f7df6de33d1c135fdfcb73de61896f78ab186705f231fe1e73ac5a66
@@ -3,6 +3,10 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/).
5
5
 
6
+ ## [0.3.0] - 2020-11-15
7
+ - [#5](https://github.com/boltops-tools/terraspace_plugin_azurerm/pull/5) helper and secrets support
8
+ - azure_secret helper
9
+
6
10
  ## [0.2.3]
7
11
  - #4 validate env vars and use older storage client
8
12
 
@@ -23,12 +23,22 @@ module TerraspacePluginAzurerm
23
23
  Interfaces::Config.instance.config
24
24
  end
25
25
 
26
+ @@logger = nil
27
+ def logger
28
+ @@logger ||= Terraspace.logger
29
+ end
30
+
31
+ def logger=(v)
32
+ @@logger = v
33
+ end
34
+
26
35
  extend self
27
36
  end
28
37
 
29
38
  Terraspace::Plugin.register("azurerm",
30
39
  backend: "azurerm",
31
40
  config_class: TerraspacePluginAzurerm::Interfaces::Config,
41
+ helper_class: TerraspacePluginAzurerm::Interfaces::Helper,
32
42
  layer_class: TerraspacePluginAzurerm::Interfaces::Layer,
33
43
  root: File.dirname(__dir__),
34
44
  )
@@ -1,7 +1,6 @@
1
1
  class TerraspacePluginAzurerm::Interfaces::Backend
2
2
  class StorageContainer < Base
3
3
  include TerraspacePluginAzurerm::Clients::Storage
4
- extend Memoist
5
4
 
6
5
  def create
7
6
  if exist?
@@ -15,12 +15,12 @@ module TerraspacePluginAzurerm::Interfaces
15
15
  c = ActiveSupport::OrderedOptions.new
16
16
  c.auto_create = true
17
17
  c.location = nil # AzureInfo.location not assigned here so it can be lazily inferred
18
-
18
+ c.secrets = ActiveSupport::OrderedOptions.new
19
+ c.secrets.vault = nil
19
20
  c.storage_account = ActiveSupport::OrderedOptions.new
20
21
  c.storage_account.sku = ActiveSupport::OrderedOptions.new
21
22
  c.storage_account.sku.name = "Standard_LRS"
22
23
  c.storage_account.sku.tier = "Standard"
23
-
24
24
  c
25
25
  end
26
26
  end
@@ -0,0 +1,10 @@
1
+ module TerraspacePluginAzurerm::Interfaces
2
+ module Helper
3
+ include Terraspace::Plugin::Helper::Interface
4
+
5
+ def azure_secret(name, options={})
6
+ Secret.new(options).fetch(name, options)
7
+ end
8
+ cache_helper :azure_secret
9
+ end
10
+ end
@@ -0,0 +1,26 @@
1
+ require "base64"
2
+
3
+ module TerraspacePluginAzurerm::Interfaces::Helper
4
+ class Secret
5
+ extend Memoist
6
+ include TerraspacePluginAzurerm::Logging
7
+ include TerraspacePluginAzurerm::Clients::Options
8
+
9
+ def initialize(options={})
10
+ @options = options
11
+ @base64 = options[:base64]
12
+ end
13
+
14
+ # opts: version, vault
15
+ def fetch(name, opts={})
16
+ value = fetcher.fetch(name, opts)
17
+ value = Base64.strict_encode64(value).strip if @base64
18
+ value
19
+ end
20
+
21
+ def fetcher
22
+ Fetcher.new
23
+ end
24
+ memoize :fetcher
25
+ end
26
+ end
@@ -0,0 +1,112 @@
1
+ require "net/http"
2
+
3
+ class TerraspacePluginAzurerm::Interfaces::Helper::Secret
4
+ class Fetcher
5
+ class Error < StandardError; end
6
+ class VaultNotFoundError < Error; end
7
+
8
+ include TerraspacePluginAzurerm::Logging
9
+ include TerraspacePluginAzurerm::Clients::Options
10
+
11
+ def initialize
12
+ o = base_client_options
13
+ @client_id = o[:client_id]
14
+ @client_secret = o[:client_secret]
15
+ @tenant_id = o[:tenant_id]
16
+ end
17
+
18
+ def fetch(name, opts={})
19
+ opts[:vault] ||= TerraspacePluginAzurerm.config.secrets.vault
20
+ get_secret(name, opts)
21
+ end
22
+
23
+ def get_secret(name, vault: nil, version: nil)
24
+ unless token
25
+ return "ERROR: Unable to authorize and get the temporary token. Double check your ARM_ env variables."
26
+ end
27
+
28
+ version = "/#{version}" if version
29
+ vault_subdomain = vault.downcase
30
+ # Using Azure REST API since the old gem doesnt support secrets https://github.com/Azure/azure-sdk-for-ruby
31
+ # https://docs.microsoft.com/en-us/rest/api/keyvault/getsecret/getsecret
32
+ url = "https://#{vault_subdomain}.vault.azure.net/secrets/#{name}#{version}?api-version=7.1"
33
+ uri = URI(url)
34
+ req = Net::HTTP::Get.new(uri)
35
+ req["Authorization"] = token
36
+ req["Content-Type"] = "application/json"
37
+
38
+ resp = nil
39
+ begin
40
+ resp = send_request(uri, req)
41
+ rescue VaultNotFoundError
42
+ message = "WARN: Vault not found #{vault}"
43
+ logger.info message.color(:yellow)
44
+ return message
45
+ end
46
+
47
+ case resp.code.to_s
48
+ when /^2/
49
+ data = JSON.load(resp.body)
50
+ data['value']
51
+ else
52
+ message = standard_error_message(resp)
53
+ logger.info "WARN: #{message}".color(:yellow)
54
+ message
55
+ end
56
+ end
57
+
58
+ def send_request(uri, req)
59
+ http = Net::HTTP.new(uri.host, uri.port)
60
+ http.open_timeout = http.read_timeout = 30
61
+ http.use_ssl = true if uri.scheme == 'https'
62
+
63
+ begin
64
+ http.request(req) # response
65
+ rescue SocketError => e
66
+ # SocketError: Failed to open TCP connection to MISSING-VAULT.vault.azure.net:443 (getaddrinfo: Name or service not known)
67
+ if e.message.include?("vault.azure.net")
68
+ raise VaultNotFoundError.new(e)
69
+ else
70
+ raise
71
+ end
72
+ end
73
+ end
74
+
75
+ # Secret error handling: 1. network 2. json parse 3. missing secret
76
+ #
77
+ # Azure API responses with decent error message when
78
+ # 403 Forbidden - KeyVault Access Policy needs to be set up
79
+ # 404 Not Found - Secret name is incorrect
80
+ #
81
+ def standard_error_message(resp)
82
+ data = JSON.load(resp.body)
83
+ data['error']['message']
84
+ rescue JSON::ParserError
85
+ resp.body
86
+ end
87
+
88
+ @@token = nil
89
+ def token
90
+ return @@token unless @@token.nil?
91
+ url = "https://login.microsoftonline.com/#{@tenant_id}/oauth2/token"
92
+ uri = URI(url)
93
+ req = Net::HTTP::Get.new(uri)
94
+ req.set_form_data(
95
+ grant_type: "client_credentials",
96
+ client_id: @client_id,
97
+ client_secret: @client_secret,
98
+ resource: "https://vault.azure.net",
99
+ )
100
+ resp = send_request(uri, req)
101
+ data = JSON.load(resp.body)
102
+ if resp.code =~ /^2/
103
+ @@token = "Bearer #{data['access_token']}" if data
104
+ else
105
+ logger.info "WARN: #{data['error_description']}".color(:yellow)
106
+ # return false otherwise error message is used as the bearer toke and get this error:
107
+ # ArgumentError: header field value cannot include CR/LF
108
+ @@token = false
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,7 @@
1
+ module TerraspacePluginAzurerm
2
+ module Logging
3
+ def logger
4
+ Terraspace.logger
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module TerraspacePluginAzurerm
2
- VERSION = "0.2.3"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terraspace_plugin_azurerm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-10-05 00:00:00.000000000 Z
11
+ date: 2020-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: azure-storage-blob
@@ -151,8 +151,12 @@ files:
151
151
  - lib/terraspace_plugin_azurerm/interfaces/backend/storage_container.rb
152
152
  - lib/terraspace_plugin_azurerm/interfaces/config.rb
153
153
  - lib/terraspace_plugin_azurerm/interfaces/expander.rb
154
+ - lib/terraspace_plugin_azurerm/interfaces/helper.rb
155
+ - lib/terraspace_plugin_azurerm/interfaces/helper/secret.rb
156
+ - lib/terraspace_plugin_azurerm/interfaces/helper/secret/fetcher.rb
154
157
  - lib/terraspace_plugin_azurerm/interfaces/layer.rb
155
158
  - lib/terraspace_plugin_azurerm/interfaces/summary.rb
159
+ - lib/terraspace_plugin_azurerm/logging.rb
156
160
  - lib/terraspace_plugin_azurerm/version.rb
157
161
  - terraspace_plugin_azurerm.gemspec
158
162
  homepage: https://github.com/boltops-tools/terraspace_plugin_azurerm
@@ -175,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
179
  - !ruby/object:Gem::Version
176
180
  version: '0'
177
181
  requirements: []
178
- rubygems_version: 3.1.2
182
+ rubygems_version: 3.1.4
179
183
  signing_key:
180
184
  specification_version: 4
181
185
  summary: Terraspace Azurerm Cloud Plugin