Skip to content

Commit

Permalink
feat(MCSPAuthenticator): add new authenticator for Multi-Cloud Saas P…
Browse files Browse the repository at this point in the history
…latform

This commit introduces the new MCSPAuthenticator that can be used
to exchange an apikey for an MCSP access token using the Multi-Cloud Saas Platform
authentication token server's 'POST /siusermgr/api/1.0/apikeys/token' operation.

Signed-off-by: Phil Adams <[email protected]>
  • Loading branch information
padamstx committed Nov 8, 2023
1 parent 3466fcd commit 86d05af
Show file tree
Hide file tree
Showing 10 changed files with 1,355 additions and 22 deletions.
92 changes: 76 additions & 16 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "go.sum|package-lock.json|^.secrets.baseline$",
"lines": null
},
"generated_at": "2023-09-22T20:47:15Z",
"generated_at": "2023-11-06T17:25:56Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -247,26 +247,26 @@
"verified_result": null
},
{
"hashed_secret": "f2e7745f43b0ef0e2c2faf61d6c6a28be2965750",
"hashed_secret": "2a68d46242baf9214502d1dc240a9075a7c6ed55",
"is_secret": false,
"is_verified": false,
"line_number": 71,
"line_number": 79,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "2a68d46242baf9214502d1dc240a9075a7c6ed55",
"hashed_secret": "333f0f8814d63e7268f80e1e65e7549137d2350c",
"is_secret": false,
"is_verified": false,
"line_number": 79,
"line_number": 88,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "333f0f8814d63e7268f80e1e65e7549137d2350c",
"hashed_secret": "f2e7745f43b0ef0e2c2faf61d6c6a28be2965750",
"is_secret": false,
"is_verified": false,
"line_number": 88,
"line_number": 92,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down Expand Up @@ -320,15 +320,15 @@
"hashed_secret": "d4c3d66fd0c38547a3c7a4c6bdc29c36911bc030",
"is_secret": false,
"is_verified": false,
"line_number": 45,
"line_number": 46,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "8318df9ecda039deac9868adf1944a29a95c7114",
"is_secret": false,
"is_verified": false,
"line_number": 48,
"line_number": 49,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down Expand Up @@ -637,6 +637,66 @@
"verified_result": null
}
],
"core/mcsp_authenticator.go": [
{
"hashed_secret": "347cd9c53ff77d41a7b22aa56c7b4efaf54658e3",
"is_secret": false,
"is_verified": false,
"line_number": 279,
"type": "Secret Keyword",
"verified_result": null
}
],
"core/mcsp_authenticator_test.go": [
{
"hashed_secret": "fd08cd887ed1de2f2d3e175117ff607ca65187ae",
"is_secret": false,
"is_verified": false,
"line_number": 35,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "d03d939c22ad66a948ec8b4649add9b12b8a3cf6",
"is_secret": false,
"is_verified": false,
"line_number": 38,
"type": "JSON Web Token",
"verified_result": null
},
{
"hashed_secret": "5dcb6cb71ea20f1a58387e3d36d77bd123eb9f3b",
"is_secret": false,
"is_verified": false,
"line_number": 39,
"type": "JSON Web Token",
"verified_result": null
},
{
"hashed_secret": "65e496a8c40e0364f378688b5e612a2386ad38d1",
"is_secret": false,
"is_verified": false,
"line_number": 646,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "4c809455939f19c33c732b56a8417e509f4885e8",
"is_secret": false,
"is_verified": false,
"line_number": 647,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "32e8612d8ca77c7ea8374aa7918db8e5df9252ed",
"is_secret": false,
"is_verified": false,
"line_number": 669,
"type": "Secret Keyword",
"verified_result": null
}
],
"core/utils_test.go": [
{
"hashed_secret": "0266262f439c732a31b9353ced05c9e777a07c54",
Expand Down Expand Up @@ -741,34 +801,34 @@
"verified_result": null
},
{
"hashed_secret": "f2e7745f43b0ef0e2c2faf61d6c6a28be2965750",
"hashed_secret": "4e44e97dae1aa4e93c01536f48bbd8602133a86d",
"is_secret": false,
"is_verified": false,
"line_number": 54,
"line_number": 66,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "4e44e97dae1aa4e93c01536f48bbd8602133a86d",
"hashed_secret": "00cafd126182e8a9e7c01bb2f0dfd00496be724f",
"is_secret": false,
"is_verified": false,
"line_number": 66,
"line_number": 85,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "00cafd126182e8a9e7c01bb2f0dfd00496be724f",
"hashed_secret": "f2e7745f43b0ef0e2c2faf61d6c6a28be2965750",
"is_secret": false,
"is_verified": false,
"line_number": 85,
"line_number": 90,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "9e2659aa7e2b335ec6bdcf180f3b6f41f5191af5",
"is_secret": false,
"is_verified": false,
"line_number": 90,
"line_number": 96,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down
101 changes: 98 additions & 3 deletions Authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The go-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
- No Authentication (for testing)

The SDK user configures the appropriate type of authentication for use with service instances.
Expand Down Expand Up @@ -228,7 +229,7 @@ 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 IAM token service.

- Client: (Optional) The `http.Client` object used to invoke token servive requests. If not specified
- Client: (Optional) The `http.Client` object used to invoke token service requests. If not specified
by the user, a suitable default Client will be constructed.

### Usage Notes
Expand Down Expand Up @@ -367,7 +368,7 @@ 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 IAM token service.

- Client: (optional) The `http.Client` object used to invoke token servive requests. If not specified
- Client: (optional) The `http.Client` object used to invoke token service requests. If not specified
by the user, a suitable default Client will be constructed.

### Programming example
Expand Down Expand Up @@ -557,7 +558,7 @@ 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 Cloud Pak for Data token service.

- Client: (Optional) The `http.Client` object used to invoke token servive requests. If not specified
- Client: (Optional) The `http.Client` object used to invoke token service requests. If not specified
by the user, a suitable default Client will be constructed.

### Programming example
Expand Down Expand Up @@ -619,6 +620,100 @@ if err != nil {
```


## Multi-Cloud Saas Platform (MCSP) 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)
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. `/siusermgr/api/1.0/apikeys/token`) as part of this property's value.

- DisableSSLVerification: (optional) A flag that indicates whether verificaton 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.

- Client: (optional) The `http.Client` object used to invoke token service requests. If not specified
by the user, a suitable default Client will be constructed.

### Usage Notes
- When constructing an MCSPAuthenticator instance, you must specify the ApiKey and URL properties.

- The authenticator will use the token server's `POST /siusermgr/api/1.0/apikeys/token` operation to
exchange the user-supplied apikey for an MCSP access token (the bearer token).

### Programming example
```go
import {
"github.com/IBM/go-sdk-core/v5/core"
"<appropriate-git-repo-url>/exampleservicev1"
}
...
// Create the authenticator.
authenticator, err := core.NewMCSPAuthenticatorBuilder().
SetApiKey("myapikey").
SetURL("https://example.mcsp.token-exchange.com").
Build()
if err != nil {
panic(err)
}

// Create the service options struct.
options := &exampleservicev1.ExampleServiceV1Options{
Authenticator: authenticator,
}

// Construct the service instance.
service, err := exampleservicev1.NewExampleServiceV1(options)
if err != nil {
panic(err)
}

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

### Configuration example
External configuration:
```
export EXAMPLE_SERVICE_AUTH_TYPE=mcsp
export EXAMPLE_SERVICE_APIKEY=myapikey
export EXAMPLE_SERVICE_AUTH_URL=https://example.mcsp.token-exchange.com
```
Application code:
```go
import {
"<appropriate-git-repo-url>/exampleservicev1"
}
...

// Create the service options struct.
options := &exampleservicev1.ExampleServiceV1Options{
ServiceName: "example_service",
}

// Construct the service instance.
service, err := exampleservicev1.NewExampleServiceV1UsingExternalConfig(options)
if err != nil {
panic(err)
}

// '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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ The go-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
- No Authentication (for testing)

For more information about the various authentication types and how to use them with your services, click [here](Authentication.md).
Expand Down
4 changes: 3 additions & 1 deletion core/authenticator_factory.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package core

// (C) Copyright IBM Corp. 2019, 2021.
// (C) Copyright IBM Corp. 2019, 2023.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -58,6 +58,8 @@ func GetAuthenticatorFromEnvironment(credentialKey string) (authenticator Authen
authenticator, err = newVpcInstanceAuthenticatorFromMap(properties)
} else if strings.EqualFold(authType, AUTHTYPE_CP4D) {
authenticator, err = newCloudPakForDataAuthenticatorFromMap(properties)
} else if strings.EqualFold(authType, AUTHTYPE_MCSP) {
authenticator, err = newMCSPAuthenticatorFromMap(properties)
} else if strings.EqualFold(authType, AUTHTYPE_NOAUTH) {
authenticator, err = NewNoAuthAuthenticator()
} else {
Expand Down
25 changes: 24 additions & 1 deletion core/authenticator_factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

package core

// (C) Copyright IBM Corp. 2019.
// (C) Copyright IBM Corp. 2019, 2023.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -119,6 +119,18 @@ func TestGetAuthenticatorFromEnvironment1(t *testing.T) {
assert.Equal(t, "user1", iamAuth.ClientId)
assert.Equal(t, "secret1", iamAuth.ClientSecret)
assert.Equal(t, "https://iam.refresh-token.com", iamAuth.URL)

// MCSP Authenticator.
authenticator, err = GetAuthenticatorFromEnvironment("service10")
assert.Nil(t, err)
assert.NotNil(t, authenticator)
assert.Equal(t, AUTHTYPE_MCSP, authenticator.AuthenticationType())
mcspAuth, ok := authenticator.(*MCSPAuthenticator)
assert.True(t, ok)
assert.NotNil(t, mcspAuth)
assert.Equal(t, "my-api-key", mcspAuth.ApiKey)
assert.Equal(t, "https://mcsp.ibm.com", mcspAuth.URL)
assert.True(t, mcspAuth.DisableSSLVerification)
}

func TestGetAuthenticatorFromEnvironment2(t *testing.T) {
Expand Down Expand Up @@ -207,6 +219,17 @@ func TestGetAuthenticatorFromEnvironment2(t *testing.T) {
assert.True(t, ok)
assert.NotNil(t, containerAuth)
assert.Equal(t, "iam-user2", containerAuth.IAMProfileName)

authenticator, err = GetAuthenticatorFromEnvironment("service14")
assert.Nil(t, err)
assert.NotNil(t, authenticator)
assert.Equal(t, AUTHTYPE_MCSP, authenticator.AuthenticationType())
mcspAuth, ok := authenticator.(*MCSPAuthenticator)
assert.True(t, ok)
assert.NotNil(t, mcspAuth)
assert.Equal(t, "my-api-key", mcspAuth.ApiKey)
assert.Equal(t, "https://mcsp.ibm.com", mcspAuth.URL)
assert.True(t, mcspAuth.DisableSSLVerification)
}

func TestGetAuthenticatorFromEnvironment3(t *testing.T) {
Expand Down
4 changes: 4 additions & 0 deletions core/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ var testEnvironment = map[string]string{
"SERVICE11_AUTH_TYPE": "bad_auth_type",
"SERVICE12_APIKEY": "my-apikey",
"SERVICE13_IAM_PROFILE_NAME": "iam-user2",
"SERVICE14_AUTH_TYPE": "mcsp",
"SERVICE14_AUTH_URL": "https://mcsp.ibm.com",
"SERVICE14_APIKEY": "my-api-key",
"SERVICE14_AUTH_DISABLE_SSL": "true",
}

// setTestEnvironment sets the environment variables described in our map.
Expand Down
Loading

0 comments on commit 86d05af

Please sign in to comment.