无法从本地App Engine开发服务器访问BigQuery

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

tldr; 是否有可能让App Engine本地开发服务器使用远程BigQuery服务进行身份validation? 更好的是有一个本地的BigQuery?

我明白,AppAssertionCredentials目前不在本地开发服务器上工作,虽然这本身是非常令人沮丧的。

本地开发服务器沙箱以外的标准python代码的替代方法在本地开发服务器上不起作用,因为即使启用了PyCrypto,沙盒也不允许某些posix模块,例如“pwd”。

我已经获得了在远程服务器上工作的AppAssertionCredentials以及在本地Python中工作的SignedJwtAssertionCredentials方法,所以服务帐号被正确设置。

导入在try / except块内的oauth2client / crypt.py内失败 – 在注释掉沙盒白名单例外之后很容易看到。

我在白名单上添加“pwd”,然后又出现了另一个问题,于是我急忙跑出那个兔子洞。

我试过将PyCrypto直接包含到项目中,结果类似。

我也尝试过与OpenSSL类似的结果。

我找了一个本地的特定于引擎的PyCrypto无济于事,我错过了一个? 我应该说这是在Mac OSX上 – 也许我应该启动一个Linux的盒子,并给一个去吗?

最近发布的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中 ,select一个项目,然后导航到“API&auth” – >“Credentials” – >“Create new client ID”。

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

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

  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不在应用程序源目录中, /path/to/secret.pem意外部署到您的应用程序中。

所以更深入的PyCrypto和本地appengine沙箱引导我到这个线程和具体的答复…

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

这在1.7.4中被固定。 但是,您必须使用easy_install -Z(–always-unzip)来安装PyCrypto。 OSX 10.8中的默认zipfile选项与dev_appserver中的沙箱模拟不兼容。

解决scheme变得非常简单

我用了:

 sudo easy_install pycrypto 

而且应该是:

 sudo easy_install -Z pycrypto 

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

 pip install pycrypto 

或手动下载并安装pycrypto也将工作。 我testing了这三个。

如果你已经安装了easy-install并没有-Z标志的pycrypto,那么你可能想安装pip,这样你就可以轻松地卸载pycrypto …

 easy_install pip 

为logging我build立和安装libgmp,因为弼和手动安装显示此警告…

警告:未findGMP或MPIR库; 不构buildCrypto.PublicKey._fastmath。

虽然这给了我很快的速度,但解决问题并不是必须的,因为Crypto库优雅地不会慢下来。

另一个让我绊倒的观点是我从app.yaml中删除了pycrypto,同时testing了OpenSSL是否可以给我所有我需要的东西。

所以不要忘记添加…

 - name: pycrypto version: latest 

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

由于缺less原生_counter库没有导入,因此计数器失败等

另外,对于必须将Crypto移动到应用程序文件夹本身或不在/Library/Python/2.7/site-packages/Crypto的默认Mac OS X位置的任何谈话,只有在早期版本的dev服务器中才有效。

同样,现在不需要编辑任何_WHITE_LIST_C_MODULES列表(这是在appengine 1.8以上的sandbox.py中,也包括允许Crypto.Util._counter等的正则expression式)

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

我在这一天挣扎了一两天。 我终于能够得到本地主机与服务器到服务器身份validation,服务帐户和.p12证书。

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

我同意第一个post – 本地主机/生产阻抗是a **中真正的痛苦。 AppAssertionCredentials是继续生产的正确方法,我不想在生产和本地主机之间有两个不同的代码path。 所以需要对开发环境进行调整,以便能够在不影响主代码path的情况下执行所需的authentication。

例如,也许开发人员可以使用appcfg.py使用自己的Google帐户login,然后该authentication将被caching一段时间,以便AppAssertionCredentials可以运行。 开发人员的Google帐户可以被授予相应环境的权限(例如,开发人员和testing人员)

回答:“本地BigQuery” – 我们有一些最初的东西,它们使用SQLLite来模拟unit testing和其他离线/本地testing的BigQuery交互,当然,这不是一个很好的模拟。 我同意,所有的云平台产品都需要花费大量的时间来思考App Engine所具有的开发时间体验。

是否有可能让App Engine本地开发服务器使用远程BigQuery服务进行身份validation?

我认为当前在BigQuery服务和本地App Engine服务器之间使用AppAssertionCredentials作为身份validation方法是不可能的。

或者,我正在使用与特定用户相关联的OAuth2身份validation(此用户必须在您的项目中在Google API api控制台中注册 )才能从本地App Engine服务器访问BigQuery。

为了获得用户OAuth2身份validation,我使用应用程序代码中的oauth2client.client模块。

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

更新:

这是我正在做的获得用户OAuth2授权。

编辑:

新增缺less的导入语句。 谢谢你们!

 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)