Skip to content

Commit

Permalink
fix: openapi validation for keychain-google-sm plugin
Browse files Browse the repository at this point in the history
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 hyperledger-cacti#847

Signed-off-by: Elena Izaguirre <e.izaguirre.equiza@accenture.com>
  • Loading branch information
elenaizaguirre committed Oct 20, 2021
1 parent 0b4dc2e commit 316cf31
Show file tree
Hide file tree
Showing 2 changed files with 298 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,23 @@
"summary": "Retrieves the contents of a keychain entry from the backend.",
"parameters": [],
"requestBody": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/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.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_200"
},
"400": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_400"
},
"401": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_401"
},
"404": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_404"
},
"500": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_get_entry_500"
}
}
}
Expand All @@ -59,20 +59,20 @@
"summary": "Sets a value under a key on the keychain backend.",
"parameters": [],
"requestBody": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/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.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_200"
},
"400": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_400"
},
"401": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_401"
},
"500": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_set_entry_500"
}
}
}
Expand All @@ -89,11 +89,11 @@
"summary": "Deletes an entry under a key on the keychain backend.",
"parameters": [],
"requestBody": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/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.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_delete_entry_200"
}
}
}
Expand All @@ -110,20 +110,20 @@
"summary": "Checks that an entry exists under a key on the keychain backend.",
"parameters": [],
"requestBody": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/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.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_200"
},
"400": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_400"
},
"401": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_401"
},
"500": {
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/v0.10.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.1/packages/cactus-core-api/src/main/json/openapi.json#/components/responses/keychain_has_entry_500"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
import test, { Test } from "tape-promise/tape";
import { v4 as uuidv4 } from "uuid";
import http from "http";
import type { AddressInfo } from "net";
import express from "express";
import bodyParser from "body-parser";

import {
LogLevelDesc,
IListenOptions,
Servers,
} from "@hyperledger/cactus-common";

import {
Configuration,
DefaultApi as KeychainGoogleSmApi,
DeleteKeychainEntryRequestV1,
GetKeychainEntryRequestV1,
HasKeychainEntryRequestV1,
IPluginKeychainGoogleSmOptions,
PluginKeychainGoogleSm,
SetKeychainEntryRequestV1,
} from "../../../../main/typescript/public-api";

import { SecretManagerServiceClientMock } from "../../mock/plugin-keychain-google-sm-mock";

import { installOpenapiValidationMiddleware } from "@hyperledger/cactus-core";
import OAS from "../../../../main/json/openapi.json";

const logLevel: LogLevelDesc = "TRACE";
const testCase = "Test cactus-plugin-keychain-azure-kv openapi validation";

test(testCase, async (t: Test) => {
const options: IPluginKeychainGoogleSmOptions = {
instanceId: uuidv4(),
keychainId: uuidv4(),
logLevel: logLevel,
backend: new SecretManagerServiceClientMock({
logLevel: logLevel,
}),
};
const plugin = new PluginKeychainGoogleSm(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 configuration = new Configuration({ basePath: apiHost });
const apiClient = new KeychainGoogleSmApi(configuration);

await installOpenapiValidationMiddleware({
logLevel,
app: expressApp,
apiSpec: OAS,
});

await plugin.getOrCreateWebServices();
await plugin.registerWebServices(expressApp);

const key = `${uuidv4()}?${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.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,
} 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();
});

0 comments on commit 316cf31

Please sign in to comment.