What is the preferred way to configure GCP credentials in Spring boot application

Viewed 1378

I am in process of writing a spring boot based microservice, which will be deployed on GKE. To configure service account credentials i do see there are multiple options available . What is the most preferred and possibly safer option available. I have tried below approaches, kindly suggest other ways

  1. CredentialsProvider interface with spring.cloud.gcp.credentials.location
  2. spring.cloud.gcp.credentials.encoded-key
  3. GCP secrete manager
4 Answers

In Cloud environment generally the safest and best option with least administrative overhead is to use the corresponding service from the Cloud provider - in your case it would be Secret Manager. Of course if you are planning to not tie your applications with a specific cloud provider or cater to on-prem environment as well then you can use third party Secret management providers like HashiCorp Vault.

However even with Secret Manager if you interact with the API directly you will have to provide keys to call the API somewhere which creates another problem. The general recommended solution is to to use application authenticating as Service accounts and interacting with Secret manager directly as outlined here. Or there are alternative ways of mounting Secrets from Secret Manager on the GKE Volume using CSI Driver as explained here.

Running a secure cluster and container applications is a critical requirement and here are further recommendations for GKE security hardening which covers Secret management as well. More specifically you can check the recommendation in section "CIS GKE Benchmark Recommendation: 6.3.1"

Although @Shailendra gives you a good solution, as you are using GKE, you can store sensitive information as Kubernetes secrets.

Both the Kubernetes and GKE documentation provide several examples of creating secrets.

You can later use the configured secrets in multiple ways, in the simple use case, as environment variables that can be consumed in the application. Please, see as well this article.

Th Spring Cloud Kubernetes project provides support for consuming this secrets as property sources.

This approach allows you to test your application deployment locally, with minikube or kind, and later deploy the same artifacts to the cloud provider. In addition, it is cloud provider agnostic as you are using out-of-the-box Kubernetes artifacts.


I am afraid that we were so focused in provide you further alternatives that at the end we do not actually answer your question.

Previously, I will give you the advice of use Kubernetes Secrets, and it is still perfectly fine, but please, allow me to come back to it later.

According to the different properties you are trying setting, you are trying configuring the credentials on behalf your application with interact with other services deployed in GCP.

For that purpose the first thing you need is a service account.

In a nutshell, a service account is a software artifact that agglutinates several permissions.

This service account can be later assigned to a certain GCP resource, to a certain GCP service, and it will allow that resource to inherit or act on behalf of the configured permissions when interacting with other GCP resources and services.

Every service account will have an associated set of keys which identify the service account - the information you are trying to keep safe.

There are different types of service accounts, mainly, default service accounts, created by GCP when you enable or use some Google Cloud services - one for Compute Engine and one for App Engine - and user defined ones.

You can modify the permissions associated with these service accounts: the important thing to keep in mind is always follow the principle of least privilege, only grant the service account the necessary permissions for performing its task, nothing else.

By default, your GKE cluster will use the default Compute Engine service account and the scopes for it defined. These permissions will be inherited by your pods when contacting other services.

As a consequence, one possible option is just configuring an appropriate service account for GKE and use these permissions in your code.

You can use the default Compute Engine service account, but, as indicated in the GCP docs when describing how to harden the cluster security:

Each GKE node has an Identity and Access Management (IAM) Service Account associated with it. By default, nodes are given the Compute Engine default service account, which you can find by navigating to the IAM section of the Cloud Console. This account has broad access by default, making it useful to wide variety of applications, but it has more permissions than are required to run your Kubernetes Engine cluster. You should create and use a minimally privileged service account to run your GKE cluster instead of using the Compute Engine default service account.

So probably you will need to create a service account with the minimum permissions to run your cluster (and) application. The aforementioned link provides all the necessary information.

As an alternative, you can configure a different service account for your application and this is where, as a possible alternative, you can use Kubernetes Secrets.

Please:

  • Do not directly provide your own implementation of CredentialsProvider, I think it will not provide you any additional benefit compared with the rest of solutions.

  • If you want to use the spring.cloud.gcp.credentials.location configuration property, create a Kubernetes secret and expose it as a file, and set the value of this property to that file location.

  • In a very similar way, using Kubernetes Secrets, and as exemplified for instance in this article, you can expose the service account credentials under the environment variable GOOGLE_APPLICATION_CREDENTIALS, both Spring GCP and the different GCP client libraries will look for this variable in order to obtain the required credentials.

  • I would not use the configuration property spring.cloud.gcp.credentials.encoded-key, in my opinion this approach makes the key more suitable for threats - probably you have to deal with VCS problems, etc.

  • Secret Manager... as I told, it is a suitable solution as indicated by @Shailendra in his answer.

  • The options provided by Guillaume are very good as well.

The preferred way is hard to answer. Depends on your wishes...

Personally, I prefer to keep a high level of security, it's related to service account authentication and a breach can be a disaster.

Therefore, too keep the secrets secret, I prefer not having secrets. Neither in K8S secret nor in secret manager! Problem solved!!

You can achieve that with ADC (application default credential). But like that, out of the box, the ADC use the Node identity. The problem here is if you run several pods on the same node, all will have the same identity and thus the same permissions.

A cool feature is to use Workload Identity. It allows you to bind a service account with your K8S deployment. The ADC principle is the same, except that it's bind at the pods level and not at the node level (a proxy is created that intercept the ADC requests)

If your application is running on GCP the preferred way would be to use default credentials provided by the Google GCP clients. When using the default credentials provider the clients will use the service account that is associated with you application.

Related