github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+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 }