Ejemplo n.º 1
0
    def test_get_bucket_async(self):
        config.Bucket(
            id='master.tryserver.chromium.linux',
            project_id='chromium',
            revision='deadbeef',
            config_content=MASTER_TRYSERVER_CHROMIUM_LINUX_CONFIG_TEXT,
            config_content_binary=text_to_binary(
                MASTER_TRYSERVER_CHROMIUM_LINUX_CONFIG_TEXT),
        ).put()
        project, cfg = config.get_bucket_async(
            'master.tryserver.chromium.linux').get_result()
        self.assertEqual(project, 'chromium')
        self.assertEqual(
            cfg,
            project_config_pb2.Bucket(
                name='master.tryserver.chromium.linux',
                acls=[
                    project_config_pb2.Acl(role=project_config_pb2.Acl.READER,
                                           group='all'),
                    project_config_pb2.Acl(
                        role=project_config_pb2.Acl.SCHEDULER,
                        group='tryjob-access'),
                ]),
        )

        self.assertIsNone(
            config.get_bucket_async('non.existing').get_result()[0])
Ejemplo n.º 2
0
    def impl():
        ctx = ndb.get_context()
        cache_key = 'role/%s/%s' % (identity_str, bucket_id)
        cache = yield ctx.memcache_get(cache_key)
        if cache is not None:
            raise ndb.Return(cache[0])

        _, bucket_cfg = yield config.get_bucket_async(bucket_id)
        if not bucket_cfg:
            raise ndb.Return(None)
        if auth.is_admin(identity):
            raise ndb.Return(project_config_pb2.Acl.WRITER)

        # A LUCI service calling us in the context of some project is allowed to
        # do anything it wants in that project. We trust all LUCI services to do
        # authorization on their own for this case. A cross-project request must be
        # explicitly authorized in Buildbucket ACLs though (so we proceed to the
        # bucket_cfg check below).
        if identity.is_project:
            project_id, _ = config.parse_bucket_id(bucket_id)
            if project_id == identity.name:
                raise ndb.Return(project_config_pb2.Acl.WRITER)

        # Roles are just numbers. The higher the number, the more permissions
        # the identity has. We exploit this here to get the single maximally
        # permissive role for the current identity.
        role = None
        for rule in bucket_cfg.acls:
            if rule.role <= role:
                continue
            if (rule.identity == identity_str or
                (rule.group and auth.is_group_member(rule.group, identity))):
                role = rule.role
        yield ctx.memcache_set(cache_key, (role, ), time=60)
        raise ndb.Return(role)
Ejemplo n.º 3
0
  def test_get_bucket_async(self):
    config.Bucket(
        id='master.tryserver.chromium.linux',
        project_id='chromium',
        revision='deadbeef',
        config_content=MASTER_TRYSERVER_CHROMIUM_LINUX_CONFIG_TEXT).put()
    cfg = config.get_bucket_async(
        'master.tryserver.chromium.linux').get_result()
    self.assertEqual(
        cfg,
        project_config_pb2.Bucket(
            name='master.tryserver.chromium.linux',
            acls=[
              project_config_pb2.Acl(
                  role=project_config_pb2.Acl.READER, group='all'),
              project_config_pb2.Acl(
                  role=project_config_pb2.Acl.SCHEDULER, group='tryjob-access'),
            ]),
    )

    self.assertIsNone(config.get_bucket_async('non.existing').get_result())
Ejemplo n.º 4
0
    def get_task_def(self, request):
        """Returns a swarming task definition for a build request."""
        try:
            # Checks access too.
            request.build_request.bucket = api.convert_bucket(
                request.build_request.bucket)

            build_request = api.put_request_message_to_build_request(
                request.build_request)

            # Find builder config.
            builder_id = build_request.schedule_build_request.builder
            builder_cfg = None
            bucket_id = config.format_bucket_id(builder_id.project,
                                                builder_id.bucket)
            _, bucket_cfg = config.get_bucket_async(bucket_id).get_result()
            assert bucket_cfg, 'if there is no bucket, access check would fail'
            for cfg in bucket_cfg.swarming.builders:  # pragma: no branch
                if cfg.name == builder_id.builder:
                    builder_cfg = cfg
                    break
            if not builder_cfg:
                raise endpoints.NotFoundException(
                    'Builder %s/%s/%s not found' %
                    (builder_id.project, builder_id.bucket,
                     builder_id.builder))

            settings = config.get_settings_async().get_result()

            # Create a fake build and prepare a task definition.
            identity = auth.get_current_identity()
            build = build_request.create_build_async(
                1, settings, builder_cfg, identity,
                utils.utcnow()).get_result()
            assert build.proto.HasField('infra')
            build.proto.number = 1
            settings = config.get_settings_async().get_result()
            task_def = swarming.compute_task_def(build,
                                                 settings,
                                                 fake_build=True)
            task_def_json = json.dumps(task_def)

            return GetTaskDefinitionResponseMessage(
                task_definition=task_def_json,
                swarming_host=build.proto.infra.swarming.hostname,
            )
        except errors.InvalidInputError as ex:
            raise endpoints.BadRequestException('invalid build request: %s' %
                                                ex.message)
