Make ACLs work with Unicode in user/account names

There were two separate complications:

  - Account ACLs are stored as JSON, so they were getting deserialized
    to Unicode. That's fine for ASCII names (as u'a' == b'a' under py2),
    but not arbitrary Unicode (as u'\u1234' != u'\u1234'.encode('utf8')
    for both py2 and py3). So, under py2, encode all account ACL members
    as UTF-8.

  - Container ACLs are stored as comma-separated values in a header, but
    values may contain arbitrary characters including not only non-ASCII
    Unicode but also commas and newlines. Fortunately, we have precedent
    for using URL-encoding in headers to resolve this. See crypto,
    symlink, dlo, versioned_writes, copy...

Change-Id: I37a97bb9d039a963c7cc57bd97876d0ec2134cf1
Partial-Bug: 1774238
This commit is contained in:
Tim Burke 2018-05-29 16:37:42 -07:00
parent 7cec5a8fdb
commit 9d0162a793

View File

@ -14,6 +14,8 @@
# limitations under the License.
import json
import six
from six.moves.urllib.parse import unquote
from swift.common.utils import urlparse
@ -200,7 +202,7 @@ def parse_acl_v1(acl_string):
if value.startswith('.r:'):
referrers.append(value[len('.r:'):])
else:
groups.append(value)
groups.append(unquote(value))
return referrers, groups
@ -293,8 +295,13 @@ def acls_from_account_info(info):
readonly_members = acl.get('read-only', [])
if not any((admin_members, readwrite_members, readonly_members)):
return None
return {
acls = {
'admin': admin_members,
'read-write': readwrite_members,
'read-only': readonly_members,
}
if six.PY2:
for k in ('admin', 'read-write', 'read-only'):
acls[k] = [v.encode('utf8') for v in acls[k]]
return acls