Spring Cloud — Configuration

Ahmet Cokgungordu
4 min readDec 13, 2018

Spring Cloud Config, birden çok uygulama ve ortam arasında dağıtılmış yapılandırmaların depolanması ve sunulması için Spring’in client/server yaklaşımıdır.

Bu yapılandırma deposunun senaryolarından birisi Git sürüm kontrolü altında kullanılmasıdır. Config Server ile uygulama yapılandırmaları çalışma zamanında değiştirilebilir. Tüm desteklenen yapılandırma dosyası formatları PropertySource veya Value anotasyonları ile Environment gibi yapılarla birlikte kullanılabilir.

Spring Cloud Config Server, bir uygulama örneği üzerinden daha iyi anlaşılabilir.

Proje Kurulumu ve Bağımlılıklar

Öncelikle bir Spring Boot Projesi oluşturuyoruz ve POM dosyasına bazı bağımlılıkları ekliyoruz. Bu bağımlılıkları, tüm modüller arasında paylaşılacak bir proje olarak düşünebilirsiniz.

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

Kodları yazmaya hazırlamadan önce iki yeni Maven projesi hazırlayacağız.

İlk olarak server projesi için yapılandırma ayarları aşağıdaki gibi olacaktır.

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>1.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>

Client projeleri için yapılandırma ayarları ise aşağıdaki gibi olacaktır.

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>1.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>

Config Server Uygulaması Ayarları

Uygulamanın ana kısmı @SpringBootApplication anotasyonunun yer aldığı bir yapılandırma sınıfıdır. @EnableConfigServer anotasyonu aracılığıyla gerekli tüm kurulumları çekiyoruz.

@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
public static void main(String[] arguments) {
SpringApplication.run(ConfigServer.class, arguments);
}
}

Artık sunucumuzun dinlediği sunucu portunu ve sürüm kontrollü konfigürasyon içeriğimizi sağlayan bir Git-url’i yapılandırmamız gerekiyor. Alternatif olarak http, ssh veya yerel bir dosya sistemindeki basit bir dosya gibi protokollerle kullanılabilir.

Her uygulama yeniden başlatıldığında otomatik olarak oluşturulmuş bir şifreyi önlemek için bootstrap.yml içine Basic-Authentication için bir kullanıcı adı ve şifre belirlememiz gerekir.

server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: ssh://localhost/config-repo
username: property-admin
password: admin12345
security:
user:
name: root
password: s3cr3t

Yapılandırma Deposu Olarak Bir Git Reposu

Git altında bazı yapılandırma dosyaları oluşturulması gerekiyor. Bu yapılandırma dosyalarını oluştururken ‘uygulama adı’ — ‘profil adı’ olarak oluşturulur. Örnek olarak;

config-client-development.yml-> development ortamı için

config-client-production.yml-> ürün ortamı için

Yapılandırmayı Okuma

Config Server uygulamasını başlatıyoruz ve Config Server tarafından sağlanan Git destekli yapılandırma API’sini aşağıdaki yollar kullanılarak sorgulayabiliriz.

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

{label} parametresi Git reposundaki branch dalını, {application} uygulama adını, {profil} ise mevcut uygulama profilidir.

Yapılandırma dosyasına aşağıdaki şekilde erişilebilir.

http://root:s3cr3t@localhost:8888/config-client/development/master

Client Uygulaması Ayarları

Çok basit bir Client uygulaması olarak, bir GET metodu ile REST controller oluşturalım.

@SpringBootApplication
@RestController
public class ConfigClient {
@Value("${user.role}")
private String role;
public static void main(String[] args) {
SpringApplication.run(ConfigClient.class, args);
}
@RequestMapping(
value = "/whoami/{username}",
method = RequestMethod.GET,
produces = MediaType.TEXT_PLAIN_VALUE)
public String whoami(@PathVariable("username") String username) {
return String.format("Merhaba %s! %s rolüne sahipsin...\n", username, role);
}
}

Ayarları oluşturduğumuz serverdan almak için bootstrap.application adında bir ayar dosyası oluşturuyoruz. Bu dosya, adından da anlaşıldığı gibi uygulama ayağa kalkarken ilk okunan ayar dosyasıdır. Uygulama adının yanı sıra, aktif profili ve bağlantı detaylarını bu dosya içerisine ekliyoruz.

spring.application.name=config-client
spring.profiles.active=development
spring.cloud.config.uri=http://localhost:8888
spring.cloud.config.username=root
spring.cloud.config.password=s3cr3t

Yapılandırmamız sunucudan uygun şekilde alınırsa ve controller metodunda ‘role’ değeri enjekte edilirse aşağıdaki isteği bulunduğumuzda;

http://localhost:8080/whoami/Mr_Pink

Yanıt aşağıdaki şekilde olursa, Spring Cloud Config Server üzerinden parametreleri düzgün okuyor oluruz.

Hello! You’re Mr_Pink and you’ll become a(n) Developer…

