azure-auth-token_provider 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 209fc55965a2e082f00341d66b9cd93def3a1d4f79fdfd14ae3d521880c60958
4
+ data.tar.gz: e2bbc64cba044ae1a991121e5679a30b083960998e34d4c3f3a438e4470ad9ce
5
+ SHA512:
6
+ metadata.gz: a7838e3c93175bff2a9f8c455ea80457e550470eb45f297858112c1ced9b31de52923de005906e9b4c264105bda65176faff64fa625b8bcfcb9514c0f31aa690
7
+ data.tar.gz: 855dff85980094cbb08d894ca8943ace9d548d5c4164475f7653ae308c9306a28dbb12da2763b96977766f65629ac670e9e760ab304e91efac7779c7822697be
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Andrew Maraev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,4 @@
1
+ # Gem azure-auth-token_provider
2
+
3
+ It's a simple gem to obtain Azure MSI OAuth2.0 access token.
4
+ It works in both Azure Cloud environment and local development environment.
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------------
4
+ # MIT License
5
+ #
6
+ # Copyright (c) 2019 Andrew Maraev
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be included in all
16
+ # copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+ #-------------------------------------------------------------------------------
26
+
27
+ require 'azure/auth/token_provider/azure_cli_token_source'
28
+ require 'azure/auth/token_provider/msi_token_source'
29
+
30
+ # A provider that reads access to Azure MSI token.
31
+ module Azure
32
+ module Auth
33
+ # Token provider gives an access to OAuth2.0 token
34
+ class TokenProvider
35
+ DEFAULT_RESOURCE = 'https://management.azure.com'
36
+
37
+ # Returns an access token
38
+ # @param resource [String] Azure resource URI
39
+ # @return [AzureMSITokenProvider::Token]
40
+ def token(resource = DEFAULT_RESOURCE)
41
+ @token = read_token_from_source(resource) if
42
+ @token.nil? ||
43
+ @token.is_expired? ||
44
+ @token.resource != resource
45
+ end
46
+
47
+ private
48
+
49
+ # Reads an access token from one of the known token sources
50
+ # @return [AzureMSITokenProvider::Token]
51
+ def read_token_from_source(resource)
52
+ return @selected_source.token unless @selected_source.nil?
53
+
54
+ token_sources.each do |ts|
55
+ begin
56
+ t = ts.token(resource)
57
+ @selected_source = ts
58
+ return t
59
+ rescue StandardError
60
+ next
61
+ end
62
+ end
63
+ end
64
+
65
+ # Returns an array of token sources
66
+ # @return [Array<#token>]
67
+ def token_sources
68
+ [AzureCliTokenSource.new, MsiTokenSource.new]
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------------
4
+ # MIT License
5
+ #
6
+ # Copyright (c) 2019 Andrew Maraev
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be included in all
16
+ # copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+ #-------------------------------------------------------------------------------
26
+
27
+ require 'json'
28
+ require 'open3'
29
+ require 'time'
30
+
31
+ require 'azure/auth/token_provider/token'
32
+
33
+ module Azure
34
+ module Auth
35
+ class TokenProvider
36
+ # A token source that gets token using cli tool az
37
+ class AzureCliTokenSource
38
+ DEFAULT_AZ_PATH = '/usr/bin:/usr/local/bin'
39
+ BASH = '/bin/bash'
40
+ AZ_GET_TOKEN = 'az account get-access-token -o json'
41
+
42
+ # Returns an access token from cli tool az
43
+ # @param resource [Stirng] Azure resource URI string.
44
+ # @return [AzureMSITokenProvider::Token]
45
+ def token(resource)
46
+ if Gem.win_platform?
47
+ token_windows(resource)
48
+ else
49
+ token_nix(resource)
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # Calls az on windows OS
56
+ # @return [AzureMSITokenProvider::Token]
57
+ def token_windows(_resource)
58
+ # TODO
59
+ nil
60
+ end
61
+
62
+ # Calls az on *nix OS
63
+ # @return [AzureMSITokenProvider::Token]
64
+ def token_nix(resource)
65
+ Open3.popen2(
66
+ { 'PATH' => DEFAULT_AZ_PATH },
67
+ "#{BASH} #{AZ_GET_TOKEN} --resource #{resource}"
68
+ ) do |_, o, t|
69
+ return nil unless t.value == 0
70
+
71
+ return parse_json_token(o.read)
72
+ end
73
+ end
74
+
75
+ def parse_json_token(token_src)
76
+ token_hash = JSON.parse(token_src)
77
+ Token.new(
78
+ token_hash['accessToken'],
79
+ Time.parse(token_hash['expiresOn']),
80
+ token_hash['tokenType'],
81
+ read_ext(token_hash)
82
+ )
83
+ end
84
+
85
+ def read_ext(token_hash)
86
+ {
87
+ subscription: token_hash['subscription'],
88
+ tenant: token_hash['tenant']
89
+ }
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------------
4
+ # MIT License
5
+ #
6
+ # Copyright (c) 2019 Andrew Maraev
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be included in all
16
+ # copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+ #-------------------------------------------------------------------------------
26
+
27
+ require 'net/http'
28
+ require 'uri'
29
+
30
+ require 'azure/auth/token_provider/token'
31
+
32
+ module Azure
33
+ module Auth
34
+ class TokenProvider
35
+ # Provdes OAuth 2.0 access token by calling Azure MV IDMS
36
+ class MsiTokenSource
37
+ AZURE_VM_IDMS_ENDPOINT =
38
+ 'http://169.254.169.254/metadata/identity/oauth2/token'
39
+ API_VERSION = 'api-version=2018-02-01'
40
+
41
+ def token(resource = DEFAULT_RESOURCE)
42
+ query_params = "#{API_VERSION}&resource=#{resource}"
43
+ uri_src = "#{AZURE_VM_IDMS_ENDPOINT}?#{query_params}"
44
+ uri = URI.parse(uri_src)
45
+ http = Net::HTTP.new(uri.host, uri.port)
46
+ request = Net::HTTP::Get.new(uri.request_uri)
47
+ request['Metadata'] = 'true'
48
+ response = http.request(request)
49
+ return nil if response.code != '200'
50
+
51
+ parse_json_token(response.body)
52
+ end
53
+
54
+ private
55
+
56
+ def parse_json_token(token_src)
57
+ token_hash = JSON.parse(token_src)
58
+ Token.new(
59
+ token_hash['access_token'],
60
+ Time.at(token_hash['expires_on'].to_i),
61
+ token_hash['token_type'],
62
+ read_ext(token_hash)
63
+ )
64
+ end
65
+
66
+ def read_ext(token_hash)
67
+ {
68
+ client_id: token_hash['client_id'],
69
+ expires_in: token_hash['expires_in'].to_i,
70
+ ext_expires_in: token_hash['ext_expires_in'].to_i,
71
+ not_before: Time.at(token_hash['not_before'].to_i),
72
+ resource: token_hash['resource']
73
+ }
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------------
4
+ # MIT License
5
+ #
6
+ # Copyright (c) 2019 Andrew Maraev
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be included in all
16
+ # copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+ #-------------------------------------------------------------------------------
26
+
27
+ require 'date'
28
+
29
+ module Azure
30
+ module Auth
31
+ class TokenProvider
32
+ # Azure OAuth2 access token
33
+ class Token
34
+ # Initializes new instance of Token
35
+ # @param access_token [String] JWT access token
36
+ # @param expires_on [Time] Date and time when token expires
37
+ # @param token_type [String] Token type
38
+ # @param ext [Hash] extra data
39
+ def initialize(access_token, expires_on, token_type, ext)
40
+ @access_token = access_token
41
+ @expires_on = expires_on
42
+ @token_type = token_type
43
+
44
+ @subscription = ext.fetch(:subscription, nil)
45
+ @tenant = ext.fetch(:tenant, nil)
46
+ @client_id = ext.fetch(:client_id, nil)
47
+ @expires_in = ext.fetch(:expires_in, nil)
48
+ @ext_expires_in = ext.fetch(:ext_expires_in, nil)
49
+ @not_before = ext.fetch(:not_before, nil)
50
+ @resource = ext.fetch(:resource, nil)
51
+ end
52
+
53
+ # JWT access token
54
+ # @return [String]
55
+ attr_reader :access_token
56
+
57
+ # Date and time when token expires
58
+ # @return [Time]
59
+ attr_reader :expires_on
60
+
61
+ # Azure subscription id
62
+ # @return [String]
63
+ attr_reader :subscription
64
+
65
+ # Azure app tenant id
66
+ # @return [String]
67
+ attr_reader :tenant
68
+
69
+ # Token type
70
+ # @return [String]
71
+ attr_reader :token_type
72
+
73
+ # Client Id
74
+ # @return [String]
75
+ attr_reader :client_id
76
+
77
+ # TTL in seconds
78
+ # @return [Number]
79
+ attr_reader :expires_in
80
+
81
+ # Ext expires in
82
+ # @return [Time]
83
+ attr_reader :ext_expires_in
84
+
85
+ # Date and time before which token is not valid
86
+ # @return [Time]
87
+ attr_reader :not_before
88
+
89
+ # URI of resource token is valid for
90
+ # @return [String]
91
+ attr_reader :resource
92
+
93
+ # Is token expired?
94
+ # @return [Boolean]
95
+ def expired?
96
+ Time.now > @expires_on
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ #-------------------------------------------------------------------------------
3
+ # MIT License
4
+ #
5
+ # Copyright (c) 2019 Andrew Maraev
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+ #-------------------------------------------------------------------------------
25
+
26
+ module Azure
27
+ module Auth
28
+ class TokenProvider
29
+ VERSION = '0.1.0'
30
+ end
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: azure-auth-token_provider
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrey Maraev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-07-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |2
14
+ A simple to use gem to obtain Azure MSI access token.
15
+ Supports both Azure Cloud environment and local development.
16
+ email:
17
+ - the_vk@thevk.net
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - LICENSE
23
+ - README.md
24
+ - lib/azure/auth/token_provider.rb
25
+ - lib/azure/auth/token_provider/azure_cli_token_source.rb
26
+ - lib/azure/auth/token_provider/msi_token_source.rb
27
+ - lib/azure/auth/token_provider/token.rb
28
+ - lib/azure/auth/token_provider/version.rb
29
+ homepage: https://github.com/the-vk/gem-azure-auth-token_provider
30
+ licenses:
31
+ - MIT
32
+ metadata: {}
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 2.7.6.2
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: A simple to use gem to obtain Azure MSI access token.
53
+ test_files: []