Skip to content

Commit

Permalink
[FAB-8865] Clenaup pkg/client/msp
Browse files Browse the repository at this point in the history
References to low level packages are removed from MSP Client.

Change-Id: I2214de6898301072175bd105f3760be558121cd1
Signed-off-by: Aleksandar Likic <aleksandar.likic@securekey.com>
  • Loading branch information
Aleksandar Likic committed Mar 14, 2018
1 parent 267c094 commit 8241d5c
Show file tree
Hide file tree
Showing 6 changed files with 261 additions and 32 deletions.
74 changes: 74 additions & 0 deletions pkg/client/msp/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package msp

// AttributeRequest is a request for an attribute.
type AttributeRequest struct {
Name string
Optional bool
}

// RegistrationRequest defines the attributes required to register a user with the CA
type RegistrationRequest struct {
// Name is the unique name of the identity
Name string
// Type of identity being registered (e.g. "peer, app, user")
Type string
// MaxEnrollments is the number of times the secret can be reused to enroll.
// if omitted, this defaults to max_enrollments configured on the server
MaxEnrollments int
// The identity's affiliation e.g. org1.department1
Affiliation string
// Optional attributes associated with this identity
Attributes []Attribute
// CAName is the name of the CA to connect to
CAName string
// Secret is an optional password. If not specified,
// a random secret is generated. In both cases, the secret
// is returned from registration.
Secret string
}

// Attribute defines additional attributes that may be passed along during registration
type Attribute struct {
Name string
Key string
Value string
}

// RevocationRequest defines the attributes required to revoke credentials with the CA
type RevocationRequest struct {
// Name of the identity whose certificates should be revoked
// If this field is omitted, then Serial and AKI must be specified.
Name string
// Serial number of the certificate to be revoked
// If this is omitted, then Name must be specified
Serial string
// AKI (Authority Key Identifier) of the certificate to be revoked
AKI string
// Reason is the reason for revocation. See https://godoc.org/golang.org/x/crypto/ocsp
// for valid values. The default value is 0 (ocsp.Unspecified).
Reason string
// CAName is the name of the CA to connect to
CAName string
}

// RevocationResponse represents response from the server for a revocation request
type RevocationResponse struct {
// RevokedCerts is an array of certificates that were revoked
RevokedCerts []RevokedCert
// CRL is PEM-encoded certificate revocation list (CRL) that contains all unexpired revoked certificates
CRL []byte
}

// RevokedCert represents a revoked certificate
type RevokedCert struct {
// Serial number of the revoked certificate
Serial string
// AKI of the revoked certificate
AKI string
}
87 changes: 76 additions & 11 deletions pkg/client/msp/msp.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,44 @@ func newCAClient(ctx context.Client, orgName string) (mspapi.CAClient, error) {
return caClient, nil
}

// enrollmentOptions represent enrollment options
type enrollmentOptions struct {
secret string
}

// EnrollmentOption describes a functional parameter for Enroll
type EnrollmentOption func(*enrollmentOptions) error

// WithSecret enrollment option
func WithSecret(secret string) EnrollmentOption {
return func(o *enrollmentOptions) error {
o.secret = secret
return nil
}
}

