def test_has_service_access(self): self.assertFalse(acl.can_read_config_set("services/swarming")) service_cfg = service_config_pb2.Service(id="swarming", access=["group:swarming-app"]) services.get_service_async.side_effect = lambda sid: future(service_cfg) auth.is_group_member.side_effect = lambda g: g == "swarming-app" self.assertTrue(acl.can_read_config_set("services/swarming"))
def test_has_project_access_identity(self): self.mock(projects, "get_metadata", mock.Mock()) projects.get_metadata.return_value = project_config_pb2.ProjectCfg(access=["group:googlers", "*****@*****.**"]) self.assertFalse(acl.can_read_config_set("projects/secret")) auth.get_current_identity.return_value = auth.Identity("user", "*****@*****.**") self.assertTrue(acl.can_read_config_set("projects/secret"))
def test_has_service_access(self): self.assertFalse(acl.can_read_config_set('services/swarming')) service_cfg = service_config_pb2.Service( id='swarming', access=['group:swarming-app']) services.get_service_async.side_effect = lambda sid: future(service_cfg) auth.is_group_member.side_effect = lambda g, *_: g == 'swarming-app' self.assertTrue(acl.can_read_config_set('services/swarming'))
def test_has_service_access(self): self.assertFalse(acl.can_read_config_set('services/swarming')) service_cfg = service_config_pb2.Service( id='swarming', access=['group:swarming-app']) services.get_service_async.side_effect = lambda sid: future(service_cfg) auth.is_group_member.side_effect = lambda g, *_: g == 'swarming-app' self.assertTrue(acl.can_read_config_set('services/swarming'))
def test_has_project_access_identity(self): self.mock(projects, 'get_metadata', mock.Mock()) projects.get_metadata.return_value = project_config_pb2.ProjectCfg( access=['group:googlers', '*****@*****.**']) self.assertFalse(acl.can_read_config_set('projects/secret')) auth.get_current_identity.return_value = auth.Identity( 'user', '*****@*****.**') self.assertTrue(acl.can_read_config_set('projects/secret'))
def test_has_project_access_identity(self): self.mock(projects, 'get_metadata', mock.Mock()) projects.get_metadata.return_value = project_config_pb2.ProjectCfg( access=['group:googlers', '*****@*****.**'] ) self.assertFalse(acl.can_read_config_set('projects/secret')) auth.get_current_identity.return_value = auth.Identity('user', '*****@*****.**') self.assertTrue(acl.can_read_config_set('projects/secret'))
def test_has_project_access_group(self): self.mock(projects, "get_metadata", mock.Mock()) projects.get_metadata.return_value = project_config_pb2.ProjectCfg(access=["group:googlers", "*****@*****.**"]) self.assertFalse(acl.can_read_config_set("projects/secret")) auth.is_group_member.side_effect = lambda name: name == "googlers" self.assertTrue(acl.can_read_config_set("projects/secret")) auth.is_group_member.side_effect = lambda name: name == "project-admins" self.assertTrue(acl.can_read_config_set("projects/secret"))
def test_has_project_access_group(self): self.mock(projects, 'get_metadata', mock.Mock()) projects.get_metadata.return_value = project_config_pb2.ProjectCfg( access=['group:googlers', '*****@*****.**']) self.assertFalse(acl.can_read_config_set('projects/secret')) auth.is_group_member.side_effect = lambda name: name == 'googlers' self.assertTrue(acl.can_read_config_set('projects/secret')) auth.is_group_member.side_effect = lambda name: name == 'project-admins' self.assertTrue(acl.can_read_config_set('projects/secret'))
def test_has_project_access_group(self): self.mock(projects, 'get_metadata', mock.Mock()) projects.get_metadata.return_value = project_config_pb2.ProjectCfg( access=['group:googlers', '*****@*****.**'] ) self.assertFalse(acl.can_read_config_set('projects/secret')) auth.is_group_member.side_effect = lambda name, *_: name == 'googlers' self.assertTrue(acl.can_read_config_set('projects/secret')) auth.is_group_member.side_effect = lambda name, *_: name == 'project-admins' self.assertTrue(acl.can_read_config_set('projects/secret'))
def get_config(self, request): """Gets a config file.""" res = self.GetConfigResponseMessage() try: has_access = acl.can_read_config_set( request.config_set, headers=self.request_state.headers) except ValueError: raise endpoints.BadRequestException('Invalid config set: %s' % request.config_set) if not has_access: logging.warning('%s does not have access to %s', auth.get_current_identity().to_bytes(), request.config_set) raise_config_not_found() res.revision, res.content_hash = storage.get_config_hash( request.config_set, request.path, revision=request.revision) if not res.content_hash: raise_config_not_found() if not request.hash_only: res.content = storage.get_config_by_hash(res.content_hash) if not res.content: logging.warning( 'Config hash is found, but the blob is not.\n' 'File: "%s:%s:%s". Hash: %s', request.config_set, request.revision, request.path, res.content_hash) raise_config_not_found() return res
def get_config(self, request): """Gets a config file.""" res = self.GetConfigResponseMessage() try: has_access = acl.can_read_config_set( request.config_set, headers=self.request_state.headers) except ValueError: raise endpoints.BadRequestException( 'Invalid config set: %s' % request.config_set) if not has_access: logging.warning( '%s does not have access to %s', auth.get_current_identity().to_bytes(), request.config_set) raise_config_not_found() res.revision, res.content_hash = storage.get_config_hash( request.config_set, request.path, revision=request.revision) if not res.content_hash: raise_config_not_found() if not request.hash_only: res.content = storage.get_config_by_hash(res.content_hash) if not res.content: logging.warning( 'Config hash is found, but the blob is not.\n' 'File: "%s:%s:%s". Hash: %s', request.config_set, request.revision, request.path, res.content_hash) raise_config_not_found() return res
def get_config_multi(scope, path, hashes_only): """Returns configs at |path| in all config sets. scope can be 'projects' or 'refs'. Returns empty config list if requester does not have project access. """ assert scope in ('projects', 'refs'), scope cache_key = ('v2/%s%s:%s' % (scope, ',hashes_only' if hashes_only else '', path)) configs = memcache.get(cache_key) if configs is None: configs = storage.get_latest_multi_async( get_config_sets_from_scope(scope), path, hashes_only).get_result() for config in configs: if not hashes_only and config.get('content') is None: logging.error('Blob %s referenced from %s:%s:%s was not found', config['content_hash'], config['config_set'], config['revision'], path) try: memcache.add(cache_key, configs, time=60) except ValueError: logging.exception('%s:%s configs are too big for memcache', scope, path) res = GetConfigMultiResponseMessage() for config in configs: if not acl.can_read_config_set(config['config_set']): continue if not hashes_only and config.get('content') is None: continue res.configs.append( res.ConfigEntry( config_set=config['config_set'], revision=config['revision'], content_hash=config['content_hash'], content=config.get('content'), url=config.get('url'), )) return res
def get_config_multi(scope, path, hashes_only): """Returns configs at |path| in all config sets. scope can be 'projects' or 'refs'. Returns empty config list if requester does not have project access. """ assert scope in ('projects', 'refs'), scope cache_key = ( '%s%s:%s' % (scope, ',hashes_only' if hashes_only else '', path)) configs = memcache.get(cache_key) if configs is None: configs = storage.get_latest_multi_async( get_config_sets_from_scope(scope), path, hashes_only).get_result() for config in configs: if not hashes_only and config.get('content') is None: logging.error( 'Blob %s referenced from %s:%s:%s was not found', config['content_hash'], config['config_set'], config['revision'], path) try: memcache.add(cache_key, configs, time=10*60) except ValueError: logging.exception('%s:%s configs are too big for memcache', scope, path) res = GetConfigMultiResponseMessage() for config in configs: if not acl.can_read_config_set(config['config_set']): continue if not hashes_only and config.get('content') is None: continue res.configs.append(res.ConfigEntry( config_set=config['config_set'], revision=config['revision'], content_hash=config['content_hash'], content=config.get('content'), )) return res
def test_admin_can_read_all(self): self.mock(auth, 'is_admin', mock.Mock(return_value=True)) self.assertTrue(acl.can_read_config_set('services/swarming')) self.assertTrue(acl.can_read_config_set('projects/chromium')) self.assertTrue(acl.has_project_access('chromium'))
def test_can_read_service_config_header(self): headers = wsgiref.headers.Headers([ ('X-Appengine-Inbound-Appid', 'swarming'), ]) self.assertTrue( acl.can_read_config_set('services/swarming', headers=headers))
def test_has_service_access_no_access(self): self.assertFalse(acl.can_read_config_set('services/swarming'))
def test_can_read_project_config(self): auth.is_group_member.return_value = True self.assertTrue(acl.can_read_config_set('projects/swarming')) auth.is_group_member.access_called_once_with('project-admins')
def test_admin_can_read_all(self): self.mock(auth, 'is_admin', mock.Mock(return_value=True)) self.assertTrue(acl.can_read_config_set('services/swarming')) self.assertTrue(acl.can_read_config_set('projects/chromium')) self.assertTrue(acl.has_project_access('chromium'))
def test_can_read_project_config_no_access(self): self.assertFalse(acl.can_read_config_set('projects/swarming')) self.assertFalse( acl.can_read_config_set('projects/swarming/branches/x'))
def test_can_read_service_config_header(self): headers = wsgiref.headers.Headers([ ('X-Appengine-Inbound-Appid', 'swarming'), ]) self.assertTrue( acl.can_read_config_set('services/swarming', headers=headers))
def can_read_config_set(self, config_set): try: return acl.can_read_config_set(config_set) except ValueError: raise endpoints.BadRequestException('Invalid config set: %s' % config_set)
def test_malformed_config_set(self): with self.assertRaises(ValueError): acl.can_read_config_set('invalid config set')
def test_can_read_project_config_no_access(self): self.assertFalse(acl.has_project_access('projects/swarming')) self.assertFalse( acl.can_read_config_set('projects/swarming/refs/heads/x'))
def test_can_read_project_config(self): auth.is_group_member.return_value = True self.assertTrue(acl.can_read_config_set('projects/swarming')) auth.is_group_member.access_called_once_with('project-admins')
def test_can_read_project_config_no_access(self): self.assertFalse(acl.can_read_config_set('projects/swarming')) self.assertFalse(acl.can_read_config_set('projects/swarming/branches/x'))
def test_admin_can_read_all(self): self.mock(auth, "is_admin", mock.Mock(return_value=True)) self.assertTrue(acl.can_read_config_set("services/swarming")) self.assertTrue(acl.can_read_config_set("projects/chromium")) self.assertTrue(acl.has_project_access("chromium"))
def test_can_read_project_config_no_access(self): self.assertFalse(acl.has_project_access('projects/swarming')) self.assertFalse(acl.can_read_config_set('projects/swarming/refs/heads/x'))
def can_read_config_set(self, config_set): try: return acl.can_read_config_set(config_set) except ValueError: raise endpoints.BadRequestException('Invalid config set: %s' % config_set)
def test_malformed_config_set(self): with self.assertRaises(ValueError): acl.can_read_config_set('invalid config set')
def test_has_service_access_no_access(self): self.assertFalse(acl.can_read_config_set('services/swarming'))