Пример #1
0
 def test_validate_root_service_bad(self):
     with self.assertRaises(ValueError):
         utils.validate_root_service_url('')
     with self.assertRaises(ValueError):
         utils.validate_root_service_url('blah://blah')
     with self.assertRaises(ValueError):
         utils.validate_root_service_url('https://')
     with self.assertRaises(ValueError):
         utils.validate_root_service_url('https://blah/')
     with self.assertRaises(ValueError):
         utils.validate_root_service_url('https://blah?asdad')
def _call_token_server(method, request, project_id=None):
    """Sends an RPC to tokenserver.minter.TokenMinter service.

  Args:
    method: name of the method to call.
    request: dict with request fields.
    project_id: if set, act with the authority of this LUCI project.

  Returns:
    Dict with response fields.

  Raises:
    PermissionError on HTTP 403 reply.
    MisconfigurationError if the service account is misconfigured.
    InternalError if the RPC fails unexpectedly.
  """
    # Double check token server URL looks sane ('https://....'). This is checked
    # when it's imported from the config. This check should never fail.
    ts_url = auth.get_request_auth_db().token_server_url
    try:
        utils.validate_root_service_url(ts_url)
    except ValueError as exc:
        raise MisconfigurationError('Invalid token server URL %s: %s' %
                                    (ts_url, exc))

    # See TokenMinter in
    # https://chromium.googlesource.com/infra/luci/luci-go/+/master/tokenserver/api/minter/v1/token_minter.proto
    # But beware that proto JSON serialization uses camelCase, not snake_case.
    try:
        return net.json_request(
            url='%s/prpc/tokenserver.minter.TokenMinter/%s' % (ts_url, method),
            method='POST',
            payload=request,
            project_id=project_id,
            scopes=[net.EMAIL_SCOPE])
    except net.Error as exc:
        logging.error('Error calling %s (HTTP %s: %s):\n%s', method,
                      exc.status_code, exc.message, exc.response)
        if exc.status_code == 403:
            raise PermissionError('HTTP 403 from the token server:\n%s' %
                                  exc.response)
        if exc.status_code == 400:
            raise MisconfigurationError('HTTP 400 from the token server:\n%s' %
                                        exc.response)
        # Don't put the response body into the error message, it may contain
        # internal details (that are public to Swarming server, but may not be
        # public to whoever is calling the Swarming server now).
        raise InternalError('Failed to call %s, see server logs' % method)
Пример #3
0
def _call_resultdb_recorder_api_async(method,
                                      request,
                                      headers=None,
                                      response_headers=None,
                                      scopes=(net.EMAIL_SCOPE, ),
                                      project_id=None):
    cfg = config.settings()
    rdb_url = cfg.resultdb.server
    assert rdb_url, 'ResultDB integration is not configured'
    utils.validate_root_service_url(rdb_url)

    # See Recoder API for ResultDB in
    # https://chromium.googlesource.com/infra/luci/luci-go/+/HEAD/resultdb/proto/rpc/v1/recorder.proto
    # But beware that proto JSON serialization uses camelCase, not snake_case.
    yield net.json_request_async(url='%s/prpc/luci.resultdb.v1.Recorder/%s' %
                                 (rdb_url, method),
                                 method='POST',
                                 payload=request,
                                 scopes=scopes,
                                 headers=headers,
                                 response_headers=response_headers,
                                 project_id=project_id)
Пример #4
0
def _call_token_server(method, request):
    """Sends an RPC to tokenserver.minter.TokenMinter service.

  Args:
    method: name of the method to call.
    request: dict with request fields.

  Returns:
    Dict with response fields.

  Raises:
    auth.AuthorizationError on HTTP 403 reply.
    InternalError if the RPC fails unexpectedly.
  """
    # Double check token server URL looks sane ('https://....'). This is checked
    # when it's imported from the config. This check should never fail.
    ts_url = auth.get_request_auth_db().token_server_url
    try:
        utils.validate_root_service_url(ts_url)
    except ValueError as exc:
        raise InternalError('Invalid token server URL %s: %s' % (ts_url, exc))

    # See TokenMinter in
    # https://chromium.googlesource.com/infra/luci/luci-go/+/master/tokenserver/api/minter/v1/token_minter.proto
    # But beware that proto JSON serialization uses camelCase, not snake_case.
    try:
        return net.json_request(
            url='%s/prpc/tokenserver.minter.TokenMinter/%s' % (ts_url, method),
            method='POST',
            payload=request,
            headers={'Accept': 'application/json; charset=utf-8'},
            scopes=[net.EMAIL_SCOPE])
    except net.Error as exc:
        logging.error('Error calling %s (HTTP %s: %s):\n%s', method,
                      exc.status_code, exc.message, exc.response)
        if exc.status_code == 403:
            raise auth.AuthorizationError(exc.response)
        raise InternalError(
            'Failed to call MintOAuthTokenGrant, see server logs')
Пример #5
0
    def post(self):
        if is_config_locked():
            self.abort_with_error(
                409, text='The configuration is managed elsewhere')

        body = self.parse_body()
        try:
            client_id = body['client_id']
            client_secret = body['client_not_so_secret']
            additional_client_ids = filter(bool, body['additional_client_ids'])
            token_server_url = body['token_server_url']
        except KeyError as exc:
            self.abort_with_error(400, text='Missing key %s' % exc)

        if token_server_url:
            try:
                utils.validate_root_service_url(token_server_url)
            except ValueError as exc:
                self.abort_with_error(400,
                                      text='Invalid token server URL - %s' %
                                      exc)

        @ndb.transactional
        def update():
            config = model.root_key().get()
            config.populate(oauth_client_id=client_id,
                            oauth_client_secret=client_secret,
                            oauth_additional_client_ids=additional_client_ids,
                            token_server_url=token_server_url)
            config.record_revision(modified_by=api.get_current_identity(),
                                   modified_ts=utils.utcnow(),
                                   comment='REST API')
            config.put()
            model.replicate_auth_db()

        update()
        self.send_response({'ok': True})
Пример #6
0
def _validate_oauth_config(conf):
    if not isinstance(conf, config_pb2.OAuthConfig):
        raise ValueError('Wrong message type')
    if conf.token_server_url:
        utils.validate_root_service_url(conf.token_server_url)
Пример #7
0
 def test_validate_root_service_url_gae(self):
     self.mock(utils, 'is_local_dev_server', lambda: False)
     utils.validate_root_service_url('https://blah')
     with self.assertRaises(ValueError):
         utils.validate_root_service_url('http://localhost:8080')
Пример #8
0
 def test_validate_root_service_url_dev_server(self):
     self.mock(utils, 'is_local_dev_server', lambda: True)
     utils.validate_root_service_url('https://blah')
     utils.validate_root_service_url('http://localhost:8080')