3

I have 2 Google Cloud Function 1 gen, R and C, on the same GCP project.

R is a private function with the "Allow internal traffic only" flag set to true. In the permission tab I give to the Service Account SA the invoker role.

C is a public function that has ALL the egress traffic redirected to a Serverless VCP Connector.

As expected, If I try to call R from the browser, I receive a 404 not found error.

In his code, C uses the SA json key (saved on the secret manager) to get an auth token and then make an HTTP request to R, setting the Authentication header with the Bearer token retrieved.

Here the R code:

def hello_world(request):
  return f'Hello World!'

Here the C code:

import requests
import functions_framework
import google.auth
import google.auth.transport.requests
from flask import Request
from typing import Tuple

from google.oauth2 import service_account
import os, json


def get_token() -> str:
    service_account_key = json.loads(os.getenv('SA'))
    credentials = service_account.Credentials.from_service_account_info(
        service_account_key,  
        scopes=['https://www.googleapis.com/auth/cloud-platform']  
    )
    auth_req = google.auth.transport.requests.Request()
    credentials.refresh(auth_req)
    return credentials.token


@functions_framework.http
def test(req: Request) -> Tuple[str, int]:
    url = "..."
    headers = {
        "Authentication": f"Bearer {get_token()}"
    }
    response = requests.get(url, headers=headers)
    return response.text, response.status_code

I expect that C can call R, but I receive a 403 Forbidden error.

The only way C can call R is making R public (I have tried it and it works).

This is the excepted behavior? I'm missing something?

Marco Mantovani
  • 111
  • 2
  • 7

1 Answers1

2

You must invoke the Cloud Functions with an Identity token and not an access Token. Here you use an access token.

In addition, do not use a service account key file, event stored in secret manager, it's totally useless and you increase your security risk.


Here a code sample to generate an identity token

import google.oauth2.id_token
import google.auth.transport.requests

request = google.auth.transport.requests.Request()
target_audience = "my_cloud_function_url"

id_token = google.oauth2.id_token.fetch_id_token(request, target_audience)
print(id_token)
guillaume blaquiere
  • 66,369
  • 2
  • 47
  • 76
  • Hi, thanks for the reply. I get the point about access and id token, but this code stil not work. Now it raises `google.auth.exceptions.GoogleAuthError: Provided Credential must be impersonated_credentials` – Marco Mantovani Jul 19 '23 at 08:31
  • 1
    My bad, it was a test for impersonation. Sorry, I updated the code. – guillaume blaquiere Jul 19 '23 at 12:26