Для начала прочитайте про MSP и identity.

Теперь, когда мы понимаем, что к чему прейдём к схеме:

  1. Для каждой организации у нас будет по два ЦС: rca и tls-ca
  2. В каждой организации у нас будет по два узла
  3. В каждой организации у нас будут пользователи: admin и user
  4. Также у нас будет пользователь admin для ЦС, чтобы выпускать сертификаты

fabric ca map

Установка зависимостей

Для того чтобы нам создать запросы на создание сертификатов, собственно, как и выдачу нам понадобятся утилиты. Так что первым делом нужно убедится, что они присутствуют.

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

sudo dnf -y install go wget vim docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

sudo systemctl enable --now docker
sudo usermod -aG docker $USER

go install github.com/hyperledger/fabric-ca/cmd/...@latest
sudo cp /home/admin/go/bin/fabric-ca-client /usr/local/bin/

Далее в /etc/hosts прописываем dns имена чтобы не обращаться постоянно по ip. В production конечно лучше воспользоваться dns.

sudo vim /etc/hosts
172.31.144.2 rca.ordererOrg1.example.com
172.31.144.2 tls-ca.ordererOrg1.example.com
172.31.144.4 rca.org1.example.com
172.31.144.4 tls-ca.org1.example.com
172.31.144.5 rca.org2.example.com
172.31.144.5 tls-ca.org2.example.com

Да рекомендуется использовать для tls и rca разные сервера, но я особо в этом смысла не вижу. Тут на ваше усмотрение.

Поднимаем ЦС

В каждой организации мы запускаем контейнер с двумя ЦС.

sudo mkdir -p /usr/local/ordererOrg1 && cd /usr/local/ordererOrg1

sudo vim /usr/local/ordererOrg1/docker-compose.yaml
version: '2'

networks:
  fabric-ordererOrg1-ca:

services:
  tls-ordererOrg1:
    container_name: tls-ordererOrg1
    image: hyperledger/fabric-ca:latest
    command: sh -c 'fabric-ca-server start -d -b tlsadmin:tlspwd --csr.cn tls-ca.ordererOrg1.example.com --csr.hosts tls-ca.ordererOrg1.example.com' 
    environment:
        - FABRIC_CA_SERVER_HOME=/usr/local/hyperledger/fabric-ca/crypto
        - FABRIC_CA_SERVER_TLS_ENABLED=true
        - FABRIC_CA_SERVER_CSR_CN=tls-ordererOrg1
        - FABRIC_CA_SERVER_CSR_HOSTS=0.0.0.0
        - FABRIC_CA_SERVER_DEBUG=true
        - FABRIC_CA_SERVER_PORT=7052
        - FABRIC_CA_SERVER_OPERATIONS_LISTENADDRESS=0.0.0.0:17054
        - TZ=Asia/Almaty
    volumes:
        - /usr/local/ordererOrg1/tls-ordererOrg1:/usr/local/hyperledger/fabric-ca
    networks:
        - fabric-ordererOrg1-ca
    ports:
        - 7052:7052
        
  rca-ordererOrg1:
    container_name: rca-ordererOrg1
    image: hyperledger/fabric-ca:latest
    command: sh -c 'fabric-ca-server start -d -b rcaadmin:rcapwd --csr.cn rca.ordererOrg1.example.com --csr.hosts rca.ordererOrg1.example.com'
    environment:
        - FABRIC_CA_SERVER_HOME=/usr/local/hyperledger/fabric-ca/crypto
        - FABRIC_CA_SERVER_TLS_ENABLED=true
        - FABRIC_CA_SERVER_CSR_CN=rca-ordererOrg1
        - FABRIC_CA_SERVER_CSR_HOSTS=0.0.0.0
        - FABRIC_CA_SERVER_DEBUG=true
        - FABRIC_CA_SERVER_PORT=7053
        - FABRIC_CA_SERVER_OPERATIONS_LISTENADDRESS=0.0.0.0:17055
        - TZ=Asia/Almaty
    volumes:
        - /usr/local/ordererOrg1/rca-ordererOrg1:/usr/local/hyperledger/fabric-ca
    networks:
        - fabric-ordererOrg1-ca
    ports:
        - 7053:7053

В файле мы также указываем пользователя и пароль, под которым будем выпускать сертификаты (tlsadmin, tlspwd, rcaadmin, rcapwd). Думаю, понятно, что эти значения нужно заменить на свои, также, как и dns имена rca.ordererOrg1.example.com, tls-ca.ordererOrg1.example.com.

После того, как файл создан можем приступать к запуску контейнеров с ЦС.

