Skip to content

Commit

Permalink
fix(cmd-api-server): OpenAPI spec validation
Browse files Browse the repository at this point in the history
add missing validation from plugin REST endpoints

fixes hyperledger-cacti#847

Signed-off-by: Elena Izaguirre <e.izaguirre.equiza@accenture.com>
  • Loading branch information
elenaizaguirre committed Aug 4, 2021
1 parent e6aea32 commit 734bd76
Show file tree
Hide file tree
Showing 61 changed files with 5,546 additions and 630 deletions.
2 changes: 1 addition & 1 deletion packages/cactus-cmd-api-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"express-http-proxy": "1.6.0",
"express-jwt": "6.0.0",
"express-jwt-authz": "2.4.1",
"express-openapi-validator": "3.10.0",
"express-openapi-validator": "4.12.12",
"http-status-codes": "2.1.4",
"jose": "1.28.1",
"node-forge": "0.10.0",
Expand Down
51 changes: 44 additions & 7 deletions packages/cactus-cmd-api-server/src/main/typescript/api-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ import { createServer as createSecureServer } from "https";
import { gte } from "semver";
import npm from "npm";
import expressHttpProxy from "express-http-proxy";
import type { Application, Request, Response, RequestHandler } from "express";
import type {
Application,
Request,
Response,
RequestHandler,
NextFunction,
} from "express";
import express from "express";
import { OpenApiValidator } from "express-openapi-validator";
// import { OpenApiValidator } from "express-openapi-validator";
import * as OpenApiValidator from "express-openapi-validator";
import compression from "compression";
import bodyParser from "body-parser";
import cors from "cors";
Expand All @@ -35,7 +42,11 @@ import { Logger, LoggerProvider, Servers } from "@hyperledger/cactus-common";

import { ICactusApiServerOptions } from "./config/config-service";
import OAS from "../json/openapi.json";
import { OpenAPIV3 } from "express-openapi-validator/dist/framework/types";
import {
OpenApiRequestHandler,
OpenAPIV3,
OpenApiValidatorOpts,
} from "express-openapi-validator/dist/framework/types";

import { PrometheusExporter } from "./prometheus-exporter/prometheus-exporter";
import { AuthorizerFactory } from "./authzn/authorizer-factory";
Expand Down Expand Up @@ -521,7 +532,32 @@ export class ApiServer {
}

const openApiValidator = this.createOpenApiValidator();
await openApiValidator.install(app);
app.use(openApiValidator);
// manage errors caused by api validation
app.use(
(
err: {
status?: number;
errors: [
{
path: string;
message: string;
errorCode: string;
},
];
},
req: Request,
res: Response,
next: NextFunction,
) => {
if (err) {
res.status(err.status || 500);
res.send(err.errors);
} else {
next();
}
},
);

this.getOrCreateWebServices(app); // The API server's own endpoints

Expand Down Expand Up @@ -597,12 +633,13 @@ export class ApiServer {
}
}

