diff --git a/pkg/router/routeapihelpers/validation.go b/pkg/router/routeapihelpers/validation.go index 2f105d3e8..ba8d955cb 100644 --- a/pkg/router/routeapihelpers/validation.go +++ b/pkg/router/routeapihelpers/validation.go @@ -206,6 +206,9 @@ func ExtendedValidateRoute(route *routev1.Route) field.ErrorList { tlsConfig.CACertificate = string(data) } } + if _, err := validateCACertificatePEM(tlsConfig.CACertificate); err != nil { + result = append(result, field.Invalid(tlsFieldPath.Child("caCertificate"), "redacted ca certificate data", err.Error())) + } verifyOptions = &x509.VerifyOptions{ DNSName: hostname, @@ -353,6 +356,36 @@ func validateInsecureEdgeTerminationPolicy(tls *routev1.TLSConfig, fldPath *fiel return nil } +// validateCACertificatePEM checks if a CA certificate PEM is valid and +// verifies the certificate is valid. +func validateCACertificatePEM(certPEM string) ([]*x509.Certificate, error) { + certs, err := cert.ParseCertsPEM([]byte(certPEM)) + if err != nil { + return nil, err + } + + if len(certs) < 1 { + return nil, fmt.Errorf("invalid/empty certificate data") + } + + for _, cert := range certs { + // Only intermediate CAs are affected, not root CAs. + if cert.IsCA && cert.BasicConstraintsValid && cert.Issuer.CommonName != cert.Subject.CommonName { + // Reject any unsupported cert algorithms as HaProxy will refuse to start with them. + switch certs[0].SignatureAlgorithm { + case x509.SHA1WithRSA, x509.ECDSAWithSHA1: + return certs, fmt.Errorf("router does not support intermediate certs using SHA1") + case x509.MD5WithRSA: + return certs, fmt.Errorf("router does not support intermediate certs using MD5") + default: + // Acceptable algorithm + } + } + } + + return certs, nil +} + // validateCertificatePEM checks if a certificate PEM is valid and // optionally verifies the certificate using the options. func validateCertificatePEM(certPEM string, options *x509.VerifyOptions) ([]*x509.Certificate, error) {