diff --git a/README.adoc b/README.adoc
index 85d029f7..50b8916f 100644
--- a/README.adoc
+++ b/README.adoc
@@ -198,6 +198,12 @@ https://github.com/spring-cloud-incubator/spring-cloud-vault-config/blob/master/
chapters in the
https://github.com/spring-cloud-incubator/spring-cloud-vault-config/blob/master/docs/src/main/asciidoc/spring-cloud-vault-config.adoc[reference guide].
+If the application imports the `spring-boot-starter-actuator` project, the
+status of the vault server will be available via the `\health` endpoint.
+
+The vault health indicator can be enabled or disabled through the
+property `health.vault.enabled` (default `true`)
+
== Building
==== Build requirements for Vault
@@ -206,6 +212,20 @@ Spring Cloud Vault Config requires SSL certificates and a running
Vault instance listening on `localhost:8200`. Certificates and the Vault
setup are scripted, the scripts are located in `src/test/bash`.
+The following scripts need to be run prior to building the project for the tests to pass.
+
+ $ ./src/test/bash/install_vault.sh
+ $ ./src/test/bash/create_certificates.sh
+ $ ./src/test/bash/local_run_vault.sh
+
+Changes to the documentation should be made to the adocs found under `docs/src/main/asciidoc/`
+
+README.adoc can be re-generated via the following
+
+ $ ./docs/src/main/ruby/generate_readme.sh > README.adoc
+
+This script requires ruby and the asciidoctor gem installed (`gem install asciidoctor`)
+
:jdkversion: 1.7
=== Basic Compile and Test
diff --git a/docs/src/main/asciidoc/README.adoc b/docs/src/main/asciidoc/README.adoc
index bc9e3941..ba183f35 100644
--- a/docs/src/main/asciidoc/README.adoc
+++ b/docs/src/main/asciidoc/README.adoc
@@ -25,6 +25,20 @@ Spring Cloud Vault Config requires SSL certificates and a running
Vault instance listening on `localhost:8200`. Certificates and the Vault
setup are scripted, the scripts are located in `src/test/bash`.
+The following scripts need to be run prior to building the project for the tests to pass.
+
+ $ ./src/test/bash/install_vault.sh
+ $ ./src/test/bash/create_certificates.sh
+ $ ./src/test/bash/local_run_vault.sh
+
+Changes to the documentation should be made to the adocs found under `docs/src/main/asciidoc/`
+
+README.adoc can be re-generated via the following
+
+ $ ./docs/src/main/ruby/generate_readme.sh > README.adoc
+
+This script requires ruby and the asciidoctor gem installed (`gem install asciidoctor`)
+
include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building.adoc[]
== Contributing
diff --git a/docs/src/main/asciidoc/quickstart.adoc b/docs/src/main/asciidoc/quickstart.adoc
index a3fbad1f..b59c3a6f 100644
--- a/docs/src/main/asciidoc/quickstart.adoc
+++ b/docs/src/main/asciidoc/quickstart.adoc
@@ -178,3 +178,9 @@ https://github.com/spring-cloud-incubator/spring-cloud-vault-config/blob/master/
https://github.com/spring-cloud-incubator/spring-cloud-vault-config/blob/master/docs/src/main/asciidoc/spring-cloud-vault-config.adoc#token-authentication[authentication]. Checkout these
chapters in the
https://github.com/spring-cloud-incubator/spring-cloud-vault-config/blob/master/docs/src/main/asciidoc/spring-cloud-vault-config.adoc[reference guide].
+
+If the application imports the `spring-boot-starter-actuator` project, the
+status of the vault server will be available via the `\health` endpoint.
+
+The vault health indicator can be enabled or disabled through the
+property `health.vault.enabled` (default `true`)
diff --git a/spring-cloud-vault-config/pom.xml b/spring-cloud-vault-config/pom.xml
index b58d5fdd..edd34532 100644
--- a/spring-cloud-vault-config/pom.xml
+++ b/spring-cloud-vault-config/pom.xml
@@ -21,6 +21,11 @@
spring-cloud-vault-core
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
org.springframework.cloud
spring-cloud-vault-core
diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigBootstrapHealthIndicator.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigBootstrapHealthIndicator.java
new file mode 100644
index 00000000..501136c7
--- /dev/null
+++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultConfigBootstrapHealthIndicator.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.cloud.vault.config;
+
+import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration;
+import org.springframework.boot.actuate.autoconfigure.HealthIndicatorAutoConfiguration;
+import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.vault.VaultBootstrapConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Stuart Ingram
+ */
+@Configuration
+@EnableConfigurationProperties
+@ConditionalOnBean(VaultBootstrapConfiguration.class)
+@ConditionalOnProperty(name = "spring.cloud.vault.enabled", matchIfMissing = true)
+@ConditionalOnExpression("${health.vault.enabled:true}")
+@AutoConfigureBefore({ EndpointAutoConfiguration.class })
+@AutoConfigureAfter({ HealthIndicatorAutoConfiguration.class })
+public class VaultConfigBootstrapHealthIndicator{
+ @Bean
+ @ConditionalOnMissingBean(name = "vaultHealthIndicator")
+ public HealthIndicator vaultHealthIndicator() {
+ return new VaultHealthIndicator();
+ }
+
+}
diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultHealthIndicator.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultHealthIndicator.java
new file mode 100644
index 00000000..a4cb888e
--- /dev/null
+++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultHealthIndicator.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.cloud.vault.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.cloud.vault.VaultHealthResponse;
+
+/**
+ * @author Stuart Ingram
+ */
+public class VaultHealthIndicator implements HealthIndicator {
+ @Autowired
+ private VaultTemplate vaultTemplate;
+
+ @Override
+ public Health health() {
+ try {
+ VaultHealthResponse vaultHealthResponse = vaultTemplate.health();
+ if(!vaultHealthResponse.isInitialized()) {
+ return Health.down().withDetail("Vault uninitialized",null).build();
+ } else if (vaultHealthResponse.isSealed()) {
+ return Health.down().withDetail("Vault sealed",null).build();
+ } else if (vaultHealthResponse.isStandby()) {
+ return Health.outOfService().withDetail("Vault in standby",null).build();
+ } else {
+ return Health.up().build();
+ }
+ }
+ catch(Exception e) {
+ return Health.down().build();
+ }
+
+ }
+
+}
diff --git a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultTemplate.java b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultTemplate.java
index bd41cf86..95e009a4 100644
--- a/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultTemplate.java
+++ b/spring-cloud-vault-config/src/main/java/org/springframework/cloud/vault/config/VaultTemplate.java
@@ -22,6 +22,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.cloud.vault.ClientAuthentication;
import org.springframework.cloud.vault.VaultClient;
import org.springframework.cloud.vault.VaultClientResponse;
+import org.springframework.cloud.vault.VaultHealthResponse;
import org.springframework.cloud.vault.VaultProperties;
import org.springframework.cloud.vault.VaultToken;
import org.springframework.util.Assert;
@@ -112,4 +113,30 @@ public class VaultTemplate implements InitializingBean, VaultOperations {
URI uri = client.buildUri(properties, pathTemplate, variables);
return sessionCallback.doWithVault(uri, vaultSession);
}
+
+ private final static String HEALTH_URL_TEMPLATE = "sys/health";
+
+ /**
+ * Query the current Vault service for it's health status
+ *
+ * @return A {@link VaultHealthResponse} containing the current service status.
+ */
+ public VaultHealthResponse health() {
+ URI uri = client.buildUri(properties, HEALTH_URL_TEMPLATE);
+ return client.health(uri);
+ }
+
+ /**
+ * Check whether Vault is available (vault created and unsealed).
+ *
+ * @return
+ */
+ public boolean isAvailable() {
+ try{
+ VaultHealthResponse health = health();
+ return health.isInitialized() && !health.isSealed();
+ } catch(Exception e) {
+ return false;
+ }
+ }
}
diff --git a/spring-cloud-vault-config/src/main/resources/META-INF/spring.factories b/spring-cloud-vault-config/src/main/resources/META-INF/spring.factories
index 64084bbb..c042b3b4 100644
--- a/spring-cloud-vault-config/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-vault-config/src/main/resources/META-INF/spring.factories
@@ -1,3 +1,4 @@
# Bootstrap Configuration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
-org.springframework.cloud.vault.config.VaultConfigBootstrapConfiguration
\ No newline at end of file
+org.springframework.cloud.vault.config.VaultConfigBootstrapConfiguration,\
+org.springframework.cloud.vault.config.VaultConfigBootstrapHealthIndicator
\ No newline at end of file
diff --git a/spring-cloud-vault-core/src/main/java/org/springframework/cloud/vault/VaultClient.java b/spring-cloud-vault-core/src/main/java/org/springframework/cloud/vault/VaultClient.java
index 35fd2400..e1b799de 100644
--- a/spring-cloud-vault-core/src/main/java/org/springframework/cloud/vault/VaultClient.java
+++ b/spring-cloud-vault-core/src/main/java/org/springframework/cloud/vault/VaultClient.java
@@ -15,6 +15,8 @@
*/
package org.springframework.cloud.vault;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
import java.net.URI;
import java.util.Map;
@@ -26,6 +28,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
import lombok.Getter;
@@ -102,6 +105,29 @@ public class VaultClient {
createHeaders(vaultToken)));
}
+ /**
+ * Query the current Vault service for it's health status
+ *
+ * @param uri must not be {@literal null}.
+ * @return A {@link VaultHealthResponse} containing the current service status.
+ */
+ public VaultHealthResponse health(URI uri) {
+ try {
+ ResponseEntity healthResponse = this.restTemplate.exchange(
+ uri, HttpMethod.GET, null,
+ VaultHealthResponse.class);
+ return healthResponse.getBody();
+ } catch (HttpStatusCodeException responseError) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ return mapper.readValue(responseError.getResponseBodyAsString(), VaultHealthResponse.class);
+ }
+ catch (Exception jsonError) {
+ throw responseError;
+ }
+ }
+ }
+
private VaultClientResponse exchange(URI uri, HttpMethod httpMethod,
HttpEntity> httpEntity) {
@@ -143,7 +169,7 @@ public class VaultClient {
* Build the Vault {@link URI} based on the given {@link VaultProperties} and
* {@code pathTemplate}. URI template variables will be expanded using
* {@code uriVariables}.
- *
+ *
* @param properties must not be {@literal null}.
* @param pathTemplate must not be empty or {@literal null}.
* @param uriVariables must not be {@literal null}.
diff --git a/spring-cloud-vault-core/src/main/java/org/springframework/cloud/vault/VaultHealthResponse.java b/spring-cloud-vault-core/src/main/java/org/springframework/cloud/vault/VaultHealthResponse.java
new file mode 100644
index 00000000..8ce90c2b
--- /dev/null
+++ b/spring-cloud-vault-core/src/main/java/org/springframework/cloud/vault/VaultHealthResponse.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.vault;
+
+import lombok.Data;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Value object to bind HTTP API responses for sys/health
+ *
+ * @author Stuart Ingram
+ * @author Bill Koch
+ */
+@Data
+public class VaultHealthResponse {
+ private boolean initialized;
+ private boolean sealed;
+ private boolean standby;
+ @JsonProperty("server_time_utc")
+ private int serverTimeUtc;
+}