From b270d2891d88149caa3de66096e727e82df0233e Mon Sep 17 00:00:00 2001 From: Elena Izaguirre Date: Fri, 5 Nov 2021 10:14:24 +0100 Subject: [PATCH] fix: openapi validation for keychain-aws-sm plugin Includes tests for endpoints setKeychainEntry, getKeychainEntryV1, hasKeychainEntryV1 and deleteKeychainEntryV1, each of them with test cases: - Right request - Request including an invalid parameter - Request without a required parameter Relationed with #847 Signed-off-by: Elena Izaguirre --- .../src/main/json/openapi.json | 42 +-- .../generated/openapi/typescript-axios/api.ts | 84 ++--- .../set-keychain-entry-endpoint-v1.ts | 4 +- .../openapi/openapi-validation.test.ts | 325 ++++++++++++++++++ 4 files changed, 390 insertions(+), 65 deletions(-) create mode 100644 packages/cactus-plugin-keychain-aws-sm/src/test/typescript/integration/openapi/openapi-validation.test.ts diff --git a/packages/cactus-plugin-keychain-aws-sm/src/main/json/openapi.json b/packages/cactus-plugin-keychain-aws-sm/src/main/json/openapi.json index c40f6ee993..626064c7a4 100644 --- a/packages/cactus-plugin-keychain-aws-sm/src/main/json/openapi.json +++ b/packages/cactus-plugin-keychain-aws-sm/src/main/json/openapi.json @@ -35,23 +35,23 @@ "summary": "Retrieves the contents of a keychain entry from the backend.", "parameters": [], "requestBody": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/requestBodies/keychain_get_entry_request_body" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/requestBodies/keychain_get_entry_request_body" }, "responses": { "200": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_200" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_200" }, "400": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_400" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_400" }, "401": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_401" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_401" }, "404": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_404" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_404" }, "500": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_500" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_500" } } } @@ -68,20 +68,20 @@ "summary": "Sets a value under a key on the keychain backend.", "parameters": [], "requestBody": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/requestBodies/keychain_set_entry_request_body" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/requestBodies/keychain_set_entry_request_body" }, "responses": { "200": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_200" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_200" }, "400": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_400" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_400" }, "401": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_401" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_401" }, "500": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_500" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_500" } } } @@ -98,20 +98,20 @@ "summary": "Deletes an entry under a key on the keychain backend.", "parameters": [], "requestBody": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/requestBodies/keychain_delete_entry_request_body" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/requestBodies/keychain_delete_entry_request_body" }, "responses": { "200": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_delete_entry_200" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_delete_entry_200" }, "400": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_delete_entry_400" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_delete_entry_400" }, "401": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_delete_entry_401" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_delete_entry_401" }, "500": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_delete_entry_500" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_delete_entry_500" } } } @@ -128,20 +128,20 @@ "summary": "Checks that an entry exists under a key on the keychain backend", "parameters": [], "requestBody": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/requestBodies/keychain_has_entry_request_body" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/requestBodies/keychain_has_entry_request_body" }, "responses": { "200": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_200" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_200" }, "400": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_400" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_400" }, "401": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_401" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_401" }, "500": { - "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.9.0/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_500" + "$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v1.0.0-rc.2/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_500" } } } diff --git a/packages/cactus-plugin-keychain-aws-sm/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-plugin-keychain-aws-sm/src/main/typescript/generated/openapi/typescript-axios/api.ts index 5aa7e36797..b52cb7f1ca 100644 --- a/packages/cactus-plugin-keychain-aws-sm/src/main/typescript/generated/openapi/typescript-axios/api.ts +++ b/packages/cactus-plugin-keychain-aws-sm/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -50,32 +50,32 @@ export interface DeleteKeychainEntryResponseV1 { /** * * @export - * @interface GetKeychainEntryRequest + * @interface GetKeychainEntryRequestV1 */ -export interface GetKeychainEntryRequest { +export interface GetKeychainEntryRequestV1 { /** * The key for the entry to get from the keychain. * @type {string} - * @memberof GetKeychainEntryRequest + * @memberof GetKeychainEntryRequestV1 */ key: string; } /** * * @export - * @interface GetKeychainEntryResponse + * @interface GetKeychainEntryResponseV1 */ -export interface GetKeychainEntryResponse { +export interface GetKeychainEntryResponseV1 { /** * The key that was used to retrieve the value from the keychain. * @type {string} - * @memberof GetKeychainEntryResponse + * @memberof GetKeychainEntryResponseV1 */ key: string; /** * The value associated with the requested key on the keychain. * @type {string} - * @memberof GetKeychainEntryResponse + * @memberof GetKeychainEntryResponseV1 */ value: string; } @@ -120,32 +120,32 @@ export interface HasKeychainEntryResponseV1 { /** * * @export - * @interface SetKeychainEntryRequest + * @interface SetKeychainEntryRequestV1 */ -export interface SetKeychainEntryRequest { +export interface SetKeychainEntryRequestV1 { /** * The key for the entry to set on the keychain. * @type {string} - * @memberof SetKeychainEntryRequest + * @memberof SetKeychainEntryRequestV1 */ key: string; /** * The value that will be associated with the key on the keychain. * @type {string} - * @memberof SetKeychainEntryRequest + * @memberof SetKeychainEntryRequestV1 */ value: string; } /** * * @export - * @interface SetKeychainEntryResponse + * @interface SetKeychainEntryResponseV1 */ -export interface SetKeychainEntryResponse { +export interface SetKeychainEntryResponseV1 { /** * The key that was used to set the value on the keychain. * @type {string} - * @memberof SetKeychainEntryResponse + * @memberof SetKeychainEntryResponseV1 */ key: string; } @@ -195,13 +195,13 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati /** * * @summary Retrieves the contents of a keychain entry from the backend. - * @param {GetKeychainEntryRequest} getKeychainEntryRequest Request body to obtain a keychain entry via its key + * @param {GetKeychainEntryRequestV1} getKeychainEntryRequestV1 Request body to obtain a keychain entry via its key * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getKeychainEntryV1: async (getKeychainEntryRequest: GetKeychainEntryRequest, options: any = {}): Promise => { - // verify required parameter 'getKeychainEntryRequest' is not null or undefined - assertParamExists('getKeychainEntryV1', 'getKeychainEntryRequest', getKeychainEntryRequest) + getKeychainEntryV1: async (getKeychainEntryRequestV1: GetKeychainEntryRequestV1, options: any = {}): Promise => { + // verify required parameter 'getKeychainEntryRequestV1' is not null or undefined + assertParamExists('getKeychainEntryV1', 'getKeychainEntryRequestV1', getKeychainEntryRequestV1) const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-keychain-aws-sm/get-keychain-entry`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -221,7 +221,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(getKeychainEntryRequest, localVarRequestOptions, configuration) + localVarRequestOptions.data = serializeDataIfNeeded(getKeychainEntryRequestV1, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -267,13 +267,13 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati /** * * @summary Sets a value under a key on the keychain backend. - * @param {SetKeychainEntryRequest} setKeychainEntryRequest Request body to write/update a keychain entry via its key + * @param {SetKeychainEntryRequestV1} setKeychainEntryRequestV1 Request body to write/update a keychain entry via its key * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setKeychainEntryV1: async (setKeychainEntryRequest: SetKeychainEntryRequest, options: any = {}): Promise => { - // verify required parameter 'setKeychainEntryRequest' is not null or undefined - assertParamExists('setKeychainEntryV1', 'setKeychainEntryRequest', setKeychainEntryRequest) + setKeychainEntryV1: async (setKeychainEntryRequestV1: SetKeychainEntryRequestV1, options: any = {}): Promise => { + // verify required parameter 'setKeychainEntryRequestV1' is not null or undefined + assertParamExists('setKeychainEntryV1', 'setKeychainEntryRequestV1', setKeychainEntryRequestV1) const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-keychain-aws-sm/set-keychain-entry`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -293,7 +293,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(setKeychainEntryRequest, localVarRequestOptions, configuration) + localVarRequestOptions.data = serializeDataIfNeeded(setKeychainEntryRequestV1, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -324,12 +324,12 @@ export const DefaultApiFp = function(configuration?: Configuration) { /** * * @summary Retrieves the contents of a keychain entry from the backend. - * @param {GetKeychainEntryRequest} getKeychainEntryRequest Request body to obtain a keychain entry via its key + * @param {GetKeychainEntryRequestV1} getKeychainEntryRequestV1 Request body to obtain a keychain entry via its key * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getKeychainEntryV1(getKeychainEntryRequest: GetKeychainEntryRequest, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getKeychainEntryV1(getKeychainEntryRequest, options); + async getKeychainEntryV1(getKeychainEntryRequestV1: GetKeychainEntryRequestV1, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getKeychainEntryV1(getKeychainEntryRequestV1, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** @@ -346,12 +346,12 @@ export const DefaultApiFp = function(configuration?: Configuration) { /** * * @summary Sets a value under a key on the keychain backend. - * @param {SetKeychainEntryRequest} setKeychainEntryRequest Request body to write/update a keychain entry via its key + * @param {SetKeychainEntryRequestV1} setKeychainEntryRequestV1 Request body to write/update a keychain entry via its key * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async setKeychainEntryV1(setKeychainEntryRequest: SetKeychainEntryRequest, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.setKeychainEntryV1(setKeychainEntryRequest, options); + async setKeychainEntryV1(setKeychainEntryRequestV1: SetKeychainEntryRequestV1, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.setKeychainEntryV1(setKeychainEntryRequestV1, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, } @@ -377,12 +377,12 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa /** * * @summary Retrieves the contents of a keychain entry from the backend. - * @param {GetKeychainEntryRequest} getKeychainEntryRequest Request body to obtain a keychain entry via its key + * @param {GetKeychainEntryRequestV1} getKeychainEntryRequestV1 Request body to obtain a keychain entry via its key * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getKeychainEntryV1(getKeychainEntryRequest: GetKeychainEntryRequest, options?: any): AxiosPromise { - return localVarFp.getKeychainEntryV1(getKeychainEntryRequest, options).then((request) => request(axios, basePath)); + getKeychainEntryV1(getKeychainEntryRequestV1: GetKeychainEntryRequestV1, options?: any): AxiosPromise { + return localVarFp.getKeychainEntryV1(getKeychainEntryRequestV1, options).then((request) => request(axios, basePath)); }, /** * @@ -397,12 +397,12 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa /** * * @summary Sets a value under a key on the keychain backend. - * @param {SetKeychainEntryRequest} setKeychainEntryRequest Request body to write/update a keychain entry via its key + * @param {SetKeychainEntryRequestV1} setKeychainEntryRequestV1 Request body to write/update a keychain entry via its key * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setKeychainEntryV1(setKeychainEntryRequest: SetKeychainEntryRequest, options?: any): AxiosPromise { - return localVarFp.setKeychainEntryV1(setKeychainEntryRequest, options).then((request) => request(axios, basePath)); + setKeychainEntryV1(setKeychainEntryRequestV1: SetKeychainEntryRequestV1, options?: any): AxiosPromise { + return localVarFp.setKeychainEntryV1(setKeychainEntryRequestV1, options).then((request) => request(axios, basePath)); }, }; }; @@ -429,13 +429,13 @@ export class DefaultApi extends BaseAPI { /** * * @summary Retrieves the contents of a keychain entry from the backend. - * @param {GetKeychainEntryRequest} getKeychainEntryRequest Request body to obtain a keychain entry via its key + * @param {GetKeychainEntryRequestV1} getKeychainEntryRequestV1 Request body to obtain a keychain entry via its key * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public getKeychainEntryV1(getKeychainEntryRequest: GetKeychainEntryRequest, options?: any) { - return DefaultApiFp(this.configuration).getKeychainEntryV1(getKeychainEntryRequest, options).then((request) => request(this.axios, this.basePath)); + public getKeychainEntryV1(getKeychainEntryRequestV1: GetKeychainEntryRequestV1, options?: any) { + return DefaultApiFp(this.configuration).getKeychainEntryV1(getKeychainEntryRequestV1, options).then((request) => request(this.axios, this.basePath)); } /** @@ -453,13 +453,13 @@ export class DefaultApi extends BaseAPI { /** * * @summary Sets a value under a key on the keychain backend. - * @param {SetKeychainEntryRequest} setKeychainEntryRequest Request body to write/update a keychain entry via its key + * @param {SetKeychainEntryRequestV1} setKeychainEntryRequestV1 Request body to write/update a keychain entry via its key * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public setKeychainEntryV1(setKeychainEntryRequest: SetKeychainEntryRequest, options?: any) { - return DefaultApiFp(this.configuration).setKeychainEntryV1(setKeychainEntryRequest, options).then((request) => request(this.axios, this.basePath)); + public setKeychainEntryV1(setKeychainEntryRequestV1: SetKeychainEntryRequestV1, options?: any) { + return DefaultApiFp(this.configuration).setKeychainEntryV1(setKeychainEntryRequestV1, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/packages/cactus-plugin-keychain-aws-sm/src/main/typescript/webservices/set-keychain-entry-endpoint-v1.ts b/packages/cactus-plugin-keychain-aws-sm/src/main/typescript/webservices/set-keychain-entry-endpoint-v1.ts index 7f6608d9d7..77cad4cbff 100644 --- a/packages/cactus-plugin-keychain-aws-sm/src/main/typescript/webservices/set-keychain-entry-endpoint-v1.ts +++ b/packages/cactus-plugin-keychain-aws-sm/src/main/typescript/webservices/set-keychain-entry-endpoint-v1.ts @@ -16,7 +16,7 @@ import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; import OAS from "../../json/openapi.json"; import { PluginKeychainAwsSm } from "../plugin-keychain-aws-sm"; -import { SetKeychainEntryRequest } from "../generated/openapi/typescript-axios/api"; +import { SetKeychainEntryRequestV1 } from "../generated/openapi/typescript-axios/api"; export interface ISetKeychainEntryEndpointOptions { logLevel?: LogLevelDesc; @@ -87,7 +87,7 @@ export class SetKeychainEntryV1Endpoint implements IWebServiceEndpoint { const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; this.log.debug(reqTag); try { - const { key, value } = req.body as SetKeychainEntryRequest; + const { key, value } = req.body as SetKeychainEntryRequestV1; const resBody = await this.options.connector.set(key, value); res.json(resBody); } catch (ex) { diff --git a/packages/cactus-plugin-keychain-aws-sm/src/test/typescript/integration/openapi/openapi-validation.test.ts b/packages/cactus-plugin-keychain-aws-sm/src/test/typescript/integration/openapi/openapi-validation.test.ts new file mode 100644 index 0000000000..3c87903813 --- /dev/null +++ b/packages/cactus-plugin-keychain-aws-sm/src/test/typescript/integration/openapi/openapi-validation.test.ts @@ -0,0 +1,325 @@ +import test, { Test } from "tape-promise/tape"; +import { v4 as internalIpV4 } from "internal-ip"; + +import { + Containers, + LocalStackContainer, + K_DEFAULT_LOCALSTACK_HTTP_PORT, +} from "@hyperledger/cactus-test-tooling"; + +import { v4 as uuidv4 } from "uuid"; + +import { + IListenOptions, + LogLevelDesc, + Servers, +} from "@hyperledger/cactus-common"; + +import { + IPluginKeychainAwsSmOptions, + PluginKeychainAwsSm, + AwsCredentialType, + DefaultApi as KeychainAwsSmApi, + Configuration, + SetKeychainEntryRequestV1, + GetKeychainEntryRequestV1, + HasKeychainEntryRequestV1, + DeleteKeychainEntryRequestV1, +} from "../../../../main/typescript/public-api"; + +import fs from "fs"; +import path from "path"; +import os from "os"; +import express from "express"; +import bodyParser from "body-parser"; +import http from "http"; + +import { + installOpenapiValidationMiddleware, + PluginRegistry, +} from "@hyperledger/cactus-core"; +import OAS from "../../../../main/json/openapi.json"; +import { AddressInfo } from "net"; + +const logLevel: LogLevelDesc = "TRACE"; +const testCase = "cactus-plugin-keychain-aws-sm API"; + +test(testCase, async (t: Test) => { + const localStackContainer = new LocalStackContainer({ + logLevel: logLevel, + }); + await localStackContainer.start(); + + const ci = await Containers.getById(localStackContainer.containerId); + const localstackIpAddr = await internalIpV4(); + const hostPort = await Containers.getPublicPort( + K_DEFAULT_LOCALSTACK_HTTP_PORT, + ci, + ); + const localstackHost = `http://${localstackIpAddr}:${hostPort}`; + + test.onFinish(async () => { + await localStackContainer.stop(); + await localStackContainer.destroy(); + }); + + let tmpDirPath = "tmpDirPath"; + tmpDirPath = await fs.promises.mkdtemp(path.join(os.tmpdir(), "cactus-")); + await fs.promises.writeFile( + `${tmpDirPath}/credentials`, + "[default]\naws_secret_access_key = test\naws_access_key_id = test", + "utf-8", + ); + + const options: IPluginKeychainAwsSmOptions = { + instanceId: uuidv4(), + keychainId: uuidv4(), + pluginRegistry: new PluginRegistry({}), + awsEndpoint: localstackHost, + awsRegion: "us-east-1", + awsProfile: "default", + awsCredentialType: AwsCredentialType.LocalFile, + awsCredentialFilePath: `${tmpDirPath}/credentials`, + logLevel: logLevel, + }; + const plugin = new PluginKeychainAwsSm(options); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + const server = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "0.0.0.0", + port: 0, + server, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + test.onFinish(async () => await Servers.shutdown(server)); + const { address, port } = addressInfo; + const apiHost = `http://${address}:${port}`; + + const apiConfig = new Configuration({ basePath: apiHost }); + const apiClient = new KeychainAwsSmApi(apiConfig); + + await installOpenapiValidationMiddleware({ + logLevel, + app: expressApp, + apiSpec: OAS, + }); + + await plugin.getOrCreateWebServices(); + await plugin.registerWebServices(expressApp); + + const key = uuidv4(); + const value = uuidv4(); + + const fSet = "setKeychainEntryV1"; + const fGet = "getKeychainEntryV1"; + const fHas = "hasKeychainEntryV1"; + const fDelete = "deleteKeychainEntryV1"; + const cOk = "without bad request error"; + const cWithoutParams = "not sending all required parameters"; + const cInvalidParams = "sending invalid parameters"; + + test(`${testCase} - ${fSet} - ${cOk}`, async (t2: Test) => { + const res = await apiClient.setKeychainEntryV1({ + key, + value, + }); + t2.equal(res.status, 200, `Endpoint ${fSet}: response.status === 200 OK`); + t2.end(); + }); + + test(`${testCase} - ${fGet} - ${cOk}`, async (t2: Test) => { + const res = await apiClient.getKeychainEntryV1({ key }); + t2.equal(res.status, 200, `Endpoint ${fGet}: response.status === 200 OK`); + t2.equal(res.data.value, value, "response.data.value === value1"); + t2.end(); + }); + + test(`${testCase} - ${fHas} - ${cOk}`, async (t2: Test) => { + const res = await apiClient.hasKeychainEntryV1({ key }); + t2.equal(res.status, 200, `Endpoint ${fHas}: response.status === 200 OK`); + t2.end(); + }); + + test(`${testCase} - ${fDelete} - ${cOk}`, async (t2: Test) => { + const res = await apiClient.deleteKeychainEntryV1({ key }); + t2.equal( + res.status, + 200, + `Endpoint ${fDelete}: response.status === 200 OK`, + ); + t2.end(); + }); + + test(`${testCase} - ${fSet} - ${cWithoutParams}`, async (t2: Test) => { + try { + await apiClient.setKeychainEntryV1(({ + value: value, + } as any) as SetKeychainEntryRequestV1); + } catch (e) { + t2.equal( + e.response.status, + 400, + `Endpoint ${fSet} without required key: response.status === 400 OK`, + ); + const fields = e.response.data.map((param: any) => + param.path.replace(".body.", ""), + ); + t2.ok(fields.includes("key"), "Rejected because key is required"); + } + t2.end(); + }); + + test(`${testCase} - ${fGet} - ${cWithoutParams}`, async (t2: Test) => { + try { + await apiClient.getKeychainEntryV1( + ({} as any) as GetKeychainEntryRequestV1, + ); + } catch (e) { + t2.equal( + e.response.status, + 400, + `Endpoint ${fGet} without required key: response.status === 400 OK`, + ); + const fields = e.response.data.map((param: any) => + param.path.replace(".body.", ""), + ); + t2.ok(fields.includes("key"), "Rejected because key is required"); + } + t2.end(); + }); + + test(`${testCase} - ${fHas} - ${cWithoutParams}`, async (t2: Test) => { + try { + await apiClient.hasKeychainEntryV1( + ({} as any) as HasKeychainEntryRequestV1, + ); + } catch (e) { + t2.equal( + e.response.status, + 400, + `Endpoint ${fHas} without required key: response.status === 400 OK`, + ); + const fields = e.response.data.map((param: any) => + param.path.replace(".body.", ""), + ); + t2.ok(fields.includes("key"), "Rejected because key is required"); + } + t2.end(); + }); + + test(`${testCase} - ${fDelete} - ${cWithoutParams}`, async (t2: Test) => { + try { + await apiClient.deleteKeychainEntryV1( + ({} as any) as DeleteKeychainEntryRequestV1, + ); + } catch (e) { + t2.equal( + e.response.status, + 400, + `Endpoint ${fDelete} without required key: response.status === 400 OK`, + ); + const fields = e.response.data.map((param: any) => + param.path.replace(".body.", ""), + ); + t2.ok(fields.includes("key"), "Rejected because key is required"); + } + t2.end(); + }); + + test(`${testCase} - ${fSet} - ${cInvalidParams}`, async (t2: Test) => { + try { + await apiClient.setKeychainEntryV1(({ + key, + value, + fake: 4, + } as any) as SetKeychainEntryRequestV1); + } catch (e) { + t2.equal( + e.response.status, + 400, + `Endpoint ${fSet} with fake=4: response.status === 400 OK`, + ); + const fields = e.response.data.map((param: any) => + param.path.replace(".body.", ""), + ); + t2.ok( + fields.includes("fake"), + "Rejected because fake is not a valid parameter", + ); + } + t2.end(); + }); + + test(`${testCase} - ${fGet} - ${cInvalidParams}`, async (t2: Test) => { + try { + await apiClient.getKeychainEntryV1(({ + key, + fake: 4, + } as any) as GetKeychainEntryRequestV1); + } catch (e) { + t2.equal( + e.response.status, + 400, + `Endpoint ${fGet} with fake=4: response.status === 400 OK`, + ); + const fields = e.response.data.map((param: any) => + param.path.replace(".body.", ""), + ); + t2.ok( + fields.includes("fake"), + "Rejected because fake is not a valid parameter", + ); + } + t2.end(); + }); + + test(`${testCase} - ${fHas} - ${cInvalidParams}`, async (t2: Test) => { + try { + await apiClient.hasKeychainEntryV1(({ + key, + fake: 4, + } as any) as HasKeychainEntryRequestV1); + } catch (e) { + t2.equal( + e.response.status, + 400, + `Endpoint ${fHas} with fake=4: response.status === 400 OK`, + ); + const fields = e.response.data.map((param: any) => + param.path.replace(".body.", ""), + ); + t2.ok( + fields.includes("fake"), + "Rejected because fake is not a valid parameter", + ); + } + t2.end(); + }); + + test(`${testCase} - ${fDelete} - ${cInvalidParams}`, async (t2: Test) => { + try { + await apiClient.deleteKeychainEntryV1(({ + key, + fake: 4, + } as any) as DeleteKeychainEntryRequestV1); + } catch (e) { + t2.equal( + e.response.status, + 400, + `Endpoint ${fDelete} with fake=4: response.status === 400 OK`, + ); + const fields = e.response.data.map((param: any) => + param.path.replace(".body.", ""), + ); + t2.ok( + fields.includes("fake"), + "Rejected because fake is not a valid parameter", + ); + } + t2.end(); + }); + + t.end(); +});