Pengenalan Pantas untuk Konfigurasi Awan Musim Semi

1. Gambaran keseluruhan

Spring Cloud Config adalah pendekatan klien / pelayan Spring untuk menyimpan dan melayani konfigurasi yang diedarkan di pelbagai aplikasi dan persekitaran.

Kedai konfigurasi ini mempunyai versi yang ideal di bawah kawalan versi Git dan dapat diubah suai pada waktu operasi aplikasi. Walaupun sangat sesuai di aplikasi Spring menggunakan semua format fail konfigurasi yang disokong bersama dengan konstruk seperti Environment , PropertySource atau @Value , ia dapat digunakan di lingkungan mana pun yang menjalankan bahasa pengaturcaraan apa pun.

Dalam penulisan ini, kami akan memfokuskan pada contoh cara menyediakan pelayan konfigurasi yang disokong Git , menggunakannya dalam pelayan aplikasi REST yang sederhana dan menyiapkan persekitaran yang selamat termasuk nilai harta tanah yang dienkripsi.

2. Penyediaan dan Ketergantungan Projek

Untuk bersiap sedia menulis beberapa kod, kami membuat dua projek Maven baru terlebih dahulu. Projek pelayan bergantung pada modul spring-cloud-config-server , serta bundle starter -boot-starter-security dan spring-boot-starter-web :

 org.springframework.cloud spring-cloud-config-server   org.springframework.boot spring-boot-starter-security   org.springframework.boot spring-boot-starter-web 

Walau bagaimanapun, untuk projek pelanggan, kami hanya memerlukan modul spring-cloud-starter-config dan spring-boot-starter-web :

 org.springframework.cloud spring-cloud-starter-config   org.springframework.boot spring-boot-starter-web 

3. Pelaksanaan Config Server

Bahagian utama aplikasi adalah kelas konfigurasi - lebih khusus lagi @SpringBootApplication - yang menarik semua persediaan yang diperlukan melalui anotasi konfigurasi automatik @EnableConfigServer:

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

Sekarang kita perlu mengkonfigurasi port pelayan di mana pelayan kita mendengar dan Git -url yang menyediakan kandungan konfigurasi yang dikendalikan versi kita. Yang terakhir ini dapat digunakan dengan protokol seperti http , ssh atau fail sederhana pada sistem fail tempatan.

Petua: Sekiranya anda merancang untuk menggunakan beberapa contoh pelayan konfigurasi yang menunjuk ke repositori konfigurasi yang sama, anda boleh mengkonfigurasi pelayan untuk mengklon repo anda ke dalam folder sementara tempatan. Tetapi ketahui repositori peribadi dengan pengesahan dua faktor, sukar dikendalikan! Dalam kes sedemikian, lebih mudah mengklonnya pada sistem fail tempatan anda dan bekerja dengan salinannya.

Terdapat juga beberapa pemboleh ubah placeholder dan corak carian untuk mengkonfigurasi url repositori yang tersedia; tetapi ini di luar ruang lingkup artikel kami. Sekiranya anda berminat, dokumentasi rasmi adalah tempat yang baik untuk bermula.

Kami juga perlu menetapkan nama pengguna dan kata laluan untuk Pengesahan Asas dalam aplikasi kami. Sifat untuk mengelakkan kata laluan yang dihasilkan secara automatik pada setiap aplikasi dimulakan semula:

server.port=8888 spring.cloud.config.server.git.uri=ssh://localhost/config-repo spring.cloud.config.server.git.clone-on-start=true spring.security.user.name=root spring.security.user.password=s3cr3t

4. Git Repository sebagai Penyimpanan Konfigurasi

Untuk melengkapkan pelayan kami, kita harus menginisialisasi repositori Git di bawah url yang dikonfigurasi, membuat beberapa fail sifat baru dan mempopularkannya dengan beberapa nilai.

Nama fail konfigurasi disusun seperti aplikasi Spring biasa. Harta tanah , tetapi bukannya kata 'aplikasi' nama yang dikonfigurasi, misalnya nilai harta 'spring.application.name' pelanggan digunakan, diikuti oleh tanda sempang dan profil aktif. Sebagai contoh:

$> git init $> echo 'user.role=Developer' > config-client-development.properties $> echo 'user.role=User' > config-client-production.properties $> git add . $> git commit -m 'Initial config-client properties'

Penyelesaian masalah: Sekiranya anda menghadapi masalah pengesahan yang berkaitan dengan ssh , periksa semula ~ / .ssh / known_hosts dan ~ / .ssh / Author_keys pada pelayan ssh anda!

5. Menanyakan Konfigurasi

