Bug 1896977 - route SimpleAllocationPlugin: host name validation errors: spec.host: Invalid value: ... must be no more than 63 characters
Summary: route SimpleAllocationPlugin: host name validation errors: spec.host: Invalid...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: OpenShift Container Platform
Classification: Red Hat
Component: Networking
Version: 4.1.z
Hardware: Unspecified
OS: Unspecified
low
low
Target Milestone: ---
: 4.7.0
Assignee: Candace Holman
QA Contact: Arvind iyengar
URL:
Whiteboard:
Depends On:
Blocks: 1924996 1964112
TreeView+ depends on / blocked
 
Reported: 2020-11-12 00:27 UTC by W. Trevor King
Modified: 2022-08-04 22:30 UTC (History)
8 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Cause: host name validation can fail during route admission because the validation is lenient during route creation but strict during route admission. Consequence: route admission fails because strict host name validation is performed too late. Fix: match the host name validation that is applied when the route is created and when it is admitted. A new annotation on the route is added to allow an override of the strict validation on creation: "route.openshift.io/allow-non-dns-compliant-host". Adding this annotation will allow the old behavior: a route may be created with a non-compliant host name but will not be admitted. Result: host name validation on route create is now the same as host name validation on route admission.
Clone Of:
: 1924996 1964112 (view as bug list)
Environment:
Last Closed: 2021-05-24 18:14:54 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Github openshift api pull 830 0 None closed Bug 1896977: Enhance host name validation - annotation 2021-02-15 10:39:47 UTC
Github openshift library-go pull 975 0 None closed Bug 1896977: add library function for host name validation 2021-02-15 10:39:47 UTC
Github openshift openshift-apiserver pull 167 0 None closed Bug 1896977: Enhance API host name validation 2021-02-15 10:39:47 UTC
Github openshift origin pull 25770 0 None closed Bug 1896977: Match e2e test to new enhanced host name validation 2021-02-15 10:39:47 UTC
Github openshift router pull 238 0 None closed Bug 1896977: Enhance host name validation in router 2021-02-15 10:39:47 UTC
Red Hat Product Errata RHSA-2020:5633 0 None None None 2021-02-24 15:33:22 UTC

Description W. Trevor King 2020-11-12 00:27:33 UTC
Description of problem:

If a Route is created where the combined name and namespace are too long, SimpleAllocationPlugin.GenerateHostname will generate a spec.host whose DNS segment that exceeds the 63-character cap, and the route will be rejected.

Version-Release number of selected component (if applicable):

Buggy code is very old [1,2], with the choice to combine name and namespace in one DNS segment dating to bug 1414956 (OpenShift 3.5) and still being current in 4.7/master.

How reproducible:

100%

Steps to Reproduce:
1. Install a cluster.  I'm using 4.7, but anything 3.5 and on should be fine.
2. Create a route with a long name.  For example, piggybacking on the OAuth service that v4 has by default:

$ cat route.yaml 
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: oauth-openshift-really-long-lalalalalalalalala
  namespace: openshift-authentication
spec:
  port:
    targetPort: 6443
  tls:
    insecureEdgeTerminationPolicy: Redirect
    termination: passthrough
  to:
    kind: Service
    name: oauth-openshift
    weight: 100
  wildcardPolicy: None
$ oc apply -f route.yaml 

Actual results:

The route failed to be accepted:

$ oc -n openshift-authentication get -o json route oauth-openshift-really-long-lalalalalalalalala | jq -r '.spec.host + "\n" + .status.ingress[].conditions[].message'
oauth-openshift-really-long-lalalalalalalalala-openshift-authentication.apps.ci-ln-3z9dtlt-d5d6b.origin-ci-int-aws.dev.rhcloud.com
host name validation errors: spec.host: Invalid value: "oauth-openshift-really-long-lalalalalalalalala-openshift-authentication.apps.ci-ln-3z9dtlt-d5d6b.origin-ci-int-aws.dev.rhcloud.com": must be no more than 63 characters