sudo docker-compose -f /usr/local/ordererOrg1/docker-compose.yaml up -d
sudo docker ps
a2d4c7e94316   hyperledger/fabric-ca:latest 0.0.0.0:7053->7053/tcp, :::7053->7053/tcp, 7054/tcp   rca-ordererOrg1
88810b59d9a8   hyperledger/fabric-ca:latest 0.0.0.0:7052->7052/tcp, :::7052->7052/tcp, 7054/tcp   tls-ordererOrg1

Также мы поступаем и со всеми остальными ЦС, просто меняем пароли и dns имена в файле docker-compose.yaml.

Данные корневого сертификата

При старте ЦС сгенерировали сами себе сертификаты, так как являются корневыми. Если вас что-то не устраивает в этих сертификатах, то можно это изменить. Тут каждый решает сам делать это или нет.

cd /usr/local/ordererOrg1
sudo vim rca-ordererOrg1/crypto/fabric-ca-server-config.yaml
sudo vim tls-ordererOrg1/crypto/fabric-ca-server-config.yaml

Например, можно изменить время жизни сертификата, чтобы не обновлять сертификаты каждый год.

'expiry: 8760h' >>>>> 'expiry: 87600h'
'expiry: 43800h' >>>>> 'expiry: 87600h'

Удаляем контейнеры, я добавил volumes а значит важные данные останутся.

sudo docker-compose -f /usr/local/ordererOrg1/docker-compose.yaml down
cd /usr/local/ordererOrg1/tls-ordererOrg1/crypto
sudo rm ca-cert.pem tls-cert.pem

И снова запускаем ЦС, сертификаты пересоздадутся.

sudo docker-compose -f /usr/local/ordererOrg1/docker-compose.yaml up -d
sudo docker ps

openssl x509 -in ca-cert.pem -text -noout | grep 'Not After'
Not After : Feb 25 11:16:00 2039 GMT

Выпускаем сертификат админа ЦС

Помните я говорил о том что в файле docker-compose.yaml задаётся логин и пароль? Так вот используя как раз этот логин и пароль мы получаем сертификат админа ЦС, который дальше будем использовать для генерации сертификатов другим узлам и пользователям в организации.

cd /usr/local/ordererOrg1/tls-ordererOrg1
sudo chown -R admin  /usr/local/ordererOrg1
sudo mkdir admin && cd admin

export FABRIC_CA_CLIENT_TLS_CERTFILES=../crypto/tls-cert.pem
export FABRIC_CA_CLIENT_HOME=.
fabric-ca-client enroll -d -u https://tlsadmin:tlspwd@tls-ca.ordererOrg1.example.com:7052

ls -la
-rwxr-xr-x. 1 admin admin 7173 Feb 29 17:40 fabric-ca-client-config.yaml
drwx------. 6 admin admin  122 Feb 29 17:40 msp

Тоже самое мы выполняем для rca-ca.ordererOrg1.example.com.

cd /usr/local/ordererOrg1/rca-ordererOrg1
sudo mkdir admin && cd admin
sudo chown -R admin  /usr/local/ordererOrg1

export FABRIC_CA_CLIENT_TLS_CERTFILES=../crypto/ca-cert.pem
export FABRIC_CA_CLIENT_HOME=.
fabric-ca-client enroll -d -u https://rcaadmin:rcapwd@rca.ordererOrg1.example.com:7053

ls -la
-rwxr-xr-x. 1 admin admin 7173 Feb 29 17:40 fabric-ca-client-config.yaml
drwx------. 6 admin admin  122 Feb 29 17:40 msp

Для всех остальных организаций (org1, org2) в таком же порядке выпускаем сертификаты для администраторов.

Регистрируем сертификаты

В статье про MSP и identity я писал для чего нужны сертификаты.

rca.ordererOrg1.example.com

Нам понадобятся сертификаты админа ЦС, которые мы выпускали выше поэтому. Каталог, в котором они хранятся передаётся через FABRIC_CA_CLIENT_HOME.

cd /usr/local/ordererOrg1/rca-ordererOrg1/admin

export caUrl=rca.ordererOrg1.example.com:7053
export FABRIC_CA_CLIENT_TLS_CERTFILES=../crypto/ca-cert.pem
export FABRIC_CA_CLIENT_HOME=.

fabric-ca-client register -d --id.name orderer1-ordererOrg1 --id.secret orderer1PWD --id.type orderer -u https://$caUrl
fabric-ca-client register -d --id.name orderer2-ordererOrg1 --id.secret orderer2PWD --id.type orderer -u https://$caUrl
fabric-ca-client register -d --id.name admin-ordererOrg1 --id.secret adminPWD --id.type admin -u https://$caUrl

tls-ca.ordererOrg1.example.com

cd /usr/local/ordererOrg1/tls-ordererOrg1/admin/

