blob: ff269619295db6a06f350a499f636dea5601de3e [file]
#!/usr/bin/env vpython
# Copyright 2014 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.
import base64
import datetime
import logging
import sys
import unittest
import test_env
test_env.setup_test_env()
from proto.internals import session_pb2
from server import bot_groups_config
from server import bot_session
from server import hmac_secret
from test_support import test_case
def _bot_group_config(**kwargs):
kwargs = kwargs.copy()
for f in bot_groups_config.BotGroupConfig._fields:
if f not in kwargs:
kwargs[f] = None
return bot_groups_config.BotGroupConfig(**kwargs)
TEST_CONFIG = _bot_group_config(
auth=[
bot_groups_config.BotAuth(
log_if_failed=True,
require_luci_machine_token=True,
require_service_account=[],
require_gce_vm_token=None,
ip_whitelist=None,
),
bot_groups_config.BotAuth(
log_if_failed=True,
require_luci_machine_token=False,
require_service_account=["sa1@example.com", "sa2@example.com"],
require_gce_vm_token=None,
ip_whitelist=None,
),
bot_groups_config.BotAuth(
log_if_failed=True,
require_luci_machine_token=False,
require_service_account=[],
require_gce_vm_token=bot_groups_config.BotAuthGCE("gce-proj"),
ip_whitelist=None,
),
bot_groups_config.BotAuth(
log_if_failed=False,
require_luci_machine_token=False,
require_service_account=[],
require_gce_vm_token=None,
ip_whitelist="ip-allowlist",
),
],
dimensions={
"ignored": [],
"dim1": ["a", "b"],
"dim2": ["d", "c"],
},
bot_config_script="script.py",
bot_config_script_sha256="script-sha256",
system_service_account="system@example.com",
logs_cloud_project="logs-cloud-project",
)
TEST_TIME = datetime.datetime(2010, 1, 2, 3, 4, 5, 6)
EXPECTED_BOT_CONFIG = session_pb2.BotConfig(
expiry={"seconds": 1262405045, "nanos": 6000},
debug_info={
"created": {"seconds": 1262401445, "nanos": 6000},
"swarming_version": "py/v1a",
"request_id": "7357B3D7091D",
},
bot_auth=[
{"require_luci_machine_token": True, "log_if_failed": True},
{
"require_service_account": ["sa1@example.com", "sa2@example.com"],
"log_if_failed": True,
},
{"require_gce_vm_token": {"project": "gce-proj"}, "log_if_failed": True},
{"ip_whitelist": "ip-allowlist"},
],
system_service_account="system@example.com",
logs_cloud_project="logs-cloud-project",
rbe_instance="rbe",
)
class BotSessionTest(test_case.TestCase):
def setUp(self):
super(BotSessionTest, self).setUp()
self.mock_now(TEST_TIME)
self.mock_secret("some-secret")
def mock_secret(self, val):
class MockedSecret(object):
def access(_self):
return val
self.mock(hmac_secret, "get_shared_hmac_secret", MockedSecret)
def test_round_trip(self):
original = session_pb2.Session(bot_id="bot-id", session_id="session-id")
tok = bot_session.marshal(original)
unmarshalled = bot_session.unmarshal(tok)
self.assertEqual(original, unmarshalled)
def test_bad_hmac(self):
original = session_pb2.Session(bot_id="bot-id", session_id="session-id")
tok = bot_session.marshal(original)
self.mock_secret("another-secret")
with self.assertRaises(bot_session.BadSessionToken):
bot_session.unmarshal(tok)
def test_wrong_format(self):
tok = session_pb2.SessionToken()
tok.aead_encrypted.cipher_text = "bzz"
serialized = base64.b64encode(tok.SerializeToString())
with self.assertRaises(bot_session.BadSessionToken):
bot_session.unmarshal(serialized)
def test_is_expired_session(self):
good = session_pb2.Session()
good.expiry.FromDatetime(TEST_TIME + datetime.timedelta(seconds=1))
self.assertFalse(bot_session.is_expired_session(good))
bad = session_pb2.Session()
bad.expiry.FromDatetime(TEST_TIME - datetime.timedelta(seconds=1))
self.assertTrue(bot_session.is_expired_session(bad))
def test_handshake_config(self):
data = bot_session._handshake_config_extract(TEST_CONFIG)
self.assertEqual(
data,
[
"config_script_name:script.py",
"config_script_sha256:script-sha256",
"dimension:dim1:a",
"dimension:dim1:b",
"dimension:dim2:c",
"dimension:dim2:d",
],
)
digest = bot_session._handshake_config_hash(TEST_CONFIG)
self.assertEqual(len(digest), 32)
def test_create(self):
session = bot_session.create("bot-id", "session-id", TEST_CONFIG, "rbe")
self.assertEqual(
session,
session_pb2.Session(
bot_id="bot-id",
session_id="session-id",
expiry={"seconds": 1262405045, "nanos": 6000},
debug_info={
"created": {"seconds": 1262401445, "nanos": 6000},
"swarming_version": "py/v1a",
"request_id": "7357B3D7091D",
},
bot_config=EXPECTED_BOT_CONFIG,
handshake_config_hash=bot_session._handshake_config_hash(TEST_CONFIG),
),
)
bot_session.debug_log(session)
def test_update(self):
session = session_pb2.Session()
bot_session.update(
session, TEST_CONFIG, "rbe", "pool:dut_id:dut_123", "dut_id"
)
bot_config = EXPECTED_BOT_CONFIG
bot_config.rbe_effective_bot_id = "pool:dut_id:dut_123"
bot_config.rbe_effective_bot_id_dimension = "dut_id"
self.assertEqual(
session,
session_pb2.Session(
expiry={"seconds": 1262405045, "nanos": 6000},
debug_info={
"created": {"seconds": 1262401445, "nanos": 6000},
"swarming_version": "py/v1a",
"request_id": "7357B3D7091D",
},
bot_config=bot_config,
),
)
if __name__ == "__main__":
if "-v" in sys.argv:
unittest.TestCase.maxDiff = None
logging.basicConfig(
level=logging.DEBUG if "-v" in sys.argv else logging.CRITICAL
)
unittest.main()