// Enroll enrolls a registered user in order to receive a signed X509 certificate.
// A new key pair is generated for the user. The private key and the
// enrollment certificate issued by the CA are stored in SDK stores.
// They can be retrieved by calling IdentityManager.GetSigningIdentity().
//
// enrollmentID enrollment ID of a registered user
// enrollmentSecret secret associated with the enrollment ID
func (c *MSP) Enroll(enrollmentID string, enrollmentSecret string) error {
// opts represent enrollment options
func (c *MSP) Enroll(enrollmentID string, opts ...EnrollmentOption) error {

eo := enrollmentOptions{}
for _, param := range opts {
err := param(&eo)
if err != nil {
return errors.WithMessage(err, "failed to enroll")
}
}

ca, err := newCAClient(c.ctx, c.orgName)
if err != nil {
return err
}
return ca.Enroll(enrollmentID, enrollmentSecret)
return ca.Enroll(enrollmentID, eo.secret)
}

// Reenroll reenrolls an enrolled user in order to obtain a new signed X509 certificate
Expand All @@ -107,36 +132,76 @@ func (c *MSP) Reenroll(enrollmentID string) error {
// Register registers a User with the Fabric CA
// request: Registration Request
// Returns Enrolment Secret
func (c *MSP) Register(request *mspapi.RegistrationRequest) (string, error) {
func (c *MSP) Register(request *RegistrationRequest) (string, error) {
ca, err := newCAClient(c.ctx, c.orgName)
if err != nil {
return "", err
}
return ca.Register(request)
var a []mspapi.Attribute
for i := range request.Attributes {
a = append(a, mspapi.Attribute{Name: request.Attributes[i].Name, Key: request.Attributes[i].Key, Value: request.Attributes[i].Value})
}
r := mspapi.RegistrationRequest{
Name: request.Name,
Type: request.Type,
MaxEnrollments: request.MaxEnrollments,
Affiliation: request.Affiliation,
CAName: request.CAName,
Secret: request.Secret,
}
return ca.Register(&r)
}

// Revoke revokes a User with the Fabric CA
// request: Revocation Request
func (c *MSP) Revoke(request *mspapi.RevocationRequest) (*mspapi.RevocationResponse, error) {
func (c *MSP) Revoke(request *RevocationRequest) (*RevocationResponse, error) {
ca, err := newCAClient(c.ctx, c.orgName)
if err != nil {
return nil, err
}
return ca.Revoke(request)
req := mspapi.RevocationRequest(*request)
resp, err := ca.Revoke(&req)
if err != nil {
return nil, err
}
var revokedCerts []RevokedCert
for i := range resp.RevokedCerts {
revokedCerts = append(
revokedCerts,
RevokedCert{
Serial: resp.RevokedCerts[i].Serial,
AKI: resp.RevokedCerts[i].AKI,
})
}

return &RevocationResponse{
RevokedCerts: revokedCerts,
CRL: resp.CRL,
}, nil
}

// GetSigningIdentity returns a signing identity for the given user name
func (c *MSP) GetSigningIdentity(userName string) (*mspctx.SigningIdentity, error) {
func (c *MSP) GetSigningIdentity(userName string) (*SigningIdentity, error) {
user, err := c.GetUser(userName)
if err != nil {
if err == mspctx.ErrUserNotFound {
return nil, ErrUserNotFound
}
return nil, err
}
signingIdentity := &mspctx.SigningIdentity{MspID: user.MspID(), PrivateKey: user.PrivateKey(), EnrollmentCert: user.EnrollmentCertificate()}
signingIdentity := &SigningIdentity{MspID: user.MspID(), PrivateKey: user.PrivateKey(), EnrollmentCert: user.EnrollmentCertificate()}
return signingIdentity, nil
}

// GetUser returns a user for the given user name
func (c *MSP) GetUser(userName string) (mspctx.User, error) {
func (c *MSP) GetUser(userName string) (User, error) {
im, _ := c.ctx.IdentityManager(c.orgName)
return im.GetUser(userName)
user, err := im.GetUser(userName)
if err != nil {
if err == mspctx.ErrUserNotFound {
return nil, ErrUserNotFound
}
return nil, err
}
return user, nil
}
15 changes: 7 additions & 8 deletions pkg/client/msp/msp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"os"

"github.com/hyperledger/fabric-sdk-go/pkg/context/api/core"
mspctx "github.com/hyperledger/fabric-sdk-go/pkg/context/api/msp"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
"github.com/hyperledger/fabric-sdk-go/pkg/msp/mocks"
Expand Down Expand Up @@ -44,27 +43,27 @@ func TestMSP(t *testing.T) {
}

// Empty enrollment ID
err = msp.Enroll("", "user1")
err = msp.Enroll("", WithSecret("user1"))
if err == nil {
t.Fatalf("Enroll shoudl return error for empty enrollment ID")
t.Fatalf("Enroll should return error for empty enrollment ID")
}

// Empty enrollment secret
err = msp.Enroll("enrolledUserName", "")
err = msp.Enroll("enrolledUserName", WithSecret(""))
if err == nil {
t.Fatalf("Enroll shoudl return error for empty enrollment secret")
t.Fatalf("Enroll should return error for empty enrollment secret")
}

// Successful enrollment scenario

enrollUserName := randomUserName()

_, err = msp.GetSigningIdentity(enrollUserName)
if err != mspctx.ErrUserNotFound {
if err != ErrUserNotFound {
t.Fatalf("Expected to not find user")
}

err = msp.Enroll(enrollUserName, "enrollmentSecret")
err = msp.Enroll(enrollUserName, WithSecret("enrollmentSecret"))
if err != nil {
t.Fatalf("Enroll return error %v", err)
}
Expand Down Expand Up @@ -110,7 +109,7 @@ func TestMSP(t *testing.T) {

org2lUserName := randomUserName()

err = msp.Enroll(org2lUserName, "enrollmentSecret")
err = msp.Enroll(org2lUserName, WithSecret("enrollmentSecret"))
if err != nil {
t.Fatalf("Enroll return error %v", err)
}
Expand Down
93 changes: 93 additions & 0 deletions pkg/client/msp/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package msp

import (
"github.com/hyperledger/fabric-sdk-go/pkg/context/api/core"
"github.com/pkg/errors"
)

var (
// ErrUserNotFound indicates the user was not found
ErrUserNotFound = errors.New("user not found")
)

// Identity supplies the serialized identity and key reference.
type Identity interface {
MspID() string
SerializedIdentity() ([]byte, error)
PrivateKey() core.Key
}

// SigningIdentity is the identity object that encapsulates the user's private key for signing
// and the user's enrollment certificate (identity)
type SigningIdentity struct {
MspID string
EnrollmentCert []byte
PrivateKey core.Key
}

// IdentityManager provides management of identities in a Fabric network
type IdentityManager interface {
GetSigningIdentity(name string) (*SigningIdentity, error)
GetUser(name string) (User, error)
}

// User represents users that have been enrolled and represented by
// an enrollment certificate (ECert) and a signing key. The ECert must have
// been signed by one of the CAs the blockchain network has been configured to trust.
// An enrolled user (having a signing key and ECert) can conduct chaincode deployments,
// transactions and queries with the Chain.
//
// User ECerts can be obtained from a CA beforehand as part of deploying the application,
// or it can be obtained from the optional Fabric COP service via its enrollment process.
//
// Sometimes User identities are confused with Peer identities. User identities represent
// signing capability because it has access to the private key, while Peer identities in
// the context of the application/SDK only has the certificate for verifying signatures.
// An application cannot use the Peer identity to sign things because the application doesn’t
// have access to the Peer identity’s private key.
type User interface {
MspID() string
Name() string
SerializedIdentity() ([]byte, error)
PrivateKey() core.Key
EnrollmentCertificate() []byte
}

// UserData is the representation of User in UserStore
// PrivateKey is stored separately, in the crypto store
type UserData struct {
Name string
MspID string
EnrollmentCertificate []byte
}

// UserStore is responsible for UserData persistence
type UserStore interface {
Store(*UserData) error
Load(UserIdentifier) (*UserData, error)
}

// UserIdentifier is the User's unique identifier
type UserIdentifier struct {
MspID string
Name string
}

// PrivKeyKey is a composite key for accessing a private key in the key store
type PrivKeyKey struct {
MspID string
UserName string
SKI []byte
}

// CertKey is a composite key for accessing a cert in the cert store
type CertKey struct {
MspID string
UserName string
}
Loading

0 comments on commit 8241d5c

Please sign in to comment.