Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit 783a09b

Browse files
author
Aleksandar Likic
committed
[FAB-8428] UserStore
Introduced a concept of a UserStore, for persistence of user information. In this first implementation, only the user primary key (mspID, name) and enrollment certificate are stored. During enrollment, user's private key is added to cryptosuite store automatically. Application still needs to add user (that contains the enrollment certificate) to user store upon enrollment. In the future this won't be necessary. Initial implementation of the store is a simple file store that stores user's enrollment cert in a pem file, using naming convention <user>@<mspid>-cert.pem. The intention is to make the user store pluggable in the future, to allow SDK integrators to plugin their own implementation of the UserStore interface. Change-Id: I63452e92a50976b141345a87766541bab2291a8e Signed-off-by: Aleksandar Likic <aleksandar.likic@securekey.com>
1 parent ef2097c commit 783a09b

File tree

23 files changed

+732
-350
lines changed

23 files changed

+732
-350
lines changed

api/apifabca/fabricca.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package apifabca
88

99
import (
1010
"github.com/hyperledger/fabric-sdk-go/api/apicryptosuite"
11+
"github.com/hyperledger/fabric-sdk-go/api/apifabclient"
1112
api "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric-ca/api"
1213
)
1314

@@ -16,9 +17,9 @@ type FabricCAClient interface {
1617
CAName() string
1718
Enroll(enrollmentID string, enrollmentSecret string) (apicryptosuite.Key, []byte, error)
1819
// Reenroll to renew user's enrollment certificate
19-
Reenroll(user User) (apicryptosuite.Key, []byte, error)
20-
Register(registrar User, request *RegistrationRequest) (string, error)
21-
Revoke(registrar User, request *RevocationRequest) (*api.RevocationResponse, error)
20+
Reenroll(user apifabclient.User) (apicryptosuite.Key, []byte, error)
21+
Register(registrar apifabclient.User, request *RegistrationRequest) (string, error)
22+
Revoke(registrar apifabclient.User, request *RevocationRequest) (*api.RevocationResponse, error)
2223
}
2324

2425
// RegistrationRequest defines the attributes required to register a user with the CA

api/apifabca/mocks/mockfabriccaclient.gen.go

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/apifabca/user.go

Lines changed: 0 additions & 40 deletions
This file was deleted.

api/apifabclient/identity.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ SPDX-License-Identifier: Apache-2.0
66

77
package apifabclient
88

9-
import "github.com/hyperledger/fabric-sdk-go/api/apicryptosuite"
9+
import (
10+
"errors"
11+
12+
"github.com/hyperledger/fabric-sdk-go/api/apicryptosuite"
13+
)
1014

1115
// User represents users that have been enrolled and represented by
1216
// an enrollment certificate (ECert) and a signing key. The ECert must have
@@ -38,3 +42,20 @@ type IdentityContext interface {
3842
Identity() ([]byte, error)
3943
PrivateKey() apicryptosuite.Key
4044
}
45+
46+
var (
47+
// ErrUserNotFound indicates the user was not found
48+
ErrUserNotFound = errors.New("user not found")
49+
)
50+
51+
// UserKey is a lookup key in UserStore
52+
type UserKey struct {
53+
MspID string
54+
Name string
55+
}
56+
57+
// UserStore is responsible for User persistence
58+
type UserStore interface {
59+
Store(User) error
60+
Load(UserKey) (User, error)
61+
}

pkg/config/testdata/config_test_pem.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ client:
6868
# Some SDKs support pluggable KV stores, the properties under "credentialStore"
6969
# are implementation specific
7070
credentialStore:
71-
# [Optional]. Not used by Go SDK. Others SDKs may use it if using an alternative impl
72-
# Could be used if SDK would require an object for properties like url, db name, etc.
71+
# [Optional]. Used by user store. Not needed if all credentials are embedded in configuration
72+
# and enrollments are performed elswhere.
7373
path: "/tmp/hfc-kvs"
7474

7575
# [Optional]. Specific to the CryptoSuite implementation used by GO SDK. Software-based implementations

