Пример #1
0
def send(to_email, subject, html_content):
    """Send email."""
    sendgrid_api_key = db_config.get_value('sendgrid_api_key')
    if not sendgrid_api_key:
        logs.log_warn(
            'Skipping email as SendGrid API key is not set in config.')
        return

    from_email = db_config.get_value('sendgrid_sender')
    if not from_email:
        logs.log_warn(
            'Skipping email as SendGrid sender is not set in config.')
        return

    message = Mail(from_email=From(str(from_email)),
                   to_emails=To(str(to_email)),
                   subject=Subject(subject),
                   html_content=HtmlContent(str(html_content)))
    try:
        sg = SendGridAPIClient(sendgrid_api_key)
        response = sg.send(message)
        logs.log('Sent email to %s.' % to_email,
                 status_code=response.status_code,
                 body=response.body,
                 headers=response.headers)
    except Exception:
        logs.log_error('Failed to send email to %s.' % to_email)
Пример #2
0
def get_access_token(verification_code):
  """Get the access token from verification code.

    See: https://developers.google.com/identity/protocols/OAuth2InstalledApp
  """
  client_id = db_config.get_value('reproduce_tool_client_id')
  if not client_id:
    raise helpers.UnauthorizedException('Client id not configured.')

  client_secret = db_config.get_value('reproduce_tool_client_secret')
  if not client_secret:
    raise helpers.UnauthorizedException('Client secret not configured.')

  response = requests.post(
      'https://www.googleapis.com/oauth2/v4/token',
      headers={'Content-Type': 'application/x-www-form-urlencoded'},
      data={
          'code': verification_code,
          'client_id': client_id,
          'client_secret': client_secret,
          'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob',
          'grant_type': 'authorization_code'
      })

  if response.status_code != 200:
    raise helpers.UnauthorizedException('Invalid verification code (%s): %s' %
                                        (verification_code, response.text))

  try:
    data = json.loads(response.text)
    return data['access_token']
  except (KeyError, ValueError) as e:
    raise helpers.EarlyExitException(
        'Parsing the JSON response body failed: %s' % response.text, 500) from e
Пример #3
0
def _is_blacklisted_user(email):
    """Check if an email is in the privileged users list."""
    blacklisted_user_emails = (db_config.get_value('blacklisted_users')
                               or '').splitlines()
    return any(
        utils.emails_equal(email, blacklisted_user_email)
        for blacklisted_user_email in blacklisted_user_emails)
Пример #4
0
def _get_access_token():
    """Get access to GitHub with the oss-fuzz personal access token"""
    token = db_config.get_value('oss_fuzz_robot_github_personal_access_token')
    if not token:
        raise RuntimeError('Unable to access GitHub account to '
                           'file/close the issue.')
    return github.Github(token)
Пример #5
0
    def post(self):
        """Download the reproduce tool configuration json."""
        client_id = db_config.get_value('reproduce_tool_client_id')
        if not client_id:
            return self.render_json(
                {'error': 'Reproduce tool is not configured.'}, 500)

        domain = data_handler.get_domain()
        link_format = 'https://{domain}/{handler}'
        configuration = {
            'testcase_info_url':
            link_format.format(domain=domain,
                               handler='reproduce-tool/testcase-info'),
            'testcase_download_url':
            link_format.format(domain=domain,
                               handler='testcase-detail/download-testcase'),
            'oauth_url':
            'https://accounts.google.com/o/oauth2/v2/auth?{}'.format(
                urllib.parse.urlencode({
                    'client_id':
                    client_id,
                    'scope':
                    'email profile',
                    'response_type':
                    'code',
                    'redirect_uri':
                    'urn:ietf:wg:oauth:2.0:oob'
                })),
        }

        return self.render_json(configuration)
Пример #6
0
    def get(self):
        """Get the HTML page."""
        documentation_url = db_config.get_value('documentation_url')
        if not documentation_url:
            documentation_url = DEFAULT_DOCUMENTATION_URL

        return self.redirect(documentation_url)
Пример #7
0
    def get(self):
        """Get the HTML page."""
        bug_report_url = db_config.get_value('bug_report_url')
        if not bug_report_url:
            bug_report_url = DEFAULT_BUG_REPORT_URL

        return self.redirect(bug_report_url)
