ibm-cloud-sdk-core 3.16.0__py3-none-any.whl → 3.21.0__py3-none-any.whl
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.
- ibm_cloud_sdk_core/__init__.py +1 -0
- ibm_cloud_sdk_core/api_exception.py +18 -4
- ibm_cloud_sdk_core/authenticators/__init__.py +1 -0
- ibm_cloud_sdk_core/authenticators/authenticator.py +2 -1
- ibm_cloud_sdk_core/authenticators/basic_authenticator.py +12 -7
- ibm_cloud_sdk_core/authenticators/bearer_token_authenticator.py +7 -2
- ibm_cloud_sdk_core/authenticators/container_authenticator.py +25 -16
- ibm_cloud_sdk_core/authenticators/cp4d_authenticator.py +38 -23
- ibm_cloud_sdk_core/authenticators/iam_authenticator.py +22 -13
- ibm_cloud_sdk_core/authenticators/iam_request_based_authenticator.py +10 -8
- ibm_cloud_sdk_core/authenticators/mcsp_authenticator.py +134 -0
- ibm_cloud_sdk_core/authenticators/vpc_instance_authenticator.py +12 -11
- ibm_cloud_sdk_core/base_service.py +137 -103
- ibm_cloud_sdk_core/detailed_response.py +21 -15
- ibm_cloud_sdk_core/get_authenticator.py +35 -17
- ibm_cloud_sdk_core/http_adapter.py +28 -0
- ibm_cloud_sdk_core/logger.py +85 -0
- ibm_cloud_sdk_core/private_helpers.py +34 -0
- ibm_cloud_sdk_core/token_managers/container_token_manager.py +63 -33
- ibm_cloud_sdk_core/token_managers/cp4d_token_manager.py +35 -22
- ibm_cloud_sdk_core/token_managers/iam_request_based_token_manager.py +50 -21
- ibm_cloud_sdk_core/token_managers/iam_token_manager.py +24 -13
- ibm_cloud_sdk_core/token_managers/jwt_token_manager.py +3 -16
- ibm_cloud_sdk_core/token_managers/mcsp_token_manager.py +108 -0
- ibm_cloud_sdk_core/token_managers/token_manager.py +20 -23
- ibm_cloud_sdk_core/token_managers/vpc_instance_token_manager.py +37 -18
- ibm_cloud_sdk_core/utils.py +127 -48
- ibm_cloud_sdk_core/version.py +1 -1
- ibm_cloud_sdk_core-3.21.0.dist-info/METADATA +159 -0
- ibm_cloud_sdk_core-3.21.0.dist-info/RECORD +35 -0
- {ibm_cloud_sdk_core-3.16.0.dist-info → ibm_cloud_sdk_core-3.21.0.dist-info}/WHEEL +1 -1
- ibm_cloud_sdk_core-3.21.0.dist-info/top_level.txt +1 -0
- ibm_cloud_sdk_core-3.16.0.dist-info/METADATA +0 -112
- ibm_cloud_sdk_core-3.16.0.dist-info/RECORD +0 -52
- ibm_cloud_sdk_core-3.16.0.dist-info/top_level.txt +0 -3
- ibm_cloud_sdk_core-3.16.0.dist-info/zip-safe +0 -1
- test/__init__.py +0 -0
- test/test_api_exception.py +0 -73
- test/test_authenticator.py +0 -21
- test/test_base_service.py +0 -933
- test/test_basic_authenticator.py +0 -36
- test/test_bearer_authenticator.py +0 -28
- test/test_container_authenticator.py +0 -105
- test/test_container_token_manager.py +0 -283
- test/test_cp4d_authenticator.py +0 -171
- test/test_cp4d_token_manager.py +0 -56
- test/test_detailed_response.py +0 -57
- test/test_iam_authenticator.py +0 -157
- test/test_iam_token_manager.py +0 -362
- test/test_jwt_token_manager.py +0 -109
- test/test_no_auth_authenticator.py +0 -15
- test/test_token_manager.py +0 -84
- test/test_utils.py +0 -634
- test/test_vpc_instance_authenticator.py +0 -66
- test/test_vpc_instance_token_manager.py +0 -266
- test_integration/__init__.py +0 -0
- test_integration/test_cp4d_authenticator_integration.py +0 -45
- {ibm_cloud_sdk_core-3.16.0.dist-info → ibm_cloud_sdk_core-3.21.0.dist-info}/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
|
|
3
|
-
# Copyright 2019 IBM All Rights Reserved.
|
|
3
|
+
# Copyright 2019, 2024 IBM All Rights Reserved.
|
|
4
4
|
#
|
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
6
|
# you may not use this file except in compliance with the License.
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
from typing import Dict, Optional
|
|
18
18
|
|
|
19
19
|
from .iam_request_based_token_manager import IAMRequestBasedTokenManager
|
|
20
|
+
from ..private_helpers import _build_user_agent
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class IAMTokenManager(IAMRequestBasedTokenManager):
|
|
@@ -60,19 +61,27 @@ class IAMTokenManager(IAMRequestBasedTokenManager):
|
|
|
60
61
|
This can be used to obtain an access token with a specific scope.
|
|
61
62
|
"""
|
|
62
63
|
|
|
63
|
-
def __init__(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
apikey: str,
|
|
67
|
+
*,
|
|
68
|
+
url: Optional[str] = None,
|
|
69
|
+
client_id: Optional[str] = None,
|
|
70
|
+
client_secret: Optional[str] = None,
|
|
71
|
+
disable_ssl_verification: bool = False,
|
|
72
|
+
headers: Optional[Dict[str, str]] = None,
|
|
73
|
+
proxies: Optional[Dict[str, str]] = None,
|
|
74
|
+
scope: Optional[str] = None,
|
|
75
|
+
) -> None:
|
|
73
76
|
super().__init__(
|
|
74
|
-
url=url,
|
|
75
|
-
|
|
77
|
+
url=url,
|
|
78
|
+
client_id=client_id,
|
|
79
|
+
client_secret=client_secret,
|
|
80
|
+
disable_ssl_verification=disable_ssl_verification,
|
|
81
|
+
headers=headers,
|
|
82
|
+
proxies=proxies,
|
|
83
|
+
scope=scope,
|
|
84
|
+
)
|
|
76
85
|
|
|
77
86
|
self.apikey = apikey
|
|
78
87
|
|
|
@@ -80,3 +89,5 @@ class IAMTokenManager(IAMRequestBasedTokenManager):
|
|
|
80
89
|
self.request_payload['grant_type'] = 'urn:ibm:params:oauth:grant-type:apikey'
|
|
81
90
|
self.request_payload['apikey'] = self.apikey
|
|
82
91
|
self.request_payload['response_type'] = 'cloud_iam'
|
|
92
|
+
|
|
93
|
+
self._set_user_agent(_build_user_agent('iam-authenticator'))
|
|
@@ -75,15 +75,7 @@ class JWTTokenManager(TokenManager, ABC):
|
|
|
75
75
|
buffer = (exp - iat) * 0.2
|
|
76
76
|
self.refresh_time = self.expire_time - buffer
|
|
77
77
|
|
|
78
|
-
def _request(self,
|
|
79
|
-
method,
|
|
80
|
-
url,
|
|
81
|
-
*,
|
|
82
|
-
headers=None,
|
|
83
|
-
params=None,
|
|
84
|
-
data=None,
|
|
85
|
-
auth_tuple=None,
|
|
86
|
-
**kwargs) -> dict:
|
|
78
|
+
def _request(self, method, url, *, headers=None, params=None, data=None, auth_tuple=None, **kwargs) -> dict:
|
|
87
79
|
kwargs = dict({"timeout": 60}, **kwargs)
|
|
88
80
|
kwargs = dict(kwargs, **self.http_config)
|
|
89
81
|
|
|
@@ -91,13 +83,8 @@ class JWTTokenManager(TokenManager, ABC):
|
|
|
91
83
|
kwargs['verify'] = False
|
|
92
84
|
|
|
93
85
|
response = requests.request(
|
|
94
|
-
method=method,
|
|
95
|
-
|
|
96
|
-
headers=headers,
|
|
97
|
-
params=params,
|
|
98
|
-
data=data,
|
|
99
|
-
auth=auth_tuple,
|
|
100
|
-
**kwargs)
|
|
86
|
+
method=method, url=url, headers=headers, params=params, data=data, auth=auth_tuple, **kwargs
|
|
87
|
+
)
|
|
101
88
|
if 200 <= response.status_code <= 299:
|
|
102
89
|
return response.json()
|
|
103
90
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
# Copyright 2023, 2024 IBM All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
from typing import Dict, Optional
|
|
19
|
+
|
|
20
|
+
from ibm_cloud_sdk_core.logger import get_logger
|
|
21
|
+
from ..private_helpers import _build_user_agent
|
|
22
|
+
from .jwt_token_manager import JWTTokenManager
|
|
23
|
+
|
|
24
|
+
logger = get_logger()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class MCSPTokenManager(JWTTokenManager):
|
|
28
|
+
"""The MCSPTokenManager accepts a user-supplied apikey and performs the necessary interactions with
|
|
29
|
+
the Multi-Cloud Saas Platform (MCSP) token service to obtain an MCSP access token (a bearer token).
|
|
30
|
+
When the access token expires, a new access token is obtained from the token server.
|
|
31
|
+
|
|
32
|
+
Keyword Arguments:
|
|
33
|
+
apikey: The apikey for authentication [required].
|
|
34
|
+
url: The endpoint for JWT token requests [required].
|
|
35
|
+
disable_ssl_verification: Disable ssl verification. Defaults to False.
|
|
36
|
+
headers: Headers to be sent with every service token request. Defaults to None.
|
|
37
|
+
proxies: Proxies to use for making request. Defaults to None.
|
|
38
|
+
proxies.http (optional): The proxy endpoint to use for HTTP requests.
|
|
39
|
+
proxies.https (optional): The proxy endpoint to use for HTTPS requests.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
TOKEN_NAME = 'token'
|
|
43
|
+
OPERATION_PATH = '/siusermgr/api/1.0/apikeys/token'
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
apikey: str,
|
|
48
|
+
url: str,
|
|
49
|
+
*,
|
|
50
|
+
disable_ssl_verification: bool = False,
|
|
51
|
+
headers: Optional[Dict[str, str]] = None,
|
|
52
|
+
proxies: Optional[Dict[str, str]] = None,
|
|
53
|
+
) -> None:
|
|
54
|
+
self.apikey = apikey
|
|
55
|
+
self.headers = headers
|
|
56
|
+
if self.headers is None:
|
|
57
|
+
self.headers = {}
|
|
58
|
+
self.headers['Content-Type'] = 'application/json'
|
|
59
|
+
self.headers['Accept'] = 'application/json'
|
|
60
|
+
self.proxies = proxies
|
|
61
|
+
super().__init__(url, disable_ssl_verification=disable_ssl_verification, token_name=self.TOKEN_NAME)
|
|
62
|
+
self._set_user_agent(_build_user_agent('mcsp-authenticator'))
|
|
63
|
+
|
|
64
|
+
def request_token(self) -> dict:
|
|
65
|
+
"""Makes a request for a token."""
|
|
66
|
+
required_headers = {
|
|
67
|
+
'User-Agent': self.user_agent,
|
|
68
|
+
}
|
|
69
|
+
request_headers = {}
|
|
70
|
+
if self.headers is not None and isinstance(self.headers, dict):
|
|
71
|
+
request_headers.update(self.headers)
|
|
72
|
+
request_headers.update(required_headers)
|
|
73
|
+
|
|
74
|
+
request_url = self.url + self.OPERATION_PATH
|
|
75
|
+
logger.debug('Invoking MCSP token service operation: %s', request_url)
|
|
76
|
+
response = self._request(
|
|
77
|
+
method='POST',
|
|
78
|
+
headers=request_headers,
|
|
79
|
+
url=request_url,
|
|
80
|
+
data=json.dumps({"apikey": self.apikey}),
|
|
81
|
+
proxies=self.proxies,
|
|
82
|
+
)
|
|
83
|
+
logger.debug('Returned from MCSP token service operation')
|
|
84
|
+
return response
|
|
85
|
+
|
|
86
|
+
def set_headers(self, headers: Dict[str, str]) -> None:
|
|
87
|
+
"""Headers to be sent with every MCSP token request.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
headers: The headers to be sent with every MCSP token request.
|
|
91
|
+
"""
|
|
92
|
+
if isinstance(headers, dict):
|
|
93
|
+
self.headers = headers
|
|
94
|
+
else:
|
|
95
|
+
raise TypeError('headers must be a dictionary')
|
|
96
|
+
|
|
97
|
+
def set_proxies(self, proxies: Dict[str, str]) -> None:
|
|
98
|
+
"""Sets the proxies the token manager will use to communicate with MCSP on behalf of the host.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
proxies: Proxies to use for making request. Defaults to None.
|
|
102
|
+
proxies.http (optional): The proxy endpoint to use for HTTP requests.
|
|
103
|
+
proxies.https (optional): The proxy endpoint to use for HTTPS requests.
|
|
104
|
+
"""
|
|
105
|
+
if isinstance(proxies, dict):
|
|
106
|
+
self.proxies = proxies
|
|
107
|
+
else:
|
|
108
|
+
raise TypeError('proxies must be a dictionary')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
|
|
3
|
-
# Copyright 2020 IBM All Rights Reserved.
|
|
3
|
+
# Copyright 2020, 2024 IBM All Rights Reserved.
|
|
4
4
|
#
|
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
6
|
# you may not use this file except in compliance with the License.
|
|
@@ -21,8 +21,11 @@ from threading import Lock
|
|
|
21
21
|
|
|
22
22
|
import requests
|
|
23
23
|
|
|
24
|
+
from ibm_cloud_sdk_core.logger import get_logger
|
|
24
25
|
from ..api_exception import ApiException
|
|
25
26
|
|
|
27
|
+
logger = get_logger()
|
|
28
|
+
|
|
26
29
|
|
|
27
30
|
# pylint: disable=too-many-instance-attributes
|
|
28
31
|
class TokenManager(ABC):
|
|
@@ -49,14 +52,10 @@ class TokenManager(ABC):
|
|
|
49
52
|
lock (Lock): Lock variable to serialize access to refresh/request times
|
|
50
53
|
http_config (dict): A dictionary containing values that control the timeout, proxies, and etc of HTTP requests.
|
|
51
54
|
access_token (str): The latest stored access token
|
|
55
|
+
user_agent (str): The User-Agent header value to be included in each outbound token request
|
|
52
56
|
"""
|
|
53
57
|
|
|
54
|
-
def __init__(
|
|
55
|
-
self,
|
|
56
|
-
url: str,
|
|
57
|
-
*,
|
|
58
|
-
disable_ssl_verification: bool = False
|
|
59
|
-
):
|
|
58
|
+
def __init__(self, url: str, *, disable_ssl_verification: bool = False):
|
|
60
59
|
self.url = url
|
|
61
60
|
self.disable_ssl_verification = disable_ssl_verification
|
|
62
61
|
self.expire_time = 0
|
|
@@ -65,6 +64,7 @@ class TokenManager(ABC):
|
|
|
65
64
|
self.lock = Lock()
|
|
66
65
|
self.http_config = {}
|
|
67
66
|
self.access_token = None
|
|
67
|
+
self.user_agent = None
|
|
68
68
|
|
|
69
69
|
def get_token(self) -> str:
|
|
70
70
|
"""Get a token to be used for authentication.
|
|
@@ -78,11 +78,15 @@ class TokenManager(ABC):
|
|
|
78
78
|
str: A valid access token
|
|
79
79
|
"""
|
|
80
80
|
if self._is_token_expired():
|
|
81
|
+
logger.debug('Performing synchronous token fetch')
|
|
81
82
|
self.paced_request_token()
|
|
82
83
|
|
|
83
84
|
if self._token_needs_refresh():
|
|
85
|
+
logger.debug('Performing background asynchronous token fetch')
|
|
84
86
|
token_response = self.request_token()
|
|
85
87
|
self._save_token_info(token_response)
|
|
88
|
+
else:
|
|
89
|
+
logger.debug('Using cached access token')
|
|
86
90
|
|
|
87
91
|
return self.access_token
|
|
88
92
|
|
|
@@ -100,6 +104,12 @@ class TokenManager(ABC):
|
|
|
100
104
|
else:
|
|
101
105
|
raise TypeError('status must be a bool')
|
|
102
106
|
|
|
107
|
+
def _set_user_agent(self, user_agent: str = None) -> None:
|
|
108
|
+
self.user_agent = user_agent
|
|
109
|
+
|
|
110
|
+
def _get_user_agent(self) -> str:
|
|
111
|
+
return self.user_agent
|
|
112
|
+
|
|
103
113
|
def paced_request_token(self) -> None:
|
|
104
114
|
"""
|
|
105
115
|
Paces requests to request_token.
|
|
@@ -190,15 +200,7 @@ class TokenManager(ABC):
|
|
|
190
200
|
"""
|
|
191
201
|
pass
|
|
192
202
|
|
|
193
|
-
def _request(self,
|
|
194
|
-
method,
|
|
195
|
-
url,
|
|
196
|
-
*,
|
|
197
|
-
headers=None,
|
|
198
|
-
params=None,
|
|
199
|
-
data=None,
|
|
200
|
-
auth_tuple=None,
|
|
201
|
-
**kwargs):
|
|
203
|
+
def _request(self, method, url, *, headers=None, params=None, data=None, auth_tuple=None, **kwargs):
|
|
202
204
|
kwargs = dict({"timeout": 60}, **kwargs)
|
|
203
205
|
kwargs = dict(kwargs, **self.http_config)
|
|
204
206
|
|
|
@@ -206,13 +208,8 @@ class TokenManager(ABC):
|
|
|
206
208
|
kwargs['verify'] = False
|
|
207
209
|
|
|
208
210
|
response = requests.request(
|
|
209
|
-
method=method,
|
|
210
|
-
|
|
211
|
-
headers=headers,
|
|
212
|
-
params=params,
|
|
213
|
-
data=data,
|
|
214
|
-
auth=auth_tuple,
|
|
215
|
-
**kwargs)
|
|
211
|
+
method=method, url=url, headers=headers, params=params, data=data, auth=auth_tuple, **kwargs
|
|
212
|
+
)
|
|
216
213
|
if 200 <= response.status_code <= 299:
|
|
217
214
|
return response
|
|
218
215
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
|
|
3
|
-
# Copyright 2021 IBM All Rights Reserved.
|
|
3
|
+
# Copyright 2021, 2024 IBM All Rights Reserved.
|
|
4
4
|
#
|
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
6
|
# you may not use this file except in compliance with the License.
|
|
@@ -15,13 +15,13 @@
|
|
|
15
15
|
# limitations under the License.
|
|
16
16
|
|
|
17
17
|
import json
|
|
18
|
-
import logging
|
|
19
18
|
from typing import Optional
|
|
20
19
|
|
|
20
|
+
from ibm_cloud_sdk_core.logger import get_logger
|
|
21
|
+
from ..private_helpers import _build_user_agent
|
|
21
22
|
from .jwt_token_manager import JWTTokenManager
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
logger = logging.getLogger(__name__)
|
|
24
|
+
logger = get_logger()
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class VPCInstanceTokenManager(JWTTokenManager):
|
|
@@ -52,18 +52,19 @@ class VPCInstanceTokenManager(JWTTokenManager):
|
|
|
52
52
|
url (str, optional): The VPC Instance Metadata Service's base endpoint URL.
|
|
53
53
|
"""
|
|
54
54
|
|
|
55
|
-
METADATA_SERVICE_VERSION = '
|
|
55
|
+
METADATA_SERVICE_VERSION = '2022-03-01'
|
|
56
56
|
DEFAULT_IMS_ENDPOINT = 'http://169.254.169.254'
|
|
57
57
|
TOKEN_NAME = 'access_token'
|
|
58
|
+
IAM_EXPIRATION_WINDOW = 10
|
|
58
59
|
|
|
59
|
-
def __init__(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
url: Optional[str] = None) -> None:
|
|
60
|
+
def __init__(
|
|
61
|
+
self, iam_profile_crn: Optional[str] = None, iam_profile_id: Optional[str] = None, url: Optional[str] = None
|
|
62
|
+
) -> None:
|
|
63
63
|
if not url:
|
|
64
64
|
url = self.DEFAULT_IMS_ENDPOINT
|
|
65
65
|
|
|
66
66
|
super().__init__(url, token_name=self.TOKEN_NAME)
|
|
67
|
+
self._set_user_agent(_build_user_agent('vpc-instance-authenticator'))
|
|
67
68
|
|
|
68
69
|
self.iam_profile_crn = iam_profile_crn
|
|
69
70
|
self.iam_profile_id = iam_profile_id
|
|
@@ -91,18 +92,19 @@ class VPCInstanceTokenManager(JWTTokenManager):
|
|
|
91
92
|
headers = {
|
|
92
93
|
'Content-Type': 'application/json',
|
|
93
94
|
'Accept': 'application/json',
|
|
94
|
-
'Authorization': 'Bearer ' + instance_identity_token
|
|
95
|
+
'Authorization': 'Bearer ' + instance_identity_token,
|
|
96
|
+
'User-Agent': self._get_user_agent(),
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
logger.debug(
|
|
98
|
-
'Invoking VPC \'create_iam_token\' operation: %s', url)
|
|
99
|
+
logger.debug('Invoking VPC \'create_iam_token\' operation: %s', url)
|
|
99
100
|
response = self._request(
|
|
100
101
|
method='POST',
|
|
101
102
|
url=url,
|
|
102
103
|
headers=headers,
|
|
103
104
|
params={'version': self.METADATA_SERVICE_VERSION},
|
|
104
|
-
data=json.dumps(request_payload) if request_payload else None
|
|
105
|
-
|
|
105
|
+
data=json.dumps(request_payload) if request_payload else None,
|
|
106
|
+
)
|
|
107
|
+
logger.debug('Returned from VPC \'create_iam_token\' operation.')
|
|
106
108
|
|
|
107
109
|
return response
|
|
108
110
|
|
|
@@ -138,18 +140,35 @@ class VPCInstanceTokenManager(JWTTokenManager):
|
|
|
138
140
|
'Content-type': 'application/json',
|
|
139
141
|
'Accept': 'application/json',
|
|
140
142
|
'Metadata-Flavor': 'ibm',
|
|
143
|
+
'User-Agent': self._get_user_agent(),
|
|
141
144
|
}
|
|
142
145
|
|
|
143
146
|
request_body = {'expires_in': 300}
|
|
144
147
|
|
|
145
|
-
logger.debug(
|
|
146
|
-
'Invoking VPC \'create_access_token\' operation: %s', url)
|
|
148
|
+
logger.debug('Invoking VPC \'create_access_token\' operation: %s', url)
|
|
147
149
|
response = self._request(
|
|
148
150
|
method='PUT',
|
|
149
151
|
url=url,
|
|
150
152
|
headers=headers,
|
|
151
153
|
params={'version': self.METADATA_SERVICE_VERSION},
|
|
152
|
-
data=json.dumps(request_body)
|
|
153
|
-
|
|
154
|
+
data=json.dumps(request_body),
|
|
155
|
+
)
|
|
156
|
+
logger.debug('Returned from VPC \'create_access_token\' operation.')
|
|
154
157
|
|
|
155
158
|
return response['access_token']
|
|
159
|
+
|
|
160
|
+
def _is_token_expired(self) -> bool:
|
|
161
|
+
"""
|
|
162
|
+
Returns true iff the current cached token is expired.
|
|
163
|
+
We'll consider an access token as expired when we reach its IAM server-reported expiration time
|
|
164
|
+
minus our expiration window (10 secs).
|
|
165
|
+
We do this to avoid using an access token that might expire in the middle of a long-running transaction
|
|
166
|
+
within an IBM Cloud service.
|
|
167
|
+
|
|
168
|
+
Returns
|
|
169
|
+
-------
|
|
170
|
+
bool
|
|
171
|
+
True if token is expired; False otherwise
|
|
172
|
+
"""
|
|
173
|
+
current_time = self._get_current_time()
|
|
174
|
+
return current_time >= (self.expire_time - self.IAM_EXPIRATION_WINDOW)
|