export caUrl=tls-ca.ordererOrg1.example.com:7052
export FABRIC_CA_CLIENT_TLS_CERTFILES=../crypto/ca-cert.pem
export FABRIC_CA_CLIENT_HOME=.

fabric-ca-client register -d --id.name orderer1-ordererOrg1 --id.secret orderer1PWD --id.type orderer -u https://$caUrl
fabric-ca-client register -d --id.name orderer2-ordererOrg1 --id.secret orderer2PWD --id.type orderer -u https://$caUrl
fabric-ca-client register -d --id.name admin-ordererOrg1 --id.secret adminPWD --id.type admin -u https://$caUrl

tls-ca.org1.example.com

Для организации org1 мы делаем тоже самое, только меняем id.type и еще добавляем пользователя user, от которого рекомендуется запускать функции смарт-контракта.

cd /usr/local/org1/tls-org1/admin/

export caUrl=tls-ca.org1.example.com:7052
export FABRIC_CA_CLIENT_TLS_CERTFILES=../crypto/ca-cert.pem
export FABRIC_CA_CLIENT_HOME=.

fabric-ca-client register -d --id.name peer1-org1 --id.secret peer1PWD --id.type peer -u https://$caUrl
fabric-ca-client register -d --id.name peer2-org1 --id.secret peer2PWD --id.type peer -u https://$caUrl
fabric-ca-client register -d --id.name admin-org1 --id.secret adminPWD --id.type admin -u https://$caUrl
fabric-ca-client register -d --id.name user-org1 --id.secret userPWD --id.type client -u https://$caUrl

Для организации org2 делаем тоже самое, конечно меняя имя организации с org1 на org2.

rca.org1.example.com

cd /usr/local/org1/rca-org1/admin

export caUrl=rca.org1.example.com:7053
export FABRIC_CA_CLIENT_TLS_CERTFILES=../crypto/ca-cert.pem
export FABRIC_CA_CLIENT_HOME=.

fabric-ca-client register -d --id.name peer1-org1 --id.secret peer1PWD --id.type peer -u https://$caUrl
fabric-ca-client register -d --id.name peer2-org1 --id.secret peer2PWD --id.type peer -u https://$caUrl
fabric-ca-client register -d --id.name admin-org1 --id.secret adminPWD --id.type admin -u https://$caUrl
fabric-ca-client register -d --id.name user-org1 --id.secret userPWD --id.type client -u https://$caUrl

Для организации org2 делаем тоже самое, конечно меняя имя организации с org1 на org2.

Выпускаем сертификаты

Для начала подготовим директории, в которые будем сохранять все необходимые сертификаты.

cd /usr/local/ordererOrg1
mkdir -p msp/{cacerts,tlscacerts} orderers/orderer{1,2} users/admin-ordererOrg1

Сертификаты для orderer

export FABRIC_CA_CLIENT_TLS_CERTFILES=/usr/local/ordererOrg1/tls-ordererOrg1/admin/msp/cacerts/tls-ca-ordererOrg1-example-com-7052.pem
export FABRIC_CA_CLIENT_HOME=/usr/local/ordererOrg1/orderers/orderer1.ordererOrg1.example.com
export FABRIC_CA_CLIENT_MSPDIR=tls-msp
export caUrl=tls-ca.ordererOrg1.example.com:7052

fabric-ca-client enroll -d -u https://orderer1-ordererOrg1:orderer1PWD@$caUrl --enrollment.profile tls --csr.hosts orderer1.ordererOrg1.example.com --csr.hosts orderer1.ordererOrg1 --csr.hosts localhost

export FABRIC_CA_CLIENT_HOME=/usr/local/ordererOrg1/orderers/orderer2.ordererOrg1.example.com
fabric-ca-client enroll -d -u https://orderer2-ordererOrg1:orderer2PWD@$caUrl --enrollment.profile tls --csr.hosts orderer2.ordererOrg1.example.com --csr.hosts orderer2.ordererOrg1 --csr.hosts localhost

export FABRIC_CA_CLIENT_HOME=/usr/local/ordererOrg1/users/admin-ordererOrg1
fabric-ca-client enroll -d -u https://admin-ordererOrg1:adminPWD@$caUrl --enrollment.profile tls

export FABRIC_CA_CLIENT_TLS_CERTFILES=/usr/local/ordererOrg1/rca-ordererOrg1/admin/msp/cacerts/rca-ordererOrg1-example-com-7053.pem
export FABRIC_CA_CLIENT_MSPDIR=msp
export caUrl=rca.ordererOrg1.example.com:7053
export FABRIC_CA_CLIENT_HOME=/usr/local/ordererOrg1/orderers/orderer1.ordererOrg1.example.com

