Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compute Engine API call fails with http 404

I need a bit of help with Google Compute Engine API call from within App Engine code. Following is part of code that I use to get a list of compute engine instances (simplified version)

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()));
            }

As you can see I am using AppIdentity to obtain access token. Then use it in request header in API call.

Basically every time the call fails with following error

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"
 }
}

What is interesting is that if I use following webapp https://developers.google.com/compute/docs/reference/latest/instances/list#try-it to make the same API call it succeeds.

So I looked into what data are sent when this web app makes request and copied bearer token string and used it in "Authorization" header. Strangely enough request now finished successfully without changing anything else. Basically that app uses user consent Oauth2 type of token - so for me it looks like there is some problem with token obtained via AppIdentity. Could someone point me in right direction? Thanks!

like image 886
Petr Chudanic Avatar asked Mar 21 '26 17:03

Petr Chudanic


1 Answers

I ran into the same issue and was able to solve it, or perhaps I should say workaround it, in a way that doesn't make complete sense to me. Hopefully someone with real knowledge on the subject can explain further. This solution is similar to what E. Anderson answered, but different because both App Engine and Compute Engine were in the same project.

Here's what I did:

  1. In app engine running for real (not in the local developer mode) print out the service account email. Using the Go runtime, I used appengine.ServiceAccount(ctx).
  2. In Google Developers Console, go to the Permissions page for your project and add the e-mail address you obtained in the previous step as a member of your project.

Once I did this, I was able to make requests to Compute Engine REST APIs from App Engine. I have no idea why this step was necessary.

like image 108
Doug Richardson Avatar answered Mar 24 '26 17:03

Doug Richardson