From a3516ef3e706182cc2ef4d73561984ab1c330510 Mon Sep 17 00:00:00 2001 From: Nidhi Singh Date: Wed, 27 Dec 2023 22:20:01 +0530 Subject: [PATCH] Set Correct policy while channel update (#114) * Set Correct policy while channel update Signed-off-by: n0s09by * Moved the rolePolicy function into utils Signed-off-by: n0s09by * Enhancement:Refractored reptitive code into method Signed-off-by: n0s09by --------- Signed-off-by: n0s09by --- .../AddOrgToChannelWriteSetBuilderImpl.java | 134 ++------------- .../service/impl/ChannelServiceImpl.java | 160 +----------------- .../rest/client/util/FabricChannelUtil.java | 133 +++++++++++++++ 3 files changed, 152 insertions(+), 275 deletions(-) create mode 100644 src/main/java/hlf/java/rest/client/util/FabricChannelUtil.java diff --git a/src/main/java/hlf/java/rest/client/service/impl/AddOrgToChannelWriteSetBuilderImpl.java b/src/main/java/hlf/java/rest/client/service/impl/AddOrgToChannelWriteSetBuilderImpl.java index d8952ef5..fce578c9 100644 --- a/src/main/java/hlf/java/rest/client/service/impl/AddOrgToChannelWriteSetBuilderImpl.java +++ b/src/main/java/hlf/java/rest/client/service/impl/AddOrgToChannelWriteSetBuilderImpl.java @@ -6,6 +6,7 @@ import hlf.java.rest.client.model.AnchorPeerDTO; import hlf.java.rest.client.model.NewOrgParamsDTO; import hlf.java.rest.client.service.AddOrgToChannelWriteSetBuilder; +import hlf.java.rest.client.util.FabricChannelUtil; import hlf.java.rest.client.util.FabricClientConstants; import java.util.ArrayList; import java.util.HashMap; @@ -15,12 +16,6 @@ import org.hyperledger.fabric.protos.common.Configtx.ConfigGroup; import org.hyperledger.fabric.protos.common.Configtx.ConfigPolicy; import org.hyperledger.fabric.protos.common.Configtx.ConfigValue; -import org.hyperledger.fabric.protos.common.MspPrincipal.MSPPrincipal; -import org.hyperledger.fabric.protos.common.MspPrincipal.MSPRole; -import org.hyperledger.fabric.protos.common.Policies.Policy; -import org.hyperledger.fabric.protos.common.Policies.SignaturePolicy; -import org.hyperledger.fabric.protos.common.Policies.SignaturePolicy.NOutOf; -import org.hyperledger.fabric.protos.common.Policies.SignaturePolicyEnvelope; import org.hyperledger.fabric.protos.msp.MspConfigPackage.FabricCryptoConfig; import org.hyperledger.fabric.protos.msp.MspConfigPackage.FabricMSPConfig; import org.hyperledger.fabric.protos.msp.MspConfigPackage.FabricNodeOUs; @@ -44,25 +39,27 @@ public ConfigGroup buildWriteset(ConfigGroup readset, NewOrgParamsDTO organizati // Get existing organizations in the channel and set with as objects and their // version to prevent deletion or modification // Omitting existing groups results in their deletion. - Map organizations = new HashMap<>(); + Map existingOrganizations = new HashMap<>(); ConfigGroup applicationConfigGroup = readset.getGroupsOrThrow(FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION); applicationConfigGroup .getGroupsMap() .forEach( (k, v) -> - organizations.put( - k, setEmptyGroup(retrieveGroupVersionFromReadset(applicationConfigGroup, k)))); + existingOrganizations.put( + k, + setEmptyGroup(retrieveMSPGroupVersionFromReadset(applicationConfigGroup, k)))); // The "Application" group ConfigGroup applicationGroup = ConfigGroup.newBuilder() .setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS) .putAllPolicies(setApplicationPolicies(readset)) .putGroups(newOrgMspId, setNewOrgGroup(newOrgMspId)) - .putAllGroups(organizations) + // putAllGroups excludes new organization + .putAllGroups(existingOrganizations) // Application group version .setVersion( - retrieveGroupVersionFromReadset( + retrieveMSPGroupVersionFromReadset( readset, FabricClientConstants.CHANNEL_CONFIG_GROUP_APPLICATION) + 1) // will // be @@ -84,17 +81,17 @@ public ConfigGroup buildWriteset(ConfigGroup readset, NewOrgParamsDTO organizati .build(); } - private long retrieveGroupVersionFromReadset(ConfigGroup readset, String groupName) + private long retrieveMSPGroupVersionFromReadset(ConfigGroup readset, String mspId) throws ServiceException { long versionLong = DEFAULT_VERSION; try { - ConfigGroup group = readset.getGroupsOrThrow(groupName); + ConfigGroup group = readset.getGroupsOrThrow(mspId); versionLong = group.getVersion(); } catch (IllegalArgumentException e) { throw new ServiceException( ErrorCode.NOT_FOUND, "WriteBuilder version iteration error: ConfigGroup with name - \"" - + groupName + + mspId + "\" - not found in Readset", e); } @@ -150,8 +147,9 @@ private Map setApplicationPolicies(ConfigGroup readset) { .setModPolicy("") .setVersion(map.get(FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS)) .build(); - Map applicationPoliciesMap = new HashMap<>(); + // add Admins, Readers, Writers, Endorsement and LifeCycle Endorsement policies at the channel + // level applicationPoliciesMap.put( FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS, adminPolicy); applicationPoliciesMap.put( @@ -177,9 +175,9 @@ private ConfigGroup setNewOrgGroup(String newOrgMspId) { return ConfigGroup.newBuilder() .setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS) - .putAllPolicies(setNewOrgPolicies(newOrgMspId)) + .putAllPolicies(FabricChannelUtil.getDefaultRolePolicy(newOrgMspId)) .putAllValues(valueMap) - .setVersion(0) + .setVersion(0) // First time update, hence version is 0 .build(); } @@ -187,108 +185,6 @@ private ConfigGroup setEmptyGroup(long version) { return ConfigGroup.newBuilder().setModPolicy("").setVersion(version).build(); } - private Map setNewOrgPolicies(String newOrgName) { - Map applicationPoliciesMap = new HashMap<>(); - applicationPoliciesMap.put( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS, - setNewOrgPolicy(newOrgName, FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS)); - applicationPoliciesMap.put( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT, - setNewOrgPolicy(newOrgName, FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT)); - applicationPoliciesMap.put( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS, - setNewOrgPolicy(newOrgName, FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS)); - applicationPoliciesMap.put( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS, - setNewOrgPolicy(newOrgName, FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS)); - - return applicationPoliciesMap; - } - - private ConfigPolicy setNewOrgPolicy(String newOrgName, String policyTarget) { - return ConfigPolicy.newBuilder() - .setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS) - .setPolicy(setTypeOnePolicy(newOrgName, policyTarget)) - .setVersion(0) - .build(); - } - - private Policy setTypeOnePolicy(String orgName, String policyTarget) { - ArrayList identitiesList = new ArrayList<>(); - - MSPRole mspRoleAdmin = - MSPRole.newBuilder().setRole(MSPRole.MSPRoleType.ADMIN).setMspIdentifier(orgName).build(); - MSPPrincipal mspPrincipalAdmin = - MSPPrincipal.newBuilder() - .setPrincipal(mspRoleAdmin.toByteString()) - .setPrincipalClassification(MSPPrincipal.Classification.ROLE) - .build(); - MSPRole mspRolePeer = - MSPRole.newBuilder().setRole(MSPRole.MSPRoleType.PEER).setMspIdentifier(orgName).build(); - MSPPrincipal mspPrincipalPeer = - MSPPrincipal.newBuilder() - .setPrincipal(mspRolePeer.toByteString()) - .setPrincipalClassification(MSPPrincipal.Classification.ROLE) - .build(); - MSPRole mspRoleClient = - MSPRole.newBuilder().setRole(MSPRole.MSPRoleType.CLIENT).setMspIdentifier(orgName).build(); - MSPPrincipal mspPrincipalClient = - MSPPrincipal.newBuilder() - .setPrincipal(mspRoleClient.toByteString()) - .setPrincipalClassification(MSPPrincipal.Classification.ROLE) - .build(); - - // "SignaturePolicy" is repeated internally despite being the same class, but - // with - // different internal components used - SignaturePolicy rules = null; - NOutOf nOutOf = null; - - switch (policyTarget) { - case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS: - identitiesList.add(mspPrincipalAdmin); - rules = SignaturePolicy.newBuilder().setSignedBy(0).build(); - nOutOf = NOutOf.newBuilder().setN(1).addRules(rules).build(); - break; - case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT: - identitiesList.add(mspPrincipalPeer); - rules = SignaturePolicy.newBuilder().setSignedBy(0).build(); - nOutOf = NOutOf.newBuilder().setN(1).addRules(rules).build(); - break; - case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS: - identitiesList.add(mspPrincipalAdmin); - identitiesList.add(mspPrincipalPeer); - identitiesList.add(mspPrincipalClient); - rules = SignaturePolicy.newBuilder().setSignedBy(0).setSignedBy(1).setSignedBy(2).build(); - nOutOf = NOutOf.newBuilder().setN(3).addRules(rules).build(); - break; - case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS: - identitiesList.add(mspPrincipalAdmin); - identitiesList.add(mspPrincipalClient); - rules = SignaturePolicy.newBuilder().setSignedBy(0).setSignedBy(1).build(); - nOutOf = NOutOf.newBuilder().setN(2).addRules(rules).build(); - break; - case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_LIFECYCLE_ENDORSEMENT: - // Fill later based on requirements - break; - default: - throw new ServiceException( - ErrorCode.NOT_FOUND, - "Error building readset. Policy Type: \"" + policyTarget + "\" not found."); - } - SignaturePolicy rule = SignaturePolicy.newBuilder().setNOutOf(nOutOf).build(); - - // For type 1 policy - SignaturePolicyEnvelope spe = - SignaturePolicyEnvelope.newBuilder() - .setVersion(0) - .addAllIdentities(identitiesList) - .setRule(rule) - .build(); - - return Policy.newBuilder().setType(1).setValue(spe.toByteString()).build(); - } - private ConfigValue setNewOrgMspValue(String newOrgMspId) { return ConfigValue.newBuilder() .setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS) diff --git a/src/main/java/hlf/java/rest/client/service/impl/ChannelServiceImpl.java b/src/main/java/hlf/java/rest/client/service/impl/ChannelServiceImpl.java index ebe5b1b4..f32d61e8 100644 --- a/src/main/java/hlf/java/rest/client/service/impl/ChannelServiceImpl.java +++ b/src/main/java/hlf/java/rest/client/service/impl/ChannelServiceImpl.java @@ -10,6 +10,7 @@ import hlf.java.rest.client.model.ClientResponseModel; import hlf.java.rest.client.service.ChannelService; import hlf.java.rest.client.service.HFClientWrapper; +import hlf.java.rest.client.util.FabricChannelUtil; import hlf.java.rest.client.util.FabricClientConstants; import java.util.ArrayList; import java.util.HashMap; @@ -25,7 +26,6 @@ import org.hyperledger.fabric.protos.common.Common; import org.hyperledger.fabric.protos.common.Configtx; import org.hyperledger.fabric.protos.common.Configuration; -import org.hyperledger.fabric.protos.common.MspPrincipal; import org.hyperledger.fabric.protos.common.Policies; import org.hyperledger.fabric.protos.msp.MspConfigPackage; import org.hyperledger.fabric.sdk.Channel; @@ -366,163 +366,12 @@ private Configtx.ConfigGroup getMSPConfigGroup(hlf.java.rest.client.model.Peer p .setVersion(EMPTY_VERSION) .putAllGroups(new HashMap<>()) .setModPolicy(EMPTY_MOD_POLICY) - .putAllPolicies(getDefaultRolePolicy(peer.getMspid())) // Organization's role policies + .putAllPolicies( + FabricChannelUtil.getDefaultRolePolicy(peer.getMspid())) // Organization's role policies .putAllValues(valueMap) .build(); } - // The method returns a default policy for each organization - // that maps the roles. The policy type is signature. Roles - // are identified by their signatures, as those signatures - // represent the certificate. - private HashMap getDefaultRolePolicy(String orgMSPId) { - HashMap defaultOrgRolePolicy = new HashMap<>(); - // add Admins, Readers, Writers and Endorsement policies - defaultOrgRolePolicy.put( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS, - getDefaultRoleConfigPolicyForMSP( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS, orgMSPId)); - defaultOrgRolePolicy.put( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS, - getDefaultRoleConfigPolicyForMSP( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS, orgMSPId)); - defaultOrgRolePolicy.put( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS, - getDefaultRoleConfigPolicyForMSP( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS, orgMSPId)); - defaultOrgRolePolicy.put( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT, - getDefaultRoleConfigPolicyForMSP( - FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT, orgMSPId)); - return defaultOrgRolePolicy; - } - - // getRolesFor returns the SignaturePolicy that has MSP - // with the logical conditions. - // For example, it is possible to design OR(msp1.member, msp2.client) - // this evaluates to - // identities: { - // ... msp1 - // ... msp2 - // } - // n out of { - // n: 1 - // rules: { - // SignaturePolicy{index: 0} - // SignaturePolicy{index: 1} - // } - // } - private List getRolesFor(String policyFor, String orgMSPId) { - List mspPrincipals = new ArrayList<>(); - MspPrincipal.MSPRole mspRole; - MspPrincipal.MSPPrincipal mspPrincipal; - switch (policyFor) { - case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS: - mspRole = - MspPrincipal.MSPRole.newBuilder() - .setMspIdentifier(orgMSPId) - .setRole(MspPrincipal.MSPRole.MSPRoleType.ADMIN) - .build(); - mspPrincipal = - MspPrincipal.MSPPrincipal.newBuilder() - .setPrincipal(mspRole.toByteString()) - .setPrincipalClassification(MspPrincipal.MSPPrincipal.Classification.ROLE) - .build(); - mspPrincipals.add(mspPrincipal); - break; - case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS: - // any member who is an admin can write - mspRole = - MspPrincipal.MSPRole.newBuilder() - .setMspIdentifier(orgMSPId) - .setRole(MspPrincipal.MSPRole.MSPRoleType.ADMIN) - .build(); - mspPrincipal = - MspPrincipal.MSPPrincipal.newBuilder() - .setPrincipal(mspRole.toByteString()) - .setPrincipalClassification(MspPrincipal.MSPPrincipal.Classification.ROLE) - .build(); - mspPrincipals.add(mspPrincipal); - // any client can also write - mspRole = - MspPrincipal.MSPRole.newBuilder() - .setMspIdentifier(orgMSPId) - .setRole(MspPrincipal.MSPRole.MSPRoleType.CLIENT) - .build(); - mspPrincipal = - MspPrincipal.MSPPrincipal.newBuilder() - .setPrincipal(mspRole.toByteString()) - .setPrincipalClassification(MspPrincipal.MSPPrincipal.Classification.ROLE) - .build(); - mspPrincipals.add(mspPrincipal); - break; - case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT: - // any member who is peer can only endorse - mspRole = - MspPrincipal.MSPRole.newBuilder() - .setMspIdentifier(orgMSPId) - .setRole(MspPrincipal.MSPRole.MSPRoleType.PEER) - .build(); - mspPrincipal = - MspPrincipal.MSPPrincipal.newBuilder() - .setPrincipal(mspRole.toByteString()) - .setPrincipalClassification(MspPrincipal.MSPPrincipal.Classification.ROLE) - .build(); - mspPrincipals.add(mspPrincipal); - break; - case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS: - // any member can read - mspRole = - MspPrincipal.MSPRole.newBuilder() - .setMspIdentifier(orgMSPId) - .setRole(MspPrincipal.MSPRole.MSPRoleType.MEMBER) - .build(); - mspPrincipal = - MspPrincipal.MSPPrincipal.newBuilder() - .setPrincipal(mspRole.toByteString()) - .setPrincipalClassification(MspPrincipal.MSPPrincipal.Classification.ROLE) - .build(); - mspPrincipals.add(mspPrincipal); - break; - } - return mspPrincipals; - } - - // The method returns a ConfigPolicy of type signature for the - // passed organization's MSP ID. - private Configtx.ConfigPolicy getDefaultRoleConfigPolicyForMSP( - String policyFor, String orgMSPId) { - List mspPrincipals = getRolesFor(policyFor, orgMSPId); - // loop through each entry and apply the n out of policy - // that is always get at least one signature. - // get the signature policy - // set rules - // create those roles - Policies.SignaturePolicyEnvelope.Builder signaturePolicyEnvelopeBuilder = - Policies.SignaturePolicyEnvelope.newBuilder(); - Policies.SignaturePolicy.Builder signaturePolicyBuilder = Policies.SignaturePolicy.newBuilder(); - Policies.SignaturePolicy.NOutOf.Builder signatureNOutOfBuilder = - Policies.SignaturePolicy.NOutOf.newBuilder().setN(1); // expect just one signature always - for (int idx = 0; idx < mspPrincipals.size(); idx++) { - signaturePolicyEnvelopeBuilder.setIdentities(idx, mspPrincipals.get(idx)); - signatureNOutOfBuilder.setRules( - idx, Policies.SignaturePolicy.newBuilder().setSignedBy(idx).build()); - } - signaturePolicyBuilder.setNOutOf(signatureNOutOfBuilder.build()); - signaturePolicyEnvelopeBuilder.setRule(signaturePolicyBuilder.build()); - // get the policy - Policies.Policy policy = - Policies.Policy.newBuilder() - .setType(Policies.Policy.PolicyType.SIGNATURE_VALUE) - .setValue(signaturePolicyEnvelopeBuilder.build().toByteString()) - .build(); - // create config policy and return - return Configtx.ConfigPolicy.newBuilder() - .setPolicy(policy) - .setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS) - .build(); - } - private Configtx.ConfigValue getOrgMspValue(hlf.java.rest.client.model.Peer peer) { return Configtx.ConfigValue.newBuilder() .setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS) @@ -653,8 +502,7 @@ private Policies.Policy getImplicitMetaPolicy(String subPolicyName, int rule) { * @param modPolicy * @return */ - private Configtx.ConfigPolicy getConfigPolicy( - String subPolicyName, int rule, String modPolicy) { + private Configtx.ConfigPolicy getConfigPolicy(String subPolicyName, int rule, String modPolicy) { return Configtx.ConfigPolicy.newBuilder() .setPolicy(getImplicitMetaPolicy(subPolicyName, rule)) .setModPolicy(modPolicy) diff --git a/src/main/java/hlf/java/rest/client/util/FabricChannelUtil.java b/src/main/java/hlf/java/rest/client/util/FabricChannelUtil.java new file mode 100644 index 00000000..0523f085 --- /dev/null +++ b/src/main/java/hlf/java/rest/client/util/FabricChannelUtil.java @@ -0,0 +1,133 @@ +package hlf.java.rest.client.util; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import lombok.experimental.UtilityClass; +import org.hyperledger.fabric.protos.common.Configtx; +import org.hyperledger.fabric.protos.common.MspPrincipal; +import org.hyperledger.fabric.protos.common.Policies; + +@UtilityClass +public class FabricChannelUtil { + + /** + * get default configuration policy for organization that maps the roles. The policy type is + * signature. Roles are identified by their signatures, as those signatures represent the + * certificate. + * + * @param orgMSPId Org MSP ID + * @return HashMap with role and the configuration policy + */ + public static HashMap getDefaultRolePolicy(String orgMSPId) { + HashMap defaultOrgRolePolicy = new HashMap<>(); + // add Admins, Readers, Writers and Endorsement policies + defaultOrgRolePolicy.put( + FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS, + getDefaultRoleConfigPolicyForMSP( + FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS, orgMSPId)); + defaultOrgRolePolicy.put( + FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS, + getDefaultRoleConfigPolicyForMSP( + FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS, orgMSPId)); + defaultOrgRolePolicy.put( + FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS, + getDefaultRoleConfigPolicyForMSP( + FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS, orgMSPId)); + defaultOrgRolePolicy.put( + FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT, + getDefaultRoleConfigPolicyForMSP( + FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT, orgMSPId)); + return defaultOrgRolePolicy; + } + + /** + * returns a ConfigPolicy of type signature for the passed organization's MSP ID + * + * @param policyFor Policy for which role + * @param orgMSPId new org MSP ID + * @return configuration policy + */ + private static Configtx.ConfigPolicy getDefaultRoleConfigPolicyForMSP( + String policyFor, String orgMSPId) { + List mspPrincipals = getRolesFor(policyFor, orgMSPId); + // loop through each entry and apply the n out of policy + // that is always get at least one signature. + // get the signature policy + // set rules + // create those roles + Policies.SignaturePolicyEnvelope.Builder signaturePolicyEnvelopeBuilder = + Policies.SignaturePolicyEnvelope.newBuilder(); + Policies.SignaturePolicy.Builder signaturePolicyBuilder = Policies.SignaturePolicy.newBuilder(); + Policies.SignaturePolicy.NOutOf.Builder signatureNOutOfBuilder = + Policies.SignaturePolicy.NOutOf.newBuilder().setN(1); // expect just one signature always + for (int idx = 0; idx < mspPrincipals.size(); idx++) { + signaturePolicyEnvelopeBuilder.setIdentities(idx, mspPrincipals.get(idx)); + signatureNOutOfBuilder.setRules( + idx, Policies.SignaturePolicy.newBuilder().setSignedBy(idx).build()); + } + signaturePolicyBuilder.setNOutOf(signatureNOutOfBuilder.build()); + signaturePolicyEnvelopeBuilder.setRule(signaturePolicyBuilder.build()); + // get the policy + Policies.Policy policy = + Policies.Policy.newBuilder() + .setType(Policies.Policy.PolicyType.SIGNATURE_VALUE) + .setValue(signaturePolicyEnvelopeBuilder.build().toByteString()) + .build(); + // create config policy and return + return Configtx.ConfigPolicy.newBuilder() + .setPolicy(policy) + .setModPolicy(FabricClientConstants.CHANNEL_CONFIG_MOD_POLICY_ADMINS) + .build(); + } + + // getRolesFor returns the SignaturePolicy that has MSP + // with the logical conditions. + // For example, it is possible to design OR(msp1.member, msp2.client) + // this evaluates to + // identities: { + // ... msp1 + // ... msp2 + // } + // n out of { + // n: 1 + // rules: { + // SignaturePolicy{index: 0} + // SignaturePolicy{index: 1} + // } + // } + + private static MspPrincipal.MSPPrincipal createMSPPrincipal( + String orgMSPId, MspPrincipal.MSPRole.MSPRoleType roleType) { + MspPrincipal.MSPRole mspRole = + MspPrincipal.MSPRole.newBuilder().setMspIdentifier(orgMSPId).setRole(roleType).build(); + return MspPrincipal.MSPPrincipal.newBuilder() + .setPrincipal(mspRole.toByteString()) + .setPrincipalClassification(MspPrincipal.MSPPrincipal.Classification.ROLE) + .build(); + } + + private static List getRolesFor(String policyFor, String orgMSPId) { + List mspPrincipals = new ArrayList<>(); + switch (policyFor) { + case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ADMINS: + mspPrincipals.add(createMSPPrincipal(orgMSPId, MspPrincipal.MSPRole.MSPRoleType.ADMIN)); + break; + case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_WRITERS: + // any member who is an admin can write + mspPrincipals.add(createMSPPrincipal(orgMSPId, MspPrincipal.MSPRole.MSPRoleType.ADMIN)); + // any client can also write + mspPrincipals.add(createMSPPrincipal(orgMSPId, MspPrincipal.MSPRole.MSPRoleType.CLIENT)); + break; + case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_ENDORSEMENT: + // any member who is peer can only endorse + mspPrincipals.add(createMSPPrincipal(orgMSPId, MspPrincipal.MSPRole.MSPRoleType.PEER)); + break; + case FabricClientConstants.CHANNEL_CONFIG_POLICY_TYPE_READERS: + // any member can read + mspPrincipals.add(createMSPPrincipal(orgMSPId, MspPrincipal.MSPRole.MSPRoleType.MEMBER)); + break; + } + return mspPrincipals; + } +}