def test_validate_bucket_name(self): with self.assertRaises(errors.InvalidInputError): errors.validate_bucket_name(1) with self.assertRaises(errors.InvalidInputError): errors.validate_bucket_name('') with self.assertRaises(errors.InvalidInputError): errors.validate_bucket_name('no spaces') with self.assertRaises(errors.InvalidInputError): errors.validate_bucket_name('no spaces') errors.validate_bucket_name('good-name')
def validate_buildbucket_cfg(cfg, ctx): import swarmingcfg acl_set_names = set() for i, acl_set in enumerate(cfg.acl_sets): with ctx.prefix('ACL set #%d (%s): ', i + 1, acl_set.name): if not acl_set.name: ctx.error('name is unspecified') elif not ACL_SET_NAME_RE.match(acl_set.name): ctx.error('invalid name "%s" does not match regex %r', acl_set.name, ACL_SET_NAME_RE.pattern) elif acl_set.name in acl_set_names: ctx.error('duplicate name "%s"', acl_set.name) acl_set_names.add(acl_set.name) validate_access_list(acl_set.acls, ctx) mixin_ctx = validation.Context( # pragma: no cover on_message=lambda msg: ctx.msg(msg.severity, '%s', msg.text)) swarmingcfg.validate_builder_mixins(cfg.builder_mixins, mixin_ctx) mixins_are_valid = not mixin_ctx.result().has_errors mixin_by_name = {m.name: m for m in cfg.builder_mixins} bucket_names = set() for i, bucket in enumerate(cfg.buckets): with ctx.prefix('Bucket %s: ', bucket.name or ('#%d' % (i + 1))): try: errors.validate_bucket_name(bucket.name, project_id=ctx.project_id) except errors.InvalidInputError as ex: ctx.error('invalid name: %s', ex.message) else: if bucket.name in bucket_names: ctx.error('duplicate bucket name') else: bucket_names.add(bucket.name) if i > 0 and bucket.name < cfg.buckets[i - 1].name: ctx.warning('out of order') validate_access_list(bucket.acls, ctx) for name in bucket.acl_sets: if name not in acl_set_names: ctx.error( 'undefined ACL set "%s". ' 'It must be defined in the same file', name) if bucket.HasField('swarming'): # pragma: no cover with ctx.prefix('swarming: '): swarmingcfg.validate_project_cfg(bucket.swarming, mixin_by_name, mixins_are_valid, ctx)
def can_async(bucket, action): errors.validate_bucket_name(bucket) assert isinstance(action, Action) identity = auth.get_current_identity() cache_key = 'acl_can/%s/%s/%s' % (bucket, identity.to_bytes(), action.name) ctx = ndb.get_context() result = yield ctx.memcache_get(cache_key) if result is not None: raise ndb.Return(result) result = yield has_any_of_roles_async(bucket, ROLES_FOR_ACTION[action]) yield ctx.memcache_set(cache_key, result, time=60) raise ndb.Return(result)
def validate_buildbucket_cfg(cfg, ctx): is_sorted = True bucket_names = set() for i, bucket in enumerate(cfg.buckets): with ctx.prefix('Bucket %s: ', bucket.name or ('#%d' % (i + 1))): try: errors.validate_bucket_name(bucket.name) except errors.InvalidInputError as ex: ctx.error('invalid name: %s', ex.message) else: if bucket.name in bucket_names: ctx.error('duplicate bucket name') else: bucket_names.add(bucket.name) if ctx.project_id: # pragma: no branch bucket_entity = Bucket.get_by_id(bucket.name) if bucket_entity and bucket_entity.project_id != ctx.project_id: ctx.error('this name is already reserved by another project') if is_sorted and i > 0 and cfg.buckets[i - 1].name: if bucket.name < cfg.buckets[i - 1].name: is_sorted = False for i, acl in enumerate(bucket.acls): with ctx.prefix('acl #%d: ', i + 1): if acl.group and acl.identity: ctx.error('either group or identity must be set, not both') elif acl.group: if not auth.is_valid_group_name(acl.group): ctx.error('invalid group: %s', acl.group) elif acl.identity: validate_identity(acl.identity, ctx) else: ctx.error('group or identity must be set') if bucket.HasField('swarming'): # pragma: no cover with ctx.prefix('swarming: '): swarmingcfg.validate_cfg(bucket.swarming, ctx) if not is_sorted: ctx.warning('Buckets are not sorted by name')
def validate_buildbucket_cfg(cfg, ctx): is_sorted = True bucket_names = set() for i, bucket in enumerate(cfg.buckets): with ctx.prefix('Bucket %s: ', bucket.name or ('#%d' % (i + 1))): try: errors.validate_bucket_name(bucket.name) except errors.InvalidInputError as ex: ctx.error('invalid name: %s', ex.message) else: if bucket.name in bucket_names: ctx.error('duplicate bucket name') else: bucket_names.add(bucket.name) if ctx.project_id: # pragma: no branch bucket_entity = Bucket.get_by_id(bucket.name) if bucket_entity and bucket_entity.project_id != ctx.project_id: ctx.error( 'this name is already reserved by another project' ) if is_sorted and i > 0 and cfg.buckets[i - 1].name: if bucket.name < cfg.buckets[i - 1].name: is_sorted = False for i, acl in enumerate(bucket.acls): with ctx.prefix('acl #%d: ', i + 1): if acl.group and acl.identity: ctx.error( 'either group or identity must be set, not both') elif acl.group: if not auth.is_valid_group_name(acl.group): ctx.error('invalid group: %s', acl.group) elif acl.identity: validate_identity(acl.identity, ctx) else: ctx.error('group or identity must be set') if not is_sorted: ctx.warning('Buckets are not sorted by name')
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)
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)
def test_validate_bucket_name(self): with self.assertRaises(errors.InvalidInputError): errors.validate_bucket_name(1) with self.assertRaises(errors.InvalidInputError): errors.validate_bucket_name('luci.x', project_id='y') with self.assertRaises(errors.InvalidInputError): errors.validate_bucket_name('') with self.assertRaises(errors.InvalidInputError): errors.validate_bucket_name('no spaces') with self.assertRaises(errors.InvalidInputError): errors.validate_bucket_name('no spaces') errors.validate_bucket_name('good-name') errors.validate_bucket_name('luci.infra.try', project_id='infra')