github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/common/tools/configtxlator/sanitycheck/sanitycheck.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8                   http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package sanitycheck
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/hyperledger/fabric/common/configtx"
    23  	cb "github.com/hyperledger/fabric/protos/common"
    24  	mspprotos "github.com/hyperledger/fabric/protos/msp"
    25  	"github.com/hyperledger/fabric/protos/utils"
    26  
    27  	"github.com/golang/protobuf/proto"
    28  )
    29  
    30  type Messages struct {
    31  	GeneralErrors   []string          `json:"general_errors"`
    32  	ElementWarnings []*ElementMessage `json:"element_errors"`
    33  	ElementErrors   []*ElementMessage `json:"element_errors"`
    34  }
    35  
    36  type ElementMessage struct {
    37  	Path    string `json:"path"`
    38  	Message string `json:"message"`
    39  }
    40  
    41  func Check(config *cb.Config) (*Messages, error) {
    42  	envConfig, err := utils.CreateSignedEnvelope(cb.HeaderType_CONFIG, "sanitycheck", nil, &cb.ConfigEnvelope{Config: config}, 0, 0)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	result := &Messages{}
    48  
    49  	cm, err := configtx.NewManagerImpl(envConfig, configtx.NewInitializer(), nil)
    50  	if err != nil {
    51  		result.GeneralErrors = []string{err.Error()}
    52  		return result, nil
    53  	}
    54  
    55  	// This should come from the MSP manager, but, for some reason
    56  	// the MSP manager is not intialized if there are no orgs, so,
    57  	// we collect this manually.
    58  	mspMap := make(map[string]struct{})
    59  
    60  	if ac, ok := cm.ApplicationConfig(); ok {
    61  		for _, org := range ac.Organizations() {
    62  			mspMap[org.MSPID()] = struct{}{}
    63  		}
    64  	}
    65  
    66  	if oc, ok := cm.OrdererConfig(); ok {
    67  		for _, org := range oc.Organizations() {
    68  			mspMap[org.MSPID()] = struct{}{}
    69  		}
    70  	}
    71  
    72  	policyWarnings, policyErrors := checkPolicyPrincipals(config.ChannelGroup, "", mspMap)
    73  
    74  	result.ElementWarnings = policyWarnings
    75  	result.ElementErrors = policyErrors
    76  
    77  	return result, nil
    78  }
    79  
    80  func checkPolicyPrincipals(group *cb.ConfigGroup, basePath string, mspMap map[string]struct{}) (warnings []*ElementMessage, errors []*ElementMessage) {
    81  	for policyName, configPolicy := range group.Policies {
    82  		appendError := func(err string) {
    83  			errors = append(errors, &ElementMessage{
    84  				Path:    basePath + ".policies." + policyName,
    85  				Message: err,
    86  			})
    87  		}
    88  
    89  		appendWarning := func(err string) {
    90  			warnings = append(errors, &ElementMessage{
    91  				Path:    basePath + ".policies." + policyName,
    92  				Message: err,
    93  			})
    94  		}
    95  
    96  		if configPolicy.Policy == nil {
    97  			appendError(fmt.Sprintf("no policy value set for %s", policyName))
    98  			continue
    99  		}
   100  
   101  		if configPolicy.Policy.Type != int32(cb.Policy_SIGNATURE) {
   102  			continue
   103  		}
   104  		spe := &cb.SignaturePolicyEnvelope{}
   105  		err := proto.Unmarshal(configPolicy.Policy.Value, spe)
   106  		if err != nil {
   107  			appendError(fmt.Sprintf("error unmarshaling policy value to SignaturePolicyEnvelope: %s", err))
   108  			continue
   109  		}
   110  
   111  		for i, identity := range spe.Identities {
   112  			var mspID string
   113  			switch identity.PrincipalClassification {
   114  			case mspprotos.MSPPrincipal_ROLE:
   115  				role := &mspprotos.MSPRole{}
   116  				err = proto.Unmarshal(identity.Principal, role)
   117  				if err != nil {
   118  					appendError(fmt.Sprintf("value of identities array at index %d is of type ROLE, but could not be unmarshaled to msp.MSPRole: %s", i, err))
   119  					continue
   120  				}
   121  				mspID = role.MspIdentifier
   122  			case mspprotos.MSPPrincipal_ORGANIZATION_UNIT:
   123  				ou := &mspprotos.OrganizationUnit{}
   124  				err = proto.Unmarshal(identity.Principal, ou)
   125  				if err != nil {
   126  					appendError(fmt.Sprintf("value of identities array at index %d is of type ORGANIZATION_UNIT, but could not be unmarshaled to msp.OrganizationUnit: %s", i, err))
   127  					continue
   128  				}
   129  				mspID = ou.MspIdentifier
   130  			default:
   131  				continue
   132  			}
   133  
   134  			_, ok := mspMap[mspID]
   135  			if !ok {
   136  				appendWarning(fmt.Sprintf("identity principal at index %d refers to MSP ID '%s', which is not an MSP in the network", i, mspID))
   137  			}
   138  		}
   139  	}
   140  
   141  	for subGroupName, subGroup := range group.Groups {
   142  		subWarnings, subErrors := checkPolicyPrincipals(subGroup, basePath+".groups."+subGroupName, mspMap)
   143  		warnings = append(warnings, subWarnings...)
   144  		errors = append(errors, subErrors...)
   145  	}
   146  	return
   147  }