ibm-cloud-sdk-core 3.19.1__tar.gz → 3.20.0__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.
- {ibm-cloud-sdk-core-3.19.1/ibm_cloud_sdk_core.egg-info → ibm-cloud-sdk-core-3.20.0}/PKG-INFO +2 -2
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/README.md +1 -1
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/api_exception.py +1 -1
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/base_service.py +3 -14
- ibm-cloud-sdk-core-3.20.0/ibm_cloud_sdk_core/private_helpers.py +34 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/token_managers/container_token_manager.py +3 -1
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/token_managers/cp4d_token_manager.py +12 -2
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/token_managers/iam_request_based_token_manager.py +27 -4
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/token_managers/iam_token_manager.py +4 -1
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/token_managers/mcsp_token_manager.py +12 -2
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/token_managers/token_manager.py +9 -1
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/token_managers/vpc_instance_token_manager.py +22 -1
- ibm-cloud-sdk-core-3.20.0/ibm_cloud_sdk_core/version.py +1 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0/ibm_cloud_sdk_core.egg-info}/PKG-INFO +2 -2
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core.egg-info/SOURCES.txt +1 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/requirements-dev.txt +1 -1
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/setup.py +1 -1
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_base_service.py +18 -2
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_container_token_manager.py +40 -12
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_cp4d_token_manager.py +17 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_iam_token_manager.py +83 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_mcsp_token_manager.py +17 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_vpc_instance_token_manager.py +61 -4
- ibm-cloud-sdk-core-3.19.1/ibm_cloud_sdk_core/version.py +0 -1
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/LICENSE +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/MANIFEST.in +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/__init__.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/__init__.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/basic_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/bearer_token_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/container_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/cp4d_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/iam_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/iam_request_based_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/mcsp_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/no_auth_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/authenticators/vpc_instance_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/detailed_response.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/get_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/token_managers/__init__.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/token_managers/jwt_token_manager.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/utils.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core.egg-info/dependency_links.txt +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core.egg-info/requires.txt +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core.egg-info/top_level.txt +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core.egg-info/zip-safe +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/pyproject.toml +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/requirements.txt +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/setup.cfg +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/__init__.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_api_exception.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_basic_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_bearer_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_container_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_cp4d_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_detailed_response.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_iam_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_jwt_token_manager.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_mcsp_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_no_auth_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_token_manager.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_utils.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_vpc_instance_authenticator.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test_integration/__init__.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test_integration/test_cp4d_authenticator_integration.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test_integration/test_iam_authenticator_integration.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test_integration/test_mcsp_authenticator_integration.py +0 -0
- {ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test_integration/test_ssl_verification.py +0 -0
{ibm-cloud-sdk-core-3.19.1/ibm_cloud_sdk_core.egg-info → ibm-cloud-sdk-core-3.20.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ibm-cloud-sdk-core
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.20.0
|
|
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
|
[](https://cla-assistant.io/ibm/python-sdk-core)
|
|
30
30
|
[](https://github.com/semantic-release/semantic-release)
|
|
31
31
|
|
|
32
|
-
# IBM Python SDK Core Version 3.
|
|
32
|
+
# IBM Python SDK Core Version 3.20.0
|
|
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
|
[](https://cla-assistant.io/ibm/python-sdk-core)
|
|
5
5
|
[](https://github.com/semantic-release/semantic-release)
|
|
6
6
|
|
|
7
|
-
# IBM Python SDK Core Version 3.
|
|
7
|
+
# IBM Python SDK Core Version 3.20.0
|
|
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
|
|
|
@@ -54,7 +54,7 @@ class ApiException(Exception):
|
|
|
54
54
|
"""The old `code` property with a deprecation warning."""
|
|
55
55
|
|
|
56
56
|
warnings.warn(
|
|
57
|
-
'Using the `code` attribute on the `ApiException` is deprecated and'
|
|
57
|
+
'Using the `code` attribute on the `ApiException` is deprecated and '
|
|
58
58
|
'will be removed in the future. Use `status_code` instead.',
|
|
59
59
|
DeprecationWarning,
|
|
60
60
|
)
|
|
@@ -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.
|
|
@@ -18,7 +18,6 @@ import gzip
|
|
|
18
18
|
import io
|
|
19
19
|
import json as json_import
|
|
20
20
|
import logging
|
|
21
|
-
import platform
|
|
22
21
|
from http.cookiejar import CookieJar
|
|
23
22
|
from os.path import basename
|
|
24
23
|
from typing import Dict, List, Optional, Tuple, Union
|
|
@@ -42,7 +41,7 @@ from .utils import (
|
|
|
42
41
|
SSLHTTPAdapter,
|
|
43
42
|
GzipStream,
|
|
44
43
|
)
|
|
45
|
-
from .
|
|
44
|
+
from .private_helpers import _build_user_agent
|
|
46
45
|
|
|
47
46
|
# Uncomment this to enable http debugging
|
|
48
47
|
# import http.client as http_client
|
|
@@ -82,7 +81,6 @@ class BaseService:
|
|
|
82
81
|
ValueError: If Authenticator is not provided or invalid type.
|
|
83
82
|
"""
|
|
84
83
|
|
|
85
|
-
SDK_NAME = 'ibm-python-sdk-core'
|
|
86
84
|
ERROR_MSG_DISABLE_SSL = (
|
|
87
85
|
'The connection failed because the SSL certificate is not valid. To use a self-signed '
|
|
88
86
|
'certificate, disable verification of the server\'s SSL certificate by invoking the '
|
|
@@ -106,7 +104,7 @@ class BaseService:
|
|
|
106
104
|
self.disable_ssl_verification = disable_ssl_verification
|
|
107
105
|
self.default_headers = None
|
|
108
106
|
self.enable_gzip_compression = enable_gzip_compression
|
|
109
|
-
self._set_user_agent_header(
|
|
107
|
+
self._set_user_agent_header(_build_user_agent())
|
|
110
108
|
self.retry_config = None
|
|
111
109
|
self.http_adapter = SSLHTTPAdapter(_disable_ssl_verification=self.disable_ssl_verification)
|
|
112
110
|
if not self.authenticator:
|
|
@@ -151,15 +149,6 @@ class BaseService:
|
|
|
151
149
|
self.http_client.mount('http://', self.http_adapter)
|
|
152
150
|
self.http_client.mount('https://', self.http_adapter)
|
|
153
151
|
|
|
154
|
-
@staticmethod
|
|
155
|
-
def _get_system_info() -> str:
|
|
156
|
-
return '{0} {1} {2}'.format(
|
|
157
|
-
platform.system(), platform.release(), platform.python_version() # OS # OS version # Python version
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
def _build_user_agent(self) -> str:
|
|
161
|
-
return '{0}-{1} {2}'.format(self.SDK_NAME, __version__, self._get_system_info())
|
|
162
|
-
|
|
163
152
|
def configure_service(self, service_name: str) -> None:
|
|
164
153
|
"""Look for external configuration of a service. Set service properties.
|
|
165
154
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
# Copyright 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
|
+
# from ibm_cloud_sdk_core.authenticators import Authenticator
|
|
17
|
+
|
|
18
|
+
import platform
|
|
19
|
+
from .version import __version__
|
|
20
|
+
|
|
21
|
+
SDK_NAME = 'ibm-python-sdk-core'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _get_system_info() -> str:
|
|
25
|
+
return 'os.name={0} os.version={1} python.version={2}'.format(
|
|
26
|
+
platform.system(), platform.release(), platform.python_version()
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _build_user_agent(component: str = None) -> str:
|
|
31
|
+
sub_component = ""
|
|
32
|
+
if component is not None:
|
|
33
|
+
sub_component = '/{0}'.format(component)
|
|
34
|
+
return '{0}{1}-{2} {3}'.format(SDK_NAME, sub_component, __version__, _get_system_info())
|
|
@@ -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.
|
|
@@ -18,6 +18,7 @@ import logging
|
|
|
18
18
|
from typing import Dict, Optional
|
|
19
19
|
|
|
20
20
|
from .iam_request_based_token_manager import IAMRequestBasedTokenManager
|
|
21
|
+
from ..private_helpers import _build_user_agent
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
logger = logging.getLogger(__name__)
|
|
@@ -111,6 +112,7 @@ class ContainerTokenManager(IAMRequestBasedTokenManager):
|
|
|
111
112
|
self.iam_profile_id = iam_profile_id
|
|
112
113
|
|
|
113
114
|
self.request_payload['grant_type'] = 'urn:ibm:params:oauth:grant-type:cr-token'
|
|
115
|
+
self._set_user_agent(_build_user_agent('container-authenticator'))
|
|
114
116
|
|
|
115
117
|
def retrieve_cr_token(self) -> str:
|
|
116
118
|
"""Retrieves the CR token for the current compute resource by reading it from the local file system.
|
|
@@ -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
|
import json
|
|
18
18
|
from typing import Dict, Optional
|
|
19
19
|
|
|
20
|
+
from ..private_helpers import _build_user_agent
|
|
20
21
|
from .jwt_token_manager import JWTTokenManager
|
|
21
22
|
|
|
22
23
|
|
|
@@ -76,12 +77,21 @@ class CP4DTokenManager(JWTTokenManager):
|
|
|
76
77
|
self.headers['Content-Type'] = 'application/json'
|
|
77
78
|
self.proxies = proxies
|
|
78
79
|
super().__init__(url, disable_ssl_verification=disable_ssl_verification, token_name=self.TOKEN_NAME)
|
|
80
|
+
self._set_user_agent(_build_user_agent('cp4d-authenticator'))
|
|
79
81
|
|
|
80
82
|
def request_token(self) -> dict:
|
|
81
83
|
"""Makes a request for a token."""
|
|
84
|
+
required_headers = {
|
|
85
|
+
'User-Agent': self.user_agent,
|
|
86
|
+
}
|
|
87
|
+
request_headers = {}
|
|
88
|
+
if self.headers is not None and isinstance(self.headers, dict):
|
|
89
|
+
request_headers.update(self.headers)
|
|
90
|
+
request_headers.update(required_headers)
|
|
91
|
+
|
|
82
92
|
response = self._request(
|
|
83
93
|
method='POST',
|
|
84
|
-
headers=
|
|
94
|
+
headers=request_headers,
|
|
85
95
|
url=self.url,
|
|
86
96
|
data=json.dumps({"username": self.username, "password": self.password, "api_key": self.apikey}),
|
|
87
97
|
proxies=self.proxies,
|
|
@@ -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,
|
|
@@ -97,9 +98,15 @@ class IAMRequestBasedTokenManager(JWTTokenManager):
|
|
|
97
98
|
Returns:
|
|
98
99
|
A dictionary containing the bearer token to be subsequently used service requests.
|
|
99
100
|
"""
|
|
100
|
-
|
|
101
|
+
required_headers = {
|
|
102
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
103
|
+
'Accept': 'application/json',
|
|
104
|
+
'User-Agent': self._get_user_agent(),
|
|
105
|
+
}
|
|
106
|
+
request_headers = {}
|
|
101
107
|
if self.headers is not None and isinstance(self.headers, dict):
|
|
102
|
-
|
|
108
|
+
request_headers.update(self.headers)
|
|
109
|
+
request_headers.update(required_headers)
|
|
103
110
|
|
|
104
111
|
data = dict(self.request_payload)
|
|
105
112
|
|
|
@@ -114,7 +121,7 @@ class IAMRequestBasedTokenManager(JWTTokenManager):
|
|
|
114
121
|
response = self._request(
|
|
115
122
|
method='POST',
|
|
116
123
|
url=(self.url + self.OPERATION_PATH) if self.url else self.url,
|
|
117
|
-
headers=
|
|
124
|
+
headers=request_headers,
|
|
118
125
|
data=data,
|
|
119
126
|
auth_tuple=auth_tuple,
|
|
120
127
|
proxies=self.proxies,
|
|
@@ -167,3 +174,19 @@ class IAMRequestBasedTokenManager(JWTTokenManager):
|
|
|
167
174
|
value: A space seperated string that makes up the scope parameter.
|
|
168
175
|
"""
|
|
169
176
|
self.scope = value
|
|
177
|
+
|
|
178
|
+
def _is_token_expired(self) -> bool:
|
|
179
|
+
"""
|
|
180
|
+
Returns true iff the current cached token is expired.
|
|
181
|
+
We'll consider an access token as expired when we reach its IAM server-reported expiration time
|
|
182
|
+
minus our expiration window (10 secs).
|
|
183
|
+
We do this to avoid using an access token that might expire in the middle of a long-running transaction
|
|
184
|
+
within an IBM Cloud service.
|
|
185
|
+
|
|
186
|
+
Returns
|
|
187
|
+
-------
|
|
188
|
+
bool
|
|
189
|
+
True if token is expired; False otherwise
|
|
190
|
+
"""
|
|
191
|
+
current_time = self._get_current_time()
|
|
192
|
+
return current_time >= (self.expire_time - self.IAM_EXPIRATION_WINDOW)
|
|
@@ -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):
|
|
@@ -88,3 +89,5 @@ class IAMTokenManager(IAMRequestBasedTokenManager):
|
|
|
88
89
|
self.request_payload['grant_type'] = 'urn:ibm:params:oauth:grant-type:apikey'
|
|
89
90
|
self.request_payload['apikey'] = self.apikey
|
|
90
91
|
self.request_payload['response_type'] = 'cloud_iam'
|
|
92
|
+
|
|
93
|
+
self._set_user_agent(_build_user_agent('iam-authenticator'))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
|
|
3
|
-
# Copyright 2023 IBM All Rights Reserved.
|
|
3
|
+
# Copyright 2023, 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
|
import json
|
|
18
18
|
from typing import Dict, Optional
|
|
19
19
|
|
|
20
|
+
from ..private_helpers import _build_user_agent
|
|
20
21
|
from .jwt_token_manager import JWTTokenManager
|
|
21
22
|
|
|
22
23
|
|
|
@@ -55,12 +56,21 @@ class MCSPTokenManager(JWTTokenManager):
|
|
|
55
56
|
self.headers['Accept'] = 'application/json'
|
|
56
57
|
self.proxies = proxies
|
|
57
58
|
super().__init__(url, disable_ssl_verification=disable_ssl_verification, token_name=self.TOKEN_NAME)
|
|
59
|
+
self._set_user_agent(_build_user_agent('mcsp-authenticator'))
|
|
58
60
|
|
|
59
61
|
def request_token(self) -> dict:
|
|
60
62
|
"""Makes a request for a token."""
|
|
63
|
+
required_headers = {
|
|
64
|
+
'User-Agent': self.user_agent,
|
|
65
|
+
}
|
|
66
|
+
request_headers = {}
|
|
67
|
+
if self.headers is not None and isinstance(self.headers, dict):
|
|
68
|
+
request_headers.update(self.headers)
|
|
69
|
+
request_headers.update(required_headers)
|
|
70
|
+
|
|
61
71
|
response = self._request(
|
|
62
72
|
method='POST',
|
|
63
|
-
headers=
|
|
73
|
+
headers=request_headers,
|
|
64
74
|
url=self.url + self.OPERATION_PATH,
|
|
65
75
|
data=json.dumps({"apikey": self.apikey}),
|
|
66
76
|
proxies=self.proxies,
|
|
@@ -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.
|
|
@@ -49,6 +49,7 @@ class TokenManager(ABC):
|
|
|
49
49
|
lock (Lock): Lock variable to serialize access to refresh/request times
|
|
50
50
|
http_config (dict): A dictionary containing values that control the timeout, proxies, and etc of HTTP requests.
|
|
51
51
|
access_token (str): The latest stored access token
|
|
52
|
+
user_agent (str): The User-Agent header value to be included in each outbound token request
|
|
52
53
|
"""
|
|
53
54
|
|
|
54
55
|
def __init__(self, url: str, *, disable_ssl_verification: bool = False):
|
|
@@ -60,6 +61,7 @@ class TokenManager(ABC):
|
|
|
60
61
|
self.lock = Lock()
|
|
61
62
|
self.http_config = {}
|
|
62
63
|
self.access_token = None
|
|
64
|
+
self.user_agent = None
|
|
63
65
|
|
|
64
66
|
def get_token(self) -> str:
|
|
65
67
|
"""Get a token to be used for authentication.
|
|
@@ -95,6 +97,12 @@ class TokenManager(ABC):
|
|
|
95
97
|
else:
|
|
96
98
|
raise TypeError('status must be a bool')
|
|
97
99
|
|
|
100
|
+
def _set_user_agent(self, user_agent: str = None) -> None:
|
|
101
|
+
self.user_agent = user_agent
|
|
102
|
+
|
|
103
|
+
def _get_user_agent(self) -> str:
|
|
104
|
+
return self.user_agent
|
|
105
|
+
|
|
98
106
|
def paced_request_token(self) -> None:
|
|
99
107
|
"""
|
|
100
108
|
Paces requests to request_token.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
|
|
3
|
-
# Copyright 2021,
|
|
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.
|
|
@@ -18,6 +18,7 @@ import json
|
|
|
18
18
|
import logging
|
|
19
19
|
from typing import Optional
|
|
20
20
|
|
|
21
|
+
from ..private_helpers import _build_user_agent
|
|
21
22
|
from .jwt_token_manager import JWTTokenManager
|
|
22
23
|
|
|
23
24
|
|
|
@@ -55,6 +56,7 @@ class VPCInstanceTokenManager(JWTTokenManager):
|
|
|
55
56
|
METADATA_SERVICE_VERSION = '2022-03-01'
|
|
56
57
|
DEFAULT_IMS_ENDPOINT = 'http://169.254.169.254'
|
|
57
58
|
TOKEN_NAME = 'access_token'
|
|
59
|
+
IAM_EXPIRATION_WINDOW = 10
|
|
58
60
|
|
|
59
61
|
def __init__(
|
|
60
62
|
self, iam_profile_crn: Optional[str] = None, iam_profile_id: Optional[str] = None, url: Optional[str] = None
|
|
@@ -63,6 +65,7 @@ class VPCInstanceTokenManager(JWTTokenManager):
|
|
|
63
65
|
url = self.DEFAULT_IMS_ENDPOINT
|
|
64
66
|
|
|
65
67
|
super().__init__(url, token_name=self.TOKEN_NAME)
|
|
68
|
+
self._set_user_agent(_build_user_agent('vpc-instance-authenticator'))
|
|
66
69
|
|
|
67
70
|
self.iam_profile_crn = iam_profile_crn
|
|
68
71
|
self.iam_profile_id = iam_profile_id
|
|
@@ -91,6 +94,7 @@ class VPCInstanceTokenManager(JWTTokenManager):
|
|
|
91
94
|
'Content-Type': 'application/json',
|
|
92
95
|
'Accept': 'application/json',
|
|
93
96
|
'Authorization': 'Bearer ' + instance_identity_token,
|
|
97
|
+
'User-Agent': self._get_user_agent(),
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
logger.debug('Invoking VPC \'create_iam_token\' operation: %s', url)
|
|
@@ -137,6 +141,7 @@ class VPCInstanceTokenManager(JWTTokenManager):
|
|
|
137
141
|
'Content-type': 'application/json',
|
|
138
142
|
'Accept': 'application/json',
|
|
139
143
|
'Metadata-Flavor': 'ibm',
|
|
144
|
+
'User-Agent': self._get_user_agent(),
|
|
140
145
|
}
|
|
141
146
|
|
|
142
147
|
request_body = {'expires_in': 300}
|
|
@@ -152,3 +157,19 @@ class VPCInstanceTokenManager(JWTTokenManager):
|
|
|
152
157
|
logger.debug('Returned from VPC \'create_access_token\' operation."')
|
|
153
158
|
|
|
154
159
|
return response['access_token']
|
|
160
|
+
|
|
161
|
+
def _is_token_expired(self) -> bool:
|
|
162
|
+
"""
|
|
163
|
+
Returns true iff the current cached token is expired.
|
|
164
|
+
We'll consider an access token as expired when we reach its IAM server-reported expiration time
|
|
165
|
+
minus our expiration window (10 secs).
|
|
166
|
+
We do this to avoid using an access token that might expire in the middle of a long-running transaction
|
|
167
|
+
within an IBM Cloud service.
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
bool
|
|
172
|
+
True if token is expired; False otherwise
|
|
173
|
+
"""
|
|
174
|
+
current_time = self._get_current_time()
|
|
175
|
+
return current_time >= (self.expire_time - self.IAM_EXPIRATION_WINDOW)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '3.20.0'
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0/ibm_cloud_sdk_core.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ibm-cloud-sdk-core
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.20.0
|
|
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
|
[](https://cla-assistant.io/ibm/python-sdk-core)
|
|
30
30
|
[](https://github.com/semantic-release/semantic-release)
|
|
31
31
|
|
|
32
|
-
# IBM Python SDK Core Version 3.
|
|
32
|
+
# IBM Python SDK Core Version 3.20.0
|
|
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
|
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core.egg-info/SOURCES.txt
RENAMED
|
@@ -10,6 +10,7 @@ ibm_cloud_sdk_core/api_exception.py
|
|
|
10
10
|
ibm_cloud_sdk_core/base_service.py
|
|
11
11
|
ibm_cloud_sdk_core/detailed_response.py
|
|
12
12
|
ibm_cloud_sdk_core/get_authenticator.py
|
|
13
|
+
ibm_cloud_sdk_core/private_helpers.py
|
|
13
14
|
ibm_cloud_sdk_core/utils.py
|
|
14
15
|
ibm_cloud_sdk_core/version.py
|
|
15
16
|
ibm_cloud_sdk_core.egg-info/PKG-INFO
|
|
@@ -1,5 +1,21 @@
|
|
|
1
|
-
# coding
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
# Copyright 2019, 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
|
+
|
|
2
17
|
# pylint: disable=missing-docstring,protected-access,too-few-public-methods,too-many-lines
|
|
18
|
+
|
|
3
19
|
import gzip
|
|
4
20
|
import json
|
|
5
21
|
import os
|
|
@@ -802,7 +818,7 @@ def test_user_agent_header():
|
|
|
802
818
|
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
803
819
|
user_agent_header = service.user_agent_header
|
|
804
820
|
assert user_agent_header is not None
|
|
805
|
-
assert user_agent_header['User-Agent']
|
|
821
|
+
assert user_agent_header['User-Agent'].startswith('ibm-python-sdk-core-')
|
|
806
822
|
|
|
807
823
|
responses.add(responses.GET, 'https://gateway.watsonplatform.net/test/api', status=200, body='some text')
|
|
808
824
|
prepped = service.prepare_request('GET', url='', headers={'user-agent': 'my_user_agent'})
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_container_token_manager.py
RENAMED
|
@@ -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
|
|
|
@@ -94,6 +111,9 @@ def test_request_token_auth_default():
|
|
|
94
111
|
assert len(responses.calls) == 1
|
|
95
112
|
assert responses.calls[0].request.url == iam_url
|
|
96
113
|
assert responses.calls[0].request.headers.get('Authorization') is None
|
|
114
|
+
assert (
|
|
115
|
+
responses.calls[0].request.headers.get('User-Agent').startswith('ibm-python-sdk-core/container-authenticator')
|
|
116
|
+
)
|
|
97
117
|
assert json.loads(responses.calls[0].response.text)['access_token'] == TEST_ACCESS_TOKEN_1
|
|
98
118
|
|
|
99
119
|
|
|
@@ -169,18 +189,22 @@ def test_get_token_success():
|
|
|
169
189
|
assert access_token == TEST_ACCESS_TOKEN_1
|
|
170
190
|
assert token_manager.access_token == TEST_ACCESS_TOKEN_1
|
|
171
191
|
|
|
172
|
-
# Verify the token manager
|
|
173
|
-
# Before we call
|
|
174
|
-
#
|
|
175
|
-
|
|
176
|
-
token_manager.
|
|
192
|
+
# Verify that the token manager returns the cached value.
|
|
193
|
+
# Before we call `get_token` again, set the expiration and refresh time
|
|
194
|
+
# so that we do not fetch a new access token.
|
|
195
|
+
# This is necessary because we are using a fixed JWT response.
|
|
196
|
+
token_manager.expire_time = _get_current_time() + 1000
|
|
197
|
+
token_manager.refresh_time = _get_current_time() + 1000
|
|
177
198
|
token_manager.set_scope('send-second-token')
|
|
178
199
|
access_token = token_manager.get_token()
|
|
179
200
|
assert access_token == TEST_ACCESS_TOKEN_1
|
|
180
201
|
assert token_manager.access_token == TEST_ACCESS_TOKEN_1
|
|
181
202
|
|
|
182
203
|
# Force expiration to get the second token.
|
|
183
|
-
|
|
204
|
+
# We'll set the expiration time to be current-time + EXPIRATION_WINDOW (10 secs)
|
|
205
|
+
# because we want the access token to be considered as "expired"
|
|
206
|
+
# when we reach the IAM-server reported expiration time minus 10 secs.
|
|
207
|
+
token_manager.expire_time = _get_current_time() + EXPIRATION_WINDOW
|
|
184
208
|
access_token = token_manager.get_token()
|
|
185
209
|
assert access_token == TEST_ACCESS_TOKEN_2
|
|
186
210
|
assert token_manager.access_token == TEST_ACCESS_TOKEN_2
|
|
@@ -206,17 +230,21 @@ def test_authenticate_success():
|
|
|
206
230
|
authenticator.authenticate(request)
|
|
207
231
|
assert request['headers']['Authorization'] == 'Bearer ' + TEST_ACCESS_TOKEN_1
|
|
208
232
|
|
|
209
|
-
# Verify the token manager
|
|
210
|
-
# Before we call
|
|
211
|
-
#
|
|
212
|
-
|
|
213
|
-
authenticator.token_manager.
|
|
233
|
+
# Verify that the token manager returns the cached value.
|
|
234
|
+
# Before we call `get_token` again, set the expiration and refresh time
|
|
235
|
+
# so that we do not fetch a new access token.
|
|
236
|
+
# This is necessary because we are using a fixed JWT response.
|
|
237
|
+
authenticator.token_manager.expire_time = _get_current_time() + 1000
|
|
238
|
+
authenticator.token_manager.refresh_time = _get_current_time() + 1000
|
|
214
239
|
authenticator.token_manager.set_scope('send-second-token')
|
|
215
240
|
authenticator.authenticate(request)
|
|
216
241
|
assert request['headers']['Authorization'] == 'Bearer ' + TEST_ACCESS_TOKEN_1
|
|
217
242
|
|
|
218
243
|
# Force expiration to get the second token.
|
|
219
|
-
|
|
244
|
+
# We'll set the expiration time to be current-time + EXPIRATION_WINDOW (10 secs)
|
|
245
|
+
# because we want the access token to be considered as "expired"
|
|
246
|
+
# when we reach the IAM-server reported expiration time minus 10 secs.
|
|
247
|
+
authenticator.token_manager.expire_time = _get_current_time() + EXPIRATION_WINDOW
|
|
220
248
|
authenticator.authenticate(request)
|
|
221
249
|
assert request['headers']['Authorization'] == 'Bearer ' + TEST_ACCESS_TOKEN_2
|
|
222
250
|
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
# Copyright 2019, 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 time
|
|
@@ -38,6 +54,7 @@ def test_request_token():
|
|
|
38
54
|
|
|
39
55
|
assert len(responses.calls) == 1
|
|
40
56
|
assert responses.calls[0].request.url == url + '/v1/authorize'
|
|
57
|
+
assert responses.calls[0].request.headers.get('User-Agent').startswith('ibm-python-sdk-core/cp4d-authenticator')
|
|
41
58
|
assert token == access_token
|
|
42
59
|
|
|
43
60
|
token_manager = CP4DTokenManager("username", "password", url + '/v1/authorize')
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
# Copyright 2019, 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 = {
|
|
@@ -46,6 +72,7 @@ def test_request_token_auth_default():
|
|
|
46
72
|
assert len(responses.calls) == 1
|
|
47
73
|
assert responses.calls[0].request.url == iam_url
|
|
48
74
|
assert responses.calls[0].request.headers.get('Authorization') is None
|
|
75
|
+
assert responses.calls[0].request.headers.get('User-Agent').startswith('ibm-python-sdk-core/iam-authenticator')
|
|
49
76
|
assert responses.calls[0].response.text == response
|
|
50
77
|
|
|
51
78
|
|
|
@@ -268,6 +295,62 @@ def test_request_token_auth_in_setter_scope():
|
|
|
268
295
|
assert 'scope=john+snow' in responses.calls[0].response.request.body
|
|
269
296
|
|
|
270
297
|
|
|
298
|
+
@responses.activate
|
|
299
|
+
def test_get_token_success():
|
|
300
|
+
iam_url = "https://iam.cloud.ibm.com/identity/token"
|
|
301
|
+
|
|
302
|
+
# Create two mock responses with different access tokens.
|
|
303
|
+
response1 = """{
|
|
304
|
+
"access_token": "%s",
|
|
305
|
+
"token_type": "Bearer",
|
|
306
|
+
"expires_in": 3600,
|
|
307
|
+
"expiration": 1600003600,
|
|
308
|
+
"refresh_token": "jy4gl91BQ"
|
|
309
|
+
}""" % (
|
|
310
|
+
TEST_ACCESS_TOKEN_1
|
|
311
|
+
)
|
|
312
|
+
response2 = """{
|
|
313
|
+
"access_token": "%s",
|
|
314
|
+
"token_type": "Bearer",
|
|
315
|
+
"expires_in": 3600,
|
|
316
|
+
"expiration": 1600007200,
|
|
317
|
+
"refresh_token": "jy4gl91BQ"
|
|
318
|
+
}""" % (
|
|
319
|
+
TEST_ACCESS_TOKEN_2
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
token_manager = IAMTokenManager("iam_apikey")
|
|
323
|
+
|
|
324
|
+
access_token = token_manager.access_token
|
|
325
|
+
assert access_token is None
|
|
326
|
+
|
|
327
|
+
responses.add(responses.POST, url=iam_url, body=response1, status=200)
|
|
328
|
+
access_token = token_manager.get_token()
|
|
329
|
+
assert access_token == TEST_ACCESS_TOKEN_1
|
|
330
|
+
assert token_manager.access_token == TEST_ACCESS_TOKEN_1
|
|
331
|
+
|
|
332
|
+
# Verify that the token manager returns the cached value.
|
|
333
|
+
# Before we call `get_token` again, set the expiration and refresh time
|
|
334
|
+
# so that we do not fetch a new access token.
|
|
335
|
+
# This is necessary because we are using a fixed JWT response.
|
|
336
|
+
token_manager.expire_time = _get_current_time() + 1000
|
|
337
|
+
token_manager.refresh_time = _get_current_time() + 1000
|
|
338
|
+
access_token = token_manager.get_token()
|
|
339
|
+
assert access_token == TEST_ACCESS_TOKEN_1
|
|
340
|
+
assert token_manager.access_token == TEST_ACCESS_TOKEN_1
|
|
341
|
+
|
|
342
|
+
# Force expiration to get the second token.
|
|
343
|
+
# We'll set the expiration time to be current-time + EXPIRATION_WINDOW (10 secs)
|
|
344
|
+
# because we want the access token to be considered as "expired"
|
|
345
|
+
# when we reach the IAM-server reported expiration time minus 10 secs.
|
|
346
|
+
responses.add(responses.POST, url=iam_url, body=response2, status=200)
|
|
347
|
+
token_manager.expire_time = _get_current_time() + EXPIRATION_WINDOW
|
|
348
|
+
token_manager.refresh_time = _get_current_time() + 1000
|
|
349
|
+
access_token = token_manager.get_token()
|
|
350
|
+
assert access_token == TEST_ACCESS_TOKEN_2
|
|
351
|
+
assert token_manager.access_token == TEST_ACCESS_TOKEN_2
|
|
352
|
+
|
|
353
|
+
|
|
271
354
|
@responses.activate
|
|
272
355
|
def test_get_refresh_token():
|
|
273
356
|
iam_url = "https://iam.cloud.ibm.com/identity/token"
|
|
@@ -1,3 +1,19 @@
|
|
|
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
|
+
|
|
1
17
|
# pylint: disable=missing-docstring
|
|
2
18
|
import json
|
|
3
19
|
import time
|
|
@@ -45,6 +61,7 @@ def test_request_token():
|
|
|
45
61
|
|
|
46
62
|
assert len(responses.calls) == 1
|
|
47
63
|
assert responses.calls[0].request.url == MOCK_URL + OPERATION_PATH
|
|
64
|
+
assert responses.calls[0].request.headers.get('User-Agent').startswith('ibm-python-sdk-core/mcsp-authenticator')
|
|
48
65
|
assert token == access_token
|
|
49
66
|
|
|
50
67
|
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_vpc_instance_token_manager.py
RENAMED
|
@@ -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
|
-
|
|
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():
|
|
@@ -78,6 +85,7 @@ def test_retrieve_instance_identity_token(caplog):
|
|
|
78
85
|
assert responses.calls[0].request.headers['Content-Type'] == 'application/json'
|
|
79
86
|
assert responses.calls[0].request.headers['Accept'] == 'application/json'
|
|
80
87
|
assert responses.calls[0].request.headers['Metadata-Flavor'] == 'ibm'
|
|
88
|
+
assert responses.calls[0].request.headers['User-Agent'].startswith('ibm-python-sdk-core/vpc-instance-authenticator')
|
|
81
89
|
assert responses.calls[0].request.params['version'] == '2022-03-01'
|
|
82
90
|
assert responses.calls[0].request.body == '{"expires_in": 300}'
|
|
83
91
|
assert ii_token == TEST_TOKEN
|
|
@@ -144,6 +152,7 @@ def test_request_token_with_crn(caplog):
|
|
|
144
152
|
assert responses.calls[0].request.headers['Content-Type'] == 'application/json'
|
|
145
153
|
assert responses.calls[0].request.headers['Accept'] == 'application/json'
|
|
146
154
|
assert responses.calls[0].request.headers['Authorization'] == 'Bearer ' + TEST_TOKEN
|
|
155
|
+
assert responses.calls[0].request.headers['User-Agent'].startswith('ibm-python-sdk-core/vpc-instance-authenticator')
|
|
147
156
|
assert responses.calls[0].request.body == '{"trusted_profile": {"crn": "crn:iam-profile:123"}}'
|
|
148
157
|
assert responses.calls[0].request.params['version'] == '2022-03-01'
|
|
149
158
|
# Check the logs.
|
|
@@ -272,7 +281,7 @@ def test_access_token():
|
|
|
272
281
|
'access_token': TEST_TOKEN,
|
|
273
282
|
}
|
|
274
283
|
response_iam = {
|
|
275
|
-
'access_token':
|
|
284
|
+
'access_token': TEST_ACCESS_TOKEN_1,
|
|
276
285
|
}
|
|
277
286
|
|
|
278
287
|
responses.add(
|
|
@@ -290,6 +299,54 @@ def test_access_token():
|
|
|
290
299
|
assert token_manager.refresh_time == 0
|
|
291
300
|
|
|
292
301
|
token_manager.get_token()
|
|
293
|
-
assert token_manager.access_token ==
|
|
302
|
+
assert token_manager.access_token == TEST_ACCESS_TOKEN_1
|
|
294
303
|
assert token_manager.expire_time > 0
|
|
295
304
|
assert token_manager.refresh_time > 0
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@responses.activate
|
|
308
|
+
def test_get_token_success():
|
|
309
|
+
token_manager = VPCInstanceTokenManager()
|
|
310
|
+
|
|
311
|
+
# Mock the retrieve instance identity token method.
|
|
312
|
+
def mock_retrieve_instance_identity_token():
|
|
313
|
+
return TEST_TOKEN
|
|
314
|
+
|
|
315
|
+
token_manager.retrieve_instance_identity_token = mock_retrieve_instance_identity_token
|
|
316
|
+
|
|
317
|
+
response1 = {
|
|
318
|
+
'access_token': TEST_ACCESS_TOKEN_1,
|
|
319
|
+
}
|
|
320
|
+
response2 = {
|
|
321
|
+
'access_token': TEST_ACCESS_TOKEN_2,
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
responses.add(
|
|
325
|
+
responses.POST, 'http://169.254.169.254/instance_identity/v1/iam_token', body=json.dumps(response1), status=200
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
access_token = token_manager.get_token()
|
|
329
|
+
assert access_token == TEST_ACCESS_TOKEN_1
|
|
330
|
+
assert token_manager.access_token == TEST_ACCESS_TOKEN_1
|
|
331
|
+
|
|
332
|
+
# Verify that the token manager returns the cached value.
|
|
333
|
+
# Before we call `get_token` again, set the expiration and refresh time
|
|
334
|
+
# so that we do not fetch a new access token.
|
|
335
|
+
# This is necessary because we are using a fixed JWT response.
|
|
336
|
+
token_manager.expire_time = _get_current_time() + 1000
|
|
337
|
+
token_manager.refresh_time = _get_current_time() + 1000
|
|
338
|
+
access_token = token_manager.get_token()
|
|
339
|
+
assert access_token == TEST_ACCESS_TOKEN_1
|
|
340
|
+
assert token_manager.access_token == TEST_ACCESS_TOKEN_1
|
|
341
|
+
|
|
342
|
+
# Force expiration to get the second token.
|
|
343
|
+
# We'll set the expiration time to be current-time + EXPIRATION_WINDOW (10 secs)
|
|
344
|
+
# because we want the access token to be considered as "expired"
|
|
345
|
+
# when we reach the IAM-server reported expiration time minus 10 secs.
|
|
346
|
+
responses.add(
|
|
347
|
+
responses.POST, 'http://169.254.169.254/instance_identity/v1/iam_token', body=json.dumps(response2), status=200
|
|
348
|
+
)
|
|
349
|
+
token_manager.expire_time = _get_current_time() + EXPIRATION_WINDOW
|
|
350
|
+
access_token = token_manager.get_token()
|
|
351
|
+
assert access_token == TEST_ACCESS_TOKEN_2
|
|
352
|
+
assert token_manager.access_token == TEST_ACCESS_TOKEN_2
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '3.19.1'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/detailed_response.py
RENAMED
|
File without changes
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core/get_authenticator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core.egg-info/requires.txt
RENAMED
|
File without changes
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core.egg-info/top_level.txt
RENAMED
|
File without changes
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/ibm_cloud_sdk_core.egg-info/zip-safe
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_container_authenticator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test/test_vpc_instance_authenticator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ibm-cloud-sdk-core-3.19.1 → ibm-cloud-sdk-core-3.20.0}/test_integration/test_ssl_verification.py
RENAMED
|
File without changes
|