|
1 This patch fixes bug 1400966 for Havana. |
|
2 https://bugs.launchpad.net/glance/+bug/1400966 |
|
3 |
|
4 commit 8bdb7ed9f5beaf816e7abba726904646bf3680dd |
|
5 Author: Zhi Yan Liu <[email protected]> |
|
6 Date: Mon Dec 15 12:29:55 2014 +0800 |
|
7 |
|
8 To prevent client use v2 patch api to handle file and swift location |
|
9 |
|
10 The change will be used to restrict client to download and delete any |
|
11 file in glance-api server. The same resone and logic as what we did in |
|
12 v1: |
|
13 https://github.com/openstack/glance/blob/master/glance/api/v1/images.py#L429 |
|
14 |
|
15 Closes-Bug: bug/1400966 |
|
16 DocImpact |
|
17 |
|
18 Conflicts: |
|
19 glance/api/v1/images.py |
|
20 glance/common/store_utils.py |
|
21 glance/location.py |
|
22 glance/tests/functional/v1/test_copy_to_file.py |
|
23 glance/tests/functional/v2/test_images.py |
|
24 glance/tests/unit/test_store_image.py |
|
25 glance/tests/unit/test_store_location.py |
|
26 glance/tests/unit/utils.py |
|
27 glance/tests/unit/v1/test_api.py |
|
28 |
|
29 (cherry picked from commit 4afdb017aa1ccef01482f117cb8d0736a6da38ed) |
|
30 Signed-off-by: Zhi Yan Liu <[email protected]> |
|
31 Change-Id: I72dbead3cb2dcb87f52658ddb880e26880cc229b |
|
32 |
|
33 --- glance-2013.2.3/glance/api/v1/images.py.orig 2014-12-23 08:16:59.633230138 -0800 |
|
34 +++ glance-2013.2.3/glance/api/v1/images.py 2014-12-23 08:19:15.059375018 -0800 |
|
35 @@ -50,7 +50,8 @@ import glance.registry.client.v1.api as |
|
36 from glance.store import (get_from_backend, |
|
37 get_size_from_backend, |
|
38 get_store_from_location, |
|
39 - get_store_from_scheme) |
|
40 + get_store_from_scheme, |
|
41 + validate_external_location) |
|
42 |
|
43 LOG = logging.getLogger(__name__) |
|
44 SUPPORTED_PARAMS = glance.api.v1.SUPPORTED_PARAMS |
|
45 @@ -375,20 +376,19 @@ class Controller(controller.BaseControll |
|
46 @staticmethod |
|
47 def _validate_source(source, req): |
|
48 """ |
|
49 - External sources (as specified via the location or copy-from headers) |
|
50 - are supported only over non-local store types, i.e. S3, Swift, HTTP. |
|
51 - Note the absence of file:// for security reasons, see LP bug #942118. |
|
52 - If the above constraint is violated, we reject with 400 "Bad Request". |
|
53 + To validate if external sources (as specified via the location |
|
54 + or copy-from headers) are supported. Otherwise we reject |
|
55 + with 400 "Bad Request". |
|
56 """ |
|
57 if source: |
|
58 - for scheme in ['s3', 'swift', 'http', 'rbd', 'sheepdog', 'cinder']: |
|
59 - if source.lower().startswith(scheme): |
|
60 - return source |
|
61 - msg = _("External sourcing not supported for store %s") % source |
|
62 - LOG.debug(msg) |
|
63 - raise HTTPBadRequest(explanation=msg, |
|
64 - request=req, |
|
65 - content_type="text/plain") |
|
66 + if validate_external_location(source): |
|
67 + return source |
|
68 + else: |
|
69 + msg = _("External source are not supported: '%s'") % source |
|
70 + LOG.debug(msg) |
|
71 + raise HTTPBadRequest(explanation=msg, |
|
72 + request=req, |
|
73 + content_type="text/plain") |
|
74 |
|
75 @staticmethod |
|
76 def _copy_from(req): |
|
77 --- glance-2013.2.3/glance/store/__init__.py.orig 2014-12-23 08:20:52.254600393 -0800 |
|
78 +++ glance-2013.2.3/glance/store/__init__.py 2014-12-23 08:23:48.661399000 -0800 |
|
79 @@ -21,6 +21,7 @@ import sys |
|
80 import time |
|
81 |
|
82 from oslo.config import cfg |
|
83 +import six.moves.urllib.parse as urlparse |
|
84 |
|
85 from glance.common import crypt |
|
86 from glance.common import exception |
|
87 @@ -369,6 +370,24 @@ def set_acls(context, location_uri, publ |
|
88 LOG.debug(_("Skipping store.set_acls... not implemented.")) |
|
89 |
|
90 |
|
91 +def validate_external_location(uri): |
|
92 + """ |
|
93 + Validate if URI of external location are supported. |
|
94 + |
|
95 + Only over non-local store types are OK, i.e. S3, Swift, |
|
96 + HTTP. Note the absence of 'file://' for security reasons, |
|
97 + see LP bug #942118, 1400966, 'swift+config://' is also |
|
98 + absent for security reasons, see LP bug #1334196. |
|
99 + |
|
100 + :param uri: The URI of external image location. |
|
101 + :return: Whether given URI of external image location are OK. |
|
102 + """ |
|
103 + pieces = urlparse.urlparse(uri) |
|
104 + valid_schemes = [scheme for scheme in location.SCHEME_TO_CLS_MAP.keys() |
|
105 + if scheme != 'file' and scheme != 'swift+config'] |
|
106 + return pieces.scheme in valid_schemes |
|
107 + |
|
108 + |
|
109 class ImageRepoProxy(glance.domain.proxy.Repo): |
|
110 |
|
111 def __init__(self, image_repo, context, store_api): |
|
112 @@ -401,22 +420,23 @@ class ImageRepoProxy(glance.domain.proxy |
|
113 |
|
114 |
|
115 def _check_location_uri(context, store_api, uri): |
|
116 - """ |
|
117 - Check if an image location uri is valid. |
|
118 + """Check if an image location is valid. |
|
119 |
|
120 :param context: Glance request context |
|
121 :param store_api: store API module |
|
122 :param uri: location's uri string |
|
123 """ |
|
124 + |
|
125 is_ok = True |
|
126 try: |
|
127 - size = store_api.get_size_from_backend(context, uri) |
|
128 # NOTE(zhiyan): Some stores return zero when it catch exception |
|
129 - is_ok = size > 0 |
|
130 + is_ok = (store_api.validate_external_location(uri) and |
|
131 + store_api.get_size_from_backend(context, uri) > 0) |
|
132 except (exception.UnknownScheme, exception.NotFound): |
|
133 is_ok = False |
|
134 if not is_ok: |
|
135 - raise exception.BadStoreUri(_('Invalid location: %s') % uri) |
|
136 + reason = _('Invalid location') |
|
137 + raise exception.BadStoreUri(message=reason) |
|
138 |
|
139 |
|
140 def _check_image_location(context, store_api, location): |