createOpenApiValidator(): OpenApiValidator {
return new OpenApiValidator({
createOpenApiValidator(): OpenApiRequestHandler[] {
const options: OpenApiValidatorOpts = {
apiSpec: OAS as OpenAPIV3.Document,
validateRequests: true,
validateResponses: false,
});
};
return OpenApiValidator.middleware(options);
}

createCorsMiddleware(allowedDomains: string[]): RequestHandler {
Expand Down
2 changes: 2 additions & 0 deletions packages/cactus-core-api/src/main/json/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@
"required": [
"key"
],
"additionalProperties": false,
"properties": {
"key": {
"type": "string",
Expand Down Expand Up @@ -583,6 +584,7 @@
"key",
"value"
],
"additionalProperties": false,
"properties": {
"key": {
"type": "string",
Expand Down
1 change: 1 addition & 0 deletions packages/cactus-plugin-consortium-manual/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"axios": "0.21.1",
"body-parser": "1.19.0",
"express": "4.17.1",
"express-openapi-validator": "4.12.12",
"jose": "1.28.1",
"json-stable-stringify": "1.0.1",
"prom-client": "13.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,6 @@
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"servers": [
{
"url": "https://www.cactus.stream/{basePath}",
"description": "Public test instance",
"variables": {
"basePath": {
"default": ""
}
}
},
{
"url": "http://localhost:4000/{basePath}",
"description": "Local test instance",
"variables": {
"basePath": {
"default": ""
}
}
}
],
"components": {
"schemas": {
"GetNodeJwsResponse": {
Expand All @@ -39,7 +19,7 @@
"properties": {
"jws": {
"description": "The JSON Web Signature of the Cactus node.",
"$ref": "../../../../cactus-core-api/src/main/json/openapi.json#/components/schemas/JWSGeneral",
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/fix-847--2021-07-14/packages/cactus-core-api/src/main/json/openapi.json#/components/schemas/JWSGeneral",
"nullable": false
}
}
Expand All @@ -52,7 +32,7 @@
"properties": {
"jws": {
"description": "The JSON Web Signature of the Cactus consortium.",
"$ref": "../../../../cactus-core-api/src/main/json/openapi.json#/components/schemas/JWSGeneral",
"$ref": "https://raw.githubusercontent.com/hyperledger/cactus/fix-847--2021-07-14/packages/cactus-core-api/src/main/json/openapi.json#/components/schemas/JWSGeneral",
"nullable": false,
"format": "The general format which is a JSON object, not a string."
}
Expand All @@ -64,11 +44,13 @@
},
"GetNodeJwsRequest": {
"type": "object",
"additionalProperties": false,
"properties": {
}
},
"GetConsortiumJwsRequest": {
"type": "object",
"additionalProperties": false,
"properties": {
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { Configuration } from "./configuration";
// @ts-ignore
import globalAxios, { AxiosPromise, AxiosInstance } from 'axios';

export const BASE_PATH = "https://www.cactus.stream".replace(/\/+$/, "");
export const BASE_PATH = "http://localhost".replace(/\/+$/, "");

/**
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ import { Server } from "http";
import { Server as SecureServer } from "https";
import { Optional } from "typescript-optional";
import { promisify } from "util";
import express, { Express } from "express";
import express, { Express, NextFunction, Request, Response } from "express";
import bodyParser from "body-parser";
import { JWS, JWK } from "jose";
import jsonStableStringify from "json-stable-stringify";
import { v4 as uuidv4 } from "uuid";

import OAS from "../json/openapi.json";
import * as OpenApiValidator from "express-openapi-validator";
import { OpenAPIV3 } from "express-openapi-validator/dist/framework/types";

import {
ConsortiumDatabase,
IPluginWebService,
Expand Down Expand Up @@ -87,6 +91,10 @@ export class PluginConsortiumManual
this.prometheusExporter.setNodeCount(this.getNodeCount());
}

getOpenApiSpecs(): OpenAPIV3.Document {
return (OAS as unknown) as OpenAPIV3.Document;
}

public getInstanceId(): string {
return this.instanceId;
}
Expand Down Expand Up @@ -168,6 +176,40 @@ export class PluginConsortiumManual
}

const webServices = await this.getOrCreateWebServices();
const apiSpec = this.getOpenApiSpecs();
const openApiMiddleware = OpenApiValidator.middleware({
apiSpec,
validateApiSpec: false,
$refParser: {
mode: "dereference",
},
});
app.use(openApiMiddleware);
app.use(
(
err: {
status?: number;
errors: [
{
path: string;
message: string;
errorCode: string;
},
];
},
req: Request,
res: Response,
next: NextFunction,
) => {
if (err) {
res.status(err.status || 500);
res.send(err.errors);
} else {
next();
}
},
);

webServices.forEach((ws) => ws.registerExpress(webApp));
return webServices;
}
Expand Down
1 change: 1 addition & 0 deletions packages/cactus-plugin-htlc-eth-besu-erc20/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"@hyperledger/cactus-plugin-ledger-connector-besu": "0.6.0",
"axios": "0.21.1",
"express": "4.17.1",
"express-openapi-validator": "4.12.12",
"joi": "14.3.1",
"openapi-types": "7.0.1",
"typescript-optional": "2.0.1"
Expand Down
Loading

0 comments on commit 734bd76

Please sign in to comment.