Google Cloud Function returning a 403 response

craig
New Member

Hi All,

I am new to Apigee so just finding my feet with the product, my use case is that I have a Google Cloud function which is to be locked down to only a Google service account.

The extension seems to be working fine and the POST request reaches the function to return a 200 response. However the actual response from Google is a 403.

Steps and code

GCP Functions Extension

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ConnectorCallout async="false" continueOnError="true" enabled="true" name="Synaptek">
    <DisplayName>Agigee</DisplayName>
    <Connector>cloud-functions</Connector>
    <Action>invoke</Action>
    <Input><![CDATA[
        {
         "region": "europe-west2",
         "projectId": "agipee",
         "functionName": "helloApigee",
         "method": "POST",
         "payload": {request.content}
        }
     ]]></Input>
    <Output>function.response</Output>
</ConnectorCallout> 

In the trace I can see that I get a response of 200 and the output from GCP and the logs in the function suggest it has ran successfully.

10176-screenshot-2020-07-31-at-085438.png

As the request continues I get the below:

10177-screenshot-2020-07-31-at-085703.png

I have tried increasing the permissions on the service account, added CORS to the request but nothing seems work, there are no errors in the extension logs. Any help would be greatly appreciated.

Solved Solved
0 2 1,787
1 ACCEPTED SOLUTION

I think I know what's going on, but first some background.

The Apigee gateway acts primarily as a proxy. A caller sends a request in, Apigee copies that request maybe does "something" to it, then Apigee invokes a target system with the possibly modified copy of the inbound request, receives the response. Apigee then maybe does "something else" with that response, and then finally sends the possibly modified response to the original caller.

The "something" and "something else" can be ... check a credential, enforce a rate limit, transform the message body, add or remove a header or query param, modify the path... and so on. These actions all directly affect the request or response message.

Call the inbound request message "Req". It is static, constant. It does not change.

The copied request message might be "Req(p)". It may change through the course of the Apigee proxy execution, for example if you use an AssignMessage policy to add or remove a header to the request. The final version of the Req(p) is the thing that gets sent to the target.

The received response message from the "target" might be "Resp", and the copy of that Response might be "Resp(p)" (p is for "proxy"). That Resp(p) might also change, in the same way Req(p) might undergo changes. The response that eventually reaches the original caller is the final version of Resp(p), after all modifications.

In the course of handling a request, Apigee can also do things that _don't_ modify the request or response messages (Req(p) or Resp(p)). . One of those things is a ConnectorCallout, which allows Apigee to connect to a remote GCP Service - for example, a cloud function. The invocation of the cloud function does not affect Req(p) or Resp(p). If there is something sent to the cloud function (or any other thing that ConnectorCallout can reach), there is a different, secondary pair of messages (a request and a response) to carry the information back and forth. So, no direct affect on the request or response message that Apigee is currently processing, and no affect on the primary "target" of the Apigee proxy. A common reason for using the ConnectorCallout and other similar mechanisms like the ServiceCallout is to use the result of the callout to then modify or augment the Req(p) or Resp(p). Or maybe the result of the callout might be used to decide how to direct the request message (maybe to a dynamically determined target), or how to modify a message.

From what you've told me, it sounds to me that

- you are using the connector to invoke the Cloud Function. Probably within the Request processing. (IE, before Apigee attempts to invoke a target)

- that works, you see a 200 OK response.

- Apigee continues processing and invokes a target. We don't know what that is, you haven't told us.

- that target responds with a 403 Forbidden

Maybe you are not intending to invoke a target? Maybe the Cloud Function is the intended "target"? It wouldn't REALLY be a target for Apigee; what I'm suggesting is maybe it is your intention that the Cloud function is the primary thing you want Apigee to invoke. You can't directly specify a Google Cloud Function as a "target" for an Apigee proxy, not today.

The model I described above, in which Apigee acts as a proxy for a target, is the general case. It is possible to create "no target" API proxies in Apigee, so... for example you could configure the Apigee proxy to invoke the ConnectorCallout, then ... just not invoke any target at all. You could then configure the Apigee proxy to use AssignMessage to then copy the result of the connector callout to the Resp(p). and then send that back to the client.

You can read more about "no target" proxies here and see an example here.

Or google for it.

View solution in original post

2 REPLIES 2

I think I know what's going on, but first some background.

The Apigee gateway acts primarily as a proxy. A caller sends a request in, Apigee copies that request maybe does "something" to it, then Apigee invokes a target system with the possibly modified copy of the inbound request, receives the response. Apigee then maybe does "something else" with that response, and then finally sends the possibly modified response to the original caller.

The "something" and "something else" can be ... check a credential, enforce a rate limit, transform the message body, add or remove a header or query param, modify the path... and so on. These actions all directly affect the request or response message.

Call the inbound request message "Req". It is static, constant. It does not change.

The copied request message might be "Req(p)". It may change through the course of the Apigee proxy execution, for example if you use an AssignMessage policy to add or remove a header to the request. The final version of the Req(p) is the thing that gets sent to the target.

The received response message from the "target" might be "Resp", and the copy of that Response might be "Resp(p)" (p is for "proxy"). That Resp(p) might also change, in the same way Req(p) might undergo changes. The response that eventually reaches the original caller is the final version of Resp(p), after all modifications.

In the course of handling a request, Apigee can also do things that _don't_ modify the request or response messages (Req(p) or Resp(p)). . One of those things is a ConnectorCallout, which allows Apigee to connect to a remote GCP Service - for example, a cloud function. The invocation of the cloud function does not affect Req(p) or Resp(p). If there is something sent to the cloud function (or any other thing that ConnectorCallout can reach), there is a different, secondary pair of messages (a request and a response) to carry the information back and forth. So, no direct affect on the request or response message that Apigee is currently processing, and no affect on the primary "target" of the Apigee proxy. A common reason for using the ConnectorCallout and other similar mechanisms like the ServiceCallout is to use the result of the callout to then modify or augment the Req(p) or Resp(p). Or maybe the result of the callout might be used to decide how to direct the request message (maybe to a dynamically determined target), or how to modify a message.

From what you've told me, it sounds to me that

- you are using the connector to invoke the Cloud Function. Probably within the Request processing. (IE, before Apigee attempts to invoke a target)

- that works, you see a 200 OK response.

- Apigee continues processing and invokes a target. We don't know what that is, you haven't told us.

- that target responds with a 403 Forbidden

Maybe you are not intending to invoke a target? Maybe the Cloud Function is the intended "target"? It wouldn't REALLY be a target for Apigee; what I'm suggesting is maybe it is your intention that the Cloud function is the primary thing you want Apigee to invoke. You can't directly specify a Google Cloud Function as a "target" for an Apigee proxy, not today.

The model I described above, in which Apigee acts as a proxy for a target, is the general case. It is possible to create "no target" API proxies in Apigee, so... for example you could configure the Apigee proxy to invoke the ConnectorCallout, then ... just not invoke any target at all. You could then configure the Apigee proxy to use AssignMessage to then copy the result of the connector callout to the Resp(p). and then send that back to the client.

You can read more about "no target" proxies here and see an example here.

Or google for it.

Thank you so much for the detailed response, in this case the cloud function is the target so your suggestion to create a "no-target" proxy resolved my query.