Expected results:

The generated name would truncate long segments.  And maybe replace the last few legal characters with a random, uniqifying suffix.  Collisions aren't a great UX, and folks who really care about the name should probably be setting either host or subdomain.  But deterministic names are nice too.  Anyhow, always failing works in no cases, so either mitigation would be better than what we have today.

[1]: https://github.com/openshift/openshift-apiserver/blame/d7b5d2432130ae600c4ab6e047d8a7ce29698a56/pkg/route/apiserver/simplerouteallocation/plugin.go#L54
[2]: https://github.com/openshift/openshift-apiserver/commit/6c5ca8feb15eab4854109d5c0436e2d536ca77a2

Comment 1 W. Trevor King 2020-11-12 00:31:33 UTC
>  I'm using 4.7...

Oops.  I was actually using 4.6.4.  But still the same code in 4.7.

Comment 2 W. Trevor King 2020-11-12 04:34:20 UTC
I've floated [1] to block long cluster domains to hold a full 63 characters for subdomains.  Not that I think GenerateHostname should rely on that behavior, but it will hopefully keep most folks away from needing really drastic truncation from the desired subdomain(s).

[1]: https://github.com/openshift/installer/pull/4368

Comment 3 Stefan Schimanski 2020-11-12 09:42:20 UTC
This is in openshift-apiserver. But reassigning to the respective team as they own the business logic for this topic and would want to define the algorithm used to generate the name.

Comment 5 Candace Holman 2020-12-03 15:06:58 UTC
Collecting feedback on some discussion points: https://docs.google.com/document/d/1Kampp-19H6Lfb5VUMWG7lGhMomx4C2wzalaY_Asmh20/edit#

Comment 6 Candace Holman 2020-12-03 19:01:16 UTC
Currently working on this and will resolve in upcoming sprint.

Comment 7 Candace Holman 2020-12-14 22:05:26 UTC
Change route validation to apply the stricter validation rules from IsFullyQualifiedDomainName on host name when OpenShiftAllowNonDNSCompliantHostAnnotation is false or missing: host name must have at least two labels, with each label less than 64 chars, no disallowed characters, total length less than 254 chars, and trailing dots are allowed. If OpenShiftAllowNonDNSCompliantHostAnnotation is true then use the former lenient validation of just IsDNS1123Subdomain: total length less than 254, and no disallowed characters.

Add new annotation: OpenShiftAllowNonDNSCompliantHostAnnotation = "openshift.io/allow-non-dns-compliant-host" to allow configuations that suppress the stricter validation.  This may produce routes that cannot be admitted (no change from previous issue).

Comment 9 Yang Yang 2021-02-04 04:11:47 UTC
I run into this issue when installing 4.6 osus.

status:
  ingress:
  - conditions:
    - lastTransitionTime: "2021-02-03T09:27:39Z"
      message: 'host name validation errors: spec.host: Invalid value: "updateservice-internal-policy-engine-route-openshift-update-service.apps.yangyang0202.qe.gcp.devcluster.openshift.com": must be no more than 63 characters'
      reason: InvalidHost
      status: "False"
      type: Admitted
    host: updateservice-internal-policy-engine-route-openshift-update-service.apps.yangyang0202.qe.gcp.devcluster.openshift.com
    routerCanonicalHostname: apps.yangyang0202.qe.gcp.devcluster.openshift.com
    routerName: default
    wildcardPolicy: None

