This example uses openssl
utility to generate custom CA and signs
web3signer and client certs and shows how to setup Web3Signer with them.
The keytool
example can be seen here.
openssl genrsa -out root_ca.key 4096
Create root CSR and self-sign (Modify CN as per your requirements).
openssl req -x509 -nodes -sha256 -new -key root_ca.key -out root_ca.crt -days 1024 \
-subj "/CN=root.mycompany.com" \
-addext "keyUsage = critical, keyCertSign" \
-addext "basicConstraints = critical, CA:TRUE, pathlen:0" \
-addext "subjectKeyIdentifier = hash"
The Web3Signer certificate CN should be the hostname where web3signer is hosted. In this example, I am using localhost. The san extension should be used to specify the all the hostnames and IP addresses from which Web3Signer is served. Modify following commands according to your requirements.
Generate key pair
openssl genrsa -out web3signer.key 2048
Create openssl configuration for web3signer
cat <<EOF >./server_openssl.conf
$(cat /etc/ssl/openssl.cnf)
[SAN]
subjectAltName=DNS:localhost,DNS:www.localhost,IP:127.0.0.1
EOF
Create CSR (Modify -subj
as per your requirements.)
openssl req -new -sha256 \
-key web3signer.key \
-subj "/C=AU/ST=QLD/O=Consensys/OU=Protocols/CN=localhost" \
-reqexts SAN \
-config ./server_openssl.conf \
-out web3signer.csr
Verify the CSR
openssl req -in web3signer.csr -noout -text
Create openssl configuration for signing web3signer. Modify Subject Alt Names accordingly.
cat << EOF >./web3signer_san_openssl.conf
[req]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[req_distinguished_name]
countryName = AU
stateOrProvinceName = QLD
organizationName = Consensys
commonName = localhost
[req_ext]
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
basicConstraints = CA:FALSE
authorityKeyIdentifier = keyid:always
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = www.localhost
IP.1 = 127.0.0.1
IP.2 = 10.0.0.1
EOF
openssl x509 -req -in web3signer.csr -CA ./root_ca.crt -CAkey ./root_ca.key \
-CAcreateserial -out web3signer.crt -days 500 -sha256 \
-extfile web3signer_san_openssl.conf -extensions req_ext
Verify crt
openssl x509 -in web3signer.crt -text -noout
Now that we have signed certificates, we need to convert it to PKCS12 so that it can be used by Web3Signer.
Using password 123456
.
openssl pkcs12 -export \
-certfile root_ca.crt \
-inkey web3signer.key \
-in web3signer.crt \
-out web3signer_keystore.p12
Verify pkcs12 keystore
openssl pkcs12 -info -in web3signer_keystore.p12
web3signer_keystore.p12
now contains full CA chain as well as signed certificate. Time to get Web3Signer start with TLS enabled.
In the following example, Web3Signer is using tls-allow-any-client: true
.
mkdir -p ./config/keys
cp ./web3signer_keystore.p12 ./config
cat <<EOF >./config/password.txt
123456
EOF
cat <<EOF >./config/config.yaml
http-listen-host: "0.0.0.0"
http-listen-port: 9000
http-host-allowlist: "*"
key-store-path: /var/config/keys
# tls options
tls-keystore-file: /var/config/web3signer_keystore.p12
tls-keystore-password-file: /var/config/password.txt
# tls-known-clients-file: /var/config/knownClients.txt
tls-allow-any-client: true
# eth2 subcommand options
eth2.slashing-protection-enabled: false
EOF
cat <<EOF >./docker-compose.yaml
version: "3.9"
services:
web3signer:
image: consensys/web3signer:develop
command: --config-file=/var/config/config.yaml eth2
volumes:
- ./config:/var/config
ports:
- "9000:9000"
EOF
docker compose up
...
tlscerts-web3signer-1 | 2023-01-17 02:52:59.659+00:00 | pool-2-thread-1 | INFO | DefaultArtifactSignerProvider | Total signers (keys) currently loaded in memory: 0
tlscerts-web3signer-1 | 2023-01-17 02:53:00.140+00:00 | main | INFO | Runner | Web3Signer has started with TLS enabled, and ready to handle signing requests on 0.0.0.0:9000
» curl --cacert ./root_ca.crt https://localhost:9000/upcheck
OK%
Following scenario means that client will present its certificate to web3Signer for mutual TLS authentication. Hence Web3Signer needs to add the client's certificate fingerprint in the known clients.
This example will be using curl
utility to connect to web3signer. Hence the file names are named curl.crt
and curl.key
accordingly.
openssl genrsa -out curl.key 2048
Create openssl configuration for client
cat <<EOF >./curl_openssl.conf
$(cat /etc/ssl/openssl.cnf)
[SAN]
subjectAltName=DNS:localhost,IP:127.0.0.1
EOF
Create the CSR. Note that the value of client CN will be used by Web3Signer in its knownClients.txt
file later on.
openssl req -new -sha256 \
-key curl.key \
-subj "/CN=curl" \
-reqexts SAN \
-config ./curl_openssl.conf \
-out curl.csr
Verify CSR
openssl req -in curl.csr -noout -text
Create openssl configuration for client (curl) certificate. Make sure to note commonName
as it
will be used by Web3Signer later on in knownClients.txt
file.
cat << EOF >./curl_san_openssl.conf
[req]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[req_distinguished_name]
countryName = AU
stateOrProvinceName = QLD
organizationName = Consensys
commonName = curl
[req_ext]
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
basicConstraints = CA:FALSE
authorityKeyIdentifier = keyid:always
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = www.localhost
IP.1 = 127.0.0.1
EOF
openssl x509 -req -in curl.csr -CA ./root_ca.crt -CAkey ./root_ca.key \
-CAcreateserial -out curl.crt -days 500 -sha256 \
-extfile curl_san_openssl.conf -extensions req_ext
Verify crt
openssl x509 -in curl.crt -text -noout
Client certificate fingerprint. This will be used later on by Web3Signer knownClients.txt
file.
The actual value might be different in your example.
openssl x509 -in curl.crt -noout -fingerprint
SHA256 Fingerprint=77:3E:E6:5F:47:92:33:FA:94:EF:15:79:3C:1C:14:D1:91:D8:8F:4C:C7:83:D7:CA:29:88:E5:81:44:5F:23:38
cat <<EOF >./config/knownClients.txt
curl 77:3E:E6:5F:47:92:33:FA:94:EF:15:79:3C:1C:14:D1:91:D8:8F:4C:C7:83:D7:CA:29:88:E5:81:44:5F:23:38
EOF
Modify Web3Signer's config file so that it uses the knownClients.txt
file and
commented out tls-allow-any-client
(or set it to false).
The tls options should look like:
...
# tls options
tls-keystore-file: /var/config/web3signer_keystore.p12
tls-keystore-password-file: /var/config/password.txt
tls-known-clients-file: /var/config/knownClients.txt
# tls-allow-any-client: true
...
docker compose up
curl --cacert ./root_ca.crt \
--cert ./curl.crt \
--key ./curl.key \
https://localhost:9000/upcheck