Case Study Bloom Credit: Multi-Provider API Security with KrakenD

Document updated on May 10, 2023

Google Cloud service-to-service authentication

Google Cloud service-to-service authentication

KrakenD supports the three different service-to-service authentication mechanisms Google Cloud provides: Service Accounts (this page), OAuth 2.0, and Mutual TLS Authentication.

A service account is a special type of Google account that belongs to an application or a virtual machine. Service accounts are used to authenticate requests to Google Cloud APIs and services or when connecting to your Google Cloud Run services if you added an option “Require Authentication”.

When KrakenD requests a Google Cloud resource, Google Cloud checks the IAM policy associated with the resource to determine whether it has the necessary permissions to access the resource. If KrakenD is authenticated and authorized to access the resource, the request is allowed, and the resource is accessed. If KrakenD is not authenticated or authorized, the request is denied, and an error message is returned.

GCP configuration

The auth/gcp component automatically retrieves a token from Google to perform the authorization against the service behind KrakenD, using the specified audience. The configuration is straightforward, and almost all the work is on Google Cloud’s side.

By default, the credentials are taken from the environment variableGOOGLE_APPLICATION_CREDENTIALS, which Cloud Run passes automatically.

You can pass another value for the environment var if necessary. GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/application_default_credentials.json".

You can also define the credentials by passing a JSON file, whether as path (credentials_file) or copy/pasted inside the configuration (credentials_json). This option is more relevant when KrakenD is outside of Google.

Fields of GCP Authentication
* required fields

Minimum configuration needs any of: audience , or audience + credentials_file , or audience + credentials_json

audience string
The audience in GCP looks like an URL, and contains the destination service you will ask a token for. Most of the times this URL will match exactly with the host entry.
Example: "https://gcptest-76fewi6rca-uc.a.run.app"
credentials_file string
The relative or absolute path to a credentials file in JSON format that contains all the credentials to authenticate API calls to the given service account.
Example: "/etc/krakend/gcp.json"
credentials_json object
An inline JSON object containing all the credentials fields to authenticate to GCP.
Example: {"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","auth_uri":"https://accounts.google.com/o/oauth2/auth","client_email":"[email protected]","client_id":"123","client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/xyz%40developer.gserviceaccount.com","private_key":"-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzd9ZdbPLAR4/g\nj+Rodu15kEasMpxf/Mz+gKRb2fmgR2Y18Y/iRBYZ4SkmF2pBSfzvwE/aTCzSPBGl\njHhPzohXnSN029eWoItmxVONlqCbR29pD07aLzv08LGeIGdHIEdhVjhvRwTkYZIF\ndXmlHNDRUU/EbJN9D+3ahw22BNnC4PaDgfIWTs3xIlTCSf2rL39I4DSNLTS/LzxK\n/XrQfBMtfwMWwyQaemXbc7gRgzOy8L56wa1W1zyXx99th97j1bLnoAXBGplhB4Co\n25ohyDAuhxRm+XGMEaO0Mzo7u97kvhj48a569RH1QRhOf7EBf60jO4h5eOmfi5P5\nPV3l7041AgMBAAECggEAEZ0RTNoEeRqM5F067YW+iM/AH+ZXspP9Cn1VpC4gcbqQ\nLXsnw+0qvh97CmIB66Z3TJBzRdl0DK4YjUbcB/kdKHwjnrR01DOtesijCqJd4N+B\n762w73jzSXbV9872U+S3HLZ5k3JE6KUqz55X8fyCAgkY6w4862lEzs2yasrPFHEV\nRoQp3PM0Miif8R3hGDhOWcHxcobullthG6JHAQFfc1ctwEjZI4TK0iWqlzfWGyKN\nT9UgvjUDud5cGvS9el0AiLN6keAf77tcPn1zetUVhxN1KN4bVAm1Q+6O8esl63Rj\n7JXpHzxaRnit9S6/aH/twHsGGtLg5Puw6jey6xs4AQKBgQD2JNy1wzewCRkD+jug\n8CHbJ+LIJVRNIaWa/RK1QD8/UjmFPkIzRQSF3AKC5mRAWSa2FL3yVK3N/DD7hazW\n85XSBB7IDcnoJnA9SkUeWwqQGkDx3EntlU3gX8Kn/+ofF8O9jLXxAa901MAVXVuf\n5YDzrl4PNE3bFnPCdiNmSdRfhQKBgQC6p4DsCpwqbeTu9f5ak9VW/fQP47Fgt+Mf\nwGjBnKP5PbbNJpHCfamF7jqSRH83Xy0KNssH7jD/NZ2oT594sMmiQPUC5ni9VYY6\nsuYB0JbD5Mq+EjKIVhYtxaQJ76LzHreEI+G4z6k3H7/hRpr3/C48n9G/uVkT9DbJ\noplxxEx68QKBgQCdJ23vcwO0Firtmi/GEmtbVHz70rGfSXNFoHz4UlvPXv0wsE5u\nE4vOt2i3EMhDOWh46odYGG6bzH+tp2xyFTW70Dui+QLHgPs6dpfoyLHWzZxXj5F3\n6lK9hgZvYvqk/XRRKmzjwnK2wjsdqOyeC1covlR5mqh20D/6kZkKbur0TQKBgAwy\nCZBimRWEnKKoW/gbFKNccGfhXqONID/g2Hdd/rC4QYth68AjacIgcJ9B7nX1uAGk\n1tsryvPB0w0+NpMyKdp6GAgaeuUUA3MuYSzZLiCagEyu77JMvaI7+Z3UlHcCGMd/\neK4Uk1/QqT7U2Cc/yN2ZK6E1QQa2vCWshA4U31JhAoGAbtbSSSsul1c+PsJ13Cfk\n6qVnqYzPqt23QTyOZmGAvUHH/M4xRiQpOE0cDF4t/r5PwenAQPQzTvMmWRzj6uAY\n3eaU0eAK7ZfoweCoOIAPnpFbbRLrXfoY46H7MYh7euWGXOKEpxz5yzuEkd9ByNUE\n86vSEidqbMIiXVgEgnu/k08=\n-----END PRIVATE KEY-----\n","private_key_id":"private_key_id","project_id":"project_id","token_uri":"https://accounts.google.com/o/oauth2/token","type":"service_account"}
custom_claims object
Custom private claims that you can optionally add to an ID token.