Comment 10 Candace Holman 2021-02-04 21:12:37 UTC
(In reply to Yang Yang from comment #9)
> I run into this issue when installing 4.6 osus.
> 
> status:
>   ingress:
>   - conditions:
>     - lastTransitionTime: "2021-02-03T09:27:39Z"
>       message: 'host name validation errors: spec.host: Invalid value:
> "updateservice-internal-policy-engine-route-openshift-update-service.apps.
> yangyang0202.qe.gcp.devcluster.openshift.com": must be no more than 63
> characters'
>       reason: InvalidHost
>       status: "False"
>       type: Admitted
>     host:
> updateservice-internal-policy-engine-route-openshift-update-service.apps.
> yangyang0202.qe.gcp.devcluster.openshift.com
>     routerCanonicalHostname:
> apps.yangyang0202.qe.gcp.devcluster.openshift.com
>     routerName: default
>     wildcardPolicy: None

This is the correct behavior.  The host name here is invalid.  The solution should be tested for route creation.  Please let me know if you need assistance.

Comment 11 Yang Yang 2021-02-05 02:00:05 UTC
(In reply to Candace Holman from comment #10)
> (In reply to Yang Yang from comment #9)
> > I run into this issue when installing 4.6 osus.
> > 
> > status:
> >   ingress:
> >   - conditions:
> >     - lastTransitionTime: "2021-02-03T09:27:39Z"
> >       message: 'host name validation errors: spec.host: Invalid value:
> > "updateservice-internal-policy-engine-route-openshift-update-service.apps.
> > yangyang0202.qe.gcp.devcluster.openshift.com": must be no more than 63
> > characters'
> >       reason: InvalidHost
> >       status: "False"
> >       type: Admitted
> >     host:
> > updateservice-internal-policy-engine-route-openshift-update-service.apps.
> > yangyang0202.qe.gcp.devcluster.openshift.com
> >     routerCanonicalHostname:
> > apps.yangyang0202.qe.gcp.devcluster.openshift.com
> >     routerName: default
> >     wildcardPolicy: None
> 
> This is the correct behavior.  The host name here is invalid.  The solution
> should be tested for route creation.  Please let me know if you need
> assistance.

Thanks. I was told that the short hostname should have at most 63 chars. I'll try again with a short updateservice name and namespace

Comment 12 Arvind iyengar 2021-02-05 11:10:36 UTC
Verified in "4.7.0-0.nightly-2021-02-03-11345" which includes the merge. With this payload, adding the "route.openshift.io/allow-non-dns-compliant-host: true" annotation, causes the long route names to be accepted: 
------
Route with long naming convention:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  annotations:
    route.openshift.io/allow-non-dns-compliant-host: "true"
  name: service-unsecure-really-long-name-lalalalalalalalala-lllllssssss-test1
  namespace: test1
spec:
  port:
    targetPort: 8080
  to:
    kind: Service
    name: service-unsecure
    weight: null
  wildcardPolicy: None

$ oc create -f route-test.yaml
route.route.openshift.io/service-unsecure-really-long-name-lalalalalalalalala-lllllssssss-test1 created


NAME                                                                     HOST/PORT                                                                                                                             PATH   SERVICES           PORT   TERMINATION   WILDCARD
service-unsecure-really-long-name-lalalalalalalalala-lllllssssss-test1   service-unsecure-really-long-name-lalalalalalalalala-lllllssssss-test1-test1.apps.aiyengar-oc47-patched.qe.devcluster.openshift.com          service-unsecure   8080                 None
------

Without the annotation in place, the route gets rejected during the creation: 
------
$ oc create -f route-test.yaml                                                                     
The Route "route-test" is invalid: spec.host: Invalid value: "ervice-unsecure-really-long-name-lalalalalalalalala-lllllssssss-test1-test1.apps.aiyengar-oc47-patched.qe.devcluster.openshift.com": host must conform to DNS 1123 naming conventions: [spec.host: Invalid value: "service-unsecure-really-long-name-lalalalalalalalala-lllllssssss-test1": must be no more than 63 characters]
------

Comment 15 errata-xmlrpc 2021-02-24 15:32:36 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (Moderate: OpenShift Container Platform 4.7.0 security, bug fix, and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHSA-2020:5633


Note You need to log in before you can comment on or make changes to this bug.