예제 #1
0
 def test_bad_ip_whitelist_name(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(auth=bots_pb2.BotAuth(
             ip_whitelist='bad ## name'))
     ])
     self.validator_test(
         cfg, ['bot_group #0: invalid ip_whitelist name "bad ## name"'])
예제 #2
0
 def test_bad_owners(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(
             bot_id=['blah'], auth=DEFAULT_AUTH_CFG, owners=['bad email']),
     ])
     self.validator_test(cfg,
                         ['bot_group #0: invalid owner email "bad email"'])
예제 #3
0
 def test_bad_auth_cfg_no_ip_whitelist(self):
     cfg = bots_pb2.BotsCfg(
         bot_group=[bots_pb2.BotGroup(auth=bots_pb2.BotAuth())])
     self.validator_test(cfg, [
         'bot_group #0: if both require_luci_machine_token and '
         'require_service_account are unset, ip_whitelist is required'
     ])
예제 #4
0
 def test_bad_required_service_account(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(auth=bots_pb2.BotAuth(
             require_service_account='not-an-email'))
     ])
     self.validator_test(
         cfg,
         ['bot_group #0: invalid service account email "not-an-email"'])
예제 #5
0
 def test_duplicate_prefixes(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(bot_id_prefix=['abc-'], auth=DEFAULT_AUTH_CFG),
         bots_pb2.BotGroup(bot_id_prefix=['abc-'], auth=DEFAULT_AUTH_CFG),
     ])
     self.validator_test(cfg, [
         'bot_group #1: bot_id_prefix "abc-" is already specified in group #0'
     ])
예제 #6
0
 def test_bot_id_duplication(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(bot_id=['b{0..5}'], auth=DEFAULT_AUTH_CFG),
         bots_pb2.BotGroup(bot_id=['b5'], auth=DEFAULT_AUTH_CFG),
     ])
     self.validator_test(
         cfg,
         ['bot_group #1: bot_id "b5" was already mentioned in group #0'])
예제 #7
0
 def test_bad_bot_id(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(bot_id=['blah{}'], auth=DEFAULT_AUTH_CFG),
     ])
     self.validator_test(cfg, [
         'bot_group #0: bad bot_id expression "blah{}" - Invalid set "", '
         'not a list and not a range'
     ])
예제 #8
0
 def test_bad_dimension_not_kv(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(bot_id=['blah'],
                           auth=DEFAULT_AUTH_CFG,
                           dimensions=['not_kv_pair']),
     ])
     self.validator_test(cfg, [
         'bot_group #0: bad dimension "not_kv_pair", not a key:value pair'
     ])
예제 #9
0
 def test_bad_dimension_bad_dim_key(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(bot_id=['blah'],
                           auth=DEFAULT_AUTH_CFG,
                           dimensions=['blah####key:value:value']),
     ])
     self.validator_test(cfg, [
         'bot_group #0: bad dimension key in "blah####key:value:value", '
         'should match ^[a-zA-Z\\-\\_\\.]+$'
     ])
예제 #10
0
 def test_bad_auth_cfg_two_methods(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(auth=bots_pb2.BotAuth(
             require_luci_machine_token=True,
             require_service_account='*****@*****.**',
         ))
     ])
     self.validator_test(cfg, [
         'bot_group #0: require_luci_machine_token and require_service_account '
         'can\'t both be used at the same time'
     ])
예제 #11
0
def _get_expanded_bots_cfg(known_digest=None):
    """Fetches expanded bots.cfg from the datastore cache.

  If the cache is not there (may happen right after deploying the service or
  after changing _BOT_CFG_CACHE_VER), falls back to fetching the config directly
  right here. This situation is rare.

  Args:
    known_digest: digest of ExpandedBotsCfg already known to the caller, to skip
        fetching it from the cache if nothing has changed.

  Returns:
    (True, ExpandedBotsCfg) if fetched some new version from the cache.
    (True, None) if there's no bots.cfg config at all.
    (False, None) if the cached version has digest matching 'known_digest'.

  Raises:
    BadConfigError if there's no cached config and the current config at HEAD is
    not passing validation.
  """
    head = _bots_cfg_head_key().get()
    if not head:
        # This branch is hit when we deploy the service the first time, before
        # the fetch cron runs, or after changing _BOT_CFG_CACHE_VER. We manually
        # refresh the cache in this case, not waiting for the cron.
        logging.warning('No bots.cfg cached for code v%d, forcing the refresh',
                        _BOT_CFG_CACHE_VER)
        expanded = refetch_from_config_service(
        )  # raises BadConfigError on errors
        if expanded and known_digest and expanded.digest == known_digest:
            return False, None
        return True, expanded

    if known_digest and head.digest == known_digest:
        return False, None
    if head.empty:
        return True, None

    # At this point we know there's something newer stored in the cache. Grab it.
    # Since this happens outside of a transaction, we may fetch a version that is
    # ever newer than pointed to by 'head'. This is fine.
    body = _bots_cfg_body_key().get()
    if not body:
        raise AssertionError(
            'BotsCfgBody is missing, this should not be possible')

    if known_digest and body.digest == known_digest:
        return False, None  # the body was sneakily reverted back just now
    if body.empty:
        return True, None

    bots = bots_pb2.BotsCfg()
    bots.ParseFromString(body.bots_cfg)
    return True, ExpandedBotsCfg(bots, body.bots_cfg_rev, body.digest)
