From 467c0adf6ef073c341a54efc749c93c5a0ac2246 Mon Sep 17 00:00:00 2001 From: Phil Adams Date: Mon, 31 Aug 2020 16:53:22 -0500 Subject: [PATCH] feat(Configuration Governance): add service to project (#42) Co-authored-by: Jorge Rangel Co-authored-by: Mike Kistler --- .gitignore | 1 + README.md | 1 + configuration-governance/v1.ts | 1302 +++++++++++++++++ examples/configuration-governance.v1.test.js | 409 ++++++ scripts/typedoc/generate_typedoc.sh | 1 + .../configuration-governance.v1.test.js | 1049 +++++++++++++ test/unit/configuration-governance.v1.test.js | 1011 +++++++++++++ 7 files changed, 3774 insertions(+) create mode 100644 configuration-governance/v1.ts create mode 100644 examples/configuration-governance.v1.test.js create mode 100644 test/integration/configuration-governance.v1.test.js create mode 100644 test/unit/configuration-governance.v1.test.js diff --git a/.gitignore b/.gitignore index 96f0830f..9c3917af 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ lib/*.js # service-name/*.js // UNCOMMENT AND ADD YOUR OWN SERVICE FILES case-management/*.js catalog-management/*.js +configuration-governance/*.js enterprise-management/*.js global-catalog/*.js global-search/*.js diff --git a/README.md b/README.md index a52d5f41..2e73645a 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ Service Name | Import Path --- | --- [Case Management](https://cloud.ibm.com/apidocs/case-management) | ibm-platform-services/case-management/v1 [Catalog Management](https://cloud.ibm.com/apidocs/resource-catalog/private-catalog) | ibm-platform-services/catalog-management/v1 +[Configuration Governance](https://cloud.ibm.com/apidocs/security-compliance/config) | ibm-platform-services/configuration-governance/v1 [Enterprise Management](https://cloud.ibm.com/apidocs/enterprise-apis/enterprise) | ibm-platform-services/enterprise-management/v1 [Global Catalog](https://cloud.ibm.com/apidocs/resource-catalog/global-catalog) | ibm-platform-services/global-catalog/v1 [Global Search](https://cloud.ibm.com/apidocs/search) | ibm-platform-services/global-search/v2 diff --git a/configuration-governance/v1.ts b/configuration-governance/v1.ts new file mode 100644 index 00000000..8c6fa0dd --- /dev/null +++ b/configuration-governance/v1.ts @@ -0,0 +1,1302 @@ +/** + * (C) Copyright IBM Corp. 2020. + * + * 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. + */ + +/** + * IBM OpenAPI SDK Code Generator Version: 99-SNAPSHOT-68ee7c8f-20200829-062726 + */ + + +import * as extend from 'extend'; +import { IncomingHttpHeaders, OutgoingHttpHeaders } from 'http'; +import { Authenticator, BaseService, getAuthenticatorFromEnvironment, getMissingParams, UserOptions } from 'ibm-cloud-sdk-core'; +import { getSdkHeaders } from '../lib/common'; + +/** + * API specification for the Configuration Governance service. + */ + +class ConfigurationGovernanceV1 extends BaseService { + + static DEFAULT_SERVICE_URL: string = 'https://compliance.cloud.ibm.com'; + static DEFAULT_SERVICE_NAME: string = 'configuration_governance'; + + /************************* + * Factory method + ************************/ + + /** + * Constructs an instance of ConfigurationGovernanceV1 with passed in options and external configuration. + * + * @param {UserOptions} [options] - The parameters to send to the service. + * @param {string} [options.serviceName] - The name of the service to configure + * @param {Authenticator} [options.authenticator] - The Authenticator object used to authenticate requests to the service + * @param {string} [options.serviceUrl] - The URL for the service + * @returns {ConfigurationGovernanceV1} + */ + + public static newInstance(options: UserOptions): ConfigurationGovernanceV1 { + options = options || {}; + + if (!options.serviceName) { + options.serviceName = this.DEFAULT_SERVICE_NAME; + } + if (!options.authenticator) { + options.authenticator = getAuthenticatorFromEnvironment(options.serviceName); + } + const service = new ConfigurationGovernanceV1(options); + service.configureService(options.serviceName); + if (options.serviceUrl) { + service.setServiceUrl(options.serviceUrl); + } + return service; + } + + + /** + * Construct a ConfigurationGovernanceV1 object. + * + * @param {Object} options - Options for the service. + * @param {string} [options.serviceUrl] - The base url to use when contacting the service (e.g. 'https://gateway.watsonplatform.net'). The base url may differ between IBM Cloud regions. + * @param {OutgoingHttpHeaders} [options.headers] - Default headers that shall be included with every request to the service. + * @param {Authenticator} options.authenticator - The Authenticator object used to authenticate requests to the service + * @constructor + * @returns {ConfigurationGovernanceV1} + */ + constructor(options: UserOptions) { + options = options || {}; + + super(options); + if (options.serviceUrl) { + this.setServiceUrl(options.serviceUrl); + } else { + this.setServiceUrl(ConfigurationGovernanceV1.DEFAULT_SERVICE_URL); + } + } + + /************************* + * rules + ************************/ + + /** + * Create rules. + * + * Creates one or more rules that you can use to govern the way that IBM Cloud resources can be provisioned and + * configured. + * + * A successful `POST /config/rules` request defines a rule based on the target, conditions, and enforcement actions + * that you specify. The response returns the ID value for your rule, along with other metadata. + * + * @param {Object} params - The parameters to send to the service. + * @param {CreateRuleRequest[]} params.rules - A list of rules to be created. + * @param {string} [params.transactionId] - The unique identifier that is used to trace an entire request. If you omit + * this field, the service generates and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `Transaction-Id` + * with each request. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public createRules(params: ConfigurationGovernanceV1.CreateRulesParams): Promise> { + const _params = Object.assign({}, params); + const requiredParams = ['rules']; + + return new Promise((resolve, reject) => { + const missingParams = getMissingParams(_params, requiredParams); + if (missingParams) { + return reject(missingParams); + } + + const body = { + 'rules': _params.rules + }; + + const sdkHeaders = getSdkHeaders(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME, 'v1', 'createRules'); + + const parameters = { + options: { + url: '/config/v1/rules', + method: 'POST', + body, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend(true, sdkHeaders, { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Transaction-Id': _params.transactionId + }, _params.headers), + }), + }; + + return resolve(this.createRequest(parameters)); + }); + }; + + /** + * List rules. + * + * Retrieves a list of the rules that are available in your account. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.accountId - Your IBM Cloud account ID. + * @param {string} [params.transactionId] - The unique identifier that is used to trace an entire request. If you omit + * this field, the service generates and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `Transaction-Id` + * with each request. + * @param {boolean} [params.attached] - Retrieves a list of rules that have scope attachments. + * @param {string} [params.labels] - Retrieves a list of rules that match the labels that you specify. + * @param {string} [params.scopes] - Retrieves a list of rules that match the scope ID that you specify. + * @param {number} [params.limit] - The number of resources to retrieve. By default, list operations return the first + * 100 items. To retrieve a different set of items, use `limit` with `offset` to page through your available + * resources. + * + * **Usage:** If you have 20 rules, and you want to retrieve only the first 5 rules, use + * `../rules?account_id={account_id}&limit=5`. + * @param {number} [params.offset] - The number of resources to skip. By specifying `offset`, you retrieve a subset of + * resources that starts with the `offset` value. Use `offset` with `limit` to page through your available resources. + * + * **Usage:** If you have 100 rules, and you want to retrieve rules 26 through 50, use + * `../rules?account_id={account_id}&offset=25&limit=5`. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public listRules(params: ConfigurationGovernanceV1.ListRulesParams): Promise> { + const _params = Object.assign({}, params); + const requiredParams = ['accountId']; + + return new Promise((resolve, reject) => { + const missingParams = getMissingParams(_params, requiredParams); + if (missingParams) { + return reject(missingParams); + } + + const query = { + 'account_id': _params.accountId, + 'attached': _params.attached, + 'labels': _params.labels, + 'scopes': _params.scopes, + 'limit': _params.limit, + 'offset': _params.offset + }; + + const sdkHeaders = getSdkHeaders(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME, 'v1', 'listRules'); + + const parameters = { + options: { + url: '/config/v1/rules', + method: 'GET', + qs: query, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend(true, sdkHeaders, { + 'Accept': 'application/json', + 'Transaction-Id': _params.transactionId + }, _params.headers), + }), + }; + + return resolve(this.createRequest(parameters)); + }); + }; + + /** + * Get a rule. + * + * Retrieves an existing rule and its details. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.ruleId - The UUID that uniquely identifies the rule. + * @param {string} [params.transactionId] - The unique identifier that is used to trace an entire request. If you omit + * this field, the service generates and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `Transaction-Id` + * with each request. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public getRule(params: ConfigurationGovernanceV1.GetRuleParams): Promise> { + const _params = Object.assign({}, params); + const requiredParams = ['ruleId']; + + return new Promise((resolve, reject) => { + const missingParams = getMissingParams(_params, requiredParams); + if (missingParams) { + return reject(missingParams); + } + + const path = { + 'rule_id': _params.ruleId + }; + + const sdkHeaders = getSdkHeaders(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME, 'v1', 'getRule'); + + const parameters = { + options: { + url: '/config/v1/rules/{rule_id}', + method: 'GET', + path, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend(true, sdkHeaders, { + 'Accept': 'application/json', + 'Transaction-Id': _params.transactionId + }, _params.headers), + }), + }; + + return resolve(this.createRequest(parameters)); + }); + }; + + /** + * Update a rule. + * + * Updates an existing rule based on the properties that you specify. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.ruleId - The UUID that uniquely identifies the rule. + * @param {string} params.ifMatch - Compares a supplied `Etag` value with the version that is stored for the requested + * resource. If the values match, the server allows the request method to continue. + * + * To find the `Etag` value, run a GET request on the resource that you want to modify, and check the response + * headers. + * @param {string} params.name - A human-readable alias to assign to your rule. + * @param {string} params.description - An extended description of your rule. + * @param {TargetResource} params.target - The properties that describe the resource that you want to target + * with the rule. + * @param {RuleRequiredConfig} params.requiredConfig - + * @param {EnforcementAction[]} params.enforcementActions - The actions that the service must run on your behalf when + * a request to create or modify the target resource does not comply with your conditions. + * @param {string} [params.accountId] - Your IBM Cloud account ID. + * @param {string} [params.ruleType] - The type of rule. Rules that you create are `user_defined`. + * @param {string[]} [params.labels] - Labels that you can use to group and search for similar rules, such as those + * that help you to meet a specific organization guideline. + * @param {string} [params.transactionId] - The unique identifier that is used to trace an entire request. If you omit + * this field, the service generates and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `Transaction-Id` + * with each request. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public updateRule(params: ConfigurationGovernanceV1.UpdateRuleParams): Promise> { + const _params = Object.assign({}, params); + const requiredParams = ['ruleId', 'ifMatch', 'name', 'description', 'target', 'requiredConfig', 'enforcementActions']; + + return new Promise((resolve, reject) => { + const missingParams = getMissingParams(_params, requiredParams); + if (missingParams) { + return reject(missingParams); + } + + const body = { + 'name': _params.name, + 'description': _params.description, + 'target': _params.target, + 'required_config': _params.requiredConfig, + 'enforcement_actions': _params.enforcementActions, + 'account_id': _params.accountId, + 'rule_type': _params.ruleType, + 'labels': _params.labels + }; + + const path = { + 'rule_id': _params.ruleId + }; + + const sdkHeaders = getSdkHeaders(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME, 'v1', 'updateRule'); + + const parameters = { + options: { + url: '/config/v1/rules/{rule_id}', + method: 'PUT', + body, + path, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend(true, sdkHeaders, { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'If-Match': _params.ifMatch, + 'Transaction-Id': _params.transactionId + }, _params.headers), + }), + }; + + return resolve(this.createRequest(parameters)); + }); + }; + + /** + * Delete a rule. + * + * Deletes an existing rule. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.ruleId - The UUID that uniquely identifies the rule. + * @param {string} [params.transactionId] - The unique identifier that is used to trace an entire request. If you omit + * this field, the service generates and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `Transaction-Id` + * with each request. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public deleteRule(params: ConfigurationGovernanceV1.DeleteRuleParams): Promise> { + const _params = Object.assign({}, params); + const requiredParams = ['ruleId']; + + return new Promise((resolve, reject) => { + const missingParams = getMissingParams(_params, requiredParams); + if (missingParams) { + return reject(missingParams); + } + + const path = { + 'rule_id': _params.ruleId + }; + + const sdkHeaders = getSdkHeaders(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME, 'v1', 'deleteRule'); + + const parameters = { + options: { + url: '/config/v1/rules/{rule_id}', + method: 'DELETE', + path, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend(true, sdkHeaders, { + 'Transaction-Id': _params.transactionId + }, _params.headers), + }), + }; + + return resolve(this.createRequest(parameters)); + }); + }; + + /** + * Create attachments. + * + * Creates one or more scope attachments for an existing rule. + * + * You can attach an existing rule to a scope, such as a specific IBM Cloud account, to start evaluating the rule for + * compliance. A successful + * `POST /config/v1/rules/{rule_id}/attachments` returns the ID value for the attachment, along with other metadata. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.ruleId - The UUID that uniquely identifies the rule. + * @param {AttachmentRequest[]} params.attachments - + * @param {string} [params.transactionId] - The unique identifier that is used to trace an entire request. If you omit + * this field, the service generates and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `Transaction-Id` + * with each request. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public createAttachments(params: ConfigurationGovernanceV1.CreateAttachmentsParams): Promise> { + const _params = Object.assign({}, params); + const requiredParams = ['ruleId', 'attachments']; + + return new Promise((resolve, reject) => { + const missingParams = getMissingParams(_params, requiredParams); + if (missingParams) { + return reject(missingParams); + } + + const body = { + 'attachments': _params.attachments + }; + + const path = { + 'rule_id': _params.ruleId + }; + + const sdkHeaders = getSdkHeaders(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME, 'v1', 'createAttachments'); + + const parameters = { + options: { + url: '/config/v1/rules/{rule_id}/attachments', + method: 'POST', + body, + path, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend(true, sdkHeaders, { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Transaction-Id': _params.transactionId + }, _params.headers), + }), + }; + + return resolve(this.createRequest(parameters)); + }); + }; + + /** + * List attachments. + * + * Retrieves a list of scope attachments that are associated with the specified rule. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.ruleId - The UUID that uniquely identifies the rule. + * @param {string} [params.transactionId] - The unique identifier that is used to trace an entire request. If you omit + * this field, the service generates and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `Transaction-Id` + * with each request. + * @param {number} [params.limit] - The number of resources to retrieve. By default, list operations return the first + * 100 items. To retrieve a different set of items, use `limit` with `offset` to page through your available + * resources. + * + * **Usage:** If you have 20 rules, and you want to retrieve only the first 5 rules, use + * `../rules?account_id={account_id}&limit=5`. + * @param {number} [params.offset] - The number of resources to skip. By specifying `offset`, you retrieve a subset of + * resources that starts with the `offset` value. Use `offset` with `limit` to page through your available resources. + * + * **Usage:** If you have 100 rules, and you want to retrieve rules 26 through 50, use + * `../rules?account_id={account_id}&offset=25&limit=5`. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public listAttachments(params: ConfigurationGovernanceV1.ListAttachmentsParams): Promise> { + const _params = Object.assign({}, params); + const requiredParams = ['ruleId']; + + return new Promise((resolve, reject) => { + const missingParams = getMissingParams(_params, requiredParams); + if (missingParams) { + return reject(missingParams); + } + + const query = { + 'limit': _params.limit, + 'offset': _params.offset + }; + + const path = { + 'rule_id': _params.ruleId + }; + + const sdkHeaders = getSdkHeaders(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME, 'v1', 'listAttachments'); + + const parameters = { + options: { + url: '/config/v1/rules/{rule_id}/attachments', + method: 'GET', + qs: query, + path, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend(true, sdkHeaders, { + 'Accept': 'application/json', + 'Transaction-Id': _params.transactionId + }, _params.headers), + }), + }; + + return resolve(this.createRequest(parameters)); + }); + }; + + /** + * Get an attachment. + * + * Retrieves an existing scope attachment for a rule. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.ruleId - The UUID that uniquely identifies the rule. + * @param {string} params.attachmentId - The UUID that uniquely identifies the attachment. + * @param {string} [params.transactionId] - The unique identifier that is used to trace an entire request. If you omit + * this field, the service generates and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `Transaction-Id` + * with each request. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public getAttachment(params: ConfigurationGovernanceV1.GetAttachmentParams): Promise> { + const _params = Object.assign({}, params); + const requiredParams = ['ruleId', 'attachmentId']; + + return new Promise((resolve, reject) => { + const missingParams = getMissingParams(_params, requiredParams); + if (missingParams) { + return reject(missingParams); + } + + const path = { + 'rule_id': _params.ruleId, + 'attachment_id': _params.attachmentId + }; + + const sdkHeaders = getSdkHeaders(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME, 'v1', 'getAttachment'); + + const parameters = { + options: { + url: '/config/v1/rules/{rule_id}/attachments/{attachment_id}', + method: 'GET', + path, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend(true, sdkHeaders, { + 'Accept': 'application/json', + 'Transaction-Id': _params.transactionId + }, _params.headers), + }), + }; + + return resolve(this.createRequest(parameters)); + }); + }; + + /** + * Update an attachment. + * + * Updates an existing scope attachment based on the properties that you specify. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.ruleId - The UUID that uniquely identifies the rule. + * @param {string} params.attachmentId - The UUID that uniquely identifies the attachment. + * @param {string} params.ifMatch - Compares a supplied `Etag` value with the version that is stored for the requested + * resource. If the values match, the server allows the request method to continue. + * + * To find the `Etag` value, run a GET request on the resource that you want to modify, and check the response + * headers. + * @param {string} params.accountId - Your IBM Cloud account ID. + * @param {RuleScope} params.includedScope - The extent at which the rule can be attached across your accounts. + * @param {RuleScope[]} [params.excludedScopes] - The extent at which the rule can be excluded from the included + * scope. + * @param {string} [params.transactionId] - The unique identifier that is used to trace an entire request. If you omit + * this field, the service generates and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `Transaction-Id` + * with each request. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public updateAttachment(params: ConfigurationGovernanceV1.UpdateAttachmentParams): Promise> { + const _params = Object.assign({}, params); + const requiredParams = ['ruleId', 'attachmentId', 'ifMatch', 'accountId', 'includedScope']; + + return new Promise((resolve, reject) => { + const missingParams = getMissingParams(_params, requiredParams); + if (missingParams) { + return reject(missingParams); + } + + const body = { + 'account_id': _params.accountId, + 'included_scope': _params.includedScope, + 'excluded_scopes': _params.excludedScopes + }; + + const path = { + 'rule_id': _params.ruleId, + 'attachment_id': _params.attachmentId + }; + + const sdkHeaders = getSdkHeaders(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME, 'v1', 'updateAttachment'); + + const parameters = { + options: { + url: '/config/v1/rules/{rule_id}/attachments/{attachment_id}', + method: 'PUT', + body, + path, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend(true, sdkHeaders, { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'If-Match': _params.ifMatch, + 'Transaction-Id': _params.transactionId + }, _params.headers), + }), + }; + + return resolve(this.createRequest(parameters)); + }); + }; + + /** + * Delete an attachment. + * + * Deletes an existing scope attachment. + * + * @param {Object} params - The parameters to send to the service. + * @param {string} params.ruleId - The UUID that uniquely identifies the rule. + * @param {string} params.attachmentId - The UUID that uniquely identifies the attachment. + * @param {string} [params.transactionId] - The unique identifier that is used to trace an entire request. If you omit + * this field, the service generates and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `Transaction-Id` + * with each request. + * @param {OutgoingHttpHeaders} [params.headers] - Custom request headers + * @returns {Promise>} + */ + public deleteAttachment(params: ConfigurationGovernanceV1.DeleteAttachmentParams): Promise> { + const _params = Object.assign({}, params); + const requiredParams = ['ruleId', 'attachmentId']; + + return new Promise((resolve, reject) => { + const missingParams = getMissingParams(_params, requiredParams); + if (missingParams) { + return reject(missingParams); + } + + const path = { + 'rule_id': _params.ruleId, + 'attachment_id': _params.attachmentId + }; + + const sdkHeaders = getSdkHeaders(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME, 'v1', 'deleteAttachment'); + + const parameters = { + options: { + url: '/config/v1/rules/{rule_id}/attachments/{attachment_id}', + method: 'DELETE', + path, + }, + defaultOptions: extend(true, {}, this.baseOptions, { + headers: extend(true, sdkHeaders, { + 'Transaction-Id': _params.transactionId + }, _params.headers), + }), + }; + + return resolve(this.createRequest(parameters)); + }); + }; + +} + +/************************* + * interfaces + ************************/ + +namespace ConfigurationGovernanceV1 { + + /** An operation response. */ + export interface Response { + result: T; + status: number; + statusText: string; + headers: IncomingHttpHeaders; + } + + /** The callback for a service request. */ + export type Callback = (error: any, response?: Response) => void; + + /** The body of a service request that returns no response data. */ + export interface Empty { } + + /** A standard JS object, defined to avoid the limitations of `Object` and `object` */ + export interface JsonObject { + [key: string]: any; + } + + /************************* + * request interfaces + ************************/ + + /** Parameters for the `createRules` operation. */ + export interface CreateRulesParams { + /** A list of rules to be created. */ + rules: CreateRuleRequest[]; + /** The unique identifier that is used to trace an entire request. If you omit this field, the service generates + * and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a + * `Transaction-Id` with each request. + */ + transactionId?: string; + headers?: OutgoingHttpHeaders; + } + + /** Parameters for the `listRules` operation. */ + export interface ListRulesParams { + /** Your IBM Cloud account ID. */ + accountId: string; + /** The unique identifier that is used to trace an entire request. If you omit this field, the service generates + * and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a + * `Transaction-Id` with each request. + */ + transactionId?: string; + /** Retrieves a list of rules that have scope attachments. */ + attached?: boolean; + /** Retrieves a list of rules that match the labels that you specify. */ + labels?: string; + /** Retrieves a list of rules that match the scope ID that you specify. */ + scopes?: string; + /** The number of resources to retrieve. By default, list operations return the first 100 items. To retrieve a + * different set of items, use `limit` with `offset` to page through your available resources. + * + * **Usage:** If you have 20 rules, and you want to retrieve only the first 5 rules, use + * `../rules?account_id={account_id}&limit=5`. + */ + limit?: number; + /** The number of resources to skip. By specifying `offset`, you retrieve a subset of resources that starts with + * the `offset` value. Use `offset` with `limit` to page through your available resources. + * + * **Usage:** If you have 100 rules, and you want to retrieve rules 26 through 50, use + * `../rules?account_id={account_id}&offset=25&limit=5`. + */ + offset?: number; + headers?: OutgoingHttpHeaders; + } + + /** Parameters for the `getRule` operation. */ + export interface GetRuleParams { + /** The UUID that uniquely identifies the rule. */ + ruleId: string; + /** The unique identifier that is used to trace an entire request. If you omit this field, the service generates + * and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a + * `Transaction-Id` with each request. + */ + transactionId?: string; + headers?: OutgoingHttpHeaders; + } + + /** Parameters for the `updateRule` operation. */ + export interface UpdateRuleParams { + /** The UUID that uniquely identifies the rule. */ + ruleId: string; + /** Compares a supplied `Etag` value with the version that is stored for the requested resource. If the values + * match, the server allows the request method to continue. + * + * To find the `Etag` value, run a GET request on the resource that you want to modify, and check the response + * headers. + */ + ifMatch: string; + /** A human-readable alias to assign to your rule. */ + name: string; + /** An extended description of your rule. */ + description: string; + /** The properties that describe the resource that you want to target with the rule. */ + target: TargetResource; + requiredConfig: RuleRequiredConfig; + /** The actions that the service must run on your behalf when a request to create or modify the target resource + * does not comply with your conditions. + */ + enforcementActions: EnforcementAction[]; + /** Your IBM Cloud account ID. */ + accountId?: string; + /** The type of rule. Rules that you create are `user_defined`. */ + ruleType?: UpdateRuleConstants.RuleType | string; + /** Labels that you can use to group and search for similar rules, such as those that help you to meet a + * specific organization guideline. + */ + labels?: string[]; + /** The unique identifier that is used to trace an entire request. If you omit this field, the service generates + * and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a + * `Transaction-Id` with each request. + */ + transactionId?: string; + headers?: OutgoingHttpHeaders; + } + + /** Constants for the `updateRule` operation. */ + export namespace UpdateRuleConstants { + /** The type of rule. Rules that you create are `user_defined`. */ + export enum RuleType { + USER_DEFINED = 'user_defined', + } + } + + /** Parameters for the `deleteRule` operation. */ + export interface DeleteRuleParams { + /** The UUID that uniquely identifies the rule. */ + ruleId: string; + /** The unique identifier that is used to trace an entire request. If you omit this field, the service generates + * and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a + * `Transaction-Id` with each request. + */ + transactionId?: string; + headers?: OutgoingHttpHeaders; + } + + /** Parameters for the `createAttachments` operation. */ + export interface CreateAttachmentsParams { + /** The UUID that uniquely identifies the rule. */ + ruleId: string; + attachments: AttachmentRequest[]; + /** The unique identifier that is used to trace an entire request. If you omit this field, the service generates + * and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a + * `Transaction-Id` with each request. + */ + transactionId?: string; + headers?: OutgoingHttpHeaders; + } + + /** Parameters for the `listAttachments` operation. */ + export interface ListAttachmentsParams { + /** The UUID that uniquely identifies the rule. */ + ruleId: string; + /** The unique identifier that is used to trace an entire request. If you omit this field, the service generates + * and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a + * `Transaction-Id` with each request. + */ + transactionId?: string; + /** The number of resources to retrieve. By default, list operations return the first 100 items. To retrieve a + * different set of items, use `limit` with `offset` to page through your available resources. + * + * **Usage:** If you have 20 rules, and you want to retrieve only the first 5 rules, use + * `../rules?account_id={account_id}&limit=5`. + */ + limit?: number; + /** The number of resources to skip. By specifying `offset`, you retrieve a subset of resources that starts with + * the `offset` value. Use `offset` with `limit` to page through your available resources. + * + * **Usage:** If you have 100 rules, and you want to retrieve rules 26 through 50, use + * `../rules?account_id={account_id}&offset=25&limit=5`. + */ + offset?: number; + headers?: OutgoingHttpHeaders; + } + + /** Parameters for the `getAttachment` operation. */ + export interface GetAttachmentParams { + /** The UUID that uniquely identifies the rule. */ + ruleId: string; + /** The UUID that uniquely identifies the attachment. */ + attachmentId: string; + /** The unique identifier that is used to trace an entire request. If you omit this field, the service generates + * and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a + * `Transaction-Id` with each request. + */ + transactionId?: string; + headers?: OutgoingHttpHeaders; + } + + /** Parameters for the `updateAttachment` operation. */ + export interface UpdateAttachmentParams { + /** The UUID that uniquely identifies the rule. */ + ruleId: string; + /** The UUID that uniquely identifies the attachment. */ + attachmentId: string; + /** Compares a supplied `Etag` value with the version that is stored for the requested resource. If the values + * match, the server allows the request method to continue. + * + * To find the `Etag` value, run a GET request on the resource that you want to modify, and check the response + * headers. + */ + ifMatch: string; + /** Your IBM Cloud account ID. */ + accountId: string; + /** The extent at which the rule can be attached across your accounts. */ + includedScope: RuleScope; + /** The extent at which the rule can be excluded from the included scope. */ + excludedScopes?: RuleScope[]; + /** The unique identifier that is used to trace an entire request. If you omit this field, the service generates + * and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a + * `Transaction-Id` with each request. + */ + transactionId?: string; + headers?: OutgoingHttpHeaders; + } + + /** Parameters for the `deleteAttachment` operation. */ + export interface DeleteAttachmentParams { + /** The UUID that uniquely identifies the rule. */ + ruleId: string; + /** The UUID that uniquely identifies the attachment. */ + attachmentId: string; + /** The unique identifier that is used to trace an entire request. If you omit this field, the service generates + * and sends a transaction ID in the + * `trace` field of the response body. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a + * `Transaction-Id` with each request. + */ + transactionId?: string; + headers?: OutgoingHttpHeaders; + } + + /************************* + * model interfaces + ************************/ + + /** The scopes to attach to the rule. */ + export interface Attachment { + /** The UUID that uniquely identifies the attachment. */ + attachment_id: string; + /** The UUID that uniquely identifies the rule. */ + rule_id: string; + /** Your IBM Cloud account ID. */ + account_id: string; + /** The extent at which the rule can be attached across your accounts. */ + included_scope: RuleScope; + /** The extent at which the rule can be excluded from the included scope. */ + excluded_scopes?: RuleScope[]; + } + + /** A list of attachments. */ + export interface AttachmentList { + /** The requested offset for the returned items. */ + offset: number; + /** The requested limit for the returned items. */ + limit: number; + /** The total number of available items. */ + total_count: number; + /** The first page of available items. */ + first: Link; + /** The last page of available items. */ + last: Link; + attachments: Attachment[]; + } + + /** The scopes to attach to the rule. */ + export interface AttachmentRequest { + /** Your IBM Cloud account ID. */ + account_id: string; + /** The extent at which the rule can be attached across your accounts. */ + included_scope: RuleScope; + /** The extent at which the rule can be excluded from the included scope. */ + excluded_scopes?: RuleScope[]; + } + + /** CreateAttachmentsResponse. */ + export interface CreateAttachmentsResponse { + attachments: Attachment[]; + } + + /** A rule to be created. */ + export interface CreateRuleRequest { + /** A field that you can use in bulk operations to store a custom identifier for an individual request. If you + * omit this field, the service generates and sends a `request_id` string for each new rule. The generated string + * corresponds with the numerical order of the rules request array. For example, `"request_id": "1"`, + * `"request_id": "2"`. + * + * **Note:** To help with debugging logs, it is strongly recommended that you generate and supply a `request_id` + * with each request. + */ + request_id?: string; + /** User-settable properties associated with a rule to be created or updated. */ + rule: RuleRequest; + } + + /** Response information for a rule request. If the 'status_code' property indicates success, the 'request_id' and 'rule' properties will be present. If the 'status_code' property indicates an error, the 'request_id', 'errors', and 'trace' fields will be present. */ + export interface CreateRuleResponse { + /** The identifier that is used to correlate an individual request. + * + * To assist with debugging, you can use this ID to identify and inspect only one request that was made as part of + * a bulk operation. + */ + request_id?: string; + /** The HTTP response status code. */ + status_code?: number; + /** Information about a newly-created rule. + * + * This field will be present for a successful request. + */ + rule?: Rule; + /** The error contents of the multi-status response. + * + * This field will be present for a failed rule request. + */ + errors?: RuleResponseError[]; + /** The UUID that uniquely identifies the request. + * + * This field will be present for a failed rule request. + */ + trace?: string; + } + + /** The response associated with a request to create one or more rules. */ + export interface CreateRulesResponse { + /** An array of rule responses. */ + rules: CreateRuleResponse[]; + } + + /** EnforcementAction. */ + export interface EnforcementAction { + /** To block a request from completing, use `disallow`. To log the request to Activity Tracker with LogDNA, use + * `audit_log`. + */ + action: string; + } + + /** A link that is used to paginate through available resources. */ + export interface Link { + /** The URL for the first, previous, next, or last page of resources. */ + href: string; + } + + /** Properties associated with a rule, including both user-settable and server-populated properties. */ + export interface Rule { + /** Your IBM Cloud account ID. */ + account_id?: string; + /** A human-readable alias to assign to your rule. */ + name: string; + /** An extended description of your rule. */ + description: string; + /** The type of rule. Rules that you create are `user_defined`. */ + rule_type?: string; + /** The properties that describe the resource that you want to target with the rule. */ + target: TargetResource; + required_config: RuleRequiredConfig; + /** The actions that the service must run on your behalf when a request to create or modify the target resource + * does not comply with your conditions. + */ + enforcement_actions: EnforcementAction[]; + /** Labels that you can use to group and search for similar rules, such as those that help you to meet a + * specific organization guideline. + */ + labels?: string[]; + /** The UUID that uniquely identifies the rule. */ + rule_id?: string; + /** The date the resource was created. */ + creation_date?: string; + /** The unique identifier for the user or application that created the resource. */ + created_by?: string; + /** The date the resource was last modified. */ + modification_date?: string; + /** The unique identifier for the user or application that last modified the resource. */ + modified_by?: string; + /** The number of scope attachments that are associated with the rule. */ + number_of_attachments?: number; + } + + /** RuleCondition. */ + export interface RuleCondition { + } + + /** A list of rules. */ + export interface RuleList { + /** The requested offset for the returned items. */ + offset: number; + /** The requested limit for the returned items. */ + limit: number; + /** The total number of available items. */ + total_count: number; + /** The first page of available items. */ + first: Link; + /** The last page of available items. */ + last: Link; + /** An array of rules. */ + rules: Rule[]; + } + + /** User-settable properties associated with a rule to be created or updated. */ + export interface RuleRequest { + /** Your IBM Cloud account ID. */ + account_id?: string; + /** A human-readable alias to assign to your rule. */ + name: string; + /** An extended description of your rule. */ + description: string; + /** The type of rule. Rules that you create are `user_defined`. */ + rule_type?: string; + /** The properties that describe the resource that you want to target with the rule. */ + target: TargetResource; + required_config: RuleRequiredConfig; + /** The actions that the service must run on your behalf when a request to create or modify the target resource + * does not comply with your conditions. + */ + enforcement_actions: EnforcementAction[]; + /** Labels that you can use to group and search for similar rules, such as those that help you to meet a + * specific organization guideline. + */ + labels?: string[]; + } + + /** RuleRequiredConfig. */ + export interface RuleRequiredConfig { + } + + /** RuleResponseError. */ + export interface RuleResponseError { + /** Specifies the problem that caused the error. */ + code: string; + /** Describes the problem. */ + message: string; + } + + /** The extent at which the rule can be attached across your accounts. */ + export interface RuleScope { + /** A short description or alias to assign to the scope. */ + note?: string; + /** The ID of the scope, such as an enterprise, account, or account group, that you want to evaluate. */ + scope_id: string; + /** The type of scope that you want to evaluate. */ + scope_type: string; + } + + /** The requirement that must be met to determine the resource's level of compliance in accordance with the rule. To apply a single property check, define a configuration property and the desired value that you want to check against. */ + export interface RuleSingleProperty { + description?: string; + /** A resource configuration variable that describes the property that you want to apply to the target resource. + * + * Available options depend on the target service and resource. Currently, + * `public_access_enabled` is supported. + */ + property: string; + /** The way in which the `property` field is compared to its value. + * + * There are three types of operators: string, numeric, and boolean. + */ + operator: string; + /** The way in which you want your property to be applied. + * + * Value options differ depending on the rule that you configure. If you use a boolean operator, you do not need to + * input a value. + */ + value?: string; + } + + /** The attributes that are associated with a rule target. */ + export interface RuleTargetAttribute { + name: string; + /** The way in which the `name` field is compared to its value. + * + * There are three types of operators: string, numeric, and boolean. + */ + operator: string; + /** The way in which you want your property to be applied. + * + * Value options differ depending on the rule that you configure. If you use a boolean operator, you do not need to + * input a value. + */ + value?: string; + } + + /** The properties that describe the resource that you want to target with the rule. */ + export interface TargetResource { + /** The programmatic name of the IBM Cloud service that you want to target with the rule. Currently, + * `iam-groups` is supported. + */ + service_name: string; + /** The type of resource that you want to target. */ + resource_kind: string; + /** An extra qualifier for the resource kind. When you include additional attributes, only the resources that + * match the definition are included in the rule. + */ + additional_target_attributes?: RuleTargetAttribute[]; + } + + /** A condition with the `and` logical operator. */ + export interface RuleConditionAndLvl2 extends RuleCondition { + description?: string; + and: RuleSingleProperty[]; + } + + /** A condition with the `or` logical operator. */ + export interface RuleConditionOrLvl2 extends RuleCondition { + description?: string; + or: RuleSingleProperty[]; + } + + /** The requirement that must be met to determine the resource's level of compliance in accordance with the rule. To apply a single property check, define a configuration property and the desired value that you want to check against. */ + export interface RuleConditionSingleProperty extends RuleCondition { + description?: string; + /** A resource configuration variable that describes the property that you want to apply to the target resource. + * + * Available options depend on the target service and resource. Currently, + * `public_access_enabled` is supported. + */ + property: string; + /** The way in which the `property` field is compared to its value. + * + * There are three types of operators: string, numeric, and boolean. + */ + operator: string; + /** The way in which you want your property to be applied. + * + * Value options differ depending on the rule that you configure. If you use a boolean operator, you do not need to + * input a value. + */ + value?: string; + } + + /** The requirements that must be met to determine the resource's level of compliance in accordance with the rule. Use logical operators (`and`/`or`) to define multiple property checks and conditions. To define requirements for a rule, list one or more property check objects in the `and` array. To add conditions to a property check, use `or`. */ + export interface RuleRequiredConfigMultipleProperties extends RuleRequiredConfig { + } + + /** The requirement that must be met to determine the resource's level of compliance in accordance with the rule. To apply a single property check, define a configuration property and the desired value that you want to check against. */ + export interface RuleRequiredConfigSingleProperty extends RuleRequiredConfig { + description?: string; + /** A resource configuration variable that describes the property that you want to apply to the target resource. + * + * Available options depend on the target service and resource. Currently, + * `public_access_enabled` is supported. + */ + property: string; + /** The way in which the `property` field is compared to its value. + * + * There are three types of operators: string, numeric, and boolean. + */ + operator: string; + /** The way in which you want your property to be applied. + * + * Value options differ depending on the rule that you configure. If you use a boolean operator, you do not need to + * input a value. + */ + value?: string; + } + + /** A condition with the `and` logical operator. */ + export interface RuleRequiredConfigMultiplePropertiesConditionAnd extends RuleRequiredConfigMultipleProperties { + description?: string; + and: RuleCondition[]; + } + + /** A condition with the `or` logical operator. */ + export interface RuleRequiredConfigMultiplePropertiesConditionOr extends RuleRequiredConfigMultipleProperties { + description?: string; + or: RuleCondition[]; + } + +} + +export = ConfigurationGovernanceV1; diff --git a/examples/configuration-governance.v1.test.js b/examples/configuration-governance.v1.test.js new file mode 100644 index 00000000..d6048ff5 --- /dev/null +++ b/examples/configuration-governance.v1.test.js @@ -0,0 +1,409 @@ +/** +* @jest-environment node +*/ +/** + * (C) Copyright IBM Corp. 2020. + * + * 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. + */ +'use strict'; + +const ConfigurationGovernanceV1 = require('../dist/configuration-governance/v1'); +const { readExternalSources } = require('ibm-cloud-sdk-core'); +const authHelper = require('../test/resources/auth-helper.js'); + +// Location of our config file. +const configFile = 'configuration_governance.env'; + +const describe = authHelper.prepareTests(configFile); + +// Save original console.log and console.warn +const originalLog = console.log +const originalWarn = console.warn + +// Mocks for console.log and console.warn +const consoleLogMock = jest.spyOn(console, 'log'); +const consoleWarnMock = jest.spyOn(console, 'warn'); + +describe('ConfigurationGovernanceV1', () => { + + // begin-common + + const configurationGovernanceService = ConfigurationGovernanceV1.newInstance({}); + + // end-common + + // Globlal variables to hold link values + let attachmentEtag + let attachmentId + let ruleEtag + let ruleId + + const config = readExternalSources(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME); + + // Additional configuration settings + let testLabel = 'NodeSDKExamples'; + let accountId = config.accountId; + let serviceName = config.exampleServiceName; + let enterpriseScopeId = config.enterpriseScopeId; + let subacctScopeId = config.subacctScopeId; + + beforeAll(async done => { + // Clean any existing test rules before we start the actual tests. + await cleanRules(testLabel, done); + }); + + test('createRules request example', done => { + + consoleLogMock.mockImplementation(output => { + let responseBody = JSON.parse(output); + ruleId = responseBody.rules[0].rule.rule_id; + done(); + }); + consoleWarnMock.mockImplementation(output => { + done(output); + }); + + // begin-create_rules + + const params = { + rules: [{ request_id: '3cebc877-58e7-44a5-a292-32114fa73558', rule: { account_id: accountId, name: 'Disable public access', description: 'Ensure that public access to account resources is disabled.', labels: ['Access', 'IAM'], target: { service_name: serviceName, resource_kind: 'service' }, required_config: { description: 'Public access check', and: [{ property: 'public_access_enabled', operator: 'is_false' }] }, enforcement_actions: [{ action: 'disallow' }, { action: 'audit_log' }] } }], + }; + + configurationGovernanceService.createRules(params) + .then(res => { + const { result, status } = res; + if (status === 201) { + console.log(JSON.stringify(result, null, 2)); + } else { + // some rules may have failed + for (rule of result.rules) { + if (rule.errors !== undefined && rule.errors.length > 0) { + throw new Error(rule.errors[0].message) + } + } + } + }) + .catch(err => { + console.warn(err) + }); + + // end-create_rules + }); + test('createAttachments request example', done => { + + consoleLogMock.mockImplementation(output => { + let responseBody = JSON.parse(output); + attachmentId = responseBody.attachments[0].attachment_id; + done(); + }); + consoleWarnMock.mockImplementation(output => { + done(output); + }); + + // begin-create_attachments + + const params = { + ruleId: ruleId, + attachments: [{ attachment_id: 'attachment-4301178a-8028-4220-9cb6-dfb86f09da99', account_id: accountId, rule_id: 'rule-702d1db7-ca4a-414b-8464-2b517a065c14', included_scope: { note: 'My enterprise', scope_id: enterpriseScopeId, scope_type: 'enterprise' }, excluded_scopes: [{ note: 'Development account', scope_id: subacctScopeId, scope_type: 'enterprise.account' }] }], + }; + + configurationGovernanceService.createAttachments(params) + .then(res => { + console.log(JSON.stringify(res.result, null, 2)); + }) + .catch(err => { + console.warn(err) + }); + + // end-create_attachments + }); + test('getAttachment request example', done => { + + consoleLogMock.mockImplementation(output => { + let responseBody = JSON.parse(output); + configurationGovernanceService.getAttachment({ + ruleId: ruleId, + attachmentId: attachmentId, + }).then(res => { + attachmentEtag = res.headers['etag']; + done(); + }) + .catch(err => { + console.warn(err) + }); + }); + consoleWarnMock.mockImplementation(output => { + done(output); + }); + + // begin-get_attachment + + const params = { + ruleId: ruleId, + attachmentId: attachmentId, + }; + + configurationGovernanceService.getAttachment(params) + .then(res => { + console.log(JSON.stringify(res.result, null, 2)); + }) + .catch(err => { + console.warn(err) + }); + + // end-get_attachment + }); + test('getRule request example', done => { + + consoleLogMock.mockImplementation(output => { + let responseBody = JSON.parse(output); + configurationGovernanceService.getRule({ + ruleId: ruleId + }).then(res => { + ruleEtag = res.headers['etag']; + done(); + }) + .catch(err => { + console.warn(err) + }); + }); + consoleWarnMock.mockImplementation(output => { + done(output); + }); + + // begin-get_rule + + const params = { + ruleId: ruleId, + }; + + configurationGovernanceService.getRule(params) + .then(res => { + console.log(JSON.stringify(res.result, null, 2)); + }) + .catch(err => { + console.warn(err) + }); + + // end-get_rule + }); + test('listRules request example', done => { + + consoleLogMock.mockImplementation(output => { + done(); + }); + consoleWarnMock.mockImplementation(output => { + done(output); + }); + + // begin-list_rules + + const params = { + accountId: accountId + }; + + configurationGovernanceService.listRules(params) + .then(res => { + console.log(JSON.stringify(res.result, null, 2)); + }) + .catch(err => { + console.warn(err) + }); + + // end-list_rules + }); + test('updateRule request example', done => { + + consoleLogMock.mockImplementation(output => { + done(); + }); + consoleWarnMock.mockImplementation(output => { + done(output); + }); + + // begin-update_rule + + const params = { + ruleId: ruleId, + ifMatch: ruleEtag, + name: 'Disable public access', + description: 'Ensure that public access to account resources is disabled.', + target: { "service_name": "iam-groups", "resource_kind": "service", "additional_target_attributes": [] }, + requiredConfig: { property: 'public_access_enabled', operator: 'is_false' }, + enforcementActions: [{ action: 'audit_log' }, { action: 'disallow' }], + accountId: accountId, + ruleType: 'user_defined', + labels: ['SOC2', 'ITCS300'], + }; + + configurationGovernanceService.updateRule(params) + .then(res => { + console.log(JSON.stringify(res.result, null, 2)); + }) + .catch(err => { + console.warn(err) + }); + + // end-update_rule + }); + test('listAttachments request example', done => { + + consoleLogMock.mockImplementation(output => { + done(); + }); + consoleWarnMock.mockImplementation(output => { + done(output); + }); + + // begin-list_attachments + + const params = { + ruleId: ruleId, + }; + + configurationGovernanceService.listAttachments(params) + .then(res => { + console.log(JSON.stringify(res.result, null, 2)); + }) + .catch(err => { + console.warn(err) + }); + + // end-list_attachments + }); + test('updateAttachment request example', done => { + + consoleLogMock.mockImplementation(output => { + done(); + }); + consoleWarnMock.mockImplementation(output => { + done(output); + }); + + // begin-update_attachment + + const params = { + ruleId: ruleId, + attachmentId: attachmentId, + ifMatch: attachmentEtag, + accountId: accountId, + includedScope: { note: 'My enterprise', scope_id: enterpriseScopeId, scope_type: 'enterprise' }, + excludedScopes: [{ note: 'Development account', scope_id: subacctScopeId, scope_type: 'enterprise.account' }], + }; + + configurationGovernanceService.updateAttachment(params) + .then(res => { + console.log(JSON.stringify(res.result, null, 2)); + }) + .catch(err => { + console.warn(err) + }); + + // end-update_attachment + }); + test('deleteAttachment request example', done => { + + consoleLogMock.mockImplementation(output => { + done(); + }); + consoleWarnMock.mockImplementation(output => { + done(output); + }); + + // begin-delete_attachment + + const params = { + ruleId: ruleId, + attachmentId: attachmentId, + }; + + configurationGovernanceService.deleteAttachment(params) + .then(res => { + console.log(JSON.stringify(res.result, null, 2)); + }) + .catch(err => { + console.warn(err) + }); + + // end-delete_attachment + }); + test('deleteRule request example', done => { + + consoleLogMock.mockImplementation(output => { + done(); + }); + consoleWarnMock.mockImplementation(output => { + done(output); + }); + + // begin-delete_rule + + const params = { + ruleId: ruleId, + }; + + configurationGovernanceService.deleteRule(params) + .then(res => { + console.log(JSON.stringify(res.result, null, 2)); + }) + .catch(err => { + console.warn(err) + }); + + // end-delete_rule + }); + + async function cleanRules(label, done) { + console.log('Cleaning rules...'); + + try { + // List any existing rules for this account with the specified label. + const params = { + accountId: accountId, + labels: label, + limit: 1000, + offset: 0, + }; + + const res = await configurationGovernanceService.listRules(params); + expect(res).not.toBeNull(); + expect(res.status).toEqual(200); + const ruleListResult = res.result; + expect(ruleListResult).not.toBeNull(); + + console.log(`Found ${ruleListResult.total_count} rule(s) to be cleaned`); + + // Now walk through the returned rules and delete each one. + if (ruleListResult.total_count > 0) { + for (const rule of ruleListResult.rules) { + const deleteRuleParams = { + ruleId: rule.rule_id, + }; + + console.log(`Deleting rule: name=${rule.name} id=${rule.rule_id}`); + + const deleteRuleRes = await configurationGovernanceService.deleteRule(deleteRuleParams); + expect(deleteRuleRes).not.toBeNull(); + expect(deleteRuleRes.status).toEqual(204); + } + } + console.log(`Finished cleaning rules...`); + done(); + } catch (err) { + console.log(err); + done(err); + } + } + +}); diff --git a/scripts/typedoc/generate_typedoc.sh b/scripts/typedoc/generate_typedoc.sh index fc8e3056..7a01e69e 100755 --- a/scripts/typedoc/generate_typedoc.sh +++ b/scripts/typedoc/generate_typedoc.sh @@ -5,6 +5,7 @@ --out ./doc \ ./case-management/v1.ts \ ./catalog-management/v1.ts \ + ./configuration-governance/v1.ts \ ./enterprise-management/v1.ts \ ./global-catalog/v1.ts \ ./global-search/v2.ts \ diff --git a/test/integration/configuration-governance.v1.test.js b/test/integration/configuration-governance.v1.test.js new file mode 100644 index 00000000..e7273ba8 --- /dev/null +++ b/test/integration/configuration-governance.v1.test.js @@ -0,0 +1,1049 @@ +/* eslint-disable no-console */ +/** + * (C) Copyright IBM Corp. 2020. + * + * 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. + */ + +'use strict'; +const ConfigurationGovernanceV1 = require('../../dist/configuration-governance/v1'); +const { readExternalSources } = require('ibm-cloud-sdk-core'); +const authHelper = require('../resources/auth-helper.js'); +const { v4: uuidv4 } = require('uuid'); + +// testcase timeout value (25s). +const timeout = 25000; + +// Location of our config file. +const configFile = 'configuration_governance.env'; + +const describe = authHelper.prepareTests(configFile); + +const verbose = true; +let configurationGovernanceService; +let configurationGovernanceServiceNoAccess; + +let TEST_LABEL; +let ACCOUNT_ID; +let TEST_SERVICE_NAME; +let ENTERPRISE_SCOPE_ID; +let SUBACCT_SCOPE_ID; + +// Generate a txn-id to be used during this test run. +const transactionId = uuidv4(); + +// Variables to hold various id's and object instances (these could perhaps be configured via links). +let ruleId1; +let rule1; +let ruleEtag1; +let ruleId2; + +let sampleRule1; +let sampleRule2; +let badSampleRule; + +let enterpriseScope; +let accountScope; +let badScope; + +let attachmentId1; +let attachment1; +let attachmentEtag1; +let attachmentId2; + +describe('ConfigurationGovernanceV1_integration', () => { + jest.setTimeout(timeout); + + beforeAll(async done => { + log('Starting setup...'); + configurationGovernanceService = ConfigurationGovernanceV1.newInstance({}); + expect(configurationGovernanceService).not.toBeNull(); + expect(configurationGovernanceService.baseOptions.serviceUrl).not.toBeNull(); + + // Construct a separate service client for some negative tests. + // This service has an apikey that lacks the necessary access to create or list rules, etc. + configurationGovernanceServiceNoAccess = ConfigurationGovernanceV1.newInstance({ serviceName: 'NO_ACCESS' }); + expect(configurationGovernanceServiceNoAccess).not.toBeNull(); + expect(configurationGovernanceServiceNoAccess.baseOptions.serviceUrl).not.toBeNull(); + + // Load up our test-specific config properties. + const config = readExternalSources(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME); + expect(config).not.toBeNull(); + expect(config.length).not.toBe(0); + expect(configurationGovernanceService.baseOptions.serviceUrl).toEqual(config.url); + + // Retrieve and verify some additional test-related config properties. + ACCOUNT_ID = config.accountId; + TEST_SERVICE_NAME = config.testServiceName; + ENTERPRISE_SCOPE_ID = config.enterpriseScopeId; + SUBACCT_SCOPE_ID = config.subacctScopeId; + expect(ACCOUNT_ID).not.toBeNull(); + expect(ACCOUNT_ID).not.toBeUndefined(); + expect(TEST_SERVICE_NAME).not.toBeNull(); + expect(TEST_SERVICE_NAME).not.toBeUndefined(); + expect(ENTERPRISE_SCOPE_ID).not.toBeNull(); + expect(ENTERPRISE_SCOPE_ID).not.toBeUndefined(); + expect(SUBACCT_SCOPE_ID).not.toBeNull(); + expect(SUBACCT_SCOPE_ID).not.toBeUndefined(); + + log(`Service URL: ${configurationGovernanceService.baseOptions.serviceUrl}`); + log(`Transaction ID: ${transactionId}`); + + // Clean any existing test rules before we start the actual tests. + await cleanRules(TEST_LABEL, done); + + // Create some sample model instances that we'll use when invoking the operations. + initSampleData(); + + log('Finished setup.'); + }); + + test('createRule1', done => { + const ruleRequest1 = { + request_id: 'request-0', + rule: sampleRule1, + }; + + const params = { + rules: [ruleRequest1], + transactionId: transactionId, + }; + + configurationGovernanceService + .createRules(params) + .then(res => { + expect(res).not.toBeNull(); + expect(res.status).toEqual(201); + + const result = res.result; + expect(result).not.toBeNull(); + expect(result.rules.length).toEqual(1); + + const ruleResponse1 = result.rules[0]; + expect(ruleResponse1.request_id).toEqual('request-0'); + expect(ruleResponse1.status_code).toEqual(201); + ruleId1 = ruleResponse1.rule.rule_id; + expect(ruleId1).not.toBeNull(); + expect(ruleId1 != '').toBe(true); + done(); + }) + .catch(err => { + log(err); + done(err); + }); + }); + + test('createRule2', done => { + // CreateRuleRequest + const ruleRequest2 = { + rule: sampleRule2, + }; + + const params = { + rules: [ruleRequest2], + transactionId: transactionId, + }; + + configurationGovernanceService + .createRules(params) + .then(res => { + expect(res).not.toBeNull(); + expect(res.status).toEqual(201); + + const result = res.result; + expect(result).not.toBeNull(); + expect(result.rules.length).toEqual(1); + + const ruleResponse2 = result.rules[0]; + expect(ruleResponse2.request_id.length).toBeGreaterThan(0); + expect(ruleResponse2.status_code).toEqual(201); + ruleId2 = ruleResponse2.rule.rule_id; + expect(ruleId2).not.toBeNull(); + expect(ruleId2 != '').toBe(true); + expect(ruleId1).not.toEqual(ruleId2); + done(); + }) + .catch(err => { + log(err); + done(err); + }); + }); + + test('createRuleInvalidRule', done => { + // CreateRuleRequest + const ruleRequestBad = { + request_id: 'request-1', + rule: badSampleRule, + }; + + const params = { + rules: [ruleRequestBad], + transactionId: transactionId, + }; + + // An error will be reported within the resultentry, but the operation itself will + // return a 207 status code. + configurationGovernanceService + .createRules(params) + .then(res => { + expect(res).not.toBeNull(); + expect(res.status).toEqual(207); + + const result = res.result; + expect(result).not.toBeNull(); + expect(result.rules.length).toEqual(1); + + // Verify the response entry indicates an error. + const ruleResponse = result.rules[0]; + expect(ruleResponse.request_id).toEqual('request-1'); + expect(ruleResponse.status_code).toEqual(400); + expect(ruleResponse.trace).toEqual(transactionId); + expect(ruleResponse.errors.length).toBeGreaterThan(0); + expect(ruleResponse.errors[0].code).toEqual('rule_error'); + done(); + }) + .catch(err => { + log(err); + done(err); + }); + }); + + test('createRuleNoAccess', done => { + const ruleRequest1 = { + request_id: 'request-1', + rule: sampleRule1, + }; + + const params = { + rules: [ruleRequest1], + transactionId: transactionId, + }; + + configurationGovernanceServiceNoAccess + .createRules(params) + .then(res => { + done(`Using a no-access apikey should not have succeeded!`); + }) + .catch(err => { + expect(err.status).toEqual(403); + expect(err.message).toContain('Access is denied'); + done(); + }); + }); + test('listRules', done => { + const params = { + accountId: ACCOUNT_ID, + transactionId: transactionId, + labels: TEST_LABEL, + limit: 1000, + offset: 0, + }; + + configurationGovernanceService + .listRules(params) + .then(res => { + expect(res).not.toBeNull(); + expect(res.status).toEqual(200); + + const result = res.result; + expect(result).not.toBeNull(); + expect(result.total_count).toEqual(2); + expect(result.offset).toEqual(0); + expect(result.limit).toEqual(1000); + expect(result.first).not.toBeNull(); + expect(result.last).not.toBeNull(); + done(); + }) + .catch(err => { + log(err); + done(err); + }); + }); + + test('listRulesNoAccess', done => { + const params = { + accountId: ACCOUNT_ID, + transactionId: transactionId, + labels: TEST_LABEL, + limit: 1000, + offset: 0, + }; + + configurationGovernanceServiceNoAccess + .listRules(params) + .then(res => { + log(res); + done(`Using a no-access apikey should not have succeeded!`); + }) + .catch(err => { + expect(err.status).toEqual(403); + expect(err.message).toContain('Access is denied'); + done(); + }); + }); + + test('getRule', done => { + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + const params = { + ruleId: ruleId1, + transactionId: transactionId, + }; + + configurationGovernanceService + .getRule(params) + .then(res => { + expect(res).not.toBeNull(); + expect(res.status).toEqual(200); + + const result = res.result; + expect(result).not.toBeNull(); + rule1 = result; + + // Grab the Etag value from the response for use in the update operation. + expect(res.headers.etag).not.toBeNull(); + expect(res.headers.etag.length).not.toBe(0); + ruleEtag1 = res.headers.etag; + expect(ruleEtag1).not.toBeNull(); + done(); + }) + .catch(err => { + log(err); + done(err); + }); + }); + + test('getRuleInvalidRuleId', done => { + const params = { + ruleId: 'BOGUS_ID', + transactionId: transactionId, + }; + + configurationGovernanceService + .getRule(params) + .then(res => { + log(res); + done('Invalid get should not have succeeded!'); + }) + .catch(err => { + expect(err.status).toEqual(404); + expect(err.message).toContain('not found'); + done(); + }); + }); + + test('updateRule', done => { + expect(rule1).not.toBeNull(); + expect(rule1).not.toBeUndefined(); + + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + expect(ruleEtag1).not.toBeNull(); + expect(ruleEtag1).not.toBeUndefined(); + + // Starting with "rule1" (result of a get), modify the description, then call the update operation. + const params = { + ruleId: ruleId1, + ifMatch: ruleEtag1, + name: rule1.name, + description: `Updated: ${rule1.description}`, + target: rule1.target, + requiredConfig: rule1.required_config, + enforcementActions: rule1.enforcement_actions, + accountId: rule1.account_id, + ruleType: rule1.rule_type, + labels: rule1.labels, + transactionId: transactionId, + }; + + configurationGovernanceService + .updateRule(params) + .then(res => { + expect(res).not.toBeNull(); + expect(res.status).toEqual(200); + + const result = res.result; + expect(result).not.toBeNull(); + expect(result.description.startsWith('Updated:')).toBe(true); + done(); + }) + .catch(err => { + log(err); + done(err); + }); + }); + + test('updateRuleInvalidEtag', done => { + expect(rule1).not.toBeNull(); + expect(rule1).not.toBeUndefined(); + + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + expect(ruleEtag1).not.toBeNull(); + expect(ruleEtag1).not.toBeUndefined(); + + // Starting with "rule1" (result of a get), modify the description, then call the update operation. + const params = { + ruleId: ruleId1, + ifMatch: `${ruleEtag1} just-foolin`, + name: rule1.name, + description: `Updated: ${rule1.description}`, + target: rule1.target, + requiredConfig: rule1.required_config, + enforcementActions: rule1.enforcement_actions, + accountId: rule1.account_id, + ruleType: rule1.rule_type, + labels: rule1.labels, + transactionId: transactionId, + }; + + configurationGovernanceService + .updateRule(params) + .then(res => { + log(res); + done('Invalid update should not have succeeded!'); + }) + .catch(err => { + expect(err.status).toEqual(400); + expect(err.message).toContain('If-Match'); + done(); + }); + }); + + test('deleteRule', async done => { + expect(ruleId2).not.toBeNull(); + expect(ruleId2).not.toBeUndefined(); + + const params = { + ruleId: ruleId2, + transactionId: transactionId, + }; + + let deleteRuleResp; + let listRulesResp; + try { + deleteRuleResp = await configurationGovernanceService.deleteRule(params); + + // Now check to make sure listRules() returns only 1 rule. + const listRuleParams = { + accountId: ACCOUNT_ID, + transactionId: transactionId, + labels: TEST_LABEL, + limit: 1000, + offset: 0, + }; + + listRulesResp = await configurationGovernanceService.listRules(listRuleParams); + } catch (err) { + log(err); + done(err); + } + + expect(deleteRuleResp).not.toBeNull(); + expect(deleteRuleResp.status).toEqual(204); + + expect(listRulesResp).not.toBeNull(); + expect(listRulesResp.status).toEqual(200); + + const result = listRulesResp.result; + expect(result).not.toBeNull(); + expect(result.total_count).toEqual(1); + + // Next, make sure we can not do a get on the deleted rule. + const rule = await getRule(ruleId2); + expect(rule).toBeNull(); + done(); + }); + + test('deleteRuleInvalidRuleId', done => { + const params = { + ruleId: 'BOGUS_RULE_ID', + transactionId: transactionId, + }; + + configurationGovernanceService + .deleteRule(params) + .then(res => { + log(res); + done('Invalid delete should not have succeeded!'); + }) + .catch(err => { + expect(err.status).toEqual(404); + expect(err.message).toContain('not found'); + done(); + }); + }); + + test('createAttachment1', async done => { + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + const attachmentRequestModel = { + account_id: ACCOUNT_ID, + included_scope: enterpriseScope, + excluded_scopes: [accountScope], + }; + + const params = { + ruleId: ruleId1, + attachments: [attachmentRequestModel], + transactionId: transactionId, + }; + + let createAttachmentsResp; + try { + createAttachmentsResp = await configurationGovernanceService.createAttachments(params); + } catch (err) { + log(err); + done(err); + } + + expect(createAttachmentsResp).not.toBeNull(); + expect(createAttachmentsResp.status).toEqual(201); + + const result = createAttachmentsResp.result; + expect(result).not.toBeNull(); + expect(result.attachments).not.toBeNull(); + expect(result.attachments.length).toEqual(1); + expect(result.attachments[0]).not.toBeNull(); + attachmentId1 = result.attachments[0].attachment_id; + expect(attachmentId1).not.toBeNull(); + + // Now retrieve the rule and make sure the num_attachments is 1. + const rule = await getRule(ruleId1); + expect(rule).not.toBeNull(); + expect(rule.number_of_attachments).not.toBeNull(); + expect(rule.number_of_attachments).toEqual(1); + done(); + }); + + test('createAttachment2', async done => { + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + const attachmentRequestModel = { + account_id: ACCOUNT_ID, + included_scope: accountScope, + }; + + const params = { + ruleId: ruleId1, + attachments: [attachmentRequestModel], + transactionId: transactionId, + }; + + let createAttachmentsResp; + try { + createAttachmentsResp = await configurationGovernanceService.createAttachments(params); + } catch (err) { + log(err); + done(err); + } + + expect(createAttachmentsResp).not.toBeNull(); + expect(createAttachmentsResp.status).toEqual(201); + + const result = createAttachmentsResp.result; + expect(result).not.toBeNull(); + expect(result.attachments).not.toBeNull(); + expect(result.attachments.length).toEqual(1); + expect(result.attachments[0]).not.toBeNull(); + attachmentId2 = result.attachments[0].attachment_id; + expect(attachmentId2).not.toBeNull(); + + // Now retrieve the rule and make sure the num_attachments is 2. + const rule = await getRule(ruleId1); + expect(rule).not.toBeNull(); + expect(rule.number_of_attachments).not.toBeNull(); + expect(rule.number_of_attachments).toEqual(2); + done(); + }); + + test('createAttachmentInvalidScopeType', done => { + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + const attachmentRequestModel = { + account_id: ACCOUNT_ID, + included_scope: accountScope, + excluded_scopes: [badScope], + }; + + const params = { + ruleId: ruleId1, + attachments: [attachmentRequestModel], + transactionId: transactionId, + }; + + configurationGovernanceService + .createAttachments(params) + .then(res => { + log(res); + done('Invalid attachment should not have succeeded!'); + }) + .catch(err => { + expect(err.status).toEqual(400); + expect(err.message).toContain('not a descendant'); + done(); + }); + }); + + test('getAttachment', done => { + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + expect(attachmentId1).not.toBeNull(); + expect(attachmentId1).not.toBeUndefined(); + + const params = { + ruleId: ruleId1, + attachmentId: attachmentId1, + }; + + configurationGovernanceService + .getAttachment(params) + .then(res => { + expect(res).not.toBeNull(); + expect(res.status).toEqual(200); + + const result = res.result; + expect(result).not.toBeNull(); + attachment1 = result; + + expect(result.account_id).toEqual(ACCOUNT_ID); + expect(result.rule_id).toEqual(ruleId1); + expect(result.attachment_id).toEqual(attachmentId1); + expect(result.included_scope.note).toEqual('enterprise'); + expect(result.excluded_scopes.length).toEqual(1); + + // Grab the Etag value from the response for use in the update operation. + expect(res.headers.etag).not.toBeNull(); + expect(res.headers.etag.length).not.toBe(0); + attachmentEtag1 = res.headers.etag; + expect(attachmentEtag1).not.toBeNull(); + done(); + }) + .catch(err => { + log(err); + done(err); + }); + done(); + }); + + test('getAttachmentInvalidAttachmentId', done => { + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + expect(attachmentId1).not.toBeNull(); + expect(attachmentId1).not.toBeUndefined(); + + const params = { + ruleId: ruleId1, + attachmentId: 'BOGUS_ID', + }; + + configurationGovernanceService + .getAttachment(params) + .then(res => { + log(res); + done('Invalid attachment id should not have succeeded!'); + }) + .catch(err => { + expect(err.status).toEqual(404); + expect(err.message).toContain('not found'); + done(); + }); + }); + + test('listAttachments', done => { + const params = { + ruleId: ruleId1, + transactionId: transactionId, + limit: 1000, + offset: 0, + }; + + configurationGovernanceService + .listAttachments(params) + .then(res => { + expect(res).not.toBeNull(); + expect(res.status).toEqual(200); + + const result = res.result; + expect(result).not.toBeNull(); + + expect(result.offset).toEqual(0); + expect(result.limit).toEqual(1000); + expect(result.total_count).toEqual(2); + expect(result.first).not.toBeNull(); + expect(result.last).not.toBeNull(); + result.attachments.forEach(att => { + if (attachmentId1 === att.attachment_id) { + expect(att.included_scope.note).toEqual('enterprise'); + expect(att.excluded_scopes.length).toEqual(1); + } else if (attachmentId2 === att.attachment_id) { + expect(att.included_scope.note).toEqual('leaf account'); + expect(att.excluded_scopes == null || att.excluded_scopes.length == 0).toBe(true); + } else { + done(`Unrecognized attachmentId: ${att.attachment_id}`); + } + }); + done(); + }) + .catch(err => { + log(err); + done(err); + }); + }); + + test('updateAttachment', done => { + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + expect(attachment1).not.toBeNull(); + expect(attachment1).not.toBeUndefined(); + + expect(attachmentEtag1).not.toBeNull(); + expect(attachmentEtag1).not.toBeUndefined(); + + const updatedScope = attachment1.included_scope; + updatedScope.note = `Updated: ${attachment1.included_scope.note}`; + + const params = { + ruleId: attachment1.rule_id, + attachmentId: attachment1.attachment_id, + ifMatch: attachmentEtag1, + accountId: attachment1.account_id, + includedScope: updatedScope, + excludedScopes: attachment1.excluded_scopes, + transactionId: transactionId, + }; + + configurationGovernanceService + .updateAttachment(params) + .then(res => { + expect(res).not.toBeNull(); + expect(res.status).toEqual(200); + + const result = res.result; + expect(result).not.toBeNull(); + expect(result.included_scope).not.toBeNull(); + expect(result.included_scope.note.startsWith('Updated:')).toBe(true); + done(); + }) + .catch(err => { + log(err); + done(err); + }); + }); + + test('updateAttachmentInvalidEtag', done => { + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + expect(attachment1).not.toBeNull(); + expect(attachment1).not.toBeUndefined(); + + expect(attachmentEtag1).not.toBeNull(); + expect(attachmentEtag1).not.toBeUndefined(); + + const updatedScope = attachment1.included_scope; + updatedScope.note = `Updated: ${attachment1.included_scope.note}`; + + const params = { + ruleId: attachment1.rule_id, + attachmentId: attachment1.attachment_id, + ifMatch: 'BOGUS_TAG', + accountId: attachment1.account_id, + includedScope: updatedScope, + excludedScopes: attachment1.excluded_scopes, + transactionId: transactionId, + }; + + configurationGovernanceService + .updateAttachment(params) + .then(res => { + log(res); + done('Invalid update should not have succeeded!'); + }) + .catch(err => { + expect(err.status).toEqual(400); + expect(err.message).toContain('If-Match'); + done(); + }); + }); + + test('deleteAttachment', async done => { + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + expect(attachmentId2).not.toBeNull(); + expect(attachmentId2).not.toBeUndefined(); + + const params = { + ruleId: ruleId1, + attachmentId: attachmentId2, + transactionId: transactionId, + }; + + let deleteAttachmentResp; + let listAttachmentsResp; + try { + deleteAttachmentResp = await configurationGovernanceService.deleteAttachment(params); + + // Now verify that listAttachments() returns only 1. + const listAttachmentsParams = { + ruleId: ruleId1, + transactionId: transactionId, + limit: 1000, + offset: 0, + }; + + listAttachmentsResp = await configurationGovernanceService.listAttachments(listAttachmentsParams); + } catch (err) { + log(err); + done(err); + } + + expect(deleteAttachmentResp).not.toBeNull(); + expect(deleteAttachmentResp.status).toEqual(204); + + expect(listAttachmentsResp).not.toBeNull(); + expect(listAttachmentsResp.status).toEqual(200); + + const result = listAttachmentsResp.result; + expect(result).not.toBeNull(); + expect(result.total_count).toEqual(1); + + // Next, make sure we cannot retrieve the deleted attachment via a get. + const attachment = await getAttachment(ruleId1, attachmentId2); + expect(attachment).toBeNull(); + done(); + }); + + test('deleteAttachmentInvalidAttachmentId', done => { + expect(ruleId1).not.toBeNull(); + expect(ruleId1).not.toBeUndefined(); + + const params = { + ruleId: ruleId1, + attachmentId: 'BOGUS_ID', + transactionId: transactionId, + }; + + configurationGovernanceService + .deleteAttachment(params) + .then(res => { + log(res); + done('Invalid delete should not have succeeded!'); + }) + .catch(err => { + expect(err.status).toEqual(404); + expect(err.message).toContain('not found'); + done(); + }); + }); + + // cleanup resources + afterAll(async done => { + log('Starting post clean up...'); + await cleanRules(TEST_LABEL, done); + log('Post clean up complete.'); + done(); + }); +}); + +function log(msg) { + if (verbose) { + console.log(msg); + } +} + +async function cleanRules(label, done) { + log('Cleaning rules...'); + + try { + // List any existing rules for this account with the specified label. + const params = { + accountId: ACCOUNT_ID, + labels: label, + limit: 1000, + offset: 0, + }; + + const res = await configurationGovernanceService.listRules(params); + expect(res).not.toBeNull(); + expect(res.status).toEqual(200); + const ruleListResult = res.result; + expect(ruleListResult).not.toBeNull(); + + log(`Found ${ruleListResult.total_count} rule(s) to be cleaned`); + + // Now walk through the returned rules and delete each one. + if (ruleListResult.total_count > 0) { + for (const rule of ruleListResult.rules) { + const deleteRuleParams = { + ruleId: rule.rule_id, + }; + + log(`Deleting rule: name=${rule.name} id=${rule.rule_id}`); + + const deleteRuleRes = await configurationGovernanceService.deleteRule(deleteRuleParams); + expect(deleteRuleRes).not.toBeNull(); + expect(deleteRuleRes.status).toEqual(204); + } + } + log(`Finished cleaning rules...`); + done(); + } catch (err) { + log(err); + done(err); + } +} + +function initSampleData() { + const ruleTargetAttributeModel = { + name: 'resource_id', + operator: 'is_not_empty', + }; + + const targetResourceModel = { + service_name: TEST_SERVICE_NAME, + resource_kind: 'bucket', + additional_target_attributes: [ruleTargetAttributeModel], + }; + + const allowedGBCondition = { + property: 'allowed_gb', + operator: 'num_less_than_equals', + value: '20', + }; + + const locationCondition = { + property: 'location', + operator: 'string_equals', + value: 'us-east"', + }; + + // Used in sampleRule1. + const ruleRequiredConfigModel1 = { + description: "allowed_gb==20 && location=='us-east'", + and: [allowedGBCondition, locationCondition], + }; + + // Used in sampleRule2. + const ruleRequiredConfigModel2 = { + description: 'allowed_gb<=30', + property: 'allowed_gb', + operator: 'num_less_than_equals', + value: '30', + }; + + const enforcementActionModel = { + action: 'disallow', + }; + + // Sample rules. + sampleRule1 = { + account_id: ACCOUNT_ID, + name: 'Node Test Rule #1', + description: 'This is the description for Node Test Rule #1.', + rule_type: 'user_defined', + target: targetResourceModel, + required_config: ruleRequiredConfigModel1, + enforcement_actions: [enforcementActionModel], + labels: [TEST_LABEL], + }; + + sampleRule2 = { + account_id: ACCOUNT_ID, + name: 'Node Test Rule #2', + description: 'This is the description for Node Test Rule #2.', + rule_type: 'user_defined', + target: targetResourceModel, + required_config: ruleRequiredConfigModel2, + enforcement_actions: [enforcementActionModel], + labels: [TEST_LABEL], + }; + + badSampleRule = { + account_id: ACCOUNT_ID, + name: 'Node Test Rule #2', + description: 'This is the description for Node Test Rule #2.', + rule_type: 'service_defined', + target: targetResourceModel, + required_config: ruleRequiredConfigModel2, + enforcement_actions: [enforcementActionModel], + labels: [TEST_LABEL], + }; + + // Sample rule scopes. + enterpriseScope = { + note: 'enterprise', + scope_id: ENTERPRISE_SCOPE_ID, + scope_type: 'enterprise', + }; + + accountScope = { + note: 'leaf account', + scope_id: SUBACCT_SCOPE_ID, + scope_type: 'enterprise.account', + }; + + badScope = { + note: 'leaf account', + scope_id: SUBACCT_SCOPE_ID, + scope_type: 'enterprise.BOGUS', + }; +} + +async function getRule(ruleId) { + let result = null; + try { + const params = { + ruleId: ruleId, + transactionId: transactionId, + }; + + const res = await configurationGovernanceService.getRule(params); + + if (res != null) { + result = res.result; + } + return result; + } catch (err) { + return result; + } +} + +async function getAttachment(ruleId, attachmentId) { + let result = null; + try { + const params = { + ruleId: ruleId, + attachmentId: attachmentId, + }; + + const res = await configurationGovernanceService.getAttachment(params); + + if (res != null) { + result = res.result; + } + return result; + } catch (err) { + return result; + } +} diff --git a/test/unit/configuration-governance.v1.test.js b/test/unit/configuration-governance.v1.test.js new file mode 100644 index 00000000..9d4a3604 --- /dev/null +++ b/test/unit/configuration-governance.v1.test.js @@ -0,0 +1,1011 @@ +/** + * (C) Copyright IBM Corp. 2020. + * + * 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. + */ +'use strict'; + +// need to import the whole package to mock getAuthenticatorFromEnvironment +const core = require('ibm-cloud-sdk-core'); +const { NoAuthAuthenticator, unitTestUtils } = core; + +const ConfigurationGovernanceV1 = require('../../dist/configuration-governance/v1'); + +const { + getOptions, + checkUrlAndMethod, + checkMediaHeaders, + expectToBePromise, + checkUserHeader, +} = unitTestUtils; + +const service = { + authenticator: new NoAuthAuthenticator(), + url: 'https://compliance.cloud.ibm.com', +}; + +const configurationGovernanceService = new ConfigurationGovernanceV1(service); + +// dont actually create a request +const createRequestMock = jest.spyOn(configurationGovernanceService, 'createRequest'); +createRequestMock.mockImplementation(() => Promise.resolve()); + +// dont actually construct an authenticator +const getAuthenticatorMock = jest.spyOn(core, 'getAuthenticatorFromEnvironment'); +getAuthenticatorMock.mockImplementation(() => new NoAuthAuthenticator()); + +afterEach(() => { + createRequestMock.mockClear(); + getAuthenticatorMock.mockClear(); +}); + +describe('ConfigurationGovernanceV1', () => { + describe('the newInstance method', () => { + test('should use defaults when options not provided', () => { + const testInstance = ConfigurationGovernanceV1.newInstance(); + + expect(getAuthenticatorMock).toHaveBeenCalled(); + expect(testInstance.baseOptions.authenticator).toBeInstanceOf(NoAuthAuthenticator); + expect(testInstance.baseOptions.serviceName).toBe(ConfigurationGovernanceV1.DEFAULT_SERVICE_NAME); + expect(testInstance.baseOptions.serviceUrl).toBe(ConfigurationGovernanceV1.DEFAULT_SERVICE_URL); + expect(testInstance).toBeInstanceOf(ConfigurationGovernanceV1); + }); + + test('should set serviceName, serviceUrl, and authenticator when provided', () => { + const options = { + authenticator: new NoAuthAuthenticator(), + serviceUrl: 'custom.com', + serviceName: 'my-service', + }; + + const testInstance = ConfigurationGovernanceV1.newInstance(options); + + expect(getAuthenticatorMock).not.toHaveBeenCalled(); + expect(testInstance.baseOptions.authenticator).toBeInstanceOf(NoAuthAuthenticator); + expect(testInstance.baseOptions.serviceUrl).toBe('custom.com'); + expect(testInstance.baseOptions.serviceName).toBe('my-service'); + expect(testInstance).toBeInstanceOf(ConfigurationGovernanceV1); + }); + }); + describe('the constructor', () => { + test('use user-given service url', () => { + const options = { + authenticator: new NoAuthAuthenticator(), + serviceUrl: 'custom.com', + }; + + const testInstance = new ConfigurationGovernanceV1(options); + + expect(testInstance.baseOptions.serviceUrl).toBe('custom.com'); + }); + + test('use default service url', () => { + const options = { + authenticator: new NoAuthAuthenticator(), + }; + + const testInstance = new ConfigurationGovernanceV1(options); + + expect(testInstance.baseOptions.serviceUrl).toBe(ConfigurationGovernanceV1.DEFAULT_SERVICE_URL); + }); + }); + describe('createRules', () => { + describe('positive tests', () => { + // Request models needed by this operation. + + // RuleTargetAttribute + const ruleTargetAttributeModel = { + name: 'testString', + operator: 'string_equals', + value: 'testString', + }; + + // TargetResource + const targetResourceModel = { + service_name: 'iam-groups', + resource_kind: 'service', + additional_target_attributes: [ruleTargetAttributeModel], + }; + + // RuleRequiredConfigSingleProperty + const ruleRequiredConfigModel = { + description: 'Public access check', + property: 'public_access_enabled', + operator: 'is_true', + value: 'testString', + }; + + // EnforcementAction + const enforcementActionModel = { + action: 'audit_log', + }; + + // RuleRequest + const ruleRequestModel = { + account_id: '531fc3e28bfc43c5a2cea07786d93f5c', + name: 'Disable public access', + description: 'Ensure that public access to account resources is disabled.', + rule_type: 'user_defined', + target: targetResourceModel, + required_config: ruleRequiredConfigModel, + enforcement_actions: [enforcementActionModel], + labels: ['testString'], + }; + + // CreateRuleRequest + const createRuleRequestModel = { + request_id: '3cebc877-58e7-44a5-a292-32114fa73558', + rule: ruleRequestModel, + }; + + test('should pass the right params to createRequest', () => { + // Construct the params object for operation createRules + const rules = [createRuleRequestModel]; + const transactionId = 'testString'; + const params = { + rules: rules, + transactionId: transactionId, + }; + + const createRulesResult = configurationGovernanceService.createRules(params); + + // all methods should return a Promise + expectToBePromise(createRulesResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const options = getOptions(createRequestMock); + + checkUrlAndMethod(options, '/config/v1/rules', 'POST'); + const expectedAccept = 'application/json'; + const expectedContentType = 'application/json'; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + checkUserHeader(createRequestMock, 'Transaction-Id', transactionId); + expect(options.body['rules']).toEqual(rules); + }); + + test('should prioritize user-given headers', () => { + // parameters + const rules = [createRuleRequestModel]; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const params = { + rules, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + configurationGovernanceService.createRules(params); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async done => { + let err; + try { + await configurationGovernanceService.createRules({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + + test('should reject promise when required params are not given', done => { + const createRulesPromise = configurationGovernanceService.createRules(); + expectToBePromise(createRulesPromise); + + createRulesPromise.catch(err => { + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + }); + }); + }); + describe('listRules', () => { + describe('positive tests', () => { + test('should pass the right params to createRequest', () => { + // Construct the params object for operation listRules + const accountId = '531fc3e28bfc43c5a2cea07786d93f5c'; + const transactionId = 'testString'; + const attached = true; + const labels = 'SOC2,ITCS300'; + const scopes = 'scope_id'; + const limit = 1000; + const offset = 38; + const params = { + accountId: accountId, + transactionId: transactionId, + attached: attached, + labels: labels, + scopes: scopes, + limit: limit, + offset: offset, + }; + + const listRulesResult = configurationGovernanceService.listRules(params); + + // all methods should return a Promise + expectToBePromise(listRulesResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const options = getOptions(createRequestMock); + + checkUrlAndMethod(options, '/config/v1/rules', 'GET'); + const expectedAccept = 'application/json'; + const expectedContentType = undefined; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + checkUserHeader(createRequestMock, 'Transaction-Id', transactionId); + expect(options.qs['account_id']).toEqual(accountId); + expect(options.qs['attached']).toEqual(attached); + expect(options.qs['labels']).toEqual(labels); + expect(options.qs['scopes']).toEqual(scopes); + expect(options.qs['limit']).toEqual(limit); + expect(options.qs['offset']).toEqual(offset); + }); + + test('should prioritize user-given headers', () => { + // parameters + const accountId = '531fc3e28bfc43c5a2cea07786d93f5c'; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const params = { + accountId, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + configurationGovernanceService.listRules(params); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async done => { + let err; + try { + await configurationGovernanceService.listRules({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + + test('should reject promise when required params are not given', done => { + const listRulesPromise = configurationGovernanceService.listRules(); + expectToBePromise(listRulesPromise); + + listRulesPromise.catch(err => { + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + }); + }); + }); + describe('getRule', () => { + describe('positive tests', () => { + test('should pass the right params to createRequest', () => { + // Construct the params object for operation getRule + const ruleId = 'testString'; + const transactionId = 'testString'; + const params = { + ruleId: ruleId, + transactionId: transactionId, + }; + + const getRuleResult = configurationGovernanceService.getRule(params); + + // all methods should return a Promise + expectToBePromise(getRuleResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const options = getOptions(createRequestMock); + + checkUrlAndMethod(options, '/config/v1/rules/{rule_id}', 'GET'); + const expectedAccept = 'application/json'; + const expectedContentType = undefined; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + checkUserHeader(createRequestMock, 'Transaction-Id', transactionId); + expect(options.path['rule_id']).toEqual(ruleId); + }); + + test('should prioritize user-given headers', () => { + // parameters + const ruleId = 'testString'; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const params = { + ruleId, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + configurationGovernanceService.getRule(params); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async done => { + let err; + try { + await configurationGovernanceService.getRule({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + + test('should reject promise when required params are not given', done => { + const getRulePromise = configurationGovernanceService.getRule(); + expectToBePromise(getRulePromise); + + getRulePromise.catch(err => { + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + }); + }); + }); + describe('updateRule', () => { + describe('positive tests', () => { + // Request models needed by this operation. + + // RuleTargetAttribute + const ruleTargetAttributeModel = { + name: 'testString', + operator: 'string_equals', + value: 'testString', + }; + + // TargetResource + const targetResourceModel = { + service_name: 'iam-groups', + resource_kind: 'service', + additional_target_attributes: [ruleTargetAttributeModel], + }; + + // RuleRequiredConfigSingleProperty + const ruleRequiredConfigModel = { + description: 'testString', + property: 'public_access_enabled', + operator: 'is_false', + value: 'testString', + }; + + // EnforcementAction + const enforcementActionModel = { + action: 'audit_log', + }; + + test('should pass the right params to createRequest', () => { + // Construct the params object for operation updateRule + const ruleId = 'testString'; + const ifMatch = 'testString'; + const name = 'Disable public access'; + const description = 'Ensure that public access to account resources is disabled.'; + const target = targetResourceModel; + const requiredConfig = ruleRequiredConfigModel; + const enforcementActions = [enforcementActionModel]; + const accountId = '531fc3e28bfc43c5a2cea07786d93f5c'; + const ruleType = 'user_defined'; + const labels = ['testString']; + const transactionId = 'testString'; + const params = { + ruleId: ruleId, + ifMatch: ifMatch, + name: name, + description: description, + target: target, + requiredConfig: requiredConfig, + enforcementActions: enforcementActions, + accountId: accountId, + ruleType: ruleType, + labels: labels, + transactionId: transactionId, + }; + + const updateRuleResult = configurationGovernanceService.updateRule(params); + + // all methods should return a Promise + expectToBePromise(updateRuleResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const options = getOptions(createRequestMock); + + checkUrlAndMethod(options, '/config/v1/rules/{rule_id}', 'PUT'); + const expectedAccept = 'application/json'; + const expectedContentType = 'application/json'; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + checkUserHeader(createRequestMock, 'If-Match', ifMatch); + checkUserHeader(createRequestMock, 'Transaction-Id', transactionId); + expect(options.body['name']).toEqual(name); + expect(options.body['description']).toEqual(description); + expect(options.body['target']).toEqual(target); + expect(options.body['required_config']).toEqual(requiredConfig); + expect(options.body['enforcement_actions']).toEqual(enforcementActions); + expect(options.body['account_id']).toEqual(accountId); + expect(options.body['rule_type']).toEqual(ruleType); + expect(options.body['labels']).toEqual(labels); + expect(options.path['rule_id']).toEqual(ruleId); + }); + + test('should prioritize user-given headers', () => { + // parameters + const ruleId = 'testString'; + const ifMatch = 'testString'; + const name = 'Disable public access'; + const description = 'Ensure that public access to account resources is disabled.'; + const target = targetResourceModel; + const requiredConfig = ruleRequiredConfigModel; + const enforcementActions = [enforcementActionModel]; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const params = { + ruleId, + ifMatch, + name, + description, + target, + requiredConfig, + enforcementActions, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + configurationGovernanceService.updateRule(params); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async done => { + let err; + try { + await configurationGovernanceService.updateRule({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + + test('should reject promise when required params are not given', done => { + const updateRulePromise = configurationGovernanceService.updateRule(); + expectToBePromise(updateRulePromise); + + updateRulePromise.catch(err => { + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + }); + }); + }); + describe('deleteRule', () => { + describe('positive tests', () => { + test('should pass the right params to createRequest', () => { + // Construct the params object for operation deleteRule + const ruleId = 'testString'; + const transactionId = 'testString'; + const params = { + ruleId: ruleId, + transactionId: transactionId, + }; + + const deleteRuleResult = configurationGovernanceService.deleteRule(params); + + // all methods should return a Promise + expectToBePromise(deleteRuleResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const options = getOptions(createRequestMock); + + checkUrlAndMethod(options, '/config/v1/rules/{rule_id}', 'DELETE'); + const expectedAccept = undefined; + const expectedContentType = undefined; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + checkUserHeader(createRequestMock, 'Transaction-Id', transactionId); + expect(options.path['rule_id']).toEqual(ruleId); + }); + + test('should prioritize user-given headers', () => { + // parameters + const ruleId = 'testString'; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const params = { + ruleId, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + configurationGovernanceService.deleteRule(params); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async done => { + let err; + try { + await configurationGovernanceService.deleteRule({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + + test('should reject promise when required params are not given', done => { + const deleteRulePromise = configurationGovernanceService.deleteRule(); + expectToBePromise(deleteRulePromise); + + deleteRulePromise.catch(err => { + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + }); + }); + }); + describe('createAttachments', () => { + describe('positive tests', () => { + // Request models needed by this operation. + + // RuleScope + const ruleScopeModel = { + note: 'My enterprise', + scope_id: '282cf433ac91493ba860480d92519990', + scope_type: 'enterprise', + }; + + // AttachmentRequest + const attachmentRequestModel = { + account_id: '531fc3e28bfc43c5a2cea07786d93f5c', + included_scope: ruleScopeModel, + excluded_scopes: [ruleScopeModel], + }; + + test('should pass the right params to createRequest', () => { + // Construct the params object for operation createAttachments + const ruleId = 'testString'; + const attachments = [attachmentRequestModel]; + const transactionId = 'testString'; + const params = { + ruleId: ruleId, + attachments: attachments, + transactionId: transactionId, + }; + + const createAttachmentsResult = configurationGovernanceService.createAttachments(params); + + // all methods should return a Promise + expectToBePromise(createAttachmentsResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const options = getOptions(createRequestMock); + + checkUrlAndMethod(options, '/config/v1/rules/{rule_id}/attachments', 'POST'); + const expectedAccept = 'application/json'; + const expectedContentType = 'application/json'; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + checkUserHeader(createRequestMock, 'Transaction-Id', transactionId); + expect(options.body['attachments']).toEqual(attachments); + expect(options.path['rule_id']).toEqual(ruleId); + }); + + test('should prioritize user-given headers', () => { + // parameters + const ruleId = 'testString'; + const attachments = [attachmentRequestModel]; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const params = { + ruleId, + attachments, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + configurationGovernanceService.createAttachments(params); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async done => { + let err; + try { + await configurationGovernanceService.createAttachments({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + + test('should reject promise when required params are not given', done => { + const createAttachmentsPromise = configurationGovernanceService.createAttachments(); + expectToBePromise(createAttachmentsPromise); + + createAttachmentsPromise.catch(err => { + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + }); + }); + }); + describe('listAttachments', () => { + describe('positive tests', () => { + test('should pass the right params to createRequest', () => { + // Construct the params object for operation listAttachments + const ruleId = 'testString'; + const transactionId = 'testString'; + const limit = 1000; + const offset = 38; + const params = { + ruleId: ruleId, + transactionId: transactionId, + limit: limit, + offset: offset, + }; + + const listAttachmentsResult = configurationGovernanceService.listAttachments(params); + + // all methods should return a Promise + expectToBePromise(listAttachmentsResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const options = getOptions(createRequestMock); + + checkUrlAndMethod(options, '/config/v1/rules/{rule_id}/attachments', 'GET'); + const expectedAccept = 'application/json'; + const expectedContentType = undefined; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + checkUserHeader(createRequestMock, 'Transaction-Id', transactionId); + expect(options.qs['limit']).toEqual(limit); + expect(options.qs['offset']).toEqual(offset); + expect(options.path['rule_id']).toEqual(ruleId); + }); + + test('should prioritize user-given headers', () => { + // parameters + const ruleId = 'testString'; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const params = { + ruleId, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + configurationGovernanceService.listAttachments(params); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async done => { + let err; + try { + await configurationGovernanceService.listAttachments({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + + test('should reject promise when required params are not given', done => { + const listAttachmentsPromise = configurationGovernanceService.listAttachments(); + expectToBePromise(listAttachmentsPromise); + + listAttachmentsPromise.catch(err => { + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + }); + }); + }); + describe('getAttachment', () => { + describe('positive tests', () => { + test('should pass the right params to createRequest', () => { + // Construct the params object for operation getAttachment + const ruleId = 'testString'; + const attachmentId = 'testString'; + const transactionId = 'testString'; + const params = { + ruleId: ruleId, + attachmentId: attachmentId, + transactionId: transactionId, + }; + + const getAttachmentResult = configurationGovernanceService.getAttachment(params); + + // all methods should return a Promise + expectToBePromise(getAttachmentResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const options = getOptions(createRequestMock); + + checkUrlAndMethod(options, '/config/v1/rules/{rule_id}/attachments/{attachment_id}', 'GET'); + const expectedAccept = 'application/json'; + const expectedContentType = undefined; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + checkUserHeader(createRequestMock, 'Transaction-Id', transactionId); + expect(options.path['rule_id']).toEqual(ruleId); + expect(options.path['attachment_id']).toEqual(attachmentId); + }); + + test('should prioritize user-given headers', () => { + // parameters + const ruleId = 'testString'; + const attachmentId = 'testString'; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const params = { + ruleId, + attachmentId, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + configurationGovernanceService.getAttachment(params); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async done => { + let err; + try { + await configurationGovernanceService.getAttachment({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + + test('should reject promise when required params are not given', done => { + const getAttachmentPromise = configurationGovernanceService.getAttachment(); + expectToBePromise(getAttachmentPromise); + + getAttachmentPromise.catch(err => { + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + }); + }); + }); + describe('updateAttachment', () => { + describe('positive tests', () => { + // Request models needed by this operation. + + // RuleScope + const ruleScopeModel = { + note: 'My enterprise', + scope_id: '282cf433ac91493ba860480d92519990', + scope_type: 'enterprise', + }; + + test('should pass the right params to createRequest', () => { + // Construct the params object for operation updateAttachment + const ruleId = 'testString'; + const attachmentId = 'testString'; + const ifMatch = 'testString'; + const accountId = '531fc3e28bfc43c5a2cea07786d93f5c'; + const includedScope = ruleScopeModel; + const excludedScopes = [ruleScopeModel]; + const transactionId = 'testString'; + const params = { + ruleId: ruleId, + attachmentId: attachmentId, + ifMatch: ifMatch, + accountId: accountId, + includedScope: includedScope, + excludedScopes: excludedScopes, + transactionId: transactionId, + }; + + const updateAttachmentResult = configurationGovernanceService.updateAttachment(params); + + // all methods should return a Promise + expectToBePromise(updateAttachmentResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const options = getOptions(createRequestMock); + + checkUrlAndMethod(options, '/config/v1/rules/{rule_id}/attachments/{attachment_id}', 'PUT'); + const expectedAccept = 'application/json'; + const expectedContentType = 'application/json'; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + checkUserHeader(createRequestMock, 'If-Match', ifMatch); + checkUserHeader(createRequestMock, 'Transaction-Id', transactionId); + expect(options.body['account_id']).toEqual(accountId); + expect(options.body['included_scope']).toEqual(includedScope); + expect(options.body['excluded_scopes']).toEqual(excludedScopes); + expect(options.path['rule_id']).toEqual(ruleId); + expect(options.path['attachment_id']).toEqual(attachmentId); + }); + + test('should prioritize user-given headers', () => { + // parameters + const ruleId = 'testString'; + const attachmentId = 'testString'; + const ifMatch = 'testString'; + const accountId = '531fc3e28bfc43c5a2cea07786d93f5c'; + const includedScope = ruleScopeModel; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const params = { + ruleId, + attachmentId, + ifMatch, + accountId, + includedScope, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + configurationGovernanceService.updateAttachment(params); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async done => { + let err; + try { + await configurationGovernanceService.updateAttachment({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + + test('should reject promise when required params are not given', done => { + const updateAttachmentPromise = configurationGovernanceService.updateAttachment(); + expectToBePromise(updateAttachmentPromise); + + updateAttachmentPromise.catch(err => { + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + }); + }); + }); + describe('deleteAttachment', () => { + describe('positive tests', () => { + test('should pass the right params to createRequest', () => { + // Construct the params object for operation deleteAttachment + const ruleId = 'testString'; + const attachmentId = 'testString'; + const transactionId = 'testString'; + const params = { + ruleId: ruleId, + attachmentId: attachmentId, + transactionId: transactionId, + }; + + const deleteAttachmentResult = configurationGovernanceService.deleteAttachment(params); + + // all methods should return a Promise + expectToBePromise(deleteAttachmentResult); + + // assert that create request was called + expect(createRequestMock).toHaveBeenCalledTimes(1); + + const options = getOptions(createRequestMock); + + checkUrlAndMethod(options, '/config/v1/rules/{rule_id}/attachments/{attachment_id}', 'DELETE'); + const expectedAccept = undefined; + const expectedContentType = undefined; + checkMediaHeaders(createRequestMock, expectedAccept, expectedContentType); + checkUserHeader(createRequestMock, 'Transaction-Id', transactionId); + expect(options.path['rule_id']).toEqual(ruleId); + expect(options.path['attachment_id']).toEqual(attachmentId); + }); + + test('should prioritize user-given headers', () => { + // parameters + const ruleId = 'testString'; + const attachmentId = 'testString'; + const userAccept = 'fake/accept'; + const userContentType = 'fake/contentType'; + const params = { + ruleId, + attachmentId, + headers: { + Accept: userAccept, + 'Content-Type': userContentType, + }, + }; + + configurationGovernanceService.deleteAttachment(params); + checkMediaHeaders(createRequestMock, userAccept, userContentType); + }); + }); + + describe('negative tests', () => { + test('should enforce required parameters', async done => { + let err; + try { + await configurationGovernanceService.deleteAttachment({}); + } catch (e) { + err = e; + } + + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + + test('should reject promise when required params are not given', done => { + const deleteAttachmentPromise = configurationGovernanceService.deleteAttachment(); + expectToBePromise(deleteAttachmentPromise); + + deleteAttachmentPromise.catch(err => { + expect(err.message).toMatch(/Missing required parameters/); + done(); + }); + }); + }); + }); +});