haggis
haggis

Reputation: 417

Hyperledger Fabric: Each organization acting as peer and ordering role - which certificates should be used?

even though the Fabric docs discourage this scenario because of default settings (it shouldn't be discouraged if you take care of the policies, right?), I'm in need of setting up a network with 3 equitable organizations. Each will have 1 orderer and 1 peer.

So my crypto-config.yaml for cryptogen defines 3 orgs, each as orderer and peer organization:

OrdererOrgs:
  - Name: Org1
    Domain: org1.example.com
    EnableNodeOUs: true
    Specs:
      - Hostname: orderer

  # same for org2 and org3

PeerOrgs:
  - Name: Org1
    Domain: org1.example.com
    EnableNodeOUs: true
    Template:
      Count: 1
    Users:
      Count: 1

  # same for org2 and org3

The configtx.yaml for configtxgen looks as follows:

---
Organizations:
    - &Org1
        Name: Org2MSP
        SkipAsForeign: false
        ID: Org1MSP
        MSPDir: crypto-config/ordererOrganizations/org1.example.com/msp

        Policies: &Org1Policies
            Readers:
                Type: Signature
                Rule: "OR('Org1.member')"
            Writers:
                Type: Signature
                Rule: "OR('Org1.member')"
            Admins:
                Type: Signature
                Rule: "OR('Org1.admin')"
            Endorsement:
                Type: Signature
                Rule: "OR('Org1.member')"
            BlockValidation:
                Type: Signature
                Rule: "OR('Org1.orderer')"

        OrdererEndpoints:
            - "127.0.0.1:7050"

        AnchorPeers:
            - Host: org1-peer1
              Port: 30110

    # same for org2 and org3

I'm now getting confused with the output of cryptogen, because it creates double certificates for each organization. Like this:

crypto-config/ordererOrganizations/org1.example.com/...
crypto-config/peerOrganizations/org1.example.com/...

TL;DR
Question: Should I just omit the PeerOrgs section in crypto-config.yaml and mention each organization only under OrdererOrgs if they're acting in both roles??

Kind regards
Patrick

Upvotes: 1

Views: 605

Answers (2)

Ta-seen Junaid
Ta-seen Junaid

Reputation: 474

You can follow this link:

https://medium.com/@kctheservant/decentralized-ordering-service-with-peer-org-owned-orderers-d0939ea026f6

By following this link you may have total understanding about the entire process.

So the crypto-config.yaml file looks like:

PeerOrgs:
  - Name: Org1
    Domain: org1.example.com
    EnableNodeOUs: true
    Specs:
      - Hostname: orderer0
      - Hostname: orderer1
      - Hostname: peer0
      - Hostname: peer1
    Users:
      Count: 0
  - Name: Org2
    Domain: org2.example.com
    EnableNodeOUs: true
    Specs:
      - Hostname: orderer0
      - Hostname: orderer1
      - Hostname: peer0
      - Hostname: peer1
    Users:
      Count: 0

You can also use fabric-ca or OpenSSL or other tools for generating crypto material.

configtx.yaml looks like:

Organizations:
    - &Org1
        Name: Org1MSP
        ID: Org1MSP
        MSPDir: crypto-config/peerOrganizations/org1.example.com/msp                
        Policies: &Org1MSPPolicies
            Readers:
                Type: Signature
                Rule: "OR('Org1MSP.member')"
            Writers:
                Type: Signature
                Rule: "OR('Org1MSP.member')"
            Admins:
                Type: Signature
                Rule: "OR('Org1MSP.admin')"
        AnchorPeers:
            - Host: peer0.org1.example.com
              Port: 7051

    - &Org2
        Name: Org2MSP
        ID: Org2MSP
        MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
        Policies: &Org2MSPPolicies
            Readers:
                Type: Signature
                Rule: "OR('Org2MSP.member')"
            Writers:
                Type: Signature
                Rule: "OR('Org2MSP.member')"
            Admins:
                Type: Signature
                Rule: "OR('Org2MSP.admin')"
        AnchorPeers:
            - Host: peer0.org2.example.com
              Port: 7051

Capabilities:
    Channel: &ChannelCapabilities
        V1_4_3: true
    Orderer: &OrdererCapabilities
        V1_4_2: true
    Application: &ApplicationCapabilities
        V1_4_2: true
        V1_3: false
        V1_2: false
        V1_1: false

Application: &ApplicationDefaults
    Organizations:
    Policies: &ApplicationDefaultPolicies
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
    Capabilities:
        <<: *ApplicationCapabilities

Orderer: &OrdererDefaults
    OrdererType: etcdraft
    Addresses:
        - orderer0.org1.example.com:7050
        - orderer1.org1.example.com:7050
        - orderer0.org2.example.com:7050
        - orderer1.org2.example.com:7050
    BatchTimeout: 2s
    BatchSize:
        MaxMessageCount: 500
        AbsoluteMaxBytes: 10 MB
        PreferredMaxBytes: 2 MB
    MaxChannels: 0
    Kafka:
        Brokers:
            - kafka0:9092
            - kafka1:9092
            - kafka2:9092
    EtcdRaft:
        Consenters:
            - Host: orderer0.org1.example.com
              Port: 7050
              ClientTLSCert: crypto-config/peerOrganizations/org1.example.com/peers/orderer0.org1.example.com/tls/server.crt
              ServerTLSCert: crypto-config/peerOrganizations/org1.example.com/peers/orderer0.org1.example.com/tls/server.crt
            - Host: orderer1.org1.example.com
              Port: 7050
              ClientTLSCert: crypto-config/peerOrganizations/org1.example.com/peers/orderer1.org1.example.com/tls/server.crt
              ServerTLSCert: crypto-config/peerOrganizations/org1.example.com/peers/orderer1.org1.example.com/tls/server.crt
            - Host: orderer0.org2.example.com
              Port: 7050
              ClientTLSCert: crypto-config/peerOrganizations/org2.example.com/peers/orderer0.org2.example.com/tls/server.crt
              ServerTLSCert: crypto-config/peerOrganizations/org2.example.com/peers/orderer0.org2.example.com/tls/server.crt
            - Host: orderer1.org2.example.com
              Port: 7050
              ClientTLSCert: crypto-config/peerOrganizations/org2.example.com/peers/orderer1.org2.example.com/tls/server.crt
              ServerTLSCert: crypto-config/peerOrganizations/org2.example.com/peers/orderer1.org2.example.com/tls/server.crt

        Options:
            TickInterval: 500ms
            ElectionTick: 10
            HeartbeatTick: 1
            MaxInflightBlocks: 5
            SnapshotIntervalSize: 20 MB
    Organizations:
    Policies:
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
        BlockValidation:
            Type: ImplicitMeta
            Rule: "ANY Writers"
    Capabilities:
        <<: *OrdererCapabilities
Channel: &ChannelDefaults
    Policies:
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
    Capabilities:
        <<: *ChannelCapabilities

Profiles:
    OrdererGenesis:
        <<: *ChannelDefaults
        Orderer:
            <<: *OrdererDefaults
            Organizations:
                - *Org1
                - *Org2
        Consortiums:
            SampleConsortium:
                Organizations:
                    - *Org1
                    - *Org2
    Channel:
        <<: *ChannelDefaults
        Consortium: SampleConsortium
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1
                - *Org2

Now for orderer use fabric fabric-orderer image in docker file to up the orderer.

services:
  orderer0.org1.example.com:
    container_name: orderer0.org1.example.com
    image: hyperledger/fabric-orderer:$IMAGE_TAG
    environment:
      - FABRIC_LOGGING_SPEC=INFO
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
      - ORDERER_GENERAL_GENESISMETHOD=file
      - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
      - ORDERER_GENERAL_LOCALMSPID=Org1MSP
      - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
      # enabled TLS
      - ORDERER_GENERAL_TLS_ENABLED=true
      - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
      - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
      - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
      - ORDERER_KAFKA_TOPIC_REPLICATIONFACTOR=1
      - ORDERER_KAFKA_VERBOSE=true
      - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
      - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
      - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric
    command: orderer
    ports:
      - 7050:7050
    volumes:
        - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
        - ./crypto-config/peerOrganizations/org1.example.com/peers/orderer0.org1.example.com/msp:/var/hyperledger/orderer/msp
        - ./crypto-config/peerOrganizations/org1.example.com/peers/orderer0.org1.example.com/tls/:/var/hyperledger/orderer/tls
        - orderer0.org1.example.com:/var/hyperledger/production/orderer
    networks:
      - byfn

Now for peer use fabric fabric-peer image in docker file to up the peer.

services:
  peer0.org1.example.com:
    container_name: peer0.org1.example.com
    image: hyperledger/fabric-peer:$IMAGE_TAG
    environment:
      - CORE_PEER_ID=peer0.org1.example.com
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      - CORE_PEER_LISTENADDRESS=0.0.0.0:7051
      - CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:7051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      # the following setting starts chaincode containers on the same
      # bridge network as the peers
      # https://docs.docker.com/compose/networking/
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=first-network
      - FABRIC_LOGGING_SPEC=INFO
      #- FABRIC_LOGGING_SPEC=DEBUG
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_PROFILE_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt      
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
    ports:
      - 7051:7051
    volumes:
        - /var/run/:/host/var/run/
        - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
        - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls
        - peer0.org1.example.com:/var/hyperledger/production
    networks:
      - byfn

Upvotes: 1

Jason Yellick
Jason Yellick

Reputation: 1624

As your post points out, Fabric encourages users never to share an organization definition across ordering and application spaces. It is possible, but it creates a number of problems.

First, it's very easy to misconfigure your policies and reduce the security of the system significantly. The ordering service and the application operate based on the principle of separation of powers. It is important that ordering nodes cannot fabricate authenticate transactions, and it is likewise important that application transactors cannot fabricate blocks. Although you can "be careful", are you certain you understand exactly how every policy is applied and how every role is evaluated? For instance, in the configtx.yaml snippet you posted, your oganization has a BlockValidation policy defined, do you know how that's used? (Hint: unless you modified other parts of your configtx.yaml, it's not).

Second,because the MSP definition must appear in both sections of the channel config, you end up with two identical copies of the MSP definition, which must be kept exactly in sync. Since both MSPs have the same ID, if the contents are not exactly the same, then it creates an ambiguity in evaluating identities. So, there is a literal field by field comparison of their configurations every time the channel config is updated. For commodity scripts or tools, they generally expect to operate on one definition at a time, so you will likely run into problems here unless you roll your own tooling.

To directly answer your question, if you really want to run in this odd configuration, I would skip cryptogen and go straight to fabric-ca. The cryptogen tool should never be used in production anyway, and you'll need to begin rolling the tooling necessary to support this configuration, so might as well get a head start anyway.

Upvotes: 2

Related Questions