Search code examples
hyperledger-fabrichyperledger-fabric-ca

How to add attribute values to the admin on Hyperledger fabric?


Based on fabcar-sample (v1.4) I developed an app in which I want to use attribute values for the admin and for the users. I face an issue about how to add attribute values while I enroll in the admin. I do not know if it is possible to add attribute values for the admin. In the examples that I have seen are only added from the registered users. In the fabcar sample looks like the admin is just enrolled and not registered in contrast to the users.


  • registerUser.js
const gateway = new Gateway();
await gateway.connect(ccpPath, { wallet, identity: 'admin', discovery: { enabled: true, asLocalhost: true } });
console.log('Create a new gateway for connecting to our peer node');
// Get the CA client object from the gateway for interacting with the CA.
const ca = gateway.getClient().getCertificateAuthority();
const adminIdentity = gateway.getCurrentIdentity();
console.log('Get the CA client object from the gateway for interacting with the CA');

const aff = adminIdentity.getAffiliation();
const secret = await ca.register({ affiliation: aff, enrollmentID: username, role: 'client', attrs: [ {"name": "email", "value": "myemail@test.com", "ecert": true} ] }, adminIdentity);
const enrollment = await ca.enroll({ enrollmentID: username, enrollmentSecret: secret, attr_reqs: [{ name: "email", optional: false }]});
  • enrollAdmin.js
const caInfo = ccp.certificateAuthorities[ca_info];
const caTLSCACerts = caInfo.tlsCACerts.pem;
const ca = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName);

// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), wallet_info);
const wallet = new FileSystemWallet(walletPath);
const enrollment = await ca.enroll({ enrollmentID: username, enrollmentSecret:'adminpw'});
const identity = X509WalletMixin.createIdentity(MSP, enrollment.certificate, enrollment.key.toBytes());
await wallet.import(username, identity);
  • smartcontract.go
func (c *SmartContract) getEmail(stub shim.ChaincodeStubInterface) (string, error) {
    email, ok, err := cid.GetAttributeValue(stub, "email")

    if err != nil {
        return "", err
    }

    if !ok {
        return "", errors.New("email attribute is missing")
    }

    return email, nil
}

Any idea how to add attribute values on the admin while in this process in not registered the admin like the users?


Solution

  • In the case of the admin client, when the fabric-ca-server is executed, the value can be set in the configuration. Most of the examples work only with the ID and password by using the -b option. like fabric-ca-server start -b admin:adminpw -d


    default configuration can be changed in fabric-ca-server-config.yaml file.

    fabric-ca-server-config.yaml link is fabric-samples v2.0, but fabric-ca has no changes(v1.4) and the configuration form is the same.

    You can add admin's attr in this file.


    [EDIT] I wrote it according to the guide document, but I confirmed that it does not work. After deepdive analysis of the code, I confirmed and corrected that the regular expression did not work properly.

    hf.Registrar.Attributes: "*"

    to

    hf.Registrar.Attributes: "email,hf.Registrar.Roles,hf.Registrar.DelegateRoles,hf.Revoker,hf.IntermediateCA,hf.GenCRL,hf.Registrar.Attributes,hf.AffiliationMgr"

    in fabric-ca-server-config.yaml


    Here is example.

    • docker-compose-ca.yaml
    version: '3'
    
    services:
      ca.org1.example.com:
        image: hyperledger/fabric-ca:1.4
        environment:
          - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
          - FABRIC_CA_SERVER_CA_NAME=ca.org1.example.com
          - FABRIC_CA_SERVER_TLS_ENABLED=true
          - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
          - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/<your_ca_org1_private_key>
          - FABRIC_CA_SERVER_PORT=7054
        ports:
          - "7054:7054"
        command: sh -c 'fabric-ca-server start -d'
        volumes:
          # mounting fabric-ca-server-config.yaml file
          - ./fabric-ca-server-config.yaml:/etc/hyperledger/fabric-ca-server/fabric-ca-server-config.yaml
          - ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
        container_name: ca.org1.example.com
    
    • fabric-ca-server-config.yaml
    ...
    registry:
      maxenrollments: -1
      identities:
         - name: test
           pass: testpw
           type: client
           affiliation: ""
           attrs:
              # <add_your_attrs>
              email: "myemail@test.com"
              hf.Registrar.Roles: "*"
              hf.Registrar.DelegateRoles: "*"
              hf.Revoker: true
              hf.IntermediateCA: true
              hf.GenCRL: true
              hf.Registrar.Attributes: "email,hf.Registrar.Roles,hf.Registrar.DelegateRoles,hf.Revoker,hf.IntermediateCA,hf.GenCRL,hf.Registrar.Attributes,hf.AffiliationMgr"
              hf.AffiliationMgr: true
    ...
    
    • enrollAdmin.js
    ...
    // Enroll the admin user, and import the new identity into the wallet.
    // with attrs
    const enrollment = await ca.enroll({ enrollmentID: 'test', enrollmentSecret: 'testpw', 
                                         attr_reqs: [{ name: "email", optional: false }] });
    const x509Identity = {
        credentials: {
            certificate: enrollment.certificate,
            privateKey: enrollment.key.toBytes(),
        },
        mspId: 'Org1MSP',
        type: 'X.509',
    };
    await wallet.put('admin', x509Identity);
    console.log('Successfully enrolled admin user "admin" and imported it into the wallet');
    ...
    
    node enrollAdmin.js
    Successfully enrolled admin user "admin" and imported it into the wallet
    

    it works!


    [NOTE] If you don't want to touch the docker or configuration it's okay to add another admin to work.

    • registerAndEnrollAdmin.js
    ...
    
    // Register the user, enroll the user, and import the new identity into the wallet.
    const adminUser = await provider.getUserContext(adminIdentity, 'admin');
    
    const secret = await ca.register({
        affiliation: 'org1.department1',
        enrollmentID: 'admin2',
        role: 'client',
        attrs: [ {"name": "hf.Registrar.Roles", "value": "client,orderer,peer"}, {"name": "hf.Registrar.DelegateRoles", "value": "client,orderer,peer"}, {"name": "hf.Revoker", "value": "true"},
                {"name": "email", "value": "test@example.com"}, {"name": "hf.Registrar.Attributes", "value": "email, hf.Registrar.Roles, hf.Registrar.DelegateRoles, hf.Revoker, hf.Registrar.Attributes"} ] }
    , adminUser);
    const enrollment = await ca.enroll({
        enrollmentID: 'admin2',
        enrollmentSecret: secret,
        attr_reqs: [{ name: "email", optional: false }]
    });
    ...
    

    then you can register users using admin2