Centralized Configuration System written in Golang - Spring cloud compatible
Vecosy is a configuration service exposed through REST/GRPC.
Is Spring Cloud Conf compatible and also provide a Golang client.
The Golang client (or any other GRPC client) has the ability to detect the configuration changes maintaining a connection
to the server via a GRPC stream.
A configuration is identified by three elements: application name, application version and the environment.
Vecosy uses a GIT repository as configuration store with a naming convention to identify the correct application branch (appName/appVersion
),
The system will find the closest (<=) version *very useful when a new release doesn’t need any configuration changes
The security is guaranteed by a JWS token for each application branch and via a TLS connection.
Each application branch can use three different structures/merging strategies: smartConfig, spring, raw (see Configuration repo for more details)
The demo uses the config-sample repository
```shell script
$ docker pull vecosy/vecosy:demo
$ docker run —rm -p 8080:8080 -p 8081:8081 vecosy/vecosy:demo
### Generate the JWS token
Use the [app1/1.0.0 branch](https://github.com/vecosy/config-sample/tree/app1/1.0.0) to run
```shell script
$ echo "app1" | jose-util sign --key priv.key --alg RS256
the code below has already a valid token for the vecosy:demo
package main
import (
"fmt"
"github.com/spf13/viper"
"github.com/vecosy/vecosy/v2/pkg/vecosy"
)
func main() {
jwsToken := "eyJhbGciOiJSUzI1NiJ9.YXBwMQo.A98GFL-P3vtehn0r5GCO_a0OYb5h6trxg3a8WE9hOPDzJ40yOEGtZxyUM6_3Exk65c52-nzWEEc5P-QtgGrgJFOOZlKneKoa1bYBlWRONoysuq95UtSY0doEOMWGvI9AqB685OzmVPuW2UlHg_HlQuuTO6Re1uKc5gr1qZPlyyWEsfoVYTFbfidLoBKWPOuZTxpd8uRx0Rv3LrrmFEcGPHaMNQ2WiXAEJG6OaMTBtwKiynEFH3DU5Rx2WP9M98bH-emC_w7Zq1xKaCOsj2t09F00KohcGC49zSPgPVpp_TwF1qt6_0d0Mnh_Eqi_NHpobVvO85ZOLS05AyW9LQyA5A"
vecosyCl, err := vecosy.NewClientBuilder("localhost:8081", "app1", "1.0.0", "dev").WithJWSToken(jwsToken).Build(nil)
panicOnError(err)
err = vecosyCl.WatchChanges()
panicOnError(err)
fmt.Printf("db.user:%s\n", viper.GetString("db.user"))
}
func panicOnError(err error) {
if err != nil {
panic(err)
}
}
Take a look to spring-boot-example
Remember to add the Authorization
header with the token generated before Bearer [token]
(except if the server has been started with --insecure
option)
from app1/1.0.0
for app1/1.0.0
Create a folder for the server configuration $HOME/myVecosyConf
.
Create a $HOME/myVecosyConf/vecosy.yml
with your configuration (see Server Configuration chapter)
```shell script
$> docker -d —name myVecosyInstance -v $HOME/myVecosyConf:/config -p 8080:8080 -p 8081:8081 vecosy/vecosy:latest
# Server Configuration
*some configuration options can be passed via command line run `vecosy-server --help` for the options*
## TLS
```yaml
server:
tls:
enabled: true
certificateFile: ./myCert.crt
keyFile: ./myCert.key
rest:
address: ":8443"
grpc:
address: ":8081"
...
...
repo:
remote:
url: https://github.com/vecosy/config-sample.git
pullEvery: 30s
local:
path: /tmp/vecosyData
...
repo:
remote:
url: https://github.com/vecosy/config-sample.git
pullEvery: 30s
auth:
type: plain
username: gitRepoUsername
password: gitRepoPassword
local:
path: /tmp/vecosyData
...
repo:
remote:
url: https://github.com/vecosy/config-sample.git
pullEvery: 30s
auth:
type: http
username: gitRepoUsername
password: gitRepoPassword
local:
path: /tmp/vecosyData
...
repo:
remote:
url: github.com:vecosy/config-sample.git
pullEvery: 30s
auth:
type: pubKey
username: git
keyFile: ./myPubKeyFile
keyFilePassword: myPubKeyPassword
local:
path: /tmp/vecosyData
server:
tls:
enabled: true
certificateFile: ./myCert.crt
keyFile: ./myCert.key
rest:
address: ":8443"
grpc:
address: ":8081"
repo:
remote:
url: github.com:vecosy/config-sample.git
pullEvery: 30s
auth:
type: pubKey
username: git
keyFile: ./myPubKeyFile
keyFilePassword: myPubKeyPassword
local:
path: /tmp/vecosyData
The app configuration is stored in a git repository, vecosy use a branch name convention to manage different configuration on the same repository appName/version
(i.e app1/1.0.0).
When a configuration request is processed, the system will find the related branch on the git repo appname/appVersion
if the specific version is not present, the nearest (<=
) version will be used.
Vecosy supports two different merging systems, each one use a different naming convention to merge configuration files.
The config.yml
in the root folder is the common configuration that will be merged by the specific environment (for dev env: dev/config.yml
).
https://github.com/vecosy/config-sample/tree/app1/1.0.0
It uses the spring-cloud naming convention.
The application.yml
will be overriden by [appname].yml
file that will be overriden by [appname]-[profile].yml
https://github.com/vecosy/config-sample/tree/spring-app1/1.0.0
The security is based on a JWS token.
Every application branch has to contains a pub.key
file with the public key of the specific application.
```shell script
$ openssl genrsa -out priv.key 2048
$ openssl rsa -in priv.key -outform PEM -pubout -out pub.key
The `pub.key` has to be added on the application branch on the git repo at the root level.
The `priv.key` will be necessary generating the JWS token for each application that will need the configuration
and should be saved in an external safe place like [vault](https://www.vaultproject.io/)
### 2. generate a jws token
#### install jose-util
```shell script
$ go get -u github.com/square/go-jose/jose-util
$ go install github.com/square/go-jose/jose-util
```shell script
$ echo “myAppName” | jose-util sign —key priv.key —alg RS256
the generated token can be used as *Bearer* Authorization header, in the `token` variable in the GRPC metadata header or as spring cloud configuration [token](https://github.com/vecosy/spring-boot-example/blob/master/src/main/resources/bootstrap.yml)
### 3. Configure your application to use the JWS token
#### vecosy-client (golang)
passing on the `vecosy.NewClientBuilder(...).WithJWSToken(jwsToken)` parameter
#### Spring-cloud application (java)
by Spring cloud configuration [token](https://github.com/vecosy/spring-boot-example/blob/master/src/main/resources/bootstrap.yml)
## Disable the security
the `--insecure` command line option will disable the security system.
# Client (Golang)
Vecosy client use [viper](https://github.com/spf13/viper) as configuration system.
## Specific viper configuration
```go
cfg := viper.New()
vecosyCl,err := vecosy.NewClientBuilder("my-vecosy-server:8080","myApp", "myAppVersion", "integration").
WithJWStoken(jwsToken).
Build(cfg)
// now you can use cfg to get the your app configuration
cfg.getString("my.app.config")
vecosyCl,err := vecosy.NewClientBuilder("my-vecosy-server:8080","myApp", "myAppVersion", "integration").
WithJWStoken(jwsToken).
Build(nil)
viper.getString("my.app.config")
The server has to be started with --insecure
option
vecosyCl,err := vecosy.NewClientBuilder("my-vecosy-server:8080","myApp", "myAppVersion", "integration").
Insecure().
Build(nil)
viper.getString("my.app.config")
vecosyCl,err:= vecosy.NewClientBuilder("my-vecosy-server:8080","myApp", "myAppVersion", "integration").
WithTLS("./myTrust.crt").
WithJWSToken(jwsToken).
Build(nil)
viper.getString("my.app.config")
vecosyCl,err:= vecosy.NewClientBuilder("my-vecosy-server:8080","myApp", "myAppVersion", "integration").
WithJWStoken(jwsToken).
Build(nil)
vecosyCl.WatchChanges()
This will maintain a GRPC connection with the server that will inform the client on every configuration changes on the git repo.
It’s also possible to add handlers to react to the changes
vecosyCl.AddOnChangeHandler(func(prevConfiguration map[string]interface{}) {
fmt.Printf("something has changed from %+v to %+v",prevConfiguration, viper.AllSettings())
})
have a look to the integration test for more details