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!
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:
appengine.ServiceAccount(ctx).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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With