github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/configtx/validator_test.go (about)

     1  /*
     2  Copyright hechain. 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  	mockpolicies "github.com/hechain20/hechain/common/configtx/mock"
    15  	"github.com/hechain20/hechain/common/policies"
    16  	"github.com/hechain20/hechain/protoutil"
    17  	cb "github.com/hyperledger/fabric-protos-go/common"
    18  	"github.com/stretchr/testify/require"
    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  	require.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  	if err != nil {
   109  		t.Fatalf("Error constructing config manager: %s", err)
   110  	}
   111  
   112  	newConfig := makeConfigUpdateEnvelope("wrongChannel", makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 1, []byte("foo"))))
   113  
   114  	_, err = vi.ProposeConfigUpdate(newConfig)
   115  	if err == nil {
   116  		t.Error("Should have errored when proposing a new config set the wrong channel ID")
   117  	}
   118  }
   119  
   120  // TestOldConfigReplay tests that resubmitting a config for a sequence number which is not newer is ignored
   121  func TestOldConfigReplay(t *testing.T) {
   122  	vi, err := NewValidatorImpl(
   123  		defaultChannel,
   124  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   125  		"foonamespace",
   126  		defaultPolicyManager())
   127  	if err != nil {
   128  		t.Fatalf("Error constructing config manager: %s", err)
   129  	}
   130  
   131  	newConfig := makeConfigUpdateEnvelope(defaultChannel, makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 0, []byte("foo"))))
   132  
   133  	_, err = vi.ProposeConfigUpdate(newConfig)
   134  
   135  	require.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")
   136  }
   137  
   138  // TestValidConfigChange tests the happy path of updating a config value with no defaultModificationPolicy
   139  func TestValidConfigChange(t *testing.T) {
   140  	vi, err := NewValidatorImpl(
   141  		defaultChannel,
   142  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   143  		"foonamespace",
   144  		defaultPolicyManager())
   145  	if err != nil {
   146  		t.Fatalf("Error constructing config manager: %s", err)
   147  	}
   148  
   149  	newConfig := makeConfigUpdateEnvelope(defaultChannel, makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 1, []byte("foo"))))
   150  
   151  	configEnv, err := vi.ProposeConfigUpdate(newConfig)
   152  	if err != nil {
   153  		t.Errorf("Should not have errored proposing config: %s", err)
   154  	}
   155  
   156  	err = vi.Validate(configEnv)
   157  	if err != nil {
   158  		t.Errorf("Should not have errored validating config: %s", err)
   159  	}
   160  }
   161  
   162  // TestConfigChangeRegressedSequence tests to make sure that a new config cannot roll back one of the
   163  // config values while advancing another
   164  func TestConfigChangeRegressedSequence(t *testing.T) {
   165  	vi, err := NewValidatorImpl(
   166  		defaultChannel,
   167  		makeConfig(makeConfigPair("foo", "foo", 1, []byte("foo"))),
   168  		"foonamespace",
   169  		defaultPolicyManager())
   170  	if err != nil {
   171  		t.Fatalf("Error constructing config manager: %s", err)
   172  	}
   173  
   174  	newConfig := makeConfigUpdateEnvelope(
   175  		defaultChannel,
   176  		makeConfigSet(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   177  		makeConfigSet(makeConfigPair("bar", "bar", 2, []byte("bar"))),
   178  	)
   179  
   180  	_, err = vi.ProposeConfigUpdate(newConfig)
   181  	require.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")
   182  }
   183  
   184  // TestConfigChangeOldSequence tests to make sure that a new config cannot roll back one of the
   185  // config values while advancing another
   186  func TestConfigChangeOldSequence(t *testing.T) {
   187  	vi, err := NewValidatorImpl(
   188  		defaultChannel,
   189  		makeConfig(makeConfigPair("foo", "foo", 1, []byte("foo"))),
   190  		"foonamespace",
   191  		defaultPolicyManager())
   192  	if err != nil {
   193  		t.Fatalf("Error constructing config manager: %s", err)
   194  	}
   195  
   196  	newConfig := makeConfigUpdateEnvelope(
   197  		defaultChannel,
   198  		makeConfigSet(),
   199  		makeConfigSet(
   200  			makeConfigPair("foo", "foo", 2, []byte("foo")),
   201  			makeConfigPair("bar", "bar", 1, []byte("bar")),
   202  		),
   203  	)
   204  
   205  	_, err = vi.ProposeConfigUpdate(newConfig)
   206  
   207  	require.EqualError(t, err, "error authorizing update: error validating DeltaSet: attempted to set key [Value]  /foonamespace/bar to version 1, but key does not exist")
   208  }
   209  
   210  // TestConfigPartialUpdate tests to make sure that a new config can set only part
   211  // of the config and still be accepted
   212  func TestConfigPartialUpdate(t *testing.T) {
   213  	vi, err := NewValidatorImpl(
   214  		defaultChannel,
   215  		makeConfig(
   216  			makeConfigPair("foo", "foo", 0, []byte("foo")),
   217  			makeConfigPair("bar", "bar", 0, []byte("bar")),
   218  		),
   219  		"foonamespace",
   220  		defaultPolicyManager())
   221  	if err != nil {
   222  		t.Fatalf("Error constructing config manager: %s", err)
   223  	}
   224  
   225  	newConfig := makeConfigUpdateEnvelope(
   226  		defaultChannel,
   227  		makeConfigSet(),
   228  		makeConfigSet(makeConfigPair("bar", "bar", 1, []byte("bar"))),
   229  	)
   230  
   231  	_, err = vi.ProposeConfigUpdate(newConfig)
   232  	require.NoError(t, err, "Should have allowed partial update")
   233  }
   234  
   235  // TestEmptyConfigUpdate tests to make sure that an empty config is rejected as an update
   236  func TestEmptyConfigUpdate(t *testing.T) {
   237  	vi, err := NewValidatorImpl(
   238  		defaultChannel,
   239  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   240  		"foonamespace",
   241  		defaultPolicyManager())
   242  	if err != nil {
   243  		t.Fatalf("Error constructing config manager: %s", err)
   244  	}
   245  
   246  	newConfig := &cb.Envelope{}
   247  
   248  	_, err = vi.ProposeConfigUpdate(newConfig)
   249  	require.EqualError(t, err, "error converting envelope to config update: envelope must have a Header")
   250  }
   251  
   252  // TestSilentConfigModification tests to make sure that even if a validly signed new config for an existing sequence number
   253  // is substituted into an otherwise valid new config, that the new config is rejected for attempting a modification without
   254  // increasing the config item's LastModified
   255  func TestSilentConfigModification(t *testing.T) {
   256  	vi, err := NewValidatorImpl(
   257  		defaultChannel,
   258  		makeConfig(
   259  			makeConfigPair("foo", "foo", 0, []byte("foo")),
   260  			makeConfigPair("bar", "bar", 0, []byte("bar")),
   261  		),
   262  		"foonamespace",
   263  		defaultPolicyManager())
   264  	if err != nil {
   265  		t.Fatalf("Error constructing config manager: %s", err)
   266  	}
   267  
   268  	newConfig := makeConfigUpdateEnvelope(
   269  		defaultChannel,
   270  		makeConfigSet(),
   271  		makeConfigSet(
   272  			makeConfigPair("foo", "foo", 0, []byte("different")),
   273  			makeConfigPair("bar", "bar", 1, []byte("bar")),
   274  		),
   275  	)
   276  
   277  	_, err = vi.ProposeConfigUpdate(newConfig)
   278  	require.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")
   279  }
   280  
   281  // TestConfigChangeViolatesPolicy checks to make sure that if policy rejects the validation of a config item that
   282  // it is rejected in a config update
   283  func TestConfigChangeViolatesPolicy(t *testing.T) {
   284  	pm := defaultPolicyManager()
   285  	vi, err := NewValidatorImpl(
   286  		defaultChannel,
   287  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   288  		"foonamespace",
   289  		pm)
   290  	if err != nil {
   291  		t.Fatalf("Error constructing config manager: %s", err)
   292  	}
   293  	// Set the mock policy to error
   294  	fakePolicy := &mockpolicies.Policy{}
   295  	fakePolicy.EvaluateSignedDataReturns(fmt.Errorf("err"))
   296  	pm.GetPolicyReturns(fakePolicy, true)
   297  
   298  	newConfig := makeConfigUpdateEnvelope(defaultChannel, makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 1, []byte("foo"))))
   299  
   300  	_, err = vi.ProposeConfigUpdate(newConfig)
   301  	require.EqualError(t, err, "error authorizing update: error validating DeltaSet: policy for [Value]  /foonamespace/foo not satisfied: err")
   302  }
   303  
   304  // TestUnchangedConfigViolatesPolicy checks to make sure that existing config items are not revalidated against their modification policies
   305  // as the policy may have changed, certs revoked, etc. since the config was adopted.
   306  func TestUnchangedConfigViolatesPolicy(t *testing.T) {
   307  	pm := defaultPolicyManager()
   308  	vi, err := NewValidatorImpl(
   309  		defaultChannel,
   310  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   311  		"foonamespace",
   312  		pm)
   313  	if err != nil {
   314  		t.Fatalf("Error constructing config manager: %s", err)
   315  	}
   316  
   317  	newConfig := makeConfigUpdateEnvelope(
   318  		defaultChannel,
   319  		makeConfigSet(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   320  		makeConfigSet(makeConfigPair("bar", "bar", 0, []byte("foo"))),
   321  	)
   322  
   323  	configEnv, err := vi.ProposeConfigUpdate(newConfig)
   324  	if err != nil {
   325  		t.Errorf("Should not have errored proposing config, but got %s", err)
   326  	}
   327  
   328  	err = vi.Validate(configEnv)
   329  	if err != nil {
   330  		t.Errorf("Should not have errored validating config, but got %s", err)
   331  	}
   332  }
   333  
   334  // TestInvalidProposal checks that even if the policy allows the transaction and the sequence etc. is well formed,
   335  // that if the handler does not accept the config, it is rejected
   336  func TestInvalidProposal(t *testing.T) {
   337  	pm := defaultPolicyManager()
   338  	vi, err := NewValidatorImpl(
   339  		defaultChannel,
   340  		makeConfig(makeConfigPair("foo", "foo", 0, []byte("foo"))),
   341  		"foonamespace",
   342  		pm)
   343  	if err != nil {
   344  		t.Fatalf("Error constructing config manager: %s", err)
   345  	}
   346  
   347  	fakePolicy := &mockpolicies.Policy{}
   348  	fakePolicy.EvaluateSignedDataReturns(fmt.Errorf("err"))
   349  	pm.GetPolicyReturns(fakePolicy, true)
   350  
   351  	newConfig := makeConfigUpdateEnvelope(defaultChannel, makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 1, []byte("foo"))))
   352  
   353  	_, err = vi.ProposeConfigUpdate(newConfig)
   354  	require.EqualError(t, err, "error authorizing update: error validating DeltaSet: policy for [Value]  /foonamespace/foo not satisfied: err")
   355  }
   356  
   357  func TestValidateErrors(t *testing.T) {
   358  	t.Run("TestNilConfigEnv", func(t *testing.T) {
   359  		err := (&ValidatorImpl{}).Validate(nil)
   360  		require.Error(t, err)
   361  		require.Regexp(t, "config envelope is nil", err.Error())
   362  	})
   363  
   364  	t.Run("TestNilConfig", func(t *testing.T) {
   365  		err := (&ValidatorImpl{}).Validate(&cb.ConfigEnvelope{})
   366  		require.Error(t, err)
   367  		require.Regexp(t, "config envelope has nil config", err.Error())
   368  	})
   369  
   370  	t.Run("TestSequenceSkip", func(t *testing.T) {
   371  		err := (&ValidatorImpl{}).Validate(&cb.ConfigEnvelope{
   372  			Config: &cb.Config{
   373  				Sequence: 2,
   374  			},
   375  		})
   376  		require.Error(t, err)
   377  		require.Regexp(t, "config currently at sequence 0", err.Error())
   378  	})
   379  }
   380  
   381  func TestConstructionErrors(t *testing.T) {
   382  	t.Run("NilConfig", func(t *testing.T) {
   383  		v, err := NewValidatorImpl("test", nil, "foonamespace", &mockpolicies.PolicyManager{})
   384  		require.Nil(t, v)
   385  		require.Error(t, err)
   386  		require.Regexp(t, "nil config parameter", err.Error())
   387  	})
   388  
   389  	t.Run("NilChannelGroup", func(t *testing.T) {
   390  		v, err := NewValidatorImpl("test", &cb.Config{}, "foonamespace", &mockpolicies.PolicyManager{})
   391  		require.Nil(t, v)
   392  		require.Error(t, err)
   393  		require.Regexp(t, "nil channel group", err.Error())
   394  	})
   395  
   396  	t.Run("BadChannelID", func(t *testing.T) {
   397  		v, err := NewValidatorImpl("*&$#@*&@$#*&", &cb.Config{ChannelGroup: &cb.ConfigGroup{}}, "foonamespace", &mockpolicies.PolicyManager{})
   398  		require.Nil(t, v)
   399  		require.Error(t, err)
   400  		require.Regexp(t, "bad channel ID", err.Error())
   401  		require.EqualError(t, err, "bad channel ID: '*&$#@*&@$#*&' contains illegal characters")
   402  	})
   403  
   404  	t.Run("EmptyChannelID", func(t *testing.T) {
   405  		v, err := NewValidatorImpl("", &cb.Config{ChannelGroup: &cb.ConfigGroup{}}, "foonamespace", &mockpolicies.PolicyManager{})
   406  		require.Nil(t, v)
   407  		require.Error(t, err)
   408  		require.Regexp(t, "bad channel ID", err.Error())
   409  		require.EqualError(t, err, "bad channel ID: channel ID illegal, cannot be empty")
   410  	})
   411  
   412  	t.Run("MaxLengthChannelID", func(t *testing.T) {
   413  		maxChannelID := strings.Repeat("a", 250)
   414  		v, err := NewValidatorImpl(maxChannelID, &cb.Config{ChannelGroup: &cb.ConfigGroup{}}, "foonamespace", &mockpolicies.PolicyManager{})
   415  		require.Nil(t, v)
   416  		require.Error(t, err)
   417  		require.EqualError(t, err, "bad channel ID: channel ID illegal, cannot be longer than 249")
   418  	})
   419  }