|
1 | 1 | # -*- coding: utf-8 -*- |
2 | 2 | # Copyright (c) 2017-2019, Shengpeng Liu. All rights reserved. |
| 3 | +# Copyright (c) 2019, Alex Ford. All rights reserved. |
3 | 4 | # Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved. |
4 | 5 |
|
5 | 6 | from tornado import web |
|
8 | 9 | from notebook.utils import url_path_join as ujoin |
9 | 10 | from notebook.base.handlers import path_regex |
10 | 11 |
|
11 | | -try: |
12 | | - import wrapt |
13 | | - @wrapt.patch_function_wrapper(web.RequestHandler, 'check_xsrf_cookie') |
14 | | - def translate_check_xsrf_cookie(wrapped, instance, args, kwargs): |
15 | | - |
16 | | - if ((instance.request.headers.get("X-XSRF-TOKEN")) and |
17 | | - not (instance.get_argument("_xsrf", None) |
18 | | - or instance.request.headers.get("X-Xsrftoken") |
19 | | - or instance.request.headers.get("X-Csrftoken"))): |
20 | | - |
21 | | - instance.request.headers.add("X-Xsrftoken", instance.request.headers.get("X-XSRF-TOKEN")) |
22 | | - |
23 | | - wrapped(*args, **kwargs) |
24 | | -except: |
25 | | - pass |
26 | | - |
27 | | - |
28 | 12 | notebook_dir = None |
29 | 13 |
|
30 | 14 | def load_jupyter_server_extension(nb_app): |
@@ -70,7 +54,6 @@ def load_jupyter_server_extension(nb_app): |
70 | 54 |
|
71 | 55 | class TensorboardHandler(IPythonHandler): |
72 | 56 |
|
73 | | - |
74 | 57 | def _impl(self, name, path): |
75 | 58 |
|
76 | 59 | self.request.path = path |
@@ -105,6 +88,74 @@ def post(self, name, path): |
105 | 88 |
|
106 | 89 | self._impl(name, path) |
107 | 90 |
|
| 91 | + def check_xsrf_cookie(self): |
| 92 | + """Expand XSRF check exceptions for POST requests. |
| 93 | +
|
| 94 | + For TensorBoard versions <= 2.4.x, expand check_xsrf_cookie exceptions, |
| 95 | + normally only applied to GET and HEAD requests, to POST requests |
| 96 | + for TensorBoard API calls, as TensorBoard doesn't return back the |
| 97 | + header used for XSRF checks. |
| 98 | +
|
| 99 | + Provides support for TensorBoard plugins that use POST to retrieve |
| 100 | + experiment information. |
| 101 | +
|
| 102 | + """ |
| 103 | + |
| 104 | + # Set our own expectations as to whether TB will implement this |
| 105 | + # See https://github.com/tensorflow/tensorboard/issues/4685 |
| 106 | + # Presently assuming TB > 2.4 will fix this |
| 107 | + from distutils.version import LooseVersion |
| 108 | + import tensorboard as tb |
| 109 | + tb_has_xsrf = (LooseVersion(tb.__version__) >= LooseVersion("2.5")) |
| 110 | + |
| 111 | + # Check whether any XSRF token is provided |
| 112 | + req_has_xsrf = (self.get_argument("_xsrf", None) |
| 113 | + or self.request.headers.get("X-Xsrftoken") |
| 114 | + or self.request.headers.get("X-Csrftoken")) |
| 115 | + |
| 116 | + # If applicable, translate Angular's XSRF header to Tornado's name |
| 117 | + if (self.request.headers.get("X-XSRF-TOKEN") and not req_has_xsrf): |
| 118 | + |
| 119 | + self.request.headers.add("X-Xsrftoken", |
| 120 | + self.request.headers.get("X-XSRF-TOKEN")) |
| 121 | + |
| 122 | + req_has_xsrf = True |
| 123 | + |
| 124 | + |
| 125 | + # Check XSRF token |
| 126 | + try: |
| 127 | + return super(TensorboardHandler, self).check_xsrf_cookie() |
| 128 | + |
| 129 | + except web.HTTPError: |
| 130 | + # Note: GET and HEAD exceptions are already handled in |
| 131 | + # IPythonHandler.check_xsrf_cookie and will not normally throw 403 |
| 132 | + |
| 133 | + # If the request had one of the XSRF tokens, or if TB > 2.4.x, |
| 134 | + # then no exceptions, and we're done |
| 135 | + if req_has_xsrf or tb_has_xsrf: |
| 136 | + raise |
| 137 | + |
| 138 | + # Otherwise, we must loosen our expectations a bit. IPythonHandler |
| 139 | + # has some existing exceptions to consider a matching Referer as |
| 140 | + # sufficient for GET and HEAD requests; we extend that here to POST |
| 141 | + # for TB versions <= 2.4.x that don't handle XSRF tokens |
| 142 | + |
| 143 | + if self.request.method in {"POST"}: |
| 144 | + # Consider Referer a sufficient cross-origin check, mirroring |
| 145 | + # logic in IPythonHandler.check_xsrf_cookie. |
| 146 | + if not self.check_referer(): |
| 147 | + referer = self.request.headers.get("Referer") |
| 148 | + if referer: |
| 149 | + msg = ( |
| 150 | + "Blocking Cross Origin request from {}." |
| 151 | + .format(referer) |
| 152 | + ) |
| 153 | + else: |
| 154 | + msg = "Blocking request from unknown origin" |
| 155 | + raise web.HTTPError(403, msg) |
| 156 | + else: |
| 157 | + raise |
| 158 | + |
108 | 159 |
|
109 | 160 | class TbFontHandler(IPythonHandler): |
110 | 161 |
|
|
0 commit comments