github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-config/configtx/consortiums.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package configtx
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	cb "github.com/hyperledger/fabric-protos-go/common"
    15  	mb "github.com/hyperledger/fabric-protos-go/msp"
    16  )
    17  
    18  // Consortium is a group of non-orderer organizations used in channel transactions.
    19  type Consortium struct {
    20  	Name          string
    21  	Organizations []Organization
    22  }
    23  
    24  // ConsortiumsGroup encapsulates the parts of the config that control consortiums.
    25  type ConsortiumsGroup struct {
    26  	consortiumsGroup *cb.ConfigGroup
    27  }
    28  
    29  // ConsortiumGroup encapsulates the parts of the config that control
    30  // a specific consortium. This type implements retrieval of the various
    31  // consortium config values.
    32  type ConsortiumGroup struct {
    33  	consortiumGroup *cb.ConfigGroup
    34  	name            string
    35  }
    36  
    37  // ConsortiumOrg encapsulates the parts of the config that control a
    38  // consortium organization's configuration.
    39  type ConsortiumOrg struct {
    40  	orgGroup *cb.ConfigGroup
    41  	name     string
    42  }
    43  
    44  // MSP returns an OrganizationMSP object that can be used to configure the organization's MSP.
    45  func (c *ConsortiumOrg) MSP() *OrganizationMSP {
    46  	return &OrganizationMSP{
    47  		configGroup: c.orgGroup,
    48  	}
    49  }
    50  
    51  // Consortiums returns the consortiums group from the updated config.
    52  func (c *ConfigTx) Consortiums() *ConsortiumsGroup {
    53  	consortiumsGroup := c.updated.ChannelGroup.Groups[ConsortiumsGroupKey]
    54  	return &ConsortiumsGroup{consortiumsGroup: consortiumsGroup}
    55  }
    56  
    57  // Consortium returns a consortium group from the updated config.
    58  func (c *ConfigTx) Consortium(name string) *ConsortiumGroup {
    59  	consortiumGroup, ok := c.updated.ChannelGroup.Groups[ConsortiumsGroupKey].Groups[name]
    60  	if !ok {
    61  		return nil
    62  	}
    63  	return &ConsortiumGroup{name: name, consortiumGroup: consortiumGroup}
    64  }
    65  
    66  // SetConsortium sets the consortium in a channel configuration.
    67  // If the consortium already exists in the current configuration, its value will be overwritten.
    68  func (c *ConsortiumsGroup) SetConsortium(consortium Consortium) error {
    69  	c.consortiumsGroup.Groups[consortium.Name] = newConfigGroup()
    70  
    71  	for _, org := range consortium.Organizations {
    72  		err := c.consortium(consortium.Name).SetOrganization(org)
    73  		if err != nil {
    74  			return err
    75  		}
    76  	}
    77  
    78  	return nil
    79  }
    80  
    81  func (c *ConsortiumsGroup) consortium(name string) *ConsortiumGroup {
    82  	consortiumGroup := c.consortiumsGroup.Groups[name]
    83  	return &ConsortiumGroup{name: name, consortiumGroup: consortiumGroup}
    84  }
    85  
    86  // RemoveConsortium removes a consortium from a channel configuration.
    87  // Removal will panic if the consortiums group does not exist.
    88  func (c *ConsortiumsGroup) RemoveConsortium(name string) {
    89  	delete(c.consortiumsGroup.Groups, name)
    90  }
    91  
    92  // Organization returns the consortium org from the original config.
    93  func (c *ConsortiumGroup) Organization(name string) *ConsortiumOrg {
    94  	orgGroup, ok := c.consortiumGroup.Groups[name]
    95  	if !ok {
    96  		return nil
    97  	}
    98  	return &ConsortiumOrg{name: name, orgGroup: orgGroup}
    99  }
   100  
   101  // SetOrganization sets the organization config group for the given org key in
   102  // an existing Consortium configuration's Groups map.
   103  // If the consortium org already exists in the current configuration, its
   104  // value will be overwritten.
   105  func (c *ConsortiumGroup) SetOrganization(org Organization) error {
   106  	orgGroup, err := newOrgConfigGroup(org)
   107  	if err != nil {
   108  		return fmt.Errorf("failed to create consortium org %s: %v", org.Name, err)
   109  	}
   110  
   111  	c.consortiumGroup.Groups[org.Name] = orgGroup
   112  
   113  	return nil
   114  }
   115  
   116  // RemoveOrganization removes an org from a consortium group.
   117  // Removal will panic if either the consortiums group or consortium group does not exist.
   118  func (c *ConsortiumGroup) RemoveOrganization(name string) {
   119  	delete(c.consortiumGroup.Groups, name)
   120  }
   121  
   122  // Configuration returns a list of consortium configurations from the updated
   123  // config. Consortiums are only defined for the ordering system channel.
   124  func (c *ConsortiumsGroup) Configuration() ([]Consortium, error) {
   125  	consortiums := []Consortium{}
   126  	for consortiumName := range c.consortiumsGroup.Groups {
   127  		consortium, err := c.consortium(consortiumName).Configuration()
   128  		if err != nil {
   129  			return nil, err
   130  		}
   131  		consortiums = append(consortiums, consortium)
   132  	}
   133  
   134  	return consortiums, nil
   135  }
   136  
   137  // Configuration returns the configuration for a consortium group.
   138  func (c *ConsortiumGroup) Configuration() (Consortium, error) {
   139  	orgs := []Organization{}
   140  	for orgName, orgGroup := range c.consortiumGroup.Groups {
   141  		org, err := getOrganization(orgGroup, orgName)
   142  		if err != nil {
   143  			return Consortium{}, fmt.Errorf("failed to retrieve organization %s from consortium %s: ", orgName, c.name)
   144  		}
   145  		orgs = append(orgs, org)
   146  	}
   147  	return Consortium{
   148  		Name:          c.name,
   149  		Organizations: orgs,
   150  	}, nil
   151  }
   152  
   153  // Configuration retrieves an existing org's configuration from a consortium
   154  // organization config group in the updated config.
   155  func (c *ConsortiumOrg) Configuration() (Organization, error) {
   156  	org, err := getOrganization(c.orgGroup, c.name)
   157  	if err != nil {
   158  		return Organization{}, err
   159  	}
   160  
   161  	// Remove AnchorPeers which are application org specific.
   162  	org.AnchorPeers = nil
   163  
   164  	return org, err
   165  }
   166  
   167  // SetMSP updates the MSP config for the specified consortium org group.
   168  func (c *ConsortiumOrg) SetMSP(updatedMSP MSP) error {
   169  	currentMSP, err := c.MSP().Configuration()
   170  	if err != nil {
   171  		return fmt.Errorf("retrieving msp: %v", err)
   172  	}
   173  
   174  	if currentMSP.Name != updatedMSP.Name {
   175  		return errors.New("MSP name cannot be changed")
   176  	}
   177  
   178  	err = updatedMSP.validateCACerts()
   179  	if err != nil {
   180  		return err
   181  	}
   182  
   183  	err = c.setMSPConfig(updatedMSP)
   184  	if err != nil {
   185  		return err
   186  	}
   187  
   188  	return nil
   189  }
   190  
   191  func (c *ConsortiumOrg) setMSPConfig(updatedMSP MSP) error {
   192  	mspConfig, err := newMSPConfig(updatedMSP)
   193  	if err != nil {
   194  		return fmt.Errorf("new msp config: %v", err)
   195  	}
   196  
   197  	err = setValue(c.orgGroup, mspValue(mspConfig), AdminsPolicyKey)
   198  	if err != nil {
   199  		return err
   200  	}
   201  
   202  	return nil
   203  }
   204  
   205  // SetChannelCreationPolicy sets the ConsortiumChannelCreationPolicy for
   206  // the given configuration Group.
   207  // If the policy already exists in current configuration, its value will be overwritten.
   208  func (c *ConsortiumGroup) SetChannelCreationPolicy(policy Policy) error {
   209  	imp, err := implicitMetaFromString(policy.Rule)
   210  	if err != nil {
   211  		return fmt.Errorf("invalid implicit meta policy rule '%s': %v", policy.Rule, err)
   212  	}
   213  
   214  	implicitMetaPolicy, err := implicitMetaPolicy(imp.SubPolicy, imp.Rule)
   215  	if err != nil {
   216  		return fmt.Errorf("failed to make implicit meta policy: %v", err)
   217  	}
   218  
   219  	// update channel creation policy value back to consortium
   220  	if err = setValue(c.consortiumGroup, channelCreationPolicyValue(implicitMetaPolicy), ordererAdminsPolicyName); err != nil {
   221  		return fmt.Errorf("failed to update channel creation policy to consortium %s: %v", c.name, err)
   222  	}
   223  
   224  	return nil
   225  }
   226  
   227  // Policies returns a map of policies for a specific consortium org.
   228  func (c *ConsortiumOrg) Policies() (map[string]Policy, error) {
   229  	return getPolicies(c.orgGroup.Policies)
   230  }
   231  
   232  // SetModPolicy sets the specified modification policy for the consortium org group.
   233  func (c *ConsortiumOrg) SetModPolicy(modPolicy string) error {
   234  	if modPolicy == "" {
   235  		return errors.New("non empty mod policy is required")
   236  	}
   237  
   238  	c.orgGroup.ModPolicy = modPolicy
   239  
   240  	return nil
   241  }
   242  
   243  // SetPolicy sets the specified policy in the consortium org group's config policy map.
   244  // If the policy already exists in current configuration, its value will be overwritten.
   245  func (c *ConsortiumOrg) SetPolicy(name string, policy Policy) error {
   246  	err := setPolicy(c.orgGroup, name, policy)
   247  	if err != nil {
   248  		return fmt.Errorf("failed to set policy '%s' to consortium org '%s': %v", name, c.name, err)
   249  	}
   250  
   251  	return nil
   252  }
   253  
   254  // SetPolicies sets the specified policies in the consortium org group's config policy map.
   255  // If the policies already exist in current configuration, the values will be replaced with new policies.
   256  func (c *ConsortiumOrg) SetPolicies(policies map[string]Policy) error {
   257  	err := setPolicies(c.orgGroup, policies)
   258  	if err != nil {
   259  		return fmt.Errorf("failed to set policies to consortium org '%s': %v", c.name, err)
   260  	}
   261  
   262  	return nil
   263  }
   264  
   265  // RemovePolicy removes an existing policy from a consortium's organization.
   266  // Removal will panic if either the consortiums group, consortium group, or consortium org group does not exist.
   267  func (c *ConsortiumOrg) RemovePolicy(name string) {
   268  	delete(c.orgGroup.Policies, name)
   269  }
   270  
   271  // newConsortiumsGroup returns the consortiums component of the channel configuration. This element is only defined for
   272  // the ordering system channel.
   273  // It sets the mod_policy for all elements to "/Channel/Orderer/Admins".
   274  func newConsortiumsGroup(consortiums []Consortium) (*cb.ConfigGroup, error) {
   275  	var err error
   276  
   277  	consortiumsGroup := newConfigGroup()
   278  	consortiumsGroup.ModPolicy = ordererAdminsPolicyName
   279  
   280  	// acceptAllPolicy always evaluates to true
   281  	acceptAllPolicy := envelope(nOutOf(0, []*cb.SignaturePolicy{}), [][]byte{})
   282  
   283  	// This policy is not referenced anywhere, it is only used as part of the implicit meta policy rule at the
   284  	// channel level, so this setting effectively degrades control of the ordering system channel to the ordering admins
   285  	signaturePolicy, err := signaturePolicy(AdminsPolicyKey, acceptAllPolicy)
   286  	if err != nil {
   287  		return nil, err
   288  	}
   289  
   290  	consortiumsGroup.Policies[signaturePolicy.key] = &cb.ConfigPolicy{
   291  		Policy:    signaturePolicy.value,
   292  		ModPolicy: ordererAdminsPolicyName,
   293  	}
   294  
   295  	for _, consortium := range consortiums {
   296  		consortiumsGroup.Groups[consortium.Name], err = newConsortiumGroup(consortium)
   297  		if err != nil {
   298  			return nil, err
   299  		}
   300  	}
   301  
   302  	return consortiumsGroup, nil
   303  }
   304  
   305  // newConsortiumGroup returns a consortiums component of the channel configuration.
   306  func newConsortiumGroup(consortium Consortium) (*cb.ConfigGroup, error) {
   307  	var err error
   308  
   309  	consortiumGroup := newConfigGroup()
   310  	consortiumGroup.ModPolicy = ordererAdminsPolicyName
   311  
   312  	for _, org := range consortium.Organizations {
   313  		consortiumGroup.Groups[org.Name], err = newOrgConfigGroup(org)
   314  		if err != nil {
   315  			return nil, fmt.Errorf("org group '%s': %v", org.Name, err)
   316  		}
   317  	}
   318  
   319  	implicitMetaAnyPolicy, err := implicitMetaAnyPolicy(AdminsPolicyKey)
   320  	if err != nil {
   321  		return nil, err
   322  	}
   323  
   324  	err = setValue(consortiumGroup, channelCreationPolicyValue(implicitMetaAnyPolicy.value), ordererAdminsPolicyName)
   325  	if err != nil {
   326  		return nil, err
   327  	}
   328  
   329  	return consortiumGroup, nil
   330  }
   331  
   332  // consortiumValue returns the config definition for the consortium name
   333  // It is a value for the channel group.
   334  func consortiumValue(name string) *standardConfigValue {
   335  	return &standardConfigValue{
   336  		key: ConsortiumKey,
   337  		value: &cb.Consortium{
   338  			Name: name,
   339  		},
   340  	}
   341  }
   342  
   343  // channelCreationPolicyValue returns the config definition for a consortium's channel creation policy
   344  // It is a value for the /Channel/Consortiums/*/*.
   345  func channelCreationPolicyValue(policy *cb.Policy) *standardConfigValue {
   346  	return &standardConfigValue{
   347  		key:   ChannelCreationPolicyKey,
   348  		value: policy,
   349  	}
   350  }
   351  
   352  // envelope builds an envelope message embedding a SignaturePolicy.
   353  func envelope(policy *cb.SignaturePolicy, identities [][]byte) *cb.SignaturePolicyEnvelope {
   354  	ids := make([]*mb.MSPPrincipal, len(identities))
   355  	for i := range ids {
   356  		ids[i] = &mb.MSPPrincipal{PrincipalClassification: mb.MSPPrincipal_IDENTITY, Principal: identities[i]}
   357  	}
   358  
   359  	return &cb.SignaturePolicyEnvelope{
   360  		Version:    0,
   361  		Rule:       policy,
   362  		Identities: ids,
   363  	}
   364  }
   365  
   366  // nOutOf creates a policy which requires N out of the slice of policies to evaluate to true.
   367  func nOutOf(n int32, policies []*cb.SignaturePolicy) *cb.SignaturePolicy {
   368  	return &cb.SignaturePolicy{
   369  		Type: &cb.SignaturePolicy_NOutOf_{
   370  			NOutOf: &cb.SignaturePolicy_NOutOf{
   371  				N:     n,
   372  				Rules: policies,
   373  			},
   374  		},
   375  	}
   376  }
   377  
   378  // signaturePolicy defines a policy with key policyName and the given signature policy.
   379  func signaturePolicy(policyName string, sigPolicy *cb.SignaturePolicyEnvelope) (*standardConfigPolicy, error) {
   380  	signaturePolicy, err := proto.Marshal(sigPolicy)
   381  	if err != nil {
   382  		return nil, fmt.Errorf("marshaling signature policy: %v", err)
   383  	}
   384  
   385  	return &standardConfigPolicy{
   386  		key: policyName,
   387  		value: &cb.Policy{
   388  			Type:  int32(cb.Policy_SIGNATURE),
   389  			Value: signaturePolicy,
   390  		},
   391  	}, nil
   392  }
   393  
   394  // implicitMetaPolicy creates a new *cb.Policy of cb.Policy_IMPLICIT_META type.
   395  func implicitMetaPolicy(subPolicyName string, rule cb.ImplicitMetaPolicy_Rule) (*cb.Policy, error) {
   396  	implicitMetaPolicy, err := proto.Marshal(&cb.ImplicitMetaPolicy{
   397  		Rule:      rule,
   398  		SubPolicy: subPolicyName,
   399  	})
   400  	if err != nil {
   401  		return nil, fmt.Errorf("failed to marshal implicit meta policy: %v", err)
   402  	}
   403  
   404  	return &cb.Policy{
   405  		Type:  int32(cb.Policy_IMPLICIT_META),
   406  		Value: implicitMetaPolicy,
   407  	}, nil
   408  }
   409  
   410  // implicitMetaAnyPolicy defines an implicit meta policy whose sub_policy and key is policyname with rule ANY.
   411  func implicitMetaAnyPolicy(policyName string) (*standardConfigPolicy, error) {
   412  	implicitMetaPolicy, err := implicitMetaPolicy(policyName, cb.ImplicitMetaPolicy_ANY)
   413  	if err != nil {
   414  		return nil, fmt.Errorf("failed to make implicit meta ANY policy: %v", err)
   415  	}
   416  
   417  	return &standardConfigPolicy{
   418  		key:   policyName,
   419  		value: implicitMetaPolicy,
   420  	}, nil
   421  }
   422  
   423  // getConsortiumOrg returns the organization config group for a consortium org in the
   424  // provided config. It will panic if the consortium doesn't exist, and it
   425  // will return nil if the org doesn't exist in the config.
   426  func getConsortiumOrg(config *cb.Config, consortiumName string, orgName string) *cb.ConfigGroup {
   427  	consortiumsGroup := config.ChannelGroup.Groups[ConsortiumsGroupKey].Groups
   428  	consortiumGroup := consortiumsGroup[consortiumName]
   429  	return consortiumGroup.Groups[orgName]
   430  }