Skip to content

Commit 64f88d7

Browse files
author
OpenShift Bot
authored
Merge pull request #11716 from ramr/fix-extval-bug
Merged by openshift-bot
2 parents 755d248 + 0ed0fb5 commit 64f88d7

File tree

2 files changed

+887
-41
lines changed

2 files changed

+887
-41
lines changed

pkg/route/api/validation/validation.go

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package validation
33
import (
44
"crypto/tls"
55
"crypto/x509"
6-
"encoding/pem"
76
"fmt"
87
"strings"
98

@@ -15,6 +14,7 @@ import (
1514
"k8s.io/kubernetes/pkg/util/validation/field"
1615

1716
oapi "github.com/openshift/origin/pkg/api"
17+
cmdutil "github.com/openshift/origin/pkg/cmd/util"
1818
routeapi "github.com/openshift/origin/pkg/route/api"
1919
)
2020

@@ -131,23 +131,29 @@ func ExtendedValidateRoute(route *routeapi.Route) field.ErrorList {
131131
// break, so disable the hostname validation for now.
132132
// hostname := route.Spec.Host
133133
hostname := ""
134-
var certPool *x509.CertPool
134+
var verifyOptions *x509.VerifyOptions
135135

136136
if len(tlsConfig.CACertificate) > 0 {
137-
certPool = x509.NewCertPool()
138-
if ok := certPool.AppendCertsFromPEM([]byte(tlsConfig.CACertificate)); !ok {
139-
result = append(result, field.Invalid(tlsFieldPath.Child("caCertificate"), tlsConfig.CACertificate, "failed to parse CA certificate"))
137+
certPool := x509.NewCertPool()
138+
if certs, err := cmdutil.CertificatesFromPEM([]byte(tlsConfig.CACertificate)); err != nil {
139+
errmsg := fmt.Sprintf("failed to parse CA certificate: %v", err)
140+
result = append(result, field.Invalid(tlsFieldPath.Child("caCertificate"), "<ca certificate data>", errmsg))
141+
} else {
142+
for _, cert := range certs {
143+
certPool.AddCert(cert)
144+
}
140145
}
141-
}
142146

143-
verifyOptions := &x509.VerifyOptions{
144-
DNSName: hostname,
145-
Roots: certPool,
147+
verifyOptions = &x509.VerifyOptions{
148+
DNSName: hostname,
149+
Intermediates: certPool,
150+
Roots: certPool,
151+
}
146152
}
147153

148154
if len(tlsConfig.Certificate) > 0 {
149155
if _, err := validateCertificatePEM(tlsConfig.Certificate, verifyOptions); err != nil {
150-
result = append(result, field.Invalid(tlsFieldPath.Child("certificate"), tlsConfig.Certificate, err.Error()))
156+
result = append(result, field.Invalid(tlsFieldPath.Child("certificate"), "<certificate data>", err.Error()))
151157
}
152158

153159
certKeyBytes := []byte{}
@@ -158,14 +164,14 @@ func ExtendedValidateRoute(route *routeapi.Route) field.ErrorList {
158164
}
159165

160166
if _, err := tls.X509KeyPair(certKeyBytes, certKeyBytes); err != nil {
161-
result = append(result, field.Invalid(tlsFieldPath.Child("key"), tlsConfig.Key, err.Error()))
167+
result = append(result, field.Invalid(tlsFieldPath.Child("key"), "<key data>", err.Error()))
162168
}
163169
}
164170

165171
if len(tlsConfig.DestinationCACertificate) > 0 {
166-
roots := x509.NewCertPool()
167-
if ok := roots.AppendCertsFromPEM([]byte(tlsConfig.DestinationCACertificate)); !ok {
168-
result = append(result, field.Invalid(tlsFieldPath.Child("destinationCACertificate"), tlsConfig.DestinationCACertificate, "failed to parse destination CA certificate"))
172+
if _, err := cmdutil.CertificatesFromPEM([]byte(tlsConfig.DestinationCACertificate)); err != nil {
173+
errmsg := fmt.Sprintf("failed to parse destination CA certificate: %v", err)
174+
result = append(result, field.Invalid(tlsFieldPath.Child("destinationCACertificate"), "<destination ca certificate data>", errmsg))
169175
}
170176
}
171177

@@ -218,25 +224,25 @@ func validateTLS(route *routeapi.Route, fldPath *field.Path) field.ErrorList {
218224
//passthrough term should not specify any cert
219225
case routeapi.TLSTerminationPassthrough:
220226
if len(tls.Certificate) > 0 {
221-
result = append(result, field.Invalid(fldPath.Child("certificate"), tls.Certificate, "passthrough termination does not support certificates"))
227+
result = append(result, field.Invalid(fldPath.Child("certificate"), "<certificate data>", "passthrough termination does not support certificates"))
222228
}
223229

224230
if len(tls.Key) > 0 {
225-
result = append(result, field.Invalid(fldPath.Child("key"), tls.Key, "passthrough termination does not support certificates"))
231+
result = append(result, field.Invalid(fldPath.Child("key"), "<key data>", "passthrough termination does not support certificates"))
226232
}
227233

228234
if len(tls.CACertificate) > 0 {
229-
result = append(result, field.Invalid(fldPath.Child("caCertificate"), tls.CACertificate, "passthrough termination does not support certificates"))
235+
result = append(result, field.Invalid(fldPath.Child("caCertificate"), "<ca certificate data>", "passthrough termination does not support certificates"))
230236
}
231237

232238
if len(tls.DestinationCACertificate) > 0 {
233-
result = append(result, field.Invalid(fldPath.Child("destinationCACertificate"), tls.DestinationCACertificate, "passthrough termination does not support certificates"))
239+
result = append(result, field.Invalid(fldPath.Child("destinationCACertificate"), "<destination ca certificate data>", "passthrough termination does not support certificates"))
234240
}
235241
// edge cert should only specify cert, key, and cacert but those certs
236242
// may not be specified if the route is a wildcard route
237243
case routeapi.TLSTerminationEdge:
238244
if len(tls.DestinationCACertificate) > 0 {
239-
result = append(result, field.Invalid(fldPath.Child("destinationCACertificate"), tls.DestinationCACertificate, "edge termination does not support destination certificates"))
245+
result = append(result, field.Invalid(fldPath.Child("destinationCACertificate"), "<destination ca certificate data>", "edge termination does not support destination certificates"))
240246
}
241247
default:
242248
validValues := []string{string(routeapi.TLSTerminationEdge), string(routeapi.TLSTerminationPassthrough), string(routeapi.TLSTerminationReencrypt)}
@@ -282,37 +288,33 @@ func validateInsecureEdgeTerminationPolicy(tls *routeapi.TLSConfig, fldPath *fie
282288

283289
// validateCertificatePEM checks if a certificate PEM is valid and
284290
// optionally verifies the certificate using the options.
285-
func validateCertificatePEM(certPEM string, options *x509.VerifyOptions) (*x509.Certificate, error) {
286-
var data *pem.Block
287-
for remaining := []byte(certPEM); len(remaining) > 0; {
288-
block, rest := pem.Decode(remaining)
289-
if block == nil {
290-
return nil, fmt.Errorf("error decoding certificate data")
291-
}
292-
if block.Type == "CERTIFICATE" {
293-
data = block
294-
break
295-
}
296-
remaining = rest
291+
func validateCertificatePEM(certPEM string, options *x509.VerifyOptions) ([]*x509.Certificate, error) {
292+
certs, err := cmdutil.CertificatesFromPEM([]byte(certPEM))
293+
if err != nil {
294+
return nil, err
297295
}
298296

299-
if data == nil || len(data.Bytes) < 1 {
297+
if len(certs) < 1 {
300298
return nil, fmt.Errorf("invalid/empty certificate data")
301299
}
302300

303-
cert, err := x509.ParseCertificate(data.Bytes)
304-
if err != nil {
305-
return nil, fmt.Errorf("error parsing certificate: %s", err.Error())
306-
}
307-
308301
if options != nil {
309-
_, err = cert.Verify(*options)
302+
// Ensure we don't report errors for expired certs or if
303+
// the validity is in the future.
304+
// Not that this can be for the actual certificate or any
305+
// intermediates in the CA chain. This allows the router to
306+
// still serve an expired/valid-in-the-future certificate
307+
// and lets the client to control if it can tolerate that
308+
// (just like for self-signed certs).
309+
_, err = certs[0].Verify(*options)
310310
if err != nil {
311-
return cert, fmt.Errorf("error verifying certificate: %s", err.Error())
311+
if invalidErr, ok := err.(x509.CertificateInvalidError); !ok || invalidErr.Reason != x509.Expired {
312+
return certs, fmt.Errorf("error verifying certificate: %s", err.Error())
313+
}
312314
}
313315
}
314316

315-
return cert, nil
317+
return certs, nil
316318
}
317319

318320
var (

0 commit comments

Comments
 (0)