Encryption ve Decryption

Spring encryption ve decryption özelliklerini kullanabilmek için, JVM’inizde ‘Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files’ yüklü olması gereklidir. Bunu Oracle’dan indirilebilirsiniz.

Daha sonra yukarıdaki Oracle linkinden indirdiğimiz dosya içerisindeki 2 dosyayı sistemde yüklü olan JDK içerisindeki ‘/jre/lib/security’ klasöründeki aynı isimdeki dosyalar ile değiştiriyoruz.

Config Server projesindeki yapılandırma dosyası içerisine belirleyeceğiniz key aşağıdaki gibi eklenir ve server tekrar başlatılır.

encrypt.key: asd123

Config Server Veriyi Şifreleme

Config Server üzerinde ‘/encrypt’ ve ‘/decrypt’ POST metodları bulunmaktadır. Postman yardımıyla aşağıdaki isteğin body kısmına şifrelenecek değer yazılır ve POST ile çağırımda bulunulur ve response olarak şifrelenmiş değerin geldiğini göreceksiniz. Bunun tam tersi işlemi yaparak kontrolünü sağlayabilirsiniz.

POST http://localhost:8888/encrypt
Request Body: passDeneme
Response: 1785d7e84e6f6055f22527b53e2444b78d38773f0c27f53ed58b616948dc59ca
POST http://localhost:8888/decrypt
Request Body: 1785d7e84e6f6055f22527b53e2444b78d38773f0c27f53ed58b616948dc59ca
Response: passDeneme

Encrypt edilmiş bu değeri yapılandırma dosyası içerisine aşağıdaki gibi ekleriz. yml dosya uzantısında başına ve sonuna tek tırnak eklenmelidir.

accounts.account1.password: '{cipher}1785d7e84e6f6055f22527b53e2444b78d38773f0c27f53ed58b616948dc59ca'

Yapılandırma dosyasında yapılan bu değişiklik dosya sisteminde ise Config Server üzerinde bir istekte bulunmaya gerek yoktur. Git üzerinden okunuyorsa öncelikle Config Server üzerinden yeni değerin okunması için Config Server’a aşağıdaki istekte bulunuyoruz.

POST http://localhost:8888/refresh

Güncellenecek değişkenin olduğu sınıfta @ConfigurationProperties veya @RefreshScope anotasyonları bulunmalıdır. @ConfigurationProperties kullanıyorsanız, @RefreshScope gerekli değildir.

Client projesine bu değişikliğin yansıması için client uygulamasına ‘/refresh’ isteğinde bulunmamız gerekiyor. Bu istek için öncelikle ‘spring-boot-starter-actuator’ bağımlılığının Client projesinde ekli olması gerekiyor. Daha sonra aşağıdaki istekte bulunup contextin güncellenmesini sağlıyoruz.

POST http://localhost:8040/refresh

Key Yönetimi

Config Server, simetrik veya asimetrik bir şekilde parametre değerlerini şifrelemek için varsayılan değeri aktiftir.

Simetrik şifreleme, yukarıdaki örnekte olduğu gibi ‘encrypt.key’ kullanarak yapılan şifreleme yönetimidir.

Asimetrik şifreleme ise, PEM-encoded değeri veya keystore kullanarak yapılan bir şifreleme yöntemidir.

Asimetrik şifrelemeyi kullanarak Config Server yapılandırmasını yaparken öncelikle Java keytool yardımı ile aşağıdaki komutu çalıştırıp bir keystore oluşturuyoruz.

keytool -genkeypair -alias config-server-key -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -dname "CN=Config Server,OU=Spring Cloud,O=Egabyte" -keypass rty321zxc -keystore config-server.jks -storepass asd123dfg

Daha sonra, ‘encrypt.key’ parametresinin yerine, oluşan dosyayı Config Server içerisindeki yapılandırma dosyasına aşağıdaki gibi ekliyoruz ve Config Server’ı tekrar başlatıyoruz.

encrypt.key-store.location=classpath:/config-server.jks
encrypt.key-store.password=asd123dfg
encrypt.key-store.alias=config-server-key
encrypt.key-store.secret=rty321zxc

Daha sonra yukarıdaki veriyi şifreleme işlemlerini aynen yapabiliyor olacağız. Bu yöntemde şifre daha karmaşık olarak dönecektir.

Sunucu tarafında şifrelemeyi devre dışı bırakmak ve değerlerin çözülmesini görebilmek için Config Server yapılandırmasına aşağıdaki parametreyi ekliyoruz.

spring.cloud.config.server.encrypt.enabled=false

Config Server uygulamasını tekrar başlattığınızda şifrelenmiş parametreyi ‘{cipher}AgBi60p+CBBf7MsgC…’ şeklinde şifreli haliyle göreceksiniz.

Ayrıca, REST servislerini de devre dışı bırakmak için diğer tüm ‘encrypt.*’ özelliklerini silebilirsiniz.

--

--