terraspace_plugin_azurerm 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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