DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Component Tests for Spring Cloud Microservices
  • A Robust Distributed Payment Network With Enchanted Audit Functionality - Part 2: Spring Boot, Axon, and Implementation
  • 7 Microservices Best Practices for Developers

Trending

  • Code Reviews: Building an AI-Powered GitHub Integration
  • Efficient API Communication With Spring WebClient
  • Introducing Graph Concepts in Java With Eclipse JNoSQL
  • The Evolution of Scalable and Resilient Container Infrastructure
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. Exploring Spring Cloud Configuration Server  in Microservices

Exploring Spring Cloud Configuration Server  in Microservices

In this article, we'll learn how to use the Spring Cloud Configuration server to centralize managing the configuration of our microservices.

By 
Magnus Larsson user avatar
Magnus Larsson
·
Updated Aug. 31, 21 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
10.9K Views

Join the DZone community and get the full member experience.

Join For Free

In this article, we will learn how to use the Spring Cloud Configuration server to centralize managing the configuration of our microservices. An increasing number of microservices typically come with an increasing number of configuration files that need to be managed and updated. 

With the Spring Cloud Configuration server, we can place the configuration files for all our microservices in a central configuration repository that will make it much easier to handle them. Our microservices will be updated to retrieve their configuration from the configuration server at startup. 

This article is an excerpt from my book, Microservices with Spring Boot and Spring Cloud, Second Edition – A step-by-step guide to creating and deploying production-quality microservices-based applications.  

The Spring Cloud Configuration server (shortened to config server) will be added to the existing microservice landscape behind the edge server, in the same way as for the other microservices:  

  

Figure 1: Adding a config server to the system landscape  

When it comes to setting up a config server, there are a number of options to consider:  

  • Selecting a storage type for the configuration repository.  
  • Deciding on the initial client connection, either to the config server or to the discovery server.  
  • Securing the configuration, both against unauthorized access to the API and by avoiding storing sensitive information in plain text in the configuration repository.  

Let's go through each option one by one and also introduce the API exposed by the config server.  

Selecting Storage Type of the Configuration Repository  

The config server supports the storing of configuration files in a number of different backends, for example:  

  • Git repository  
  • Local filesystem  
  • HashiCorp Vault  
  • A JDBC database  

Other Spring projects have added extra backends for storing configuration, for example, the Spring Cloud AWS project, which has support for using either AWS Parameter Store or AWS Secrets Manager as backends. 

In this section, we are going to use a local filesystem. To do this, we need to launch the config server with the Spring profile, native, enabled. The configuration repository location  is specified by using the spring.cloud.config.server.native.searchLocations property.  

Deciding on the Initial Client Connection  

By default, a client connects first to the config server to retrieve its configuration. Based on the configuration, it connects to the discovery server, Netflix Eureka in our case, to register itself. It is also possible to do this the other way around, that is, the client first connecting to the discovery server to find a config server instance and then connecting to the config server to get its configuration. There are pros and cons to both approaches.  

Here, the clients will first connect to the config server. With this approach, it will be possible to store the configuration of the discovery server in the config server.  

Note: One concern with connecting to the config server first is that the config server can become a single point of failure. If the clients connect first to a discovery server, such as Netflix Eureka, there can be multiple config server instances registered so that a single point of failure can be avoided.  

Securing the Configuration  

Configuration information will, in general, be handled as sensitive information. This means that we need to secure the configuration information both in transit and at rest. From a runtime perspective, the config server does not need to be exposed to the outside through the edge server. During development, however, it is useful to be able to access the API of the config server to check the configuration. In production environments, it is recommended to lock down external access to the config server.   

Securing the Configuration in Transit  

When the configuration information is asked for by a microservice, or anyone using the API of the config server, it will be protected against eavesdropping by the edge server since it already uses HTTPS.  

To ensure that the API user is a known client, we will use HTTP Basic authentication. We can set up HTTP Basic authentication by using Spring Security in the config server and specifying the environment variables, SPRING_SECURITY_USER_NAME and SPRING_SECURITY_USER_PASSWORD, with the permitted credentials.  

Securing the Configuration at Rest  

To avoid a situation where someone with access to the configuration repository can steal sensitive information, such as passwords, the config server supports the encryption of configuration information when stored on a disk. The config server supports the use of both symmetric and asymmetric keys. Asymmetric keys are more secure but harder to manage.  

In this chapter, we will use a symmetric key. The symmetric key is given to the config server at startup by specifying an environment variable, ENCRYPT_KEY. The encrypted key is just a plain text string that needs to be protected in the same way as any sensitive information.  

Introducing the Config Server API  

The config server exposes a REST API that can be used by its clients to retrieve their configuration. In this chapter, we will use the following endpoints in the API:  

  • /actuator: The standard actuator endpoint is exposed by all microservices. 
    As always, these should be used with care. They are very useful during development but must be locked down before being used in production.  
  • /encrypt and /decrypt: Endpoints for encrypting and decrypting sensitive information. These must also be locked down before being used in production.  
  • /{microservice}/{profile}: Returns the configuration for the specified microservice and the specified Spring profile.  

We will see some sample uses for the API when we try out the config server.  

Setting up a Config Server 

