Skip to content

Conversation

@thelabdude
Copy link
Contributor

@thelabdude thelabdude commented Apr 13, 2021

The most expedient approach is to supply a client cert and key via a TLS secret to the operator during deployment to use to identify itself to Solr pods with mTLS enabled. Additionally, if the Certificate Authority (CA) for the Solr certs is not inherently trusted, users may also need to supply the CA’s cert PEM to the operator via another secret.

With this approach, either the client cert used by the operator or the CA’s cert must be in the truststore used by the Solr pods. Just trusting the CA cert is the most flexible, but also implies any client cert signed by that CA will be accepted by Solr, so may be too open for some users.

However, this means all Solr clusters managed by the same operator instance need to trust the client cert used by the operator. In other words, there’s only 1 client cert used by an operator instance. Feels a bit cumbersome to try to support many different certs, but perhaps that can be a future enhancement?

Here’s a script to set up the certs and a custom CA for testing mTLS. Save this script in a directory named solr-mTLS and run it (it will create several sub-directories holding various cert related files):

mkdir root-ca
mkdir server

STOREPASS="secret"
KEYPASS="secret"

# create the CA
keytool -v -genkeypair -dname "CN=Root-CA,OU=CertificateAuthority,O=dev,C=US" \
  -keystore root-ca/identity.p12 -deststoretype pkcs12 \
  -storepass ${STOREPASS} -keypass ${KEYPASS} \
  -keyalg RSA -keysize 2048 \
  -alias root-ca -validity 3650 \
  -ext KeyUsage=digitalSignature,keyCertSign \
  -ext BasicConstraints=ca:true,PathLen:3

# create the server cert
keytool -v -genkeypair -dname "CN=Solr,OU=Test,O=dev,C=US" \
  -keystore server/identity.p12 -deststoretype pkcs12 \
  -storepass ${STOREPASS} \
  -keypass ${KEYPASS} \
  -keyalg RSA -keysize 2048 -alias server -validity 3650 \
  -ext KeyUsage=digitalSignature,dataEncipherment,keyEncipherment,keyAgreement \
  -ext ExtendedKeyUsage=serverAuth,clientAuth \
  -ext SubjectAlternativeName:c=DNS:localhost,IP:127.0.0.1

# create the CSR for the server cert
keytool -v -certreq -file server/server.csr -keystore server/identity.p12 \
  -alias server -keypass ${KEYPASS} -storepass ${STOREPASS} -keyalg rsa

keytool -v -gencert -infile server/server.csr -outfile server/server-signed.cer \
  -keystore root-ca/identity.p12 -storepass ${STOREPASS} -alias root-ca \
  -ext KeyUsage=digitalSignature,dataEncipherment,keyEncipherment,keyAgreement \
  -ext ExtendedKeyUsage=serverAuth,clientAuth \
  -ext SubjectAlternativeName:c=DNS:localhost,IP:127.0.0.1

keytool -v -exportcert -file root-ca/root-ca.pem -alias root-ca -keystore root-ca/identity.p12 -storepass ${STOREPASS} -rfc
keytool -v -importcert -file root-ca/root-ca.pem -alias root-ca -keystore server/identity.p12 -storepass ${STOREPASS} -noprompt
keytool -v -importcert -file server/server-signed.cer -alias server -keystore server/identity.p12 -storepass ${STOREPASS}

kubectl delete secret my-pkcs12-cert
kubectl create secret generic my-pkcs12-cert --from-literal=password-key=secret --from-file=keystore.p12=./server/identity.p12

# client side
mkdir client

keytool -v -genkeypair -dname "CN=client,OU=self,O=dev,C=US" \
  -keystore client/identity.p12 -deststoretype pkcs12 \
  -storepass ${STOREPASS} -keypass ${KEYPASS} -keyalg RSA \
  -keysize 2048 -alias client -validity 3650 \
  -ext KeyUsage=digitalSignature,dataEncipherment,keyEncipherment,keyAgreement \
  -ext ExtendedKeyUsage=serverAuth,clientAuth

keytool -v -certreq -file client/client.csr -keystore client/identity.p12 \
  -alias client -storepass ${STOREPASS} -keypass ${KEYPASS} -keyalg rsa

keytool -v -gencert -infile client/client.csr \
  -outfile client/client-signed.cer \
  -keystore root-ca/identity.p12 -storepass ${STOREPASS} \
  -alias root-ca \
  -ext KeyUsage=digitalSignature,dataEncipherment,keyEncipherment,keyAgreement \
  -ext ExtendedKeyUsage=serverAuth,clientAuth

keytool -v -importcert -file root-ca/root-ca.pem -alias root-ca -keystore client/identity.p12 -storepass ${STOREPASS} -noprompt
keytool -v -importcert -file client/client-signed.cer -alias client -keystore client/identity.p12 -storepass ${STOREPASS}

keytool -v -exportcert -file client/client.pem \
  -alias client \
  -keystore client/identity.p12 \
  -storepass ${STOREPASS} \
  -storetype PKCS12 -rfc

# get the pem's for the TLS secret
openssl pkcs12 -in client/identity.p12 -nodes -nocerts -out client/private_key.pem -password pass:${STOREPASS}

kubectl delete secret my-client-cert
kubectl delete secret my-client-ca-cert

kubectl create secret tls my-client-cert --cert=client/client.pem --key=client/private_key.pem
kubectl create secret generic my-client-ca-cert --from-file=ca-cert-pem=./root-ca/root-ca.pem

Here are the notable config settings you need to make this work.

Operator Helm chart settings (referenced secrets created in script above ^^):

helm upgrade --install solr-operator helm/solr-operator \
  --set-string image.repository=dev/solr-operator  \
  --set-string image.pullPolicy=Never \
  --set-string image.tag=latest \
  --set zookeeper-operator.install=false \
  --set zookeeper-operator.use=true \
  --set mTLS.clientCertSecret=my-client-cert \
  --set mTLS.caCertSecret=my-client-ca-cert \
  --set mTLS.caCertSecretKey=ca-cert-pem

SolrCloud CRD YAML (secrets created in script above ^^):

  solrTLS:
    clientAuth: Need
    keyStorePasswordSecret:
      name: my-pkcs12-cert
      key: password-key
    pkcs12Secret:
      name: my-pkcs12-cert
      key: keystore.p12

Once you deploy Solr with solrTLS enabled, you can test using curl (after creating a port-forward to a Solr pod) from the solr-mTLS directory using:

curl "https://localhost:8983/solr/admin/info/system" -v \
  --key client/private_key.pem --cacert root-ca/root-ca.pem --cert client/client.pem

@thelabdude thelabdude marked this pull request as draft April 13, 2021 17:10
@thelabdude thelabdude marked this pull request as ready for review April 14, 2021 19:07
@thelabdude thelabdude changed the title Support mTLS (WIP) Support mTLS Apr 14, 2021
@thelabdude thelabdude changed the title Support mTLS Operator should be able to present a client certificate to make API calls to mTLS enabled SolrClouds Apr 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Supply client cert for API calls to mTLS enabled Solr clusters

2 participants