Skip to content

Commit 10d340c

Browse files
author
Jason Yellick
committed
[FAB-5944] Restore disabled config update checks
In order to refactor the channel config to be immutable, checks which depended upon the previous state had to be removed (in particular, checks for the consensus type changing and for the org's MSPID changing were temporarily removed). This CR adds those checks back in a step which allows the previous config to validate the new one via 'ValidateNew'. Change-Id: Ic6c51f4b09f5aaaa8d176d850728287a1381b5e4 Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
1 parent 0cd1626 commit 10d340c

File tree

11 files changed

+308
-17
lines changed

11 files changed

+308
-17
lines changed

common/channelconfig/api.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ type Consortiums interface {
6464
type Consortium interface {
6565
// ChannelCreationPolicy returns the policy to check when instantiating a channel for this consortium
6666
ChannelCreationPolicy() *cb.Policy
67+
68+
// Organizations returns the organizations for this consortium
69+
Organizations() map[string]Org
6770
}
6871

6972
// Orderer stores the common shared orderer config
@@ -116,4 +119,7 @@ type Resources interface {
116119

117120
// MSPManager returns the msp.MSPManager for the chain
118121
MSPManager() msp.MSPManager
122+
123+
// ValidateNew should return an error if a new set of configuration resources is incompatible with the current one
124+
ValidateNew(resources Resources) error
119125
}

common/channelconfig/bundle.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,77 @@ func (b *Bundle) ConfigtxManager() configtxapi.Manager {
8080
return b.configtxManager
8181
}
8282

83+
// ValidateNew checks if a new bundle's contained configuration is valid to be derived from the current bundle.
84+
// This allows checks of the nature "Make sure that the consensus type did not change." which is otherwise
85+
func (b *Bundle) ValidateNew(nb Resources) error {
86+
if oc, ok := b.OrdererConfig(); ok {
87+
noc, ok := nb.OrdererConfig()
88+
if !ok {
89+
return fmt.Errorf("Current config has orderer section, but new config does not")
90+
}
91+
92+
if oc.ConsensusType() != noc.ConsensusType() {
93+
return fmt.Errorf("Attempted to change consensus type from %s to %s", oc.ConsensusType(), noc.ConsensusType())
94+
}
95+
96+
for orgName, org := range oc.Organizations() {
97+
norg, ok := noc.Organizations()[orgName]
98+
if !ok {
99+
continue
100+
}
101+
mspID := org.MSPID()
102+
if mspID != norg.MSPID() {
103+
return fmt.Errorf("Orderer org %s attempted to change MSP ID from %s to %s", orgName, mspID, norg.MSPID())
104+
}
105+
}
106+
}
107+
108+
if ac, ok := b.ApplicationConfig(); ok {
109+
nac, ok := nb.ApplicationConfig()
110+
if !ok {
111+
return fmt.Errorf("Current config has consortiums section, but new config does not")
112+
}
113+
114+
for orgName, org := range ac.Organizations() {
115+
norg, ok := nac.Organizations()[orgName]
116+
if !ok {
117+
continue
118+
}
119+
mspID := org.MSPID()
120+
if mspID != norg.MSPID() {
121+
return fmt.Errorf("Application org %s attempted to change MSP ID from %s to %s", orgName, mspID, norg.MSPID())
122+
}
123+
}
124+
}
125+
126+
if cc, ok := b.ConsortiumsConfig(); ok {
127+
ncc, ok := nb.ConsortiumsConfig()
128+
if !ok {
129+
return fmt.Errorf("Current config has consortiums section, but new config does not")
130+
}
131+
132+
for consortiumName, consortium := range cc.Consortiums() {
133+
nconsortium, ok := ncc.Consortiums()[consortiumName]
134+
if !ok {
135+
continue
136+
}
137+
138+
for orgName, org := range consortium.Organizations() {
139+
norg, ok := nconsortium.Organizations()[orgName]
140+
if !ok {
141+
continue
142+
}
143+
mspID := org.MSPID()
144+
if mspID != norg.MSPID() {
145+
return fmt.Errorf("Consortium %s org %s attempted to change MSP ID from %s to %s", consortiumName, orgName, mspID, norg.MSPID())
146+
}
147+
}
148+
}
149+
}
150+
151+
return nil
152+
}
153+
83154
type simpleProposer struct {
84155
policyManager policies.Manager
85156
}

common/channelconfig/bundle_test.go

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package channelconfig
8+
9+
import (
10+
"testing"
11+
12+
ab "github.com/hyperledger/fabric/protos/orderer"
13+
14+
"github.com/stretchr/testify/assert"
15+
)
16+
17+
func TestValidateNew(t *testing.T) {
18+
t.Run("DisappearingOrdererConfig", func(t *testing.T) {
19+
cb := &Bundle{
20+
channelConfig: &ChannelConfig{
21+
ordererConfig: &OrdererConfig{},
22+
},
23+
}
24+
25+
nb := &Bundle{
26+
channelConfig: &ChannelConfig{},
27+
}
28+
29+
err := cb.ValidateNew(nb)
30+
assert.Error(t, err)
31+
assert.Regexp(t, "Current config has orderer section, but new config does not", err.Error())
32+
})
33+
34+
t.Run("DisappearingApplicationConfig", func(t *testing.T) {
35+
cb := &Bundle{
36+
channelConfig: &ChannelConfig{
37+
appConfig: &ApplicationConfig{},
38+
},
39+
}
40+
41+
nb := &Bundle{
42+
channelConfig: &ChannelConfig{},
43+
}
44+
45+
err := cb.ValidateNew(nb)
46+
assert.Error(t, err)
47+
assert.Regexp(t, "Current config has consortiums section, but new config does not", err.Error())
48+
})
49+
50+
t.Run("DisappearingConsortiumsConfig", func(t *testing.T) {
51+
cb := &Bundle{
52+
channelConfig: &ChannelConfig{
53+
consortiumsConfig: &ConsortiumsConfig{},
54+
},
55+
}
56+
57+
nb := &Bundle{
58+
channelConfig: &ChannelConfig{},
59+
}
60+
61+
err := cb.ValidateNew(nb)
62+
assert.Error(t, err)
63+
assert.Regexp(t, "Current config has consortiums section, but new config does not", err.Error())
64+
})
65+
66+
t.Run("ConsensusTypeChange", func(t *testing.T) {
67+
cb := &Bundle{
68+
channelConfig: &ChannelConfig{
69+
ordererConfig: &OrdererConfig{
70+
protos: &OrdererProtos{
71+
ConsensusType: &ab.ConsensusType{
72+
Type: "type1",
73+
},
74+
},
75+
},
76+
},
77+
}
78+
79+
nb := &Bundle{
80+
channelConfig: &ChannelConfig{
81+
ordererConfig: &OrdererConfig{
82+
protos: &OrdererProtos{
83+
ConsensusType: &ab.ConsensusType{
84+
Type: "type2",
85+
},
86+
},
87+
},
88+
},
89+
}
90+
91+
err := cb.ValidateNew(nb)
92+
assert.Error(t, err)
93+
assert.Regexp(t, "Attempted to change consensus type from", err.Error())
94+
})
95+
96+
t.Run("OrdererOrgMSPIDChange", func(t *testing.T) {
97+
cb := &Bundle{
98+
channelConfig: &ChannelConfig{
99+
ordererConfig: &OrdererConfig{
100+
protos: &OrdererProtos{
101+
ConsensusType: &ab.ConsensusType{
102+
Type: "type1",
103+
},
104+
},
105+
orgs: map[string]Org{
106+
"org1": &OrganizationConfig{mspID: "org1msp"},
107+
"org2": &OrganizationConfig{mspID: "org2msp"},
108+
"org3": &OrganizationConfig{mspID: "org3msp"},
109+
},
110+
},
111+
},
112+
}
113+
114+
nb := &Bundle{
115+
channelConfig: &ChannelConfig{
116+
ordererConfig: &OrdererConfig{
117+
protos: &OrdererProtos{
118+
ConsensusType: &ab.ConsensusType{
119+
Type: "type1",
120+
},
121+
},
122+
orgs: map[string]Org{
123+
"org1": &OrganizationConfig{mspID: "org1msp"},
124+
"org3": &OrganizationConfig{mspID: "org2msp"},
125+
},
126+
},
127+
},
128+
}
129+
130+
err := cb.ValidateNew(nb)
131+
assert.Error(t, err)
132+
assert.Regexp(t, "Orderer org org3 attempted to change MSP ID from", err.Error())
133+
})
134+
135+
t.Run("ApplicationOrgMSPIDChange", func(t *testing.T) {
136+
cb := &Bundle{
137+
channelConfig: &ChannelConfig{
138+
appConfig: &ApplicationConfig{
139+
applicationOrgs: map[string]ApplicationOrg{
140+
"org1": &ApplicationOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org1msp"}},
141+
"org2": &ApplicationOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org2msp"}},
142+
"org3": &ApplicationOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org3msp"}},
143+
},
144+
},
145+
},
146+
}
147+
148+
nb := &Bundle{
149+
channelConfig: &ChannelConfig{
150+
appConfig: &ApplicationConfig{
151+
applicationOrgs: map[string]ApplicationOrg{
152+
"org1": &ApplicationOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org1msp"}},
153+
"org3": &ApplicationOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org2msp"}},
154+
},
155+
},
156+
},
157+
}
158+
159+
err := cb.ValidateNew(nb)
160+
assert.Error(t, err)
161+
assert.Regexp(t, "Application org org3 attempted to change MSP ID from", err.Error())
162+
})
163+
164+
t.Run("ConsortiumOrgMSPIDChange", func(t *testing.T) {
165+
cb := &Bundle{
166+
channelConfig: &ChannelConfig{
167+
consortiumsConfig: &ConsortiumsConfig{
168+
consortiums: map[string]Consortium{
169+
"consortium1": &ConsortiumConfig{
170+
orgs: map[string]Org{
171+
"org1": &OrganizationConfig{mspID: "org1msp"},
172+
"org2": &OrganizationConfig{mspID: "org2msp"},
173+
"org3": &OrganizationConfig{mspID: "org3msp"},
174+
},
175+
},
176+
"consortium2": &ConsortiumConfig{},
177+
"consortium3": &ConsortiumConfig{},
178+
},
179+
},
180+
},
181+
}
182+
183+
nb := &Bundle{
184+
channelConfig: &ChannelConfig{
185+
consortiumsConfig: &ConsortiumsConfig{
186+
consortiums: map[string]Consortium{
187+
"consortium1": &ConsortiumConfig{
188+
orgs: map[string]Org{
189+
"org1": &OrganizationConfig{mspID: "org1msp"},
190+
"org3": &OrganizationConfig{mspID: "org2msp"},
191+
},
192+
},
193+
},
194+
},
195+
},
196+
}
197+
198+
err := cb.ValidateNew(nb)
199+
assert.Error(t, err)
200+
assert.Regexp(t, "Consortium consortium1 org org3 attempted to change MSP ID from", err.Error())
201+
})
202+
}

common/channelconfig/bundlesource.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,8 @@ func (bs *BundleSource) ApplicationConfig() (Application, bool) {
9393
func (bs *BundleSource) ConfigtxManager() configtxapi.Manager {
9494
return bs.StableBundle().ConfigtxManager()
9595
}
96+
97+
// ValidateNew passes through to the current bundle
98+
func (bs *BundleSource) ValidateNew(resources Resources) error {
99+
return bs.StableBundle().ValidateNew(resources)
100+
}

common/channelconfig/consortium.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ type ConsortiumProtos struct {
2020
// ConsortiumConfig holds the consoritums configuration information
2121
type ConsortiumConfig struct {
2222
protos *ConsortiumProtos
23-
orgs map[string]*OrganizationConfig
23+
orgs map[string]Org
2424
}
2525

2626
// NewConsortiumConfig creates a new instance of the consoritums config
2727
func NewConsortiumConfig(consortiumGroup *cb.ConfigGroup, mspConfig *MSPConfigHandler) (*ConsortiumConfig, error) {
2828
cc := &ConsortiumConfig{
2929
protos: &ConsortiumProtos{},
30-
orgs: make(map[string]*OrganizationConfig),
30+
orgs: make(map[string]Org),
3131
}
3232

3333
if err := DeserializeProtoValuesFromGroup(consortiumGroup, cc.protos); err != nil {
@@ -45,7 +45,7 @@ func NewConsortiumConfig(consortiumGroup *cb.ConfigGroup, mspConfig *MSPConfigHa
4545
}
4646

4747
// Organizations returns the set of organizations in the consortium
48-
func (cc *ConsortiumConfig) Organizations() map[string]*OrganizationConfig {
48+
func (cc *ConsortiumConfig) Organizations() map[string]Org {
4949
return cc.orgs
5050
}
5151

common/channelconfig/orderer.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ func (oc *OrdererConfig) Organizations() map[string]Org {
116116

117117
func (oc *OrdererConfig) Validate() error {
118118
for _, validator := range []func() error{
119-
oc.validateConsensusType,
120119
oc.validateBatchSize,
121120
oc.validateBatchTimeout,
122121
oc.validateKafkaBrokers,
@@ -129,11 +128,6 @@ func (oc *OrdererConfig) Validate() error {
129128
return nil
130129
}
131130

132-
func (oc *OrdererConfig) validateConsensusType() error {
133-
// XXX TODO add check to prevent changing consensus type back
134-
return nil
135-
}
136-
137131
func (oc *OrdererConfig) validateBatchSize() error {
138132
if oc.protos.BatchSize.MaxMessageCount == 0 {
139133
return fmt.Errorf("Attempted to set the batch size max message count to an invalid value: 0")

common/channelconfig/orderer_test.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@ func init() {
1919
logging.SetLevel(logging.DEBUG, "")
2020
}
2121

22-
func TestConsensusType(t *testing.T) {
23-
oc := &OrdererConfig{protos: &OrdererProtos{ConsensusType: &ab.ConsensusType{Type: "foo"}}}
24-
assert.NoError(t, oc.validateConsensusType(), "Should have validly set new consensus type")
25-
}
26-
2722
func TestBatchSize(t *testing.T) {
2823
validMaxMessageCount := uint32(10)
2924
validAbsoluteMaxBytes := uint32(1000)

common/channelconfig/organization.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,5 @@ func (oc *OrganizationConfig) validateMSP() error {
8484
return fmt.Errorf("MSP for org %s has empty MSP ID", oc.name)
8585
}
8686

87-
// XXX TODO Add back a check for MSP ID modification
88-
8987
return nil
9088
}

common/mocks/config/resources.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type Resources struct {
3434

3535
// MSPManagerVal is returned as the result of MSPManager()
3636
MSPManagerVal msp.MSPManager
37+
38+
// ValidateNewErr is returned as the result of ValidateNew
39+
ValidateNewErr error
3740
}
3841

3942
// ConfigtxMangaer returns ConfigtxManagerVal
@@ -69,3 +72,8 @@ func (r *Resources) ConsortiumsConfig() (channelconfig.Consortiums, bool) {
6972
func (r *Resources) MSPManager() msp.MSPManager {
7073
return r.MSPManagerVal
7174
}
75+
76+
// ValidateNew returns ValidateNewErr
77+
func (r *Resources) ValidateNew(res channelconfig.Resources) error {
78+
return r.ValidateNewErr
79+
}

0 commit comments

Comments
 (0)