This article demonstrates how you can use a crypto.Signer
implementation i wrote some years ago to make an mTLS connection using a private key that exists only in GCP KMS.
Basically, you will create a KMS key that is enabled for RSA-PSS
Signing.
We will then issue a Certificate Signing Request (csr) using the private key to sign the request.
From there, we have a local Certificate Authority that will issue the x509 cert for the client.
We will then run an https server that requires client certificates issued by that same CA
The client will use the client x509 and KMS private key reference to establish an mTLS connection to the server.
You can find the source here
this repo is not supported by google
For more information, see
First create a KMS key
export GCLOUD_USER=`gcloud config get-value core/account`
gcloud kms keyrings create tlskr --location=global
gcloud kms keys create k1 --keyring=tlskr \
--location=global --purpose=asymmetric-signing \
--default-algorithm=rsa-sign-pss-2048-sha256
gcloud kms keys add-iam-policy-binding k1 \
--keyring=tlskr --location=global \
--member=user:$GCLOUD_USER --role=roles/cloudkms.signer
gcloud kms keys add-iam-policy-binding k1 \
--keyring=tlskr --location=global \
--member=user:$GCLOUD_USER --role=roles/cloudkms.viewer
$ gcloud kms keys list --keyring=tlskr --location=global
NAME PURPOSE ALGORITHM PROTECTION_LEVEL
projects/PROJECT/locations/global/keyRings/tlskr/cryptoKeys/k1 ASYMMETRIC_SIGN RSA_SIGN_PSS_2048_SHA256 SOFTWARE
recall the public key (your’s will ofcourse be different)
$ gcloud kms keys versions get-public-key 1 --key=k1 --keyring=tlskr --location=global
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzHdXnqlUgvFlTaAXBMAU
cxi74Vfb0tA7Pn/356xIqB820t6bSRmCutPOnHUYz02piNFJP2Vx+HKiqmT3S7jy
Yv6xPWxGfOHmKbwl8UkMzOdPtTyMLk11TSGA0Wgar9e/chU1UxH1Rk9sQ5CG8xBK
7ToGGIn0fxBvyWeAucsgn3PONuuqrKsTfW/hckyk866oI8e8C7+XWrbtM6gBt4/U
Z2OiF/QfdoXB4oBFLi+NHkLdYBk0pM6R/xaXCGUchLQkfw6MdD68MvfNVSY7YIuy
g5ZIrWFQzSptCtn4mF9CLooRK/2d360d9hsCUybCTRAw6D8Ra27aVS5+Vl+lajxu
JQIDAQAB
-----END PUBLIC KEY-----
now create a CSR:
export PROJECT_ID=`gcloud config get-value core/project`
cd csr/
go run main.go --projectID=$PROJECT_ID --cn client.domain.com --filename ../certs/client.csr
Then initialize the CA using the certificate authority here (you can create you own CA here).
cd certs/
rm -rf /tmp/kmsca
mkdir -p /tmp/kmsca
cp /dev/null /tmp/kmsca/tls-ca.db
cp /dev/null /tmp/kmsca/tls-ca.db.attr
echo 01 > /tmp/kmsca/tls-ca.crt.srl
echo 01 > /tmp/kmsca/tls-ca.crl.srl
openssl ca \
-config tls-ca.conf \
-in client.csr \
-out client.crt \
-extensions client_ext
You can also confirm the certificate has the same public key from KMS
$ openssl x509 -pubkey -noout -in client.crt
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzHdXnqlUgvFlTaAXBMAU
cxi74Vfb0tA7Pn/356xIqB820t6bSRmCutPOnHUYz02piNFJP2Vx+HKiqmT3S7jy
Yv6xPWxGfOHmKbwl8UkMzOdPtTyMLk11TSGA0Wgar9e/chU1UxH1Rk9sQ5CG8xBK
7ToGGIn0fxBvyWeAucsgn3PONuuqrKsTfW/hckyk866oI8e8C7+XWrbtM6gBt4/U
Z2OiF/QfdoXB4oBFLi+NHkLdYBk0pM6R/xaXCGUchLQkfw6MdD68MvfNVSY7YIuy
g5ZIrWFQzSptCtn4mF9CLooRK/2d360d9hsCUybCTRAw6D8Ra27aVS5+Vl+lajxu
JQIDAQAB
-----END PUBLIC KEY-----
Now run the TLS Server
cd example/
go run server/main.go
cd example
go run client/client.go --projectID $PROJECT_ID
Once you connect, the server will show the peer certificate’s public key it recieved….and surprise, its
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzHdXnqlUgvFlTaAXBMAU
cxi74Vfb0tA7Pn/356xIqB820t6bSRmCutPOnHUYz02piNFJP2Vx+HKiqmT3S7jy
Yv6xPWxGfOHmKbwl8UkMzOdPtTyMLk11TSGA0Wgar9e/chU1UxH1Rk9sQ5CG8xBK
7ToGGIn0fxBvyWeAucsgn3PONuuqrKsTfW/hckyk866oI8e8C7+XWrbtM6gBt4/U
Z2OiF/QfdoXB4oBFLi+NHkLdYBk0pM6R/xaXCGUchLQkfw6MdD68MvfNVSY7YIuy
g5ZIrWFQzSptCtn4mF9CLooRK/2d360d9hsCUybCTRAw6D8Ra27aVS5+Vl+lajxu
JQIDAQAB
-----END PUBLIC KEY-----
If you enabled auditlogs for KMS, you will see both the csr and client request a sign API request on either side to establish the mTLS connection
Well…yeah, there is some and thats one of the biggest reasons this is a bit academic. I ran this setup a couple times and saw that the API calls from my laptop to establish just a TLS connection using one KMS key added on about 150ms
…This would be faster on a compute engine or on GKE on cloud though…but its still a lot.
This site supports webmentions. Send me a mention via this form.