【问题标题】:Unable to access BigQuery from local App Engine development server无法从本地 App Engine 开发服务器访问 BigQuery
【发布时间】:2013-12-19 09:27:52
【问题描述】:

这是一个与 Python Google AppEngine 应用和 Google 的 BigQuery 之间的服务器到服务器授权有关的问题,但可能与其他云服务相关。

tldr;是否可以让 App Engine 本地开发服务器向远程 BigQuery 服务进行身份验证?更好的是有本地 BigQuery 吗?

我了解 AppAssertionCredentials 目前无法在本地开发服务器上运行,尽管这本身就非常令人沮丧。

适用于本地开发服务器沙箱之外的标准 python 代码的替代方法,详细 here 不适用于本地开发服务器,因为即使启用了 PyCrypto,沙箱也不允许某些 posix 模块,例如'密码'。

我有 AppAssertionCredentials 在远程服务器上工作,而 SignedJwtAssertionCredentials 方法在本地 Python 中工作,因此服务帐户设置正确。

在 try/except 块内的 oauth2client/crypt.py 中导入失败 - 将它们注释掉后,沙箱白名单异常很容易看到。

我一直在尝试将“pwd”添加到白名单中,然后又出现了另一个问题,所以我急忙从那个兔子洞里跑了出来。

我尝试将 PyCrypto 直接包含在项目中,结果相似。

我也尝试过使用 OpenSSL,结果相似。

我一直在寻找本地 appengine 特定的 PyCrypto 无济于事,我错过了吗?我应该说这是在 Mac OSX 上 - 也许我应该启动一个 linux 机器并试一试?

