1# Copyright 2020 Google Inc. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# 15################################################################################ 16"""Cloud function to build base images on Google Cloud Builder.""" 17 18import datetime 19import logging 20 21import google.auth 22from googleapiclient.discovery import build 23 24BASE_IMAGES = [ 25 'base-image', 26 'base-clang', 27 'base-builder', 28 'base-runner', 29 'base-runner-debug', 30] 31BASE_PROJECT = 'oss-fuzz-base' 32TAG_PREFIX = f'gcr.io/{BASE_PROJECT}/' 33 34BASE_SANITIZER_LIBS_IMAGE = TAG_PREFIX + 'base-sanitizer-libs-builder' 35MSAN_LIBS_IMAGE = TAG_PREFIX + 'msan-libs-builder' 36 37 38def _get_base_image_steps(images, tag_prefix=TAG_PREFIX): 39 """Returns build steps for given images.""" 40 steps = [{ 41 'args': [ 42 'clone', 43 'https://github.com/google/oss-fuzz.git', 44 ], 45 'name': 'gcr.io/cloud-builders/git', 46 }] 47 48 for base_image in images: 49 steps.append({ 50 'args': [ 51 'build', 52 '-t', 53 tag_prefix + base_image, 54 '.', 55 ], 56 'dir': 'oss-fuzz/infra/base-images/' + base_image, 57 'name': 'gcr.io/cloud-builders/docker', 58 }) 59 60 return steps 61 62 63def get_logs_url(build_id, project_id='oss-fuzz-base'): 64 """Returns url that displays the build logs.""" 65 url_format = ('https://console.developers.google.com/logs/viewer?' 66 'resource=build%2Fbuild_id%2F{0}&project={1}') 67 return url_format.format(build_id, project_id) 68 69 70# pylint: disable=no-member 71def run_build(steps, images): 72 """Execute the retrieved build steps in gcp.""" 73 credentials, _ = google.auth.default() 74 build_body = { 75 'steps': steps, 76 'timeout': str(6 * 3600) + 's', 77 'options': { 78 'machineType': 'N1_HIGHCPU_32' 79 }, 80 'images': images 81 } 82 cloudbuild = build('cloudbuild', 83 'v1', 84 credentials=credentials, 85 cache_discovery=False) 86 build_info = cloudbuild.projects().builds().create(projectId=BASE_PROJECT, 87 body=build_body).execute() 88 build_id = build_info['metadata']['build']['id'] 89 logging.info('Build ID: %s', build_id) 90 logging.info('Logs: %s', get_logs_url(build_id, BASE_PROJECT)) 91 92 93def base_builder(event, context): 94 """Cloud function to build base images.""" 95 del event, context 96 97 tag_prefix = f'gcr.io/{BASE_PROJECT}/' 98 steps = _get_base_image_steps(BASE_IMAGES, tag_prefix) 99 images = [tag_prefix + base_image for base_image in BASE_IMAGES] 100 101 run_build(steps, images) 102 103 104def _get_msan_steps(image): 105 """Get build steps for msan-libs-builder.""" 106 timestamp = datetime.datetime.utcnow().strftime('%Y%m%d%H%M') 107 upload_name = 'msan-libs-' + timestamp + '.zip' 108 109 steps = _get_base_image_steps([ 110 'base-sanitizer-libs-builder', 111 'msan-libs-builder', 112 ]) 113 steps.extend([{ 114 'name': image, 115 'args': [ 116 'bash', 117 '-c', 118 'cd /msan && zip -r /workspace/libs.zip .', 119 ], 120 }, { 121 'name': 122 'gcr.io/cloud-builders/gsutil', 123 'args': [ 124 'cp', 125 '/workspace/libs.zip', 126 'gs://oss-fuzz-msan-libs/' + upload_name, 127 ], 128 }]) 129 return steps 130 131 132def base_msan_builder(event, context): 133 """Cloud function to build base images.""" 134 del event, context 135 steps = _get_msan_steps(MSAN_LIBS_IMAGE) 136 images = [ 137 BASE_SANITIZER_LIBS_IMAGE, 138 MSAN_LIBS_IMAGE, 139 ] 140 141 run_build(steps, images) 142