How to verify Google Cloud Run outbound IP and country
One of my projects was to make sure a Google Cloud Run Function has a specific static public ip address, since it needed to be whitelisted on some 3rd party location. This can be achieved with Direct VPC egress.
In order to test the outbound connectivity through the VPC (and possibly through a Cloud NAT solution), I created a small function, which will check the public ip address of the Cloud Function, also it shows the country (and possibly other details if needed). It's written in Python, and it calls out to checkip.amazonaws.com.
Once it gets the public ip address from where the function traffic came, it creates another request to http://ipinfo.io/{ip_address}/json with the public ip address it received in the previous request.
ipinfo.io will provide a JSON response with various details about the given public ip address, like country, city, ISP details. In my example, I only needed the country to verify traffic is truly originated from the right Google Cloud region.
I included various "print(number)" lines, which is useful to identify if the function fails or doesn't provide the expected output. These printed numbers can be checked in the Cloud Run logs.
It needs a requirements.txt with the necessary packages:
functions-framework==3.*
requests==2.*
Then the function (I called it main.py) looks like this:
import functions_framework
import requests
@functions_framework.http
def verify_location(request):
# URL to get the public IP address of the instance
ip_service_url = "http://checkip.amazonaws.com/"
print(1)
try:
# Get the public IP address
ip_response = requests.get(ip_service_url)
print(2)
if ip_response.status_code == 200:
print(3)
ip_address = ip_response.text.strip() # Get the IP address and remove any surrounding whitespace
print(4)
# Use ipinfo.io to get the location based on the IP address
geo_service_url = f"http://ipinfo.io/{ip_address}/json"
geo_response = requests.get(geo_service_url)
print(geo_response)
if geo_response.status_code == 200:
print(6)
geo_data = geo_response.json()
print(7)
country = geo_data.get("country")
city = geo_data.get("city")
publicip = geo_data.get("ip")
print(8)
return f'This function is executed from the country: {country} {city} {publicip}', 200
else:
print(9)
return 'Could not determine the geographical location.', 500
else:
print(10)
return 'Could not determine the IP address.', 500
except Exception as e:
return f'An error occurred: {str(e)}', 500
Make sure you add the function entrypoint: "verify_location"
So eventually if I test the function, it will respond back with the country, city and the source public IP address of the function.
curl https://test3-880271935964.us-central1.run.app/ #this is the cloud function URL
This function is executed from the country: US Mountain View 34.96.44.195