nucleus 0.2.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +9 -0
- data/README.md +43 -72
- data/lib/nucleus/adapter_resolver.rb +3 -3
- data/lib/nucleus/adapters/base_adapter.rb +109 -109
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/application.rb +111 -111
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/cloud_foundry_v2.rb +141 -141
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/data.rb +97 -97
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/domains.rb +5 -5
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/lifecycle.rb +41 -41
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/logs.rb +6 -6
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/regions.rb +33 -33
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/services.rb +6 -6
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/vars.rb +80 -80
- data/lib/nucleus/adapters/v1/heroku/app_states.rb +57 -57
- data/lib/nucleus/adapters/v1/heroku/data.rb +78 -78
- data/lib/nucleus/adapters/v1/heroku/heroku.rb +146 -146
- data/lib/nucleus/adapters/v1/heroku/lifecycle.rb +51 -51
- data/lib/nucleus/adapters/v1/heroku/logs.rb +2 -2
- data/lib/nucleus/adapters/v1/heroku/regions.rb +42 -42
- data/lib/nucleus/adapters/v1/heroku/services.rb +168 -168
- data/lib/nucleus/adapters/v1/heroku/vars.rb +65 -65
- data/lib/nucleus/adapters/v1/openshift_v2/app_states.rb +68 -68
- data/lib/nucleus/adapters/v1/openshift_v2/application.rb +1 -1
- data/lib/nucleus/adapters/v1/openshift_v2/data.rb +96 -96
- data/lib/nucleus/adapters/v1/openshift_v2/lifecycle.rb +60 -60
- data/lib/nucleus/adapters/v1/openshift_v2/logs.rb +106 -106
- data/lib/nucleus/adapters/v1/openshift_v2/openshift_v2.rb +125 -125
- data/lib/nucleus/adapters/v1/openshift_v2/regions.rb +58 -58
- data/lib/nucleus/adapters/v1/openshift_v2/services.rb +173 -173
- data/lib/nucleus/adapters/v1/openshift_v2/vars.rb +49 -49
- data/lib/nucleus/adapters/v1/stub_adapter.rb +464 -464
- data/lib/nucleus/core/adapter_extensions/auth/auth_client.rb +44 -44
- data/lib/nucleus/core/adapter_extensions/auth/expiring_token_auth_client.rb +53 -53
- data/lib/nucleus/core/adapter_extensions/auth/http_basic_auth_client.rb +3 -3
- data/lib/nucleus/core/adapter_extensions/auth/o_auth2_auth_client.rb +95 -95
- data/lib/nucleus/core/adapter_extensions/auth/token_auth_client.rb +36 -36
- data/lib/nucleus/core/adapter_extensions/http_client.rb +5 -5
- data/lib/nucleus/core/common/files/archive_extractor.rb +1 -1
- data/lib/nucleus/core/common/files/archiver.rb +2 -2
- data/lib/nucleus/core/file_handling/file_manager.rb +64 -64
- data/lib/nucleus/core/file_handling/git_deployer.rb +133 -133
- data/lib/nucleus/core/import/adapter_configuration.rb +53 -53
- data/lib/nucleus/scripts/initialize_config_defaults.rb +26 -26
- data/lib/nucleus/version.rb +1 -1
- data/nucleus.gemspec +2 -2
- data/spec/integration/api/auth_spec.rb +3 -3
- data/spec/spec_helper.rb +98 -98
- data/spec/test_suites.rake +1 -1
- data/spec/unit/adapters/git_deployer_spec.rb +262 -262
- data/spec/unit/common/helpers/auth_helper_spec.rb +1 -1
- data/tasks/evaluation.rake +1 -1
- data/wiki/adapter_tests.md +0 -7
- data/wiki/implement_new_adapter.md +1 -1
- metadata +4 -20
- data/config/adapters/cloud_control.yml +0 -32
- data/lib/nucleus/adapters/v1/cloud_control/application.rb +0 -108
- data/lib/nucleus/adapters/v1/cloud_control/authentication.rb +0 -27
- data/lib/nucleus/adapters/v1/cloud_control/buildpacks.rb +0 -23
- data/lib/nucleus/adapters/v1/cloud_control/cloud_control.rb +0 -153
- data/lib/nucleus/adapters/v1/cloud_control/data.rb +0 -76
- data/lib/nucleus/adapters/v1/cloud_control/domains.rb +0 -68
- data/lib/nucleus/adapters/v1/cloud_control/lifecycle.rb +0 -27
- data/lib/nucleus/adapters/v1/cloud_control/log_poller.rb +0 -71
- data/lib/nucleus/adapters/v1/cloud_control/logs.rb +0 -103
- data/lib/nucleus/adapters/v1/cloud_control/regions.rb +0 -32
- data/lib/nucleus/adapters/v1/cloud_control/scaling.rb +0 -17
- data/lib/nucleus/adapters/v1/cloud_control/semantic_errors.rb +0 -31
- data/lib/nucleus/adapters/v1/cloud_control/services.rb +0 -162
- data/lib/nucleus/adapters/v1/cloud_control/token.rb +0 -17
- data/lib/nucleus/adapters/v1/cloud_control/vars.rb +0 -88
@@ -1,44 +1,44 @@
|
|
1
|
-
module Nucleus
|
2
|
-
module Adapters
|
3
|
-
class AuthClient
|
4
|
-
attr_reader :verify_ssl
|
5
|
-
|
6
|
-
# Create a new instance of an {AuthClient}.
|
7
|
-
# @param [Boolean] check_certificates true if SSL certificates are to be validated,
|
8
|
-
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
9
|
-
def initialize(check_certificates = true)
|
10
|
-
@verify_ssl = check_certificates
|
11
|
-
end
|
12
|
-
|
13
|
-
# Perform authentication with the given username and password at the desired endpoint.
|
14
|
-
# @param[String] username username to use for authentication
|
15
|
-
# @param[String] password password to the username, which is to be used for authentication
|
16
|
-
# @raise[Nucleus::Errors::EndpointAuthenticationError] if authentication failed
|
17
|
-
# @raise[Nucleus::Errors::UnknownAdapterCallError] if the generic AuthClient did expect the endpoint
|
18
|
-
# to behave differently, usually indicates implementation issues
|
19
|
-
# @return[Nucleus::Adapters::AuthClient] current AuthClient instance
|
20
|
-
def authenticate(username, password)
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
# Get the authentication header for the current AuthClient instance that must be used to execute requests
|
25
|
-
# against the endpoint.<br>
|
26
|
-
# If the authentication is known to be expired, a refresh will be made first.
|
27
|
-
# @raise[Nucleus::Errors::EndpointAuthenticationError] if the refresh failed
|
28
|
-
# @return[Hash<String, String>] authentication header that enables requests against the endpoint
|
29
|
-
def auth_header
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
# Refresh a rejected authentication and generate a new authentication header.<br>
|
35
|
-
# Should be called if the authentication is known to be expired, or when a request is rejected with an
|
36
|
-
# authentication header that used to be accepted.
|
37
|
-
# @raise [Nucleus::Errors::EndpointAuthenticationError] if token refresh failed or authentication never succeeded
|
38
|
-
# @return [Nucleus::Adapters::AuthClient] current AuthClient instance
|
39
|
-
def refresh
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
1
|
+
module Nucleus
|
2
|
+
module Adapters
|
3
|
+
class AuthClient
|
4
|
+
attr_reader :verify_ssl
|
5
|
+
|
6
|
+
# Create a new instance of an {AuthClient}.
|
7
|
+
# @param [Boolean] check_certificates true if SSL certificates are to be validated,
|
8
|
+
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
9
|
+
def initialize(check_certificates = true)
|
10
|
+
@verify_ssl = check_certificates
|
11
|
+
end
|
12
|
+
|
13
|
+
# Perform authentication with the given username and password at the desired endpoint.
|
14
|
+
# @param[String] username username to use for authentication
|
15
|
+
# @param[String] password password to the username, which is to be used for authentication
|
16
|
+
# @raise[Nucleus::Errors::EndpointAuthenticationError] if authentication failed
|
17
|
+
# @raise[Nucleus::Errors::UnknownAdapterCallError] if the generic AuthClient did expect the endpoint
|
18
|
+
# to behave differently, usually indicates implementation issues
|
19
|
+
# @return[Nucleus::Adapters::AuthClient] current AuthClient instance
|
20
|
+
def authenticate(username, password)
|
21
|
+
raise Errors::EndpointAuthenticationError, 'Authentication client does not support authentication'
|
22
|
+
end
|
23
|
+
|
24
|
+
# Get the authentication header for the current AuthClient instance that must be used to execute requests
|
25
|
+
# against the endpoint.<br>
|
26
|
+
# If the authentication is known to be expired, a refresh will be made first.
|
27
|
+
# @raise[Nucleus::Errors::EndpointAuthenticationError] if the refresh failed
|
28
|
+
# @return[Hash<String, String>] authentication header that enables requests against the endpoint
|
29
|
+
def auth_header
|
30
|
+
raise Errors::EndpointAuthenticationError,
|
31
|
+
'Authentication client does not support to create the authentication header'
|
32
|
+
end
|
33
|
+
|
34
|
+
# Refresh a rejected authentication and generate a new authentication header.<br>
|
35
|
+
# Should be called if the authentication is known to be expired, or when a request is rejected with an
|
36
|
+
# authentication header that used to be accepted.
|
37
|
+
# @raise [Nucleus::Errors::EndpointAuthenticationError] if token refresh failed or authentication never succeeded
|
38
|
+
# @return [Nucleus::Adapters::AuthClient] current AuthClient instance
|
39
|
+
def refresh
|
40
|
+
raise Errors::EndpointAuthenticationError, 'Authentication client does not support refresh'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,53 +1,53 @@
|
|
1
|
-
module Nucleus
|
2
|
-
module Adapters
|
3
|
-
class ExpiringTokenAuthClient < TokenAuthClient
|
4
|
-
# Create a new instance of an {ExpiringTokenAuthClient}. An expiring token knows when it starts to be invalid,
|
5
|
-
# saving requests to the endpoint that would fail anyways.
|
6
|
-
# @param [Boolean] check_certificates true if SSL certificates are to be validated,
|
7
|
-
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
8
|
-
# @yield [verify_ssl, username, password] Auth credentials token parser block,
|
9
|
-
# must provide the API token and its expiration date, usually retrieved from an HTTP call to the endpoint.
|
10
|
-
# @yieldparam [Boolean] verify_ssl true if SSL certificates are to be validated,
|
11
|
-
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
12
|
-
# @yieldparam [String] username username to be used to retrieve the API token
|
13
|
-
# @yieldparam [String] password password to be used to retrieve the API token
|
14
|
-
# @yieldreturn [Array<String>] Array with 2 contents:
|
15
|
-
# [0] = API token to be used for authenticated API requests,
|
16
|
-
# nil if authentication failed, e.g. due to bad credentials
|
17
|
-
# [1] = Expiration time until the token is valid
|
18
|
-
def initialize(check_certificates = true, &token_expiration_parser)
|
19
|
-
@token_expiration_parser = token_expiration_parser
|
20
|
-
super(check_certificates)
|
21
|
-
end
|
22
|
-
|
23
|
-
# @see AuthClient#authenticate
|
24
|
-
def authenticate(username, password)
|
25
|
-
token, expiration_time = @token_expiration_parser.call(verify_ssl, username, password)
|
26
|
-
|
27
|
-
# verification passed, credentials are valid
|
28
|
-
@api_token = token
|
29
|
-
@expires = expiration_time
|
30
|
-
self
|
31
|
-
end
|
32
|
-
|
33
|
-
# @see AuthClient#auth_header
|
34
|
-
def auth_header
|
35
|
-
|
36
|
-
|
37
|
-
{ 'Authorization' => "Bearer #{api_token}" }
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
# Checks if the token is expired.
|
43
|
-
# @return [true, false] true if the token is expired, false if it is still valid
|
44
|
-
def expired?
|
45
|
-
@expires >= Time.now
|
46
|
-
end
|
47
|
-
|
48
|
-
def to_s
|
49
|
-
api_token
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
1
|
+
module Nucleus
|
2
|
+
module Adapters
|
3
|
+
class ExpiringTokenAuthClient < TokenAuthClient
|
4
|
+
# Create a new instance of an {ExpiringTokenAuthClient}. An expiring token knows when it starts to be invalid,
|
5
|
+
# saving requests to the endpoint that would fail anyways.
|
6
|
+
# @param [Boolean] check_certificates true if SSL certificates are to be validated,
|
7
|
+
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
8
|
+
# @yield [verify_ssl, username, password] Auth credentials token parser block,
|
9
|
+
# must provide the API token and its expiration date, usually retrieved from an HTTP call to the endpoint.
|
10
|
+
# @yieldparam [Boolean] verify_ssl true if SSL certificates are to be validated,
|
11
|
+
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
12
|
+
# @yieldparam [String] username username to be used to retrieve the API token
|
13
|
+
# @yieldparam [String] password password to be used to retrieve the API token
|
14
|
+
# @yieldreturn [Array<String>] Array with 2 contents:
|
15
|
+
# [0] = API token to be used for authenticated API requests,
|
16
|
+
# nil if authentication failed, e.g. due to bad credentials
|
17
|
+
# [1] = Expiration time until the token is valid
|
18
|
+
def initialize(check_certificates = true, &token_expiration_parser)
|
19
|
+
@token_expiration_parser = token_expiration_parser
|
20
|
+
super(check_certificates)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @see AuthClient#authenticate
|
24
|
+
def authenticate(username, password)
|
25
|
+
token, expiration_time = @token_expiration_parser.call(verify_ssl, username, password)
|
26
|
+
raise Errors::EndpointAuthenticationError, 'Authentication failed, credentials seem to be invalid' unless token
|
27
|
+
# verification passed, credentials are valid
|
28
|
+
@api_token = token
|
29
|
+
@expires = expiration_time
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
# @see AuthClient#auth_header
|
34
|
+
def auth_header
|
35
|
+
raise Errors::EndpointAuthenticationError, 'Authentication client was not authenticated yet' unless @api_token
|
36
|
+
raise Errors::EndpointAuthenticationError, 'Cached authentication token expired' if expired?
|
37
|
+
{ 'Authorization' => "Bearer #{api_token}" }
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Checks if the token is expired.
|
43
|
+
# @return [true, false] true if the token is expired, false if it is still valid
|
44
|
+
def expired?
|
45
|
+
@expires >= Time.now
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
api_token
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -20,7 +20,7 @@ module Nucleus
|
|
20
20
|
def authenticate(username, password)
|
21
21
|
packed_credentials = ["#{username}:#{password}"].pack('m*').delete("\n")
|
22
22
|
valid = @verification.call(verify_ssl, 'Authorization' => "Basic #{packed_credentials}")
|
23
|
-
|
23
|
+
raise Errors::EndpointAuthenticationError, 'Authentication failed, credentials seem to be invalid' unless valid
|
24
24
|
# verification passed, credentials are valid
|
25
25
|
@packed_credentials = packed_credentials
|
26
26
|
self
|
@@ -28,8 +28,8 @@ module Nucleus
|
|
28
28
|
|
29
29
|
# @see AuthClient#auth_header
|
30
30
|
def auth_header
|
31
|
-
|
32
|
-
|
31
|
+
raise Errors::EndpointAuthenticationError,
|
32
|
+
'Authentication client was not authenticated yet' unless @packed_credentials
|
33
33
|
{ 'Authorization' => "Basic #{@packed_credentials}" }
|
34
34
|
end
|
35
35
|
end
|
@@ -1,95 +1,95 @@
|
|
1
|
-
module Nucleus
|
2
|
-
module Adapters
|
3
|
-
class OAuth2AuthClient < AuthClient
|
4
|
-
include Nucleus::Logging
|
5
|
-
|
6
|
-
# Create a new instance of an {OAuth2AuthClient}, which uses the standardized OAuth2 authentication method.
|
7
|
-
# @param [Boolean] check_certificates true if SSL certificates are to be validated,
|
8
|
-
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
9
|
-
# @param [String] auth_url URL to the OAuth2 endpoint
|
10
|
-
def initialize(auth_url, check_certificates = true)
|
11
|
-
@auth_url = auth_url
|
12
|
-
super(check_certificates)
|
13
|
-
end
|
14
|
-
|
15
|
-
def authenticate(username, password)
|
16
|
-
return self if @access_token
|
17
|
-
response = post(query: { grant_type: 'password', username: username, password: password })
|
18
|
-
body = body(response)
|
19
|
-
extract(body)
|
20
|
-
# refresh token is not included in later updates
|
21
|
-
@refresh_token = body[:refresh_token]
|
22
|
-
self
|
23
|
-
end
|
24
|
-
|
25
|
-
def auth_header
|
26
|
-
|
27
|
-
if expired?
|
28
|
-
log.debug('OAuth2 access_token is expired, trigger refresh before returning auth_header')
|
29
|
-
# token is expired, renew first
|
30
|
-
refresh
|
31
|
-
end
|
32
|
-
# then return the authorization header
|
33
|
-
header
|
34
|
-
end
|
35
|
-
|
36
|
-
def refresh
|
37
|
-
if @refresh_token.nil?
|
38
|
-
|
39
|
-
end
|
40
|
-
log.debug("Attempt to refresh the access_token with our refresh_token: '#{@refresh_token}'")
|
41
|
-
response = post(query: { grant_type: 'refresh_token', refresh_token: @refresh_token })
|
42
|
-
extract(body(response))
|
43
|
-
self
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def post(params)
|
49
|
-
middleware = Excon.defaults[:middlewares].dup
|
50
|
-
middleware << Excon::Middleware::Decompress
|
51
|
-
middleware << Excon::Middleware::RedirectFollower
|
52
|
-
# explicitly allow redirects, otherwise they would cause an error
|
53
|
-
# TODO: Basic Y2Y6 could be cloud-foundry specific
|
54
|
-
request_params = { expects: [200, 301, 302, 303, 307, 308], middlewares: middleware.uniq,
|
55
|
-
headers: { 'Authorization' => 'Basic Y2Y6',
|
56
|
-
'Content-Type' => 'application/x-www-form-urlencoded',
|
57
|
-
'Accept' => 'application/json' } }.merge(params)
|
58
|
-
# execute the post request and return the response
|
59
|
-
Excon.new(@auth_url, ssl_verify_peer: verify_ssl).post(request_params)
|
60
|
-
rescue Excon::Errors::HTTPStatusError => e
|
61
|
-
log.debug "OAuth2 authentication failed: #{e}"
|
62
|
-
case e.response.status
|
63
|
-
when 403
|
64
|
-
log.error("OAuth2 for '#{@auth_url}' failed with status 403 (access denied), indicating an adapter issue")
|
65
|
-
raise Errors::UnknownAdapterCallError, 'Access to resource denied, probably the adapter must be updated'
|
66
|
-
when 400, 401
|
67
|
-
raise Errors::EndpointAuthenticationError, body(e.response)[:error_description]
|
68
|
-
end
|
69
|
-
# re-raise all unhandled exception, indicating adapter issues
|
70
|
-
raise Errors::UnknownAdapterCallError, 'OAuth2 call failed unexpectedly, probably the adapter must be updated'
|
71
|
-
end
|
72
|
-
|
73
|
-
def header
|
74
|
-
{ 'Authorization' => "#{@token_type} #{@access_token}" }
|
75
|
-
end
|
76
|
-
|
77
|
-
def expired?
|
78
|
-
return true if @expiration.nil?
|
79
|
-
Time.now >= @expiration
|
80
|
-
end
|
81
|
-
|
82
|
-
def body(response)
|
83
|
-
Oj.load(response.body, symbol_keys: true)
|
84
|
-
end
|
85
|
-
|
86
|
-
def extract(body)
|
87
|
-
@access_token = body[:access_token]
|
88
|
-
# number of seconds until expiration, deduct processing buffer
|
89
|
-
seconds_left = body[:expires_in] - 30
|
90
|
-
@expiration = Time.now + seconds_left
|
91
|
-
@token_type = body[:token_type]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
1
|
+
module Nucleus
|
2
|
+
module Adapters
|
3
|
+
class OAuth2AuthClient < AuthClient
|
4
|
+
include Nucleus::Logging
|
5
|
+
|
6
|
+
# Create a new instance of an {OAuth2AuthClient}, which uses the standardized OAuth2 authentication method.
|
7
|
+
# @param [Boolean] check_certificates true if SSL certificates are to be validated,
|
8
|
+
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
9
|
+
# @param [String] auth_url URL to the OAuth2 endpoint
|
10
|
+
def initialize(auth_url, check_certificates = true)
|
11
|
+
@auth_url = auth_url
|
12
|
+
super(check_certificates)
|
13
|
+
end
|
14
|
+
|
15
|
+
def authenticate(username, password)
|
16
|
+
return self if @access_token
|
17
|
+
response = post(query: { grant_type: 'password', username: username, password: password })
|
18
|
+
body = body(response)
|
19
|
+
extract(body)
|
20
|
+
# refresh token is not included in later updates
|
21
|
+
@refresh_token = body[:refresh_token]
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def auth_header
|
26
|
+
raise Errors::EndpointAuthenticationError, 'Authentication client was not authenticated yet' unless @access_token
|
27
|
+
if expired?
|
28
|
+
log.debug('OAuth2 access_token is expired, trigger refresh before returning auth_header')
|
29
|
+
# token is expired, renew first
|
30
|
+
refresh
|
31
|
+
end
|
32
|
+
# then return the authorization header
|
33
|
+
header
|
34
|
+
end
|
35
|
+
|
36
|
+
def refresh
|
37
|
+
if @refresh_token.nil?
|
38
|
+
raise Errors::EndpointAuthenticationError, "Can't refresh token before initial authentication"
|
39
|
+
end
|
40
|
+
log.debug("Attempt to refresh the access_token with our refresh_token: '#{@refresh_token}'")
|
41
|
+
response = post(query: { grant_type: 'refresh_token', refresh_token: @refresh_token })
|
42
|
+
extract(body(response))
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def post(params)
|
49
|
+
middleware = Excon.defaults[:middlewares].dup
|
50
|
+
middleware << Excon::Middleware::Decompress
|
51
|
+
middleware << Excon::Middleware::RedirectFollower
|
52
|
+
# explicitly allow redirects, otherwise they would cause an error
|
53
|
+
# TODO: Basic Y2Y6 could be cloud-foundry specific
|
54
|
+
request_params = { expects: [200, 301, 302, 303, 307, 308], middlewares: middleware.uniq,
|
55
|
+
headers: { 'Authorization' => 'Basic Y2Y6',
|
56
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
57
|
+
'Accept' => 'application/json' } }.merge(params)
|
58
|
+
# execute the post request and return the response
|
59
|
+
Excon.new(@auth_url, ssl_verify_peer: verify_ssl).post(request_params)
|
60
|
+
rescue Excon::Errors::HTTPStatusError => e
|
61
|
+
log.debug "OAuth2 authentication failed: #{e}"
|
62
|
+
case e.response.status
|
63
|
+
when 403
|
64
|
+
log.error("OAuth2 for '#{@auth_url}' failed with status 403 (access denied), indicating an adapter issue")
|
65
|
+
raise Errors::UnknownAdapterCallError, 'Access to resource denied, probably the adapter must be updated'
|
66
|
+
when 400, 401
|
67
|
+
raise Errors::EndpointAuthenticationError, body(e.response)[:error_description]
|
68
|
+
end
|
69
|
+
# re-raise all unhandled exception, indicating adapter issues
|
70
|
+
raise Errors::UnknownAdapterCallError, 'OAuth2 call failed unexpectedly, probably the adapter must be updated'
|
71
|
+
end
|
72
|
+
|
73
|
+
def header
|
74
|
+
{ 'Authorization' => "#{@token_type} #{@access_token}" }
|
75
|
+
end
|
76
|
+
|
77
|
+
def expired?
|
78
|
+
return true if @expiration.nil?
|
79
|
+
Time.now >= @expiration
|
80
|
+
end
|
81
|
+
|
82
|
+
def body(response)
|
83
|
+
Oj.load(response.body, symbol_keys: true)
|
84
|
+
end
|
85
|
+
|
86
|
+
def extract(body)
|
87
|
+
@access_token = body[:access_token]
|
88
|
+
# number of seconds until expiration, deduct processing buffer
|
89
|
+
seconds_left = body[:expires_in] - 30
|
90
|
+
@expiration = Time.now + seconds_left
|
91
|
+
@token_type = body[:token_type]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -1,36 +1,36 @@
|
|
1
|
-
module Nucleus
|
2
|
-
module Adapters
|
3
|
-
class TokenAuthClient < AuthClient
|
4
|
-
attr_reader :api_token
|
5
|
-
|
6
|
-
# Create a new instance of an {TokenAuthClient}.
|
7
|
-
# @param [Boolean] check_certificates true if SSL certificates are to be validated,
|
8
|
-
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
9
|
-
# @yield [verify_ssl, username, password] Auth credentials token parser block,
|
10
|
-
# must provide the API token, usually retrieved from an HTTP call to the endpoint.
|
11
|
-
# @yieldparam [Boolean] verify_ssl true if SSL certificates are to be validated,
|
12
|
-
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
13
|
-
# @yieldparam [String] username username to be used to retrieve the API token
|
14
|
-
# @yieldparam [String] password password to be used to retrieve the API token
|
15
|
-
# @yieldreturn [String] API token to be used for authenticated API requests,
|
16
|
-
# nil if authentication failed, e.g. due to bad credentials
|
17
|
-
def initialize(check_certificates = true, &token_parser)
|
18
|
-
@token_parser = token_parser
|
19
|
-
super(check_certificates)
|
20
|
-
end
|
21
|
-
|
22
|
-
def authenticate(username, password)
|
23
|
-
token = @token_parser.call(verify_ssl, username, password)
|
24
|
-
|
25
|
-
# verification passed, credentials are valid
|
26
|
-
@api_token = token
|
27
|
-
self
|
28
|
-
end
|
29
|
-
|
30
|
-
def auth_header
|
31
|
-
|
32
|
-
{ 'Authorization' => "Bearer #{api_token}" }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
1
|
+
module Nucleus
|
2
|
+
module Adapters
|
3
|
+
class TokenAuthClient < AuthClient
|
4
|
+
attr_reader :api_token
|
5
|
+
|
6
|
+
# Create a new instance of an {TokenAuthClient}.
|
7
|
+
# @param [Boolean] check_certificates true if SSL certificates are to be validated,
|
8
|
+
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
9
|
+
# @yield [verify_ssl, username, password] Auth credentials token parser block,
|
10
|
+
# must provide the API token, usually retrieved from an HTTP call to the endpoint.
|
11
|
+
# @yieldparam [Boolean] verify_ssl true if SSL certificates are to be validated,
|
12
|
+
# false if they are to be ignored (e.g. when using self-signed certificates in development environments)
|
13
|
+
# @yieldparam [String] username username to be used to retrieve the API token
|
14
|
+
# @yieldparam [String] password password to be used to retrieve the API token
|
15
|
+
# @yieldreturn [String] API token to be used for authenticated API requests,
|
16
|
+
# nil if authentication failed, e.g. due to bad credentials
|
17
|
+
def initialize(check_certificates = true, &token_parser)
|
18
|
+
@token_parser = token_parser
|
19
|
+
super(check_certificates)
|
20
|
+
end
|
21
|
+
|
22
|
+
def authenticate(username, password)
|
23
|
+
token = @token_parser.call(verify_ssl, username, password)
|
24
|
+
raise Errors::EndpointAuthenticationError, 'Authentication failed, credentials seem to be invalid' unless token
|
25
|
+
# verification passed, credentials are valid
|
26
|
+
@api_token = token
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def auth_header
|
31
|
+
raise Errors::EndpointAuthenticationError, 'Authentication client was not authenticated yet' unless @api_token
|
32
|
+
{ 'Authorization' => "Bearer #{api_token}" }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|