ibm-cloud-sdk-core 3.19.1__tar.gz → 3.19.2__tar.gz

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.
Files changed (69) hide show
  1. {ibm-cloud-sdk-core-3.19.1/ibm_cloud_sdk_core.egg-info → ibm-cloud-sdk-core-3.19.2}/PKG-INFO +2 -2
  2. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/README.md +1 -1
  3. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/token_managers/iam_request_based_token_manager.py +18 -1
  4. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/token_managers/vpc_instance_token_manager.py +18 -1
  5. ibm-cloud-sdk-core-3.19.2/ibm_cloud_sdk_core/version.py +1 -0
  6. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2/ibm_cloud_sdk_core.egg-info}/PKG-INFO +2 -2
  7. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/requirements-dev.txt +1 -1
  8. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/setup.py +1 -1
  9. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_container_token_manager.py +37 -12
  10. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_iam_token_manager.py +82 -0
  11. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_vpc_instance_token_manager.py +59 -4
  12. ibm-cloud-sdk-core-3.19.1/ibm_cloud_sdk_core/version.py +0 -1
  13. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/LICENSE +0 -0
  14. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/MANIFEST.in +0 -0
  15. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/__init__.py +0 -0
  16. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/api_exception.py +0 -0
  17. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/__init__.py +0 -0
  18. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/authenticator.py +0 -0
  19. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/basic_authenticator.py +0 -0
  20. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/bearer_token_authenticator.py +0 -0
  21. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/container_authenticator.py +0 -0
  22. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/cp4d_authenticator.py +0 -0
  23. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/iam_authenticator.py +0 -0
  24. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/iam_request_based_authenticator.py +0 -0
  25. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/mcsp_authenticator.py +0 -0
  26. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/no_auth_authenticator.py +0 -0
  27. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/authenticators/vpc_instance_authenticator.py +0 -0
  28. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/base_service.py +0 -0
  29. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/detailed_response.py +0 -0
  30. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/get_authenticator.py +0 -0
  31. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/token_managers/__init__.py +0 -0
  32. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/token_managers/container_token_manager.py +0 -0
  33. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/token_managers/cp4d_token_manager.py +0 -0
  34. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/token_managers/iam_token_manager.py +0 -0
  35. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/token_managers/jwt_token_manager.py +0 -0
  36. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/token_managers/mcsp_token_manager.py +0 -0
  37. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/token_managers/token_manager.py +0 -0
  38. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core/utils.py +0 -0
  39. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core.egg-info/SOURCES.txt +0 -0
  40. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core.egg-info/dependency_links.txt +0 -0
  41. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core.egg-info/requires.txt +0 -0
  42. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core.egg-info/top_level.txt +0 -0
  43. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/ibm_cloud_sdk_core.egg-info/zip-safe +0 -0
  44. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/pyproject.toml +0 -0
  45. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/requirements.txt +0 -0
  46. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/setup.cfg +0 -0
  47. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/__init__.py +0 -0
  48. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_api_exception.py +0 -0
  49. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_authenticator.py +0 -0
  50. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_base_service.py +0 -0
  51. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_basic_authenticator.py +0 -0
  52. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_bearer_authenticator.py +0 -0
  53. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_container_authenticator.py +0 -0
  54. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_cp4d_authenticator.py +0 -0
  55. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_cp4d_token_manager.py +0 -0
  56. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_detailed_response.py +0 -0
  57. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_iam_authenticator.py +0 -0
  58. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_jwt_token_manager.py +0 -0
  59. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_mcsp_authenticator.py +0 -0
  60. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_mcsp_token_manager.py +0 -0
  61. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_no_auth_authenticator.py +0 -0
  62. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_token_manager.py +0 -0
  63. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_utils.py +0 -0
  64. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test/test_vpc_instance_authenticator.py +0 -0
  65. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test_integration/__init__.py +0 -0
  66. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test_integration/test_cp4d_authenticator_integration.py +0 -0
  67. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test_integration/test_iam_authenticator_integration.py +0 -0
  68. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test_integration/test_mcsp_authenticator_integration.py +0 -0
  69. {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.19.2}/test_integration/test_ssl_verification.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ibm-cloud-sdk-core
3
- Version: 3.19.1
3
+ Version: 3.19.2
4
4
  Summary: Core library used by SDKs for IBM Cloud Services
