Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# semantic-release is also run to create a new release (if
# warranted by the new commits being built).

name: Build/Test
name: build

on:
push:
Expand All @@ -16,7 +16,7 @@ on:
jobs:
detect-secrets:
if: "!contains(github.event.head_commit.message, '[skip ci]')"
name: Detect-Secrets
name: detect-secrets
runs-on: ubuntu-latest

steps:
Expand All @@ -38,8 +38,8 @@ jobs:
detect-secrets -v audit --report --fail-on-unaudited --fail-on-live --fail-on-audited-real .secrets.baseline

build:
name: build-test (python ${{ matrix.python-version }})
needs: detect-secrets
name: Build/Test (Python ${{ matrix.python-version }})

runs-on: ubuntu-latest
strategy:
Expand All @@ -59,8 +59,8 @@ jobs:
run: make ci

create-release:
name: semantic-release
needs: build
name: Semantic-Release
if: "github.ref_name == 'main' && github.event_name != 'pull_request'"
runs-on: ubuntu-latest

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# - building and publishing javadocs to the git repository.
# It is triggered when a new release is created.

name: Publish
name: publish
on:
release:
types: [created]
Expand All @@ -12,7 +12,7 @@ on:

jobs:
publish:
name: Publish Release
name: publish-pypi
runs-on: ubuntu-latest

steps:
Expand Down
3 changes: 2 additions & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ disable=
too-many-arguments,
unnecessary-pass,
no-member,
consider-using-f-string
consider-using-f-string,
too-many-instance-attributes

