Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call Cloud Run from Cloud Function: IAM Authentication

I've deployed a small HTTP endpoint via Google Cloud Run. It is working fine when I turn off the authentication.

I now want to turn it on so that it is only callable by my Firebase Cloud Function. If I understand it right, I just have to add the correct service account mail address in the IAM settings of the Cloud Run as "Cloud Run invoker". But which address is the correct one?

I've tried all addresses that I have found in Firebase Console -> Project Settings -> Service Accounts.

like image 577
luhu Avatar asked Jul 10 '20 21:07

luhu


2 Answers

I think you can check the specific firebase function. In the UI, the service account used should be listed.

By default, GCF functions all use <project_id>@appspot.gserviceaccount.com

like image 196
wlhee Avatar answered Oct 13 '22 19:10

wlhee


Thanks to @AhmetB - Google and @whlee's answer I got it working. Basically it is enough adding an Authorization Bearer token to the request, which you can get from a special endpoint: https://cloud.google.com/run/docs/authenticating/service-to-service#nodejs

Then you just have to add the service account of the function to the IAM list of the Cloud Run container: <project_id>@appspot.gserviceaccount.com

The nodejs example is using the deprecated request library, so here is my version using axios:

    const getOAuthToken = async (receivingServiceURL: string): Promise<string> => {

      // Set up metadata server request
      const metadataServerTokenURL = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=';
      const uri = metadataServerTokenURL + receivingServiceURL;
      const options = {
        headers: {
          'Metadata-Flavor': 'Google'
        }
      };

      return axios.get(uri, options)
        .then((res) => res.data)
        .catch((error) => Promise.reject(error));
    }

Then you can just use the token in the actual request:

    const url = `...`;
    const token = await getOAuthToken(url);

    axios.post(url, formData, {
        headers: {
            Authorization: `Bearer ${token}`,
        }
    }).then(...).catch(...);
like image 2
luhu Avatar answered Oct 13 '22 20:10

luhu