ibm-cloud-sdk-core 3.23.0__tar.gz → 3.24.1__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 (72) hide show
  1. {ibm_cloud_sdk_core-3.23.0/ibm_cloud_sdk_core.egg-info → ibm_cloud_sdk_core-3.24.1}/PKG-INFO +6 -5
  2. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/README.md +3 -3
  3. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/__init__.py +1 -0
  4. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/__init__.py +6 -0
  5. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/authenticator.py +2 -1
  6. ibm_cloud_sdk_core-3.24.1/ibm_cloud_sdk_core/authenticators/mcspv2_authenticator.py +270 -0
  7. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/get_authenticator.py +51 -6
  8. ibm_cloud_sdk_core-3.24.1/ibm_cloud_sdk_core/token_managers/mcspv2_token_manager.py +185 -0
  9. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/utils.py +13 -1
  10. ibm_cloud_sdk_core-3.24.1/ibm_cloud_sdk_core/version.py +1 -0
  11. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1/ibm_cloud_sdk_core.egg-info}/PKG-INFO +6 -5
  12. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core.egg-info/SOURCES.txt +4 -0
  13. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/pyproject.toml +1 -1
  14. ibm_cloud_sdk_core-3.23.0/test/test_utils.py → ibm_cloud_sdk_core-3.24.1/test/test_get_authenticator.py +49 -313
  15. ibm_cloud_sdk_core-3.24.1/test/test_mcspv2_authenticator.py +409 -0
  16. ibm_cloud_sdk_core-3.24.1/test/test_utils.py +337 -0
  17. ibm_cloud_sdk_core-3.23.0/ibm_cloud_sdk_core/version.py +0 -1
  18. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/LICENSE +0 -0
  19. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/MANIFEST.in +0 -0
  20. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/api_exception.py +0 -0
  21. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/basic_authenticator.py +0 -0
  22. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/bearer_token_authenticator.py +0 -0
  23. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/container_authenticator.py +0 -0
  24. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/cp4d_authenticator.py +0 -0
  25. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/iam_assume_authenticator.py +0 -0
  26. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/iam_authenticator.py +0 -0
  27. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/iam_request_based_authenticator.py +0 -0
  28. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/mcsp_authenticator.py +0 -0
  29. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/no_auth_authenticator.py +0 -0
  30. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/authenticators/vpc_instance_authenticator.py +0 -0
  31. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/base_service.py +0 -0
  32. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/detailed_response.py +0 -0
  33. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/http_adapter.py +0 -0
  34. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/logger.py +0 -0
  35. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/private_helpers.py +0 -0
  36. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/token_managers/__init__.py +0 -0
  37. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/token_managers/container_token_manager.py +0 -0
  38. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/token_managers/cp4d_token_manager.py +0 -0
  39. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/token_managers/iam_assume_token_manager.py +0 -0
  40. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/token_managers/iam_request_based_token_manager.py +0 -0
  41. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/token_managers/iam_token_manager.py +0 -0
  42. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/token_managers/jwt_token_manager.py +0 -0
  43. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/token_managers/mcsp_token_manager.py +0 -0
  44. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/token_managers/token_manager.py +0 -0
  45. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core/token_managers/vpc_instance_token_manager.py +0 -0
  46. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core.egg-info/dependency_links.txt +0 -0
  47. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core.egg-info/requires.txt +0 -0
  48. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/ibm_cloud_sdk_core.egg-info/top_level.txt +0 -0
  49. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/setup.cfg +0 -0
  50. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_api_exception.py +0 -0
  51. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_authenticator.py +0 -0
  52. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_base_service.py +0 -0
  53. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_basic_authenticator.py +0 -0
  54. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_bearer_authenticator.py +0 -0
  55. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_container_authenticator.py +0 -0
  56. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_container_token_manager.py +0 -0
  57. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_cp4d_authenticator.py +0 -0
  58. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_cp4d_token_manager.py +0 -0
  59. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_detailed_response.py +0 -0
  60. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_http_adapter.py +0 -0
  61. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_iam_assume_authenticator.py +0 -0
  62. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_iam_assume_token_manager.py +0 -0
  63. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_iam_authenticator.py +0 -0
  64. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_iam_token_manager.py +0 -0
  65. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_jwt_token_manager.py +0 -0
  66. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_logger.py +0 -0
  67. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_mcsp_authenticator.py +0 -0
  68. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_mcsp_token_manager.py +0 -0
  69. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_no_auth_authenticator.py +0 -0
  70. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_token_manager.py +0 -0
  71. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_vpc_instance_authenticator.py +0 -0
  72. {ibm_cloud_sdk_core-3.23.0 → ibm_cloud_sdk_core-3.24.1}/test/test_vpc_instance_token_manager.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: ibm-cloud-sdk-core
