github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-config/configtx/application.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  	pb "github.com/hyperledger/fabric-protos-go/peer"
    16  )
    17  
    18  // Application is a copy of the orderer configuration with the addition of an anchor peers
    19  // list in the organization definition.
    20  type Application struct {
    21  	Organizations []Organization
    22  	Capabilities  []string
    23  	Policies      map[string]Policy
    24  	ACLs          map[string]string
    25  	ModPolicy     string
    26  }
    27  
    28  // ApplicationGroup encapsulates the part of the config that controls
    29  // application channels.
    30  type ApplicationGroup struct {
    31  	applicationGroup *cb.ConfigGroup
    32  }
    33  
    34  // ApplicationOrg encapsulates the parts of the config that control
    35  // an application organization's configuration.
    36  type ApplicationOrg struct {
    37  	orgGroup *cb.ConfigGroup
    38  	name     string
    39  }
    40  
    41  // MSP returns an OrganizationMSP object that can be used to configure the organization's MSP.
    42  func (a *ApplicationOrg) MSP() *OrganizationMSP {
    43  	return &OrganizationMSP{
    44  		configGroup: a.orgGroup,
    45  	}
    46  }
    47  
    48  // Application returns the application group the updated config.
    49  func (c *ConfigTx) Application() *ApplicationGroup {
    50  	applicationGroup := c.updated.ChannelGroup.Groups[ApplicationGroupKey]
    51  	return &ApplicationGroup{applicationGroup: applicationGroup}
    52  }
    53  
    54  // Organization returns the application org from the updated config.
    55  func (a *ApplicationGroup) Organization(name string) *ApplicationOrg {
    56  	organizationGroup, ok := a.applicationGroup.Groups[name]
    57  	if !ok {
    58  		return nil
    59  	}
    60  	return &ApplicationOrg{name: name, orgGroup: organizationGroup}
    61  }
    62  
    63  // SetOrganization sets the organization config group for the given application
    64  // org key in an existing Application configuration's Groups map.
    65  // If the application org already exists in the current configuration, its value will be overwritten.
    66  func (a *ApplicationGroup) SetOrganization(org Organization) error {
    67  	orgGroup, err := newApplicationOrgConfigGroup(org)
    68  	if err != nil {
    69  		return fmt.Errorf("failed to create application org %s: %v", org.Name, err)
    70  	}
    71  
    72  	a.applicationGroup.Groups[org.Name] = orgGroup
    73  
    74  	return nil
    75  }
    76  
    77  // RemoveOrganization removes an org from the Application group.
    78  // Removal will panic if the application group does not exist.
    79  func (a *ApplicationGroup) RemoveOrganization(orgName string) {
    80  	delete(a.applicationGroup.Groups, orgName)
    81  }
    82  
    83  // Configuration returns the existing application configuration values from a config
    84  // transaction as an Application type. This can be used to retrieve existing values for the application
    85  // prior to updating the application configuration.
    86  func (a *ApplicationGroup) Configuration() (Application, error) {
    87  	var applicationOrgs []Organization
    88  	for orgName := range a.applicationGroup.Groups {
    89  		orgConfig, err := a.Organization(orgName).Configuration()
    90  		if err != nil {
    91  			return Application{}, fmt.Errorf("retrieving application org %s: %v", orgName, err)
    92  		}
    93  
    94  		applicationOrgs = append(applicationOrgs, orgConfig)
    95  	}
    96  
    97  	capabilities, err := a.Capabilities()
    98  	if err != nil {
    99  		return Application{}, fmt.Errorf("retrieving application capabilities: %v", err)
   100  	}
   101  
   102  	policies, err := a.Policies()
   103  	if err != nil {
   104  		return Application{}, fmt.Errorf("retrieving application policies: %v", err)
   105  	}
   106  
   107  	acls, err := a.ACLs()
   108  	if err != nil {
   109  		return Application{}, fmt.Errorf("retrieving application acls: %v", err)
   110  	}
   111  
   112  	return Application{
   113  		Organizations: applicationOrgs,
   114  		Capabilities:  capabilities,
   115  		Policies:      policies,
   116  		ACLs:          acls,
   117  	}, nil
   118  }
   119  
   120  // Configuration returns the existing application org configuration values
   121  // from the updated config.
   122  func (a *ApplicationOrg) Configuration() (Organization, error) {
   123  	org, err := getOrganization(a.orgGroup, a.name)
   124  	if err != nil {
   125  		return Organization{}, err
   126  	}
   127  	return org, nil
   128  }
   129  
   130  // Capabilities returns a map of enabled application capabilities
   131  // from the updated config.
   132  func (a *ApplicationGroup) Capabilities() ([]string, error) {
   133  	capabilities, err := getCapabilities(a.applicationGroup)
   134  	if err != nil {
   135  		return nil, fmt.Errorf("retrieving application capabilities: %v", err)
   136  	}
   137  
   138  	return capabilities, nil
   139  }
   140  
   141  // AddCapability sets capability to the provided channel config.
   142  // If the provided capability already exists in current configuration, this action
   143  // will be a no-op.
   144  func (a *ApplicationGroup) AddCapability(capability string) error {
   145  	capabilities, err := a.Capabilities()
   146  	if err != nil {
   147  		return err
   148  	}
   149  
   150  	err = addCapability(a.applicationGroup, capabilities, AdminsPolicyKey, capability)
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	return nil
   156  }
   157  
   158  // RemoveCapability removes capability to the provided channel config.
   159  func (a *ApplicationGroup) RemoveCapability(capability string) error {
   160  	capabilities, err := a.Capabilities()
   161  	if err != nil {
   162  		return err
   163  	}
   164  
   165  	err = removeCapability(a.applicationGroup, capabilities, AdminsPolicyKey, capability)
   166  	if err != nil {
   167  		return err
   168  	}
   169  
   170  	return nil
   171  }
   172  
   173  // Policies returns a map of policies for the application config group in
   174  // the updatedconfig.
   175  func (a *ApplicationGroup) Policies() (map[string]Policy, error) {
   176  	return getPolicies(a.applicationGroup.Policies)
   177  }
   178  
   179  // SetModPolicy sets the specified modification policy for the application group.
   180  func (a *ApplicationGroup) SetModPolicy(modPolicy string) error {
   181  	if modPolicy == "" {
   182  		return errors.New("non empty mod policy is required")
   183  	}
   184  
   185  	a.applicationGroup.ModPolicy = modPolicy
   186  
   187  	return nil
   188  }
   189  
   190  // SetPolicy sets the specified policy in the application group's config policy map.
   191  // If the policy already exists in current configuration, its value will be overwritten.
   192  func (a *ApplicationGroup) SetPolicy(policyName string, policy Policy) error {
   193  	err := setPolicy(a.applicationGroup, policyName, policy)
   194  	if err != nil {
   195  		return fmt.Errorf("failed to set policy '%s': %v", policyName, err)
   196  	}
   197  
   198  	return nil
   199  }
   200  
   201  // SetPolicies sets the specified policies in the application group's config policy map.
   202  // If the policies already exist in current configuration, the values will be replaced with new policies.
   203  func (a *ApplicationGroup) SetPolicies(policies map[string]Policy) error {
   204  	err := setPolicies(a.applicationGroup, policies)
   205  	if err != nil {
   206  		return fmt.Errorf("failed to set policies: %v", err)
   207  	}
   208  
   209  	return nil
   210  }
   211  
   212  // RemovePolicy removes an existing policy from an application's configuration.
   213  // Removal will panic if the application group does not exist.
   214  func (a *ApplicationGroup) RemovePolicy(policyName string) error {
   215  	policies, err := a.Policies()
   216  	if err != nil {
   217  		return err
   218  	}
   219  
   220  	removePolicy(a.applicationGroup, policyName, policies)
   221  	return nil
   222  }
   223  
   224  // Policies returns the map of policies for a specific application org in
   225  // the updated config.
   226  func (a *ApplicationOrg) Policies() (map[string]Policy, error) {
   227  	return getPolicies(a.orgGroup.Policies)
   228  }
   229  
   230  // SetModPolicy sets the specified modification policy for the application organization group.
   231  func (a *ApplicationOrg) SetModPolicy(modPolicy string) error {
   232  	if modPolicy == "" {
   233  		return errors.New("non empty mod policy is required")
   234  	}
   235  
   236  	a.orgGroup.ModPolicy = modPolicy
   237  
   238  	return nil
   239  }
   240  
   241  // SetPolicy sets the specified policy in the application org group's config policy map.
   242  // If an Organization policy already exists in current configuration, its value will be overwritten.
   243  func (a *ApplicationOrg) SetPolicy(policyName string, policy Policy) error {
   244  	err := setPolicy(a.orgGroup, policyName, policy)
   245  	if err != nil {
   246  		return fmt.Errorf("failed to set policy '%s': %v", policyName, err)
   247  	}
   248  
   249  	return nil
   250  }
   251  
   252  // SetPolicies sets the specified policies in the application org group's config policy map.
   253  // If the policies already exist in current configuration, the values will be replaced with new policies.
   254  func (a *ApplicationOrg) SetPolicies(policies map[string]Policy) error {
   255  	err := setPolicies(a.orgGroup, policies)
   256  	if err != nil {
   257  		return fmt.Errorf("failed to set policies: %v", err)
   258  	}
   259  
   260  	return nil
   261  }
   262  
   263  // RemovePolicy removes an existing policy from an application organization.
   264  func (a *ApplicationOrg) RemovePolicy(policyName string) error {
   265  	policies, err := a.Policies()
   266  	if err != nil {
   267  		return err
   268  	}
   269  
   270  	removePolicy(a.orgGroup, policyName, policies)
   271  	return nil
   272  }
   273  
   274  // AnchorPeers returns the list of anchor peers for an application org
   275  // in the updated config.
   276  func (a *ApplicationOrg) AnchorPeers() ([]Address, error) {
   277  	anchorPeerConfigValue, ok := a.orgGroup.Values[AnchorPeersKey]
   278  	if !ok {
   279  		return nil, nil
   280  	}
   281  
   282  	anchorPeersProto := &pb.AnchorPeers{}
   283  
   284  	err := proto.Unmarshal(anchorPeerConfigValue.Value, anchorPeersProto)
   285  	if err != nil {
   286  		return nil, fmt.Errorf("failed unmarshaling %s's anchor peer endpoints: %v", a.name, err)
   287  	}
   288  
   289  	if len(anchorPeersProto.AnchorPeers) == 0 {
   290  		return nil, nil
   291  	}
   292  
   293  	anchorPeers := []Address{}
   294  	for _, ap := range anchorPeersProto.AnchorPeers {
   295  		anchorPeers = append(anchorPeers, Address{
   296  			Host: ap.Host,
   297  			Port: int(ap.Port),
   298  		})
   299  	}
   300  
   301  	return anchorPeers, nil
   302  }
   303  
   304  // AddAnchorPeer adds an anchor peer to an application org's configuration
   305  // in the updated config.
   306  func (a *ApplicationOrg) AddAnchorPeer(newAnchorPeer Address) error {
   307  	anchorPeersProto := &pb.AnchorPeers{}
   308  
   309  	if anchorPeerConfigValue, ok := a.orgGroup.Values[AnchorPeersKey]; ok {
   310  		// Unmarshal existing anchor peers if the config value exists
   311  		err := proto.Unmarshal(anchorPeerConfigValue.Value, anchorPeersProto)
   312  		if err != nil {
   313  			return fmt.Errorf("failed unmarshaling anchor peer endpoints: %v", err)
   314  		}
   315  	}
   316  
   317  	// Persist existing anchor peers if found
   318  	anchorProtos := anchorPeersProto.AnchorPeers
   319  
   320  	for _, anchorPeer := range anchorProtos {
   321  		if anchorPeer.Host == newAnchorPeer.Host && anchorPeer.Port == int32(newAnchorPeer.Port) {
   322  			return nil
   323  		}
   324  	}
   325  
   326  	// Append new anchor peer to anchorProtos
   327  	anchorProtos = append(anchorProtos, &pb.AnchorPeer{
   328  		Host: newAnchorPeer.Host,
   329  		Port: int32(newAnchorPeer.Port),
   330  	})
   331  
   332  	// Add anchor peers config value back to application org
   333  	err := setValue(a.orgGroup, anchorPeersValue(anchorProtos), AdminsPolicyKey)
   334  	if err != nil {
   335  		return err
   336  	}
   337  	return nil
   338  }
   339  
   340  // RemoveAnchorPeer removes an anchor peer from an application org's configuration
   341  // in the updated config.
   342  func (a *ApplicationOrg) RemoveAnchorPeer(anchorPeerToRemove Address) error {
   343  	anchorPeersProto := &pb.AnchorPeers{}
   344  
   345  	if anchorPeerConfigValue, ok := a.orgGroup.Values[AnchorPeersKey]; ok {
   346  		// Unmarshal existing anchor peers if the config value exists
   347  		err := proto.Unmarshal(anchorPeerConfigValue.Value, anchorPeersProto)
   348  		if err != nil {
   349  			return fmt.Errorf("failed unmarshaling anchor peer endpoints for application org %s: %v", a.name, err)
   350  		}
   351  	}
   352  
   353  	existingAnchorPeers := anchorPeersProto.AnchorPeers[:0]
   354  	for _, anchorPeer := range anchorPeersProto.AnchorPeers {
   355  		if anchorPeer.Host != anchorPeerToRemove.Host || anchorPeer.Port != int32(anchorPeerToRemove.Port) {
   356  			existingAnchorPeers = append(existingAnchorPeers, anchorPeer)
   357  
   358  			// Add anchor peers config value back to application org
   359  			err := setValue(a.orgGroup, anchorPeersValue(existingAnchorPeers), AdminsPolicyKey)
   360  			if err != nil {
   361  				return fmt.Errorf("failed to remove anchor peer %v from org %s: %v", anchorPeerToRemove, a.name, err)
   362  			}
   363  
   364  			return nil
   365  		}
   366  	}
   367  
   368  	if len(existingAnchorPeers) == len(anchorPeersProto.AnchorPeers) {
   369  		return fmt.Errorf("could not find anchor peer %s:%d in application org %s", anchorPeerToRemove.Host, anchorPeerToRemove.Port, a.name)
   370  	}
   371  
   372  	// Add anchor peers config value back to application org
   373  	err := setValue(a.orgGroup, anchorPeersValue(existingAnchorPeers), AdminsPolicyKey)
   374  	if err != nil {
   375  		return fmt.Errorf("failed to remove anchor peer %v from org %s: %v", anchorPeerToRemove, a.name, err)
   376  	}
   377  
   378  	return nil
   379  }
   380  
   381  // ACLs returns a map of ACLS for given config application.
   382  func (a *ApplicationGroup) ACLs() (map[string]string, error) {
   383  	aclConfigValue, ok := a.applicationGroup.Values[ACLsKey]
   384  	if !ok {
   385  		return nil, nil
   386  	}
   387  
   388  	aclProtos := &pb.ACLs{}
   389  
   390  	err := proto.Unmarshal(aclConfigValue.Value, aclProtos)
   391  	if err != nil {
   392  		return nil, fmt.Errorf("unmarshaling %s: %v", ACLsKey, err)
   393  	}
   394  
   395  	retACLs := map[string]string{}
   396  	for apiResource, policyRef := range aclProtos.Acls {
   397  		retACLs[apiResource] = policyRef.PolicyRef
   398  	}
   399  
   400  	return retACLs, nil
   401  }
   402  
   403  // SetACLs sets ACLS to an existing channel config application.
   404  // If an ACL already exists in current configuration, it will be replaced with new ACL.
   405  func (a *ApplicationGroup) SetACLs(acls map[string]string) error {
   406  	err := setValue(a.applicationGroup, aclValues(acls), AdminsPolicyKey)
   407  	if err != nil {
   408  		return err
   409  	}
   410  
   411  	return nil
   412  }
   413  
   414  // RemoveACLs a list of ACLs from given channel config application.
   415  // Specifying acls that do not exist in the application ConfigGroup of the channel config will not return a error.
   416  // Removal will panic if application group does not exist.
   417  func (a *ApplicationGroup) RemoveACLs(acls []string) error {
   418  	configACLs, err := a.ACLs()
   419  	if err != nil {
   420  		return err
   421  	}
   422  
   423  	for _, acl := range acls {
   424  		delete(configACLs, acl)
   425  	}
   426  
   427  	err = setValue(a.applicationGroup, aclValues(configACLs), AdminsPolicyKey)
   428  	if err != nil {
   429  		return err
   430  	}
   431  
   432  	return nil
   433  }
   434  
   435  // SetMSP updates the MSP config for the specified application
   436  // org group.
   437  func (a *ApplicationOrg) SetMSP(updatedMSP MSP) error {
   438  	currentMSP, err := a.MSP().Configuration()
   439  	if err != nil {
   440  		return fmt.Errorf("retrieving msp: %v", err)
   441  	}
   442  
   443  	if currentMSP.Name != updatedMSP.Name {
   444  		return errors.New("MSP name cannot be changed")
   445  	}
   446  
   447  	err = updatedMSP.validateCACerts()
   448  	if err != nil {
   449  		return err
   450  	}
   451  
   452  	err = a.setMSPConfig(updatedMSP)
   453  	if err != nil {
   454  		return err
   455  	}
   456  
   457  	return nil
   458  }
   459  
   460  func (a *ApplicationOrg) setMSPConfig(updatedMSP MSP) error {
   461  	mspConfig, err := newMSPConfig(updatedMSP)
   462  	if err != nil {
   463  		return fmt.Errorf("new msp config: %v", err)
   464  	}
   465  
   466  	err = setValue(a.orgGroup, mspValue(mspConfig), AdminsPolicyKey)
   467  	if err != nil {
   468  		return err
   469  	}
   470  
   471  	return nil
   472  }
   473  
   474  // newApplicationGroupTemplate returns the application component of the channel
   475  // configuration with only the names of the application organizations.
   476  // By default, it sets the mod_policy of all elements to "Admins".
   477  func newApplicationGroupTemplate(application Application) (*cb.ConfigGroup, error) {
   478  	var err error
   479  
   480  	applicationGroup := newConfigGroup()
   481  	applicationGroup.ModPolicy = AdminsPolicyKey
   482  
   483  	if application.ModPolicy != "" {
   484  		applicationGroup.ModPolicy = application.ModPolicy
   485  	}
   486  
   487  	if err = setPolicies(applicationGroup, application.Policies); err != nil {
   488  		return nil, err
   489  	}
   490  
   491  	if len(application.ACLs) > 0 {
   492  		err = setValue(applicationGroup, aclValues(application.ACLs), AdminsPolicyKey)
   493  		if err != nil {
   494  			return nil, err
   495  		}
   496  	}
   497  
   498  	if len(application.Capabilities) > 0 {
   499  		err = setValue(applicationGroup, capabilitiesValue(application.Capabilities), AdminsPolicyKey)
   500  		if err != nil {
   501  			return nil, err
   502  		}
   503  	}
   504  
   505  	for _, org := range application.Organizations {
   506  		applicationGroup.Groups[org.Name] = newConfigGroup()
   507  	}
   508  
   509  	return applicationGroup, nil
   510  }
   511  
   512  // newApplicationGroup returns the application component of the channel
   513  // configuration with the entire configuration for application organizations.
   514  // By default, it sets the mod_policy of all elements to "Admins".
   515  func newApplicationGroup(application Application) (*cb.ConfigGroup, error) {
   516  	applicationGroup, err := newApplicationGroupTemplate(application)
   517  	if err != nil {
   518  		return nil, err
   519  	}
   520  
   521  	for _, org := range application.Organizations {
   522  		applicationGroup.Groups[org.Name], err = newOrgConfigGroup(org)
   523  		if err != nil {
   524  			return nil, fmt.Errorf("org group '%s': %v", org.Name, err)
   525  		}
   526  	}
   527  
   528  	return applicationGroup, nil
   529  }
   530  
   531  // aclValues returns the config definition for an application's resources based ACL definitions.
   532  // It is a value for the /Channel/Application/.
   533  func aclValues(acls map[string]string) *standardConfigValue {
   534  	a := &pb.ACLs{
   535  		Acls: make(map[string]*pb.APIResource),
   536  	}
   537  
   538  	for apiResource, policyRef := range acls {
   539  		a.Acls[apiResource] = &pb.APIResource{PolicyRef: policyRef}
   540  	}
   541  
   542  	return &standardConfigValue{
   543  		key:   ACLsKey,
   544  		value: a,
   545  	}
   546  }
   547  
   548  // anchorPeersValue returns the config definition for an org's anchor peers.
   549  // It is a value for the /Channel/Application/*.
   550  func anchorPeersValue(anchorPeers []*pb.AnchorPeer) *standardConfigValue {
   551  	return &standardConfigValue{
   552  		key:   AnchorPeersKey,
   553  		value: &pb.AnchorPeers{AnchorPeers: anchorPeers},
   554  	}
   555  }