Skip to content

Commit

Permalink
[FAB-18063] Support individual MSP updates for organization (#35)
Browse files Browse the repository at this point in the history
Signed-off-by: Tiffany Harris <tiffany.harris@ibm.com>
  • Loading branch information
stephyee authored Jul 28, 2020
1 parent 41c3811 commit a97807f
Show file tree
Hide file tree
Showing 10 changed files with 1,456 additions and 252 deletions.
28 changes: 8 additions & 20 deletions configtx/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ SPDX-License-Identifier: Apache-2.0
package configtx

import (
"crypto/x509"
"crypto/x509/pkix"
"errors"
"fmt"

Expand Down Expand Up @@ -39,6 +37,13 @@ type ApplicationOrg struct {
name string
}

// MSP returns an OrganizationMSP object that can be used to configure the organization's MSP.
func (a *ApplicationOrg) MSP() *OrganizationMSP {
return &OrganizationMSP{
configGroup: a.orgGroup,
}
}

// Application returns the application group the updated config.
func (c *ConfigTx) Application() *ApplicationGroup {
applicationGroup := c.updated.ChannelGroup.Groups[ApplicationGroupKey]
Expand Down Expand Up @@ -378,16 +383,10 @@ func (a *ApplicationGroup) RemoveACLs(acls []string) error {
return nil
}

// MSP returns the MSP configuration for an existing application
// org in the updated config of a config transaction.
func (a *ApplicationOrg) MSP() (MSP, error) {
return getMSPConfig(a.orgGroup)
}

// SetMSP updates the MSP config for the specified application
// org group.
func (a *ApplicationOrg) SetMSP(updatedMSP MSP) error {
currentMSP, err := a.MSP()
currentMSP, err := a.MSP().Configuration()
if err != nil {
return fmt.Errorf("retrieving msp: %v", err)
}
Expand Down Expand Up @@ -423,17 +422,6 @@ func (a *ApplicationOrg) setMSPConfig(updatedMSP MSP) error {
return nil
}

// CreateMSPCRL creates a CRL that revokes the provided certificates
// for the specified application org signed by the provided SigningIdentity.
func (a *ApplicationOrg) CreateMSPCRL(signingIdentity *SigningIdentity, certs ...*x509.Certificate) (*pkix.CertificateList, error) {
msp, err := a.MSP()
if err != nil {
return nil, fmt.Errorf("retrieving application org msp: %s", err)
}

return msp.newMSPCRL(signingIdentity, certs...)
}

// newApplicationGroupTemplate returns the application component of the channel
// configuration with only the names of the application organizations.
// By default, it sets the mod_policy of all elements to "Admins".
Expand Down
181 changes: 18 additions & 163 deletions configtx/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func TestNewApplicationGroupFailure(t *testing.T) {
}
}

func TestAddAnchorPeer(t *testing.T) {
func TestAppOrgAddAnchorPeer(t *testing.T) {
t.Parallel()

gt := NewGomegaWithT(t)
Expand Down Expand Up @@ -368,7 +368,7 @@ func TestAddAnchorPeer(t *testing.T) {
gt.Expect(proto.Equal(c.updated, expectedUpdatedConfig)).To(BeTrue())
}

func TestRemoveAnchorPeer(t *testing.T) {
func TestAppOrgRemoveAnchorPeer(t *testing.T) {
t.Parallel()

gt := NewGomegaWithT(t)
Expand Down Expand Up @@ -502,7 +502,7 @@ func TestRemoveAnchorPeer(t *testing.T) {
gt.Expect(proto.Equal(c.updated, expectedUpdatedConfig)).To(BeTrue())
}

func TestRemoveAnchorPeerFailure(t *testing.T) {
func TestAppOrgRemoveAnchorPeerFailure(t *testing.T) {
t.Parallel()

tests := []struct {
Expand Down Expand Up @@ -652,7 +652,7 @@ func TestSetACL(t *testing.T) {
}
}

func TestRemoveACL(t *testing.T) {
func TestAppOrgRemoveACL(t *testing.T) {
t.Parallel()

tests := []struct {
Expand Down Expand Up @@ -1091,7 +1091,7 @@ func TestApplicationCapabilities(t *testing.T) {
gt.Expect(applicationCapabilities).To(BeNil())
}

func TestAddApplicationCapability(t *testing.T) {
func TestAppOrgAddApplicationCapability(t *testing.T) {
t.Parallel()

tests := []struct {
Expand Down Expand Up @@ -1309,7 +1309,7 @@ func TestAddApplicationCapability(t *testing.T) {
}
}

func TestAddApplicationCapabilityFailures(t *testing.T) {
func TestAppOrgAddApplicationCapabilityFailures(t *testing.T) {
t.Parallel()

tests := []struct {
Expand Down Expand Up @@ -1360,7 +1360,7 @@ func TestAddApplicationCapabilityFailures(t *testing.T) {
}
}

func TestRemoveApplicationCapability(t *testing.T) {
func TestAppOrgRemoveApplicationCapability(t *testing.T) {
t.Parallel()

gt := NewGomegaWithT(t)
Expand Down Expand Up @@ -1466,7 +1466,7 @@ func TestRemoveApplicationCapability(t *testing.T) {
gt.Expect(buf.String()).To(Equal(expectedConfigGroupJSON))
}

func TestRemoveApplicationCapabilityFailures(t *testing.T) {
func TestAppOrgRemoveApplicationCapabilityFailures(t *testing.T) {
t.Parallel()

tests := []struct {
Expand Down Expand Up @@ -1572,7 +1572,7 @@ func TestApplicationOrg(t *testing.T) {
}
}

func TestRemoveApplicationOrg(t *testing.T) {
func TestAppOrgRemoveApplicationOrg(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)

Expand All @@ -1599,7 +1599,7 @@ func TestRemoveApplicationOrg(t *testing.T) {
gt.Expect(c.updated.ChannelGroup.Groups[ApplicationGroupKey].Groups["Org1"]).To(BeNil())
}

func TestRemoveApplicationOrgPolicy(t *testing.T) {
func TestAppOrgRemoveApplicationOrgPolicy(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)

Expand Down Expand Up @@ -1639,7 +1639,7 @@ func TestRemoveApplicationOrgPolicy(t *testing.T) {
gt.Expect(actualOrg1Policies).To(Equal(expectedPolicies))
}

func TestRemoveApplicationOrgPolicyFailures(t *testing.T) {
func TestAppOrgRemoveApplicationOrgPolicyFailures(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)

Expand Down Expand Up @@ -1804,7 +1804,7 @@ func TestSetApplicationPolicyFailures(t *testing.T) {
gt.Expect(err).To(MatchError("failed to set policy 'TestPolicy': unknown policy type: "))
}

func TestRemoveApplicationPolicy(t *testing.T) {
func TestAppOrgRemoveApplicationPolicy(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)

Expand Down Expand Up @@ -1846,7 +1846,7 @@ func TestRemoveApplicationPolicy(t *testing.T) {
gt.Expect(updatedPolicies).To(Equal(expectedPolicies))
}

func TestRemoveApplicationPolicyFailures(t *testing.T) {
func TestAppOrgRemoveApplicationPolicyFailures(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)

Expand Down Expand Up @@ -1892,7 +1892,7 @@ func TestApplicationMSP(t *testing.T) {

c := New(config)

msp, err := c.Application().Organization("Org1").MSP()
msp, err := c.Application().Organization("Org1").MSP().Configuration()
gt.Expect(err).NotTo(HaveOccurred())
gt.Expect(msp).To(Equal(application.Organizations[0].MSP))
}
Expand Down Expand Up @@ -2014,7 +2014,7 @@ func TestSetApplicationMSPFailure(t *testing.T) {

c := New(config)

org1MSP, err := c.Application().Organization("Org1").MSP()
org1MSP, err := c.Application().Organization("Org1").MSP().Configuration()
gt.Expect(err).NotTo(HaveOccurred())

org1MSP = tc.mspMod(org1MSP)
Expand All @@ -2024,151 +2024,6 @@ func TestSetApplicationMSPFailure(t *testing.T) {
}
}

func TestCreateApplicationMSPCRL(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)

channelGroup, privKeys, err := baseApplicationChannelGroup(t)
gt.Expect(err).ToNot(HaveOccurred())
config := &cb.Config{
ChannelGroup: channelGroup,
}

c := New(config)

org1MSP, err := c.Application().Organization("Org1").MSP()
gt.Expect(err).NotTo(HaveOccurred())
org1RootCert := org1MSP.RootCerts[0]
org1PrivKey := privKeys[0]

// update org2MSP to include an intemediate cert that is different
// from the root cert
org2MSP, err := c.Application().Organization("Org2").MSP()
gt.Expect(err).NotTo(HaveOccurred())
org2Cert := org2MSP.RootCerts[0]
org2PrivKey := privKeys[1]
org2IntermediateCert, org2IntermediatePrivKey := generateIntermediateCACertAndPrivateKey(t, "org2.example.com", org2Cert, org2PrivKey)
org2MSP.IntermediateCerts = append(org2MSP.IntermediateCerts, org2IntermediateCert)
err = c.Application().Organization("Org2").SetMSP(org2MSP)
gt.Expect(err).NotTo(HaveOccurred())

tests := []struct {
spec string
orgName string
caCert *x509.Certificate
caPrivKey *ecdsa.PrivateKey
numCertsToRevoke int
}{
{
spec: "create CRL using a root cert",
orgName: "Org1",
caCert: org1RootCert,
caPrivKey: org1PrivKey,
numCertsToRevoke: 2,
},
{
spec: "create CRL using an intermediate cert",
orgName: "Org2",
caCert: org2IntermediateCert,
caPrivKey: org2IntermediatePrivKey,
numCertsToRevoke: 1,
},
}
for _, tc := range tests {
tc := tc
t.Run(tc.spec, func(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)
certsToRevoke := make([]*x509.Certificate, tc.numCertsToRevoke)
for i := 0; i < tc.numCertsToRevoke; i++ {
certToRevoke, _ := generateCertAndPrivateKeyFromCACert(t, tc.orgName, tc.caCert, tc.caPrivKey)
certsToRevoke[i] = certToRevoke
}
signingIdentity := &SigningIdentity{
Certificate: tc.caCert,
PrivateKey: tc.caPrivKey,
MSPID: "MSPID",
}
crl, err := c.Application().Organization(tc.orgName).CreateMSPCRL(signingIdentity, certsToRevoke...)
gt.Expect(err).NotTo(HaveOccurred())
err = tc.caCert.CheckCRLSignature(crl)
gt.Expect(err).NotTo(HaveOccurred())
gt.Expect(crl.TBSCertList.RevokedCertificates).To(HaveLen(tc.numCertsToRevoke))
for i := 0; i < tc.numCertsToRevoke; i++ {
gt.Expect(crl.TBSCertList.RevokedCertificates[i].SerialNumber).To(Equal(certsToRevoke[i].SerialNumber))
}
})
}
}

func TestCreateApplicationMSPCRLFailure(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)

channelGroup, privKeys, err := baseApplicationChannelGroup(t)
gt.Expect(err).ToNot(HaveOccurred())
config := &cb.Config{
ChannelGroup: channelGroup,
}

c := New(config)

org1MSP, err := c.Application().Organization("Org1").MSP()
gt.Expect(err).NotTo(HaveOccurred())
org1Cert := org1MSP.RootCerts[0]
org1PrivKey := privKeys[0]
org1CertToRevoke, _ := generateCertAndPrivateKeyFromCACert(t, "org1.example.com", org1Cert, org1PrivKey)

org2MSP, err := c.Application().Organization("Org2").MSP()
gt.Expect(err).NotTo(HaveOccurred())
org2Cert := org2MSP.RootCerts[0]
org2PrivKey := privKeys[1]
org2CertToRevoke, _ := generateCertAndPrivateKeyFromCACert(t, "org2.example.com", org2Cert, org2PrivKey)

signingIdentity := &SigningIdentity{
Certificate: org1Cert,
PrivateKey: org1PrivKey,
}
tests := []struct {
spec string
mspMod func(MSP) MSP
signingIdentity *SigningIdentity
certToRevoke *x509.Certificate
orgName string
expectedErr string
}{
{
spec: "signing cert is not a root/intermediate cert for msp",
orgName: "Org1",
signingIdentity: &SigningIdentity{
Certificate: org2Cert,
PrivateKey: org2PrivKey,
},
certToRevoke: org1CertToRevoke,
expectedErr: "signing cert is not a root/intermediate cert for this MSP: MSPID",
},
{
spec: "certificate not issued by this MSP",
orgName: "Org1",
signingIdentity: signingIdentity,
certToRevoke: org2CertToRevoke,
expectedErr: fmt.Sprintf("certificate not issued by this MSP. serial number: %d", org2CertToRevoke.SerialNumber),
},
}

for _, tc := range tests {
tc := tc
t.Run(tc.spec, func(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)

newCRL, err := c.Application().Organization(tc.orgName).CreateMSPCRL(tc.signingIdentity, tc.certToRevoke)
gt.Expect(err).To(MatchError(tc.expectedErr))
gt.Expect(newCRL).To(BeNil())
})
}
}

func TestSetApplicationMSP(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)
Expand All @@ -2181,9 +2036,9 @@ func TestSetApplicationMSP(t *testing.T) {

c := New(config)

org1MSP, err := c.Application().Organization("Org1").MSP()
org1MSP, err := c.Application().Organization("Org1").MSP().Configuration()
gt.Expect(err).NotTo(HaveOccurred())
org2MSP, err := c.Application().Organization("Org2").MSP()
org2MSP, err := c.Application().Organization("Org2").MSP().Configuration()
gt.Expect(err).NotTo(HaveOccurred())
org1CertBase64, org1CRLBase64 := certCRLBase64(t, org1MSP)
org2CertBase64, org2CRLBase64 := certCRLBase64(t, org2MSP)
Expand All @@ -2204,7 +2059,7 @@ func TestSetApplicationMSP(t *testing.T) {
PrivateKey: privKey,
MSPID: "MSPID",
}
newCRL, err := c.Application().Organization("Org1").CreateMSPCRL(signingIdentity, certToRevoke)
newCRL, err := org1MSP.CreateMSPCRL(signingIdentity, certToRevoke)
gt.Expect(err).NotTo(HaveOccurred())
pemNewCRL, err := pemEncodeCRL(newCRL)
gt.Expect(err).NotTo(HaveOccurred())
Expand Down
Loading

0 comments on commit a97807f

Please sign in to comment.