[TYPECHECK]
ignored-classes= responses
Expand Down
82 changes: 59 additions & 23 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "package-lock.json|^.secrets.baseline$",
"lines": null
},
"generated_at": "2025-01-09T21:56:01Z",
"generated_at": "2025-05-27T14:04:58Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -70,55 +70,55 @@
"hashed_secret": "91dfd9ddb4198affc5c194cd8ce6d338fde470e2",
"is_secret": false,
"is_verified": false,
"line_number": 66,
"line_number": 67,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "4f51cde3ac0a5504afa4bc06859b098366592c19",
"is_secret": false,
"is_verified": false,
"line_number": 207,
"line_number": 208,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "e87559ed7decb62d0733ae251ae58d42a55291d8",
"is_secret": false,
"is_verified": false,
"line_number": 209,
"line_number": 210,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "12f4a68ed3d0863e56497c9cdb1e2e4e91d5cb68",
"is_secret": false,
"is_verified": false,
"line_number": 273,
"line_number": 274,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "c837b75d7cd93ef9c2243ca28d6e5156259fd253",
"is_secret": false,
"is_verified": false,
"line_number": 277,
"line_number": 278,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "98635b2eaa2379f28cd6d72a38299f286b81b459",
"is_secret": false,
"is_verified": false,
"line_number": 502,
"line_number": 505,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "47fcf185ee7e15fe05cae31fbe9e4ebe4a06a40d",
"is_secret": false,
"is_verified": false,
"line_number": 597,
"line_number": 694,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down Expand Up @@ -213,6 +213,16 @@
"verified_result": null
}
],
"resources/ibm-credentials-mcspv2.env": [
{
"hashed_secret": "f2e7745f43b0ef0e2c2faf61d6c6a28be2965750",
"is_secret": false,
"is_verified": false,
"line_number": 23,
"type": "Secret Keyword",
"verified_result": null
}
],
"resources/ibm-credentials-retry.env": [
{
"hashed_secret": "ce49dd46e23153d6593eccd68534b9f1465d5bbd",
Expand Down Expand Up @@ -341,6 +351,40 @@
"verified_result": null
}
],
"test/test_get_authenticator.py": [
{
"hashed_secret": "34a0a47a51d5bf739df0214450385e29ee7e9847",
"is_secret": false,
"is_verified": false,
"line_number": 256,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "f2e7745f43b0ef0e2c2faf61d6c6a28be2965750",
"is_secret": false,
"is_verified": false,
"line_number": 267,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "2863fa4b5510c46afc2bd2998dfbc0cf3d6df032",
"is_secret": false,
"is_verified": false,
"line_number": 348,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "b9cad336062c0dc3bb30145b1a6697fccfe755a6",
"is_secret": false,
"is_verified": false,
"line_number": 409,
"type": "Secret Keyword",
"verified_result": null
}
],
"test/test_iam_assume_authenticator.py": [
{
"hashed_secret": "4080eeeaf54faf879b9e8d99c49a8503f7e855bb",
Expand Down Expand Up @@ -507,36 +551,28 @@
"verified_result": null
}
],
"test/test_utils.py": [
{
"hashed_secret": "34a0a47a51d5bf739df0214450385e29ee7e9847",
"is_secret": false,
"is_verified": false,
"line_number": 453,
"type": "Secret Keyword",
"verified_result": null
},
"test/test_mcspv2_authenticator.py": [
{
"hashed_secret": "f2e7745f43b0ef0e2c2faf61d6c6a28be2965750",
"is_secret": false,
"is_verified": false,
"line_number": 464,
"line_number": 15,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "2863fa4b5510c46afc2bd2998dfbc0cf3d6df032",
"hashed_secret": "da2f27d2c57a0e1ed2dc3a34b4ef02faf2f7a4c2",
"is_secret": false,
"is_verified": false,
"line_number": 545,
"type": "Secret Keyword",
"line_number": 246,
"type": "Hex High Entropy String",
"verified_result": null
},
{
"hashed_secret": "b9cad336062c0dc3bb30145b1a6697fccfe755a6",
"hashed_secret": "ace1a5bf229c3af3f699369c6f2fa1a628692ab8",
"is_secret": false,
"is_verified": false,
"line_number": 606,
"line_number": 392,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down
107 changes: 103 additions & 4 deletions Authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ The python-sdk-core project supports the following types of authentication:
- Container Authentication
- VPC Instance Authentication
- Cloud Pak for Data Authentication
- Multi-Cloud Saas Platform (MCSP) Authentication
- Multi-Cloud Saas Platform (MCSP) V1 Authentication
- Multi-Cloud Saas Platform (MCSP) V2 Authentication
- No Authentication (for testing)

The SDK user configures the appropriate type of authentication for use with service instances.
Expand Down Expand Up @@ -546,11 +547,11 @@ service = ExampleServiceV1.new_instance(service_name='example_service')
```


## Multi-Cloud Saas Platform (MCSP) Authentication
## Multi-Cloud Saas Platform (MCSP) V1 Authentication
The `MCSPAuthenticator` can be used in scenarios where an application needs to
interact with an IBM Cloud service that has been deployed to a non-IBM Cloud environment (e.g. AWS).
It accepts a user-supplied apikey and performs the necessary interactions with the
Multi-Cloud Saas Platform token service to obtain a suitable MCSP access token (a bearer token)
It accepts a user-supplied apikey and invokes the Multi-Cloud Saas Platform token service's
`POST /siusermgr/api/1.0/apikeys/token` operation to obtain a suitable MCSP access token (a bearer token)
for the specified apikey.
The authenticator will also obtain a new bearer token when the current token expires.
The bearer token is then added to each outbound request in the `Authorization` header in the
Expand Down Expand Up @@ -610,6 +611,104 @@ service = ExampleServiceV1.new_instance(service_name='example_service')
```


## Multi-Cloud Saas Platform (MCSP) V2 Authentication
The `MCSPV2Authenticator` can be used in scenarios where an application needs to
interact with an IBM Cloud service that has been deployed to a non-IBM Cloud environment (e.g. AWS).
It accepts a user-supplied apikey and invokes the Multi-Cloud Saas Platform token service's
`POST /api/2.0/{scopeCollectionType}/{scopeId}/apikeys/token` operation to obtain a suitable MCSP access token (a bearer token)
for the specified apikey.
The authenticator will also obtain a new bearer token when the current token expires.
The bearer token is then added to each outbound request in the `Authorization` header in the
form:
```
Authorization: Bearer <bearer-token>
```

### Properties

- apikey: (required) The apikey to be used to obtain an MCSP access token.

- url: (required) The URL representing the MCSP token service endpoint's base URL string. Do not include the
operation path (e.g. `/api/2.0/{scopeCollectionType}/{scopeId}/apikeys/token`) as part of this property's value.

- scope_collection_type: (required) The scope collection type of item(s).
The valid values are: `accounts`, `subscriptions`, `services`.

- scope_id: (required) The scope identifier of item(s).

- include_builtin_actions: (optional) A flag to include builtin actions in the `actions` claim in the MCSP token (default: false).

- include_custom_actions: (optional) A flag to include custom actions in the `actions` claim in the MCSP token (default: false).

- include_roles: (optional) A flag to include the `roles` claim in the MCSP token (default: true).

- prefix_roles: (optional) A flag to add a prefix with the scope level where
the role is defined in the `roles` claim (default: false).

- caller_ext_claim: (optional) A map containing keys and values to be injected into the returned access token
as the `callerExt` claim. The keys used in this map must be enabled in the apikey by setting the
`callerExtClaimNames` property when the apikey is created.
This property is typically only used in scenarios involving an apikey with identityType `SERVICEID`.

- disable_ssl_verification: (optional) A flag that indicates whether verification of the server's SSL
certificate should be disabled or not. The default value is `false`.

- headers: (optional) A set of key/value pairs that will be sent as HTTP headers in requests
made to the MCSP token service.

### Usage Notes
- When constructing an MCSPV2Authenticator instance, the apikey, url, scope_collection_type, and scope_id properties are required.

- If you specify the caller_ext_claim map, the keys used in the map must have been previously enabled in the apikey
by setting the `callerExtClaimNames` property when you created the apikey.
The entries contained in this map will appear in the `callerExt` field (claim) of the returned access token.

- The authenticator will invoke the token server's `POST /api/2.0/{scopeCollectionType}/{scopeId}/apikeys/token` operation to
exchange the apikey for an MCSP access token (the bearer token).

### Programming example
```python
from ibm_cloud_sdk_core.authenticators import MCSPV2Authenticator
from <sdk-package-name>.example_service_v1 import *

# Create the authenticator.
authenticator = MCSPV2Authenticator(
apikey='myapikey',
url='https://example.mcspv2.token-exchange.com',
scope_collection_type='accounts',
scope_id='20250519-2128-3755-60b3-103e01c509e8',
include_builtin_actions=True,
caller_ext_claim={'productID': 'prod-123'},
)

# Construct the service instance.
service = ExampleServiceV1(authenticator=authenticator)

# 'service' can now be used to invoke operations.
```

### Configuration example
External configuration:
```
export EXAMPLE_SERVICE_AUTH_TYPE=mcspv2
export EXAMPLE_SERVICE_APIKEY=myapikey
export EXAMPLE_SERVICE_AUTH_URL=https://example.mcspv2.token-exchange.com
export EXAMPLE_SERVICE_SCOPE_COLLECTION_TYPE=accounts
export EXAMPLE_SERVICE_SCOPE_ID=20250519-2128-3755-60b3-103e01c509e8
export EXAMPLE_SERVICE_INCLUDE_BUILTIN_ACTIONS=true
export EXAMPLE_SERVICE_CALLER_EXT_CLAIM={"productID":"prod-123"}
```
Application code:
```python
from <sdk-package-name>.example_service_v1 import *

# Construct the service instance.
service = ExampleServiceV1.new_instance(service_name='example_service')

# 'service' can now be used to invoke operations.
```


## No Auth Authentication
The `NoAuthAuthenticator` is a placeholder authenticator which performs no actual authentication function.
It can be used in situations where authentication needs to be bypassed, perhaps while developing
Expand Down
1 change: 1 addition & 0 deletions ibm_cloud_sdk_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
from .token_managers.container_token_manager import ContainerTokenManager
from .token_managers.vpc_instance_token_manager import VPCInstanceTokenManager
from .token_managers.mcsp_token_manager import MCSPTokenManager
from .token_managers.mcspv2_token_manager import MCSPV2TokenManager
from .api_exception import ApiException
from .utils import datetime_to_string, string_to_datetime, read_external_sources
from .utils import datetime_to_string_list, string_to_datetime_list
Expand Down
6 changes: 6 additions & 0 deletions ibm_cloud_sdk_core/authenticators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,14 @@
Authenticator: Abstract Base Class. Implement this interface to provide custom authentication schemes to services.
BasicAuthenticator: Authenticator for passing supplied basic authentication information to service endpoint.
BearerTokenAuthenticator: Authenticator for passing supplied bearer token to service endpoint.
ContainerAuthenticator: Authenticator for use in a container environment.
CloudPakForDataAuthenticator: Authenticator for passing CP4D authentication information to service endpoint.
IAMAuthenticator: Authenticator for passing IAM authentication information to service endpoint.
IAMAssumeAuthenticator: Authenticator for the "assume" grant type.
VPCInstanceAuthenticator: Authenticator for use within a VPC instance.
NoAuthAuthenticator: Performs no authentication. Useful for testing purposes.
MCSPAuthenticator: Authenticator that supports the MCSP v1 token exchange.
MCSPV2Authenticator: Authenticator that supports the MCSP v2 token exchange.
"""

from .authenticator import Authenticator
Expand All @@ -43,3 +48,4 @@
from .vpc_instance_authenticator import VPCInstanceAuthenticator
from .no_auth_authenticator import NoAuthAuthenticator
from .mcsp_authenticator import MCSPAuthenticator
from .mcspv2_authenticator import MCSPV2Authenticator
Loading