Skip to content

Commit 726da6e

Browse files
committed
[FAB-5668] NodeOUs Configuration
This change-set does the following: - It enhance FabricMSPConfig to support Node identification via OUs. - Node OUs can be specified in the msp configuration file. - If the Node OUs check is enabled then only identities with a recognized Node OU (as setup in the configuration file) will be considered valid. Tests have been added to validate the change-set. Change-Id: If2015dd5ae25c8400f7f2a59b19158002b52e4ba Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
1 parent e4cb863 commit 726da6e

File tree

56 files changed

+1247
-171
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1247
-171
lines changed

msp/configbuilder.go

+81-2
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,39 @@ import (
2121
"gopkg.in/yaml.v2"
2222
)
2323

24+
// OrganizationalUnitIdentifiersConfiguration is used to represent an OU
25+
// and an associated trusted certificate
2426
type OrganizationalUnitIdentifiersConfiguration struct {
25-
Certificate string `yaml:"Certificate,omitempty"`
27+
// Certificate is the path to a root or intermediate certificate
28+
Certificate string `yaml:"Certificate,omitempty"`
29+
// OrganizationalUnitIdentifier is the name of the OU
2630
OrganizationalUnitIdentifier string `yaml:"OrganizationalUnitIdentifier,omitempty"`
2731
}
2832

33+
// NodeOUs contains information on how to tell apart clients, peers and orderers
34+
// based on OUs. If the check is enforced, by setting Enabled to true,
35+
// the MSP will consider an identity valid if it is an identity of a client, a peer or
36+
// an orderer. An identity should have only one of these special OUs.
37+
type NodeOUs struct {
38+
// Enable activates the OU enforcement
39+
Enable bool `yaml:"Enable,omitempty"`
40+
// ClientOUIdentifier specifies how to recognize clients by OU
41+
ClientOUIdentifier *OrganizationalUnitIdentifiersConfiguration `yaml:"ClientOUIdentifier,omitempty"`
42+
// PeerOUIdentifier specifies how to recognize peers by OU
43+
PeerOUIdentifier *OrganizationalUnitIdentifiersConfiguration `yaml:"PeerOUIdentifier,omitempty"`
44+
// OrdererOUIdentifier specifies how to recognize orderers by OU
45+
OrdererOUIdentifier *OrganizationalUnitIdentifiersConfiguration `yaml:"OrdererOUIdentifier,omitempty"`
46+
}
47+
48+
// Configuration represents the accessory configuration an MSP can be equipped with.
49+
// By default, this configuration is stored in a yaml file
2950
type Configuration struct {
51+
// OrganizationalUnitIdentifiers is a list of OUs. If this is set, the MSP
52+
// will consider an identity valid only it contains at least one of these OUs
3053
OrganizationalUnitIdentifiers []*OrganizationalUnitIdentifiersConfiguration `yaml:"OrganizationalUnitIdentifiers,omitempty"`
54+
// NodeOUs enables the MSP to tell apart clients, peers and orderers based
55+
// on the identity's OU.
56+
NodeOUs *NodeOUs `yaml:"NodeOUs,omitempty"`
3157
}
3258

