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 }