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 +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/terraspace_plugin_azurerm.rb +10 -0
- data/lib/terraspace_plugin_azurerm/interfaces/backend/storage_container.rb +0 -1
- data/lib/terraspace_plugin_azurerm/interfaces/config.rb +2 -2
- data/lib/terraspace_plugin_azurerm/interfaces/helper.rb +10 -0
- data/lib/terraspace_plugin_azurerm/interfaces/helper/secret.rb +26 -0
- data/lib/terraspace_plugin_azurerm/interfaces/helper/secret/fetcher.rb +112 -0
- data/lib/terraspace_plugin_azurerm/logging.rb +7 -0
- data/lib/terraspace_plugin_azurerm/version.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8704700ce76610490c5f29da3091ea5b9b14489911095418deb51561920f2062
|
|
4
|
+
data.tar.gz: e60b1a62a544c6cbc21838c13c41c93541806786600c85620a650e45a0aa7ae2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f800a5c07d7ce75482b99b7ee459d8a87c9607e99086d149b83cc8cb81618a569906480df8c9b2457a81a4a4374eef0d2bcab7224998c894161f6e041e9444b3
|
|
7
|
+
data.tar.gz: 5ffcda4941b3b43d275d907861606b5c20f6cf76a570169c6369c2093e1a7dc4c0022180f7df6de33d1c135fdfcb73de61896f78ab186705f231fe1e73ac5a66
|
data/CHANGELOG.md
CHANGED
|
@@ -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
|
)
|
|
@@ -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,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
|
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.
|
|
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-
|
|
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.
|
|
182
|
+
rubygems_version: 3.1.4
|
|
179
183
|
signing_key:
|
|
180
184
|
specification_version: 4
|
|
181
185
|
summary: Terraspace Azurerm Cloud Plugin
|