mirror of https://github.com/k3s-io/k3s
Merge pull request #29204 from aledbf/ingress-wildcard-hosts
Automatic merge from submit-queue Allow leading * in ingress hostname fixes #29043pull/6/head
commit
0410c33995
|
@ -323,6 +323,20 @@ func validateIngressTLS(spec *extensions.IngressSpec, fldPath *field.Path) field
|
|||
allErrs := field.ErrorList{}
|
||||
// TODO: Perform a more thorough validation of spec.TLS.Hosts that takes
|
||||
// the wildcard spec from RFC 6125 into account.
|
||||
for _, itls := range spec.TLS {
|
||||
for i, host := range itls.Hosts {
|
||||
if strings.Contains(host, "*") {
|
||||
for _, msg := range validation.IsWildcardDNS1123Subdomain(host) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("hosts"), host, msg))
|
||||
}
|
||||
continue
|
||||
}
|
||||
for _, msg := range validation.IsDNS1123Subdomain(host) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("hosts"), host, msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
@ -358,21 +372,27 @@ func ValidateIngressStatusUpdate(ingress, oldIngress *extensions.Ingress) field.
|
|||
return allErrs
|
||||
}
|
||||
|
||||
func validateIngressRules(IngressRules []extensions.IngressRule, fldPath *field.Path) field.ErrorList {
|
||||
func validateIngressRules(ingressRules []extensions.IngressRule, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(IngressRules) == 0 {
|
||||
if len(ingressRules) == 0 {
|
||||
return append(allErrs, field.Required(fldPath, ""))
|
||||
}
|
||||
for i, ih := range IngressRules {
|
||||
for i, ih := range ingressRules {
|
||||
if len(ih.Host) > 0 {
|
||||
// TODO: Ports and ips are allowed in the host part of a url
|
||||
// according to RFC 3986, consider allowing them.
|
||||
for _, msg := range validation.IsDNS1123Subdomain(ih.Host) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, msg))
|
||||
}
|
||||
if isIP := (net.ParseIP(ih.Host) != nil); isIP {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, "must be a DNS name, not an IP address"))
|
||||
}
|
||||
// TODO: Ports and ips are allowed in the host part of a url
|
||||
// according to RFC 3986, consider allowing them.
|
||||
if strings.Contains(ih.Host, "*") {
|
||||
for _, msg := range validation.IsWildcardDNS1123Subdomain(ih.Host) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, msg))
|
||||
}
|
||||
continue
|
||||
}
|
||||
for _, msg := range validation.IsDNS1123Subdomain(ih.Host) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, msg))
|
||||
}
|
||||
}
|
||||
allErrs = append(allErrs, validateIngressRuleValue(&ih.IngressRuleValue, fldPath.Index(0))...)
|
||||
}
|
||||
|
|
|
@ -796,6 +796,82 @@ func TestValidateIngress(t *testing.T) {
|
|||
errorCases[badPathErr] = badRegexPath
|
||||
errorCases[badHostIPErr] = badHostIP
|
||||
|
||||
wildcardHost := "foo.*.bar.com"
|
||||
badWildcard := newValid()
|
||||
badWildcard.Spec.Rules[0].Host = wildcardHost
|
||||
badWildcardErr := fmt.Sprintf("spec.rules[0].host: Invalid value: '%v'", wildcardHost)
|
||||
errorCases[badWildcardErr] = badWildcard
|
||||
|
||||
for k, v := range errorCases {
|
||||
errs := ValidateIngress(&v)
|
||||
if len(errs) == 0 {
|
||||
t.Errorf("expected failure for %q", k)
|
||||
} else {
|
||||
s := strings.Split(k, ":")
|
||||
err := errs[0]
|
||||
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) {
|
||||
t.Errorf("unexpected error: %q, expected: %q", err, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIngressTLS(t *testing.T) {
|
||||
defaultBackend := extensions.IngressBackend{
|
||||
ServiceName: "default-backend",
|
||||
ServicePort: intstr.FromInt(80),
|
||||
}
|
||||
|
||||
newValid := func() extensions.Ingress {
|
||||
return extensions.Ingress{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: extensions.IngressSpec{
|
||||
Backend: &extensions.IngressBackend{
|
||||
ServiceName: "default-backend",
|
||||
ServicePort: intstr.FromInt(80),
|
||||
},
|
||||
Rules: []extensions.IngressRule{
|
||||
{
|
||||
Host: "foo.bar.com",
|
||||
IngressRuleValue: extensions.IngressRuleValue{
|
||||
HTTP: &extensions.HTTPIngressRuleValue{
|
||||
Paths: []extensions.HTTPIngressPath{
|
||||
{
|
||||
Path: "/foo",
|
||||
Backend: defaultBackend,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: extensions.IngressStatus{
|
||||
LoadBalancer: api.LoadBalancerStatus{
|
||||
Ingress: []api.LoadBalancerIngress{
|
||||
{IP: "127.0.0.1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
errorCases := map[string]extensions.Ingress{}
|
||||
|
||||
wildcardHost := "foo.*.bar.com"
|
||||
badWildcardTLS := newValid()
|
||||
badWildcardTLS.Spec.Rules[0].Host = "*.foo.bar.com"
|
||||
badWildcardTLS.Spec.TLS = []extensions.IngressTLS{
|
||||
{
|
||||
Hosts: []string{wildcardHost},
|
||||
},
|
||||
}
|
||||
badWildcardTLSErr := fmt.Sprintf("spec.tls[0].hosts: Invalid value: '%v'", wildcardHost)
|
||||
errorCases[badWildcardTLSErr] = badWildcardTLS
|
||||
|
||||
for k, v := range errorCases {
|
||||
errs := ValidateIngress(&v)
|
||||
if len(errs) == 0 {
|
||||
|
|
|
@ -139,6 +139,27 @@ func IsDNS1035Label(value string) []string {
|
|||
return errs
|
||||
}
|
||||
|
||||
// wildcard definition - RFC 1034 section 4.3.3.
|
||||
// examples:
|
||||
// - valid: *.bar.com, *.foo.bar.com
|
||||
// - invalid: *.*.bar.com, *.foo.*.com, *bar.com, f*.bar.com, *
|
||||
const wildcardDNF1123SubdomainFmt = "\\*\\." + dns1123SubdomainFmt
|
||||
|
||||
// IsWildcardDNS1123Subdomain tests for a string that conforms to the definition of a
|
||||
// wildcard subdomain in DNS (RFC 1034 section 4.3.3).
|
||||
func IsWildcardDNS1123Subdomain(value string) []string {
|
||||
wildcardDNS1123SubdomainRegexp := regexp.MustCompile("^\\*\\." + dns1123SubdomainFmt + "$")
|
||||
|
||||
var errs []string
|
||||
if len(value) > DNS1123SubdomainMaxLength {
|
||||
errs = append(errs, MaxLenError(DNS1123SubdomainMaxLength))
|
||||
}
|
||||
if !wildcardDNS1123SubdomainRegexp.MatchString(value) {
|
||||
errs = append(errs, RegexError(wildcardDNF1123SubdomainFmt, "*.example.com"))
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
const cIdentifierFmt string = "[A-Za-z_][A-Za-z0-9_]*"
|
||||
|
||||
var cIdentifierRegexp = regexp.MustCompile("^" + cIdentifierFmt + "$")
|
||||
|
|
|
@ -407,3 +407,29 @@ func TestIsConfigMapKey(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsWildcardDNS1123Subdomain(t *testing.T) {
|
||||
goodValues := []string{
|
||||
"*.example.com",
|
||||
"*.bar.com",
|
||||
"*.foo.bar.com",
|
||||
}
|
||||
for _, val := range goodValues {
|
||||
if errs := IsWildcardDNS1123Subdomain(val); len(errs) != 0 {
|
||||
t.Errorf("expected no errors for %q: %v", val, errs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []string{
|
||||
"*.*.bar.com",
|
||||
"*.foo.*.com",
|
||||
"*bar.com",
|
||||
"f*.bar.com",
|
||||
"*",
|
||||
}
|
||||
for _, val := range badValues {
|
||||
if errs := IsWildcardDNS1123Subdomain(val); len(errs) == 0 {
|
||||
t.Errorf("expected errors for %q", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue