Understanding user registration and enrollment in Hyperledger Fabric


  • The bootstrap identity is defined by the username:password used in -b argument to fabric-ca-server start
  • The bootstrap identity is special and does not need a registration step. This is because it is automatically registered when the server starts
  • All other identities will first need to be registered by fabric-ca-client before they can be enrolled
  • If an identity that is not registered is tried to enroll, the enrollment will fail with following message on the fabric-ca server: “Failed to get user: : scode: 404, code: 63, msg: Failed to get User: sql: no rows in result set”. This gives us a clue as to what registration really does
  • fabric-ca-client assumes the identity of whatever is in $FABRIC_CA_HOME/msp
  • by default FABRIC_CA_HOME is set to /etc/hyperledger/fabric-ca-server
  • If TLS is enabled then:
    • we need to connect using https not http
    • we need to pass –tls.certfiles X to fabric-ca-client where X = the cert of the CA who issued cert to the server

When I read hyperledger docs and specifically the section on Enrolling Bootstrap Identity, I noticed it does not register a user before enrolling. This led me to think that a user can be enrolled without registering but that is not true. If one tries to enroll a user who has not been registered, the request will fail with following error message in fabric-ca server logs:

"Failed to get user: : scode: 404, code: 63, msg: Failed to get User: sql: no rows in result set"

So how come the bootstrap identity can be enrolled without registering? The answer is that when enrolling the bootstrap identity, the username and password must match the username and password given when fabric-ca-server was started. When the server is started, it automatically registers an identity with given username and password i.e., it stores a row in sql database with given username and password – that is what registration is about. When fabric-ca-client tries to enroll a user the server will check the sql database to first verify that the user exists and fail with above message otherwise. So all users except the bootstrap identity need to be registered first before enrolling.

we illustrate this below with some actual commands. Create a docker-compose.yaml file with following contents:

Screen Shot 2018-12-28 at 10.11.00 AM

now run it

$ docker-compose up

It should spin up a docker container named my-container. Log into the container:

$ docker exec -it my-container /bin/bash

since we have enabled TLS we need to connect using https instead of http. Also we need to add localhost to FABRIC_CA_SERVER_CSR_HOSTS otherwise will get an error saying

x509: certificate is valid for rca-ord, not localhost


root@1e046d83410d:/# fabric-ca-client enroll -u https://user:userpw@localhost:7054

2018/12/28 18:07:26 [INFO] TLS Enabled

Error: Failed to get client TLS config: No trusted root certificates for TLS were provided

what happened? we enabled TLS. so when the client tried to connect to the server, the server give it a cert but the client cannot verify authenticity of the certificate. The client needs to have the CA that issued cert to server in its trusted CA list. So to fix it run:

root@1e046d83410d:/# fabric-ca-client enroll -u https://user:userpw@localhost:7054 –tls.certfiles $FABRIC_CA_SERVER_HOME/tls-cert.pem
2018/12/28 17:32:28 [INFO] TLS Enabled
2018/12/28 17:32:28 [INFO] generating key: &{A:ecdsa S:256}
2018/12/28 17:32:28 [INFO] encoded CSR
Error: Response from server: Error Code: 20 – Authentication failure

on server:
my-container | 2018/12/28 17:32:28 [INFO] POST /enroll 401 23 “Failed to get user: : scode: 404, code: 63, msg: Failed to get User: sql: no rows in result set”

this is because user is not registered.

root@1e046d83410d:/# fabric-ca-client enroll -u https://admin:adminpw@localhost:7054 –tls.certfiles $FABRIC_CA_SERVER_HOME/tls-cert.pem
2018/12/28 17:25:38 [INFO] TLS Enabled
2018/12/28 17:25:38 [INFO] generating key: &{A:ecdsa S:256}
2018/12/28 17:25:38 [INFO] encoded CSR
2018/12/28 17:25:38 [INFO] Stored client certificate at /etc/hyperledger/fabric-ca-server/msp/signcerts/cert.pem
2018/12/28 17:25:38 [INFO] Stored root CA certificate at /etc/hyperledger/fabric-ca-server/msp/cacerts/localhost-7054.pem
2018/12/28 17:25:38 [INFO] Stored Issuer public key at /etc/hyperledger/fabric-ca-server/msp/IssuerPublicKey
2018/12/28 17:25:38 [INFO] Stored Issuer revocation public key at /etc/hyperledger/fabric-ca-server/msp/IssuerRevocationPublicKey

note we gave same username and password as the one used when starting the server. This is what defines the bootstrap identity – it is the user who started the server. And the command succeeds now. we can look at the cert of bootstrap identity as follows:

