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 (#258)

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 authored Nov 15, 2023
1 parent 540600f commit 4fe7f71
Show file tree
Hide file tree
Showing 14 changed files with 631 additions and 14 deletions.
66 changes: 57 additions & 9 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": "2023-06-22T15:14:17Z",
"generated_at": "2023-11-09T19:29:53Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -70,23 +70,23 @@
"hashed_secret": "91dfd9ddb4198affc5c194cd8ce6d338fde470e2",
"is_secret": false,
"is_verified": false,
"line_number": 73,
"line_number": 74,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "98635b2eaa2379f28cd6d72a38299f286b81b459",
"is_secret": false,
"is_verified": false,
"line_number": 432,
"line_number": 433,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "47fcf185ee7e15fe05cae31fbe9e4ebe4a06a40d",
"is_secret": false,
"is_verified": false,
"line_number": 470,
"line_number": 543,
"type": "Secret Keyword",
"verified_result": null
}
Expand All @@ -96,7 +96,7 @@
"hashed_secret": "bc2f74c22f98f7b6ffbc2f67453dbfa99bce9a32",
"is_secret": false,
"is_verified": false,
"line_number": 55,
"line_number": 97,
"type": "Secret Keyword",
"verified_result": null
}
Expand All @@ -106,7 +106,7 @@
"hashed_secret": "32e8612d8ca77c7ea8374aa7918db8e5df9252ed",
"is_secret": false,
"is_verified": false,
"line_number": 62,
"line_number": 63,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down Expand Up @@ -185,6 +185,16 @@
"verified_result": null
}
],
"auth/authenticators/mcsp-authenticator.ts": [
{
"hashed_secret": "8f4bfc22c4fd7cb884f94ec175ff4a3284a174a1",
"is_secret": false,
"is_verified": false,
"line_number": 60,
"type": "Secret Keyword",
"verified_result": null
}
],
"auth/token-managers/container-token-manager.ts": [
{
"hashed_secret": "184ee1f04a018aa3b897e085516a9b657fea0f6b",
Expand Down Expand Up @@ -281,12 +291,30 @@
"verified_result": null
}
],
"auth/token-managers/mcsp-token-manager.ts": [
{
"hashed_secret": "8f4bfc22c4fd7cb884f94ec175ff4a3284a174a1",
"is_secret": false,
"is_verified": false,
"line_number": 78,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "65e622227634e8876cfa733000233fb80c6f0473",
"is_secret": false,
"is_verified": false,
"line_number": 91,
"type": "Secret Keyword",
"verified_result": null
}
],
"auth/utils/get-authenticator-from-environment.ts": [
{
"hashed_secret": "6947818ac409551f11fbaa78f0ea6391960aa5b8",
"is_secret": false,
"is_verified": false,
"line_number": 49,
"line_number": 50,
"type": "Secret Keyword",
"verified_result": null
}
Expand All @@ -306,7 +334,7 @@
"hashed_secret": "45c43fe97e3a06ab078b0eeff6fbe622cc417a25",
"is_secret": false,
"is_verified": false,
"line_number": 279,
"line_number": 283,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down Expand Up @@ -499,6 +527,26 @@
"verified_result": null
}
],
"test/unit/mcsp-authenticator.test.js": [
{
"hashed_secret": "0c910ad3070d996b37a1c65f542b17adc3f962bc",
"is_secret": false,
"is_verified": false,
"line_number": 20,
"type": "Secret Keyword",
"verified_result": null
}
],
"test/unit/mcsp-token-manager.test.js": [
{
"hashed_secret": "f2e7745f43b0ef0e2c2faf61d6c6a28be2965750",
"is_secret": false,
"is_verified": false,
"line_number": 30,
"type": "Secret Keyword",
"verified_result": null
}
],
"test/unit/read-external-sources.test.js": [
{
"hashed_secret": "4c65cd3f160d60f7ca28ca04fa60b9035132781c",
Expand Down Expand Up @@ -534,7 +582,7 @@
}
]
},
"version": "0.13.1+ibm.60.dss",
"version": "0.13.1+ibm.61.dss",
"word_list": {
"file": null,
"hash": null
Expand Down
73 changes: 73 additions & 0 deletions Authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The node-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 @@ -484,6 +485,78 @@ const service = ExampleServiceV1.newInstance(options);
```


## 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.

### 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
```js
const { McspAuthenticator } = require('ibm-cloud-sdk-core');
const ExampleServiceV1 = require('<sdk-package-name>/example-service/v1');

const authenticator = new McspAuthenticator({
apikey: 'myapikey',
url: 'https://example.mcsp.token-exchange.com',
});

const options = {
authenticator,
};

const service = new ExampleServiceV1(options);

// '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:
```js
const ExampleServiceV1 = require('<sdk-package-name>/example-service/v1');

const options = {
serviceName: 'example_service',
};

const service = ExampleServiceV1.newInstance(options);

// '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
4 changes: 3 additions & 1 deletion auth/authenticators/authenticator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars, class-methods-use-this */

/**
* (C) Copyright IBM Corp. 2019, 2022.
* (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 @@ -40,6 +40,8 @@ export class Authenticator implements AuthenticatorInterface {

static AUTHTYPE_VPC = 'vpc';

static AUTHTYPE_MCSP = 'mcsp';

static AUTHTYPE_UNKNOWN = 'unknown';

/**
Expand Down
2 changes: 2 additions & 0 deletions auth/authenticators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
* IAMAuthenticator: Authenticator for passing IAM authentication information to service endpoint.
* ContainerAuthenticator: Authenticator for passing IAM authentication to a service, based on a token living on the container.
* VpcInstanceAuthenticator: Authenticator that uses the VPC Instance Metadata Service API to retrieve an IAM token.
* McspAuthenticator: Authenticator for passing MCSP authentication to a service endpoint.
* NoAuthAuthenticator: Performs no authentication. Useful for testing purposes.
*/

Expand All @@ -52,3 +53,4 @@ export { NoAuthAuthenticator } from './no-auth-authenticator';
export { IamRequestBasedAuthenticator } from './iam-request-based-authenticator';
export { TokenRequestBasedAuthenticator } from './token-request-based-authenticator';
export { VpcInstanceAuthenticator } from './vpc-instance-authenticator';
export { McspAuthenticator } from './mcsp-authenticator';
78 changes: 78 additions & 0 deletions auth/authenticators/mcsp-authenticator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* (C) Copyright IBM Corp. 2023.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Authenticator } from './authenticator';
import { McspTokenManager } from '../token-managers/mcsp-token-manager';
import { BaseOptions, TokenRequestBasedAuthenticator } from './token-request-based-authenticator';

/** Configuration options for Multi-Cloud Saas Platform (MCSP) authentication. */
export interface Options extends BaseOptions {
/** The API key used to obtain an MCSP access token. */
apikey: string;
/** The URL representing the MCSP token service endpoint. */
url: string;
}

/**
* The McspAuthenticator uses an apikey to obtain an access token from the MCSP token server.
* When the access token expires, a new access token is obtained from the token server.
* The access token will be added to outbound requests via the Authorization header
* of the form: "Authorization: Bearer <access-token>"
*/
export class McspAuthenticator extends TokenRequestBasedAuthenticator {
protected requiredOptions = ['apikey', 'url'];

protected tokenManager: McspTokenManager;

private apikey: string;

/**
* Create a new McspAuthenticator instance.
*
* @param options - Configuration options for CloudPakForData authentication.
* This should be an object containing these fields:
* - url: (required) the endpoint URL for the CloudPakForData token service
* - username: (required) the username used to obtain a bearer token
* - password: (optional) the password used to obtain a bearer token (required if apikey is not specified)
* - apikey: (optional) the API key used to obtain a bearer token (required if password is not specified)
* - disableSslVerification: (optional) a flag that indicates whether verification of the token server's SSL certificate
* should be disabled or not
* - headers: (optional) a set of HTTP headers to be sent with each request to the token service
*
* @throws Error: the username, password, and/or url are not valid, or unspecified, for Cloud Pak For Data token requests.
*/
constructor(options: Options) {
super(options);

this.apikey = options.apikey;
this.url = options.url;

// the param names are shared between the authenticator and the token
// manager so we can just pass along the options object.
// also, the token manager will handle input validation
this.tokenManager = new McspTokenManager(options);
}

/**
* Returns the authenticator's type ('cp4d').
*
* @returns a string that indicates the authenticator's type
*/
// eslint-disable-next-line class-methods-use-this
public authenticationType(): string {
return Authenticator.AUTHTYPE_MCSP;
}
}
7 changes: 5 additions & 2 deletions auth/token-managers/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* (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 All @@ -22,15 +22,17 @@
* Cloud Pak for Data
* Container (IKS, etc)
* VPC Instance
* Multi-Cloud Saas Platform (MCSP)
*
* The token managers sit inside of an authenticator and do the work to retrieve
* tokens where as the authenticators add these tokens to the actual request.
* tokens, whereas the authenticators add these tokens to the actual request.
*
* classes:
* IamTokenManager: Token Manager of IAM via apikey.
* Cp4dTokenManager: Token Manager of CloudPak for data.
* ContainerTokenManager: Token manager of IAM via compute resource token.
* VpcInstanceTokenManager: Token manager of VPC Instance Metadata Service API tokens.
* McspTokenManager: Token Manager of MCSP via apikey.
* JwtTokenManager: A class for shared functionality for parsing, storing, and requesting JWT tokens.
*/

Expand All @@ -41,3 +43,4 @@ export { IamRequestBasedTokenManager, IamRequestOptions } from './iam-request-ba
export { JwtTokenManager, JwtTokenManagerOptions } from './jwt-token-manager';
export { TokenManager, TokenManagerOptions } from './token-manager';
export { VpcInstanceTokenManager } from './vpc-instance-token-manager';
export { McspTokenManager } from './mcsp-token-manager';
Loading

0 comments on commit 4fe7f71

Please sign in to comment.