chensoul / spring-config-server

Repository from Github https://github.comchensoul/spring-config-serverRepository from Github https://github.comchensoul/spring-config-server

spring-config-server

How to run

Package the application using the maven command:

./mvnw package

Setting an environment variable named SPRING_CONFIG_ADDITIONAL_LOCATION or SPRING_CONFIG_IMPORT to the location of the configuration file, for example samples/config-repo.yml:

export SPRING_CONFIG_IMPORT=samples/config-repo.yml

Using Java 17+ or higher, run the Config Server application:

java -jar target/spring-config-server-0.0.1-SNAPSHOT.jar 

To verify, you can use curl to fetch the configuration for the default application and profile by running:

curl -u user:password http://localhost:8888/application/default

Resources

Path Description
/{app}/{profile} Configuration data for app in Spring profile (comma-separated).
/{app}/{profile}/{label} Add a git label
/{app}/{profile}{label}/{path} An environment-specific plain text config file (at "path")

Security

HTTP Basic authentication

The server is secure with HTTP Basic authentication by Spring Security (via spring-boot-starter-security). The user name is "user" and the password is "password". You can override the password with the environment variable SPRING_SECURITY_USER_PASSWORD. E.g.

SPRING_SECURITY_USER_PASSWORD=pass123

Encryption and decryption

Generate a keystore with a key pair:

keytool -genkeypair -alias mytestkey -keyalg RSA\
  -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=CN" -validity 3650 \
  -storetype PKCS12 -keystore keystore.jks -storepass changeit

Run the Config Server application with the environment variable ENCRYPT_KEYSTORE_PASSWORD set to the keystore password:

ENCRYPT_KEYSTORE_PASSWORD=changeit java -jar target/*.jar

Test encryption and decryption with the following commands:

VALUE=`curl -s -u user:password http://localhost:8888/encrypt -d hello`
curl -u user:password http://localhost:8888/decrypt -d $VALUE

Enabling Mutual TLS (mTLS)

We will use the OpenSSL command line tool to generate the certificates.

  1. Generate CA

First of all, we need a certificate authority (CA) that both the client and the server will trust. We generate these using openssl.

mkdir -p samples/tls/ca
openssl req -new -x509 -nodes -days 365 -subj '/CN=my-ca' -keyout samples/tls/ca/ca.key -out samples/tls/ca/ca.crt

This now puts a private key in ca.key and a certificate in ca.crt on our filesystem. We can inspect these a little further with the following.

openssl x509 --in samples/tls/ca/ca.crt -text --noout

Looking at the output, we see some interesting things about our CA certificate. Most importantly the X509v3 Basic Constraints value is set CA:TRUE, telling us that this certificate can be used to sign other certificates (like CA certificates can).

  1. Generate Server key and certificate

The server now needs a key and certificate. Key generation is simple, as usual:

mkdir -p samples/tls/server
openssl genrsa -out samples/tls/server/tls.key 2048

We need to create a certificate that has been signed by our CA. This means we need to generate a certificate signing request, which is then used to produce the signed certificate.

openssl req -new -key samples/tls/server/tls.key -subj '/CN=localhost' -out samples/tls/server/tls.csr

This gives us a signing request for the domain of localhost as mentioned in the -subj parameter. This signing request now gets used by the CA to generate the certificate.

openssl x509 -req -in samples/tls/server/tls.csr -CA samples/tls/ca/ca.crt -CAkey samples/tls/ca/ca.key -CAcreateserial -days 365 -out samples/tls/server/tls.crt

Inspecting the server certificate, you can see that it’s quite a bit simpler than the CA certificate. We’re only able to use this certificate for the subject that we nominated; localhost.

  1. Generate Client key and certificate

The generation of the client certificates is very much the same as the server.

mkdir -p samples/tls/client
# create a key
openssl genrsa -out samples/tls/client/tls.key 2048

# generate a signing certificate
openssl req -new -key samples/tls/client/tls.key -subj '/CN=my-client' -out samples/tls/client/tls.csr

# create a certificate signed by the CA
openssl x509 -req -in samples/tls/client/tls.csr -CA samples/tls/ca/ca.crt -CAkey samples/tls/ca/ca.key -CAcreateserial -days 365 -out samples/tls/client/tls.crt

The subject in this case is my-client.

The -CAcreateserial number also ensures that we have unique serial numbers between the server and client certificates. Again, this can be verified when you inspect the certificate.

  1. Run Config Server

Run the Config Server application:

export SPRING_CONFIG_IMPORT=file:samples/config-repo-tls.yml
java -jar target/spring-config-server-0.0.1-SNAPSHOT.jar 
  1. Test with certificates and keys
curl \
    --cacert samples/tls/ca/ca.crt \
    --cert samples/tls/client/tls.crt \
    --key samples/tls/client/tls.key \
    -u user:password \
    https://localhost:8888/application/default/main

Enable AOT

Disable the refresh scope in the application.yaml file:

spring:
  cloud:
    refresh:
      enabled: false

Install GraalVM JDK:

sdk install java 21.0.5-graal 

Run maven command to compile the native image:

./mvnw -Pnative native:compile

Run with Docker

Create an image with buildpack.

brew install buildpacks/tap/pack

pack build spring-config-server:0.0.1 \
  --path ./spring-config-server-0.0.1-SNAPSHOT.jar \
  --builder paketobuildpacks/builder:tiny

If you will be running the image on an ARM host (such as an Apple machine with an Apple chipset), you must use a different builder:

pack build spring-config-server:0.0.1 \
--path target/spring-config-server-0.0.1-SNAPSHOT.jar \
--builder dashaun/builder:tiny

Or you can create an image using docker build.

docker build -t chensoul/spring-config-server:0.0.1 .

Start the container by running:

docker run -d \
  -p 8888:8888 \
  --mount type=bind,source="$(pwd)"/samples,target=/app/samples \
  -e SPRING_CONFIG_IMPORT='file:samples/config-repo-tls.yml' \
  chensoul/spring-config-server:0.0.1

Alternatively, you can push the image to docker hub:

docker login
docker tag chensoul/spring-config-server:0.0.1 chensoul/spring-config-server:latest
docker push chensoul/spring-config-server:0.0.1

Enabling Client Applications

Config application.properties file for the client application:

spring.config.import: optional:configserver:http://myconfigserver:8888

Enabling TLS (mTLS) Authentication if the Config Server is running with TLS:

spring.config.import: optional:configserver:http://myconfigserver:8888
spring.cloud.config.tls.enabled: true
spring.cloud.config.tls.key-store: <path-to-key-store>
spring.cloud.config.tls.key-store-type: PKCS12
spring.cloud.config.tls.key-store-password: <key-store-password>
spring.cloud.config.tls.password: <key-password>
spring.cloud.config.tls.trust-store: <path-of-trust-store>
spring.cloud.config.tls.trust-store-type: PKCS12
spring.cloud.config.tls.trust-store-password: <trust-store-password>

About

License:Apache License 2.0


Languages

Language:Java 82.8%Language:Dockerfile 17.2%