Browse Source

Merge "Add 'path' query parameter to console access url" into stable/rocky

changes/76/677176/1
Zuul 1 month ago
parent
commit
e4218abdc2

+ 2
- 2
doc/api_samples/os-remote-consoles/get-rdp-console-post-resp.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
     "console": {
3 3
         "type": "rdp-html5",
4
-        "url": "http://127.0.0.1:6083/?token=191996c3-7b0f-42f3-95a7-f1839f2da6ed"
4
+        "url": "http://127.0.0.1:6083/?path=%3Ftoken%3D21efbb20-b84c-4d1f-807d-4e14f6884b7f"
5 5
     }
6
-}
6
+}

+ 2
- 2
doc/api_samples/os-remote-consoles/get-serial-console-post-resp.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
     "console": {
3 3
         "type": "serial",
4
-        "url":"ws://127.0.0.1:6083/?token=f9906a48-b71e-4f18-baca-c987da3ebdb3"
4
+        "url": "ws://127.0.0.1:6083/?path=%3Ftoken%3D6ac46b4c-2705-4d8b-baa3-1b6f1b0c7dd3"
5 5
     }
6
-}
6
+}

+ 1
- 1
doc/api_samples/os-remote-consoles/get-spice-console-post-resp.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
     "console": {
3 3
         "type": "spice-html5",
4
-        "url": "http://127.0.0.1:6082/spice_auto.html?token=a30e5d08-6a20-4043-958f-0852440c6af4"
4
+        "url": "http://127.0.0.1:6082/spice_auto.html?path=%3Ftoken%3Da7bd9607-421c-44b9-8689-18e87ada2f78"
5 5
     }
6 6
 }

+ 1
- 1
doc/api_samples/os-remote-consoles/get-vnc-console-post-resp.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
     "console": {
3 3
         "type": "novnc",
4
-        "url": "http://127.0.0.1:6080/vnc_auto.html?token=191996c3-7b0f-42f3-95a7-f1839f2da6ed"
4
+        "url": "http://127.0.0.1:6080/vnc_auto.html?path=%3Ftoken%3Ddaae261f-474d-4cae-8f6a-1865278ed8c9"
5 5
     }
6 6
 }

+ 1
- 1
doc/api_samples/os-remote-consoles/v2.6/create-vnc-console-resp.json View File

@@ -2,6 +2,6 @@
2 2
     "remote_console": {
3 3
         "protocol": "vnc",
4 4
         "type": "novnc",
5
-        "url": "http://example.com:6080/vnc_auto.html?token=b60bcfc3-5fd4-4d21-986c-e83379107819"
5
+        "url": "http://example.com:6080/vnc_auto.html?path=%3Ftoken%3Db60bcfc3-5fd4-4d21-986c-e83379107819"
6 6
     }
7 7
 }

+ 2
- 2
doc/source/admin/figures/SCH_5009_V00_NUAC-VNC_OpenStack.svg View File

@@ -467,12 +467,12 @@
467 467
 		</g>
468 468
 		<g id="shape53-111" v:mID="53" v:groupContext="shape" transform="translate(38.8888,-154.814)">
469 469
 			<title>Sheet.53</title>
470
-			<desc>Browses the url returned Http://novncip:port/?token=xyz</desc>
470
+			<desc>Browses the url returned Http://novncip:port/?path=%3Ftoken%3Dxyz</desc>
471 471
 			<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
472 472
 			<v:textRect cx="58.9065" cy="303.793" width="117.82" height="25.387"/>
473 473
 			<rect x="0" y="291.1" width="117.813" height="25.387" class="st6"/>
474 474
 			<text x="4" y="301.39" class="st7" v:langID="1036"><v:paragraph/><v:tabList/>Browses the url returned<v:newlineChar/><tspan
475
-						x="4" dy="1.2em" class="st13">Http</tspan>://novncip:port/?token=xyz</text>		</g>
475
+						x="4" dy="1.2em" class="st13">Http</tspan>://novncip:port/?path=%3Ftoken%3Dxyz</text>		</g>
476 476
 		<g id="group28-115" transform="translate(591.296,-147.811)" v:mID="28" v:groupContext="group">
477 477
 			<title>Sheet.28</title>
478 478
 			<g id="shape29-116" v:mID="29" v:groupContext="shape">

+ 1
- 1
doc/source/admin/remote-console-access.rst View File

@@ -76,7 +76,7 @@ access their instances through VNC clients.
76 76
 The VNC console connection works as follows:
77 77
 
78 78
 #. A user connects to the API and gets an ``access_url`` such as,
79
-   ``http://ip:port/?token=xyz``.
79
+   ``http://ip:port/?path=%3Ftoken%3Dxyz``.
80 80
 
