Skip to content

Commit

Permalink
Bind business network administrators at network deploy/start time (hy…
Browse files Browse the repository at this point in the history
…perledger-archives#2302)

* Don't use resolver to resolve registries for resource operations

Signed-off-by: Simon Stone <[email protected]>

* Fix spacing in invalid identity error message

Signed-off-by: Simon Stone <[email protected]>

* Cleanup context identity getter/setter tests

Signed-off-by: Simon Stone <[email protected]>

* Clear transaction after execution to permit multiple transactions

Signed-off-by: Simon Stone <[email protected]>

* Reverse the context/network manager require fix

Signed-off-by: Simon Stone <[email protected]>

* Use system registry cache for getting registries

Signed-off-by: Simon Stone <[email protected]>

* Reset business network should not erase system registries

Signed-off-by: Simon Stone <[email protected]>

* Add start business network transaction type

Signed-off-by: Simon Stone <[email protected]>

* Runtime support for start business network transaction

Signed-off-by: Simon Stone <[email protected]>

* Client support for start business network transaction

Signed-off-by: Simon Stone <[email protected]>

* Embedded runtime support for start business network transaction

Signed-off-by: Simon Stone <[email protected]>

* Stop any identity with admin in the name from having superpowers

Signed-off-by: Simon Stone <[email protected]>

* Get system tests running cleanly

Signed-off-by: Simon Stone <[email protected]>

* Web runtime support for start business network transaction

Signed-off-by: Simon Stone <[email protected]>

* Connector server support for start business network transaction

Signed-off-by: Simon Stone <[email protected]>

* HLFv1 support for start business network transaction

Signed-off-by: Simon Stone <[email protected]>

* Stop resetting a newly deployed business network

Signed-off-by: Simon Stone <[email protected]>

* Command line support for business network administrators

Signed-off-by: Simon Stone <[email protected]>

* Fix Cucumber tests

Signed-off-by: Simon Stone <[email protected]>

* Fix REST server tests

Signed-off-by: Simon Stone <[email protected]>

* Remove chaincode Docker containers inbetween system tests

Signed-off-by: Simon Stone <[email protected]>
  • Loading branch information
Simon Stone authored and mbwhite committed Oct 6, 2017
1 parent 3f38f4b commit f535d45
Show file tree
Hide file tree
Showing 67 changed files with 2,641 additions and 800 deletions.
158 changes: 152 additions & 6 deletions packages/composer-admin/lib/adminconnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,127 @@ class AdminConnection {
return this.connection.install(this.securityContext, businessNetworkIdentifier, installOptions);
}

/**
* Get the current identity.
* @private
* @return {Promise} A promise that will be fufilled with the current identity.
*/
_getCurrentIdentity() {
const method = '_getCurrentIdentity';
LOG.entry(method);
let identityName = this.securityContext.getUser();
LOG.debug(method, 'Current identity name', identityName);
return this.exportIdentity(this.connection.connectionProfile, identityName)
.then((identity) => {
LOG.exit(method, identity);
return identity;
});
}

/**
* Generate an array of bootstrap transactions for the business network.
* @private
* @param {Factory} factory The factory to use.
* @param {string} identityName The name of the current identity.
* @param {string} identityCertificate The certificate for the current identity.
* @return {Resource[]} An array of bootstrap transactions for the business network.
*/
_generateBootstrapTransactions(factory, identityName, identityCertificate) {
const method = '_generateBootstrapTransactions';
LOG.entry(method);
const participant = factory.newResource('org.hyperledger.composer.system', 'NetworkAdmin', identityName);
const targetRegistry = factory.newRelationship('org.hyperledger.composer.system', 'ParticipantRegistry', participant.getFullyQualifiedType());
const addParticipantTransaction = factory.newTransaction('org.hyperledger.composer.system', 'AddParticipant');
Object.assign(addParticipantTransaction, {
resources: [ participant ],
targetRegistry
});
LOG.debug(method, 'Created bootstrap transaction to add participant', addParticipantTransaction);
const bindIdentityTransaction = factory.newTransaction('org.hyperledger.composer.system', 'BindIdentity');
Object.assign(bindIdentityTransaction, {
participant: factory.newRelationship('org.hyperledger.composer.system', 'NetworkAdmin', identityName),
certificate: identityCertificate
});
LOG.debug(method, 'Created bootstrap transaction to bind identity', bindIdentityTransaction);
const result = [
addParticipantTransaction,
bindIdentityTransaction
];
LOG.exit(method, result);
return result;
}

/**
* Build the JSON for the start transaction.
* @private
* @param {BusinessNetworkDefinition} businessNetworkDefinition The business network definition.
* @param {Object} [startOptions] The options for starting the business network.
* @return {Promise} A promise that will be fufilled with the JSON for the start transaction.
*/
_buildStartTransaction(businessNetworkDefinition, startOptions = {}) {
const method = '_buildStartTransaction';
LOG.entry(method, businessNetworkDefinition, startOptions);

// Get the current identity - we may need it to bind the
// identity to a network admin participant.
let identityName, identityCertificate;
return this._getCurrentIdentity()
.then((identity) => {

// Extract the current identity name and certificate.
identityName = this.securityContext.getUser();
identityCertificate = identity.certificate;

// Now serialize the business network archive.
return businessNetworkDefinition.toArchive();

})
.then((businessNetworkArchive) => {

// Create a new instance of a start transaction.
const factory = businessNetworkDefinition.getFactory();
const serializer = businessNetworkDefinition.getSerializer();
const startTransaction = factory.newTransaction('org.hyperledger.composer.system', 'StartBusinessNetwork');
const classDeclaration = startTransaction.getClassDeclaration();
startTransaction.businessNetworkArchive = businessNetworkArchive.toString('base64');

// If the user has not supplied any bootstrap transactions, then we need
// to add some:
// 1) Create a NetworkAdmin participant for the current identity.
// 2) Bind the current identity to the new NetworkAdmin participant.
if (!startOptions.bootstrapTransactions || startOptions.bootstrapTransactions.length === 0) {
LOG.debug(method, 'No bootstrap transactions specified');
startTransaction.bootstrapTransactions = this._generateBootstrapTransactions(factory, identityName, identityCertificate);
delete startOptions.bootstrapTransactions;
}

// Otherwise, parse all of the supplied bootstrap transactions.
if (startOptions.bootstrapTransactions) {
startTransaction.bootstrapTransactions = startOptions.bootstrapTransactions.map((bootstrapTransactionJSON) => {
return serializer.fromJSON(bootstrapTransactionJSON);
});
delete startOptions.bootstrapTransactions;
}

// Now handle the rest of the properties in the start options.
Object.keys(startOptions).forEach((key) => {
LOG.debug(method, 'Checking start option', key);
if (classDeclaration.getProperty(key)) {
const value = startOptions[key];
LOG.debug(method, 'Start option is a property of the start transaction', key, value);
startTransaction[key] = value;
delete startOptions[key];
}
});

// Now we can start the business network.
const startTransactionJSON = serializer.toJSON(startTransaction);
LOG.exit(method, startTransactionJSON);
return startTransactionJSON;

});
}

/**
* Starts a business network within the runtime previously installed to the Hyperledger Fabric with
* the same name as the business network to be started. The connection must be connected for this
Expand All @@ -261,15 +382,27 @@ class AdminConnection {
* // Add optional error handling here.
* });
* @param {BusinessNetworkDefinition} businessNetworkDefinition - The business network to start
* @param {Object} startOptions connector specific start options
* @param {Object} [startOptions] connector specific start options
* @return {Promise} A promise that will be fufilled when the business network has been
* deployed.
*/
start(businessNetworkDefinition, startOptions) {
start(businessNetworkDefinition, startOptions = {}) {
const method = 'start';
LOG.entry(method, businessNetworkDefinition, startOptions);
Util.securityCheck(this.securityContext);
return this.connection.start(this.securityContext, businessNetworkDefinition, startOptions);
}

// Build the start transaction.
return this._buildStartTransaction(businessNetworkDefinition, startOptions)
.then((startTransactionJSON) => {

// Now we can start the business network.
return this.connection.start(this.securityContext, businessNetworkDefinition.getName(), JSON.stringify(startTransactionJSON), startOptions);

})
.then(() => {
LOG.exit(method);
});
}

/**
* Deploys a new BusinessNetworkDefinition to the Hyperledger Fabric. The connection must
Expand All @@ -290,9 +423,22 @@ class AdminConnection {
* @return {Promise} A promise that will be fufilled when the business network has been
* deployed.
*/
deploy(businessNetworkDefinition, deployOptions) {
deploy(businessNetworkDefinition, deployOptions = {}) {
const method = 'deploy';
LOG.entry(method, businessNetworkDefinition, deployOptions);
Util.securityCheck(this.securityContext);
return this.connection.deploy(this.securityContext, businessNetworkDefinition, deployOptions);

// Build the start transaction.
return this._buildStartTransaction(businessNetworkDefinition, deployOptions)
.then((startTransactionJSON) => {

// Now we can deploy the business network.
return this.connection.deploy(this.securityContext, businessNetworkDefinition.getName(), JSON.stringify(startTransactionJSON), deployOptions);

})
.then(() => {
LOG.exit(method);
});
}

/**
Expand Down
Loading

0 comments on commit f535d45

Please sign in to comment.