I deployed a service on Cloud Run where authentication is needed:
gcloud run deploy my-service --project my-project --image eu.gcr.io/my-project/rest-of-path --platform managed --region europe-west4 --no-allow-unauthenticated
This seems to work fine. However, when I try to access my service from another service (in my case it is Anvil), it gives me a Response [403]
, which means it refused to authorize it. My Service Account does have the right roles as far as I know: Cloud Run Invoker, Service Account Token Creator, Service Controller. Even if I to add the owner role, it's not working.
This is my code to access my service:
API_URL="https://my-url.run.app/"
def create_signed_jwt(credentials_json, run_service_url):
iat = time.time()
exp = iat + 3600
payload = {
'iss': credentials_json['client_email'],
'sub': credentials_json['client_email'],
'target_audience': run_service_url,
'aud': 'https://www.googleapis.com/oauth2/v4/token',
'iat': iat,
'exp': exp
}
additional_headers = {
'kid': credentials_json['private_key_id']
}
signed_jwt = jwt.encode(
payload,
credentials_json['private_key'],
headers=additional_headers,
algorithm='RS256'
)
return signed_jwt
def exchange_jwt_for_token(signed_jwt):
body = {
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion': signed_jwt
}
token_request = requests.post(
url='https://www.googleapis.com/oauth2/v4/token',
headers={
'Content-Type': 'application/x-www-form-urlencoded'
},
data=urllib.parse.urlencode(body)
)
return token_request.json()['id_token']
def get_headers():
"""
Creates the headers for each request to the API on google cloud run
"""
credentials = {
"type": "service_account",
"project_id": "my-project-id",
"private_key_id": my-key-id,
"private_key": "-----BEGIN PRIVATE KEY----- very long token-----END PRIVATE KEY-----\n",
"client_email": "my-credential-name@my-project-id.iam.gserviceaccount.com",
"client_id": my-client-id,
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": some-standard-url,
"client_x509_cert_url": some-standard-url
}
token = exchange_jwt_for_token(create_signed_jwt(credentials, API_URL))
return {
"Authorization": f"Bearer {token}"
}
def test_request_function():
""" request example url"""
response = requests.get(f'{API_URL}/health', get_headers())
print(test_request_function())
Why is it not possible to authorize?