Ejemplo n.º 5
0
def prepare_task_def_async(build, fake_build=False):
    """Prepares a swarming task definition.

  Validates the new build.
  If configured, generates a build number and updates the build.
  Creates a swarming task definition.

  Returns a tuple (bucket_cfg, builder_cfg, task_def).
  """
    if build.lease_key:
        raise errors.InvalidInputError(
            'Swarming buckets do not support creation of leased builds')
    if not build.parameters:
        raise errors.InvalidInputError(
            'A build for bucket %r must have parameters' % build.bucket)
    builder_name = build.parameters.get(BUILDER_PARAMETER)
    if not isinstance(builder_name, basestring):
        raise errors.InvalidInputError('Invalid builder name %r' %
                                       builder_name)
    project_id, bucket_cfg = yield config.get_bucket_async(build.bucket)

    if not bucket_cfg.HasField('swarming'):
        raise errors.InvalidInputError(
            'Bucket %s is not configured for swarming' % build.bucket)

    builder_cfg = None
    for b in bucket_cfg.swarming.builders:  # pragma: no branch
        if b.name == builder_name:  # pragma: no branch
            builder_cfg = b
            break
    if not builder_cfg:
        raise errors.InvalidInputError(
            'Builder %r is not defined in bucket %r' %
            (builder_name, build.bucket))

    build_number = None
    if builder_cfg.build_numbers:  # pragma: no branch
        seq_name = '%s/%s' % (build.bucket, builder_name)
        if fake_build:  # pragma: no cover | covered by swarmbucket_api_test
            build_number = 0
        else:
            build_number = yield sequence.generate_async(seq_name, 1)
        build.tags.append('build_address:%s/%d' % (seq_name, build_number))

    task_def = yield _create_task_def_async(project_id, bucket_cfg.swarming,
                                            builder_cfg, build, build_number,
                                            fake_build)
    raise ndb.Return(bucket_cfg, builder_cfg, task_def)
Ejemplo n.º 6
0
def has_any_of_roles_async(bucket, roles):
    """True if current identity has any of |roles| in |bucket|."""
    assert bucket
    assert roles
    errors.validate_bucket_name(bucket)
    roles = set(roles)
    assert roles.issubset(project_config_pb2.Acl.Role.values())

    if auth.is_admin():
        raise ndb.Return(True)

    _, bucket_cfg = yield config.get_bucket_async(bucket)
    identity_str = auth.get_current_identity().to_bytes()
    if bucket_cfg:
        for rule in bucket_cfg.acls:
            if rule.role not in roles:
                continue
            if rule.identity == identity_str:
                raise ndb.Return(True)
            if rule.group and auth.is_group_member(rule.group):
                raise ndb.Return(True)
    raise ndb.Return(False)
Ejemplo n.º 7
0
def has_any_of_roles_async(bucket, roles):
  """True if current identity has any of |roles| in |bucket|."""
  assert bucket
  assert roles
  errors.validate_bucket_name(bucket)
  roles = set(roles)
  assert roles.issubset(project_config_pb2.Acl.Role.values())

  if auth.is_admin():
    raise ndb.Return(True)

  bucket_cfg = yield config.get_bucket_async(bucket)
  identity_str = auth.get_current_identity().to_bytes()
  if bucket_cfg:
    for rule in bucket_cfg.acls:
      if rule.role not in roles:
        continue
      if rule.identity == identity_str:
        raise ndb.Return(True)
      if rule.group and auth.is_group_member(rule.group):
        raise ndb.Return(True)
  raise ndb.Return(False)