Setting up a config server on the basis of the decisions discussed is straightforward:  

  1. Create a Spring Boot project using Spring Initializr. 
  2. Add the dependencies, spring-cloud-config-server and spring-boot-starter-security, to the Gradle build file, build.gradle.  
  3. Add the annotation, @EnableConfigServer, to the application class, ConfigServerApplication:  

Java
 
@EnableConfigServer 
@SpringBootApplication 
public class ConfigServerApplication { 
  1. Add the configuration for the config server to the default property file, application.yml:  

Java
 
server.port: 8888 
 
spring.cloud.config.server.native.searchLocations: file:${PWD}/config-repo 
 
management.endpoint.health.show-details: "ALWAYS" 
management.endpoints.web.exposure.include: "*" 
 
logging.level.root: info  
 
--- 
spring.config.activate.on-profile: docker 
spring.cloud.config.server.native.searchLocations: file:/config-repo  


The most important configuration is to specify where to find the configuration repository, indicated using the spring.cloud.config.server.native.searchLocations property.  

  1. Add a routing rule to the edge server to make the API of the config server accessible from outside the microservice landscape.  

  1. Add a Dockerfile and a definition of the config server to the three Docker Compose files.  

  1. Externalize sensitive configuration parameters to the standard Docker Compose environment file, .env. The parameters are described below, in the Configuring the config server for use with the Docker section.  

  1. Add the config server to the common build file, settings.gradle:  

    Java
     
    include ':spring-cloud:config-server'

    The source code for the Spring Cloud Configuration server can be found in $BOOK_HOME/Chapter12/spring-cloud/config-server.   

Now, let's look into how to set up the routing rule referred to in step 5 and how to configure the config server added in Docker Compose, as described in steps 6 and 7.  

Setting up a Routing Rule in the Edge Server   

To be able to access the API of the config server from outside the microservice landscape, we add a routing rule to the edge server. All requests to the edge server that begin with /config will be routed to the config server with the following routing rule:  

Java
 
 - id: config-server 
   uri: http://${app.config-server}:8888 
  predicates: 
  - Path=/config/** 
  filters: 
  - RewritePath=/config/(?<segment>.*), /$\{segment}  


The RewritePath filter in the routing rule will remove the leading part, /config, from the incoming URL before it sends it to the config server.  

The edge server is also configured to permit all requests to the config server, delegating the security checks to the config server. The following line is added to the SecurityConfig class in the edge server:  

Java
 
  .pathMatchers("/config/**").permitAll()  


With this routing rule in place, we can use the API of the config server; for example, run the following command to ask for the configuration of the product service when it uses the docker Spring profile:  

Java
 
curl https://dev-usr:dev-pwd@localhost:8443/config/product/docker -ks | jq  


We will run this command when we try out the config server later on.  

Configuring the Config Server for Use With Docker  

The Dockerfile of the config server looks the same as for the other microservices, except for the fact that it exposes port 8888 instead of port 8080.  

When it comes to adding the config server to the Docker Compose files, it looks a bit different from what we have seen for the other microservices:  

Java
 
config-server: 
  build: spring-cloud/config-server 
  mem_limit: 512m  
  environment: 
    - SPRING_PROFILES_ACTIVE=docker,native 
    - ENCRYPT_KEY=${CONFIG_SERVER_ENCRYPT_KEY} 
    - SPRING_SECURITY_USER_NAME=${CONFIG_SERVER_USR} 
    - SPRING_SECURITY_USER_PASSWORD=${CONFIG_SERVER_PWD} 
  volumes: 
    - $PWD/config-repo:/config-repo 

  

Here are the explanations for the preceding source code:  

  1. The Spring profile, native, is added to signal to the config server that the config repository is based on local files.  
  2. The environment variable ENCRYPT_KEY is used to specify the symmetric encryption key that will be used by the config server to encrypt and decrypt sensitive configuration information.  
  3. The environment variables SPRING_SECURITY_USER_NAME and SPRING_SECURITY_USER_PASSWORD are used to specify the credentials to be used for protecting the APIs using basic HTTP authentication.  
  4. The volume declaration will make the config-repo folder accessible in the Docker container at /config-repo.  

The values of the three preceding environment variables, marked in the Docker Compose file with ${...}, are fetched by Docker Compose from the .env file:  

Java
 
CONFIG_SERVER_ENCRYPT_KEY=my-very-secure-encrypt-key 
CONFIG_SERVER_USR=dev-usr 
CONFIG_SERVER_PWD=dev-pwd  


The information stored in the .env file, that is, the username, password, and encryption key, is sensitive and must be protected if used for something other than development and testing. Also, note that losing the encryption key will lead to a situation where the encrypted information in the config repository cannot be decrypted!   

Summary  

In this article, we have seen how we can use the Spring Cloud Configuration server to centralize managing the configuration of our microservices. We can place the configuration files in a common configuration repository and share common configurations in a single configuration file while keeping microservice-specific configuration in microservice-specific configuration files. The microservices have been updated to retrieve their configuration from the config server at startup and are configured to handle temporary outages while retrieving their configuration from the config server. Microservices with Spring Boot and Spring Cloud, Second Edition

Spring Framework Spring Cloud microservice

Published at DZone with permission of Magnus Larsson, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Component Tests for Spring Cloud Microservices
  • A Robust Distributed Payment Network With Enchanted Audit Functionality - Part 2: Spring Boot, Axon, and Implementation
  • 7 Microservices Best Practices for Developers

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!