Skip to content

Commit e30ef54

Browse files
jardondiegoDiego Jardon
andauthored
Fix bypass Datastore access in uworker for job definition (#5293)
### Problem The function `get_value_from_job_definition` in data_handler.py can cause crashes when executed within a UWORKER (untrusted worker) environment. The function originally executed a query against Google Cloud Datastore: `job = data_types.Job.query(data_types.Job.name == job_type).get()` Because the UWORKER Docker container uses a restricted IAM Service Account ( untrusted-worker@... ), it has zero permissions to read from Datastore. This caused a fatal 403 PermissionDenied exception, crashing processes like the log upload. ### Fix When a task runs as a UWORKER, the Trusted Worker (TWORKER) that scheduled the task has already queried Datastore, extracted all the Job's environment variables, and injected them directly into the UWORKER's local environment. Therefore, querying Datastore from the UWORKER is both forbidden and redundant. --------- Co-authored-by: Diego Jardon <jardondiego@google.com>
1 parent 2a60dd6 commit e30ef54

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

src/clusterfuzz/_internal/datastore/data_handler.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,11 @@ def get_value_from_job_definition(job_type, variable_pattern, default=None):
12621262
if not job_type:
12631263
return default
12641264

1265+
# Short-circuit: UWORKERs do not have Datastore access. The TWORKER has
1266+
# already injected all job variables into the local environment.
1267+
if environment.is_uworker():
1268+
return environment.get_value(variable_pattern, default)
1269+
12651270
job = data_types.Job.query(data_types.Job.name == job_type).get()
12661271
if not job:
12671272
return default

src/clusterfuzz/_internal/tests/core/datastore/data_handler_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,3 +1223,26 @@ def test_no_entities_found(self):
12231223
self.GetEntitiesTestModel, equality_filters={'value': 5})
12241224
self.assertIsInstance(result, Generator)
12251225
self.assertCountEqual(result, [])
1226+
1227+
1228+
class GetValueFromJobDefinitionTest(unittest.TestCase):
1229+
"""Tests for get_value_from_job_definition."""
1230+
1231+
def setUp(self):
1232+
helpers.patch(self, [
1233+
'clusterfuzz._internal.system.environment.is_uworker',
1234+
'clusterfuzz._internal.system.environment.get_value',
1235+
'clusterfuzz._internal.datastore.data_types.Job.query',
1236+
])
1237+
1238+
def test_uworker_bypass(self):
1239+
"""Test that uworker environment skips Datastore and uses environment."""
1240+
self.mock.is_uworker.return_value = True
1241+
self.mock.get_value.return_value = 'env_value'
1242+
1243+
result = data_handler.get_value_from_job_definition(
1244+
'job_name', 'VAR_PATTERN', default='default_val')
1245+
1246+
self.assertEqual(result, 'env_value')
1247+
self.mock.get_value.assert_called_once_with('VAR_PATTERN', 'default_val')
1248+
self.mock.query.assert_not_called()

0 commit comments

Comments
 (0)