81 81
 #. The user pastes the URL in a browser or uses it as a client parameter.
82 82
 

+ 1
- 1
nova/api/openstack/compute/rest_api_version_history.rst View File

@@ -84,7 +84,7 @@ Example response::
84 84
     "remote_console": {
85 85
       "protocol": "vnc",
86 86
       "type": "novnc",
87
-      "url": "http://example.com:6080/vnc_auto.html?token=XYZ"
87
+      "url": "http://example.com:6080/vnc_auto.html?path=%3Ftoken%3DXYZ"
88 88
     }
89 89
   }
90 90
 

+ 4
- 1
nova/objects/console_auth_token.py View File

@@ -18,6 +18,7 @@ from oslo_log import log as logging
18 18
 from oslo_utils import strutils
19 19
 from oslo_utils import timeutils
20 20
 from oslo_utils import uuidutils
21
+import six.moves.urllib.parse as urlparse
21 22
 
22 23
 from nova.db import api as db
23 24
 from nova import exception
@@ -60,7 +61,9 @@ class ConsoleAuthToken(base.NovaTimestampObject, base.NovaObject):
60 61
         specific to this authorization.
61 62
         """
62 63
         if self.obj_attr_is_set('id'):
63
-            return '%s?token=%s' % (self.access_url_base, self.token)
64
+            qparams = {'path': '?token=%s' % self.token}
65
+            return '%s?%s' % (self.access_url_base,
66
+                              urlparse.urlencode(qparams))
64 67
 
65 68
     @staticmethod
66 69
     def _from_db_object(context, obj, db_obj):

+ 1
- 1
nova/tests/functional/api_sample_tests/api_samples/os-remote-consoles/get-rdp-console-post-resp.json.tpl View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
     "console": {
3 3
         "type": "rdp-html5",
4
-        "url": "http://127.0.0.1:6083/?token=%(uuid)s"
4
+        "url": "http://127.0.0.1:6083/?path=%%3Ftoken%%3D%(uuid)s"
5 5
     }
6 6
 }

+ 1
- 1
nova/tests/functional/api_sample_tests/api_samples/os-remote-consoles/get-serial-console-post-resp.json.tpl View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
     "console": {
3 3
         "type": "serial",
4
-        "url": "ws://127.0.0.1:6083/?token=%(uuid)s"
4
+        "url": "ws://127.0.0.1:6083/?path=%%3Ftoken%%3D%(uuid)s"
5 5
     }
6 6
 }

+ 1
- 1
nova/tests/functional/api_sample_tests/api_samples/os-remote-consoles/get-spice-console-post-resp.json.tpl View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
     "console": {
3 3
         "type": "spice-html5",
4
-        "url": "http://127.0.0.1:6082/spice_auto.html?token=%(uuid)s"
4
+        "url": "http://127.0.0.1:6082/spice_auto.html?path=%%3Ftoken%%3D%(uuid)s"
5 5
     }
6 6
 }

+ 1
- 1
nova/tests/functional/api_sample_tests/api_samples/os-remote-consoles/get-vnc-console-post-resp.json.tpl View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
     "console": {
3 3
         "type": "novnc",
4
-        "url": "http://127.0.0.1:6080/vnc_auto.html?token=%(uuid)s"
4
+        "url": "http://127.0.0.1:6080/vnc_auto.html?path=%%3Ftoken%%3D%(uuid)s"
5 5
     }
6 6
 }

+ 3
- 1
nova/tests/functional/api_sample_tests/test_console_auth_tokens.py View File

@@ -15,6 +15,7 @@
15 15
 import re
16 16
 
17 17
 from oslo_serialization import jsonutils
18
+import six.moves.urllib.parse as urlparse
18 19
 
19 20
 from nova.tests.functional.api_sample_tests import test_servers
20 21
 
@@ -32,7 +33,8 @@ class ConsoleAuthTokensSampleJsonTests(test_servers.ServersSampleBase):
32 33
                                  {'action': 'os-getRDPConsole'})
33 34
 
34 35
         url = self._get_console_url(response.content)
35
-        return re.match('.+?token=([^&]+)', url).groups()[0]
36
+        path = urlparse.urlencode({'path': '?token='})
37
+        return re.match('.+?%s([^&]+)' % path, url).groups()[0]
36 38
 
37 39
     def test_get_console_connect_info(self):
38 40
         self.flags(enabled=True, group='rdp')

+ 20
- 16
nova/tests/unit/console/test_websocketproxy.py View File

@@ -18,6 +18,7 @@ import copy
18 18
 import socket
19 19
 
20 20
 import mock
21
+import six.moves.urllib.parse as urlparse
21 22
 
22 23
 import nova.conf
23 24
 from nova.console.securityproxy import base
@@ -47,6 +48,7 @@ class NovaProxyRequestHandlerDBTestCase(test.TestCase):
47 48
         self.wh.msg = mock.MagicMock()
48 49
         self.wh.do_proxy = mock.MagicMock()
49 50
         self.wh.headers = mock.MagicMock()
51
+        self.path = urlparse.urlencode({'path': '?token=123-456-789'})
50 52
 
51 53
     def _fake_console_db(self, **updates):
52 54
         console_db = copy.deepcopy(fake_ca.fake_token_dict)
@@ -96,7 +98,7 @@ class NovaProxyRequestHandlerDBTestCase(test.TestCase):
96 98
             tsock.recv.return_value = "HTTP/1.1 200 OK\r\n\r\n"
97 99
             self.wh.socket.return_value = tsock
98 100
 
99
-        self.wh.path = "http://127.0.0.1/?token=123-456-789"
101
+        self.wh.path = "http://127.0.0.1/?%s" % self.path
100 102
         self.wh.headers = self.fake_header
101 103
 
102 104
         if instance_not_found:
@@ -143,6 +145,8 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
143 145
         self.wh.msg = mock.MagicMock()
144 146
         self.wh.do_proxy = mock.MagicMock()
145 147
         self.wh.headers = mock.MagicMock()
148
+        self.path = urlparse.urlencode({'path': '?token=123-456-789'})
149
+        self.path_invalid = urlparse.urlencode({'path': '?token=XXX'})
146 150
 
147 151
     fake_header = {
148 152
         'cookie': 'token="123-456-789"',
@@ -228,7 +232,7 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
228 232
             'access_url': 'https://example.net:6080'
229 233
         }
230 234
         self.wh.socket.return_value = '<socket>'
231
-        self.wh.path = "http://127.0.0.1/?token=123-456-789"
235
+        self.wh.path = "http://127.0.0.1/?%s" % self.path
232 236
         self.wh.headers = self.fake_header
233 237
 
234 238
         self.wh.new_websocket_client()
@@ -261,7 +265,7 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
261 265
         validate.return_value = objects.ConsoleAuthToken(**params)
262 266
 
263 267
         self.wh.socket.return_value = '<socket>'
264
-        self.wh.path = "http://127.0.0.1/?token=123-456-789"
268
+        self.wh.path = "http://127.0.0.1/?%s" % self.path
265 269
         self.wh.headers = self.fake_header
266 270
 
267 271
         self.wh.new_websocket_client()
@@ -287,7 +291,7 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
287 291
         validate.return_value = objects.ConsoleAuthToken(**params)
288 292
 
289 293
         self.wh.socket.return_value = '<socket>'
290
-        self.wh.path = "http://127.0.0.1/?token=123-456-789"
294
+        self.wh.path = "http://127.0.0.1/?%s" % self.path
291 295
         self.wh.headers = self.fake_header
292 296
 
293 297
         self.wh.new_websocket_client()
@@ -312,7 +316,7 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
312 316
         validate.return_value = objects.ConsoleAuthToken(**params)
313 317
 
314 318
         self.wh.socket.return_value = '<socket>'
315
-        self.wh.path = "http://[2001:db8::1]/?token=123-456-789"
319
+        self.wh.path = "http://[2001:db8::1]/?%s" % self.path
316 320
         self.wh.headers = self.fake_header_ipv6
317 321
 
318 322
         self.wh.new_websocket_client()
@@ -325,7 +329,7 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
325 329
     def test_new_websocket_client_token_invalid(self, validate):
326 330
         validate.side_effect = exception.InvalidToken(token='XXX')
327 331
 
328
-        self.wh.path = "http://127.0.0.1/?token=XXX"
332
+        self.wh.path = "http://127.0.0.1/?%s" % self.path_invalid
329 333
         self.wh.headers = self.fake_header_bad_token
330 334
 
331 335
         self.assertRaises(exception.InvalidToken,
@@ -353,7 +357,7 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
353 357
         tsock.recv.return_value = "HTTP/1.1 200 OK\r\n\r\n"
354 358
 
355 359
         self.wh.socket.return_value = tsock
356
-        self.wh.path = "http://127.0.0.1/?token=123-456-789"
360
+        self.wh.path = "http://127.0.0.1/?%s" % self.path
357 361
         self.wh.headers = self.fake_header
358 362
 
359 363
         self.wh.new_websocket_client()
@@ -386,7 +390,7 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
386 390
         tsock.recv.return_value = "HTTP/1.1 500 Internal Server Error\r\n\r\n"
387 391
 
388 392
         self.wh.socket.return_value = tsock
389
-        self.wh.path = "http://127.0.0.1/?token=123-456-789"
393
+        self.wh.path = "http://127.0.0.1/?%s" % self.path
390 394
         self.wh.headers = self.fake_header
391 395
 
392 396
         self.assertRaises(exception.InvalidConnectionInfo,
@@ -418,7 +422,7 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
418 422
                                   HTTP_RESP]
419 423
 
420 424
         self.wh.socket.return_value = tsock
421
-        self.wh.path = "http://127.0.0.1/?token=123-456-789"
425
+        self.wh.path = "http://127.0.0.1/?%s" % self.path
422 426
         self.wh.headers = self.fake_header
423 427
 
424 428
         self.wh.new_websocket_client()
@@ -448,7 +452,7 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
448 452
         validate.return_value = objects.ConsoleAuthToken(**params)
449 453
 
450 454
         self.wh.socket.return_value = '<socket>'
451
-        self.wh.path = "http://127.0.0.1/?token=123-456-789"
455
+        self.wh.path = "http://127.0.0.1/?%s" % self.path
452 456
         self.wh.headers = self.fake_header
453 457
 
454 458
         self.wh.new_websocket_client()
@@ -468,7 +472,7 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
468 472
             'console_type': 'novnc'
469 473
         }
470 474
         self.wh.socket.return_value = '<socket>'
471
-        self.wh.path = "ws://127.0.0.1/?token=123-456-789"
475
+        self.wh.path = "ws://127.0.0.1/?%s" % self.path
472 476
         self.wh.headers = self.fake_header
473 477
 
474 478
         self.assertRaises(exception.NovaException,
@@ -477,10 +481,9 @@ class NovaProxyRequestHandlerBaseTestCase(test.NoDBTestCase):
477 481
     @mock.patch('socket.getfqdn')
478 482
     def test_address_string_doesnt_do_reverse_dns_lookup(self, getfqdn):
479 483
         request_mock = mock.MagicMock()
480
-        request_mock.makefile().readline.side_effect = [
481
-            b'GET /vnc.html?token=123-456-789 HTTP/1.1\r\n',
482
-            b''
483
-        ]
484
+        msg = 'GET /vnc.html?%s HTTP/1.1\r\n' % self.path
485
+        request_mock.makefile().readline.side_effect = [msg.encode('utf-8'),
486
+                                                        b'']
484 487
         server_mock = mock.MagicMock()
485 488
         client_address = ('8.8.8.8', 54321)
486 489
 
@@ -734,7 +737,8 @@ class NovaWebsocketSecurityProxyTestCase(test.NoDBTestCase):
734 737
         with mock.patch('websockify.ProxyRequestHandler'):
735 738
             self.wh = websocketproxy.NovaProxyRequestHandler()
736 739
         self.wh.server = self.server
737
-        self.wh.path = "http://127.0.0.1/?token=123-456-789"
740
+        path = urlparse.urlencode({'path': '?token=123-456-789'})
741
+        self.wh.path = "http://127.0.0.1/?%s" % path
738 742
         self.wh.socket = mock.MagicMock()
739 743
         self.wh.msg = mock.MagicMock()
740 744
         self.wh.do_proxy = mock.MagicMock()

+ 4
- 3
nova/tests/unit/objects/test_console_auth_token.py View File

@@ -18,6 +18,7 @@ import mock
18 18
 
19 19
 from oslo_db.exception import DBDuplicateEntry
20 20
 from oslo_utils import timeutils
21
+import six.moves.urllib.parse as urlparse
21 22
 
22 23
 from nova import exception
23 24
 from nova.objects import console_auth_token as token_obj
@@ -70,9 +71,9 @@ class _TestConsoleAuthToken(object):
70 71
         self.compare_obj(obj, expected)
71 72
 
72 73
         url = obj.access_url
73
-        expected_url = '%s?token=%s' % (
74
-            fakes.fake_token_dict['access_url_base'],
75
-            fakes.fake_token)
74
+        path = urlparse.urlencode({'path': '?token=%s' % fakes.fake_token})
75
+        expected_url = '%s?%s' % (
76
+            fakes.fake_token_dict['access_url_base'], path)
76 77
         self.assertEqual(expected_url, url)
77 78
 
78 79
     @mock.patch('nova.db.api.console_auth_token_create')

+ 7
- 0
releasenotes/notes/support-novnc-1.1.0-ce677fe3381b2a11.yaml View File

@@ -0,0 +1,7 @@
1
+---
2
+fixes:
3
+  - |
4
+    Add support for noVNC >= v1.1.0 for VNC consoles. Prior to this fix, VNC
5
+    console token validation always failed regardless of actual token validity
6
+    with noVNC >= v1.1.0. See
7
+    https://bugs.launchpad.net/nova/+bug/1822676 for more details.

Loading…
Cancel
Save