Skip to content

Commit

Permalink
iss3351 add profile validator (hyperledger-archives#3358)
Browse files Browse the repository at this point in the history
Signed-off-by: Sam Smith <[email protected]>
  • Loading branch information
samjsmith authored and jt-nti committed Feb 8, 2018
1 parent da66622 commit 6a2c743
Show file tree
Hide file tree
Showing 13 changed files with 927 additions and 0 deletions.
12 changes: 12 additions & 0 deletions packages/composer-cli/lib/cmds/card/lib/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
const cmdUtil = require('../../utils/cmdutils');
const fs = require('fs');
const IdCard = require('composer-common').IdCard;
const Validate = require('./validate');
const path = require('path');
const chalk = require('chalk');
const prettyjson = require('prettyjson');
/**
* Composer "card import" command
* @private
Expand All @@ -42,6 +44,16 @@ class Import {
if (existingCard) {
throw new Error('Card already exists: ' + cardName);
}

let errors = Validate.validateProfile(cardToImport.getConnectionProfile());
if(errors) {
cmdUtil.log(chalk.red.bold('\nFailed to import the business network card'));
errors.forEach((err) => {
cmdUtil.log(prettyjson.render(err, {keysColor: 'red',stringColor: 'white'}) + '\n');
});
throw new Error(chalk.red.bold('Errors found in the connection profile in the card'));
}

return adminConnection.importCard(cardName, cardToImport);
}).then(() => {
cmdUtil.log(chalk.blue.bold('\nSuccessfully imported business network card'));
Expand Down
177 changes: 177 additions & 0 deletions packages/composer-cli/lib/cmds/card/lib/schema/ccpschema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
{
"$schema" : "http://json-schema.org/schema#",
"definitions" : {
"client" : {
"type" : "object",
"properties" : {
"organization" : { "type" : "string" }
},
"required" : [ "organization" ]
},
"certificateAuthorities" : {
"type" : "object",
"patternProperties": {
"^.*$" : { "$ref": "#/definitions/certificateAuthority" }
}
},
"certificateAuthority" : {
"type" : "object",
"properties": {
"url" : { "format" : "uri" },
"httpOptions" : { "$ref": "#/definitions/httpOptions" },
"tlsCACerts" : { "$ref": "#/definitions/tlsCACerts" },
"registrar" : { "$ref": "#/definitions/registrar" },
"caName" : { "type" : "string" }
},
"required": [ "url" ]
},
"registrar" : {
"properties": {
"enrollId" : { "type" : "string" },
"enrollSecret" : { "type" : "string" }
},
"required" : [ "enrollId", "enrollSecret" ]
},
"httpOptions" : {
"type" : "object",
"properties" : {
"verify" : { "type" : "boolean" }
}
},
"channels" : {
"type" : "object",
"patternProperties" : {
"^.*$" : { "$ref": "#/definitions/channel" }
},
"minimum" : 1
},
"channel" : {
"type" : "object",
"properties" : {
"orderers" : { "type" : "array" },
"peers" : { "$ref" : "#/definitions/channel-peer" },
"chaincodes" : { "type" : "array" }
},
"required" : [ "orderers", "peers" ]
},
"channel-peer" : {
"type" : "object",
"patternProperties": {
"^.*$" : {
"endorsingPeer" : { "type" : "boolean" },
"chaincodeQuery" : { "type" : "boolean" },
"ledgerQuery" : { "type" : "boolean" },
"eventSource" : { "type" : "boolean" }
},
"additionalProperties": false
},
"minimum" : 1
},
"orderers" : {
"type" : "object",
"patternProperties": {
"^.*$" : { "$ref": "#/definitions/orderer" }
},
"minimum": 1
},
"orderer" : {
"type" : "object",
"properties" : {
"url" : { "format" : "uri" },
"grpcOptions" : { "$ref": "#/definitions/grpcOptions" },
"tlsCACerts" : { "$ref": "#/definitions/tlsCACerts" }
},
"required": [ "url" ]
},
"grpcOptions" : {
"type" : "object",
"properties": {
"ssl-target-name-override" : { "type" : "string" },
"grpc-max-send-message-length" : { "type" : "number" }
}
},
"tlsCACerts" : {
"type" : "object",
"properties": {
"pem" : { "type" : "string" },
"path" : { "type" : "string" },
"client" : { "$ref": "#/definitions/tlsCACertsClient" }
}
},
"tlsCACertsClient" : {
"type" : "object",
"properties" : {
"keyfile" : { "type" : "string"},
"certfile" : { "type" : "string"}
},
"additionalProperties": false
},
"organizations" : {
"type" : "object",
"patternProperties": {
"^.*$" : { "$ref": "#/definitions/organization" }
},
"minimum": 1
},
"organization" : {
"type" : "object",
"properties": {
"certificateAuthorities" : { "type" : "array" },
"mspid" : { "type" : "string" },
"peers" : { "type" : "array" },
"adminPrivateKey" : { "$ref": "#/definitions/adminPrivateKey" },
"signedCert" : { "$ref": "#/definitions/signedCert" }
},
"required": [ "mspid", "peers" ]
},
"adminPrivateKey" : {
"type" : "object",
"properties": {
"oneOf" : {
"pem" : { "type" : "string" },
"path" : { "type" : "string" }
}
},
"required" : [ "pem" ]
},
"signedCert" : {
"type" : "object",
"properties": {
"path" : { "type" : "string" }
},
"required" : [ "path" ]
},
"peers" : {
"type" : "object",
"patternProperties": {
"^.*$" : { "$ref": "#/definitions/peer" }
},
"minimum": 1
},
"peer" : {
"type" : "object",
"properties": {
"url" : { "format" : "uri" },
"eventUrl" : { "format" : "uri" },
"grpcOptions" : { "$ref": "#/definitions/grpcOptions" },
"tlsCACerts" : { "$ref": "#/definitions/tlsCACerts" }
},
"required": [ "url", "eventUrl"]
}
},
"type" : "object",
"properties" : {
"name" : { "type" : "string", "pattern" : "^[a-zA-Z0-9_-]*$" },
"x-type" : { "enum" : [ "hlfv1", "hlfv11" ] },
"x-loggingLevel" : { "enum" : [ "info", "debug" ] },
"x-commitTimeout": { "type" : "number" },
"version" : { "type" : "string", "pattern" : "^1.0.*$" },
"client" : { "$ref" : "#/definitions/client" },
"certificateAuthorities" : { "$ref": "#/definitions/certificateAuthorities" },
"channels" : { "$ref" : "#/definitions/channels" },
"orderers" : { "$ref" : "#/definitions/orderers" },
"organizations" : { "$ref" : "#/definitions/organizations" },
"peers" : { "$ref": "#/definitions/peers" }
},
"required" : ["name", "x-type", "client", "certificateAuthorities", "channels", "orderers", "peers"]
}
40 changes: 40 additions & 0 deletions packages/composer-cli/lib/cmds/card/lib/validate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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 ajv = require('ajv');

/**
* Validate connection profile
* @private
*/
class Validate {
/**
* validateProfile
* validates connection profile
* @param {Object} profile the connection profile
* @return {Object} undef if the profile is valid, error array otherwise.
*/
static validateProfile(profile) {
let schema = require('./schema/ccpschema.json');
let validate = new ajv({ allErrors : true }).compile(schema);
validate(profile);
if(validate.errors) {
return validate.errors;
} else {
return;
}
}
}
module.exports = Validate;
2 changes: 2 additions & 0 deletions packages/composer-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"sinon": "2.3.8"
},
"dependencies": {
"ajv": "6.1.1",
"chalk": "1.1.3",
"cli-table": "0.3.1",
"composer-admin": "0.17.5",
Expand All @@ -59,6 +60,7 @@
"prompt": "1.0.0",
"sanitize-filename": "1.6.1",
"tar": "4.3.0",
"valid-url": "1.0.9",
"yargs": "10.0.3"
},
"license-check-config": {
Expand Down
62 changes: 62 additions & 0 deletions packages/composer-cli/test/card/data/connection.in.doc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"name": "hlfv1",
"x-type": "hlfv1",
"x-commitTimeout": 300,
"version": "1.0.0",
"client": {
"organization": "Org1",
"connection": {
"timeout": {
"peer": {
"endorser": "300",
"eventHub": "300",
"eventReg": "300"
},
"orderer": "300"
}
}
},
"channels": {
"composerchannel": {
"orderers": [
"orderer.example.com"
],
"peers": {
"peer0.org1.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"ledgerQuery": true,
"eventSource": true
}
}
}
},
"organizations": {
"Org1": {
"mspid": "Org1MSP",
"peers": [
"peer0.org1.example.com"
],
"certificateAuthorities": [
"ca.org1.example.com"
]
}
},
"orderers": {
"orderer.example.com": {
"url": "grpc://orderer.example.com:7050"
}
},
"peers": {
"peer0.org1.example.com": {
"url": "grpc://peer0.org1.example.com:7051",
"eventUrl": "grpc://peer0.org1.example.com:7053"
}
},
"certificateAuthorities": {
"ca.org1.example.com": {
"url": "http://ca.org1.example.com:7054",
"caName": "ca.org1.example.com"
}
}
}
57 changes: 57 additions & 0 deletions packages/composer-cli/test/card/data/connection.invalid.name.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "%invalid%",
"version": "1.0.0",
"x-commitTimeout": 300,
"x-type": "hlfv1",
"client": {
"organization": "Org1",
"connection": {
"timeout": {
"orderer": "300",
"peer": {
"endorser": "300",
"eventHub": "300",
"eventReg": "300"
}
}
}
},
"certificateAuthorities": {
"ca.org1.example.com": {
"caName": "ca.org1.example.com",
"url": "http://localhost:7054"
}
},
"channels": {
"composerchannel": {
"orderers": [
"orderer.example.com"
],
"peers": {
"peer0.org1.example.com": {}
}
}
},
"orderers": {
"orderer.example.com": {
"url": "grpc://localhost:7050"
}
},
"organizations": {
"Org1": {
"certificateAuthorities": [
"ca.org1.example.com"
],
"mspid": "Org1MSP",
"peers": [
"peer0.org1.example.com"
]
}
},
"peers": {
"peer0.org1.example.com": {
"eventUrl": "grpc://localhost:7053",
"url": "grpc://localhost:7051"
}
}
}
Loading

0 comments on commit 6a2c743

Please sign in to comment.