github.com/lzy4123/fabric@v2.1.1+incompatible/common/configtx/validator_test.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  	"fmt"
    11  	"strings"
    12  	"testing"
    13  
    14  	cb "github.com/hyperledger/fabric-protos-go/common"
    15  	mockpolicies "github.com/hyperledger/fabric/common/configtx/mock"
    16  	"github.com/hyperledger/fabric/common/policies"
    17  	"github.com/hyperledger/fabric/protoutil"
    18  	"github.com/stretchr/testify/assert"
    19  )
    20  
    21  //go:generate counterfeiter -o mock/policy_manager.go --fake-name PolicyManager . policyManager
    22  type policyManager interface {
    23  	policies.Manager
    24  }
    25  
    26  //go:generate counterfeiter -o mock/policy.go --fake-name Policy . policy
    27  type policy interface {
    28  	policies.Policy
    29  }
    30  
    31  var defaultChannel = "default.channel.id"
    32  
    33  func defaultPolicyManager() *mockpolicies.PolicyManager {
    34  	fakePolicy := &mockpolicies.Policy{}
    35  	fakePolicy.EvaluateSignedDataReturns(nil)
    36  	fakePolicyManager := &mockpolicies.PolicyManager{}
    37  	fakePolicyManager.GetPolicyReturns(fakePolicy, true)
    38  	fakePolicyManager.ManagerReturns(fakePolicyManager, true)
    39  	return fakePolicyManager
    40  }
    41  
    42  type configPair struct {
    43  	key   string
    44  	value *cb.ConfigValue
    45  }
    46  
    47  func makeConfigPair(id, modificationPolicy string, lastModified uint64, data []byte) *configPair {
    48  	return &configPair{
    49  		key: id,
    50  		value: &cb.ConfigValue{
    51  			ModPolicy: modificationPolicy,
    52  			Version:   lastModified,
    53  			Value:     data,
    54  		},
    55  	}
    56  }
    57  
    58  func makeConfig(configPairs ...*configPair) *cb.Config {
    59  	channelGroup := protoutil.NewConfigGroup()
    60  	for _, pair := range configPairs {
    61  		channelGroup.Values[pair.key] = pair.value
    62  	}
    63  
    64  	return &cb.Config{
    65  		ChannelGroup: channelGroup,
    66  	}
    67  }
    68  
    69  func makeConfigSet(configPairs ...*configPair) *cb.ConfigGroup {
    70  	result := protoutil.NewConfigGroup()
    71  	for _, pair := range configPairs {
    72  		result.Values[pair.key] = pair.value
    73  	}
    74  	return result
    75  }
    76  
    77  func makeConfigUpdateEnvelope(channelID string, readSet, writeSet *cb.ConfigGroup) *cb.Envelope {
    78  	return &cb.Envelope{
    79  		Payload: protoutil.MarshalOrPanic(&cb.Payload{
    80  			Header: &cb.Header{
    81  				ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
    82  					Type: int32(cb.HeaderType_CONFIG_UPDATE),
    83  				}),
    84  			},
    85  			Data: protoutil.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
    86  				ConfigUpdate: protoutil.MarshalOrPanic(&cb.ConfigUpdate{
    87  					ChannelId: channelID,
    88  					ReadSet:   readSet,
    89  					WriteSet:  writeSet,
    90  				}),
    91  			}),
    92  		}),
    93  	}
    94  }
    95  
    96  func TestEmptyChannel(t *testing.T) {
    97  	_, err := NewValidatorImpl("foo", &cb.Config{}, "foonamespace", defaultPolicyManager())
    98  	assert.Error(t, err)
    99  }
   100  
   101  // TestDifferentChannelID tests that a config update for a different channel ID fails
   102  func TestDifferentChannelID(t *testing.T) {
   103  	vi, err := NewValidatorImpl(
   104  		defaultChannel,
   105  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   106  		"foonamespace",
   107  		defaultPolicyManager())
   108  
   109  	if err != nil {
   110  		t.Fatalf("Error constructing config manager: %s", err)
   111  	}
   112  
   113  	newConfig := makeConfigUpdateEnvelope("wrongChannel", makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 1, []byte("foo"))))
   114  
   115  	_, err = vi.ProposeConfigUpdate(newConfig)
   116  	if err == nil {
   117  		t.Error("Should have errored when proposing a new config set the wrong channel ID")
   118  	}
   119  }
   120  
   121  // TestOldConfigReplay tests that resubmitting a config for a sequence number which is not newer is ignored
   122  func TestOldConfigReplay(t *testing.T) {
   123  	vi, err := NewValidatorImpl(
   124  		defaultChannel,
   125  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   126  		"foonamespace",
   127  		defaultPolicyManager())
   128  
   129  	if err != nil {
   130  		t.Fatalf("Error constructing config manager: %s", err)
   131  	}
   132  
   133  	newConfig := makeConfigUpdateEnvelope(defaultChannel, makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 0, []byte("foo"))))
   134  
   135  	_, err = vi.ProposeConfigUpdate(newConfig)
   136  
   137  	assert.EqualError(t, err, "error authorizing update: error validating DeltaSet: attempt to set key [Value]  /foonamespace/foo to version 0, but key is at version 0")
   138  }
   139  
   140  // TestValidConfigChange tests the happy path of updating a config value with no defaultModificationPolicy
   141  func TestValidConfigChange(t *testing.T) {
   142  	vi, err := NewValidatorImpl(
   143  		defaultChannel,
   144  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   145  		"foonamespace",
   146  		defaultPolicyManager())
   147  
   148  	if err != nil {
   149  		t.Fatalf("Error constructing config manager: %s", err)
   150  	}
   151  
   152  	newConfig := makeConfigUpdateEnvelope(defaultChannel, makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 1, []byte("foo"))))
   153  
   154  	configEnv, err := vi.ProposeConfigUpdate(newConfig)
   155  	if err != nil {
   156  		t.Errorf("Should not have errored proposing config: %s", err)
   157  	}
   158  
   159  	err = vi.Validate(configEnv)
   160  	if err != nil {
   161  		t.Errorf("Should not have errored validating config: %s", err)
   162  	}
   163  }
   164  
   165  // TestConfigChangeRegressedSequence tests to make sure that a new config cannot roll back one of the
   166  // config values while advancing another
   167  func TestConfigChangeRegressedSequence(t *testing.T) {
   168  	vi, err := NewValidatorImpl(
   169  		defaultChannel,
   170  		makeConfig(makeConfigPair("foo", "foo", 1, []byte("foo"))),
   171  		"foonamespace",
   172  		defaultPolicyManager())
   173  
   174  	if err != nil {
   175  		t.Fatalf("Error constructing config manager: %s", err)
   176  	}
   177  
   178  	newConfig := makeConfigUpdateEnvelope(
   179  		defaultChannel,
   180  		makeConfigSet(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   181  		makeConfigSet(makeConfigPair("bar", "bar", 2, []byte("bar"))),
   182  	)
   183  
   184  	_, err = vi.ProposeConfigUpdate(newConfig)
   185  	assert.EqualError(t, err, "error authorizing update: error validating ReadSet: proposed update requires that key [Value]  /foonamespace/foo be at version 0, but it is currently at version 1")
   186  }
   187  
   188  // TestConfigChangeOldSequence tests to make sure that a new config cannot roll back one of the
   189  // config values while advancing another
   190  func TestConfigChangeOldSequence(t *testing.T) {
   191  	vi, err := NewValidatorImpl(
   192  		defaultChannel,
   193  		makeConfig(makeConfigPair("foo", "foo", 1, []byte("foo"))),
   194  		"foonamespace",
   195  		defaultPolicyManager())
   196  
   197  	if err != nil {
   198  		t.Fatalf("Error constructing config manager: %s", err)
   199  	}
   200  
   201  	newConfig := makeConfigUpdateEnvelope(
   202  		defaultChannel,
   203  		makeConfigSet(),
   204  		makeConfigSet(
   205  			makeConfigPair("foo", "foo", 2, []byte("foo")),
   206  			makeConfigPair("bar", "bar", 1, []byte("bar")),
   207  		),
   208  	)
   209  
   210  	_, err = vi.ProposeConfigUpdate(newConfig)
   211  
   212  	assert.EqualError(t, err, "error authorizing update: error validating DeltaSet: attempted to set key [Value]  /foonamespace/bar to version 1, but key does not exist")
   213  }
   214  
   215  // TestConfigPartialUpdate tests to make sure that a new config can set only part
   216  // of the config and still be accepted
   217  func TestConfigPartialUpdate(t *testing.T) {
   218  	vi, err := NewValidatorImpl(
   219  		defaultChannel,
   220  		makeConfig(
   221  			makeConfigPair("foo", "foo", 0, []byte("foo")),
   222  			makeConfigPair("bar", "bar", 0, []byte("bar")),
   223  		),
   224  		"foonamespace",
   225  		defaultPolicyManager())
   226  
   227  	if err != nil {
   228  		t.Fatalf("Error constructing config manager: %s", err)
   229  	}
   230  
   231  	newConfig := makeConfigUpdateEnvelope(
   232  		defaultChannel,
   233  		makeConfigSet(),
   234  		makeConfigSet(makeConfigPair("bar", "bar", 1, []byte("bar"))),
   235  	)
   236  
   237  	_, err = vi.ProposeConfigUpdate(newConfig)
   238  	assert.NoError(t, err, "Should have allowed partial update")
   239  }
   240  
   241  // TestEmptyConfigUpdate tests to make sure that an empty config is rejected as an update
   242  func TestEmptyConfigUpdate(t *testing.T) {
   243  	vi, err := NewValidatorImpl(
   244  		defaultChannel,
   245  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   246  		"foonamespace",
   247  		defaultPolicyManager())
   248  
   249  	if err != nil {
   250  		t.Fatalf("Error constructing config manager: %s", err)
   251  	}
   252  
   253  	newConfig := &cb.Envelope{}
   254  
   255  	_, err = vi.ProposeConfigUpdate(newConfig)
   256  	assert.EqualError(t, err, "error converting envelope to config update: envelope must have a Header")
   257  }
   258  
   259  // TestSilentConfigModification tests to make sure that even if a validly signed new config for an existing sequence number
   260  // is substituted into an otherwise valid new config, that the new config is rejected for attempting a modification without
   261  // increasing the config item's LastModified
   262  func TestSilentConfigModification(t *testing.T) {
   263  	vi, err := NewValidatorImpl(
   264  		defaultChannel,
   265  		makeConfig(
   266  			makeConfigPair("foo", "foo", 0, []byte("foo")),
   267  			makeConfigPair("bar", "bar", 0, []byte("bar")),
   268  		),
   269  		"foonamespace",
   270  		defaultPolicyManager())
   271  
   272  	if err != nil {
   273  		t.Fatalf("Error constructing config manager: %s", err)
   274  	}
   275  
   276  	newConfig := makeConfigUpdateEnvelope(
   277  		defaultChannel,
   278  		makeConfigSet(),
   279  		makeConfigSet(
   280  			makeConfigPair("foo", "foo", 0, []byte("different")),
   281  			makeConfigPair("bar", "bar", 1, []byte("bar")),
   282  		),
   283  	)
   284  
   285  	_, err = vi.ProposeConfigUpdate(newConfig)
   286  	assert.EqualError(t, err, "error authorizing update: error validating DeltaSet: attempt to set key [Value]  /foonamespace/foo to version 0, but key is at version 0")
   287  }
   288  
   289  // TestConfigChangeViolatesPolicy checks to make sure that if policy rejects the validation of a config item that
   290  // it is rejected in a config update
   291  func TestConfigChangeViolatesPolicy(t *testing.T) {
   292  	pm := defaultPolicyManager()
   293  	vi, err := NewValidatorImpl(
   294  		defaultChannel,
   295  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   296  		"foonamespace",
   297  		pm)
   298  
   299  	if err != nil {
   300  		t.Fatalf("Error constructing config manager: %s", err)
   301  	}
   302  	// Set the mock policy to error
   303  	fakePolicy := &mockpolicies.Policy{}
   304  	fakePolicy.EvaluateSignedDataReturns(fmt.Errorf("err"))
   305  	pm.GetPolicyReturns(fakePolicy, true)
   306  
   307  	newConfig := makeConfigUpdateEnvelope(defaultChannel, makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 1, []byte("foo"))))
   308  
   309  	_, err = vi.ProposeConfigUpdate(newConfig)
   310  	assert.EqualError(t, err, "error authorizing update: error validating DeltaSet: policy for [Value]  /foonamespace/foo not satisfied: err")
   311  }
   312  
   313  // TestUnchangedConfigViolatesPolicy checks to make sure that existing config items are not revalidated against their modification policies
   314  // as the policy may have changed, certs revoked, etc. since the config was adopted.
   315  func TestUnchangedConfigViolatesPolicy(t *testing.T) {
   316  	pm := defaultPolicyManager()
   317  	vi, err := NewValidatorImpl(
   318  		defaultChannel,
   319  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   320  		"foonamespace",
   321  		pm)
   322  
   323  	if err != nil {
   324  		t.Fatalf("Error constructing config manager: %s", err)
   325  	}
   326  
   327  	newConfig := makeConfigUpdateEnvelope(
   328  		defaultChannel,
   329  		makeConfigSet(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   330  		makeConfigSet(makeConfigPair("bar", "bar", 0, []byte("foo"))),
   331  	)
   332  
   333  	configEnv, err := vi.ProposeConfigUpdate(newConfig)
   334  	if err != nil {
   335  		t.Errorf("Should not have errored proposing config, but got %s", err)
   336  	}
   337  
   338  	err = vi.Validate(configEnv)
   339  	if err != nil {
   340  		t.Errorf("Should not have errored validating config, but got %s", err)
   341  	}
   342  }
   343  
   344  // TestInvalidProposal checks that even if the policy allows the transaction and the sequence etc. is well formed,
   345  // that if the handler does not accept the config, it is rejected
   346  func TestInvalidProposal(t *testing.T) {
   347  	pm := defaultPolicyManager()
   348  	vi, err := NewValidatorImpl(
   349  		defaultChannel,
   350  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   351  		"foonamespace",
   352  		pm)
   353  
   354  	if err != nil {
   355  		t.Fatalf("Error constructing config manager: %s", err)
   356  	}
   357  
   358  	fakePolicy := &mockpolicies.Policy{}
   359  	fakePolicy.EvaluateSignedDataReturns(fmt.Errorf("err"))
   360  	pm.GetPolicyReturns(fakePolicy, true)
   361  
   362  	newConfig := makeConfigUpdateEnvelope(defaultChannel, makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 1, []byte("foo"))))
   363  
   364  	_, err = vi.ProposeConfigUpdate(newConfig)
   365  	assert.EqualError(t, err, "error authorizing update: error validating DeltaSet: policy for [Value]  /foonamespace/foo not satisfied: err")
   366  }
   367  
   368  func TestValidateErrors(t *testing.T) {
   369  	t.Run("TestNilConfigEnv", func(t *testing.T) {
   370  		err := (&ValidatorImpl{}).Validate(nil)
   371  		assert.Error(t, err)
   372  		assert.Regexp(t, "config envelope is nil", err.Error())
   373  	})
   374  
   375  	t.Run("TestNilConfig", func(t *testing.T) {
   376  		err := (&ValidatorImpl{}).Validate(&cb.ConfigEnvelope{})
   377  		assert.Error(t, err)
   378  		assert.Regexp(t, "config envelope has nil config", err.Error())
   379  	})
   380  
   381  	t.Run("TestSequenceSkip", func(t *testing.T) {
   382  		err := (&ValidatorImpl{}).Validate(&cb.ConfigEnvelope{
   383  			Config: &cb.Config{
   384  				Sequence: 2,
   385  			},
   386  		})
   387  		assert.Error(t, err)
   388  		assert.Regexp(t, "config currently at sequence 0", err.Error())
   389  	})
   390  }
   391  
   392  func TestConstructionErrors(t *testing.T) {
   393  	t.Run("NilConfig", func(t *testing.T) {
   394  		v, err := NewValidatorImpl("test", nil, "foonamespace", &mockpolicies.PolicyManager{})
   395  		assert.Nil(t, v)
   396  		assert.Error(t, err)
   397  		assert.Regexp(t, "nil config parameter", err.Error())
   398  	})
   399  
   400  	t.Run("NilChannelGroup", func(t *testing.T) {
   401  		v, err := NewValidatorImpl("test", &cb.Config{}, "foonamespace", &mockpolicies.PolicyManager{})
   402  		assert.Nil(t, v)
   403  		assert.Error(t, err)
   404  		assert.Regexp(t, "nil channel group", err.Error())
   405  	})
   406  
   407  	t.Run("BadChannelID", func(t *testing.T) {
   408  		v, err := NewValidatorImpl("*&$#@*&@$#*&", &cb.Config{ChannelGroup: &cb.ConfigGroup{}}, "foonamespace", &mockpolicies.PolicyManager{})
   409  		assert.Nil(t, v)
   410  		assert.Error(t, err)
   411  		assert.Regexp(t, "bad channel ID", err.Error())
   412  		assert.EqualError(t, err, "bad channel ID: '*&$#@*&@$#*&' contains illegal characters")
   413  	})
   414  
   415  	t.Run("EmptyChannelID", func(t *testing.T) {
   416  		v, err := NewValidatorImpl("", &cb.Config{ChannelGroup: &cb.ConfigGroup{}}, "foonamespace", &mockpolicies.PolicyManager{})
   417  		assert.Nil(t, v)
   418  		assert.Error(t, err)
   419  		assert.Regexp(t, "bad channel ID", err.Error())
   420  		assert.EqualError(t, err, "bad channel ID: channel ID illegal, cannot be empty")
   421  	})
   422  
   423  	t.Run("MaxLengthChannelID", func(t *testing.T) {
   424  		maxChannelID := strings.Repeat("a", 250)
   425  		v, err := NewValidatorImpl(maxChannelID, &cb.Config{ChannelGroup: &cb.ConfigGroup{}}, "foonamespace", &mockpolicies.PolicyManager{})
   426  		assert.Nil(t, v)
   427  		assert.Error(t, err)
   428  		assert.EqualError(t, err, "bad channel ID: channel ID illegal, cannot be longer than 249")
   429  	})
   430  }