Skip to content

Commit c7f4fb9

Browse files
committed
Use oauth endpoints for external testcase uploader
1 parent 96e334f commit c7f4fb9

File tree

2 files changed

+57
-36
lines changed

2 files changed

+57
-36
lines changed

src/clusterfuzz/_internal/config/local_config.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
MONITORING_REGIONS_PATH = 'monitoring.regions'
3535
PROJECT_PATH = 'project'
3636
SWARMING_PATH = 'swarming.swarming'
37-
EXTERNAL_TESTCASE_UPLOADER_PATH = 'external_testcase_reader.config'
37+
EXTERNAL_TESTCASE_UPLOADER_PATH = 'k8s.external_testcase_reader'
3838

3939

4040
def _load_yaml_file(yaml_file_path):

src/clusterfuzz/_internal/cron/external_testcase_reader.py

+56-35
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,27 @@
1919
from google.cloud import storage
2020
import requests
2121

22-
from appengine.libs import form
23-
from appengine.libs import gcs
24-
from appengine.libs import helpers
2522
from clusterfuzz._internal.config import local_config
2623
from clusterfuzz._internal.issue_management.google_issue_tracker import \
2724
issue_tracker
25+
from clusterfuzz._internal.metrics import logs
2826

2927
ACCEPTED_FILETYPES = [
3028
'text/javascript', 'application/pdf', 'text/html', 'application/zip'
3129
]
3230
ISSUETRACKER_ACCEPTED_STATE = 'ACCEPTED'
3331
ISSUETRACKER_WONTFIX_STATE = 'NOT_REPRODUCIBLE'
32+
_CLUSTERFUZZ_GET_URL = (
33+
'https://clusterfuzz.corp.google.com/upload-testcase/get-url-oauth')
34+
_UPLOAD_URL_PROPERTY = 'uploadUrl'
35+
_TESTCASE_ID_PROPERTY = 'id'
36+
37+
38+
class ExternalTestcaseReaderException(Exception):
39+
"""Error when uploading an externally submitted testcase.."""
40+
41+
def __init__(self, message):
42+
super().__init__(message)
3443

3544

3645
def get_vrp_uploaders(config):
@@ -42,19 +51,18 @@ def get_vrp_uploaders(config):
4251
return members
4352

4453

45-
def close_issue_if_invalid(upload_request, attachment_info, description,
46-
vrp_uploaders):
54+
def close_issue_if_invalid(issue, attachment_info, description, vrp_uploaders):
4755
"""Closes any invalid upload requests with a helpful message."""
4856
comment_message = (
4957
'Hello, this issue is automatically closed. Please file a new bug after'
5058
' fixing the following issues:\n\n')
5159
invalid = False
5260

5361
# TODO(pgrace) Remove after testing.
54-
if upload_request.id == 373893311:
62+
if issue.id == 373893311:
5563
return False
5664

