From 317e5236494bfa6688b5d7ea30dd8d36fb912fe2 Mon Sep 17 00:00:00 2001 From: Dean Roehrich Date: Fri, 7 Feb 2025 12:42:39 -0600 Subject: [PATCH] Use separate signing keys used for the cert and the token The key used to sign a cert and the key used to sign a token should have nothing to do with each other and they aren't even used in the same context. The following adjusts the code to allow distinct keys for certs and tokens. Signed-off-by: Dean Roehrich --- .../copyoffload-containerprofile.yaml | 20 +++++++++++++------ daemons/copy-offload-testing/e2e-mocked.sh | 5 ++++- daemons/copy-offload/cmd/main.go | 9 +++++---- tools/gen_certs.sh | 6 ++++-- tools/mk-copy-offload-secrets.sh | 18 ++++++++++++----- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/config/examples/copyoffload-containerprofile.yaml b/config/examples/copyoffload-containerprofile.yaml index 9aa81a79..64309633 100644 --- a/config/examples/copyoffload-containerprofile.yaml +++ b/config/examples/copyoffload-containerprofile.yaml @@ -18,19 +18,27 @@ data: command: - /nnf-copy-offload - --cert - - /etc/copy-offload-server/tls.crt + - /etc/copy-offload-tls/tls.crt - --cakey - - /etc/copy-offload-server/tls.key + - /etc/copy-offload-tls/tls.key + - --tokenkey + - /etc/copy-offload-token/token.key - --addr - :$(NNF_CONTAINER_PORTS) volumeMounts: - - name: copy-offload-server - mountPath: /etc/copy-offload-server + - name: copy-offload-tls + mountPath: /etc/copy-offload-tls + readOnly: true + - name: copy-offload-token + mountPath: /etc/copy-offload-token readOnly: true volumes: - - name: copy-offload-server + - name: copy-offload-tls + secret: + secretName: nnf-dm-copy-offload-server-tls + - name: copy-offload-token secret: - secretName: nnf-dm-copy-offload-server + secretName: nnf-dm-copy-offload-server-token serviceAccount: nnf-dm-copy-offload serviceAccountName: nnf-dm-copy-offload retryLimit: 2 diff --git a/daemons/copy-offload-testing/e2e-mocked.sh b/daemons/copy-offload-testing/e2e-mocked.sh index 3d1da78b..bab762a0 100755 --- a/daemons/copy-offload-testing/e2e-mocked.sh +++ b/daemons/copy-offload-testing/e2e-mocked.sh @@ -54,6 +54,9 @@ if [[ -z $SKIP_TOKEN ]]; then TOKEN=$(<"$CERTDIR/client/token") CURL_BEARER_TOKEN_HDR="Authorization: Bearer $TOKEN" CO_TLS_ARGS="$CO_TLS_ARGS -t $CERTDIR/client/token" + + token_key_file="$CERTDIR/ca/private/token_key.pem" + SRVR_CMD_TOKEN_ARGS="-tokenkey $token_key_file" fi if [[ -n $SRVR_WANTS_KEY ]]; then SRVR_CMD_TLS_ARGS="$SRVR_CMD_TLS_ARGS -cakey $CA_KEY" @@ -61,7 +64,7 @@ fi set -x # shellcheck disable=SC2086 -NNF_NODE_NAME=rabbit01 $SRVR_CMD $SRVR_CMD_TLS_ARGS $SRVR_CMD_MTLS_ARGS & +NNF_NODE_NAME=rabbit01 $SRVR_CMD $SRVR_CMD_TOKEN_ARGS $SRVR_CMD_TLS_ARGS $SRVR_CMD_MTLS_ARGS & srvr_pid=$! set +x echo "Server pid is $srvr_pid, my pid is $$" diff --git a/daemons/copy-offload/cmd/main.go b/daemons/copy-offload/cmd/main.go index 4f8d7ff9..ca850965 100644 --- a/daemons/copy-offload/cmd/main.go +++ b/daemons/copy-offload/cmd/main.go @@ -101,6 +101,7 @@ func main() { addr := flag.String("addr", "localhost:4000", "HTTPS network address") certFile := flag.String("cert", "cert.pem", "CA/server certificate PEM file. A self-signed cert.") keyFile := flag.String("cakey", "key.pem", "CA key PEM file") + tokenKeyFile := flag.String("tokenkey", "token_key.pem", "File with PEM key used to sign the token.") clientCertFile := flag.String("clientcert", "", "Client certificate PEM file. This enables mTLS.") flag.BoolVar(&skipTls, "skip-tls", skipTls, "Skip setting up TLS/mTLS.") flag.BoolVar(&skipToken, "skip-token", skipToken, "Skip the use of a bearer token.") @@ -149,10 +150,10 @@ func main() { } if !skipToken { - // Read the key out of its PEM file and convert it to DER form. Then - // base64-encode it so we are using the same representation that was - // used when signing the token. - inKey, err := os.ReadFile(*keyFile) + // Read the token's key out of its PEM file and convert it to DER form. + // Then base64-encode it so we are using the same representation that + // was used when signing the token. + inKey, err := os.ReadFile(*tokenKeyFile) if err != nil { slog.Error("unable to read back the key file", "error", err.Error()) os.Exit(1) diff --git a/tools/gen_certs.sh b/tools/gen_certs.sh index 0fb4db48..4e21fecd 100755 --- a/tools/gen_certs.sh +++ b/tools/gen_certs.sh @@ -41,6 +41,7 @@ fi CA_DIR="$CERTDIR"/ca CA_PDIR=$CA_DIR/private CA_KEY=$CA_PDIR/ca_key.pem +TOKEN_KEY=$CA_PDIR/token_key.pem RABBIT_SAN_CONF="$CERTDIR/rabbit-san.conf" @@ -60,9 +61,10 @@ DNS.1 = $SRVR_HOST fi fi -echo "Generate a key using EC algorithm" +echo "Generate keys using EC algorithm" openssl ecparam -name secp521r1 -genkey -noout -out "$CA_KEY" -DER_KEY=$(openssl ec -in "$CA_KEY" -outform DER | $BASE64) +openssl ecparam -name secp521r1 -genkey -noout -out "$TOKEN_KEY" +DER_KEY=$(openssl ec -in "$TOKEN_KEY" -outform DER | $BASE64) SERVER_DIR="$CERTDIR"/server SERVER_CERT=$SERVER_DIR/server_cert.pem diff --git a/tools/mk-copy-offload-secrets.sh b/tools/mk-copy-offload-secrets.sh index 39f7b5c5..6b986331 100755 --- a/tools/mk-copy-offload-secrets.sh +++ b/tools/mk-copy-offload-secrets.sh @@ -23,9 +23,11 @@ set -o pipefail SRVR_HOST="$1" SRVR_HOST=${SRVR_HOST:=localhost} -SERVER_SECRET=nnf-dm-copy-offload-server -TOKEN_SECRET=nnf-dm-copy-offload-client -if kubectl get secret $TOKEN_SECRET $SERVER_SECRET 2> /dev/null; then +SERVER_SECRET_TLS=nnf-dm-copy-offload-server-tls +SERVER_SECRET_TOKEN=nnf-dm-copy-offload-server-token +CLIENT_SECRET_TLS=nnf-dm-copy-offload-client-tls +CLIENT_SECRET_TOKEN=nnf-dm-copy-offload-client-token +if kubectl get secret "$SERVER_SECRET_TLS" "$SERVER_SECRET_TOKEN" "$CLIENT_SECRET_TLS" "$CLIENT_SECRET_TOKEN" 2> /dev/null; then echo "The copy-offload secrets already exist in the cluster." exit 0 fi @@ -35,8 +37,14 @@ CERTDIR=certs KEY=$CERTDIR/ca/private/ca_key.pem SERVER_CERT=$CERTDIR/server/server_cert.pem + +TOKEN_KEY=$CERTDIR/ca/private/token_key.pem TOKEN=$CERTDIR/client/token -kubectl create secret tls $SERVER_SECRET --cert $SERVER_CERT --key $KEY +kubectl create secret tls $SERVER_SECRET_TLS --cert $SERVER_CERT --key $KEY +# Use an opaque secret for the client's TLS cert because we don't want to +# give the key to the client. +kubectl create secret generic $CLIENT_SECRET_TLS --from-file "tls.crt=$SERVER_CERT" -kubectl create secret generic $TOKEN_SECRET --from-file "tls.crt"="$SERVER_CERT" --from-file token="$TOKEN" +kubectl create secret generic $CLIENT_SECRET_TOKEN --from-file "token=$TOKEN" +kubectl create secret generic $SERVER_SECRET_TOKEN --from-file "token.key=$TOKEN_KEY"