Skip to content

Commit 7dc28bd

Browse files
author
OpenShift Bot
authored
Merge pull request #10434 from ramr/route-gen-check
Merged by openshift-bot
2 parents e21c5c6 + 5d3470e commit 7dc28bd

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

pkg/route/api/validation/validation.go

+31
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ func ValidateRoute(route *routeapi.Route) field.ErrorList {
2626

2727
//host is not required but if it is set ensure it meets DNS requirements
2828
if len(route.Spec.Host) > 0 {
29+
// TODO: Add a better check that the host name matches up to
30+
// DNS requirements. Change to use:
31+
// ValidateHostName(route)
32+
// Need to check the implications of doing it here in
33+
// ValidateRoute - probably needs to be done only on
34+
// creation time for new routes.
2935
if len(kvalidation.IsDNS1123Subdomain(route.Spec.Host)) != 0 {
3036
result = append(result, field.Invalid(specPath.Child("host"), route.Spec.Host, "host must conform to DNS 952 subdomain conventions"))
3137
}
@@ -160,6 +166,31 @@ func ExtendedValidateRoute(route *routeapi.Route) field.ErrorList {
160166
return result
161167
}
162168

169+
// ValidateHostName checks that a route's host name satisfies DNS requirements.
170+
func ValidateHostName(route *routeapi.Route) field.ErrorList {
171+
result := field.ErrorList{}
172+
if len(route.Spec.Host) < 1 {
173+
return result
174+
}
175+
176+
specPath := field.NewPath("spec")
177+
hostPath := specPath.Child("host")
178+
179+
if len(kvalidation.IsDNS1123Subdomain(route.Spec.Host)) != 0 {
180+
result = append(result, field.Invalid(hostPath, route.Spec.Host, "host must conform to DNS 952 subdomain conventions"))
181+
}
182+
183+
segments := strings.Split(route.Spec.Host, ".")
184+
for _, s := range segments {
185+
errs := kvalidation.IsDNS1123Label(s)
186+
for _, e := range errs {
187+
result = append(result, field.Invalid(hostPath, route.Spec.Host, e))
188+
}
189+
}
190+
191+
return result
192+
}
193+
163194
// validateTLS tests fields for different types of TLS combinations are set. Called
164195
// by ValidateRoute.
165196
func validateTLS(route *routeapi.Route, fldPath *field.Path) field.ErrorList {

pkg/route/api/validation/validation_test.go

+78
Original file line numberDiff line numberDiff line change
@@ -997,3 +997,81 @@ func TestExtendedValidateRoute(t *testing.T) {
997997
}
998998
}
999999
}
1000+
1001+
// TestValidateHostName checks that a route's host name matches DNS requirements.
1002+
func TestValidateHostName(t *testing.T) {
1003+
tests := []struct {
1004+
name string
1005+
route *api.Route
1006+
expectedErrors bool
1007+
}{
1008+
{
1009+
name: "valid-host-name",
1010+
route: &api.Route{
1011+
Spec: api.RouteSpec{
1012+
Host: "www.example.test",
1013+
},
1014+
},
1015+
expectedErrors: false,
1016+
},
1017+
{
1018+
name: "invalid-host-name",
1019+
route: &api.Route{
1020+
Spec: api.RouteSpec{
1021+
Host: "name-namespace-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890.example.test",
1022+
},
1023+
},
1024+
expectedErrors: true,
1025+
},
1026+
{
1027+
name: "valid-host-63-chars-label",
1028+
route: &api.Route{
1029+
Spec: api.RouteSpec{
1030+
Host: "name-namespace-1234567890-1234567890-1234567890-1234567890-1234.example.test",
1031+
},
1032+
},
1033+
expectedErrors: false,
1034+
},
1035+
{
1036+
name: "invalid-host-64-chars-label",
1037+
route: &api.Route{
1038+
Spec: api.RouteSpec{
1039+
Host: "name-namespace-1234567890-1234567890-1234567890-1234567890-12345.example.test",
1040+
},
1041+
},
1042+
expectedErrors: true,
1043+
},
1044+
{
1045+
name: "valid-name-253-chars",
1046+
route: &api.Route{
1047+
Spec: api.RouteSpec{
1048+
Host: "name-namespace.a1234567890.b1234567890.c1234567890.d1234567890.e1234567890.f1234567890.g1234567890.h1234567890.i1234567890.j1234567890.k1234567890.l1234567890.m1234567890.n1234567890.o1234567890.p1234567890.q1234567890.r1234567890.s12345678.example.test",
1049+
},
1050+
},
1051+
expectedErrors: false,
1052+
},
1053+
{
1054+
name: "invalid-name-279-chars",
1055+
route: &api.Route{
1056+
Spec: api.RouteSpec{
1057+
Host: "name-namespace.a1234567890.b1234567890.c1234567890.d1234567890.e1234567890.f1234567890.g1234567890.h1234567890.i1234567890.j1234567890.k1234567890.l1234567890.m1234567890.n1234567890.o1234567890.p1234567890.q1234567890.r1234567890.s1234567890.t1234567890.u1234567890.example.test",
1058+
},
1059+
},
1060+
expectedErrors: true,
1061+
},
1062+
}
1063+
1064+
for _, tc := range tests {
1065+
errs := ValidateHostName(tc.route)
1066+
1067+
if tc.expectedErrors {
1068+
if len(errs) < 1 {
1069+
t.Errorf("Test case %s expected errors, got none.", tc.name)
1070+
}
1071+
} else {
1072+
if len(errs) > 0 {
1073+
t.Errorf("Test case %s expected no errors, got %d. %v", tc.name, len(errs), errs)
1074+
}
1075+
}
1076+
}
1077+
}

pkg/router/controller/unique_host.go

+16
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package controller
22

33
import (
44
"fmt"
5+
"strings"
56

67
"github.com/golang/glog"
78
kapi "k8s.io/kubernetes/pkg/api"
89
"k8s.io/kubernetes/pkg/util/sets"
910
"k8s.io/kubernetes/pkg/watch"
1011

1112
routeapi "github.com/openshift/origin/pkg/route/api"
13+
"github.com/openshift/origin/pkg/route/api/validation"
1214
"github.com/openshift/origin/pkg/router"
1315
)
1416

@@ -108,6 +110,20 @@ func (p *UniqueHost) HandleRoute(eventType watch.EventType, route *routeapi.Rout
108110
}
109111
route.Spec.Host = host
110112

113+
// Run time check to defend against older routes. Validate that the
114+
// route host name conforms to DNS requirements.
115+
if errs := validation.ValidateHostName(route); len(errs) > 0 {
116+
glog.V(4).Infof("Route %s - invalid host name %s", routeName, host)
117+
errMessages := make([]string, len(errs))
118+
for i := 0; i < len(errs); i++ {
119+
errMessages[i] = errs[i].Error()
120+
}
121+
122+
err := fmt.Errorf("host name validation errors: %s", strings.Join(errMessages, ", "))
123+
p.recorder.RecordRouteRejection(route, "InvalidHost", err.Error())
124+
return err
125+
}
126+
111127
// ensure hosts can only be claimed by one namespace at a time
112128
// TODO: this could be abstracted above this layer?
113129
if old, ok := p.hostToRoute[host]; ok {

0 commit comments

Comments
 (0)