Vault Integration
Chaos Engine makes use of Vault, both to securely store information. This information can be rotated in Vault and automatically refresh in runtime in Chaos Engine.
Secret Location
Secrets should be configured under the path /secrets/chaosengine. If using Spring Profiles, it will first try to look under secrets/chaosengine/{profile-name}.
Tip
If overriding the value for spring.application.name
, then that application name will be used for the secrets path instead of chaosengine.
SDK
Given the already large use of Spring Framework, Spring Cloud Vault is used to seamlessly integrate with Vault.
Configuration
The vault endpoint is configured through environment variables.
Variable | Description | Default Value |
---|---|---|
VAULT_TOKEN | Token for access into the Vault | 00000000-0000-0000-0000-000000000000 |
VAULT_SCHEME | HTTP/HTTPS scheme for access into Vault | http |
VAULT_HOST | FQDN of the Vault Host | localhost |
VAULT_PORT | Port of the Vault Host | 8200 |
VAULT_10 | Used to enable support for HashiCorp Vault v 0.10.x KV Version 2 | false |
SDK Native Variables
Variable | Mapped Variable | Description | Default |
---|---|---|---|
spring.cloud.vault.token | VAULT_TOKEN | Token used for authentication when the authentication mechanism is TOKEN | 00000000-0000-0000-0000-000000000000 |
spring.cloud.vault.port | VAULT_PORT | Port of the Vault Host | 8200 |
spring.cloud.vault.uri | N/A | The full URI of {scheme}://{host}:{port}/ | Derived from host/port/scheme. |
spring.cloud.vault.fail-fast | N/A | If set, application startup will fail if Vault is required and cannot be accessed. | false |
spring.cloud.vault.kv.enabled | VAULT_10 | Enables support for Key/Version Version 2, introduced in HashiCorp Vault 0.10 | false |
spring.cloud.vault.scheme | VAULT_SCHEME | HTTP/HTTPS scheme for access into Vault | https |
spring.cloud.vault.host | VAULT_HOST | FQDN of the Vault Host | localhost |
spring.cloud.vault.authentication | N/A | The Authentication Mechanism used to authenticate against Vault | TOKEN |
spring.cloud.vault.enabled | N/A | Flag to enable/disable Vault Integration | true |
Feeding Vault With Data Example
export VAULT_ADDR='http://$VAULT_HOST:8200'
export VAULT_DEV_ROOT_TOKEN_ID=00000000-0000-0000-0000-000000000000
vault auth $VAULT_DEV_ROOT_TOKEN_ID
vault kv put secret/chaosengine aws.accessKeyId=$AWS_ACCESS_KEY_ID aws.secretAccessKey=$AWS_SECRET_ACCESS_KEY aws.region=eu-west-1 AWS_FILTER_KEYS='Chaos Victim' AWS_FILTER_VALUES=true holidays=NONSTOP aws.ec2=true
vault kv get secret/chaosengine
Triggering a Refresh
The Java Objects are not automatically refreshed when values are changed in vault. Instead, an API must be called to trigger a reload. This should be done after ALL values have changed, as calling it with only some values changed may have unpredictable errors (i.e., Access Key ID changed but Secret Key is unchanged may cause errors).
In order to trigger the request, a HTTP POST request needs to be made against http://{chaosengine}/refresh .
Triggering a Reload
If new variables that control object creation are added or removed, then the Chaos Engines application context needs to be completely reloaded. To accomplish this, send an HTTP POST request to http://{chaosengine}/refresh/all.
Spring Profiles
The Spring Cloud Vault integration makes use of the Spring Profile option to allow for different variables to be accessible from different environments.
By default, Chaos Engine will look in /secret/chaosengine for the appropriate resource name. However, if run with a specified Spring Profile Name, it will look in /secret/chaosengine/{Profile Name}/ first, allowing for distinct secrets to be given in different environments.
Development Notes
ConfigurationProperties
Classes that need to use many values should use the \@ConfigurationProperties annotation. This can be specified with a prefix. When done, any variables named {prefix}.{variable} will automatically be assigned using a Setter method for that variable.
Example of \@ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "chaos")
public class MyClass {
private String myString; // This will inherit chaos.myString's value
private Integer myInteger; // This will inherit chaos.myInteger's value
/*
Setters are needed for the variables in order for ConfigurationProperties to inject them.
*/
public void setMyString (String myString) {
this.myString = myString;
}
public void setMyInteger (Integer myInteger) {
this.myInteger = myInteger;
}
/*
Beans need a RefreshScope annotation in order to be reinitialized when changed.
*/
@Bean
@RefreshScope
MyBean myBean () {
return new MyBean(myString, myInteger);
}
}
RefreshScope
Spring Beans that use values from ConfigurationProperties can be flagged for reinitializing with a \@RefreshScope annotation. Spring does this by adding an interpretation layer between where the bean is Autowired and where it is created, extending the class of the bean to do so. This does mean that it will not work with beans of a final class. See above for an example.