Sekarang kita dapat memulakan pelayan kita. The Git -backed API konfigurasi disediakan oleh pelayan kami boleh disoal menggunakan laluan berikut:

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

Di mana {label} placeholder merujuk kepada cabang Git, {application} ke nama aplikasi klien dan {profile} ke profil aplikasi aktif klien saat ini.

Oleh itu, kami boleh mendapatkan semula konfigurasi untuk klien konfigurasi terancang kami yang berjalan di bawah profil pembangunan di cawangan master melalui:

$> curl //root:[email protected]:8888/config-client/development/master

6. Pelaksanaan Pelanggan

Seterusnya, mari jaga pelanggan. Ini akan menjadi aplikasi pelanggan yang sangat mudah, terdiri daripada pengawal REST dengan satu kaedah GET .

Konfigurasi, untuk mengambil pelayan kami, mesti diletakkan di dalam fail sumber bernama bootstrap.application , kerana fail ini (seperti namanya) akan dimuatkan sangat awal semasa aplikasi bermula:

@SpringBootApplication @RestController public class ConfigClient { @Value("${user.role}") private String role; public static void main(String[] args) { SpringApplication.run(ConfigClient.class, args); } @GetMapping( value = "/whoami/{username}", produces = MediaType.TEXT_PLAIN_VALUE) public String whoami(@PathVariable("username") String username) { return String.format("Hello! You're %s and you'll become a(n) %s...\n", username, role); } }

Sebagai tambahan kepada nama aplikasi, kami juga meletakkan profil aktif dan perincian sambungan di bootstrap.properties kami :

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

Untuk menguji, jika konfigurasi diterima dengan betul dari pelayan kami dan nilai peranan disuntikkan dalam kaedah pengawal kami, kami hanya melengkungnya setelah boot klien:

$> curl //localhost:8080/whoami/Mr_Pink

Sekiranya tindak balas adalah seperti berikut, Server Cloud Cloud Config kami dan pelanggannya berfungsi dengan baik buat masa ini:

Hello! You're Mr_Pink and you'll become a(n) Developer...

7. Penyulitan dan Penyahsulitan

Keperluan : Untuk menggunakan kunci yang kuat secara kriptografi bersama dengan ciri penyulitan dan penyahsulitan musim bunga, anda memerlukan 'Java Policy Cryptography Extension (JCE) Unlimited Strength Jurisdiction Poles Policy' yang dipasang di JVM anda . Contohnya boleh dimuat turun dari Oracle. Untuk memasang ikuti arahan yang disertakan dalam muat turun. Beberapa pengedaran Linux juga menyediakan pakej yang boleh dipasang melalui pengurus pakej mereka.

Oleh kerana pelayan konfigurasi menyokong penyulitan dan penyahsulitan nilai harta tanah, anda boleh menggunakan repositori awam sebagai penyimpanan data sensitif seperti nama pengguna dan kata laluan. Nilai yang dienkripsi diawali dengan rentetan {cipher} dan dapat dihasilkan dengan panggilan REST ke jalan '/ enkripsi' , jika pelayan dikonfigurasi untuk menggunakan kunci simetri atau pasangan kunci.

Titik akhir untuk menyahsulit juga tersedia. Kedua-dua titik akhir tersebut menerima jalan yang mengandungi tempat letak untuk nama aplikasi dan profilnya yang sekarang: '/ * / {name} / {profile}' . Ini sangat berguna untuk mengawal kriptografi setiap pelanggan. Walau bagaimanapun, sebelum menjadi berguna, anda harus mengkonfigurasi kunci kriptografi yang akan kami lakukan di bahagian seterusnya.

Petua: Jika anda menggunakan curl untuk memanggil en- / decryption API, lebih baik menggunakan pilihan –data-urlencode (bukannya –data / -d ), atau tetapkan header 'Content-Type' eksplisit ke 'teks / polos ' . Ini memastikan pengendalian watak khas yang betul seperti '+' dalam nilai yang dienkripsi.

Sekiranya nilai tidak dapat didekripsi secara automatik semasa mengambil pelanggan, kuncinya dinamakan semula dengan nama itu sendiri, diawali dengan perkataan 'tidak sah'. Ini harus mencegah, misalnya penggunaan nilai yang dienkripsi sebagai kata laluan.

Petua: Semasa menyiapkan repositori yang mengandungi fail YAML, anda harus mengelilingi nilai yang dienkripsi dan awalan anda dengan tanda kutip tunggal! Dengan Properties ini tidak berlaku.

7.1. CSRF

Secara lalai Spring Security membolehkan perlindungan CSRF untuk semua permintaan yang dihantar ke aplikasi kami.