예제 #12
0
 def test_intersecting_prefixes(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(bot_id_prefix=['abc-'], auth=DEFAULT_AUTH_CFG),
         bots_pb2.BotGroup(bot_id_prefix=['abc-def-'],
                           auth=DEFAULT_AUTH_CFG),
     ])
     self.validator_test(cfg, [
         'bot_id_prefix "abc-", defined in group #0, is subprefix of "abc-def-", '
         'defined in group #1; it makes group assigned for bots with prefix '
         '"abc-def-" ambigious'
     ])
예제 #13
0
TEST_CONFIG = bots_pb2.BotsCfg(
    trusted_dimensions=['pool'],
    bot_group=[
        bots_pb2.BotGroup(
            bot_id=['bot_with_token'],
            auth=bots_pb2.BotAuth(require_luci_machine_token=True),
            dimensions=['pool:with_token']),
        bots_pb2.BotGroup(bot_id=['bot_with_service_account'],
                          auth=bots_pb2.BotAuth(require_service_account=[
                              '*****@*****.**',
                              '*****@*****.**',
                          ]),
                          dimensions=['pool:with_service_account']),
        bots_pb2.BotGroup(bot_id=['bot_with_ip_whitelist'],
                          auth=bots_pb2.BotAuth(ip_whitelist='ip_whitelist'),
                          dimensions=['pool:with_ip_whitelist']),
        bots_pb2.BotGroup(
            bot_id=['bot_with_service_account_and_ip_whitelist'],
            auth=bots_pb2.BotAuth(
                require_service_account=['*****@*****.**'],
                ip_whitelist='ip_whitelist',
            ),
            dimensions=['pool:with_service_account_and_ip_whitelist']),
        bots_pb2.BotGroup(bot_id=['bot_with_token_and_ip_whitelist'],
                          auth=bots_pb2.BotAuth(
                              require_luci_machine_token=True,
                              ip_whitelist='ip_whitelist'),
                          dimensions=['pool:with_token_and_ip_whitelist']),
    ],
)
예제 #14
0
 def test_empty_config_is_valid(self):
     self.validator_test(bots_pb2.BotsCfg(), [])
예제 #15
0
 def test_trusted_dimensions_valid(self):
     cfg = bots_pb2.BotsCfg(trusted_dimensions=['pool', 'project'])
     self.validator_test(cfg, [])
예제 #16
0
 def test_trusted_dimensions_invalid(self):
     cfg = bots_pb2.BotsCfg(trusted_dimensions=['pool:blah'])
     self.validator_test(cfg, [
         'trusted_dimensions: invalid dimension key - "pool:blah", '
         'must match ^[a-zA-Z\\-\\_\\.]+$'
     ])
예제 #17
0
 def test_empty_prefix(self):
     cfg = bots_pb2.BotsCfg(bot_group=[
         bots_pb2.BotGroup(bot_id_prefix=[''], auth=DEFAULT_AUTH_CFG)
     ])
     self.validator_test(
         cfg, ['bot_group #0: empty bot_id_prefix is not allowed'])
예제 #18
0
from components import utils
from components.config import validation
from test_support import test_case

from proto import bots_pb2
from server import bot_groups_config

TEST_CONFIG = bots_pb2.BotsCfg(
    trusted_dimensions=['pool'],
    bot_group=[
        bots_pb2.BotGroup(
            bot_id=['bot1', 'bot{2..3}'],
            auth=bots_pb2.BotAuth(require_luci_machine_token=True),
            owners=['*****@*****.**'],
            dimensions=['pool:A', 'pool:B', 'other:D'],
        ),
        bots_pb2.BotGroup(
            bot_id=['other_bot'],
            bot_id_prefix=['bot'],
            auth=bots_pb2.BotAuth(require_service_account='*****@*****.**')),
        bots_pb2.BotGroup(auth=bots_pb2.BotAuth(ip_whitelist='bots'),
                          dimensions=['pool:default']),
    ],
)

EXPECTED_GROUP_1 = bot_groups_config._make_bot_group_config(
    require_luci_machine_token=True,
    require_service_account=u'',
    ip_whitelist=u'',
    owners=(u'*****@*****.**', ),
    dimensions={