fabric-ca-client enroll -d -u https://orderer1-ordererOrg1:orderer1PWD@$caUrl

export FABRIC_CA_CLIENT_HOME=/usr/local/ordererOrg1/orderers/orderer2.ordererOrg1.example.com
fabric-ca-client enroll -d -u https://orderer2-ordererOrg1:orderer2PWD@$caUrl

export FABRIC_CA_CLIENT_HOME=/usr/local/ordererOrg1/users/admin-ordererOrg1
fabric-ca-client enroll -d -u https://admin-ordererOrg1:adminPWD@$caUrl

По умолчанию некоторые сертификаты имеют не особо удобочитаемый формат. Поэтому переименуем их для удобства.

cd /usr/local/ordererOrg1
cp orderers/orderer1.ordererOrg1.example.com/tls-msp/tlscacerts/tls-tls-ca-ordererOrg1-example-com-7052.pem orderers/orderer1.ordererOrg1.example.com/tls-msp/tlscacerts/tls-ca-cert.pem
cp orderers/orderer2.ordererOrg1.example.com/tls-msp/tlscacerts/tls-tls-ca-ordererOrg1-example-com-7052.pem orderers/orderer2.ordererOrg1.example.com/tls-msp/tlscacerts/tls-ca-cert.pem

cp orderers/orderer1.ordererOrg1.example.com/tls-msp/keystore/f0b1b8b10a3017a5f5c52a4f0d19bef23f5811036102c61b0c4d19cf36836b88_sk orderers/orderer1.ordererOrg1.example.com/tls-msp/keystore/tls-key.pem
cp orderers/orderer2.ordererOrg1.example.com/tls-msp/keystore/71d960ff3dad8dc1c8148e1d618f41c85474a40135d4886f416631458acf6fea_sk orderers/orderer2.ordererOrg1.example.com/tls-msp/keystore/tls-key.pem

cp orderers/orderer1.ordererOrg1.example.com/msp/cacerts/rca-ordererOrg1-example-com-7053.pem orderers/orderer1.ordererOrg1.example.com/msp/cacerts/ca-cert.pem
cp orderers/orderer2.ordererOrg1.example.com/msp/cacerts/rca-ordererOrg1-example-com-7053.pem orderers/orderer2.ordererOrg1.example.com/msp/cacerts/ca-cert.pem

cp orderers/orderer1.ordererOrg1.example.com/msp/keystore/2806edd93b6fde172553c93a463a3f44e814f3dc6d547cf60d868a71cc16ff7a_sk orderers/orderer1.ordererOrg1.example.com/msp/keystore/key.pem
cp orderers/orderer2.ordererOrg1.example.com/msp/keystore/0e19f9860d55f1de8ae22b72fba32ad43def7a48c22532c86c1c930ab10be3d3_sk orderers/orderer2.ordererOrg1.example.com/msp/keystore/key.pem

Также нужно будет скопировать сертификаты ЦС в одну директорию, msp директорию всех организаций собираются в одном месте чтобы создать нулевой блок канала. Не беспокойтесь там только публичные сертификаты.

cd /usr/local/ordererOrg1
cp orderers/orderer1.ordererOrg1.example.com/msp/cacerts/ca-cert.pem msp/cacerts/ca-cert.pem
cp orderers/orderer1.ordererOrg1.example.com/tls-msp/tlscacerts/tls-ca-cert.pem msp/tlscacerts/tls-ca-cert.pem

Сертификаты для peer

Таким же способом мы выпускаем все сертификаты для других организаций.

Создаём файл config.yaml

Если не понятно зачем он нужен, то можно почитать про MSP.

vim orderers/orderer1.ordererOrg1.example.com/msp/config.yaml
NodeOUs:
  Enable: true
  ClientOUIdentifier:
    Certificate: cacerts/ca-cert.pem
    OrganizationalUnitIdentifier: client
  PeerOUIdentifier:
    Certificate: cacerts/ca-cert.pem
    OrganizationalUnitIdentifier: peer
  AdminOUIdentifier:
    Certificate: cacerts/ca-cert.pem
    OrganizationalUnitIdentifier: admin
  OrdererOUIdentifier:
    Certificate: cacerts/ca-cert.pem
    OrganizationalUnitIdentifier: orderer
cp orderers/orderer1.ordererOrg1.example.com/msp/config.yaml orderers/orderer2.ordererOrg1.example.com/msp/config.yaml
cp orderers/orderer1.ordererOrg1.example.com/msp/config.yaml msp/

Эту процедуру нужно будет сделать и для всех других организаций, например:

cd /usr/local/org1
cp peers/peer1/msp/config.yaml peers/peer2/msp/config.yaml
cp eers/peer1/msp/config.yaml msp/

Теперь всё готово для запуска узлов организаций.