Skip to content

Commit

Permalink
[FAB-3351] MSP OUIdentifiers config
Browse files Browse the repository at this point in the history
This change-sets allows an MSP to be configured
with a set of OrganizationUnitIdentifiers against
which each identiy will be validated.

Change-Id: Ie8410c24ab7d579b69e270f18d955d9e66fa7cb9
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Apr 29, 2017
1 parent c5c4c51 commit a19279e
Show file tree
Hide file tree
Showing 23 changed files with 444 additions and 109 deletions.
2 changes: 1 addition & 1 deletion common/cauthdsl/cauthdsl_test.go
Expand Up @@ -54,7 +54,7 @@ func (id *mockIdentity) Validate() error {
return nil
}

func (id *mockIdentity) GetOrganizationalUnits() []mb.FabricOUIdentifier {
func (id *mockIdentity) GetOrganizationalUnits() []*msp.OUIdentifier {
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion common/mocks/msp/noopmsp.go
Expand Up @@ -97,7 +97,7 @@ func (id *noopidentity) Validate() error {
return nil
}

func (id *noopidentity) GetOrganizationalUnits() []msp.FabricOUIdentifier {
func (id *noopidentity) GetOrganizationalUnits() []*m.OUIdentifier {
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion core/policy/mocks.go
Expand Up @@ -112,7 +112,7 @@ func (id *MockIdentity) Validate() error {
return nil
}

func (id *MockIdentity) GetOrganizationalUnits() []mspproto.FabricOUIdentifier {
func (id *MockIdentity) GetOrganizationalUnits() []*msp.OUIdentifier {
return nil
}

Expand Down
57 changes: 54 additions & 3 deletions msp/configbuilder.go
Expand Up @@ -30,8 +30,18 @@ import (
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/protos/msp"
"gopkg.in/yaml.v2"
)

type OrganizationalUnitIdentifiersConfiguration struct {
Certificate string `yaml:"Certificate,omitempty"`
OrganizationalUnitIdentifier string `yaml:"OrganizationalUnitIdentifier,omitempty"`
}

type Configuration struct {
OrganizationalUnitIdentifiers []*OrganizationalUnitIdentifiersConfiguration `yaml:"OrganizationalUnitIdentifiers,omitempty"`
}

func readFile(file string) ([]byte, error) {
fileCont, err := ioutil.ReadFile(file)
if err != nil {
Expand Down Expand Up @@ -96,6 +106,7 @@ const (
keystore = "keystore"
intermediatecerts = "intermediatecerts"
crlsfolder = "crls"
configfilename = "config.yaml"
)

func SetupBCCSPKeystoreConfig(bccspConfig *factory.FactoryOpts, keystoreDir string) {
Expand Down Expand Up @@ -153,6 +164,7 @@ func getMspConfig(dir string, bccspConfig *factory.FactoryOpts, ID string, sigid
admincertDir := filepath.Join(dir, admincerts)
intermediatecertsDir := filepath.Join(dir, intermediatecerts)
crlsDir := filepath.Join(dir, crlsfolder)
configFile := filepath.Join(dir, configfilename)

cacerts, err := getPemMaterialFromDir(cacertDir)
if err != nil || len(cacerts) == 0 {
Expand Down Expand Up @@ -183,7 +195,45 @@ func getMspConfig(dir string, bccspConfig *factory.FactoryOpts, ID string, sigid
return nil, fmt.Errorf("Failed loading crls ca certs at [%s]: [%s]", intermediatecertsDir, err)
}

// Load FabricCryptoConfig
// Load configuration file
// if the configuration file is there then load it
// otherwise skip it
var ouis []*msp.FabricOUIdentifier
_, err = os.Stat(configFile)
if err == nil {
// load the file, if there is a failure in loading it then
// return an error
raw, err := ioutil.ReadFile(configFile)
if err != nil {
return nil, fmt.Errorf("Failed loading configuration file at [%s]: [%s]", configFile, err)
}

configuration := Configuration{}
err = yaml.Unmarshal(raw, &configuration)
if err != nil {
return nil, fmt.Errorf("Failed unmarshalling configuration file at [%s]: [%s]", configFile, err)
}

// Prepare OrganizationalUnitIdentifiers
if len(configuration.OrganizationalUnitIdentifiers) > 0 {
for _, ouID := range configuration.OrganizationalUnitIdentifiers {
f := filepath.Join(dir, ouID.Certificate)
raw, err = ioutil.ReadFile(f)
if err != nil {
return nil, fmt.Errorf("Failed loading OrganizationalUnit certificate at [%s]: [%s]", f, err)
}
oui := &msp.FabricOUIdentifier{
Certificate: raw,
OrganizationalUnitIdentifier: ouID.OrganizationalUnitIdentifier,
}
ouis = append(ouis, oui)
}
}
} else {
mspLogger.Infof("MSP configuration file not found at [%s]: [%s]", configFile, err)
}

// Set FabricCryptoConfig
cryptoConfig := &msp.FabricCryptoConfig{
SignatureHashFamily: bccsp.SHA2,
IdentityIdentifierHashFunction: bccsp.SHA256,
Expand All @@ -196,8 +246,9 @@ func getMspConfig(dir string, bccspConfig *factory.FactoryOpts, ID string, sigid
IntermediateCerts: intermediatecert,
SigningIdentity: sigid,
Name: ID,
RevocationList: crls,
CryptoConfig: cryptoConfig}
OrganizationalUnitIdentifiers: ouis,
RevocationList: crls,
CryptoConfig: cryptoConfig}

fmpsjs, _ := proto.Marshal(fmspconf)

Expand Down
6 changes: 3 additions & 3 deletions msp/identities.go
Expand Up @@ -71,7 +71,7 @@ func (id *identity) Validate() error {
}

// GetOrganizationalUnits returns the OU for this instance
func (id *identity) GetOrganizationalUnits() []msp.FabricOUIdentifier {
func (id *identity) GetOrganizationalUnits() []*OUIdentifier {
if id.cert == nil {
return nil
}
Expand All @@ -83,9 +83,9 @@ func (id *identity) GetOrganizationalUnits() []msp.FabricOUIdentifier {
return nil
}

res := []msp.FabricOUIdentifier{}
res := []*OUIdentifier{}
for _, unit := range id.cert.Subject.OrganizationalUnit {
res = append(res, msp.FabricOUIdentifier{
res = append(res, &OUIdentifier{
OrganizationalUnitIdentifier: unit,
CertifiersIdentifier: cid,
})
Expand Down
13 changes: 12 additions & 1 deletion msp/msp.go
Expand Up @@ -102,6 +102,17 @@ type MSP interface {
SatisfiesPrincipal(id Identity, principal *msp.MSPPrincipal) error
}

// OUIdentifier represents an organizational unit and
// its related chain of trust identifier.
type OUIdentifier struct {
// CertifiersIdentifier is the hash of certificates chain of trust
// related to this organizational unit
CertifiersIdentifier []byte
// OrganizationUnitIdentifier defines the organizational unit under the
// MSP identified with MSPIdentifier
OrganizationalUnitIdentifier string
}

// From this point on, there are interfaces that are shared within the peer and client API
// of the membership service provider.

Expand Down Expand Up @@ -137,7 +148,7 @@ type Identity interface {
// TODO: For X.509 based identities, check if we need a dedicated type
// for OU where the Certificate OU is properly namespaced by the
// signer's identity
GetOrganizationalUnits() []msp.FabricOUIdentifier
GetOrganizationalUnits() []*OUIdentifier

// Verify a signature over some message using this identity as reference
Verify(msg []byte, sig []byte) error
Expand Down
38 changes: 21 additions & 17 deletions msp/msp_test.go
Expand Up @@ -48,6 +48,14 @@ func TestGetIdentities(t *testing.T) {
}
}

func TestValidateDefaultSigningIdentity(t *testing.T) {
id, err := localMsp.GetDefaultSigningIdentity()
assert.NoError(t, err)

err = localMsp.Validate(id.GetPublicVersion())
assert.NoError(t, err)
}

func TestSerializeIdentities(t *testing.T) {
id, err := localMsp.GetDefaultSigningIdentity()
if err != nil {
Expand Down Expand Up @@ -244,9 +252,14 @@ func TestCertificationIdentifierComputation(t *testing.T) {
assert.NoError(t, err)

// Hash the chain
hf, err := localMsp.(*bccspmsp).bccsp.GetHash(&bccsp.SHA256Opts{})
// Use the hash of the identity's certificate as id in the IdentityIdentifier
hashOpt, err := bccsp.GetHashOpt(localMsp.(*bccspmsp).cryptoConfig.IdentityIdentifierHashFunction)
assert.NoError(t, err)

hf, err := localMsp.(*bccspmsp).bccsp.GetHash(hashOpt)
assert.NoError(t, err)
for i := 0; i < len(chain); i++ {
// Skipping first cert because it belongs to the identity
for i := 1; i < len(chain); i++ {
hf.Write(chain[i].Raw)
}
sum := hf.Sum(nil)
Expand Down Expand Up @@ -371,27 +384,18 @@ func TestMSPOus(t *testing.T) {
id, err := localMsp.GetDefaultSigningIdentity()
assert.NoError(t, err)

localMsp.(*bccspmsp).ouIdentifiers = []*msp.FabricOUIdentifier{
&msp.FabricOUIdentifier{
OrganizationalUnitIdentifier: "COP",
CertifiersIdentifier: id.GetOrganizationalUnits()[0].CertifiersIdentifier,
},
localMsp.(*bccspmsp).ouIdentifiers = map[string][][]byte{
"COP": {id.GetOrganizationalUnits()[0].CertifiersIdentifier},
}
assert.NoError(t, localMsp.Validate(id.GetPublicVersion()))

localMsp.(*bccspmsp).ouIdentifiers = []*msp.FabricOUIdentifier{
&msp.FabricOUIdentifier{
OrganizationalUnitIdentifier: "COP2",
CertifiersIdentifier: id.GetOrganizationalUnits()[0].CertifiersIdentifier,
},
localMsp.(*bccspmsp).ouIdentifiers = map[string][][]byte{
"COP2": {id.GetOrganizationalUnits()[0].CertifiersIdentifier},
}
assert.Error(t, localMsp.Validate(id.GetPublicVersion()))

localMsp.(*bccspmsp).ouIdentifiers = []*msp.FabricOUIdentifier{
&msp.FabricOUIdentifier{
OrganizationalUnitIdentifier: "COP",
CertifiersIdentifier: []byte{0, 1, 2, 3, 4},
},
localMsp.(*bccspmsp).ouIdentifiers = map[string][][]byte{
"COP": {{0, 1, 2, 3, 4}},
}
assert.Error(t, localMsp.Validate(id.GetPublicVersion()))
}
Expand Down

0 comments on commit a19279e

Please sign in to comment.