57-
if not upload_request.reporter in vrp_uploaders:
65+
if not issue.reporter in vrp_uploaders:
5866
comment_message += (
5967
'You are not authorized to submit testcases to Clusterfuzz.'
6068
' If you believe you should be, please reach out to'
@@ -90,8 +98,8 @@ def close_issue_if_invalid(upload_request, attachment_info, description,
9098
comment_message += (
9199
'\nPlease see the new bug template for more information on how to use'
92100
' Clusterfuzz direct uploads.')
93-
upload_request.status = ISSUETRACKER_WONTFIX_STATE
94-
upload_request.save(new_comment=comment_message, notify=True)
101+
issue.status = ISSUETRACKER_WONTFIX_STATE
102+
issue.save(new_comment=comment_message, notify=True)
95103

96104
return invalid
97105

@@ -116,40 +124,48 @@ def filed_n_days_ago(issue_created_time_string, config):
116124

117125
def submit_testcase(issue_id, file, filename, filetype, cmds):
118126
"""Uploads the given testcase file to Clusterfuzz."""
127+
get_url_response = requests.post(_CLUSTERFUZZ_GET_URL, timeout=10)
128+
if _UPLOAD_URL_PROPERTY not in get_url_response:
129+
logs.error('Unexpected response (missing uploadUrl): %s' % get_url_response)
130+
raise ExternalTestcaseReaderException(
131+
'Unexpected response (missing uploadUrl): %s' % get_url_response)
132+
upload_url = get_url_response[_UPLOAD_URL_PROPERTY]
133+
134+
target = None
119135
if filetype == 'text/javascript':
120136
job = 'linux_asan_d8_dbg'
121137
elif filetype == 'application/pdf':
122138
job = 'libfuzzer_pdfium_asan'
139+
# Only libfuzzer_pdfium_asan needs a fuzzer target specified
140+
target = 'pdfium_xfa_fuzzer'
123141
elif filetype == 'text/html':
124142
job = 'linux_asan_chrome_mp'
125143
elif filetype == 'application/zip':
126144
job = 'linux_asan_chrome_mp'
127145
else:
128146
raise TypeError
129-
upload_info = gcs.prepare_blob_upload()._asdict()
130-
131147
data = {
132-
# Content provided by uploader.
133-
'issue': issue_id,
148+
'platform': 'Linux',
134149
'job': job,
135-
'file': file,
150+
'issue': issue_id,
136151
'cmd': cmds,
152+
'file': file,
137153
'x-goog-meta-filename': filename,
138-
139-
# Content generated internally.
140-
'platform': 'Linux',
141-
'csrf_token': form.generate_csrf_token(),
142-
'upload_key': upload_info['key'],
143-
# TODO(pgrace) Replace with upload_info['bucket'] once testing complete.
144-
'bucket': 'clusterfuzz-test-bucket',
145-
'key': upload_info['key'],
146-
'GoogleAccessId': upload_info['google_access_id'],
147-
'policy': upload_info['policy'],
148-
'signature': upload_info['signature'],
149154
}
150155

151-
return requests.post(
152-
'https://clusterfuzz.com/upload-testcase/upload', data=data, timeout=10)
156+
if target:
157+
data['target'] = target
158+
159+
upload_response = requests.post(upload_url, data=data, timeout=10)
160+
is_error_code = upload_response.status_code != 200
161+
is_missing_testcase_id = _TESTCASE_ID_PROPERTY not in upload_response
162+
if is_error_code or is_missing_testcase_id:
163+
reason = 'missing testcase id' if is_missing_testcase_id else 'failure code'
164+
msg = 'Unexpected response (%s): %s' % (reason, upload_response)
165+
logs.error(msg)
166+
raise ExternalTestcaseReaderException(msg)
167+
168+
return upload_response
153169

154170

155171
def handle_testcases(tracker, config):
@@ -163,15 +179,15 @@ def handle_testcases(tracker, config):
163179
for issue in older_issues:
164180
# Close out older bugs that may have failed to reproduce.
165181
if close_issue_if_not_reproducible(issue, config):
166-
helpers.log('Closing issue {issue_id} as it failed to reproduce',
167-
issue.id)
182+
logs.info('Closing issue %s as it failed to reproduce' & issue.id)
168183

169184
# Handle new bugs that may need to be submitted.
170185
issues = tracker.find_issues_with_filters(
171186
keywords=[],
172187
query_filters=['componentid:1600865', 'status:new'],
173188
only_open=True)
174-
if len(issues) == 0:
189+
issues_list = list(issues)
190+
if len(issues_list) == 0:
175191
return
176192

177193
vrp_uploaders = get_vrp_uploaders(config)
@@ -180,7 +196,7 @@ def handle_testcases(tracker, config):
180196
# Process only a certain number of bugs per reporter for each job run.
181197
reporters_map = {}
182198

183-
for issue in issues:
199+
for issue in issues_list:
184200
attachment_metadata = tracker.get_attachment_metadata(issue.id)
185201
commandline_flags = tracker.get_description(issue.id)
186202
if reporters_map.get(issue.reporter,
@@ -189,7 +205,7 @@ def handle_testcases(tracker, config):
189205
reporters_map[issue.reporter] = reporters_map.get(issue.reporter, 1) + 1
190206
if close_issue_if_invalid(issue, attachment_metadata, commandline_flags,
191207
vrp_uploaders):
192-
helpers.log('Closing issue {issue_id} as it is invalid', issue.id)
208+
logs.info('Closing issue %s as it is invalid' % issue.id)
193209
continue
194210

195211
# Submit valid testcases.
@@ -202,12 +218,17 @@ def handle_testcases(tracker, config):
202218
issue.status = ISSUETRACKER_ACCEPTED_STATE
203219
issue.assignee = 'clusterfuzz@chromium.org'
204220
issue.save(new_comment=comment_message, notify=True)
205-
helpers.log('Submitted testcase file for issue {issue_id}', issue.id)
221+
logs.info('Submitted testcase file for issue %s' % issue.id)
222+
223+
224+
_ISSUE_TRACKER_URL = 'https://issues.chromium.org/issues'
206225

207226

208227
def main():
209-
tracker = issue_tracker.IssueTracker('chromium', None,
210-
{'default_component_id': 1363614})
228+
tracker = issue_tracker.IssueTracker('chromium', None, {
229+
'default_component_id': 1363614,
230+
'url': _ISSUE_TRACKER_URL
231+
})
211232
handle_testcases(tracker, local_config.ExternalTestcaseReaderConfig())
212233

213234

0 commit comments

Comments
 (0)