使用http 404,Compute Engine API调用失败

时间:2014-01-11 12:35:10

标签: google-app-engine google-api google-compute-engine

我需要在App Engine代码中对Google Compute Engine API调用提供一些帮助。以下是我用来获取计算引擎实例列表(简化版)的代码的一部分

try {
            final AppIdentityService appIdService = AppIdentityServiceFactory
                    .getAppIdentityService();
            AppIdentityService.GetAccessTokenResult result = appIdService
                    .getAccessTokenUncached(Collections
                            .singletonList(ComputeScopes.COMPUTE));
            String accessToken = result.getAccessToken();
            String url = "https://www.googleapis.com/compute/v1/projects/MYPROJECTID/zones/us-central1-b/instances";
            String payload = "";

            // Create HTTPRequest and set headers
            HTTPRequest httpRequest = new HTTPRequest(new URL(url.toString()),
                    HTTPMethod.GET, FetchOptions.Builder.doNotFollowRedirects());

            httpRequest.addHeader(new HTTPHeader("Authorization", "OAuth "
                    + accessToken));

            httpRequest.addHeader(new HTTPHeader("Host", "www.googleapis.com"));
            httpRequest.addHeader(new HTTPHeader("Content-Length", Integer
                    .toString(payload.length())));
            httpRequest.addHeader(new HTTPHeader("Content-Type",
                    "application/json"));
            httpRequest.addHeader(new HTTPHeader("User-Agent",
                    "google-api-java-client/1.0"));
            httpRequest.setPayload(payload.getBytes());

            URLFetchService fetcher = URLFetchServiceFactory
                    .getURLFetchService();
            HTTPResponse httpResponse = fetcher.fetch(httpRequest);

            int responseCode = httpResponse.getResponseCode();
            if ((responseCode == 200) || (responseCode == 204)) {
                String contentStr = new String(httpResponse.getContent());
                return extractIpsAndInstanceNames(contentStr, prefix);
            } else {
                logger.warning("Failed. Response code " + responseCode
                        + " Reason: " + new String(httpResponse.getContent()));
            }

如您所见,我正在使用AppIdentity获取访问令牌。然后在API调用中的请求标头中使用它。

基本上每次呼叫失败并出现以下错误

Failed. Response code 404 Reason: {
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "notFound",
    "message": "The resource 'projects/MYPROJECTID' was not found"
   }
  ],
  "code": 404,
  "message": "The resource 'projects/MYPROJECTID' was not found"
 }
}

有趣的是,如果我使用以下webapp https://developers.google.com/compute/docs/reference/latest/instances/list#try-it进行相同的API调用,则会成功。

因此,我查看了此Web应用程序发出请求和复制的承载令牌字符串时发送的数据,并将其用于"授权"头。奇怪的是,请求现在已经成功完成而不会改变任何其他内容基本上该应用程序使用用户同意Oauth2类型的令牌 - 所以对我来说,看起来通过AppIdentity获得的令牌存在一些问题。 有人能指出我正确的方向吗?谢谢!

3 个答案:

答案 0 :(得分:3)

我遇到了同样的问题并且能够解决它,或者我应该以一种对我来说没有任何意义的方式解决它。希望有关于这个主题的真正知识的人可以进一步解释。这个解决方案类似于E. Anderson的回答,但不同,因为App Engine和Compute Engine都在同一个项目中。

这就是我的所作所为:

  1. 在真实运行的应用引擎中(不是在本地开发者模式下)打印出服务帐户电子邮件。使用Go运行时,我使用了appengine.ServiceAccount(ctx)
  2. Google Developers Console中,转到项目的“权限”页面,并将您在上一步中获得的电子邮件地址添加为项目成员。
  3. 一旦我这样做,我就可以从App Engine向Compute Engine REST API发出请求。我不知道为什么这一步是必要的。

答案 1 :(得分:1)

您是否在与您尝试管理的GCE项目相同的项目中使用了appengine应用程序?如果没有,您需要将AppEngine应用程序中的服务帐户标识添加到GCE项目的项目团队中;查看云控制台上的“权限”选项卡,查看您的AppEngine应用程序是否可以访问GCE项目。

答案 2 :(得分:0)

在Doug answer上提供变体:

  1. 转到https://appengine.google.com,选择您的应用程序,然后转到管理> '应用程序设置'页面。您可以在此处找到您的服务帐户电子邮件地址如果您想明确添加电子邮件地址,请使用此选项,i。即如果您的计算引擎项目与您的应用引擎项目不同。如果是这种情况,请按照Doug的回答。

  2. 在应用程序设置页面的最底部,找到名为“云集成”的部分。进行整合 - 这将需要一分钟。

  3. 瞧,如果你去https://console.developers.google.com,选择你的项目,然后进入项目的权限页面(链接在左侧很远),你会发现你的应用引擎服务帐户现在显示在具有编辑权限的服务帐户列表中。 404应该得到解决。

  4. 如果您希望OAuth授权代码也可以在开发服务器上运行,则此答案可能有所帮助:https://stackoverflow.com/a/22723127