github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/initializer/orderer/configtx/profile.go (about)

     1  /*
     2   * Copyright contributors to the Hyperledger Fabric Operator project
     3   *
     4   * SPDX-License-Identifier: Apache-2.0
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at:
     9   *
    10   * 	  http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package configtx
    20  
    21  import (
    22  	"strings"
    23  
    24  	"github.com/gogo/protobuf/proto"
    25  	"github.com/hyperledger/fabric/common/cauthdsl"
    26  	"github.com/hyperledger/fabric/common/channelconfig"
    27  	"github.com/hyperledger/fabric/common/policies"
    28  
    29  	cb "github.com/hyperledger/fabric-protos-go/common"
    30  	"github.com/hyperledger/fabric-protos-go/msp"
    31  	"github.com/hyperledger/fabric-protos-go/orderer/etcdraft"
    32  	utils "github.com/hyperledger/fabric/protoutil"
    33  	"github.com/pkg/errors"
    34  )
    35  
    36  const (
    37  	ordererAdminsPolicyName = "/Channel/Orderer/Admins"
    38  )
    39  
    40  func (p *Profile) AddOrdererAddress(address string) {
    41  	p.Orderer.Addresses = append(p.Orderer.Addresses, address)
    42  }
    43  
    44  func (p *Profile) SetOrdererType(ordererType string) {
    45  	p.Orderer.OrdererType = ordererType
    46  }
    47  
    48  func (p *Profile) SetCapabilitiesForOrderer(capabilities map[string]bool) {
    49  	p.Orderer.Capabilities = capabilities
    50  }
    51  
    52  func (p *Profile) AddRaftConsentingNode(consenter *etcdraft.Consenter) error {
    53  	if strings.ToLower(p.Orderer.OrdererType) != "etcdraft" {
    54  		return errors.New("can only add raft consenting node if orderer type is 'etcdraft'")
    55  	}
    56  	p.Orderer.EtcdRaft.Consenters = append(p.Orderer.EtcdRaft.Consenters, consenter)
    57  	return nil
    58  }
    59  
    60  func (p *Profile) AddConsortium(name string, consortium *Consortium) error {
    61  	for _, org := range consortium.Organizations {
    62  		err := ValidateOrg(org)
    63  		if err != nil {
    64  			return err
    65  		}
    66  	}
    67  	p.Consortiums[name] = consortium
    68  	return nil
    69  }
    70  
    71  func (p *Profile) AddOrgToConsortium(name string, org *Organization) error {
    72  	err := ValidateOrg(org)
    73  	if err != nil {
    74  		return err
    75  	}
    76  	p.Consortiums[name].Organizations = append(p.Consortiums[name].Organizations, org)
    77  	return nil
    78  }
    79  
    80  func (p *Profile) AddOrgToOrderer(org *Organization) error {
    81  	err := ValidateOrg(org)
    82  	if err != nil {
    83  		return err
    84  	}
    85  	p.Orderer.Organizations = append(p.Orderer.Organizations, org)
    86  	return nil
    87  }
    88  
    89  func (p *Profile) SetMaxChannel(max uint64) {
    90  	p.Orderer.MaxChannels = max
    91  }
    92  
    93  func (p *Profile) SetChannelPolicy(policies map[string]*Policy) {
    94  	p.Policies = policies
    95  }
    96  
    97  func (p *Profile) GenerateBlock(channelID string, mspConfigs map[string]*msp.MSPConfig) ([]byte, error) {
    98  	if p.Orderer == nil {
    99  		return nil, errors.Errorf("refusing to generate block which is missing orderer section")
   100  	}
   101  
   102  	if p.Consortiums == nil {
   103  		return nil, errors.New("Genesis block does not contain a consortiums group definition.  This block cannot be used for orderer bootstrap.")
   104  	}
   105  
   106  	cg, err := p.NewChannelConfigGroup(mspConfigs)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  
   111  	genesisBlock := p.Block(channelID, cg)
   112  	gBlockBytes, err := utils.Marshal(genesisBlock)
   113  	if err != nil {
   114  		return nil, errors.Wrap(err, "error marshalling genesis block")
   115  	}
   116  
   117  	return gBlockBytes, nil
   118  
   119  }
   120  
   121  func (p *Profile) Block(channelID string, channelGroup *cb.ConfigGroup) *cb.Block {
   122  	payloadChannelHeader := utils.MakeChannelHeader(cb.HeaderType_CONFIG, int32(1), channelID, 0)
   123  	payloadSignatureHeader := utils.MakeSignatureHeader(nil, utils.CreateNonceOrPanic())
   124  	utils.SetTxID(payloadChannelHeader, payloadSignatureHeader)
   125  	payloadHeader := utils.MakePayloadHeader(payloadChannelHeader, payloadSignatureHeader)
   126  	payload := &cb.Payload{Header: payloadHeader, Data: utils.MarshalOrPanic(&cb.ConfigEnvelope{Config: &cb.Config{ChannelGroup: channelGroup}})}
   127  	envelope := &cb.Envelope{Payload: utils.MarshalOrPanic(payload), Signature: nil}
   128  
   129  	block := utils.NewBlock(0, nil)
   130  	block.Data = &cb.BlockData{Data: [][]byte{utils.MarshalOrPanic(envelope)}}
   131  	block.Header.DataHash = utils.BlockDataHash(block.Data)
   132  	block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIG] = utils.MarshalOrPanic(&cb.Metadata{
   133  		Value: utils.MarshalOrPanic(&cb.LastConfig{Index: 0}),
   134  	})
   135  	return block
   136  }
   137  
   138  func (p *Profile) NewChannelConfigGroup(mspConfigs map[string]*msp.MSPConfig) (*cb.ConfigGroup, error) {
   139  	channelGroup := utils.NewConfigGroup()
   140  	if len(p.Policies) == 0 {
   141  		addImplicitMetaPolicyDefaults(channelGroup)
   142  	}
   143  
   144  	err := addPolicies(channelGroup, p.Policies, channelconfig.AdminsPolicyKey)
   145  	if err != nil {
   146  		return nil, errors.Wrapf(err, "error adding policies to channel group")
   147  	}
   148  
   149  	addValue(channelGroup, channelconfig.HashingAlgorithmValue(), channelconfig.AdminsPolicyKey)
   150  	addValue(channelGroup, channelconfig.BlockDataHashingStructureValue(), channelconfig.AdminsPolicyKey)
   151  	if p.Orderer != nil && len(p.Orderer.Addresses) > 0 {
   152  		addValue(channelGroup, channelconfig.OrdererAddressesValue(p.Orderer.Addresses), ordererAdminsPolicyName)
   153  	}
   154  
   155  	if p.Consortium != "" {
   156  		addValue(channelGroup, channelconfig.ConsortiumValue(p.Consortium), channelconfig.AdminsPolicyKey)
   157  	}
   158  
   159  	if len(p.Capabilities) > 0 {
   160  		addValue(channelGroup, channelconfig.CapabilitiesValue(p.Capabilities), channelconfig.AdminsPolicyKey)
   161  	}
   162  
   163  	if p.Orderer != nil {
   164  		channelGroup.Groups[channelconfig.OrdererGroupKey], err = p.NewOrdererGroup(p.Orderer, mspConfigs)
   165  		if err != nil {
   166  			return nil, errors.Wrap(err, "could not create orderer group")
   167  		}
   168  	}
   169  
   170  	if p.Application != nil {
   171  		channelGroup.Groups[channelconfig.ApplicationGroupKey], err = NewApplicationGroup(p.Application)
   172  		if err != nil {
   173  			return nil, errors.Wrap(err, "could not create application group")
   174  		}
   175  	}
   176  
   177  	if p.Consortiums != nil {
   178  		channelGroup.Groups[channelconfig.ConsortiumsGroupKey], err = NewConsortiumsGroup(p.Consortiums)
   179  		if err != nil {
   180  			return nil, errors.Wrap(err, "could not create consortiums group")
   181  		}
   182  	}
   183  
   184  	channelGroup.ModPolicy = channelconfig.AdminsPolicyKey
   185  	return channelGroup, nil
   186  }
   187  
   188  func (p *Profile) NewOrdererGroup(conf *Orderer, mspConfigs map[string]*msp.MSPConfig) (*cb.ConfigGroup, error) {
   189  	ordererGroup := utils.NewConfigGroup()
   190  	if len(conf.Policies) == 0 {
   191  		addImplicitMetaPolicyDefaults(ordererGroup)
   192  	} else {
   193  		if err := addPolicies(ordererGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil {
   194  			return nil, errors.Wrapf(err, "error adding policies to orderer group")
   195  		}
   196  	}
   197  	ordererGroup.Policies[BlockValidationPolicyKey] = &cb.ConfigPolicy{
   198  		Policy:    policies.ImplicitMetaAnyPolicy(channelconfig.WritersPolicyKey).Value(),
   199  		ModPolicy: channelconfig.AdminsPolicyKey,
   200  	}
   201  	addValue(ordererGroup, channelconfig.BatchSizeValue(
   202  		conf.BatchSize.MaxMessageCount,
   203  		conf.BatchSize.AbsoluteMaxBytes,
   204  		conf.BatchSize.PreferredMaxBytes,
   205  	), channelconfig.AdminsPolicyKey)
   206  	addValue(ordererGroup, channelconfig.BatchTimeoutValue(conf.BatchTimeout.String()), channelconfig.AdminsPolicyKey)
   207  	addValue(ordererGroup, channelconfig.ChannelRestrictionsValue(conf.MaxChannels), channelconfig.AdminsPolicyKey)
   208  
   209  	if len(conf.Capabilities) > 0 {
   210  		addValue(ordererGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey)
   211  	}
   212  
   213  	var consensusMetadata []byte
   214  	switch conf.OrdererType {
   215  	case ConsensusTypeSolo:
   216  		// nothing to be done here
   217  	case ConsensusTypeKafka:
   218  		// nothing to be done here
   219  	case ConsensusTypeEtcdRaft:
   220  		cm, err := proto.Marshal(p.Orderer.EtcdRaft)
   221  		if err != nil {
   222  			return nil, err
   223  		}
   224  		consensusMetadata = cm
   225  	default:
   226  		return nil, errors.Errorf("unknown orderer type: %s", conf.OrdererType)
   227  	}
   228  
   229  	addValue(ordererGroup, channelconfig.ConsensusTypeValue(conf.OrdererType, consensusMetadata), channelconfig.AdminsPolicyKey)
   230  
   231  	for _, org := range conf.Organizations {
   232  		var err error
   233  		ordererGroup.Groups[org.Name], err = NewOrdererOrgGroup(org, mspConfigs[org.Name])
   234  		if err != nil {
   235  			return nil, errors.Wrap(err, "failed to create orderer org")
   236  		}
   237  	}
   238  
   239  	ordererGroup.ModPolicy = channelconfig.AdminsPolicyKey
   240  	return ordererGroup, nil
   241  }
   242  
   243  func ValidateOrg(org *Organization) error {
   244  	if org.MSPType == "" {
   245  		return errors.Errorf("failed to provide msp type for org '%s'", org.Name)
   246  	}
   247  
   248  	if org.AdminPrincipal == "" {
   249  		return errors.Errorf("failed to provide admin principal")
   250  	}
   251  
   252  	return nil
   253  }
   254  
   255  // NewOrdererOrgGroup returns an orderer org component of the channel configuration.  It defines the crypto material for the
   256  // organization (its MSP).  It sets the mod_policy of all elements to "Admins".
   257  func NewOrdererOrgGroup(conf *Organization, mspConfig *msp.MSPConfig) (*cb.ConfigGroup, error) {
   258  	ordererOrgGroup := utils.NewConfigGroup()
   259  	if len(conf.Policies) == 0 {
   260  		addSignaturePolicyDefaults(ordererOrgGroup, conf.ID, conf.AdminPrincipal != AdminRoleAdminPrincipal)
   261  	} else {
   262  		if err := addPolicies(ordererOrgGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil {
   263  			return nil, errors.Wrapf(err, "error adding policies to orderer org group '%s'", conf.Name)
   264  		}
   265  	}
   266  
   267  	addValue(ordererOrgGroup, channelconfig.MSPValue(mspConfig), channelconfig.AdminsPolicyKey)
   268  
   269  	ordererOrgGroup.ModPolicy = channelconfig.AdminsPolicyKey
   270  
   271  	if len(conf.OrdererEndpoints) > 0 {
   272  		addValue(ordererOrgGroup, channelconfig.EndpointsValue(conf.OrdererEndpoints), channelconfig.AdminsPolicyKey)
   273  	}
   274  
   275  	return ordererOrgGroup, nil
   276  }
   277  
   278  func addValue(cg *cb.ConfigGroup, value channelconfig.ConfigValue, modPolicy string) {
   279  	cg.Values[value.Key()] = &cb.ConfigValue{
   280  		Value:     utils.MarshalOrPanic(value.Value()),
   281  		ModPolicy: modPolicy,
   282  	}
   283  }
   284  
   285  func addPolicy(cg *cb.ConfigGroup, policy policies.ConfigPolicy, modPolicy string) {
   286  	cg.Policies[policy.Key()] = &cb.ConfigPolicy{
   287  		Policy:    policy.Value(),
   288  		ModPolicy: modPolicy,
   289  	}
   290  }
   291  
   292  func addPolicies(cg *cb.ConfigGroup, policyMap map[string]*Policy, modPolicy string) error {
   293  	for policyName, policy := range policyMap {
   294  		switch policy.Type {
   295  		case ImplicitMetaPolicyType:
   296  			imp, err := policies.ImplicitMetaFromString(policy.Rule)
   297  			if err != nil {
   298  				return errors.Wrapf(err, "invalid implicit meta policy rule '%s'", policy.Rule)
   299  			}
   300  			cg.Policies[policyName] = &cb.ConfigPolicy{
   301  				ModPolicy: modPolicy,
   302  				Policy: &cb.Policy{
   303  					Type:  int32(cb.Policy_IMPLICIT_META),
   304  					Value: utils.MarshalOrPanic(imp),
   305  				},
   306  			}
   307  		case SignaturePolicyType:
   308  			sp, err := cauthdsl.FromString(policy.Rule)
   309  			if err != nil {
   310  				return errors.Wrapf(err, "invalid signature policy rule '%s'", policy.Rule)
   311  			}
   312  			cg.Policies[policyName] = &cb.ConfigPolicy{
   313  				ModPolicy: modPolicy,
   314  				Policy: &cb.Policy{
   315  					Type:  int32(cb.Policy_SIGNATURE),
   316  					Value: utils.MarshalOrPanic(sp),
   317  				},
   318  			}
   319  		default:
   320  			return errors.Errorf("unknown policy type: %s", policy.Type)
   321  		}
   322  	}
   323  	return nil
   324  }
   325  
   326  func addImplicitMetaPolicyDefaults(cg *cb.ConfigGroup) {
   327  	addPolicy(cg, policies.ImplicitMetaMajorityPolicy(channelconfig.AdminsPolicyKey), channelconfig.AdminsPolicyKey)
   328  	addPolicy(cg, policies.ImplicitMetaAnyPolicy(channelconfig.ReadersPolicyKey), channelconfig.AdminsPolicyKey)
   329  	addPolicy(cg, policies.ImplicitMetaAnyPolicy(channelconfig.WritersPolicyKey), channelconfig.AdminsPolicyKey)
   330  }
   331  
   332  func addSignaturePolicyDefaults(cg *cb.ConfigGroup, mspID string, devMode bool) {
   333  	if devMode {
   334  		addPolicy(cg, policies.SignaturePolicy(channelconfig.AdminsPolicyKey, cauthdsl.SignedByMspMember(mspID)), channelconfig.AdminsPolicyKey)
   335  	} else {
   336  		addPolicy(cg, policies.SignaturePolicy(channelconfig.AdminsPolicyKey, cauthdsl.SignedByMspAdmin(mspID)), channelconfig.AdminsPolicyKey)
   337  	}
   338  	addPolicy(cg, policies.SignaturePolicy(channelconfig.ReadersPolicyKey, cauthdsl.SignedByMspMember(mspID)), channelconfig.AdminsPolicyKey)
   339  	addPolicy(cg, policies.SignaturePolicy(channelconfig.WritersPolicyKey, cauthdsl.SignedByMspMember(mspID)), channelconfig.AdminsPolicyKey)
   340  }