| OLD | NEW |
| 1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
| 2 # Copyright 2013 Google Inc. All Rights Reserved. | 2 # Copyright 2013 Google Inc. All Rights Reserved. |
| 3 # | 3 # |
| 4 # Licensed under the Apache License, Version 2.0 (the "License"); | 4 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 # you may not use this file except in compliance with the License. | 5 # you may not use this file except in compliance with the License. |
| 6 # You may obtain a copy of the License at | 6 # You may obtain a copy of the License at |
| 7 # | 7 # |
| 8 # http://www.apache.org/licenses/LICENSE-2.0 | 8 # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 # | 9 # |
| 10 # Unless required by applicable law or agreed to in writing, software | 10 # Unless required by applicable law or agreed to in writing, software |
| 11 # distributed under the License is distributed on an "AS IS" BASIS, | 11 # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 # See the License for the specific language governing permissions and | 13 # See the License for the specific language governing permissions and |
| 14 # limitations under the License. | 14 # limitations under the License. |
| 15 """Integration tests for the acl command.""" | 15 """Integration tests for the acl command.""" |
| 16 | 16 |
| 17 import gslib.tests.testcase as testcase | 17 from __future__ import absolute_import |
| 18 |
| 18 import re | 19 import re |
| 19 | 20 |
| 20 from gslib import aclhelpers | 21 from gslib import aclhelpers |
| 21 from gslib.command import CreateGsutilLogger | 22 from gslib.command import CreateGsutilLogger |
| 23 from gslib.storage_url import StorageUrlFromString |
| 24 import gslib.tests.testcase as testcase |
| 25 from gslib.tests.testcase.integration_testcase import SkipForGS |
| 26 from gslib.tests.testcase.integration_testcase import SkipForS3 |
| 22 from gslib.tests.util import ObjectToURI as suri | 27 from gslib.tests.util import ObjectToURI as suri |
| 23 from gslib.tests.util import SetBotoConfigForTest | 28 from gslib.translation_helper import AclTranslation |
| 24 from gslib.util import Retry | |
| 25 | 29 |
| 26 PUBLIC_READ_ACL_TEXT = '<Scope type="AllUsers"/><Permission>READ</Permission>' | 30 PUBLIC_READ_JSON_ACL_TEXT = '"entity":"allUsers","role":"READER"' |
| 27 | 31 |
| 28 | 32 |
| 29 class TestAcl(testcase.GsUtilIntegrationTestCase): | 33 class TestAclBase(testcase.GsUtilIntegrationTestCase): |
| 30 """Integration tests for acl command.""" | 34 """Integration test case base class for acl command.""" |
| 31 | 35 |
| 32 _set_acl_prefix = ['acl', 'set'] | 36 _set_acl_prefix = ['acl', 'set'] |
| 33 _get_acl_prefix = ['acl', 'get'] | 37 _get_acl_prefix = ['acl', 'get'] |
| 34 _set_defacl_prefix = ['defacl', 'set'] | 38 _set_defacl_prefix = ['defacl', 'set'] |
| 35 _ch_acl_prefix = ['acl', 'ch'] | 39 _ch_acl_prefix = ['acl', 'ch'] |
| 36 | 40 |
| 41 |
| 42 @SkipForS3('Tests use GS ACL model.') |
| 43 class TestAcl(TestAclBase): |
| 44 """Integration tests for acl command.""" |
| 45 |
| 37 def setUp(self): | 46 def setUp(self): |
| 38 super(TestAcl, self).setUp() | 47 super(TestAcl, self).setUp() |
| 39 self.sample_uri = self.CreateBucket() | 48 self.sample_uri = self.CreateBucket() |
| 49 self.sample_url = StorageUrlFromString(str(self.sample_uri)) |
| 40 self.logger = CreateGsutilLogger('acl') | 50 self.logger = CreateGsutilLogger('acl') |
| 41 | 51 |
| 42 def test_set_invalid_acl_object(self): | 52 def test_set_invalid_acl_object(self): |
| 43 """Ensures that invalid XML content returns a MalformedACLError.""" | 53 """Ensures that invalid content returns a bad request error.""" |
| 44 obj_uri = suri(self.CreateObject(contents='foo')) | 54 obj_uri = suri(self.CreateObject(contents='foo')) |
| 45 inpath = self.CreateTempFile(contents='badXml') | 55 inpath = self.CreateTempFile(contents='badAcl') |
| 46 stderr = self.RunGsUtil(self._set_acl_prefix + [inpath, obj_uri], | 56 stderr = self.RunGsUtil(self._set_acl_prefix + [inpath, obj_uri], |
| 47 return_stderr=True, expected_status=1) | 57 return_stderr=True, expected_status=1) |
| 48 | 58 self.assertIn('ArgumentException', stderr) |
| 49 self.assertIn('MalformedACLError', stderr) | |
| 50 | 59 |
| 51 def test_set_invalid_acl_bucket(self): | 60 def test_set_invalid_acl_bucket(self): |
| 52 """Ensures that invalid XML content returns a MalformedACLError.""" | 61 """Ensures that invalid content returns a bad request error.""" |
| 53 bucket_uri = suri(self.CreateBucket()) | 62 bucket_uri = suri(self.CreateBucket()) |
| 54 inpath = self.CreateTempFile(contents='badXml') | 63 inpath = self.CreateTempFile(contents='badAcl') |
| 55 stderr = self.RunGsUtil(self._set_acl_prefix + [inpath, bucket_uri], | 64 stderr = self.RunGsUtil(self._set_acl_prefix + [inpath, bucket_uri], |
| 56 return_stderr=True, expected_status=1) | 65 return_stderr=True, expected_status=1) |
| 66 self.assertIn('ArgumentException', stderr) |
| 57 | 67 |
| 58 self.assertIn('MalformedACLError', stderr) | 68 def test_set_xml_acl_json_api_object(self): |
| 69 """Ensures XML content returns a bad request error and migration warning.""" |
| 70 obj_uri = suri(self.CreateObject(contents='foo')) |
| 71 inpath = self.CreateTempFile(contents='<ValidXml></ValidXml>') |
| 72 stderr = self.RunGsUtil(self._set_acl_prefix + [inpath, obj_uri], |
| 73 return_stderr=True, expected_status=1) |
| 74 self.assertIn('ArgumentException', stderr) |
| 75 self.assertIn('XML ACL data provided', stderr) |
| 76 |
| 77 def test_set_xml_acl_json_api_bucket(self): |
| 78 """Ensures XML content returns a bad request error and migration warning.""" |
| 79 bucket_uri = suri(self.CreateBucket()) |
| 80 inpath = self.CreateTempFile(contents='<ValidXml></ValidXml>') |
| 81 stderr = self.RunGsUtil(self._set_acl_prefix + [inpath, bucket_uri], |
| 82 return_stderr=True, expected_status=1) |
| 83 self.assertIn('ArgumentException', stderr) |
| 84 self.assertIn('XML ACL data provided', stderr) |
| 59 | 85 |
| 60 def test_set_valid_acl_object(self): | 86 def test_set_valid_acl_object(self): |
| 61 """Ensures that valid canned and XML ACLs work with get/set.""" | 87 """Tests setting a valid ACL on an object.""" |
| 62 obj_uri = suri(self.CreateObject(contents='foo')) | 88 obj_uri = suri(self.CreateObject(contents='foo')) |
| 63 acl_string = self.RunGsUtil(self._get_acl_prefix + [obj_uri], | 89 acl_string = self.RunGsUtil(self._get_acl_prefix + [obj_uri], |
| 64 return_stdout=True) | 90 return_stdout=True) |
| 65 inpath = self.CreateTempFile(contents=acl_string) | 91 inpath = self.CreateTempFile(contents=acl_string) |
| 66 self.RunGsUtil(self._set_acl_prefix + ['public-read', obj_uri]) | 92 self.RunGsUtil(self._set_acl_prefix + ['public-read', obj_uri]) |
| 67 acl_string2 = self.RunGsUtil(self._get_acl_prefix + [obj_uri], | 93 acl_string2 = self.RunGsUtil(self._get_acl_prefix + [obj_uri], |
| 68 return_stdout=True) | 94 return_stdout=True) |
| 69 self.RunGsUtil(self._set_acl_prefix + [inpath, obj_uri]) | 95 self.RunGsUtil(self._set_acl_prefix + [inpath, obj_uri]) |
| 70 acl_string3 = self.RunGsUtil(self._get_acl_prefix + [obj_uri], | 96 acl_string3 = self.RunGsUtil(self._get_acl_prefix + [obj_uri], |
| 71 return_stdout=True) | 97 return_stdout=True) |
| 72 | 98 |
| 73 self.assertNotEqual(acl_string, acl_string2) | 99 self.assertNotEqual(acl_string, acl_string2) |
| 74 self.assertEqual(acl_string, acl_string3) | 100 self.assertEqual(acl_string, acl_string3) |
| 75 | 101 |
| 76 def test_set_valid_permission_whitespace_object(self): | 102 def test_set_valid_permission_whitespace_object(self): |
| 77 """Ensures that whitespace is allowed in <Permission> elements.""" | 103 """Ensures that whitespace is allowed in role and entity elements.""" |
| 78 obj_uri = suri(self.CreateObject(contents='foo')) | 104 obj_uri = suri(self.CreateObject(contents='foo')) |
| 79 acl_string = self.RunGsUtil(self._get_acl_prefix + [obj_uri], | 105 acl_string = self.RunGsUtil(self._get_acl_prefix + [obj_uri], |
| 80 return_stdout=True) | 106 return_stdout=True) |
| 81 acl_string = re.sub(r'<Permission>', r'<Permission> \n', acl_string) | 107 acl_string = re.sub(r'"role"', r'"role" \n', acl_string) |
| 82 acl_string = re.sub(r'</Permission>', r'\n </Permission>', acl_string) | 108 acl_string = re.sub(r'"entity"', r'\n "entity"', acl_string) |
| 83 inpath = self.CreateTempFile(contents=acl_string) | 109 inpath = self.CreateTempFile(contents=acl_string) |
| 84 | 110 |
| 85 self.RunGsUtil(self._set_acl_prefix + [inpath, obj_uri]) | 111 self.RunGsUtil(self._set_acl_prefix + [inpath, obj_uri]) |
| 86 | 112 |
| 87 def test_set_valid_acl_bucket(self): | 113 def test_set_valid_acl_bucket(self): |
| 88 """Ensures that valid canned and XML ACLs work with get/set.""" | 114 """Ensures that valid canned and XML ACLs work with get/set.""" |
| 89 bucket_uri = suri(self.CreateBucket()) | 115 bucket_uri = suri(self.CreateBucket()) |
| 90 acl_string = self.RunGsUtil(self._get_acl_prefix + [bucket_uri], | 116 acl_string = self.RunGsUtil(self._get_acl_prefix + [bucket_uri], |
| 91 return_stdout=True) | 117 return_stdout=True) |
| 92 inpath = self.CreateTempFile(contents=acl_string) | 118 inpath = self.CreateTempFile(contents=acl_string) |
| 93 self.RunGsUtil(self._set_acl_prefix + ['public-read', bucket_uri]) | 119 self.RunGsUtil(self._set_acl_prefix + ['public-read', bucket_uri]) |
| 94 acl_string2 = self.RunGsUtil(self._get_acl_prefix + [bucket_uri], | 120 acl_string2 = self.RunGsUtil(self._get_acl_prefix + [bucket_uri], |
| 95 return_stdout=True) | 121 return_stdout=True) |
| 96 self.RunGsUtil(self._set_acl_prefix + [inpath, bucket_uri]) | 122 self.RunGsUtil(self._set_acl_prefix + [inpath, bucket_uri]) |
| 97 acl_string3 = self.RunGsUtil(self._get_acl_prefix + [bucket_uri], | 123 acl_string3 = self.RunGsUtil(self._get_acl_prefix + [bucket_uri], |
| 98 return_stdout=True) | 124 return_stdout=True) |
| 99 | 125 |
| 100 self.assertNotEqual(acl_string, acl_string2) | 126 self.assertNotEqual(acl_string, acl_string2) |
| 101 self.assertEqual(acl_string, acl_string3) | 127 self.assertEqual(acl_string, acl_string3) |
| 102 | 128 |
| 103 def test_get_and_set_valid_object_acl_with_non_ascii_chars(self): | |
| 104 """Ensures that non-ASCII chars work correctly in ACL handling.""" | |
| 105 acl_entry_str = """ | |
| 106 <Entry> | |
| 107 <Scope type="UserByEmail"> | |
| 108 <EmailAddress>gs-team@google.com</EmailAddress> | |
| 109 <Name>%s</Name> | |
| 110 </Scope> | |
| 111 <Permission>READ</Permission> | |
| 112 </Entry> | |
| 113 """ | |
| 114 non_ascii_name = u'Test NonAscii łرØì•ˆ' | |
| 115 acl_entry_str = acl_entry_str % non_ascii_name | |
| 116 obj_uri = self.CreateObject(contents='foo') | |
| 117 stdout = self.RunGsUtil(self._get_acl_prefix + [suri(obj_uri)], | |
| 118 return_stdout=True) | |
| 119 new_acl_str = re.sub('</Entries>', '%s</Entries>' % acl_entry_str, stdout) | |
| 120 acl_path = self.CreateTempFile(contents=new_acl_str.encode('utf-8')) | |
| 121 self.RunGsUtil(self._set_acl_prefix + [acl_path, suri(obj_uri)]) | |
| 122 res_acl_str = self.RunGsUtil(self._get_acl_prefix + [suri(obj_uri)], | |
| 123 return_stdout=True) | |
| 124 self.assertIn(non_ascii_name.encode('utf-8'), res_acl_str) | |
| 125 | |
| 126 def test_invalid_canned_acl_object(self): | 129 def test_invalid_canned_acl_object(self): |
| 127 """Ensures that an invalid canned ACL returns a CommandException.""" | 130 """Ensures that an invalid canned ACL returns a CommandException.""" |
| 128 obj_uri = suri(self.CreateObject(contents='foo')) | 131 obj_uri = suri(self.CreateObject(contents='foo')) |
| 129 stderr = self.RunGsUtil(self._set_acl_prefix + ['not-a-canned-acl', | 132 stderr = self.RunGsUtil( |
| 130 obj_uri], return_stderr=True, expected_status=1) | 133 self._set_acl_prefix + ['not-a-canned-acl', obj_uri], |
| 134 return_stderr=True, expected_status=1) |
| 131 self.assertIn('CommandException', stderr) | 135 self.assertIn('CommandException', stderr) |
| 132 self.assertIn('Invalid canned ACL', stderr) | 136 self.assertIn('Invalid canned ACL', stderr) |
| 133 | 137 |
| 134 def test_set_valid_def_acl_bucket(self): | 138 def test_set_valid_def_acl_bucket(self): |
| 135 """Ensures that valid default canned and XML ACLs works with get/set.""" | 139 """Ensures that valid default canned and XML ACLs works with get/set.""" |
| 136 bucket_uri = self.CreateBucket() | 140 bucket_uri = self.CreateBucket() |
| 137 | 141 |
| 138 # Default ACL is project private. | 142 # Default ACL is project private. |
| 139 obj_uri1 = suri(self.CreateObject(bucket_uri=bucket_uri, contents='foo')) | 143 obj_uri1 = suri(self.CreateObject(bucket_uri=bucket_uri, contents='foo')) |
| 140 acl_string = self.RunGsUtil(self._get_acl_prefix + [obj_uri1], | 144 acl_string = self.RunGsUtil(self._get_acl_prefix + [obj_uri1], |
| 141 return_stdout=True) | 145 return_stdout=True) |
| 142 | 146 |
| 143 # Change it to authenticated-read. | 147 # Change it to authenticated-read. |
| 144 self.RunGsUtil( | 148 self.RunGsUtil( |
| 145 self._set_defacl_prefix + ['authenticated-read', suri(bucket_uri)]) | 149 self._set_defacl_prefix + ['authenticated-read', suri(bucket_uri)]) |
| 146 obj_uri2 = suri(self.CreateObject(bucket_uri=bucket_uri, contents='foo2')) | 150 obj_uri2 = suri(self.CreateObject(bucket_uri=bucket_uri, contents='foo2')) |
| 147 acl_string2 = self.RunGsUtil(self._get_acl_prefix + [obj_uri2], | 151 acl_string2 = self.RunGsUtil(self._get_acl_prefix + [obj_uri2], |
| 148 return_stdout=True) | 152 return_stdout=True) |
| 149 | 153 |
| 150 # Now change it back to the default via XML. | 154 # Now change it back to the default via XML. |
| 151 inpath = self.CreateTempFile(contents=acl_string) | 155 inpath = self.CreateTempFile(contents=acl_string) |
| 152 self.RunGsUtil(self._set_defacl_prefix + [inpath, suri(bucket_uri)]) | 156 self.RunGsUtil(self._set_defacl_prefix + [inpath, suri(bucket_uri)]) |
| 153 obj_uri3 = suri(self.CreateObject(bucket_uri=bucket_uri, contents='foo3')) | 157 obj_uri3 = suri(self.CreateObject(bucket_uri=bucket_uri, contents='foo3')) |
| 154 acl_string3 = self.RunGsUtil(self._get_acl_prefix + [obj_uri3], | 158 acl_string3 = self.RunGsUtil(self._get_acl_prefix + [obj_uri3], |
| 155 return_stdout=True) | 159 return_stdout=True) |
| 156 | 160 |
| 157 self.assertNotEqual(acl_string, acl_string2) | 161 self.assertNotEqual(acl_string, acl_string2) |
| 158 self.assertIn('AllAuthenticatedUsers', acl_string2) | 162 self.assertIn('allAuthenticatedUsers', acl_string2) |
| 159 self.assertEqual(acl_string, acl_string3) | 163 self.assertEqual(acl_string, acl_string3) |
| 160 | 164 |
| 161 def test_acl_set_version_specific_uri(self): | 165 def test_acl_set_version_specific_uri(self): |
| 166 """Tests setting an ACL on a specific version of an object.""" |
| 162 bucket_uri = self.CreateVersionedBucket() | 167 bucket_uri = self.CreateVersionedBucket() |
| 163 # Create initial object version. | 168 # Create initial object version. |
| 164 uri = self.CreateObject(bucket_uri=bucket_uri, contents='data') | 169 uri = self.CreateObject(bucket_uri=bucket_uri, contents='data') |
| 165 # Create a second object version. | 170 # Create a second object version. |
| 166 inpath = self.CreateTempFile(contents='def') | 171 inpath = self.CreateTempFile(contents='def') |
| 167 self.RunGsUtil(['cp', inpath, uri.uri]) | 172 self.RunGsUtil(['cp', inpath, uri.uri]) |
| 168 | 173 |
| 169 # Find out the two object version IDs. | 174 # Find out the two object version IDs. |
| 170 # Use @Retry as hedge against bucket listing eventual consistency. | 175 lines = self.AssertNObjectsInBucket(bucket_uri, 2, versioned=True) |
| 171 @Retry(AssertionError, tries=3, timeout_secs=1) | 176 v0_uri_str, v1_uri_str = lines[0], lines[1] |
| 172 def _GetVersions(): | |
| 173 stdout = self.RunGsUtil(['ls', '-a', uri.uri], return_stdout=True) | |
| 174 lines = stdout.split('\n') | |
| 175 # There should be 3 lines, counting final \n. | |
| 176 self.assertEqual(len(lines), 3) | |
| 177 return lines[0], lines[1] | |
| 178 | |
| 179 v0_uri_str, v1_uri_str = _GetVersions() | |
| 180 | 177 |
| 181 # Check that neither version currently has public-read permission | 178 # Check that neither version currently has public-read permission |
| 182 # (default ACL is project-private). | 179 # (default ACL is project-private). |
| 183 orig_acls = [] | 180 orig_acls = [] |
| 184 for uri_str in (v0_uri_str, v1_uri_str): | 181 for uri_str in (v0_uri_str, v1_uri_str): |
| 185 acl = self.RunGsUtil(self._get_acl_prefix + [uri_str], return_stdout=True) | 182 acl = self.RunGsUtil(self._get_acl_prefix + [uri_str], |
| 186 self.assertNotIn(PUBLIC_READ_ACL_TEXT, self._strip_xml_whitespace(acl)) | 183 return_stdout=True) |
| 184 self.assertNotIn(PUBLIC_READ_JSON_ACL_TEXT, |
| 185 self._strip_json_whitespace(acl)) |
| 187 orig_acls.append(acl) | 186 orig_acls.append(acl) |
| 188 | 187 |
| 189 # Set the ACL for the older version of the object to public-read. | 188 # Set the ACL for the older version of the object to public-read. |
| 190 self.RunGsUtil(self._set_acl_prefix + ['public-read', v0_uri_str]) | 189 self.RunGsUtil(self._set_acl_prefix + ['public-read', v0_uri_str]) |
| 191 # Check that the older version's ACL is public-read, but newer version | 190 # Check that the older version's ACL is public-read, but newer version |
| 192 # is not. | 191 # is not. |
| 193 acl = self.RunGsUtil(self._get_acl_prefix + [v0_uri_str], | 192 acl = self.RunGsUtil(self._get_acl_prefix + [v0_uri_str], |
| 194 return_stdout=True) | 193 return_stdout=True) |
| 195 self.assertIn(PUBLIC_READ_ACL_TEXT, self._strip_xml_whitespace(acl)) | 194 self.assertIn(PUBLIC_READ_JSON_ACL_TEXT, self._strip_json_whitespace(acl)) |
| 196 acl = self.RunGsUtil(self._get_acl_prefix + [v1_uri_str], | 195 acl = self.RunGsUtil(self._get_acl_prefix + [v1_uri_str], |
| 197 return_stdout=True) | 196 return_stdout=True) |
| 198 self.assertNotIn(PUBLIC_READ_ACL_TEXT, self._strip_xml_whitespace(acl)) | 197 self.assertNotIn(PUBLIC_READ_JSON_ACL_TEXT, |
| 198 self._strip_json_whitespace(acl)) |
| 199 | 199 |
| 200 # Check that reading the ACL with the version-less URI returns the | 200 # Check that reading the ACL with the version-less URI returns the |
| 201 # original ACL (since the version-less URI means the current version). | 201 # original ACL (since the version-less URI means the current version). |
| 202 acl = self.RunGsUtil(self._get_acl_prefix + [uri.uri], return_stdout=True) | 202 acl = self.RunGsUtil(self._get_acl_prefix + [uri.uri], return_stdout=True) |
| 203 self.assertEqual(acl, orig_acls[0]) | 203 self.assertEqual(acl, orig_acls[0]) |
| 204 | 204 |
| 205 def _strip_xml_whitespace(self, xml): | 205 def _strip_json_whitespace(self, json_text): |
| 206 s = re.sub('>\s*', '>', xml.replace('\n', '')) | 206 return re.sub(r'\s*', '', json_text) |
| 207 return re.sub('\s*<', '<', s) | 207 |
| 208 | |
| 209 def testAclChangeWithUserId(self): | 208 def testAclChangeWithUserId(self): |
| 210 change = aclhelpers.AclChange(self.USER_TEST_ID + ':r', | 209 change = aclhelpers.AclChange(self.USER_TEST_ID + ':r', |
| 211 scope_type=aclhelpers.ChangeType.USER) | 210 scope_type=aclhelpers.ChangeType.USER) |
| 212 acl = self.sample_uri.get_acl() | 211 acl = list(AclTranslation.BotoBucketAclToMessage(self.sample_uri.get_acl())) |
| 213 change.Execute(self.sample_uri, acl, self.logger) | 212 change.Execute(self.sample_url, acl, 'acl', self.logger) |
| 214 self._AssertHas(acl, 'READ', 'UserById', self.USER_TEST_ID) | 213 self._AssertHas(acl, 'READER', 'UserById', self.USER_TEST_ID) |
| 215 | 214 |
| 216 def testAclChangeWithGroupId(self): | 215 def testAclChangeWithGroupId(self): |
| 217 change = aclhelpers.AclChange(self.GROUP_TEST_ID + ':r', | 216 change = aclhelpers.AclChange(self.GROUP_TEST_ID + ':r', |
| 218 scope_type=aclhelpers.ChangeType.GROUP) | 217 scope_type=aclhelpers.ChangeType.GROUP) |
| 219 acl = self.sample_uri.get_acl() | 218 acl = list(AclTranslation.BotoBucketAclToMessage(self.sample_uri.get_acl())) |
| 220 change.Execute(self.sample_uri, acl, self.logger) | 219 change.Execute(self.sample_url, acl, 'acl', self.logger) |
| 221 self._AssertHas(acl, 'READ', 'GroupById', self.GROUP_TEST_ID) | 220 self._AssertHas(acl, 'READER', 'GroupById', self.GROUP_TEST_ID) |
| 222 | 221 |
| 223 def testAclChangeWithUserEmail(self): | 222 def testAclChangeWithUserEmail(self): |
| 224 change = aclhelpers.AclChange(self.USER_TEST_ADDRESS + ':r', | 223 change = aclhelpers.AclChange(self.USER_TEST_ADDRESS + ':r', |
| 225 scope_type=aclhelpers.ChangeType.USER) | 224 scope_type=aclhelpers.ChangeType.USER) |
| 226 acl = self.sample_uri.get_acl() | 225 acl = list(AclTranslation.BotoBucketAclToMessage(self.sample_uri.get_acl())) |
| 227 change.Execute(self.sample_uri, acl, self.logger) | 226 change.Execute(self.sample_url, acl, 'acl', self.logger) |
| 228 self._AssertHas(acl, 'READ', 'UserByEmail', self.USER_TEST_ADDRESS) | 227 self._AssertHas(acl, 'READER', 'UserByEmail', self.USER_TEST_ADDRESS) |
| 229 | 228 |
| 230 def testAclChangeWithGroupEmail(self): | 229 def testAclChangeWithGroupEmail(self): |
| 231 change = aclhelpers.AclChange(self.GROUP_TEST_ADDRESS + ':fc', | 230 change = aclhelpers.AclChange(self.GROUP_TEST_ADDRESS + ':fc', |
| 232 scope_type=aclhelpers.ChangeType.GROUP) | 231 scope_type=aclhelpers.ChangeType.GROUP) |
| 233 acl = self.sample_uri.get_acl() | 232 acl = list(AclTranslation.BotoBucketAclToMessage(self.sample_uri.get_acl())) |
| 234 change.Execute(self.sample_uri, acl, self.logger) | 233 change.Execute(self.sample_url, acl, 'acl', self.logger) |
| 235 self._AssertHas(acl, 'FULL_CONTROL', 'GroupByEmail', | 234 self._AssertHas(acl, 'OWNER', 'GroupByEmail', self.GROUP_TEST_ADDRESS) |
| 236 self.GROUP_TEST_ADDRESS) | |
| 237 | 235 |
| 238 def testAclChangeWithDomain(self): | 236 def testAclChangeWithDomain(self): |
| 239 change = aclhelpers.AclChange(self.DOMAIN_TEST + ':READ', | 237 change = aclhelpers.AclChange(self.DOMAIN_TEST + ':READ', |
| 240 scope_type=aclhelpers.ChangeType.GROUP) | 238 scope_type=aclhelpers.ChangeType.GROUP) |
| 241 acl = self.sample_uri.get_acl() | 239 acl = list(AclTranslation.BotoBucketAclToMessage(self.sample_uri.get_acl())) |
| 242 change.Execute(self.sample_uri, acl, self.logger) | 240 change.Execute(self.sample_url, acl, 'acl', self.logger) |
| 243 self._AssertHas(acl, 'READ', 'GroupByDomain', self.DOMAIN_TEST) | 241 self._AssertHas(acl, 'READER', 'GroupByDomain', self.DOMAIN_TEST) |
| 244 | 242 |
| 245 def testAclChangeWithAllUsers(self): | 243 def testAclChangeWithAllUsers(self): |
| 246 change = aclhelpers.AclChange('AllUsers:WRITE', | 244 change = aclhelpers.AclChange('AllUsers:WRITE', |
| 247 scope_type=aclhelpers.ChangeType.GROUP) | 245 scope_type=aclhelpers.ChangeType.GROUP) |
| 248 acl = self.sample_uri.get_acl() | 246 acl = list(AclTranslation.BotoBucketAclToMessage(self.sample_uri.get_acl())) |
| 249 change.Execute(self.sample_uri, acl, self.logger) | 247 change.Execute(self.sample_url, acl, 'acl', self.logger) |
| 250 self._AssertHas(acl, 'WRITE', 'AllUsers') | 248 self._AssertHas(acl, 'WRITER', 'AllUsers') |
| 251 | 249 |
| 252 def testAclChangeWithAllAuthUsers(self): | 250 def testAclChangeWithAllAuthUsers(self): |
| 253 change = aclhelpers.AclChange('AllAuthenticatedUsers:READ', | 251 change = aclhelpers.AclChange('AllAuthenticatedUsers:READ', |
| 254 scope_type=aclhelpers.ChangeType.GROUP) | 252 scope_type=aclhelpers.ChangeType.GROUP) |
| 255 acl = self.sample_uri.get_acl() | 253 acl = list(AclTranslation.BotoBucketAclToMessage(self.sample_uri.get_acl())) |
| 256 change.Execute(self.sample_uri, acl, self.logger) | 254 change.Execute(self.sample_url, acl, 'acl', self.logger) |
| 257 self._AssertHas(acl, 'READ', 'AllAuthenticatedUsers') | 255 self._AssertHas(acl, 'READER', 'AllAuthenticatedUsers') |
| 258 remove = aclhelpers.AclDel('AllAuthenticatedUsers') | 256 remove = aclhelpers.AclDel('AllAuthenticatedUsers') |
| 259 remove.Execute(self.sample_uri, acl, self.logger) | 257 remove.Execute(self.sample_url, acl, 'acl', self.logger) |
| 260 self._AssertHasNo(acl, 'READ', 'AllAuthenticatedUsers') | 258 self._AssertHasNo(acl, 'READER', 'AllAuthenticatedUsers') |
| 261 | 259 |
| 262 def testAclDelWithUser(self): | 260 def testAclDelWithUser(self): |
| 263 add = aclhelpers.AclChange(self.USER_TEST_ADDRESS + ':READ', | 261 add = aclhelpers.AclChange(self.USER_TEST_ADDRESS + ':READ', |
| 264 scope_type=aclhelpers.ChangeType.USER) | 262 scope_type=aclhelpers.ChangeType.USER) |
| 265 acl = self.sample_uri.get_acl() | 263 acl = list(AclTranslation.BotoBucketAclToMessage(self.sample_uri.get_acl())) |
| 266 add.Execute(self.sample_uri, acl, self.logger) | 264 add.Execute(self.sample_url, acl, 'acl', self.logger) |
| 267 self._AssertHas(acl, 'READ', 'UserByEmail', self.USER_TEST_ADDRESS) | 265 self._AssertHas(acl, 'READER', 'UserByEmail', self.USER_TEST_ADDRESS) |
| 268 | 266 |
| 269 remove = aclhelpers.AclDel(self.USER_TEST_ADDRESS) | 267 remove = aclhelpers.AclDel(self.USER_TEST_ADDRESS) |
| 270 remove.Execute(self.sample_uri, acl, self.logger) | 268 remove.Execute(self.sample_url, acl, 'acl', self.logger) |
| 271 self._AssertHasNo(acl, 'READ', 'UserByEmail', self.USER_TEST_ADDRESS) | 269 self._AssertHasNo(acl, 'READ', 'UserByEmail', self.USER_TEST_ADDRESS) |
| 272 | 270 |
| 273 def testAclDelWithGroup(self): | 271 def testAclDelWithGroup(self): |
| 274 add = aclhelpers.AclChange(self.USER_TEST_ADDRESS + ':READ', | 272 add = aclhelpers.AclChange(self.USER_TEST_ADDRESS + ':READ', |
| 275 scope_type=aclhelpers.ChangeType.GROUP) | 273 scope_type=aclhelpers.ChangeType.GROUP) |
| 276 acl = self.sample_uri.get_acl() | 274 acl = list(AclTranslation.BotoBucketAclToMessage(self.sample_uri.get_acl())) |
| 277 add.Execute(self.sample_uri, acl, self.logger) | 275 add.Execute(self.sample_url, acl, 'acl', self.logger) |
| 278 self._AssertHas(acl, 'READ', 'GroupByEmail', self.USER_TEST_ADDRESS) | 276 self._AssertHas(acl, 'READER', 'GroupByEmail', self.USER_TEST_ADDRESS) |
| 279 | 277 |
| 280 remove = aclhelpers.AclDel(self.USER_TEST_ADDRESS) | 278 remove = aclhelpers.AclDel(self.USER_TEST_ADDRESS) |
| 281 remove.Execute(self.sample_uri, acl, self.logger) | 279 remove.Execute(self.sample_url, acl, 'acl', self.logger) |
| 282 self._AssertHasNo(acl, 'READ', 'GroupByEmail', self.GROUP_TEST_ADDRESS) | 280 self._AssertHasNo(acl, 'READER', 'GroupByEmail', self.GROUP_TEST_ADDRESS) |
| 283 | 281 |
| 284 # | 282 # |
| 285 # Here are a whole lot of verbose asserts | 283 # Here are a whole lot of verbose asserts |
| 286 # | 284 # |
| 287 | 285 |
| 288 def _AssertHas(self, current_acl, perm, scope, value=None): | 286 def _AssertHas(self, current_acl, perm, scope, value=None): |
| 289 matches = list(self._YieldMatchingEntries(current_acl, perm, scope, value)) | 287 matches = list(self._YieldMatchingEntriesJson(current_acl, perm, scope, |
| 288 value)) |
| 290 self.assertEqual(1, len(matches)) | 289 self.assertEqual(1, len(matches)) |
| 291 | 290 |
| 292 def _AssertHasNo(self, current_acl, perm, scope, value=None): | 291 def _AssertHasNo(self, current_acl, perm, scope, value=None): |
| 293 matches = list(self._YieldMatchingEntries(current_acl, perm, scope, value)) | 292 matches = list(self._YieldMatchingEntriesJson(current_acl, perm, scope, |
| 293 value)) |
| 294 self.assertEqual(0, len(matches)) | 294 self.assertEqual(0, len(matches)) |
| 295 | 295 |
| 296 def _YieldMatchingEntries(self, current_acl, perm, scope, value=None): | 296 def _YieldMatchingEntriesJson(self, current_acl, perm, scope, value=None): |
| 297 """Generator that finds entries that match the change descriptor.""" | 297 """Generator that yields entries that match the change descriptor. |
| 298 for entry in current_acl.entries.entry_list: | 298 |
| 299 if entry.scope.type == scope: | 299 Args: |
| 300 if scope in ['UserById', 'GroupById']: | 300 current_acl: A list of apitools_messages.BucketAccessControls or |
| 301 if value == entry.scope.id: | 301 ObjectAccessControls which will be searched for matching |
| 302 yield entry | 302 entries. |
| 303 elif scope in ['UserByEmail', 'GroupByEmail']: | 303 perm: Role (permission) to match. |
| 304 if value == entry.scope.email_address: | 304 scope: Scope type to match. |
| 305 yield entry | 305 value: Value to match (against the scope type). |
| 306 elif scope == 'GroupByDomain': | 306 |
| 307 if value == entry.scope.domain: | 307 Yields: |
| 308 yield entry | 308 An apitools_messages.BucketAccessControl or ObjectAccessControl. |
| 309 elif scope in ['AllUsers', 'AllAuthenticatedUsers']: | 309 """ |
| 310 yield entry | 310 for entry in current_acl: |
| 311 else: | 311 if (scope in ['UserById', 'GroupById'] and |
| 312 raise Exception('Found an unrecognized ACL entry type, aborting.') | 312 entry.entityId and value == entry.entityId and |
| 313 | 313 entry.role == perm): |
| 314 def _MakeScopeRegex(self, scope_type, email_address, perm): | 314 yield entry |
| 315 template_regex = ( | 315 elif (scope in ['UserByEmail', 'GroupByEmail'] and |
| 316 r'<Scope type="{0}">\s*<EmailAddress>\s*{1}\s*</EmailAddress>\s*' | 316 entry.email and value == entry.email and |
| 317 r'</Scope>\s*<Permission>\s*{2}\s*</Permission>') | 317 entry.role == perm): |
| 318 return template_regex.format(scope_type, email_address, perm) | 318 yield entry |
| 319 elif (scope == 'GroupByDomain' and |
| 320 entry.domain and value == entry.domain and |
| 321 entry.role == perm): |
| 322 yield entry |
| 323 elif (scope in ['AllUsers', 'AllAuthenticatedUsers'] and |
| 324 entry.entity.lower() == scope.lower() and |
| 325 entry.role == perm): |
| 326 yield entry |
| 327 |
| 328 def _MakeScopeRegex(self, role, entity_type, email_address): |
| 329 template_regex = (r'\{.*"entity":\s*"%s-%s".*"role":\s*"%s".*\}' % |
| 330 (entity_type, email_address, role)) |
| 331 return re.compile(template_regex, flags=re.DOTALL) |
| 319 | 332 |
| 320 def testBucketAclChange(self): | 333 def testBucketAclChange(self): |
| 321 test_regex = self._MakeScopeRegex( | 334 """Tests acl change on a bucket.""" |
| 322 'UserByEmail', self.USER_TEST_ADDRESS, 'FULL_CONTROL') | 335 test_regex = self._MakeScopeRegex( |
| 323 xml = self.RunGsUtil( | 336 'OWNER', 'user', self.USER_TEST_ADDRESS) |
| 337 json_text = self.RunGsUtil( |
| 324 self._get_acl_prefix + [suri(self.sample_uri)], return_stdout=True) | 338 self._get_acl_prefix + [suri(self.sample_uri)], return_stdout=True) |
| 325 self.assertNotRegexpMatches(xml, test_regex) | 339 self.assertNotRegexpMatches(json_text, test_regex) |
| 326 | 340 |
| 327 self.RunGsUtil(self._ch_acl_prefix + | 341 self.RunGsUtil(self._ch_acl_prefix + |
| 328 ['-u', self.USER_TEST_ADDRESS+':fc', suri(self.sample_uri)]) | 342 ['-u', self.USER_TEST_ADDRESS+':fc', suri(self.sample_uri)]) |
| 329 xml = self.RunGsUtil( | 343 json_text = self.RunGsUtil( |
| 330 self._get_acl_prefix + [suri(self.sample_uri)], return_stdout=True) | 344 self._get_acl_prefix + [suri(self.sample_uri)], return_stdout=True) |
| 331 self.assertRegexpMatches(xml, test_regex) | 345 self.assertRegexpMatches(json_text, test_regex) |
| 346 |
| 347 test_regex2 = self._MakeScopeRegex( |
| 348 'WRITER', 'user', self.USER_TEST_ADDRESS) |
| 349 self.RunGsUtil(self._ch_acl_prefix + |
| 350 ['-u', self.USER_TEST_ADDRESS+':w', suri(self.sample_uri)]) |
| 351 json_text2 = self.RunGsUtil( |
| 352 self._get_acl_prefix + [suri(self.sample_uri)], return_stdout=True) |
| 353 self.assertRegexpMatches(json_text2, test_regex2) |
| 332 | 354 |
| 333 self.RunGsUtil(self._ch_acl_prefix + | 355 self.RunGsUtil(self._ch_acl_prefix + |
| 334 ['-d', self.USER_TEST_ADDRESS, suri(self.sample_uri)]) | 356 ['-d', self.USER_TEST_ADDRESS, suri(self.sample_uri)]) |
| 335 xml = self.RunGsUtil( | 357 json_text3 = self.RunGsUtil( |
| 336 self._get_acl_prefix + [suri(self.sample_uri)], return_stdout=True) | 358 self._get_acl_prefix + [suri(self.sample_uri)], return_stdout=True) |
| 337 self.assertNotRegexpMatches(xml, test_regex) | 359 self.assertNotRegexpMatches(json_text3, test_regex) |
| 338 | 360 |
| 339 def testObjectAclChange(self): | 361 def testObjectAclChange(self): |
| 362 """Tests acl change on an object.""" |
| 340 obj = self.CreateObject(bucket_uri=self.sample_uri, contents='something') | 363 obj = self.CreateObject(bucket_uri=self.sample_uri, contents='something') |
| 341 test_regex = self._MakeScopeRegex( | 364 self.AssertNObjectsInBucket(self.sample_uri, 1) |
| 342 'GroupByEmail', self.GROUP_TEST_ADDRESS, 'READ') | 365 |
| 343 xml = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], return_stdout=True) | 366 test_regex = self._MakeScopeRegex( |
| 344 self.assertNotRegexpMatches(xml, test_regex) | 367 'READER', 'group', self.GROUP_TEST_ADDRESS) |
| 368 json_text = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], |
| 369 return_stdout=True) |
| 370 self.assertNotRegexpMatches(json_text, test_regex) |
| 345 | 371 |
| 346 self.RunGsUtil(self._ch_acl_prefix + | 372 self.RunGsUtil(self._ch_acl_prefix + |
| 347 ['-g', self.GROUP_TEST_ADDRESS+':READ', suri(obj)]) | 373 ['-g', self.GROUP_TEST_ADDRESS+':READ', suri(obj)]) |
| 348 xml = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], return_stdout=True) | 374 json_text = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], |
| 349 self.assertRegexpMatches(xml, test_regex) | 375 return_stdout=True) |
| 376 self.assertRegexpMatches(json_text, test_regex) |
| 377 |
| 378 test_regex2 = self._MakeScopeRegex( |
| 379 'OWNER', 'group', self.GROUP_TEST_ADDRESS) |
| 380 self.RunGsUtil(self._ch_acl_prefix + |
| 381 ['-g', self.GROUP_TEST_ADDRESS+':OWNER', suri(obj)]) |
| 382 json_text2 = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], |
| 383 return_stdout=True) |
| 384 self.assertRegexpMatches(json_text2, test_regex2) |
| 350 | 385 |
| 351 self.RunGsUtil(self._ch_acl_prefix + | 386 self.RunGsUtil(self._ch_acl_prefix + |
| 352 ['-d', self.GROUP_TEST_ADDRESS, suri(obj)]) | 387 ['-d', self.GROUP_TEST_ADDRESS, suri(obj)]) |
| 353 xml = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], return_stdout=True) | 388 json_text3 = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], |
| 354 self.assertNotRegexpMatches(xml, test_regex) | 389 return_stdout=True) |
| 390 self.assertNotRegexpMatches(json_text3, test_regex2) |
| 391 |
| 392 all_auth_regex = re.compile( |
| 393 r'\{.*"entity":\s*"allAuthenticatedUsers".*"role":\s*"OWNER".*\}', |
| 394 flags=re.DOTALL) |
| 395 |
| 396 self.RunGsUtil(self._ch_acl_prefix + ['-g', 'AllAuth:O', suri(obj)]) |
| 397 json_text4 = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], |
| 398 return_stdout=True) |
| 399 self.assertRegexpMatches(json_text4, all_auth_regex) |
| 400 |
| 401 def testObjectAclChangeAllUsers(self): |
| 402 """Tests acl ch AllUsers:R on an object.""" |
| 403 obj = self.CreateObject(bucket_uri=self.sample_uri, contents='something') |
| 404 self.AssertNObjectsInBucket(self.sample_uri, 1) |
| 405 |
| 406 all_users_regex = re.compile( |
| 407 r'\{.*"entity":\s*"allUsers".*"role":\s*"READER".*\}', flags=re.DOTALL) |
| 408 json_text = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], |
| 409 return_stdout=True) |
| 410 self.assertNotRegexpMatches(json_text, all_users_regex) |
| 411 |
| 412 self.RunGsUtil(self._ch_acl_prefix + |
| 413 ['-g', 'AllUsers:R', suri(obj)]) |
| 414 json_text = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], |
| 415 return_stdout=True) |
| 416 self.assertRegexpMatches(json_text, all_users_regex) |
| 355 | 417 |
| 356 def testMultithreadedAclChange(self, count=10): | 418 def testMultithreadedAclChange(self, count=10): |
| 419 """Tests multi-threaded acl changing on several objects.""" |
| 357 objects = [] | 420 objects = [] |
| 358 for i in range(count): | 421 for i in range(count): |
| 359 objects.append(self.CreateObject( | 422 objects.append(self.CreateObject( |
| 360 bucket_uri=self.sample_uri, | 423 bucket_uri=self.sample_uri, |
| 361 contents='something {0}'.format(i))) | 424 contents='something {0}'.format(i))) |
| 362 | 425 |
| 363 test_regex = self._MakeScopeRegex( | 426 self.AssertNObjectsInBucket(self.sample_uri, count) |
| 364 'GroupByEmail', self.GROUP_TEST_ADDRESS, 'READ') | 427 |
| 365 xmls = [] | 428 test_regex = self._MakeScopeRegex( |
| 429 'READER', 'group', self.GROUP_TEST_ADDRESS) |
| 430 json_texts = [] |
| 366 for obj in objects: | 431 for obj in objects: |
| 367 xmls.append(self.RunGsUtil(self._get_acl_prefix + [suri(obj)], | 432 json_texts.append(self.RunGsUtil( |
| 368 return_stdout=True)) | 433 self._get_acl_prefix + [suri(obj)], return_stdout=True)) |
| 369 for xml in xmls: | 434 for json_text in json_texts: |
| 370 self.assertNotRegexpMatches(xml, test_regex) | 435 self.assertNotRegexpMatches(json_text, test_regex) |
| 371 | 436 |
| 372 uris = [suri(obj) for obj in objects] | 437 uris = [suri(obj) for obj in objects] |
| 373 self.RunGsUtil(['-m', '-DD'] + self._ch_acl_prefix + ['-g', | 438 self.RunGsUtil(['-m', '-DD'] + self._ch_acl_prefix + |
| 374 self.GROUP_TEST_ADDRESS+':READ'] + uris) | 439 ['-g', self.GROUP_TEST_ADDRESS+':READ'] + uris) |
| 375 | 440 |
| 376 xmls = [] | 441 json_texts = [] |
| 377 for obj in objects: | 442 for obj in objects: |
| 378 xmls.append(self.RunGsUtil(self._get_acl_prefix + [suri(obj)], | 443 json_texts.append(self.RunGsUtil( |
| 379 return_stdout=True)) | 444 self._get_acl_prefix + [suri(obj)], return_stdout=True)) |
| 380 for xml in xmls: | 445 for json_text in json_texts: |
| 381 self.assertRegexpMatches(xml, test_regex) | 446 self.assertRegexpMatches(json_text, test_regex) |
| 382 | 447 |
| 383 def testRecursiveChangeAcl(self): | 448 def testRecursiveChangeAcl(self): |
| 449 """Tests recursively changing ACLs on nested objects.""" |
| 384 obj = self.CreateObject(bucket_uri=self.sample_uri, object_name='foo/bar', | 450 obj = self.CreateObject(bucket_uri=self.sample_uri, object_name='foo/bar', |
| 385 contents='something') | 451 contents='something') |
| 386 test_regex = self._MakeScopeRegex( | 452 self.AssertNObjectsInBucket(self.sample_uri, 1) |
| 387 'GroupByEmail', self.GROUP_TEST_ADDRESS, 'READ') | 453 |
| 388 xml = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], return_stdout=True) | 454 test_regex = self._MakeScopeRegex( |
| 389 self.assertNotRegexpMatches(xml, test_regex) | 455 'READER', 'group', self.GROUP_TEST_ADDRESS) |
| 390 | 456 json_text = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], |
| 391 self.RunGsUtil(self._ch_acl_prefix + | 457 return_stdout=True) |
| 458 self.assertNotRegexpMatches(json_text, test_regex) |
| 459 |
| 460 self.RunGsUtil( |
| 461 self._ch_acl_prefix + |
| 392 ['-R', '-g', self.GROUP_TEST_ADDRESS+':READ', suri(obj)[:-3]]) | 462 ['-R', '-g', self.GROUP_TEST_ADDRESS+':READ', suri(obj)[:-3]]) |
| 393 xml = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], return_stdout=True) | 463 json_text = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], |
| 394 self.assertRegexpMatches(xml, test_regex) | 464 return_stdout=True) |
| 465 self.assertRegexpMatches(json_text, test_regex) |
| 395 | 466 |
| 396 self.RunGsUtil(self._ch_acl_prefix + | 467 self.RunGsUtil(self._ch_acl_prefix + |
| 397 ['-d', self.GROUP_TEST_ADDRESS, suri(obj)]) | 468 ['-d', self.GROUP_TEST_ADDRESS, suri(obj)]) |
| 398 xml = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], return_stdout=True) | 469 json_text = self.RunGsUtil(self._get_acl_prefix + [suri(obj)], |
| 399 self.assertNotRegexpMatches(xml, test_regex) | 470 return_stdout=True) |
| 471 self.assertNotRegexpMatches(json_text, test_regex) |
| 400 | 472 |
| 401 def testMultiVersionSupport(self): | 473 def testMultiVersionSupport(self): |
| 474 """Tests changing ACLs on multiple object versions.""" |
| 402 bucket = self.CreateVersionedBucket() | 475 bucket = self.CreateVersionedBucket() |
| 403 object_name = self.MakeTempName('obj') | 476 object_name = self.MakeTempName('obj') |
| 404 obj = self.CreateObject( | 477 self.CreateObject( |
| 405 bucket_uri=bucket, object_name=object_name, contents='One thing') | 478 bucket_uri=bucket, object_name=object_name, contents='One thing') |
| 406 # Create another on the same URI, giving us a second version. | 479 # Create another on the same URI, giving us a second version. |
| 407 self.CreateObject( | 480 self.CreateObject( |
| 408 bucket_uri=bucket, object_name=object_name, contents='Another thing') | 481 bucket_uri=bucket, object_name=object_name, contents='Another thing') |
| 409 | 482 |
| 410 # Use @Retry as hedge against bucket listing eventual consistency. | 483 lines = self.AssertNObjectsInBucket(bucket, 2, versioned=True) |
| 411 @Retry(AssertionError, tries=3, timeout_secs=1, logger=self.logger) | 484 |
| 412 def _getObjects(): | 485 obj_v1, obj_v2 = lines[0], lines[1] |
| 413 stdout = self.RunGsUtil(['ls', '-a', suri(obj)], return_stdout=True) | 486 |
| 414 lines = stdout.strip().split('\n') | 487 test_regex = self._MakeScopeRegex( |
| 415 self.assertEqual(len(lines), 2) | 488 'READER', 'group', self.GROUP_TEST_ADDRESS) |
| 416 return lines | 489 json_text = self.RunGsUtil(self._get_acl_prefix + [obj_v1], |
| 417 | 490 return_stdout=True) |
| 418 obj_v1, obj_v2 = _getObjects() | 491 self.assertNotRegexpMatches(json_text, test_regex) |
| 419 | |
| 420 test_regex = self._MakeScopeRegex( | |
| 421 'GroupByEmail', self.GROUP_TEST_ADDRESS, 'READ') | |
| 422 xml = self.RunGsUtil(self._get_acl_prefix + [obj_v1], return_stdout=True) | |
| 423 self.assertNotRegexpMatches(xml, test_regex) | |
| 424 | 492 |
| 425 self.RunGsUtil(self._ch_acl_prefix + | 493 self.RunGsUtil(self._ch_acl_prefix + |
| 426 ['-g', self.GROUP_TEST_ADDRESS+':READ', obj_v1]) | 494 ['-g', self.GROUP_TEST_ADDRESS+':READ', obj_v1]) |
| 427 xml = self.RunGsUtil(self._get_acl_prefix + [obj_v1], return_stdout=True) | 495 json_text = self.RunGsUtil(self._get_acl_prefix + [obj_v1], |
| 428 self.assertRegexpMatches(xml, test_regex) | 496 return_stdout=True) |
| 429 | 497 self.assertRegexpMatches(json_text, test_regex) |
| 430 xml = self.RunGsUtil(self._get_acl_prefix + [obj_v2], return_stdout=True) | 498 |
| 431 self.assertNotRegexpMatches(xml, test_regex) | 499 json_text = self.RunGsUtil(self._get_acl_prefix + [obj_v2], |
| 500 return_stdout=True) |
| 501 self.assertNotRegexpMatches(json_text, test_regex) |
| 432 | 502 |
| 433 def testBadRequestAclChange(self): | 503 def testBadRequestAclChange(self): |
| 434 stdout, stderr = self.RunGsUtil(self._ch_acl_prefix + | 504 stdout, stderr = self.RunGsUtil( |
| 505 self._ch_acl_prefix + |
| 435 ['-u', 'invalid_$$@hello.com:R', suri(self.sample_uri)], | 506 ['-u', 'invalid_$$@hello.com:R', suri(self.sample_uri)], |
| 436 return_stdout=True, return_stderr=True, expected_status=1) | 507 return_stdout=True, return_stderr=True, expected_status=1) |
| 437 self.assertIn('Bad Request', stderr) | 508 self.assertIn('BadRequestException', stderr) |
| 438 self.assertNotIn('Retrying', stdout) | 509 self.assertNotIn('Retrying', stdout) |
| 439 self.assertNotIn('Retrying', stderr) | 510 self.assertNotIn('Retrying', stderr) |
| 440 | 511 |
| 441 def testAclGetWithoutFullControl(self): | 512 def testAclGetWithoutFullControl(self): |
| 442 object_uri = self.CreateObject(contents='foo') | 513 object_uri = self.CreateObject(contents='foo') |
| 443 with self.SetAnonymousBotoCreds(): | 514 with self.SetAnonymousBotoCreds(): |
| 444 stderr = self.RunGsUtil(['acl', 'get', suri(object_uri)], | 515 stderr = self.RunGsUtil(self._get_acl_prefix + [suri(object_uri)], |
| 445 return_stderr = True, expected_status=1) | 516 return_stderr=True, expected_status=1) |
| 446 self.assertIn('Note that Full Control access is required to access ACLs.', | 517 self.assertIn('AccessDeniedException', stderr) |
| 447 stderr) | 518 |
| 448 | |
| 449 def testTooFewArgumentsFails(self): | 519 def testTooFewArgumentsFails(self): |
| 520 """Tests calling ACL commands with insufficient number of arguments.""" |
| 450 # No arguments for get, but valid subcommand. | 521 # No arguments for get, but valid subcommand. |
| 451 stderr = self.RunGsUtil(self._get_acl_prefix, return_stderr=True, | 522 stderr = self.RunGsUtil(self._get_acl_prefix, return_stderr=True, |
| 452 expected_status=1) | 523 expected_status=1) |
| 453 self.assertIn('command requires at least', stderr) | 524 self.assertIn('command requires at least', stderr) |
| 454 | 525 |
| 455 # No arguments for set, but valid subcommand. | 526 # No arguments for set, but valid subcommand. |
| 456 stderr = self.RunGsUtil(self._set_acl_prefix, return_stderr=True, | 527 stderr = self.RunGsUtil(self._set_acl_prefix, return_stderr=True, |
| 457 expected_status=1) | 528 expected_status=1) |
| 458 self.assertIn('command requires at least', stderr) | 529 self.assertIn('command requires at least', stderr) |
| 459 | 530 |
| 460 # No arguments for ch, but valid subcommand. | 531 # No arguments for ch, but valid subcommand. |
| 461 stderr = self.RunGsUtil(self._ch_acl_prefix, return_stderr=True, | 532 stderr = self.RunGsUtil(self._ch_acl_prefix, return_stderr=True, |
| 462 expected_status=1) | 533 expected_status=1) |
| 463 self.assertIn('command requires at least', stderr) | 534 self.assertIn('command requires at least', stderr) |
| 464 | 535 |
| 465 # Neither arguments nor subcommand. | 536 # Neither arguments nor subcommand. |
| 466 stderr = self.RunGsUtil(['acl'], return_stderr=True, expected_status=1) | 537 stderr = self.RunGsUtil(['acl'], return_stderr=True, expected_status=1) |
| 467 self.assertIn('command requires at least', stderr) | 538 self.assertIn('command requires at least', stderr) |
| 468 | 539 |
| 540 def testMinusF(self): |
| 541 """Tests -f option to continue after failure.""" |
| 542 bucket_uri = self.CreateBucket() |
| 543 obj_uri = suri(self.CreateObject(bucket_uri=bucket_uri, object_name='foo', |
| 544 contents='foo')) |
| 545 acl_string = self.RunGsUtil(self._get_acl_prefix + [obj_uri], |
| 546 return_stdout=True) |
| 547 self.RunGsUtil(self._set_acl_prefix + |
| 548 ['-f', 'public-read', suri(bucket_uri) + 'foo2', obj_uri], |
| 549 expected_status=1) |
| 550 acl_string2 = self.RunGsUtil(self._get_acl_prefix + [obj_uri], |
| 551 return_stdout=True) |
| 552 |
| 553 self.assertNotEqual(acl_string, acl_string2) |
| 554 |
| 555 |
| 556 class TestS3CompatibleAcl(TestAclBase): |
| 557 """ACL integration tests that work for s3 and gs URLs.""" |
| 558 |
| 559 def testAclObjectGetSet(self): |
| 560 bucket_uri = self.CreateBucket() |
| 561 obj_uri = self.CreateObject(bucket_uri=bucket_uri, contents='foo') |
| 562 self.AssertNObjectsInBucket(bucket_uri, 1) |
| 563 |
| 564 stdout = self.RunGsUtil(self._get_acl_prefix + [suri(obj_uri)], |
| 565 return_stdout=True) |
| 566 set_contents = self.CreateTempFile(contents=stdout) |
| 567 self.RunGsUtil(self._set_acl_prefix + [set_contents, suri(obj_uri)]) |
| 568 |
| 569 def testAclBucketGetSet(self): |
| 570 bucket_uri = self.CreateBucket() |
| 571 stdout = self.RunGsUtil(self._get_acl_prefix + [suri(bucket_uri)], |
| 572 return_stdout=True) |
| 573 set_contents = self.CreateTempFile(contents=stdout) |
| 574 self.RunGsUtil(self._set_acl_prefix + [set_contents, suri(bucket_uri)]) |
| 575 |
| 576 |
| 577 @SkipForGS('S3 ACLs accept XML and should not cause an XML warning.') |
| 578 class TestS3OnlyAcl(TestAclBase): |
| 579 """ACL integration tests that work only for s3 URLs.""" |
| 580 |
| 581 # TODO: Format all test case names consistently. |
| 582 def test_set_xml_acl(self): |
| 583 """Ensures XML content does not return an XML warning for S3.""" |
| 584 obj_uri = suri(self.CreateObject(contents='foo')) |
| 585 inpath = self.CreateTempFile(contents='<ValidXml></ValidXml>') |
| 586 stderr = self.RunGsUtil(self._set_acl_prefix + [inpath, obj_uri], |
| 587 return_stderr=True, expected_status=1) |
| 588 self.assertIn('BadRequestException', stderr) |
| 589 self.assertNotIn('XML ACL data provided', stderr) |
| 590 |
| 591 def test_set_xml_acl_bucket(self): |
| 592 """Ensures XML content does not return an XML warning for S3.""" |
| 593 bucket_uri = suri(self.CreateBucket()) |
| 594 inpath = self.CreateTempFile(contents='<ValidXml></ValidXml>') |
| 595 stderr = self.RunGsUtil(self._set_acl_prefix + [inpath, bucket_uri], |
| 596 return_stderr=True, expected_status=1) |
| 597 self.assertIn('BadRequestException', stderr) |
| 598 self.assertNotIn('XML ACL data provided', stderr) |
| 599 |
| 600 |
| 469 class TestAclOldAlias(TestAcl): | 601 class TestAclOldAlias(TestAcl): |
| 470 _set_acl_prefix = ['setacl'] | 602 _set_acl_prefix = ['setacl'] |
| 471 _get_acl_prefix = ['getacl'] | 603 _get_acl_prefix = ['getacl'] |
| 472 _set_defacl_prefix = ['setdefacl'] | 604 _set_defacl_prefix = ['setdefacl'] |
| 473 _ch_acl_prefix = ['chacl'] | 605 _ch_acl_prefix = ['chacl'] |
| OLD | NEW |