3359
func readFile(file string) ([]byte, error) {
@@ -204,6 +230,7 @@ func getMspConfig(dir string, ID string, sigid *msp.SigningIdentityInfo) (*msp.M
204230
// if the configuration file is there then load it
205231
// otherwise skip it
206232
var ouis []*msp.FabricOUIdentifier
233+
var nodeOUs *msp.FabricNodeOUs
207234
_, err = os.Stat(configFile)
208235
if err == nil {
209236
// load the file, if there is a failure in loading it then
@@ -223,17 +250,68 @@ func getMspConfig(dir string, ID string, sigid *msp.SigningIdentityInfo) (*msp.M
223250
if len(configuration.OrganizationalUnitIdentifiers) > 0 {
224251
for _, ouID := range configuration.OrganizationalUnitIdentifiers {
225252
f := filepath.Join(dir, ouID.Certificate)
226-
raw, err = ioutil.ReadFile(f)
253+
raw, err = readFile(f)
227254
if err != nil {
228255
return nil, errors.Wrapf(err, "failed loading OrganizationalUnit certificate at [%s]", f)
229256
}
257+
230258
oui := &msp.FabricOUIdentifier{
231259
Certificate: raw,
232260
OrganizationalUnitIdentifier: ouID.OrganizationalUnitIdentifier,
233261
}
234262
ouis = append(ouis, oui)
235263
}
236264
}
265+
266+
// Prepare NodeOUs
267+
if configuration.NodeOUs != nil && configuration.NodeOUs.Enable {
268+
mspLogger.Info("Loading NodeOUs")
269+
if configuration.NodeOUs.ClientOUIdentifier == nil || len(configuration.NodeOUs.ClientOUIdentifier.OrganizationalUnitIdentifier) == 0 {
270+
return nil, errors.New("Failed loading NodeOUs. ClientOU must be different from nil.")
271+
}
272+
if configuration.NodeOUs.PeerOUIdentifier == nil || len(configuration.NodeOUs.PeerOUIdentifier.OrganizationalUnitIdentifier) == 0 {
273+
return nil, errors.New("Failed loading NodeOUs. PeerOU must be different from nil.")
274+
}
275+
if configuration.NodeOUs.OrdererOUIdentifier == nil || len(configuration.NodeOUs.OrdererOUIdentifier.OrganizationalUnitIdentifier) == 0 {
276+
return nil, errors.New("Failed loading NodeOUs. OrdererOU must be different from nil.")
277+
}
278+
279+
nodeOUs = &msp.FabricNodeOUs{
280+
Enable: configuration.NodeOUs.Enable,
281+
ClientOUIdentifier: &msp.FabricOUIdentifier{OrganizationalUnitIdentifier: configuration.NodeOUs.ClientOUIdentifier.OrganizationalUnitIdentifier},
282+
PeerOUIdentifier: &msp.FabricOUIdentifier{OrganizationalUnitIdentifier: configuration.NodeOUs.PeerOUIdentifier.OrganizationalUnitIdentifier},
283+
OrdererOUIdentifier: &msp.FabricOUIdentifier{OrganizationalUnitIdentifier: configuration.NodeOUs.OrdererOUIdentifier.OrganizationalUnitIdentifier},
284+
}
285+
286+
// Read certificates, if defined
287+
288+
// ClientOU
289+
f := filepath.Join(dir, configuration.NodeOUs.ClientOUIdentifier.Certificate)
290+
raw, err = readFile(f)
291+
if err != nil {
292+
mspLogger.Infof("Failed loading ClientOU certificate at [%s]: [%s]", f, err)
293+
} else {
294+
nodeOUs.ClientOUIdentifier.Certificate = raw
295+
}
296+
297+
// PeerOU
298+
f = filepath.Join(dir, configuration.NodeOUs.PeerOUIdentifier.Certificate)
299+
raw, err = readFile(f)
300+
if err != nil {
301+
mspLogger.Debugf("Failed loading PeerOU certificate at [%s]: [%s]", f, err)
302+
} else {
303+
nodeOUs.PeerOUIdentifier.Certificate = raw
304+
}
305+
306+
// OrdererOU
307+
f = filepath.Join(dir, configuration.NodeOUs.OrdererOUIdentifier.Certificate)
308+
raw, err = readFile(f)
309+
if err != nil {
310+
mspLogger.Debugf("Failed loading OrdererOU certificate at [%s]: [%s]", f, err)
311+
} else {
312+
nodeOUs.OrdererOUIdentifier.Certificate = raw
313+
}
314+
}
237315
} else {
238316
mspLogger.Debugf("MSP configuration file not found at [%s]: [%s]", configFile, err)
239317
}
@@ -256,6 +334,7 @@ func getMspConfig(dir string, ID string, sigid *msp.SigningIdentityInfo) (*msp.M
256334
CryptoConfig: cryptoConfig,
257335
TlsRootCerts: tlsCACerts,
258336
TlsIntermediateCerts: tlsIntermediateCerts,
337+
FabricNodeOUs: nodeOUs,
259338
}
260339

261340
fmpsjs, _ := proto.Marshal(fmspconf)

msp/factory.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ func New(opts NewOpts) (MSP, error) {
4848
case *BCCSPNewOpts:
4949
switch opts.GetVersion() {
5050
case MSPv1_0:
51-
return newBccspMsp()
51+
return newBccspMsp(MSPv1_0)
52+
case MSPv1_1:
53+
return newBccspMsp(MSPv1_1)
5254
default:
5355
return nil, errors.Errorf("Invalid *BCCSPNewOpts. Version not recognized [%v]", opts.GetVersion())
5456
}

msp/factory_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ package msp
99
import (
1010
"testing"
1111

12+
"reflect"
13+
"runtime"
14+
1215
"github.com/stretchr/testify/assert"
1316
)
1417

@@ -33,6 +36,16 @@ func TestNew(t *testing.T) {
3336
i, err := New(&BCCSPNewOpts{NewBaseOpts{Version: MSPv1_0}})
3437
assert.NoError(t, err)
3538
assert.NotNil(t, i)
39+
assert.Equal(t, MSPVersion(MSPv1_0), i.(*bccspmsp).version)
40+
assert.Equal(t, runtime.FuncForPC(reflect.ValueOf(i.(*bccspmsp).internalSetupFunc).Pointer()).Name(), "github.com/hyperledger/fabric/msp.(*bccspmsp).(github.com/hyperledger/fabric/msp.setupV1)-fm")
41+
assert.Equal(t, runtime.FuncForPC(reflect.ValueOf(i.(*bccspmsp).internalValidateIdentityOusFunc).Pointer()).Name(), "github.com/hyperledger/fabric/msp.(*bccspmsp).(github.com/hyperledger/fabric/msp.validateIdentityOUsV1)-fm")
42+
43+
i, err = New(&BCCSPNewOpts{NewBaseOpts{Version: MSPv1_1}})
44+
assert.NoError(t, err)
45+
assert.NotNil(t, i)
46+
assert.Equal(t, MSPVersion(MSPv1_1), i.(*bccspmsp).version)
47+
assert.Equal(t, runtime.FuncForPC(reflect.ValueOf(i.(*bccspmsp).internalSetupFunc).Pointer()).Name(), "github.com/hyperledger/fabric/msp.(*bccspmsp).(github.com/hyperledger/fabric/msp.setupV11)-fm")
48+
assert.Equal(t, runtime.FuncForPC(reflect.ValueOf(i.(*bccspmsp).internalValidateIdentityOusFunc).Pointer()).Name(), "github.com/hyperledger/fabric/msp.(*bccspmsp).(github.com/hyperledger/fabric/msp.validateIdentityOUsV11)-fm")
3649

3750
i, err = New(&IdemixNewOpts{NewBaseOpts{Version: MSPv1_0}})
3851
assert.NoError(t, err)

msp/msp_test.go

+75-9
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func TestMSPSetupNoCryptoConf(t *testing.T) {
8484
b, err := proto.Marshal(mspconf)
8585
assert.NoError(t, err)
8686
conf.Config = b
87-
newmsp, err := newBccspMsp()
87+
newmsp, err := newBccspMsp(MSPv1_0)
8888
assert.NoError(t, err)
8989
err = newmsp.Setup(conf)
9090
assert.NoError(t, err)
@@ -97,7 +97,7 @@ func TestMSPSetupNoCryptoConf(t *testing.T) {
9797
b, err = proto.Marshal(mspconf)
9898
assert.NoError(t, err)
9999
conf.Config = b
100-
newmsp, err = newBccspMsp()
100+
newmsp, err = newBccspMsp(MSPv1_0)
101101
assert.NoError(t, err)
102102
err = newmsp.Setup(conf)
103103
assert.NoError(t, err)
@@ -109,7 +109,7 @@ func TestMSPSetupNoCryptoConf(t *testing.T) {
109109
b, err = proto.Marshal(mspconf)
110110
assert.NoError(t, err)
111111
conf.Config = b
112-
newmsp, err = newBccspMsp()
112+
newmsp, err = newBccspMsp(MSPv1_0)
113113
assert.NoError(t, err)
114114
err = newmsp.Setup(conf)
115115
assert.NoError(t, err)
@@ -157,7 +157,7 @@ func TestNotFoundInBCCSP(t *testing.T) {
157157

158158
assert.NoError(t, err)
159159

160-
thisMSP, err := newBccspMsp()
160+
thisMSP, err := newBccspMsp(MSPv1_0)
161161
assert.NoError(t, err)
162162
ks, err := sw.NewFileBasedKeyStore(nil, filepath.Join(dir, "keystore"), true)
163163
assert.NoError(t, err)
@@ -208,7 +208,7 @@ func TestGetSigningIdentityFromVerifyingMSP(t *testing.T) {
208208
os.Exit(-1)
209209
}
210210

211-
newmsp, err := newBccspMsp()
211+
newmsp, err := newBccspMsp(MSPv1_0)
212212
assert.NoError(t, err)
213213
err = newmsp.Setup(conf)
214214
assert.NoError(t, err)
@@ -327,7 +327,7 @@ func TestBadAdminIdentity(t *testing.T) {
327327
conf, err := GetLocalMspConfig("testdata/badadmin", nil, "DEFAULT")
328328
assert.NoError(t, err)
329329

330-
thisMSP, err := newBccspMsp()
330+
thisMSP, err := newBccspMsp(MSPv1_0)
331331
assert.NoError(t, err)
332332
ks, err := sw.NewFileBasedKeyStore(nil, filepath.Join("testdata/badadmin", "keystore"), true)
333333
assert.NoError(t, err)
@@ -913,13 +913,13 @@ func TestMain(m *testing.M) {
913913
os.Exit(-1)
914914
}
915915

916-
localMsp, err = newBccspMsp()
916+
localMsp, err = newBccspMsp(MSPv1_0)
917917
if err != nil {
918918
fmt.Printf("Constructor for msp should have succeeded, got err %s instead", err)
919919
os.Exit(-1)
920920
}
921921

922-
localMspBad, err = newBccspMsp()
922+
localMspBad, err = newBccspMsp(MSPv1_0)
923923
if err != nil {
924924
fmt.Printf("Constructor for msp should have succeeded, got err %s instead", err)
925925
os.Exit(-1)
@@ -978,11 +978,77 @@ func getIdentity(t *testing.T, path string) Identity {
978978
return id
979979
}
980980

981+
func getLocalMSPWithError(t *testing.T, dir string) (MSP, error) {
982+
conf, err := GetLocalMspConfig(dir, nil, "DEFAULT")
983+
assert.NoError(t, err)
984+
985+
thisMSP, err := newBccspMsp(MSPv1_0)
986+
assert.NoError(t, err)
987+
ks, err := sw.NewFileBasedKeyStore(nil, filepath.Join(dir, "keystore"), true)
988+
assert.NoError(t, err)
989+
csp, err := sw.New(256, "SHA2", ks)
990+
assert.NoError(t, err)
991+
thisMSP.(*bccspmsp).bccsp = csp
992+
993+
return thisMSP, thisMSP.Setup(conf)
994+
}
995+
996+
func getLocalMSPWithVersionAndError(t *testing.T, dir string, version MSPVersion) (MSP, error) {
997+
conf, err := GetLocalMspConfig(dir, nil, "DEFAULT")
998+
assert.NoError(t, err)
999+
1000+
thisMSP, err := newBccspMsp(version)
1001+
assert.NoError(t, err)
1002+
ks, err := sw.NewFileBasedKeyStore(nil, filepath.Join(dir, "keystore"), true)
1003+
assert.NoError(t, err)
1004+
csp, err := sw.New(256, "SHA2", ks)
1005+
assert.NoError(t, err)
1006+
thisMSP.(*bccspmsp).bccsp = csp
1007+
1008+
return thisMSP, thisMSP.Setup(conf)
1009+
}
1010+
9811011
func getLocalMSP(t *testing.T, dir string) MSP {
9821012
conf, err := GetLocalMspConfig(dir, nil, "DEFAULT")
9831013
assert.NoError(t, err)
9841014

985-
thisMSP, err := newBccspMsp()
1015+
thisMSP, err := newBccspMsp(MSPv1_0)
1016+
assert.NoError(t, err)
1017+
ks, err := sw.NewFileBasedKeyStore(nil, filepath.Join(dir, "keystore"), true)
1018+
assert.NoError(t, err)
1019+
csp, err := sw.New(256, "SHA2", ks)
1020+
assert.NoError(t, err)
1021+
thisMSP.(*bccspmsp).bccsp = csp
1022+
1023+
err = thisMSP.Setup(conf)
1024+
assert.NoError(t, err)
1025+
1026+
return thisMSP
1027+
}
1028+
1029+
func getLocalMSPWithVersion(t *testing.T, dir string, version MSPVersion) MSP {
1030+
conf, err := GetLocalMspConfig(dir, nil, "DEFAULT")
1031+
assert.NoError(t, err)
1032+
1033+
thisMSP, err := newBccspMsp(version)
1034+
assert.NoError(t, err)
1035+
ks, err := sw.NewFileBasedKeyStore(nil, filepath.Join(dir, "keystore"), true)
1036+
assert.NoError(t, err)
1037+
csp, err := sw.New(256, "SHA2", ks)
1038+
assert.NoError(t, err)
1039+
thisMSP.(*bccspmsp).bccsp = csp
1040+
1041+
err = thisMSP.Setup(conf)
1042+
assert.NoError(t, err)
1043+
1044+
return thisMSP
1045+
}
1046+
1047+
func getLocalMSPWithName(t *testing.T, name, dir string) MSP {
1048+
conf, err := GetLocalMspConfig(dir, nil, name)
1049+
assert.NoError(t, err)
1050+
1051+
thisMSP, err := newBccspMsp(MSPv1_0)
9861052
assert.NoError(t, err)
9871053
ks, err := sw.NewFileBasedKeyStore(nil, filepath.Join(dir, "keystore"), true)
9881054
assert.NoError(t, err)

0 commit comments

Comments
 (0)