Example of configuration

{
    "$schema": "https://www.krakend.io/schema/v2.7/krakend.json",
    "version": 3,
    "endpoints": [
        {
            "endpoint": "/gcp",
            "output_encoding": "no-op",
            "backend": [
                {
                    "host": [ "https://hello-76fewi6rca-uc.a.run.app" ],
                    "url_pattern": "/someurl",
                    "encoding": "no-op",
                    "extra_config": {
                        "auth/gcp": {
                            "audience": "https://hello-76fewi6rca-uc.a.run.app"
                        }
                    }
                }
            ]
        }
    ]
}

Additional resources

The following resources at Google will help you during your implementation.

Port limitations on Cloud Run

When running KrakenD on Cloud Run, Google allowys to expose one port. Therefore if you want to expose additional services to the gateway such as custom metrics, Cloud Run won’t let you. In this case, you can create a new endpoint that internally uses as the backend host this additional port as localhost:port.

For example, you can have something like this:

{
  "$schema": "https://www.krakend.io/schema/v2.7/krakend.json",
  "version": 3,
  "extra_config": {
    "telemetry/metrics": {
      "collection_time": "60s",
      "proxy_disabled": false,
      "router_disabled": false,
      "backend_disabled": false,
      "endpoint_disabled": false,
      "listen_address": ":8090"
    }
  },
  "endpoints": [
    {
      "endpoint": "/mymetrics",
      "backend": [
        {
          "host": ["localhost:8090"],
          "url_pattern": "/__stats"
        }
      ]
    }
  ]
}

This works because your container still has all the necessary ports available, only that Cloud Run won’t expose them. Through KrakenD you can remap them.

Example of configuring your service account on GCP

Screenshots might vary
Google Cloud interface keeps changing over time. The following screenshots are examples that might not match exactly what you see in the future.

You can integrate GCP when KrakenD is hosted on GCP, or outside of it. Here is an orientation example of how to manually configure it.

Log in to the Google Cloud Console and access the Cloud Run panel.

If you don’t have any service yet, click Create New Service. Next, we selected the proposed test image, which is a hello-world application.

Create a Service on Cloud Run

Then check the “Require Authentication” option when creating the Service, so it cannot be freely accessed. Require authentication

We have named our first service “hello”, and it is now accessible under a newly generated URL and is displayed at the top.

Create the hello service

We will now create the KrakenD configuration. The host and the audience match the new URL.

{
    "$schema": "https://www.krakend.io/schema/v2.7/krakend.json",
    "version": 3,
    "endpoints": [
        {
            "endpoint": "/gcp",
            "output_encoding": "no-op",
            "backend": [
                {
                    "host": [ "https://hello-76fewi6rca-uc.a.run.app" ],
                    "url_pattern": "/someurl",
                    "encoding": "no-op",
                    "extra_config": {
                        "auth/gcp": {
                            "audience": "https://hello-76fewi6rca-uc.a.run.app"
                        }
                    }
                }
            ]
        }
    ]
}

Now you should decide whether KrakenD will run in Google or not.

If we want to host KrakenD on Cloud Run, we will create an image containing the configuration and push it to the Container Registry. Now we will repeat the process of creating a service. This time we will add the krakend service, and we will select the image we have just pushed.

In the creation screen, we do not set any authentication; the gateway will take care of this with the end user with JWT or similar.

Create the krakend service

Depending on your Google Cloud configuration, the integration might immediately work because there could be a default service account allowing KrakenD to access the Hello service.

Whether this is the case or not, we want to contemplate the possibility of hosting KrakenD outside, so we will dig a little further into the Service accounts.

The Service Accounts are under the “IAM & Admin” section of our console.

We are going to create a new Service Account for our project.

Create the service account Create the service account

If we are going to connect from outside Google, we will need to create the credentials. From the Service Account Keys tab we create new ones and select the JSON format. Create the service account

We can use this key from an external KrakenD to authenticate to GCP once we assign it to the Hello project. The last step is to assign the permissions to the hello application, so it allows KrakenD to interact with it.

Select the Service Hello and add permissions by clicking on “Add Principal”. Create a Service on Cloud Run

In the next screen, choose the Service Account you have created and select the role “Cloud Run Invoker” from the list. Click on Save. Create a Service on Cloud Run

The last step you have to take is to include the credentials we just created. The key you downloaded must be copied in your KrakenD directory and referenced as a credentials_file entry, or copy and paste it as credentials_json (or even better, use a template and inject it).

Your Service is now ready. You should be able to access your Hello service from KrakenD.

Scarf

Unresolved issues?

The documentation is only a piece of the help you can get! Whether you are looking for Open Source or Enterprise support, see more support channels that can help you.

See all support channels