← Back to team overview

yahoo-eng-team team mailing list archive

[Bug 1915868] [NEW] novnc-proxy fails to connect through a reverse-proxy

 

Public bug reported:

Novnc-proxy will generate a URL for console access using a hard-coded
empty string for the path query argument.  This causes issues when
exposing novnc-proxy through a reverse-proxy.

The current URL generation for novnc proxy uses the following to
construct the URL:

                qparams = {'path': '?token=%s' % (self.token)}
                return '%s?%s' % (self.access_url_base,
                                  urlparse.urlencode(qparams))


With a novncproxy_base_url of "https://host.domain.com/novncproxy/vnc_lite.html";, The resulting URL is:
 https://host.domain.com/novncproxy/vnc_lite.html?path=%3Ftoken%3Ddc2ff4cd-b92d-4af8-8549-922d9d22f9f6&title=cirros1(fe675807-982f-45dd-a0b7-4352ba93abb0)

This URL will cause the client browser to open a websocket URL
wss://host.domain.com/?token%3Ddc2ff4cd-b92d-
4af8-8549-922d9d22f9f6&title=cirros1(fe675807-982f-45dd-
a0b7-4352ba93abb0)

If https://host.domain.com/novncproxy is a reverse proxy (i.e.
kubernetes ingress), the websocket URL will fail to connect.

Modifying the Novnc URL to include the path elements of the base_url allows the websocket to connect to the correct URL.
This URL works as expected (edited manually in the browser address bar):
https://host.domain.com/novncproxy/vnc_lite.html?path=novncproxy%3Ftoken%3Ddc2ff4cd-b92d-4af8-8549-922d9d22f9f6&title=cirros1(fe675807-982f-45dd-a0b7-4352ba93abb0)

I fixed this issue in my environment by patching
nova/objects/console_auth_token.py to extract the path from the
novncproxy_base_url and add it to the generated console URL.  After
applying this change, novncproxy works without special considerations or
configuration, aside from a basic rewrite-target, through a reverse
proxy.

    @property
    def access_url(self):
        if self.obj_attr_is_set('id'):
            if self.console_type == 'novnc':
                # extract file path from access_url_base
                raw_path = path.dirname(urlparse.urlparse(self.access_url_base).path)
                # remove the leading "/" separately to prevent an exception from occurring
                # when the URL contains no path.
                if raw_path[0] == "/":
                    path_arg = raw_path[1:]
                else:
                    path_arg = raw_path
                # add the resulting path string before "?token" in the "path" query argument.
                qparams = {'path': '%s?token=%s' % (path_arg, self.token)}
                return '%s?%s' % (self.access_url_base,
                                  urlparse.urlencode(qparams))
            else:
                return '%s?token=%s' % (self.access_url_base, self.token)

This is the actual patch I applied to nova/objects/console_auth_token.py

21a22
> from os import path
73c74,79
<                 qparams = {'path': '?token=%s' % self.token}
---
>                 raw_path = path.dirname(urlparse.urlparse(self.access_url_base).path)
>                 if raw_path[0] == "/":
>                     path_arg = raw_path[1:]
>                 else:
>                     path_arg = raw_path
>                 qparams = {'path': '%s?token=%s' % (path_arg, self.token)}

** Affects: nova
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Yahoo!
Engineering Team, which is subscribed to OpenStack Compute (nova).
https://bugs.launchpad.net/bugs/1915868

Title:
  novnc-proxy fails to connect through a reverse-proxy

Status in OpenStack Compute (nova):
  New

Bug description:
  Novnc-proxy will generate a URL for console access using a hard-coded
  empty string for the path query argument.  This causes issues when
  exposing novnc-proxy through a reverse-proxy.

  The current URL generation for novnc proxy uses the following to
  construct the URL:

                  qparams = {'path': '?token=%s' % (self.token)}
                  return '%s?%s' % (self.access_url_base,
                                    urlparse.urlencode(qparams))

  
  With a novncproxy_base_url of "https://host.domain.com/novncproxy/vnc_lite.html";, The resulting URL is:
   https://host.domain.com/novncproxy/vnc_lite.html?path=%3Ftoken%3Ddc2ff4cd-b92d-4af8-8549-922d9d22f9f6&title=cirros1(fe675807-982f-45dd-a0b7-4352ba93abb0)

  This URL will cause the client browser to open a websocket URL
  wss://host.domain.com/?token%3Ddc2ff4cd-b92d-
  4af8-8549-922d9d22f9f6&title=cirros1(fe675807-982f-45dd-
  a0b7-4352ba93abb0)

  If https://host.domain.com/novncproxy is a reverse proxy (i.e.
  kubernetes ingress), the websocket URL will fail to connect.

  Modifying the Novnc URL to include the path elements of the base_url allows the websocket to connect to the correct URL.
  This URL works as expected (edited manually in the browser address bar):
  https://host.domain.com/novncproxy/vnc_lite.html?path=novncproxy%3Ftoken%3Ddc2ff4cd-b92d-4af8-8549-922d9d22f9f6&title=cirros1(fe675807-982f-45dd-a0b7-4352ba93abb0)

  I fixed this issue in my environment by patching
  nova/objects/console_auth_token.py to extract the path from the
  novncproxy_base_url and add it to the generated console URL.  After
  applying this change, novncproxy works without special considerations
  or configuration, aside from a basic rewrite-target, through a reverse
  proxy.

      @property
      def access_url(self):
          if self.obj_attr_is_set('id'):
              if self.console_type == 'novnc':
                  # extract file path from access_url_base
                  raw_path = path.dirname(urlparse.urlparse(self.access_url_base).path)
                  # remove the leading "/" separately to prevent an exception from occurring
                  # when the URL contains no path.
                  if raw_path[0] == "/":
                      path_arg = raw_path[1:]
                  else:
                      path_arg = raw_path
                  # add the resulting path string before "?token" in the "path" query argument.
                  qparams = {'path': '%s?token=%s' % (path_arg, self.token)}
                  return '%s?%s' % (self.access_url_base,
                                    urlparse.urlencode(qparams))
              else:
                  return '%s?token=%s' % (self.access_url_base, self.token)

  This is the actual patch I applied to
  nova/objects/console_auth_token.py

  21a22
  > from os import path
  73c74,79
  <                 qparams = {'path': '?token=%s' % self.token}
  ---
  >                 raw_path = path.dirname(urlparse.urlparse(self.access_url_base).path)
  >                 if raw_path[0] == "/":
  >                     path_arg = raw_path[1:]
  >                 else:
  >                     path_arg = raw_path
  >                 qparams = {'path': '%s?token=%s' % (path_arg, self.token)}

To manage notifications about this bug go to:
https://bugs.launchpad.net/nova/+bug/1915868/+subscriptions