Repository: Kinto/kinto

Issue:
Crash in authz policy with invalid characters in bucket id
```
{"Pid":3109,"EnvVersion":"2.0","Hostname":"ip-172-31-2-114","Timestamp":1479738668906000000,"Fields":{"lang":null,"exception":"Traceback (most recent call last):\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/pyramid\/tweens.py\", line 22, in excview_tween\n    response = handler(request)\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/pyramid_tm\/__init__.py\", line 109, in tm_tween\n    reraise(*exc_info)\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/pyramid_tm\/__init__.py\", line 88, in tm_tween\n    response = handler(request)\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/pyramid\/router.py\", line 127, in handle_request\n    root = root_factory(request)\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/kinto\/core\/authorization.py\", line 144, in __init__\n    self._find_required_permission(request, service))\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/kinto\/core\/authorization.py\", line 237, in _find_required_permission\n    collection_path = service.collection_path.format(**request.matchdict)\nUnicodeEncodeError: 'ascii' codec can't encode characters in position 5-6: ordinal not in range(128)","uid":null,"errno":null,"querystring":"{}","agent":"Amazon CloudFront","method":"GET","path":"\/v1\/buckets\/block%C2%93%C2%96sts\/collections\/certificates","authn_type":null},"Logger":"kinto","Type":["ascii","block\u0093\u0096sts",5,7,"ordinal not in range(128)"],"Severity":2}
```
Crash in authz policy with invalid characters in bucket id
```
{"Pid":3109,"EnvVersion":"2.0","Hostname":"ip-172-31-2-114","Timestamp":1479738668906000000,"Fields":{"lang":null,"exception":"Traceback (most recent call last):\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/pyramid\/tweens.py\", line 22, in excview_tween\n    response = handler(request)\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/pyramid_tm\/__init__.py\", line 109, in tm_tween\n    reraise(*exc_info)\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/pyramid_tm\/__init__.py\", line 88, in tm_tween\n    response = handler(request)\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/pyramid\/router.py\", line 127, in handle_request\n    root = root_factory(request)\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/kinto\/core\/authorization.py\", line 144, in __init__\n    self._find_required_permission(request, service))\n  File \"\/data\/kinto-dist\/lib\/python2.7\/site-packages\/kinto\/core\/authorization.py\", line 237, in _find_required_permission\n    collection_path = service.collection_path.format(**request.matchdict)\nUnicodeEncodeError: 'ascii' codec can't encode characters in position 5-6: ordinal not in range(128)","uid":null,"errno":null,"querystring":"{}","agent":"Amazon CloudFront","method":"GET","path":"\/v1\/buckets\/block%C2%93%C2%96sts\/collections\/certificates","authn_type":null},"Logger":"kinto","Type":["ascii","block\u0093\u0096sts",5,7,"ordinal not in range(128)"],"Severity":2}
```


Discussion:

Resolving patch:
diff --git a/kinto/core/authorization.py b/kinto/core/authorization.py
--- a/kinto/core/authorization.py
+++ b/kinto/core/authorization.py
@@ -1,5 +1,6 @@
 import functools
 
+import six
 from pyramid.settings import aslist
 from pyramid.security import IAuthorizationPolicy, Authenticated
 from zope.interface import implementer
@@ -234,7 +235,8 @@ def _find_required_permission(self, request, service):
         required_permission = self.method_permissions.get(method)
 
         # For create permission, the object id is the plural endpoint.
-        collection_path = service.collection_path.format(**request.matchdict)
+        collection_path = six.text_type(service.collection_path)
+        collection_path = collection_path.format(**request.matchdict)
 
         # In the case of a "PUT", check if the targetted record already
         # exists, return "write" if it does, "create" otherwise.


Test patch:
diff --git a/tests/test_views_objects_permissions.py b/tests/test_views_objects_permissions.py
--- a/tests/test_views_objects_permissions.py
+++ b/tests/test_views_objects_permissions.py
@@ -77,6 +77,11 @@ def setUp(self):
                           MINIMALIST_COLLECTION,
                           headers=self.headers)
 
+    def test_passing_unicode_on_parent_id_is_supported(self):
+        self.app.get('/buckets/block%C2%93%C2%96sts/collections/barley',
+                     headers=self.alice_headers,
+                     status=403)
+
     def test_read_is_allowed_if_read_on_bucket(self):
         self.app.get('/buckets/beer/collections/barley',
                      headers=self.alice_headers)