5
5
  Home-page: https://github.com/IBM/python-sdk-core
6
6
  Author: IBM
@@ -29,7 +29,7 @@ License-File: LICENSE
29
29
  [![CLA assistant](https://cla-assistant.io/readme/badge/ibm/python-sdk-core)](https://cla-assistant.io/ibm/python-sdk-core)
30
30
  [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
31
31
 
32
- # IBM Python SDK Core Version 3.19.1
32
+ # IBM Python SDK Core Version 3.19.2
33
33
  This project contains core functionality required by Python code generated by the IBM Cloud OpenAPI SDK Generator
34
34
  (openapi-sdkgen).
35
35
 
@@ -4,7 +4,7 @@
4
4
  [![CLA assistant](https://cla-assistant.io/readme/badge/ibm/python-sdk-core)](https://cla-assistant.io/ibm/python-sdk-core)
5
5
  [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
6
6
 
7
- # IBM Python SDK Core Version 3.19.1
7
+ # IBM Python SDK Core Version 3.19.2
8
8
  This project contains core functionality required by Python code generated by the IBM Cloud OpenAPI SDK Generator
9
9
  (openapi-sdkgen).
10
10
 
@@ -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.
@@ -63,6 +63,7 @@ class IAMRequestBasedTokenManager(JWTTokenManager):
63
63
 
64
64
  DEFAULT_IAM_URL = 'https://iam.cloud.ibm.com'
65
65
  OPERATION_PATH = "/identity/token"
66
+ IAM_EXPIRATION_WINDOW = 10
66
67
 
67
68
  def __init__(
68
69
  self,
@@ -167,3 +168,19 @@ class IAMRequestBasedTokenManager(JWTTokenManager):
167
168
  value: A space seperated string that makes up the scope parameter.
168
169
  """
169
170
  self.scope = value
171
+
172
+ def _is_token_expired(self) -> bool:
173
+ """
174
+ Returns true iff the current cached token is expired.
175
+ We'll consider an access token as expired when we reach its IAM server-reported expiration time
176
+ minus our expiration window (10 secs).
177
+ We do this to avoid using an access token that might expire in the middle of a long-running transaction
178
+ within an IBM Cloud service.
179
+
180
+ Returns
181
+ -------
182
+ bool
183
+ True if token is expired; False otherwise
184
+ """
185
+ current_time = self._get_current_time()
186
+ return current_time >= (self.expire_time - self.IAM_EXPIRATION_WINDOW)
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- # Copyright 2021, 2023 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.
@@ -55,6 +55,7 @@ class VPCInstanceTokenManager(JWTTokenManager):
55
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
60
  def __init__(
60
61
  self, iam_profile_crn: Optional[str] = None, iam_profile_id: Optional[str] = None, url: Optional[str] = None
@@ -152,3 +153,19 @@ class VPCInstanceTokenManager(JWTTokenManager):
152
153
  logger.debug('Returned from VPC \'create_access_token\' operation."')
153
154
 
154
155
  return response['access_token']
156
+
157
+ def _is_token_expired(self) -> bool:
158
+ """
159
+ Returns true iff the current cached token is expired.
160
+ We'll consider an access token as expired when we reach its IAM server-reported expiration time
161
+ minus our expiration window (10 secs).
162
+ We do this to avoid using an access token that might expire in the middle of a long-running transaction
163
+ within an IBM Cloud service.
164
+
165
+ Returns
166
+ -------
167
+ bool
168
+ True if token is expired; False otherwise
169
+ """
170
+ current_time = self._get_current_time()
171
+ return current_time >= (self.expire_time - self.IAM_EXPIRATION_WINDOW)
@@ -0,0 +1 @@
1
+ __version__ = '3.19.2'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ibm-cloud-sdk-core
3
- Version: 3.19.1
3
+ Version: 3.19.2
4
4
  Summary: Core library used by SDKs for IBM Cloud Services
5
5
  Home-page: https://github.com/IBM/python-sdk-core
6
6
  Author: IBM
@@ -29,7 +29,7 @@ License-File: LICENSE
29
29
  [![CLA assistant](https://cla-assistant.io/readme/badge/ibm/python-sdk-core)](https://cla-assistant.io/ibm/python-sdk-core)
30
30
  [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
31
31
 
32
- # IBM Python SDK Core Version 3.19.1
32
+ # IBM Python SDK Core Version 3.19.2
33
33
  This project contains core functionality required by Python code generated by the IBM Cloud OpenAPI SDK Generator
34
34
  (openapi-sdkgen).
35
35
 
@@ -3,4 +3,4 @@ pylint>=3.0.0,<4.0.0
3
3
  pytest>=7.4.2,<8.0.0
4
4
  pytest-cov>=4.1.0,<5.0.0
5
5
  responses>=0.23.3,<1.0.0
6
- black>=23.9.1
6
+ black>=24.0.0,<25.0.0
@@ -19,7 +19,7 @@ import pkg_resources
19
19
  from setuptools import setup, find_packages
20
20
  from setuptools.command.test import test as TestCommand
21
21
 
22
- __version__ = '3.19.1'
22
+ __version__ = '3.19.2'
23
23
 
24
24
  if sys.argv[-1] == 'publish':
25
25
  # test server
@@ -1,3 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ # Copyright 2021, 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
+
1
17
  # pylint: disable=missing-docstring
2
18
  import json
3
19
  import os
@@ -17,6 +33,7 @@ TEST_REFRESH_TOKEN = 'Xj7Gle500MachEOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI
17
33
  MOCK_IAM_PROFILE_NAME = 'iam-user-123'
18
34
  MOCK_CLIENT_ID = 'client-id-1'
19
35
  MOCK_CLIENT_SECRET = 'client-secret-1'
36
+ EXPIRATION_WINDOW = 10
20
37
 
21
38
  cr_token_file = os.path.join(os.path.dirname(__file__), '../resources/cr-token.txt')
22
39
 
@@ -169,18 +186,22 @@ def test_get_token_success():
169
186
  assert access_token == TEST_ACCESS_TOKEN_1
170
187
  assert token_manager.access_token == TEST_ACCESS_TOKEN_1
171
188
 
172
- # Verify the token manager return the cached value.
173
- # Before we call the `get_token` again, set the expiration and time.
174
- # This is necessary because we are using a fix JWT response.
175
- token_manager.expire_time = _get_current_time() + 3600
176
- token_manager.refresh_time = _get_current_time() + 3600
189
+ # Verify that the token manager returns the cached value.
190
+ # Before we call `get_token` again, set the expiration and refresh time
191
+ # so that we do not fetch a new access token.
192
+ # This is necessary because we are using a fixed JWT response.
193
+ token_manager.expire_time = _get_current_time() + 1000
194
+ token_manager.refresh_time = _get_current_time() + 1000
177
195
  token_manager.set_scope('send-second-token')
178
196
  access_token = token_manager.get_token()
179
197
  assert access_token == TEST_ACCESS_TOKEN_1
180
198
  assert token_manager.access_token == TEST_ACCESS_TOKEN_1
181
199
 
182
200
  # Force expiration to get the second token.
183
- token_manager.expire_time = _get_current_time() - 1
201
+ # We'll set the expiration time to be current-time + EXPIRATION_WINDOW (10 secs)
202
+ # because we want the access token to be considered as "expired"
203
+ # when we reach the IAM-server reported expiration time minus 10 secs.
204
+ token_manager.expire_time = _get_current_time() + EXPIRATION_WINDOW
184
205
  access_token = token_manager.get_token()
185
206
  assert access_token == TEST_ACCESS_TOKEN_2
186
207
  assert token_manager.access_token == TEST_ACCESS_TOKEN_2
@@ -206,17 +227,21 @@ def test_authenticate_success():
206
227
  authenticator.authenticate(request)
207
228
  assert request['headers']['Authorization'] == 'Bearer ' + TEST_ACCESS_TOKEN_1
208
229
 
209
- # Verify the token manager return the cached value.
210
- # Before we call the `get_token` again, set the expiration and time.
211
- # This is necessary because we are using a fix JWT response.
212
- authenticator.token_manager.expire_time = _get_current_time() + 3600
213
- authenticator.token_manager.refresh_time = _get_current_time() + 3600
230
+ # Verify that the token manager returns the cached value.
231
+ # Before we call `get_token` again, set the expiration and refresh time
232
+ # so that we do not fetch a new access token.
233
+ # This is necessary because we are using a fixed JWT response.
234
+ authenticator.token_manager.expire_time = _get_current_time() + 1000
235
+ authenticator.token_manager.refresh_time = _get_current_time() + 1000
214
236
  authenticator.token_manager.set_scope('send-second-token')
215
237
  authenticator.authenticate(request)
216
238
  assert request['headers']['Authorization'] == 'Bearer ' + TEST_ACCESS_TOKEN_1
217
239
 
218
240
  # Force expiration to get the second token.
219
- authenticator.token_manager.expire_time = _get_current_time() - 1
241
+ # We'll set the expiration time to be current-time + EXPIRATION_WINDOW (10 secs)
242
+ # because we want the access token to be considered as "expired"
243
+ # when we reach the IAM-server reported expiration time minus 10 secs.
244
+ authenticator.token_manager.expire_time = _get_current_time() + EXPIRATION_WINDOW
220
245
  authenticator.authenticate(request)
221
246
  assert request['headers']['Authorization'] == 'Bearer ' + TEST_ACCESS_TOKEN_2
222
247
 
@@ -1,3 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ # Copyright 2021, 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
+
1
17
  # pylint: disable=missing-docstring
2
18
  import os
3
19
  import time
@@ -8,6 +24,16 @@ import responses
8
24
 
9
25
  from ibm_cloud_sdk_core import IAMTokenManager, ApiException, get_authenticator_from_environment
10
26
 
27
+ # pylint: disable=line-too-long
28
+ TEST_ACCESS_TOKEN_1 = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImhlbGxvIiwicm9sZSI6InVzZXIiLCJwZXJtaXNzaW9ucyI6WyJhZG1pbmlzdHJhdG9yIiwiZGVwbG95bWVudF9hZG1pbiJdLCJzdWIiOiJoZWxsbyIsImlzcyI6IkpvaG4iLCJhdWQiOiJEU1giLCJ1aWQiOiI5OTkiLCJpYXQiOjE1NjAyNzcwNTEsImV4cCI6MTU2MDI4MTgxOSwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4In0.cIodB4I6CCcX8vfIImz7Cytux3GpWyObt9Gkur5g1QI'
29
+ TEST_ACCESS_TOKEN_2 = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjIzMDQ5ODE1MWMyMTRiNzg4ZGQ5N2YyMmI4NTQxMGE1In0.eyJ1c2VybmFtZSI6ImR1bW15Iiwicm9sZSI6IkFkbWluIiwicGVybWlzc2lvbnMiOlsiYWRtaW5pc3RyYXRvciIsIm1hbmFnZV9jYXRhbG9nIl0sInN1YiI6ImFkbWluIiwiaXNzIjoic3NzIiwiYXVkIjoic3NzIiwidWlkIjoic3NzIiwiaWF0IjozNjAwLCJleHAiOjE2MjgwMDcwODF9.zvUDpgqWIWs7S1CuKv40ERw1IZ5FqSFqQXsrwZJyfRM'
30
+ TEST_REFRESH_TOKEN = 'Xj7Gle500MachEOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImhlbGxvIiwicm9sZSI6InVzZXIiLCJwZXJtaXNzaW9ucyI6WyJhZG1pbmlzdHJhdG9yIiwiZGVwbG95bWVudF9hZG1pbiJdLCJzdWIiOiJoZWxsbyIsImlzcyI6IkpvaG4iLCJhdWQiOiJEU1giLCJ1aWQiOiI5OTkiLCJpYXQiOjE1NjAyNzcwNTEsImV4cCI6MTU2MDI4MTgxOSwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4In0.cIodB4I6CCcX8vfIImz7Cytux3GpWyObt9Gkur5g1QI'
31
+ EXPIRATION_WINDOW = 10
32
+
33
+
34
+ def _get_current_time() -> int:
35
+ return int(time.time())
36
+
11
37
 
12
38
  def get_access_token() -> str:
13
39
  access_token_layout = {
@@ -268,6 +294,62 @@ def test_request_token_auth_in_setter_scope():
268
294
  assert 'scope=john+snow' in responses.calls[0].response.request.body
269
295
 
270
296
 
297
+ @responses.activate
298
+ def test_get_token_success():
299
+ iam_url = "https://iam.cloud.ibm.com/identity/token"
300
+
301
+ # Create two mock responses with different access tokens.
302
+ response1 = """{
303
+ "access_token": "%s",
304
+ "token_type": "Bearer",
305
+ "expires_in": 3600,
306
+ "expiration": 1600003600,
307
+ "refresh_token": "jy4gl91BQ"
308
+ }""" % (
309
+ TEST_ACCESS_TOKEN_1
310
+ )
311
+ response2 = """{
312
+ "access_token": "%s",
313
+ "token_type": "Bearer",
314
+ "expires_in": 3600,
315
+ "expiration": 1600007200,
316
+ "refresh_token": "jy4gl91BQ"
317
+ }""" % (
318
+ TEST_ACCESS_TOKEN_2
319
+ )
320
+
321
+ token_manager = IAMTokenManager("iam_apikey")
322
+
323
+ access_token = token_manager.access_token
324
+ assert access_token is None
325
+
326
+ responses.add(responses.POST, url=iam_url, body=response1, status=200)
327
+ access_token = token_manager.get_token()
328
+ assert access_token == TEST_ACCESS_TOKEN_1
329
+ assert token_manager.access_token == TEST_ACCESS_TOKEN_1
330
+
331
+ # Verify that the token manager returns the cached value.
332
+ # Before we call `get_token` again, set the expiration and refresh time
333
+ # so that we do not fetch a new access token.
334
+ # This is necessary because we are using a fixed JWT response.
335
+ token_manager.expire_time = _get_current_time() + 1000
336
+ token_manager.refresh_time = _get_current_time() + 1000
337
+ access_token = token_manager.get_token()
338
+ assert access_token == TEST_ACCESS_TOKEN_1
339
+ assert token_manager.access_token == TEST_ACCESS_TOKEN_1
340
+
341
+ # Force expiration to get the second token.
342
+ # We'll set the expiration time to be current-time + EXPIRATION_WINDOW (10 secs)
343
+ # because we want the access token to be considered as "expired"
344
+ # when we reach the IAM-server reported expiration time minus 10 secs.
345
+ responses.add(responses.POST, url=iam_url, body=response2, status=200)
346
+ token_manager.expire_time = _get_current_time() + EXPIRATION_WINDOW
347
+ token_manager.refresh_time = _get_current_time() + 1000
348
+ access_token = token_manager.get_token()
349
+ assert access_token == TEST_ACCESS_TOKEN_2
350
+ assert token_manager.access_token == TEST_ACCESS_TOKEN_2
351
+
352
+
271
353
  @responses.activate
272
354
  def test_get_refresh_token():
273
355
  iam_url = "https://iam.cloud.ibm.com/identity/token"
@@ -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.
@@ -17,6 +17,7 @@
17
17
  # pylint: disable=missing-docstring
18
18
  import json
19
19
  import logging
20
+ import time
20
21
 
21
22
  import pytest
22
23
  import responses
@@ -25,11 +26,17 @@ from ibm_cloud_sdk_core import ApiException, VPCInstanceTokenManager
25
26
 
26
27
 
27
28
  # pylint: disable=line-too-long
28
- TEST_ACCESS_TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImhlbGxvIiwicm9sZSI6InVzZXIiLCJwZXJtaXNzaW9ucyI6WyJhZG1pbmlzdHJhdG9yIiwiZGVwbG95bWVudF9hZG1pbiJdLCJzdWIiOiJoZWxsbyIsImlzcyI6IkpvaG4iLCJhdWQiOiJEU1giLCJ1aWQiOiI5OTkiLCJpYXQiOjE1NjAyNzcwNTEsImV4cCI6MTU2MDI4MTgxOSwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4In0.cIodB4I6CCcX8vfIImz7Cytux3GpWyObt9Gkur5g1QI'
29
+ TEST_ACCESS_TOKEN_1 = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImhlbGxvIiwicm9sZSI6InVzZXIiLCJwZXJtaXNzaW9ucyI6WyJhZG1pbmlzdHJhdG9yIiwiZGVwbG95bWVudF9hZG1pbiJdLCJzdWIiOiJoZWxsbyIsImlzcyI6IkpvaG4iLCJhdWQiOiJEU1giLCJ1aWQiOiI5OTkiLCJpYXQiOjE1NjAyNzcwNTEsImV4cCI6MTU2MDI4MTgxOSwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4In0.cIodB4I6CCcX8vfIImz7Cytux3GpWyObt9Gkur5g1QI'
30
+ TEST_ACCESS_TOKEN_2 = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjIzMDQ5ODE1MWMyMTRiNzg4ZGQ5N2YyMmI4NTQxMGE1In0.eyJ1c2VybmFtZSI6ImR1bW15Iiwicm9sZSI6IkFkbWluIiwicGVybWlzc2lvbnMiOlsiYWRtaW5pc3RyYXRvciIsIm1hbmFnZV9jYXRhbG9nIl0sInN1YiI6ImFkbWluIiwiaXNzIjoic3NzIiwiYXVkIjoic3NzIiwidWlkIjoic3NzIiwiaWF0IjozNjAwLCJleHAiOjE2MjgwMDcwODF9.zvUDpgqWIWs7S1CuKv40ERw1IZ5FqSFqQXsrwZJyfRM'
29
31
  TEST_TOKEN = 'abc123'
30
32
  TEST_IAM_TOKEN = 'iam-abc123'
31
33
  TEST_IAM_PROFILE_CRN = 'crn:iam-profile:123'
32
34
  TEST_IAM_PROFILE_ID = 'iam-id-123'
35
+ EXPIRATION_WINDOW = 10
36
+
37
+
38
+ def _get_current_time() -> int:
39
+ return int(time.time())
33
40
 
34
41
 
35
42
  def test_constructor():
@@ -272,7 +279,7 @@ def test_access_token():
272
279
  'access_token': TEST_TOKEN,
273
280
  }
274
281
  response_iam = {
275
- 'access_token': TEST_ACCESS_TOKEN,
282
+ 'access_token': TEST_ACCESS_TOKEN_1,
276
283
  }
277
284
 
278
285
  responses.add(
@@ -290,6 +297,54 @@ def test_access_token():
290
297
  assert token_manager.refresh_time == 0
291
298
 
292
299
  token_manager.get_token()
293
- assert token_manager.access_token == TEST_ACCESS_TOKEN
300
+ assert token_manager.access_token == TEST_ACCESS_TOKEN_1
294
301
  assert token_manager.expire_time > 0
295
302
  assert token_manager.refresh_time > 0
303
+
304
+
305
+ @responses.activate
306
+ def test_get_token_success():
307
+ token_manager = VPCInstanceTokenManager()
308
+
309
+ # Mock the retrieve instance identity token method.
310
+ def mock_retrieve_instance_identity_token():
311
+ return TEST_TOKEN
312
+
313
+ token_manager.retrieve_instance_identity_token = mock_retrieve_instance_identity_token
314
+
315
+ response1 = {
316
+ 'access_token': TEST_ACCESS_TOKEN_1,
317
+ }
318
+ response2 = {
319
+ 'access_token': TEST_ACCESS_TOKEN_2,
320
+ }
321
+
322
+ responses.add(
323
+ responses.POST, 'http://169.254.169.254/instance_identity/v1/iam_token', body=json.dumps(response1), status=200
324
+ )
325
+
326
+ access_token = token_manager.get_token()
327
+ assert access_token == TEST_ACCESS_TOKEN_1
328
+ assert token_manager.access_token == TEST_ACCESS_TOKEN_1
329
+
330
+ # Verify that the token manager returns the cached value.
331
+ # Before we call `get_token` again, set the expiration and refresh time
332
+ # so that we do not fetch a new access token.
333
+ # This is necessary because we are using a fixed JWT response.
334
+ token_manager.expire_time = _get_current_time() + 1000
335
+ token_manager.refresh_time = _get_current_time() + 1000
336
+ access_token = token_manager.get_token()
337
+ assert access_token == TEST_ACCESS_TOKEN_1
338
+ assert token_manager.access_token == TEST_ACCESS_TOKEN_1
339
+
340
+ # Force expiration to get the second token.
341
+ # We'll set the expiration time to be current-time + EXPIRATION_WINDOW (10 secs)
342
+ # because we want the access token to be considered as "expired"
343
+ # when we reach the IAM-server reported expiration time minus 10 secs.
344
+ responses.add(
345
+ responses.POST, 'http://169.254.169.254/instance_identity/v1/iam_token', body=json.dumps(response2), status=200
346
+ )
347
+ token_manager.expire_time = _get_current_time() + EXPIRATION_WINDOW
348
+ access_token = token_manager.get_token()
349
+ assert access_token == TEST_ACCESS_TOKEN_2
350
+ assert token_manager.access_token == TEST_ACCESS_TOKEN_2
@@ -1 +0,0 @@
1
- __version__ = '3.19.1'