Пример #8
0
def _is_privileged_user(email):
    """Check if an email is in the privileged users list."""
    if local_config.AuthConfig().get('all_users_privileged'):
        return True

    privileged_user_emails = (db_config.get_value('privileged_users')
                              or '').splitlines()
    return any(
        utils.emails_equal(email, privileged_user_email)
        for privileged_user_email in privileged_user_emails)
Пример #9
0
def get_email_and_access_token(authorization):
  """Get user email from the request.

    See: https://developers.google.com/identity/protocols/OAuth2InstalledApp
  """
  if authorization.startswith(VERIFICATION_CODE_PREFIX):
    verification_code = authorization.split(' ')[1]
    access_token = get_access_token(verification_code)
    authorization = BEARER_PREFIX + access_token

  if not authorization.startswith(BEARER_PREFIX):
    raise helpers.UnauthorizedException(
        'The Authorization header is invalid. It should have been started with'
        " '%s'." % BEARER_PREFIX)

  access_token = authorization.split(' ')[1]

  response = requests.get(
      'https://www.googleapis.com/oauth2/v3/tokeninfo',
      params={'access_token': access_token})
  if response.status_code != 200:
    raise helpers.UnauthorizedException(
        'Failed to authorize. The Authorization header (%s) might be invalid.' %
        authorization)

  try:
    data = json.loads(response.text)

    # Whitelist service accounts. They have different client IDs (or aud).
    # Therefore, we check against their email directly.
    if data.get('email_verified') and data.get('email') in _auth_config().get(
        'whitelisted_oauth_emails', default=[]):
      return data['email'], authorization

    # Validate that this is an explicitly whitelisted client ID, or the client
    # ID for the reproduce tool.
    whitelisted_client_ids = _auth_config().get(
        'whitelisted_oauth_client_ids', default=[])
    reproduce_tool_client_id = db_config.get_value('reproduce_tool_client_id')
    if reproduce_tool_client_id:
      whitelisted_client_ids += [reproduce_tool_client_id]
    if data.get('aud') not in whitelisted_client_ids:
      raise helpers.UnauthorizedException(
          "The access token doesn't belong to one of the allowed OAuth clients"
          ': %s.' % response.text)

    if not data.get('email_verified'):
      raise helpers.UnauthorizedException('The email (%s) is not verified: %s.'
                                          % (data.get('email'), response.text))

    return data['email'], authorization
  except (KeyError, ValueError) as e:
    raise helpers.EarlyExitException(
        'Parsing the JSON response body failed: %s' % response.text, 500) from e
Пример #10
0
    def locked_get(self):
        """Return Credentials."""
        content = db_config.get_value('client_credentials')
        if not content:
            return None

        try:
            credentials = Credentials.new_from_json(content)
            credentials.set_store(self)
        except ValueError:
            return None

        return credentials
Пример #11
0
def get_github_url(url):
    """Return contents of URL."""
    github_credentials = db_config.get_value('github_credentials')
    if not github_credentials:
        raise ProjectSetupError('No github credentials.')

    client_id, client_secret = github_credentials.strip().split(';')
    response = requests.get(url, auth=(client_id, client_secret))
    if response.status_code != 200:
        logs.log_error('Failed to get github url: %s' % url,
                       status_code=response.status_code)
        response.raise_for_status()

    return json.loads(response.text)
Пример #12
0
def get_user_job_type():
    """Return the job_type that is assigned to the current user. None means one
    can access any job type. You might want to invoke get_access(..) with
    the job type afterward."""
    email = helpers.get_user_email()
    privileged_user_emails = (db_config.get_value('privileged_users')
                              or '').splitlines()
    for privileged_user_email in privileged_user_emails:
        if ';' in privileged_user_email:
            tokens = privileged_user_email.split(';')
            privileged_user_real_email = tokens[0]
            privileged_user_job_type = tokens[1]
            if utils.emails_equal(email, privileged_user_real_email):
                return privileged_user_job_type
    return None
