How to use Spring Cloud Config Server with Git and Vault

In this article I will show how to use Spring Cloud Config Server with two sources: Git and Vault. I will use Git for the common configuration and Vault for the critical information.

Content

  • Distributed Configuration Pattern
  • Spring Cloud Config Server
  • Spring Cloud Config Client
  • Vault

Watch this video for more details.

All the code of the article is available in this repository.

Distributed Configuration Pattern

To use Spring Cloud Config, I need to configure it both the server and the client. In a traditional application, both the code and the configuration are stored together. With the help of the Spring profiles, i can select a different configuration for the development environment and for the production environment. Nevertheless, most of the configuration refers to the infrastructure. The infrastructure may not have the same lifecycle as the application.

So, why to store the configuration for the infrastructure next to the code? With a distributed configuration, the application, at the startup, will download the last version of its configuration. It will be downloaded from the configuration server. This one will be linked to a source folder where the configuration files will be stored. The source folder can be a simple folder, a Git repository, a database, a Redis server, or more. This way, the configuration files can be updated easily. Without the need to change the application.

Spring Cloud Config Server

This means that I need a new project to act as the configuration server. The only dependency I need to make a Spring Boot project acting as a configuration server is the following:

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>

I can also add the Actuator. I don’t need more.

Now, the main class must include the annotation which will indicate to act as the server, @EnableConfigServer.

@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class DistributedConfigurationServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(DistributedConfigurationServiceApplication.class, args);
	}

}

I will also add the @EnableDiscoveryClient annotation to read the application names from the service discovery. Now, configure the server in the application.yml file. Specify the default port used by the server and a different context path.

server:
  port: 8888
  servlet:
    context-path: /config

management:
  health:
    livenessState.enabled: true
    readinessState.enabled: true
  endpoint.health.probes.enabled: true

spring:
  application.name: service-config
  cloud.config.server:
    git:
      uri: file://${user.home}/personal/config-repo

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka

To configure the server to read the configuration from a git repository, I need to specify where to locate the Git repository with the configuration files. If needed, i can specify the username and password to fetch the changes from the repository.

Now, I can move my configuration files from the other projects to this Git repository. I must renamed the application.yml files to the name of the application. The same name specified at the “spring.application.name”, the same name used in the service discovery.

Nevertheless, there is one configuration which will remain in the projects: the “spring.application.name”, obviously. This configuration must placed in a bootstrap.yml file. This file will be loaded at the begging, before calling the configuration server. It must contain the necessary information to get the configuration from the server, nothing more.

Here is an example for a service called service-users:

spring:
  application.name: service-users
  cloud.config.uri: http://localhost:8888/config

Spring Cloud Config Clients

I will need to add two dependencies to each client.

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bootstrap</artifactId>
		</dependency>

spring-cloud-starter-config will configure my microservice to work as a client. and spring-cloud-starter-bootstrap will allow the application to read the configuration from a bootstrap file.

Why do i need this bootstrap file? When starting a Spring Boot application, it first loads some preliminary beans, then reads the application.yml to configure the remaining beans. But in my case, i don’t want those preliminary beans to be loaded with the default values, because i may have some specific values for them. The bootstrap context will load a bootstrap file with the initial configuration. There will be located the URL of the configuration server. This way, the remote configuration will be downloaded at the very startup of the application.

This is not the case for older version of Spring Boot, where the bootstrap context is loaded by default.

Vault

I could end the article now, but having the username and the password of the database stored clearly in a Git repository is far from being a good practice.

Where should i store my credentials? Let’s use Vault. Vault is a key value storage system which encrypts everything at storage. It’s a very good option to store credentials passwords or secrets. I specify which key i want to store, let’s say my username, i pass the value and my authentication token. Nobody, unless the admin, can now read this information. Even other users of the Vault won’t be able to read my username without my token.

So now, i must configure the Spring Cloud Config Server to read from the Vault server and from the Git repository. But having two sources, i must now specify the priority. As i store the most critical information in Vault, this will be the high priority. Even if Spring Cloud Config finds the credentials in the Git repository, they will be overridden by those coming from the Vault server.

spring:
  profiles:
    active: git, vault
  application.name: service-config
  cloud.config.server:
    vault:
      host: 127.0.0.1
      port: 8200
      order: 1
      kv-version: 2
      authentication: TOKEN
      token: <root-token>
    git:
      uri: file://${user.home}/personal/config-repo
      order: 2

The profiles will indicate which sources are available to be read.

I have to specify the version 2 if i am using a recent version of Vault.

I will use the authentication via token. There are about 10 more different types of authentication.

Having the configuration separated from the code allows me to perform some modifications easily to my application. Without the need to redeploy a new version. I can even configure the client to accept a hot reload of the configuration, to allow me to modify on real time some parameters.

References

Repository

My New ebook, How to Master Git With 20 Commands, is available now.

2 responses to “How to use Spring Cloud Config Server with Git and Vault”

  1. […] and most complete (and complex) is using a distributed configuration service. As described in this article. But this needs another service, register it in the load balancer, change the bootstrap startup of […]

    Like

Leave a comment

A WordPress.com Website.