diff --git a/AWS-CloudHSM/Dockerfile b/AWS-CloudHSM/Dockerfile new file mode 100644 index 0000000..31c7374 --- /dev/null +++ b/AWS-CloudHSM/Dockerfile @@ -0,0 +1,61 @@ +########## Build the pkcs11 proxy ########## +FROM registry.access.redhat.com/ubi8/ubi-minimal as builder +ARG ARCH=amd64 + +ARG VERSION=2032875 + +RUN microdnf install -y \ + git \ + make \ + cmake \ + openssl-devel \ + libseccomp-devel \ + gcc; + +RUN git clone https://github.com/SUNET/pkcs11-proxy && \ + cd pkcs11-proxy && \ + git checkout ${VERSION} && \ + cmake . && \ + make && \ + make install; + +# proxy with CloudHSM client +FROM registry.access.redhat.com/ubi8/ubi-minimal +ARG ARCH=amd64 + +RUN microdnf update -y \ + && microdnf install -y \ + libedit \ + make \ + ncurses-compat-libs \ + python36 \ + shadow-utils; + +# install dependencies not available in ubi stream +RUN if [ "${ARCH}" == "amd64" ]; then ARCH="x86_64"; fi \ + && rpm -ivh https://kojipkgs.fedoraproject.org/packages/compat-openssl10/1.0.2o/5.fc30/${ARCH}/compat-openssl10-1.0.2o-5.fc30.${ARCH}.rpm; + + +# install AWS CloudHSM client +RUN rpm -ivh https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL7/cloudhsm-client-latest.el7.x86_64.rpm \ + && rpm -ivh https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL7/cloudhsm-client-pkcs11-latest.el7.x86_64.rpm; + +RUN chown -R hsmuser:hsmuser /opt/cloudhsm/etc + +RUN ln -s /usr/lib64/libjson-c.so.4 usr/lib64/libjson-c.so.2; +RUN ln -s /usr/bin/python3 /usr/bin/python + +# copy daemon from builder +COPY --from=builder /usr/local/bin/pkcs11-daemon /usr/local/bin/pkcs11-daemon + +# pkcs-daemon listen port +ENV PKCS11_DAEMON_SOCKET tcp://0.0.0.0:2345 +# pkcs11 library +ENV LIBRARY_LOCATION /opt/cloudhsm/lib/libcloudhsm_pkcs11.so + +EXPOSE 2345 + +ADD docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +ENTRYPOINT [ "/usr/local/bin/docker-entrypoint.sh" ] + +CMD [ "pkcs11-daemon", "/opt/cloudhsm/lib/libcloudhsm_pkcs11.so", "-"] \ No newline at end of file diff --git a/AWS-CloudHSM/Dockerfile.ubi7 b/AWS-CloudHSM/Dockerfile.ubi7 new file mode 100644 index 0000000..c309dfe --- /dev/null +++ b/AWS-CloudHSM/Dockerfile.ubi7 @@ -0,0 +1,52 @@ +FROM registry.access.redhat.com/ubi7 as builder + +# add centos repo +ADD centos7.repo /etc/yum.repos.d/centos.repo + +RUN yum -y update; + +RUN yum install -y \ + gcc \ + make \ + cmake \ + git \ + libseccomp-devel \ + openssl-devel; + +# build and install pkcs11-proxy +RUN git clone https://github.com/SUNET/pkcs11-proxy.git \ + && cd pkcs11-proxy \ + && cmake . \ + && make \ + && make install; + +# proxy image +FROM registry.access.redhat.com/ubi7 + +# add centos repo +ADD centos7.repo /etc/yum.repos.d/centos.repo + +RUN yum -y update; + +RUN yum install -y \ + libseccomp \ + libedit \ + scl-utils \ + rh-python36; + +# copy proxy +COPY --from=builder /usr/local/bin/pkcs11-daemon /usr/local/bin/pkcs11-daemon + +# install AWS cloudhsm client +RUN rpm -ivh https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL7/cloudhsm-client-latest.el7.x86_64.rpm \ + && rpm -ivh https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL7/cloudhsm-client-pkcs11-latest.el7.x86_64.rpm; + +ENV PATH /opt/rh/rh-python36/root/usr/bin:$PATH +ENV PKCS11_DAEMON_SOCKET tcp://0.0.0.0:2345 + +# add entrypoint +ADD docker-entrypoint-ubi7.sh /usr/local/bin/docker-entrypoint.sh +ENTRYPOINT [ "/usr/local/bin/docker-entrypoint.sh" ] + +CMD [ "pkcs11-daemon", "/opt/cloudhsm/lib/libcloudhsm_pkcs11.so", "-"] + diff --git a/AWS-CloudHSM/README.md b/AWS-CloudHSM/README.md new file mode 100644 index 0000000..c7d9ef7 --- /dev/null +++ b/AWS-CloudHSM/README.md @@ -0,0 +1,87 @@ +# PKCS#11 proxy deployment instructions for AWS CloudHSM +In order for your IBM Blockchain Platform (IBP) nodes to leverage an AWS CloudHSM to manage their enrollment private keys, they must be configured to communicate with the PKCS#11 interface provided by the AWS CloudHSM. While you can modify the Docker images provided by IBP to include the appropriate PKCS#11 library, this README describes how to build a PKCS#11 proxy image which communicates with the AWS CloudHSM. IBP nodes include the PKCS#11 library required to communicate with the PKCS#11 proxy. The path to this library within each container image is `/usr/local/lib/libpkcs11-proxy.so`. + +## Before you begin + +- You will need to provision and configure an AWS CloudHSM using the AWS documentation. You will need the following artifacts from your AWS CloudHSM deployment: + - `customerCA.crt` which was used to sign the cluster CSR + - `ENI (elastic network interface) IP` for one of the HSMs in your cluster. This can be obtained by using the `describe-clusters` command using the AWS CLI + - Username and password for an HSM user with the CU (crypto user) role +- You will need an environment in which you can build Docker images. + +## Build the PKCS#11 proxy image + +This repository has a [`Dockerfile`](./Dockerfile) which can be used to build an image which runs a **PKCS#11 proxy daemon (pkcs11-daemon)** as well as the **AWS cloudhsm_client** process. The proxy daemon uses the AWS CloudHSM PKCS#11 library to communicate with AWS CloudHSM. + +The Docker image is based on [Red Hat Universal Base Image (ubi)](https://access.redhat.com/containers/#/registry.access.redhat.com/ubi8/ubi-minimal) but also includes packages from Fedora 30 which are required by the AWS CloudHSM client and PKCS#11 library but are not availabie in the ubi stream. It uses [docker-entrypoint.sh](./docker-entrypoint.sh) to configure the AWS CloudHSM client and start the `cloudhsm_client` process in the background. The `pkcs11-daemon` is started in the foreground and is configured to run on port `2345` and the image also exposes this port externally. + +To build the images, run the following command in the root directory of this repository: + +``` +docker build -t pkcs11-proxy-cloudhsm . +``` + +If you plan to use this image on a remote Docker host or orchestration environment such as Kubernetes, you will need to push this image to a Docker registry which is accessible from the chosen environment: + +``` +docker login ${REGISTRY_URL} +docker tag pkcs11-proxy-cloudhsm ${REGISTRY_URL}/pkcs11-proxy-cloudhsm +docker login ${REGISTRY_URL} +docker push ${REGISTRY_URL}/pkcs11-proxy-cloudhsm +``` + +## Deploying the PKCS#11 proxy image + +Two inputs are required when launching **pkcs11-proxy-cloudhsm** image created above as a container: +- An environment variable named **`CLOUDHSM_ENI_IP`** set to the **ENI IP** of the HSM cluster. +- **`customerCA.crt`** mounted as `/opt/cloudhsm/etc/customerCA.crt`. + +### Running the proxy on Docker engine + +To start a container using Docker, run the following command: +``` +docker run -e "CLOUDHSM_ENI_IP=${ENI IP}" -v ${CUSTOMERCAPATH}/customerCA.crt:/opt/cloudhsm/etc/customerCA.crt ${REGISTRY_URL}/pkcs11-proxy-cloudhsm +``` +For example, assuming `customerCA.crt` is in your current directory and your ENI IP is 10.0.0.2, you would run: +``` +docker run -e "CLOUDHSM_ENI_IP=10.0.0.2" -v $PWD/customerCA.crt:/opt/cloudhsm/etc/customerCA.crt ${REGISTRY_URL}/pkcs11-proxy-cloudhsm +``` + +### Deploying to Kubernetes + +**COMING SOON** + +## Configuring the IBM Blockchain images to use the PKCS#11 proxy + +The IBM Blockchain peer, orderer and CA images include built-in support for connecting to the PKCS#11 proxy. The PKCS#11 driver used to communicate with the proxy is installed in each image in the following location: `/usr/local/lib/libpkcs11-proxy.so`. + +This section will cover running the IBM Blockchain Platform images on three environments: + +- IBM Blockchain Platform +- Kubernetes +- Docker engine + + +### Running the IBM Blockchain images on Docker engine + + + +In order to communicate with the PKCS#11 proxy, two items must be configured when launching a peer, orderer and/or CA container: +- An environment variable named **`PKCS11_PROXY_SOCKET`** must be set to a URL of the form `tcp://${HOSTIP}:2345` where `${HOSTIP}` represents the routable address for a running PKCS#11 proxy container. +- The `bccsp` section of the configuration file for each peer (`core.yaml`), orderer (`orderer.yaml`) and/or CA (`fabric-ca-server-config.yaml`) must be configured to use the `pkcs11` cryptographic provider as follows: + ``` + BCCSP: + Default: PKCS11 + PKCS11: + # Location of the PKCS11 module library + Library: /usr/local/lib/libpkcs11-proxy.so + # Alternate ID + AltId: ${ALT_ID} + # User PIN + Pin: ${HSM_USER}:${HSM_PASSWORD} + Hash: SHA2 + Security: 256 + ``` + where `${ALT_ID}` is the PKCS#11 label for the key and `${HSM_USER}` and `${HSM_PASSWORD}` are the credentials for an HSM user with the CU role. + + Note: If you intend to have the Fabric CA or the Fabric CA client generate the private key for you, then you should specify a unique, secure string for ${ALT_ID} as this will be used to set the PKCS#11 label \ No newline at end of file diff --git a/AWS-CloudHSM/centos7.repo b/AWS-CloudHSM/centos7.repo new file mode 100644 index 0000000..e9b86b5 --- /dev/null +++ b/AWS-CloudHSM/centos7.repo @@ -0,0 +1,6 @@ +[centos] +name=CentOS-7 +baseurl=http://ftp.heanet.ie/pub/centos/7/os/x86_64/ +enabled=1 +gpgcheck=1 +gpgkey=http://ftp.heanet.ie/pub/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7 \ No newline at end of file diff --git a/AWS-CloudHSM/docker-entrypoint-ubi7.sh b/AWS-CloudHSM/docker-entrypoint-ubi7.sh new file mode 100755 index 0000000..915ddad --- /dev/null +++ b/AWS-CloudHSM/docker-entrypoint-ubi7.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# create the AWS CloudHSM client config +scl enable rh-python36 -- /opt/cloudhsm/bin/configure -a ${CLOUDHSM_ENI_IP} + +# start CloudHSM client +echo -n "* Starting CloudHSM client ... " +/opt/cloudhsm/bin/cloudhsm_client /opt/cloudhsm/etc/cloudhsm_client.cfg &> /tmp/cloudhsm_client_start.log & + +# wait for CloudHSM client to be ready +while true +do + if grep 'libevmulti_init: Ready !' /tmp/cloudhsm_client_start.log &> /dev/null + then + echo "[OK]" + break + fi + sleep 0.5 +done +echo -e "\n* CloudHSM client started successfully ... \n" + +exec "$@" \ No newline at end of file diff --git a/AWS-CloudHSM/docker-entrypoint.sh b/AWS-CloudHSM/docker-entrypoint.sh new file mode 100755 index 0000000..041ec4e --- /dev/null +++ b/AWS-CloudHSM/docker-entrypoint.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# create the AWS CloudHSM client config +/opt/cloudhsm/bin/configure -a ${CLOUDHSM_ENI_IP} + +# start CloudHSM client +echo -n "* Starting CloudHSM client ... " +/opt/cloudhsm/bin/cloudhsm_client /opt/cloudhsm/etc/cloudhsm_client.cfg &> /tmp/cloudhsm_client_start.log & + +# wait for CloudHSM client to be ready +while true +do + if grep 'libevmulti_init: Ready !' /tmp/cloudhsm_client_start.log &> /dev/null + then + echo "[OK]" + break + fi + sleep 0.5 +done +echo -e "\n* CloudHSM client started successfully ... \n" + +exec "$@" \ No newline at end of file