【问题讨论】:

    标签: google-app-engine google-oauth google-bigquery google-api-python-client


    【解决方案1】:

    最近发布的 Google App Engine SDK 添加了对开发服务器上 AppAssertionCredentials 方法的支持。要在本地使用此方法,请将以下参数添加到 dev_appserver.py

    $ dev_appserver.py --help
    ...
    Application Identity:
      --appidentity_email_address APPIDENTITY_EMAIL_ADDRESS
                            email address associated with a service account that
                            has a downloadable key. May be None for no local
                            application identity. (default: None)
      --appidentity_private_key_path APPIDENTITY_PRIVATE_KEY_PATH
                            path to private key file associated with service
                            account (.pem format). Must be set if
                            appidentity_email_address is set. (default: None)
    

    要使用这些:

    1. Google Developer Console 中,选择一个项目,然后导航到“API & auth” -> “Credentials” -> “Create new client ID”。

    2. 选择“服务帐号”并按照提示下载PKCS12(.p12)格式的私钥。记下服务帐户的电子邮件地址。

    3. 确保将该服务帐户电子邮件地址添加到包含需要访问的数据的任何项目的“权限”选项卡中,默认情况下,它会添加到创建它的项目团队中。

    4. 使用以下命令将 PKCS12 格式转换为 PKCS1 格式:

      $ cat /path/to/xxxx-privatekey.p12 | openssl pkcs12 -nodes -nocerts -passin pass:notasecret | openssl rsa > /path/to/secret.pem

    5. dev_appserver.py 开头:

      $ dev_appserver.py --appidentity_email_address xxxx@developer.gserviceaccount.com --appidentity_private_key_path /path/to/secret.pem ...

    6. 在本地使用 appidentity 模块和 AppAssertionCredentials 的方式与通常在生产环境中使用的方式相同。

    请确保/path/to/secret.pem 位于您的应用程序源目录之外,以免意外将其部署为您的应用程序的一部分。

    【讨论】:

    • 非常酷。但是现在我的集成测试......我仍然不能使用 AppAssertionCredentials 方法,对吗?看到没有其他方法可以实现两种授权策略。
    • Java SDK 是否有类似的功能?
    • 第 4 步转换密钥至关重要。我尝试了许多其他方法来转换它,这些方法在其他地方提到过,但是通过管道将它传递到 openssl rsa 是唯一有效的方法。谢谢!
    【解决方案2】:

    因此,更深入地搜索 PyCrypto 和本地 appengine 沙箱将我引至此线程并专门响应...

    https://code.google.com/p/googleappengine/issues/detail?id=1627#c22

    这在 1.7.4 中已修复。但是,您必须使用 easy_install -Z (--always-unzip) 安装 PyCrypto。中的默认 zipfile 选项 OSX 10.8 与沙盒仿真不兼容 dev_appserver。

    结果证明解决方案非常简单......

    我用过:

    sudo easy_install pycrypto
    

    它应该是:

    sudo easy_install -Z pycrypto
    

    根据上面的线程。使用 PIP 也可以:

    pip install pycrypto 
    

    或者手动下载和安装 pycrypto 也可以。我测试了所有三个。

    如果您使用 easy_install 安装了 pycrypto,但没有 -Z 标志,那么您可能需要安装 pip,以便轻松卸载 pycrypto...

    easy_install pip
    

    作为记录,我构建并安装了 libgmp,因为 pil 和手动安装显示了此警告...

    警告:未找到 GMP 或 MPIR 库;不建 Crypto.PublicKey._fastmath。

    虽然这给了我快速数学,但解决问题并不是必须的,因为 Crypto 库优雅地失败了。

    另一个让我有点不解的地方是我从 app.yaml 中删除了 pycrypto,同时测试 OpenSSL 是否可以满足我的所有需求。

    所以不要忘记添加...

    - name: pycrypto
      version: latest
    

    进入 libraries: 部分下的 app.yaml。

    由于缺少此功能,未导入本机 _counter 库,因此 Counter 失败等。

    此外,任何关于必须将 Crypto 移动到应用程序文件夹本身或从 /Library/Python/2.7/site-packages/Crypto 的默认 Mac OS X 位置移出的讨论仅在早期版本的开发中有效服务器。

    同样,现在无需编辑任何 _WHITE_LIST_C_MODULES 列表(在 appengine 1.8 及更高版本的 sandbox.py 中,其中还包括允许 Crypto.Util._counter 等的正则表达式)

    如果您在发现关键问题之前到达这里,另一个难题是您从控制台下载的密钥文件是 PKCS12 并以十六进制文本下载,因此我将其转换为二进制,然后将其转换为PEM,所以我可以将它包含在源代码中。

    【讨论】:

    【解决方案3】:

    我为此苦苦挣扎了一两天。我终于能够让 localhost 与服务器到服务器身份验证、服务帐户和 .p12 证书一起使用。

    如果它对任何人都有帮助,这里有一个简单的要点:https://gist.github.com/dandelauro/7836962

    【讨论】:

    • 你有什么要问的吗?
    • @dandelauro - 我第一次使用原生 python 代码,我的问题和这个线程,根据标题是专门关于“App Engine 本地开发服务器”的,这对我来说几乎是有效的
    • @danmux ok... localhost 是应用引擎本地开发服务器。不?无论哪种方式,这对我来说都可以完美地作为 django 的基础模型。我努力寻找解决方案,所以我只是想提供帮助。祝你好运。
    • @dandelauro 不,本地开发服务器可以并且通常确实在本地主机上运行,​​但在“沙盒”脚本中,这限制了某些 api 的可用性以模拟实时应用程序引擎环境。您的要点与谷歌代码developers.google.com/bigquery/docs/… 几乎相同,在沙箱中不起作用。
    【解决方案4】:

    我同意第一篇文章 - 本地主机/生产阻抗是 a** 的真正痛苦。 AppAssertionCredentials 是进行生产的正确方法,我不想在生产和本地主机之间有两个不同的代码路径。因此需要调整开发环境,使其能够在不影响主代码路径的情况下执行所需的身份验证。

    例如,也许开发人员可以使用 appcfg.py 使用自己的 Google 帐户登录,然后该身份验证将被缓存一段时间,以便 AppAssertionCredentials 可以正常工作。开发者的 Google 帐户可以被授予适当环境的权限(例如为我们开发和测试)

    re:“本地 BigQuery”——我们有一些初始的东西,它们使用 SQLLite 来模拟 BigQuery 交互以进行单元测试和其他离线/本地测试,但当然,这不是一个很好的模拟。我同意所有 Cloud Platform 产品都需要像 App Engine 一样花费尽可能多的时间来考虑开发时体验。

    【讨论】:

    • 非常正确,甚至认为我最终确实让 SignedJwtAssertionCredentials 方法在开发服务器中工作,你是对的,我现在有代码检测它是否在 snadbox 中或没有在两者之间切换:(
    【解决方案5】:

    是否可以让 App Engine 本地开发服务器通过远程 BigQuery 服务进行身份验证?

    我认为目前无法在 BigQuery 服务和本地 App Engine 服务器之间使用 AppAssertionCredentials 作为身份验证方法。

    或者,我正在使用与特定用户关联的 OAuth2 身份验证(此用户必须在您的项目中注册,地址为 google api console)从本地 App Engine 服务器访问 BigQuery。

    为了获得用户 OAuth2 身份验证,我在应用代码中使用了oauth2client.client 模块。

    我希望这对您的问题有所帮助。

    更新:

    这就是我为获得用户 OAuth2 授权所做的工作。

    已编辑:

    添加了缺少的导入语句。 感谢遮罩!

    import os
    import webapp2
    import httplib2
    from oauth2client.client import OAuth2Credentials
    from oauth2client.appengine import StorageByKeyName, CredentialsModel, OAuth2DecoratorFromClientSecrets
    from google.appengine.api import users
    
    oauth2_decorator = OAuth2DecoratorFromClientSecrets(
        os.path.join(os.path.dirname(__file__), 'client_secrets.json'),
        scope='https://www.googleapis.com/auth/bigquery')
    oauth2_decorator._kwargs = {'approval_prompt': 'force'}
    
    
    class TestPage(webapp2.RequestHandler):
      @oauth2_decorator.oauth_required
      def get(self):
        user_id = users.get_current_user().user_id()
        credentials = StorageByKeyName(CredentialsModel, user_id, 'credentials').locked_get()
        http = credentials.authorize(httplib2.Http()) # now you can use this http object to access BigQuery service
    
    
    application = webapp2.WSGIApplication([
      ('/', TestPage),
      (oauth2_decorator.callback_path, oauth2_decorator.callback_handler()),
    ], debug=True)
    

    【讨论】:

    • 谢谢@addisict,但它的 oauth2client.client 模块对我来说失败了,你能告诉我你正在使用什么操作系统和 appengine 的版本
    • 我的环境:本地应用引擎服务器(版本 1.8.0)在 Mac OS X 10.8.5 上运行。
    • 另外,我添加了获取授权http对象的示例代码。请检查一下。
    • 再次感谢 @addsict 上面的示例代码似乎是需要重定向的 Web 服务器示例,但是我特别询问服务器到服务器身份验证,(使用本地证书,例如可能使用 SignedJwtAssertionCredentials跨度>
    • 我明白了...好的,我会调查 SignedJWTAssertionCredentials 是否适用于本地应用引擎服务器和 BigQuery 服务身份验证。
    猜你喜欢
    • 2016-12-18
    • 2011-11-10
    • 2017-10-19
    • 2017-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    相关资源
    最近更新 更多