root@1e046d83410d:/# openssl x509 -in /etc/hyperledger/fabric-ca-server/msp/signcerts/cert.pem -text -noout
Version: 3 (0x2)
Serial Number:
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=US, ST=North Carolina, O=Hyperledger, OU=Fabric, CN=rca-ord
Not Before: Dec 28 17:21:00 2018 GMT
Not After : Dec 28 17:26:00 2019 GMT
Subject: C=US, ST=North Carolina, O=Hyperledger, OU=client, CN=admin
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
ASN1 OID: prime256v1
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Basic Constraints: critical
X509v3 Subject Key Identifier:
X509v3 Authority Key Identifier:

X509v3 Subject Alternative Name:
Signature Algorithm: ecdsa-with-SHA256

Lets try to enroll the user defined in BOOTSTRAP_USER_PASS variable when we started the server

root@1e046d83410d:/# fabric-ca-client enroll -u https://rca-ord-admin:rca-ord-adminpw@localhost:7054 –tls.certfiles $FABRIC_CA_SERVER_HOME/tls-cert.pem
2018/12/28 17:36:03 [INFO] TLS Enabled
2018/12/28 17:36:03 [INFO] generating key: &{A:ecdsa S:256}
2018/12/28 17:36:03 [INFO] encoded CSR
Error: Response from server: Error Code: 20 – Authentication failure

my-container | 2018/12/28 17:36:03 [INFO] POST /enroll 401 23 “Failed to get user: : scode: 404, code: 63, msg: Failed to get User: sql: no rows in result set”

it does not work. Lets try to enroll a new user

root@1e046d83410d:/# fabric-ca-client register –id.name admin2 –id.affiliation org1.department1 –id.attrs ‘hf.Revoker=true,admin=true:ecert’ -u https://localhost:7054 –tls.certfiles $FABRIC_CA_SERVER_HOME/tls-cert.pem
2018/12/28 17:42:34 [INFO] Configuration file location: /etc/hyperledger/fabric-ca-server/fabric-ca-client-config.yaml
2018/12/28 17:42:34 [INFO] TLS Enabled
2018/12/28 17:42:34 [INFO] TLS Enabled
Password: mMNrwlSgLXqE

Things to note:

  1. Note that we enrolled bootstrap user earlier and above command ran under its identity. the fabric-ca-client will take identity from $FABRIC_CA_HOME/msp
  2. Since we did not specify any password the server generated one for us

Example showing password set at time of registration:

root@1e046d83410d:/# fabric-ca-client register –id.name test-user1 –id.secret test-user1pw –id.affiliation org1.department1 -u https://localhost:7054 –tls.certfiles $FABRIC_CA_SERVER_HOME/tls-cert.pem
2018/12/28 17:46:03 [INFO] Configuration file location: /etc/hyperledger/fabric-ca-server/fabric-ca-client-config.yaml
2018/12/28 17:46:03 [INFO] TLS Enabled
2018/12/28 17:46:03 [INFO] TLS Enabled
Password: test-user1pw

Also note what happens below:

root@1e046d83410d:/# mv /etc/hyperledger/fabric-ca-server/msp /etc/hyperledger/fabric-ca-server/msp1

root@1e046d83410d:/# fabric-ca-client register –id.name test-user2 –id.secret test-user2pw –id.affiliation org1.department1 -u https://localhost:7054 –tls.certfiles $FABRIC_CA_SERVER_HOME/tls-cert.pem
2018/12/28 19:38:00 [INFO] Configuration file location: /etc/hyperledger/fabric-ca-server/fabric-ca-client-config.yaml
2018/12/28 19:38:00 [INFO] TLS Enabled
2018/12/28 19:38:00 [ERROR] Enrollment check failed: Idemix enrollment information does not exist
Error: Enrollment information does not exist. Please execute enroll command first. Example: fabric-ca-client enroll -u http://user:userpw@serverAddr:serverPort

So it looks like fabric-ca-client is taking its identity from /etc/hyperledger/fabric-ca-server/msp which is same as $FABRIC_CA_HOME/msp

PS: I am not able to get wordpress to post code. I have tried wrapping code blocks in tags as explained here but every time i have more than one line in my code, wordpress would insert p and span tags and mess it up. I haven’t found a solution to this. When I try to google this problem i come across links saying to edit functions.php file but this file cannot be accessed from wordpress.com. I think the file can only be access if someone is running a self-hosted blog using the open source wordpress.org code. wordpress.com does not allow ftp. i cannot find functions.php under Admin -> Appearance -> … I hate wordpress.

This entry was posted in Software. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s