Пример #13
0
    def render_forbidden(self, message):
        """Write HTML response for 403."""
        login_url = make_login_url(dest_url=request.url)
        user_email = helpers.get_user_email()
        if not user_email:
            return self.redirect(login_url)

        contact_string = db_config.get_value('contact_string')
        template_values = {
            'message': message,
            'user_email': helpers.get_user_email(),
            'login_url': login_url,
            'switch_account_url': login_url,
            'logout_url': make_logout_url(dest_url=request.url),
            'contact_string': contact_string,
        }
        return self.render('error-403.html', template_values, 403)
Пример #14
0
def _get_current_lock_zone():
  """Get the current zone for locking purposes."""
  if environment.get_value('LOCAL_DEVELOPMENT', False):
    return 'local'

  platform = environment.get_platform_group().lower()
  platform_group_mappings = db_config.get_value('platform_group_mappings')
  for mapping in platform_group_mappings.splitlines():
    if ';' not in mapping:
      continue

    platform_group, zone = mapping.split(';')
    if platform_group.strip() == platform:
      return zone

  # Default to per-platform separation.
  logs.log_warn('Platform group mapping not set in admin configuration, '
                'using default platform - %s.' % platform)
  return platform
Пример #15
0
def get_client():
  """Return client with connection to build apiary."""
  # Connect using build apiary service account credentials.
  build_apiary_service_account_private_key = db_config.get_value(
      'build_apiary_service_account_private_key')
  if not build_apiary_service_account_private_key:
    logs.log(
        'Android build apiary credentials are not set, skip artifact fetch.')
    return None

  credentials = ServiceAccountCredentials.from_json_keyfile_dict(
      json.loads(build_apiary_service_account_private_key),
      scopes='https://www.googleapis.com/auth/androidbuild.internal')
  client = apiclient.discovery.build(
      'androidbuildinternal',
      'v2beta1',
      credentials=credentials,
      cache_discovery=False)

  return client
Пример #16
0
def execute_task(testcase_id, _):
    """Attempt to find the CL introducing the bug associated with testcase_id."""
    # Locate the testcase associated with the id.
    testcase = data_handler.get_testcase_by_id(testcase_id)
    if not testcase:
        return

    # Make sure that predator topic is configured. If not, nothing to do here.
    topic = db_config.get_value('predator_crash_topic')
    if not topic:
        logs.log('Predator is not configured, skipping blame task.')
        return

    data_handler.update_testcase_comment(testcase,
                                         data_types.TaskState.STARTED)

    # Prepare pubsub message to send to predator.
    message = _prepare_predator_message(testcase)
    if not message:
        testcase = data_handler.get_testcase_by_id(testcase_id)
        data_handler.update_testcase_comment(
            testcase, data_types.TaskState.ERROR,
            'Failed to generate request for Predator')
        return

    # Clear existing results and mark blame result as pending.
    testcase = data_handler.get_testcase_by_id(testcase_id)
    _clear_blame_result_and_set_pending_flag(testcase)

    # Post request to pub sub.
    client = pubsub.PubSubClient()
    message_ids = client.publish(topic, [message])
    logs.log(
        'Successfully published testcase %s to Predator. Message IDs: %s.' %
        (testcase_id, message_ids))
    data_handler.update_testcase_comment(testcase,
                                         data_types.TaskState.FINISHED)
Пример #17
0
  def get(self):
    """Process a GET request."""
    subscription = db_config.get_value('predator_result_topic')
    if not subscription:
      logs.log('No Predator subscription configured. Aborting.')
      return

    client = pubsub.PubSubClient()
    messages = client.pull_from_subscription(subscription, acknowledge=True)
    for message in messages:
      message = json.loads(message.data)
      testcase_id = message['crash_identifiers']
      try:
        testcase = data_handler.get_testcase_by_id(testcase_id)
      except errors.InvalidTestcaseError:
        logs.log('Testcase %s no longer exists.' % str(testcase_id))
        continue

      testcase.set_metadata('predator_result', message, update_testcase=False)
      testcase.delete_metadata('blame_pending', update_testcase=False)
      testcase.put()
      logs.log('Set predator result for testcase %d.' % testcase.key.id())

    logs.log('Finished processing predator results. %d total.' % len(messages))