3
- Version: 3.23.0
3
+ Version: 3.24.1
4
4
  Summary: Core library used by SDKs for IBM Cloud Services
5
5
  Author-email: IBM <devxsdk@us.ibm.com>
6
6
  Project-URL: Repository, https://github.com/IBM/python-sdk-core
@@ -42,6 +42,7 @@ Requires-Dist: black<25.0.0,>=24.0.0; extra == "dev"
42
42
  Provides-Extra: publish
43
43
  Requires-Dist: build; extra == "publish"
44
44
  Requires-Dist: twine; extra == "publish"
45
+ Dynamic: license-file
45
46
 
46
47
  [![Build Status](https://github.com/IBM/python-sdk-core/actions/workflows/build.yaml/badge.svg)](https://github.com/IBM/python-sdk-core/actions/workflows/build.yaml)
47
48
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ibm-cloud-sdk-core)](https://pypi.org/project/ibm-cloud-sdk-core/)
@@ -49,7 +50,7 @@ Requires-Dist: twine; extra == "publish"
49
50
  [![CLA assistant](https://cla-assistant.io/readme/badge/ibm/python-sdk-core)](https://cla-assistant.io/ibm/python-sdk-core)
50
51
  [![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)
51
52
 
52
- # IBM Python SDK Core Version 3.23.0
53
+ # IBM Python SDK Core Version 3.24.1
53
54
  This project contains core functionality required by Python code generated by the IBM Cloud OpenAPI SDK Generator
54
55
  (openapi-sdkgen).
55
56
 
@@ -115,12 +116,12 @@ When running your application, you should see output like this if debug logging
115
116
  ```
116
117
  2024-09-16 15:44:45,174 [ibm-cloud-sdk-core:DEBUG] Get authenticator from environment, key=global_search
117
118
  2024-09-16 15:44:45,175 [ibm-cloud-sdk-core:DEBUG] Set service URL: https://api.global-search-tagging.cloud.ibm.com
118
- 2024-09-16 15:44:45,175 [ibm-cloud-sdk-core:DEBUG] Set User-Agent: ibm-python-sdk-core-3.23.0 os.name=Linux os.version=6.10.9-100.fc39.x86_64 python.version=3.12.5
119
+ 2024-09-16 15:44:45,175 [ibm-cloud-sdk-core:DEBUG] Set User-Agent: ibm-python-sdk-core-3.24.1 os.name=Linux os.version=6.10.9-100.fc39.x86_64 python.version=3.12.5
119
120
  2024-09-16 15:44:45,181 [ibm-cloud-sdk-core:DEBUG] Configuring BaseService instance with service name: global_search
120
121
  2024-09-16 15:44:45,181 [ibm-cloud-sdk-core:DEBUG] Performing synchronous token fetch
121
122
  2024-09-16 15:44:45,182 [ibm-cloud-sdk-core:DEBUG] Invoking IAM get_token operation: https://iam.cloud.ibm.com/identity/token
122
123
  2024-09-16 15:44:45,182 [urllib3.connectionpool:DEBUG] Starting new HTTPS connection (1): iam.cloud.ibm.com:443
123
- send: b'POST /identity/token HTTP/1.1\r\nHost: iam.cloud.ibm.com\r\nUser-Agent: ibm-python-sdk-core/iam-authenticator-3.23.0 os.name=Linux os.version=6.10.9-100.fc39.x86_64 python.version=3.12.5\r\nAccept-Encoding: gzip, deflate\r\nAccept: application/json\r\nConnection: keep-alive\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 135\r\n\r\n'
124
+ send: b'POST /identity/token HTTP/1.1\r\nHost: iam.cloud.ibm.com\r\nUser-Agent: ibm-python-sdk-core/iam-authenticator-3.24.1 os.name=Linux os.version=6.10.9-100.fc39.x86_64 python.version=3.12.5\r\nAccept-Encoding: gzip, deflate\r\nAccept: application/json\r\nConnection: keep-alive\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 135\r\n\r\n'
124
125
  send: b'grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey=[redacted]&response_type=cloud_iam'
125
126
  reply: 'HTTP/1.1 200 OK\r\n'
126
127
  header: Content-Type: application/json
@@ -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.23.0
7
+ # IBM Python SDK Core Version 3.24.1
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
 
@@ -70,12 +70,12 @@ When running your application, you should see output like this if debug logging
70
70
  ```
71
71
  2024-09-16 15:44:45,174 [ibm-cloud-sdk-core:DEBUG] Get authenticator from environment, key=global_search
72
72
  2024-09-16 15:44:45,175 [ibm-cloud-sdk-core:DEBUG] Set service URL: https://api.global-search-tagging.cloud.ibm.com
73
- 2024-09-16 15:44:45,175 [ibm-cloud-sdk-core:DEBUG] Set User-Agent: ibm-python-sdk-core-3.23.0 os.name=Linux os.version=6.10.9-100.fc39.x86_64 python.version=3.12.5
73
+ 2024-09-16 15:44:45,175 [ibm-cloud-sdk-core:DEBUG] Set User-Agent: ibm-python-sdk-core-3.24.1 os.name=Linux os.version=6.10.9-100.fc39.x86_64 python.version=3.12.5
74
74
  2024-09-16 15:44:45,181 [ibm-cloud-sdk-core:DEBUG] Configuring BaseService instance with service name: global_search
75
75
  2024-09-16 15:44:45,181 [ibm-cloud-sdk-core:DEBUG] Performing synchronous token fetch
76
76
  2024-09-16 15:44:45,182 [ibm-cloud-sdk-core:DEBUG] Invoking IAM get_token operation: https://iam.cloud.ibm.com/identity/token
77
77
  2024-09-16 15:44:45,182 [urllib3.connectionpool:DEBUG] Starting new HTTPS connection (1): iam.cloud.ibm.com:443
78
- send: b'POST /identity/token HTTP/1.1\r\nHost: iam.cloud.ibm.com\r\nUser-Agent: ibm-python-sdk-core/iam-authenticator-3.23.0 os.name=Linux os.version=6.10.9-100.fc39.x86_64 python.version=3.12.5\r\nAccept-Encoding: gzip, deflate\r\nAccept: application/json\r\nConnection: keep-alive\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 135\r\n\r\n'
78
+ send: b'POST /identity/token HTTP/1.1\r\nHost: iam.cloud.ibm.com\r\nUser-Agent: ibm-python-sdk-core/iam-authenticator-3.24.1 os.name=Linux os.version=6.10.9-100.fc39.x86_64 python.version=3.12.5\r\nAccept-Encoding: gzip, deflate\r\nAccept: application/json\r\nConnection: keep-alive\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 135\r\n\r\n'
79
79
  send: b'grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey=[redacted]&response_type=cloud_iam'
80
80
  reply: 'HTTP/1.1 200 OK\r\n'
81
81
  header: Content-Type: application/json
@@ -46,6 +46,7 @@ from .token_managers.cp4d_token_manager import CP4DTokenManager
46
46
  from .token_managers.container_token_manager import ContainerTokenManager
47
47
  from .token_managers.vpc_instance_token_manager import VPCInstanceTokenManager
48
48
  from .token_managers.mcsp_token_manager import MCSPTokenManager
49
+ from .token_managers.mcspv2_token_manager import MCSPV2TokenManager
49
50
  from .api_exception import ApiException
50
51
  from .utils import datetime_to_string, string_to_datetime, read_external_sources
51
52
  from .utils import datetime_to_string_list, string_to_datetime_list
@@ -28,9 +28,14 @@ classes:
28
28
  Authenticator: Abstract Base Class. Implement this interface to provide custom authentication schemes to services.
29
29
  BasicAuthenticator: Authenticator for passing supplied basic authentication information to service endpoint.
30
30
  BearerTokenAuthenticator: Authenticator for passing supplied bearer token to service endpoint.
31
+ ContainerAuthenticator: Authenticator for use in a container environment.
31
32
  CloudPakForDataAuthenticator: Authenticator for passing CP4D authentication information to service endpoint.
32
33
  IAMAuthenticator: Authenticator for passing IAM authentication information to service endpoint.
34
+ IAMAssumeAuthenticator: Authenticator for the "assume" grant type.
35
+ VPCInstanceAuthenticator: Authenticator for use within a VPC instance.
33
36
  NoAuthAuthenticator: Performs no authentication. Useful for testing purposes.
37
+ MCSPAuthenticator: Authenticator that supports the MCSP v1 token exchange.
38
+ MCSPV2Authenticator: Authenticator that supports the MCSP v2 token exchange.
34
39
  """
35
40
 
36
41
  from .authenticator import Authenticator
@@ -43,3 +48,4 @@ from .iam_assume_authenticator import IAMAssumeAuthenticator
43
48
  from .vpc_instance_authenticator import VPCInstanceAuthenticator
44
49
  from .no_auth_authenticator import NoAuthAuthenticator
45
50
  from .mcsp_authenticator import MCSPAuthenticator
51
+ from .mcspv2_authenticator import MCSPV2Authenticator
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- # Copyright 2019, 2023 IBM All Rights Reserved.
3
+ # Copyright 2019, 2025 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.
@@ -30,6 +30,7 @@ class Authenticator(ABC):
30
30
  AUTHTYPE_VPC = 'vpc'
31
31
  AUTHTYPE_NOAUTH = 'noAuth'
32
32
  AUTHTYPE_MCSP = 'mcsp'
33
+ AUTHTYPE_MCSPV2 = 'mcspv2'
33
34
  AUTHTYPE_UNKNOWN = 'unknown'
34
35
 
35
36
  @abstractmethod
@@ -0,0 +1,270 @@
1
+ # coding: utf-8
2
+
3
+ # Copyright 2025. 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
+ from typing import Dict, Optional
18
+
19
+ from requests import Request
20
+
21
+ from ibm_cloud_sdk_core.logger import get_logger
22
+ from .authenticator import Authenticator
23
+ from ..token_managers.mcspv2_token_manager import MCSPV2TokenManager
24
+
25
+ logger = get_logger()
26
+
27
+
28
+ class MCSPV2Authenticator(Authenticator):
29
+ """The MCSPV2Authenticator invokes the MCSP v2 token-exchange operation
30
+ (POST /api/2.0/{scopeCollectionType}/{scopeId}/apikeys/token) to obtain an access token
31
+ for an apikey, and adds the access token to requests via an Authorization header
32
+ of the form: "Authorization: Bearer <access-token>".
33
+
34
+ Keyword Args:
35
+ apikey: The apikey used to obtain an access token [required].
36
+ url: The base endpoint URL for the MCSP token service [required].
37
+ scope_collection_type: The scope collection type of item(s) [required].
38
+ Valid values are: "accounts", "subscriptions", "services".
39
+ scope_id: The scope identifier of item(s) [required].
40
+ include_builtin_actions: A flag to include builtin actions in the "actions" claim in the
41
+ MCSP access token (default: False).
42
+ include_custom_actions: A flag to include custom actions in the "actions" claim in the
43
+ MCSP access token (default: False).
44
+ include_roles: A flag to include the "roles" claim in the MCSP access token (default: True).
45
+ prefix_roles: A flag to add a prefix with the scope level where the role is defined
46
+ in the "roles" claim (default: False).
47
+ caller_ext_claim: A map (dictionary) containing keys and values to be injected into
48
+ the access token as the "callerExt" claim (default: None).
49
+ The keys used in this map must be enabled in the apikey by setting the
50
+ "callerExtClaimNames" property when the apikey is created.
51
+ This property is typically only used in scenarios involving an apikey with identityType `SERVICEID`.
52
+ disable_ssl_verification: A flag that indicates whether verification of the server's SSL
53
+ certificate should be disabled or not (default: False).
54
+ headers: Default headers to be sent with every MCSP token request (default: None).
55
+ proxies: Dictionary for mapping request protocol to proxy URL (default: None).
56
+ proxies.http (optional): The proxy endpoint to use for HTTP requests.
57
+ proxies.https (optional): The proxy endpoint to use for HTTPS requests.
58
+
59
+ Attributes:
60
+ token_manager (MCSPTokenManager): Retrieves and manages MCSP tokens from the endpoint specified by the url.
61
+
62
+ Raises:
63
+ TypeError: The `disable_ssl_verification` is not a bool.
64
+ ValueError: An error occurred while validating the configuration.
65
+ """
66
+
67
+ def __init__(
68
+ self,
69
+ *,
70
+ apikey: str,
71
+ url: str,
72
+ scope_collection_type: str,
73
+ scope_id: str,
74
+ include_builtin_actions: bool = False,
75
+ include_custom_actions: bool = False,
76
+ include_roles: bool = True,
77
+ prefix_roles: bool = False,
78
+ caller_ext_claim: Optional[Dict[str, str]] = None,
79
+ disable_ssl_verification: bool = False,
80
+ headers: Optional[Dict[str, str]] = None,
81
+ proxies: Optional[Dict[str, str]] = None,
82
+ ) -> None:
83
+
84
+ self.token_manager = MCSPV2TokenManager(
85
+ apikey=apikey,
86
+ url=url,
87
+ scope_collection_type=scope_collection_type,
88
+ scope_id=scope_id,
89
+ include_builtin_actions=include_builtin_actions,
90
+ include_custom_actions=include_custom_actions,
91
+ include_roles=include_roles,
92
+ prefix_roles=prefix_roles,
93
+ caller_ext_claim=caller_ext_claim,
94
+ disable_ssl_verification=disable_ssl_verification,
95
+ headers=headers,
96
+ proxies=proxies,
97
+ )
98
+ self.validate()
99
+
100
+ def authentication_type(self) -> str:
101
+ """Returns this authenticator's type ('mcsp')."""
102
+ return Authenticator.AUTHTYPE_MCSPV2
103
+
104
+ def validate(self) -> None:
105
+ """Validate the configuration.
106
+
107
+ Raises:
108
+ ValueError: The <...> property shouldn't be None.
109
+ """
110
+ if not isinstance(self.token_manager.apikey, str):
111
+ raise TypeError('"apikey" must be a string')
112
+ if not isinstance(self.token_manager.url, str):
113
+ raise TypeError('"url" must be a string')
114
+ if not isinstance(self.token_manager.scope_collection_type, str):
115
+ raise TypeError('"scope_collection_type" must be a string')
116
+ if not isinstance(self.token_manager.scope_id, str):
117
+ raise TypeError('"scope_id" must be a string')
118
+ if not isinstance(self.token_manager.include_builtin_actions, bool):
119
+ raise TypeError('"include_builtin_actions" must be a bool')
120
+ if not isinstance(self.token_manager.include_custom_actions, bool):
121
+ raise TypeError('"include_custom_actions" must be a bool')
122
+ if not isinstance(self.token_manager.include_roles, bool):
123
+ raise TypeError('"include_roles" must be a bool')
124
+ if not isinstance(self.token_manager.prefix_roles, bool):
125
+ raise TypeError('"prefix_roles" must be a bool')
126
+ if not isinstance(self.token_manager.caller_ext_claim, (dict, type(None))):
127
+ raise TypeError('"caller_ext_claim" must be a dictionary or None')
128
+ if not isinstance(self.token_manager.disable_ssl_verification, bool):
129
+ raise TypeError('"disable_ssl_verification" must be a bool')
130
+ if not isinstance(self.token_manager.headers, (dict, type(None))):
131
+ raise TypeError('"headers" must be a dictionary or None')
132
+ if not isinstance(self.token_manager.proxies, (dict, type(None))):
133
+ raise TypeError('"proxies" must be a dictionary or None')
134
+
135
+ def authenticate(self, req: Request) -> None:
136
+ """Adds MCSP authentication information to the request.
137
+
138
+ The MCSP bearer token will be added to the request's headers in the form:
139
+ Authorization: Bearer <bearer-token>
140
+
141
+ Args:
142
+ req: The request to add MCSP authentication information to. Must contain a key to a dictionary
143
+ called headers.
144
+ """
145
+ headers = req.get('headers')
146
+ bearer_token = self.token_manager.get_token()
147
+ headers['Authorization'] = 'Bearer {0}'.format(bearer_token)
148
+ logger.debug('Authenticated outbound request (type=%s)', self.authentication_type())
149
+
150
+ def set_scope_collection_type(self, scope_collection_type: str) -> None:
151
+ """Set the scope_collection_type value.
152
+
153
+ Args:
154
+ scope_collection_type: the value to set.
155
+
156
+ Raises:
157
+ TypeError: "scope_collection_type" must be a string.
158
+ """
159
+ if not isinstance(scope_collection_type, str):
160
+ raise TypeError('"scope_collection_type" must be a string')
161
+ self.token_manager.scope_collection_type = scope_collection_type
162
+
163
+ def set_scope_id(self, scope_id: str) -> None:
164
+ """Set the scope_id value.
165
+
166
+ Args:
167
+ scope_id: the value to set.
168
+
169
+ Raises:
170
+ TypeError: "scope_id" must be a string.
171
+ """
172
+ if not isinstance(scope_id, str):
173
+ raise TypeError('"scope_id" must be a string')
174
+ self.token_manager.scope_id = scope_id
175
+
176
+ def set_include_builtin_actions(self, include_builtin_actions: bool = False) -> None:
177
+ """Set the include_builtin_actions flag.
178
+
179
+ Args:
180
+ include_builtin_actions: The value to set (default: False).
181
+
182
+ Raises:
183
+ TypeError: "include_builtin_actions" must be a bool.
184
+ """
185
+ if not isinstance(include_builtin_actions, bool):
186
+ raise TypeError('"include_builtin_actions" must be a bool')
187
+ self.token_manager.include_builtin_actions = include_builtin_actions
188
+
189
+ def set_include_custom_actions(self, include_custom_actions: bool = False) -> None:
190
+ """Set the include_custom_actions flag.
191
+
192
+ Args:
193
+ include_custom_actions: The value to set (default: False).
194
+
195
+ Raises:
196
+ TypeError: "include_custom_actions" must be a bool.
197
+ """
198
+ if not isinstance(include_custom_actions, bool):
199
+ raise TypeError('"include_custom_actions" must be a bool')
200
+ self.token_manager.include_custom_actions = include_custom_actions
201
+
202
+ def set_include_roles(self, include_roles: bool = True) -> None:
203
+ """Set the include_roles flag.
204
+
205
+ Args:
206
+ include_roles: The value to set (default: True).
207
+
208
+ Raises:
209
+ TypeError: "include_roles" must be a bool.
210
+ """
211
+ if not isinstance(include_roles, bool):
212
+ raise TypeError('"include_roles" must be a bool')
213
+ self.token_manager.include_roles = include_roles
214
+
215
+ def set_prefix_roles(self, prefix_roles: bool = False) -> None:
216
+ """Set the prefix_roles flag.
217
+
218
+ Args:
219
+ prefix_roles: The value to set (default: False).
220
+
221
+ Raises:
222
+ TypeError: "prefix_roles" must be a bool.
223
+ """
224
+ if not isinstance(prefix_roles, bool):
225
+ raise TypeError('"prefix_roles" must be a bool')
226
+ self.token_manager.prefix_roles = prefix_roles
227
+
228
+ def set_caller_ext_claim(self, caller_ext_claim: Optional[Dict[str, str]] = None) -> None:
229
+ """Set the caller_ext_claim value.
230
+
231
+ Args:
232
+ caller_ext_claim: The value to set (default: False).
233
+
234
+ Raises:
235
+ TypeError: "caller_ext_claim" must be a dictionary or None.
236
+ """
237
+ if not isinstance(caller_ext_claim, (dict, type(None))):
238
+ raise TypeError('"caller_ext_claim" must be a dictionary or None')
239
+ self.token_manager.caller_ext_claim = caller_ext_claim
240
+
241
+ def set_disable_ssl_verification(self, disable_ssl_verification: bool = False) -> None:
242
+ """Set the disable_ssl_verification flag.
243
+
244
+ Args:
245
+ disable_ssl_verification: The value to set (default: False).
246
+
247
+ Raises:
248
+ TypeError: "disable_ssl_verification" must be a bool.
249
+ """
250
+ if not isinstance(disable_ssl_verification, bool):
251
+ raise TypeError('"disable_ssl_verification" must be a bool')
252
+ self.token_manager.disable_ssl_verification = disable_ssl_verification
253
+
254
+ def set_headers(self, headers: Optional[Dict[str, str]] = None) -> None:
255
+ """Set the headers to be sent with each MCSP token-exchange request.
256
+
257
+ Args:
258
+ headers: The headers to be sent with each MCSP token request (default: None).
259
+ """
260
+ self.token_manager.set_headers(headers)
261
+
262
+ def set_proxies(self, proxies: Optional[Dict[str, str]] = None) -> None:
263
+ """Sets the proxies the token manager will use to communicate with MCSP on behalf of the host.
264
+
265
+ Args:
266
+ proxies: Dictionary for mapping request protocol to proxy URL (default: None).
267
+ proxies.http (optional): The proxy endpoint to use for HTTP requests.
268
+ proxies.https (optional): The proxy endpoint to use for HTTPS requests.
269
+ """
270
+ self.token_manager.set_proxies(proxies)
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- # Copyright 2019, 2024 IBM All Rights Reserved.
3
+ # Copyright 2019, 2025 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.
@@ -14,6 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
+ import json
17
18
  from .authenticators import (
18
19
  Authenticator,
19
20
  BasicAuthenticator,
@@ -25,8 +26,9 @@ from .authenticators import (
25
26
  NoAuthAuthenticator,
26
27
  VPCInstanceAuthenticator,
27
28
  MCSPAuthenticator,
29
+ MCSPV2Authenticator,
28
30
  )
29
- from .utils import read_external_sources
31
+ from .utils import read_external_sources, string_to_bool
30
32
  from .logger import get_logger
31
33
 
32
34
  logger = get_logger()
@@ -57,6 +59,7 @@ def get_authenticator_from_environment(service_name: str) -> Authenticator:
57
59
 
58
60
 
59
61
  # pylint: disable=too-many-branches
62
+ # pylint: disable=too-many-statements
60
63
  def __construct_authenticator(config: dict) -> Authenticator:
61
64
  # Determine the authentication type if not specified explicitly.
62
65
  if config.get('AUTH_TYPE'):
@@ -86,7 +89,7 @@ def __construct_authenticator(config: dict) -> Authenticator:
86
89
  url=config.get('AUTH_URL'),
87
90
  client_id=config.get('CLIENT_ID'),
88
91
  client_secret=config.get('CLIENT_SECRET'),
89
- disable_ssl_verification=config.get('AUTH_DISABLE_SSL', 'false').lower() == 'true',
92
+ disable_ssl_verification=string_to_bool(config.get('AUTH_DISABLE_SSL', 'false')),
90
93
  scope=config.get('SCOPE'),
91
94
  )
92
95
  elif auth_type == Authenticator.AUTHTYPE_CP4D.lower():
@@ -95,7 +98,7 @@ def __construct_authenticator(config: dict) -> Authenticator:
95
98
  password=config.get('PASSWORD'),
96
99
  url=config.get('AUTH_URL'),
97
100
  apikey=config.get('APIKEY'),
98
- disable_ssl_verification=config.get('AUTH_DISABLE_SSL', 'false').lower() == 'true',
101
+ disable_ssl_verification=string_to_bool(config.get('AUTH_DISABLE_SSL', 'false')),
99
102
  )
100
103
  elif auth_type == Authenticator.AUTHTYPE_IAM.lower() and config.get('APIKEY'):
101
104
  authenticator = IAMAuthenticator(
@@ -103,7 +106,7 @@ def __construct_authenticator(config: dict) -> Authenticator:
103
106
  url=config.get('AUTH_URL'),
104
107
  client_id=config.get('CLIENT_ID'),
105
108
  client_secret=config.get('CLIENT_SECRET'),
106
- disable_ssl_verification=config.get('AUTH_DISABLE_SSL', 'false').lower() == 'true',
109
+ disable_ssl_verification=string_to_bool(config.get('AUTH_DISABLE_SSL', 'false')),
107
110
  scope=config.get('SCOPE'),
108
111
  )
109
112
  elif auth_type == Authenticator.AUTHTYPE_IAM_ASSUME.lower():
@@ -116,7 +119,7 @@ def __construct_authenticator(config: dict) -> Authenticator:
116
119
  url=config.get('AUTH_URL'),
117
120
  client_id=config.get('CLIENT_ID'),
118
121
  client_secret=config.get('CLIENT_SECRET'),
119
- disable_ssl_verification=config.get('AUTH_DISABLE_SSL', 'false').lower() == 'true',
122
+ disable_ssl_verification=string_to_bool(config.get('AUTH_DISABLE_SSL', 'false')),
120
123
  scope=config.get('SCOPE'),
121
124
  )
122
125
  elif auth_type == Authenticator.AUTHTYPE_VPC.lower():
@@ -130,6 +133,48 @@ def __construct_authenticator(config: dict) -> Authenticator:
130
133
  apikey=config.get('APIKEY'),
131
134
  url=config.get('AUTH_URL'),
132
135
  )
136
+ elif auth_type == Authenticator.AUTHTYPE_MCSPV2.lower():
137
+ # Required arguments.
138
+ apikey = config.get('APIKEY')
139
+ url = config.get('AUTH_URL')
140
+ scope_collection_type = config.get('SCOPE_COLLECTION_TYPE')
141
+ scope_id = config.get('SCOPE_ID')
142
+
143
+ # Optional arguments.
144
+ optional_args = {}
145
+ str_value = config.get("INCLUDE_BUILTIN_ACTIONS")
146
+ if str_value is not None:
147
+ optional_args['include_builtin_actions'] = string_to_bool(str_value)
148
+
149
+ str_value = config.get("INCLUDE_CUSTOM_ACTIONS")
150
+ if str_value is not None:
151
+ optional_args['include_custom_actions'] = string_to_bool(str_value)
152
+
153
+ str_value = config.get("INCLUDE_ROLES")
154
+ if str_value is not None:
155
+ optional_args['include_roles'] = string_to_bool(str_value)
156
+
157
+ str_value = config.get("PREFIX_ROLES")
158
+ if str_value is not None:
159
+ optional_args['prefix_roles'] = string_to_bool(str_value)
160
+
161
+ str_value = config.get("CALLER_EXT_CLAIM")
162
+ if str_value is not None:
163
+ try:
164
+ optional_args['caller_ext_claim'] = json.loads(str_value)
165
+ except Exception as caused_by:
166
+ msg = 'An error occurred while unmarshalling the CALLER_EXT_CLAIM configuration property: {0}'.format(
167
+ str_value
168
+ )
169
+ raise ValueError(msg) from caused_by
170
+
171
+ str_value = config.get("AUTH_DISABLE_SSL")
172
+ if str_value is not None:
173
+ optional_args['disable_ssl_verification'] = string_to_bool(str_value)
174
+
175
+ authenticator = MCSPV2Authenticator(
176
+ apikey=apikey, url=url, scope_collection_type=scope_collection_type, scope_id=scope_id, **optional_args
177
+ )
133
178
  elif auth_type == Authenticator.AUTHTYPE_NOAUTH.lower():
134
179
  authenticator = NoAuthAuthenticator()
135
180