Cloud Resume Challenge – Visitor Counter Part 3, API Gateway

So, I’ve built a functioning API with Cloud Run and Datastore. Technically speaking, I now have a URL that my frontend JavaScript code could use to query and update the visitor count but there are a few reasons not to do this. It’s better to expose an API via a dedicated platform that centralises authentication, access control, monitoring, and versioning of your API, as well as creating a defined separation between your frontend and backend. This platform is API Gateway.

API Gateway uses the Open API Specification to define and expose the available services of an API, the http methods by which they can be accessed, and any security requirements (such as key authentication.)

Following the Open API Spec, the first step is to create a config file using the YAML markup format, which has some basic descriptive info, and then defines the primary address of the backend, the available resources, the paths & method to access them, and the type of data that will be returned:

The next step is to create the service account that the gateway will use to authenticate itself with my Cloud Run backend service. In GCP, service accounts are non-human “users” that authenticate GCP resources to access data from other GCP resources. It’s best practice to grant these accounts the minimum access they need to perform the task they’re intended for. In this case, I need to create an account with the “run invoker” role. It’s simple to do this directly in the cli like so:

$ gcloud iam service-accounts create gateway-run-invoker \
--description="Service account for API Gateway to invoke Cloud Run service" \
--display-name="Gateway Run Invoker"

I can then grant it the “run invoker” role:

$ gcloud projects add-iam-policy-binding visitor-counter \
--member="serviceAccount:gateway-run-invoker@visitor-counter.iam.gserviceaccount.com" \
--role="roles/run.invoker"

The API can then be created at the same time as I create the config by uploading the YAML file:

$ gcloud api-gateway api-configs describe visitor-counter-config \
--api=visitor-counter-api --project=visitor-counter

And, finally, I can deploy my API on API Gateway, like so:

$ gcloud api-gateway api-configs describe visitor-counter-config \
--api=visitor-counter-api --project=visitor-counter

This will create the “hostname” portion of a URL to which I then just need to append the correct path, in order to receive the expected response from our API call:

Great! At this stage, I’m pretty much ready go but there is one thing I want to do first. As the URL is going to be exposed in my frontend code, I want to lock down access to the API as much as possible. There’s obviously limited chance that anyone’s going to want to mess with my resume’s hit counter API but I’ll err on the side of caution!

So heading over to the API Library, I first need to find my new API and click “Enable”. Then I can go to the Credentials area to create the key. I’m choosing to lock the key down so that only calls from my own domain can successfully use it, and I’ve ensured that the key can only call my Visitor Counter API. The key is then issued on the same page. I then need to modify my API config YAML to specify that the key must be passed as a parameter in the request URL:

I then need to create this as a new config in API Gateway as before, and edit my own gateway to use this new file. Now if I attempt to make a request to the API without the key, I get an authentication error but with the key passed as a param in the URL the call executes successfully.

OK, so I now have a published, secure, working, RESTful API. Next I’ll work on the JavaScript required to display this on my resume site…