| Index: appengine/config_service/acl.py
 | 
| diff --git a/appengine/config_service/acl.py b/appengine/config_service/acl.py
 | 
| index a63292385e53861670019db65bbd3f25c9991e8b..2eae49cfc38ba7eea1c7e9fa415ebb4cb6f7a82f 100644
 | 
| --- a/appengine/config_service/acl.py
 | 
| +++ b/appengine/config_service/acl.py
 | 
| @@ -10,6 +10,8 @@ from components import utils
 | 
|  
 | 
|  from proto import service_config_pb2
 | 
|  import common
 | 
| +import projects
 | 
| +import services
 | 
|  import storage
 | 
|  
 | 
|  
 | 
| @@ -18,8 +20,22 @@ def read_acl_cfg():
 | 
|    return storage.get_self_config_async(
 | 
|        common.ACL_FILENAME, service_config_pb2.AclCfg).get_result()
 | 
|  
 | 
| -
 | 
| -def can_read_config_set(config_set, headers=None):
 | 
| +def _has_access(access_list):
 | 
| +  cur_ident = auth.get_current_identity().to_bytes()
 | 
| +  for ac in access_list:
 | 
| +    if ac.startswith('group:'):
 | 
| +      if auth.is_group_member(ac.split(':', 2)[1]):
 | 
| +        return True
 | 
| +    else:
 | 
| +      identity_str = ac
 | 
| +      if ':' not in identity_str:
 | 
| +        identity_str = 'user:%s' % identity_str
 | 
| +      if cur_ident == identity_str:
 | 
| +        return True
 | 
| +  return False
 | 
| +
 | 
| +
 | 
| +def can_read_config_set(config_set):
 | 
|    """Returns True if current requester has access to the |config_set|.
 | 
|  
 | 
|    Raise:
 | 
| @@ -29,17 +45,17 @@ def can_read_config_set(config_set, headers=None):
 | 
|      service_match = config.SERVICE_CONFIG_SET_RGX.match(config_set)
 | 
|      if service_match:
 | 
|        service_name = service_match.group(1)
 | 
| -      return can_read_service_config(service_name, headers=headers)
 | 
| +      return has_service_access(service_name)
 | 
|  
 | 
|      project_match = config.PROJECT_CONFIG_SET_RGX.match(config_set)
 | 
|      if project_match:
 | 
|        project_id = project_match.group(1)
 | 
| -      return can_read_project_config(project_id)
 | 
| +      return has_project_access(project_id)
 | 
|  
 | 
|      ref_match = config.REF_CONFIG_SET_RGX.match(config_set)
 | 
|      if ref_match:
 | 
|        project_id = ref_match.group(1)
 | 
| -      return can_read_project_config(project_id)
 | 
| +      return has_project_access(project_id)
 | 
|  
 | 
|    except ValueError:  # pragma: no cover
 | 
|      # Make sure we don't let ValueError raise for a reason different than
 | 
| @@ -49,32 +65,26 @@ def can_read_config_set(config_set, headers=None):
 | 
|    raise ValueError()
 | 
|  
 | 
|  
 | 
| -def can_read_service_config(service_id, headers=None):
 | 
| +def has_service_access(service_id):
 | 
|    """Returns True if current requester can read service configs.
 | 
|  
 | 
| -  If X-Appengine-Inbound-Appid header matches service_id, the permission is
 | 
| -  granted.
 | 
| +  An app <app-id> has access to configs of service with id <app-id>.
 | 
|    """
 | 
|    assert isinstance(service_id, basestring)
 | 
|    assert service_id
 | 
|  
 | 
| -  group = read_acl_cfg().service_access_group
 | 
| -  return (
 | 
| -      auth.is_admin() or
 | 
| -      group and auth.is_group_member(group) or
 | 
| -      (headers or {}).get('X-Appengine-Inbound-Appid') == service_id
 | 
| -  )
 | 
| -
 | 
| +  if auth.is_admin():
 | 
| +    return True
 | 
|  
 | 
| -# pylint: disable=W0613
 | 
| -def can_read_project_config(project_id):  # pragma: no cover
 | 
| -  return has_project_access()
 | 
| +  service_cfg = services.get_service_async(service_id).get_result()
 | 
| +  return service_cfg and _has_access(service_cfg.access)
 | 
|  
 | 
|  
 | 
| -def can_read_project_list():  # pragma: no cover
 | 
| -  return has_project_access()
 | 
| -
 | 
| -
 | 
| -def has_project_access():
 | 
| -  group = read_acl_cfg().project_access_group
 | 
| -  return auth.is_admin() or (group and auth.is_group_member(group))
 | 
| +def has_project_access(project_id):
 | 
| +  metadata = projects.get_metadata(project_id)
 | 
| +  super_group = read_acl_cfg().project_access_group
 | 
| +  return (
 | 
| +      auth.is_admin() or
 | 
| +      super_group and auth.is_group_member(super_group) or
 | 
| +      metadata and _has_access(metadata.access)
 | 
| +  )
 | 
| 
 |