pkg/config/testdata/template/config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ client:
6868
# Some SDKs support pluggable KV stores, the properties under "credentialStore"
6969
# are implementation specific
7070
credentialStore:
71-
# [Optional]. Not used by Go SDK. Others SDKs may use it if using an alternative impl
72-
# Could be used if SDK would require an object for properties like url, db name, etc.
71+
# [Optional]. Used by user store. Not needed if all credentials are embedded in configuration
72+
# and enrollments are performed elswhere.
7373
path: unused/by/sdk/go
7474

7575
# [Optional]. Specific to the CryptoSuite implementation used by GO SDK. Software-based implementations

pkg/fabric-ca-client/fabricca.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
config "github.com/hyperledger/fabric-sdk-go/api/apiconfig"
1313
sdkApi "github.com/hyperledger/fabric-sdk-go/api/apifabca"
14+
"github.com/hyperledger/fabric-sdk-go/api/apifabclient"
1415
api "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric-ca/api"
1516
fabric_ca "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric-ca/lib"
1617
"github.com/hyperledger/fabric-sdk-go/pkg/config/urlutil"
@@ -124,7 +125,7 @@ func (fabricCAServices *FabricCA) Enroll(enrollmentID string, enrollmentSecret s
124125

125126
// Reenroll an enrolled user in order to receive a signed X509 certificate
126127
// Returns X509 certificate
127-
func (fabricCAServices *FabricCA) Reenroll(user sdkApi.User) (apicryptosuite.Key, []byte, error) {
128+
func (fabricCAServices *FabricCA) Reenroll(user apifabclient.User) (apicryptosuite.Key, []byte, error) {
128129
if user == nil {
129130
return nil, nil, errors.New("user required")
130131
}
@@ -153,7 +154,7 @@ func (fabricCAServices *FabricCA) Reenroll(user sdkApi.User) (apicryptosuite.Key
153154
// registrar: The User that is initiating the registration
154155
// request: Registration Request
155156
// Returns Enrolment Secret
156-
func (fabricCAServices *FabricCA) Register(registrar sdkApi.User,
157+
func (fabricCAServices *FabricCA) Register(registrar apifabclient.User,
157158
request *sdkApi.RegistrationRequest) (string, error) {
158159
// Validate registration request
159160
if request == nil {
@@ -190,7 +191,7 @@ func (fabricCAServices *FabricCA) Register(registrar sdkApi.User,
190191
// Revoke a User with the Fabric CA
191192
// registrar: The User that is initiating the revocation
192193
// request: Revocation Request
193-
func (fabricCAServices *FabricCA) Revoke(registrar sdkApi.User,
194+
func (fabricCAServices *FabricCA) Revoke(registrar apifabclient.User,
194195
request *sdkApi.RevocationRequest) (*api.RevocationResponse, error) {
195196
// Validate revocation request
196197
if request == nil {
@@ -212,8 +213,7 @@ func (fabricCAServices *FabricCA) Revoke(registrar sdkApi.User,
212213
}
213214

214215
// createSigningIdentity creates an identity to sign Fabric CA requests with
215-
func (fabricCAServices *FabricCA) createSigningIdentity(user sdkApi.
216-
User) (*fabric_ca.Identity, error) {
216+
func (fabricCAServices *FabricCA) createSigningIdentity(user apifabclient.User) (*fabric_ca.Identity, error) {
217217
// Validate user
218218
if user == nil {
219219
return nil, errors.New("user required")

pkg/fabric-client/client.go

Lines changed: 12 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,14 @@ SPDX-License-Identifier: Apache-2.0
77
package fabricclient
88

99
import (
10-
"encoding/json"
11-
1210
config "github.com/hyperledger/fabric-sdk-go/api/apiconfig"
1311
fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
14-
"github.com/hyperledger/fabric-sdk-go/api/kvstore"
1512
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
1613
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
1714

1815
"github.com/hyperledger/fabric-sdk-go/api/apicryptosuite"
1916
channel "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/channel"
2017
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/chconfig"
21-
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/identity"
2218
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/resource"
2319
"github.com/hyperledger/fabric-sdk-go/pkg/logging"
2420
"github.com/pkg/errors"
@@ -30,7 +26,7 @@ var logger = logging.NewLogger("fabric_sdk_go")
3026
type Client struct {
3127
channels map[string]fab.Channel
3228
cryptoSuite apicryptosuite.CryptoSuite
33-
stateStore kvstore.KVStore
29+
stateStore fab.UserStore
3430
signingIdentity fab.IdentityContext
3531
config config.Config
3632
signingManager fab.SigningManager
@@ -99,12 +95,12 @@ func (c *Client) QueryChannelInfo(name string, peers []fab.Peer) (fab.Channel, e
9995
* so that multiple app instances can share app state via the database (note that this doesn’t necessarily make the app stateful).
10096
* This API makes this pluggable so that different store implementations can be selected by the application.
10197
*/
102-
func (c *Client) SetStateStore(stateStore kvstore.KVStore) {
98+
func (c *Client) SetStateStore(stateStore fab.UserStore) {
10399
c.stateStore = stateStore
104100
}
105101

106102
// StateStore is a convenience method for obtaining the state store object in use for this client.
107-
func (c *Client) StateStore() kvstore.KVStore {
103+
func (c *Client) StateStore() fab.UserStore {
108104
return c.stateStore
109105
}
110106

@@ -152,63 +148,29 @@ func (c *Client) SaveUserToStateStore(user fab.User) error {
152148
if c.stateStore == nil {
153149
return errors.New("stateStore is nil")
154150
}
155-
userJSON := &identity.JSON{
156-
MspID: user.MspID(),
157-
Roles: user.Roles(),
158-
PrivateKeySKI: user.PrivateKey().SKI(),
159-
EnrollmentCertificate: user.EnrollmentCertificate(),
160-
}
161-
data, err := json.Marshal(userJSON)
162-
if err != nil {
163-
return errors.Wrap(err, "marshal json return error")
164-
}
165-
err = c.stateStore.Store(user.Name(), data)
151+
err := c.stateStore.Store(user)
166152
if err != nil {
167-
return errors.WithMessage(err, "stateStore SetValue failed")
153+
return errors.WithMessage(err, "saving user failed")
168154
}
169155
return nil
170156
}
171157

172-
// LoadUserFromStateStore ...
173-
/**
174-
* Restore the state of this member from the key value store (if found). If not found, do nothing.
175-
* @returns {Promise} A Promise for a {User} object upon successful restore, or if the user by the name
176-
* does not exist in the state store, returns null without rejecting the promise
177-
*/
178-
func (c *Client) LoadUserFromStateStore(name string) (fab.User, error) {
179-
if name == "" {
180-
return nil, nil
158+
// LoadUserFromStateStore loads a user from user store.
159+
// If user is not found, returns ErrUserNotFound
160+
func (c *Client) LoadUserFromStateStore(mspID string, name string) (fab.User, error) {
161+
if mspID == "" || name == "" {
162+
return nil, errors.New("Invalid user key")
181163
}
182164
if c.stateStore == nil {
183-
return nil, nil
165+
return nil, errors.New("Invalid state - start store is missing")
184166
}
185167
if c.cryptoSuite == nil {
186168
return nil, errors.New("cryptoSuite required")
187169
}
188-
value, err := c.stateStore.Load(name)
170+
user, err := c.stateStore.Load(fab.UserKey{MspID: mspID, Name: name})
189171
if err != nil {
190-
if err == kvstore.ErrNotFound {
191-
return nil, nil
192-
}
193172
return nil, err
194173
}
195-
valueBytes, ok := value.([]byte)
196-
if !ok {
197-
return nil, errors.New("state store return wrong data type")
198-
}
199-
var userJSON identity.JSON
200-
err = json.Unmarshal(valueBytes, &userJSON)
201-
if err != nil {
202-
return nil, errors.Wrap(err, "unmarshal user JSON failed")
203-
}
204-
user := identity.NewUser(name, userJSON.MspID)
205-
user.SetRoles(userJSON.Roles)
206-
user.SetEnrollmentCertificate(userJSON.EnrollmentCertificate)
207-
key, err := c.cryptoSuite.GetKey(userJSON.PrivateKeySKI)
208-
if err != nil {
209-
return nil, errors.Wrap(err, "cryptoSuite GetKey failed")
210-
}
211-
user.SetPrivateKey(key)
212174
return user, nil
213175
}
214176

0 commit comments

Comments
 (0)