In able to enable Presto to work with TLS and authentication, we first need to create server, client, and CA certificates and keys. Then, we need to create multiple secrets locally that store these certificates and keys. Once that is done we can move on to configuring our k8s resources and custom MeteringConfig resource.
export METERING_NAMESPACE="your namespace"
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt -subj "/C=US/ST=Massachusetts/L=Lowell/O=Presto /OU=Presto Test/CN=Root Presto CA"
The command will prompt us to provide some information, most importantly is the CN. Here is a snippet of the output from openssl x509 -noout -text -in ca.crt
of my local root CA:
Issuer: C = US, ST = Massachusetts, L = Lowell, O = Presto, OU = Presto Test, CN = Root Presto CA
Validity
Not Before: Jun 6 22:01:36 2019 GMT
Not After : Jun 5 22:01:36 2020 GMT
Subject: C = US, ST = Massachusetts, L = Lowell, O = Presto, OU = Presto Test, CN = Root Presto CA
You can configure the distinguished name to be whatever you want, or model it after the output of the snippet above.
openssl genrsa -out server.key 2048
Now that we have a server private key, we can generate a certificate signing request (CSR):
openssl req -new -key server.key -out server.csr -subj "/C=US/ST=Massachusetts/L=Boston/O=Red Hat/OU=Presto/CN=*.presto-nodes"
Again, we will need to fill out some information. Configure the CN to be *.presto-nodes
. Here is the subject of my local server.csr
:
Subject: C = US, ST = Massachusetts, L = Boston, O = Red Hat, OU = Presto, CN = *.presto-nodes
Again, you can configure the principal however you want, just make note that the CN needs to be *.presto-nodes
.
We now need to create a configuration file for the server so we can define the SAN extensions, which are needed in the server certificate:
# save this as "server.conf"
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alternate_names
[alternate_names]
DNS.2 = *.presto-nodes.$METERING_NAMESPACE.svc.cluster.local
DNS.3 = presto
DNS.4 = *.presto-nodes
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256 -extfile server.conf
Generate client certificates (this is based on https://gist.github.com/mtigas/952344#create-the-client-key-and-csr):
CLIENT_ID="01-coordinator"
CLIENT_SERIAL=01
openssl genrsa -out ${CLIENT_ID}.key 2048
openssl req -new -key ${CLIENT_ID}.key -out ${CLIENT_ID}.csr -subj "/CN=coordinator.presto-nodes"
Note that the common name (CN) doesn't have to match the CN of the root CA or server certificate, so you can make it something like coordinator
or worker.presto-nodes
to distinguish from other client certificates.
openssl x509 -req -days 365 -in ${CLIENT_ID}.csr -CA ca.crt -CAkey ca.key -set_serial ${CLIENT_SERIAL} -out ${CLIENT_ID}.crt
Now, we should have a directory full of server.crt
, server.key
, ca.crt
, ca.key
, ${CLIENT_ID}.crt
. and ${CLIENT_ID}.key
(excluding the configuration files and CSRs)
kubectl create ns $METERING_NAMESPACE
# note that the current implementation was based on a TLS secret - which requires having a tls.key/tls.crt naming convention, but running this command is easier
kubectl -n $METERING_NAMESPACE create secret generic presto-tls --from-file=ca.crt=ca.crt --from-file=tls.crt=server.crt --from-file=tls.key=server.key
kubectl -n $METERING_NAMESPACE create secret generic presto-client-tls --from-file=tls.key=${CLIENT_ID}.key --from-file=tls.crt=${CLIENT_ID}.crt --from-file=ca.crt=ca.crt
cp manifests/metering-config/default.yaml metering-custom.yaml
export METERING_CR_FILE="metering-custom.yaml"
Here is the local version of my metering-custom.yaml
apiVersion: metering.openshift.io/v1alpha1
kind: MeteringConfig
metadata:
name: "operator-metering"
spec:
tls:
enabled: false
reporting-operator:
spec:
# note: the reporting operator and ansible operator images have been updated in master
config:
presto:
tls:
createSecret: false
# this contains the server cert/key and ca cert
secretName: presto-tls
auth:
enabled: true
secretName: presto-client-tls
presto:
spec:
presto:
worker:
replicas: 1
config:
tls:
createSecret: false
secretName: presto-tls
auth:
createSecret: false
secretName: presto-client-tls
After copying my custom metering config, run this command to apply the changes:
kubectl -n $METERING_NAMESPACE apply -f metering-custom.yaml
Need to change the two authentication fields controlling whether or not it's enabled so set presto.config.auth.enabled: false
, and reporting-operator.spec.config.prestoAuth.enabled = false
. We then need to re-apply the MeteringConfig
:
kubectl -n $METERING_NAMESPACE apply -f metering-custom.yaml
Then, we need to update the resources:
./hack/openshift-install.sh
In order to verify that TLS works, I'd recommend checking the logs of the presto-coordinator-0
and reporting-operator*
pods to ensure that there's no errors in the logs.
We can definitely tell that authentication is working properly if you try to view the presto UI on your browser and get a 401 (unauthorized error)
kubectl port-forward svc/presto 8080:8080
As that command is running, try to visit https://presto:8080
We can avoid prompts with the
-subj
option likeopenssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt -subj "/C=US/ST=CA/L=Sunnvyale/O=RedHat/CN=*.presto-nodes"