Oleh itu, untuk dapat menggunakan titik akhir / menyulitkan dan / menyahsulit , mari kita lumpuhkan CSRF untuk mereka:

@Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.csrf() .ignoringAntMatchers("/encrypt/**") .ignoringAntMatchers("/decrypt/**"); super.configure(http); } }

7.2. Pengurusan Utama

Pelayan konfigurasi diaktifkan secara lalai untuk menyulitkan nilai harta dengan cara simetrik atau asimetrik.

Untuk menggunakan kriptografi simetri , anda hanya perlu menetapkan harta 'encrypt.key' dalam aplikasi anda. Harta menjadi rahsia pilihan anda . Sebagai alternatif anda boleh memasukkan pemboleh ubah persekitaran ENCRYPT_KEY .

For asymmetric cryptography, you can set ‘encrypt.key' to a PEM-encoded string value or configure a keystore to use.

Because we need a highly secured environment for our demo server, we chose the latter option and generating a new keystore, including a RSA key-pair, with the Java keytool first:

$> keytool -genkeypair -alias config-server-key \ -keyalg RSA -keysize 4096 -sigalg SHA512withRSA \ -dname 'CN=Config Server,OU=Spring Cloud,O=Baeldung' \ -keypass my-k34-s3cr3t -keystore config-server.jks \ -storepass my-s70r3-s3cr3t

After that, we're adding the created keystore to our server's bootstrap.properties and re-run it:

encrypt.keyStore.location=classpath:/config-server.jks encrypt.keyStore.password=my-s70r3-s3cr3t encrypt.keyStore.alias=config-server-key encrypt.keyStore.secret=my-k34-s3cr3t

As next step we can query the encryption-endpoint and add the response as value to a configuration in our repository:

$> export PASSWORD=$(curl -X POST --data-urlencode d3v3L \ //root:[email protected]:8888/encrypt) $> echo "user.password={cipher}$PASSWORD" >> config-client-development.properties $> git commit -am 'Added encrypted password' $> curl -X POST //root:[email protected]:8888/refresh

To test, if our setup works correctly, we're modifying the ConfigClient class and restart our client:

@SpringBootApplication @RestController public class ConfigClient { ... @Value("${user.password}") private String password; ... public String whoami(@PathVariable("username") String username) { return String.format("Hello! You're %s and you'll become a(n) %s, " + "but only if your password is '%s'!\n", username, role, password); } }

A final query against our client will show us, if our configuration value is being correct decrypted:

$> curl //localhost:8080/whoami/Mr_Pink Hello! You're Mr_Pink and you'll become a(n) Developer, \ but only if your password is 'd3v3L'!

7.3. Using Multiple Keys

If you want to use multiple keys for encryption and decryption, for example: a dedicated one for each served application, you can add another prefix in the form of {name:value} between the {cipher} prefix and the BASE64-encoded property value.

The config server understands prefixes like {secret:my-crypto-secret} or {key:my-key-alias} nearly out-of-the-box. The latter option needs a configured keystore in your application.properties. This keystore is searched for a matching key alias. For example:

user.password={cipher}{secret:my-499-s3cr3t}AgAMirj1DkQC0WjRv... user.password={cipher}{key:config-client-key}AgAMirj1DkQC0WjRv...

For scenarios without keystore you have to implement a @Bean of type TextEncryptorLocator which handles the lookup and returns a TextEncryptor-Object for each key.

7.4. Serving Encrypted Properties

If you want to disable server-side cryptography and handle decryption of property-values locally, you can put the following in your server's application.properties:

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

Furthermore you can delete all the other ‘encrypt.*' properties to disable the REST endpoints.

8. Conclusion

Now we are able to create a configuration server to provide a set of configuration files from a Git repository to client applications. There are a few other things you can do with such a server.

For example:

  • Serve configuration in YAML or Properties format instead of JSON – also with placeholders resolved. Which can be useful, when using it in non-Spring environments, where the configuration is not directly mapped to a PropertySource.
  • Serve plain text configuration files – in turn optionally with resolved placeholders. This can be useful for example to provide an environment-dependent logging-configuration.
  • Embed the config server into an application, where it configures itself from a Git repository, instead of running as standalone application serving clients. Therefore some bootstrap properties must be set and/or the @EnableConfigServer annotation must be removed, which depends on the use case.
  • Jadikan pelayan konfigurasi tersedia di penemuan perkhidmatan Spring Netflix Eureka dan aktifkan penemuan pelayan automatik pada klien konfigurasi. Ini menjadi penting sekiranya pelayan tidak mempunyai lokasi tetap atau bergerak di lokasinya.

Untuk menyelesaikannya, anda akan menemui kod sumber untuk artikel ini di Github .