appuio / component-openshift4-ingress

Commodore component to manage Ingress Controllers on OpenShift 4
BSD 3-Clause "New" or "Revised" License
1 stars 1 forks source link

The component must be tolerant to certificate chains without a newline #30

Closed megian closed 2 years ago

megian commented 2 years ago

If the certificate chain openshift4-ingress/wildcard-certificate/cert does not contain a newline, the deployment on the OpenShift 4 cluster fails, because chain and key are concatenated -----END CERTIFICATE----------BEGIN PRIVATE KEY-----,.

Steps to Reproduce the Problem

  1. Inject a certificate chain WITHOUT a newline at the end -----END CERTIFICATE-----
    secrets:
      customer-apps-tls:
        stringData:
          tls.crt: ?{vaultkv:${cluster:tenant}/${cluster:name}/openshift4-ingress/wildcard-certificate/cert}
  2. Check the OpenShift cluster router secrets
    oc -n openshift-ingress get secret router-apps-tls -o jsonpath="{.data.tls\.crt}" | base64 -d
    oc -n openshift-authentication get secret v4-0-config-system-router-certs -o jsonpath="{.data.apps\.cluster\.domain\.ch}" | base64 -d | grep "BEGIN PRIVATE KEY"

Actual Behavior

Without a newline this result in -----END CERTIFICATE----------BEGIN PRIVATE KEY-----, which causes several base components not starting or even crashing.

Expected Behavior

The component must either check for a newline at the end of the injected certificate chain and add one if not there. Or potentially just add always a newline to the chain (untested).

Test the certificate chain ahead could be an other solution to it, but would potentially cause downtime.

It's not acceptable that the user has to check for a newline, because it is high likely this is happening very often and we can't ensure component users read the documentation at such low level.

ccremer commented 2 years ago

Why does it end up in -----END CERTIFICATE----------BEGIN PRIVATE KEY----- in the first place? Do you configure a secret with both tls.crt and tls.key? (You aren't supposed to put the private key into tls.crt field) see https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets

megian commented 2 years ago

It's not the case that the key is added to the tls.crt but this happens on the cluster via the operators.

$ oc -n openshift-authentication get secret v4-0-config-system-router-certs -o yaml
apiVersion: v1
data:
  apps.cluster.cluster.ch: LS0...
kind: Secret
metadata:
...
  name: v4-0-config-system-router-certs
  namespace: openshift-authentication
...
type: Opaque
ccremer commented 2 years ago

ah, that's how it works...

I'm not sure the component can help here. The secret value is retrieved when ArgoCD deploys the manifest. The component compilation can't retrieve the value from Vault, add a newline and update it back in Vault...

simu commented 2 years ago

The component must either check for a newline at the end of the injected certificate chain and add one if not there.

Please note that it's impossible for the component to do that, as either the certificate or key may be provided from Vault and the component can't check values stored in Vault by design.

The proposed solution in #32 unconditionally appends a newline to all present fields in the secrets, a quick manual test shows that extra newlines in the concatenated data don't matter to openshift-authentication.