Health status query and response model implemented (#15)
This commit is contained in:
parent
23419e94f1
commit
df7de5dd73
@ -1,3 +1,6 @@
|
||||
## 0.7.0 [work in progress]
|
||||
* [feature] Retrieval of health status via `getHealth()`
|
||||
|
||||
## 0.6.2 [2017-08-19]
|
||||
* [fix] Prevent potential NPE on SecretResponse getter
|
||||
* [fix] Removed stack traces on PUT request and response deserialization (#13)
|
||||
|
2
pom.xml
2
pom.xml
@ -4,7 +4,7 @@
|
||||
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>connector</artifactId>
|
||||
<version>0.6.2</version>
|
||||
<version>0.7.0-SNAPSHOT</version>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
@ -59,6 +59,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
private static final String PATH_AUTH_APPID = "auth/app-id/";
|
||||
private static final String PATH_AUTH_APPROLE = "auth/approle/";
|
||||
private static final String PATH_REVOKE = "sys/revoke/";
|
||||
private static final String PATH_HEALTH = "sys/health";
|
||||
|
||||
private static final String HEADER_VAULT_TOKEN = "X-Vault-Token";
|
||||
|
||||
@ -249,6 +250,25 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HealthResponse getHealth() throws VaultConnectorException {
|
||||
/* Force status code to be 200, so we don't need to modify the request sequence. */
|
||||
Map<String, String> param = new HashMap<>();
|
||||
param.put("standbycode", "200"); // Default: 429.
|
||||
param.put("sealedcode", "200"); // Default: 503.
|
||||
param.put("uninitcode", "200"); // Default: 501.
|
||||
try {
|
||||
String response = requestGet(PATH_HEALTH, param);
|
||||
/* Parse response */
|
||||
return jsonMapper.readValue(response, HealthResponse.class);
|
||||
} catch (IOException e) {
|
||||
throw new InvalidResponseException("Unable to parse response", e);
|
||||
} catch (URISyntaxException e) {
|
||||
/* this should never occur and may leak sensible information */
|
||||
throw new InvalidRequestException("Invalid URI format");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isAuthorized() {
|
||||
return authorized && (tokenTTL == 0 || tokenTTL >= System.currentTimeMillis());
|
||||
|
@ -71,6 +71,15 @@ public interface VaultConnector extends AutoCloseable {
|
||||
return unseal(key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query server health information.
|
||||
*
|
||||
* @return Health information.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.7.0
|
||||
*/
|
||||
HealthResponse getHealth() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Get all availale authentication backends.
|
||||
*
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2016-2017 Stefan Kalscheuer
|
||||
*
|
||||
* 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 de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Vault response for health query.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class HealthResponse implements VaultResponse {
|
||||
@JsonProperty("cluster_id")
|
||||
private String clusterID;
|
||||
|
||||
@JsonProperty("cluster_name")
|
||||
private String clusterName;
|
||||
|
||||
@JsonProperty("version")
|
||||
private String version;
|
||||
|
||||
@JsonProperty("server_time_utc")
|
||||
private Long serverTimeUTC;
|
||||
|
||||
@JsonProperty("standby")
|
||||
private Boolean standby;
|
||||
|
||||
@JsonProperty("sealed")
|
||||
private Boolean sealed;
|
||||
|
||||
@JsonProperty("initialized")
|
||||
private Boolean initialized;
|
||||
|
||||
/**
|
||||
* @return The Cluster ID.
|
||||
*/
|
||||
public String getClusterID() {
|
||||
return clusterID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Cluster name.
|
||||
*/
|
||||
public String getClusterName() {
|
||||
return clusterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Vault version.
|
||||
*/
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server time UTC (timestamp).
|
||||
*/
|
||||
public Long getServerTimeUTC() {
|
||||
return serverTimeUTC;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server standby status.
|
||||
*/
|
||||
public Boolean isStandby() {
|
||||
return standby;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server seal status.
|
||||
*/
|
||||
public Boolean isSealed() {
|
||||
return sealed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server initialization status.
|
||||
*/
|
||||
public Boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
}
|
@ -48,6 +48,7 @@ import static org.junit.Assume.*;
|
||||
* @since 0.1
|
||||
*/
|
||||
public class HTTPVaultConnectorTest {
|
||||
private static String VAULT_VERISON = "0.8.1"; // the vault version this test is supposed to run against
|
||||
private static String KEY = "81011a8061e5c028bd0d9503eeba40bd9054b9af0408d080cb24f57405c27a61";
|
||||
private static String TOKEN_ROOT = "d1bd50e2-587b-6e68-d80b-a9a507625cb7";
|
||||
private static String USER_VALID = "validUser";
|
||||
@ -135,6 +136,36 @@ public class HTTPVaultConnectorTest {
|
||||
assertThat("Vault not unsealed", sealStatus.isSealed(), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test health status
|
||||
*/
|
||||
@Test
|
||||
public void healthTest() {
|
||||
HealthResponse res = null;
|
||||
try {
|
||||
res = connector.getHealth();
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Retrieving health status failed: " + e.getMessage());
|
||||
}
|
||||
assertThat("Health response should be set", res, is(notNullValue()));
|
||||
assertThat("Unexpected version", res.getVersion(), is(VAULT_VERISON));
|
||||
assertThat("Unexpected init status", res.isInitialized(), is(true));
|
||||
assertThat("Unexpected seal status", res.isSealed(), is(false));
|
||||
assertThat("Unexpected standby status", res.isStandby(), is(false));
|
||||
|
||||
// No seal vault and verify correct status.
|
||||
authRoot();
|
||||
connector.seal();
|
||||
assumeTrue(connector.sealStatus().isSealed());
|
||||
connector.resetAuth(); // SHould work unauthenticated
|
||||
try {
|
||||
res = connector.getHealth();
|
||||
} catch (VaultConnectorException e) {
|
||||
fail("Retrieving health status failed when sealed: " + e.getMessage());
|
||||
}
|
||||
assertThat("Unexpected seal status", res.isSealed(), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test listing of authentication backends
|
||||
*/
|
||||
|
@ -0,0 +1,56 @@
|
||||
package de.stklcode.jvault.connector.model.response;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* JUnit Test for {@link AuthResponse} model.
|
||||
*
|
||||
* @author Stefan Kalscheuer
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class HealthResponseTest {
|
||||
private static final String CLUSTER_ID = "c9abceea-4f46-4dab-a688-5ce55f89e228";
|
||||
private static final String CLUSTER_NAME = "vault-cluster-5515c810";
|
||||
private static final String VERSION = "0.6.2";
|
||||
private static final Long SERVER_TIME_UTC = 1469555798L;
|
||||
private static final Boolean STANDBY = false;
|
||||
private static final Boolean SEALED = false;
|
||||
private static final Boolean INITIALIZED = true;
|
||||
|
||||
private static final String RES_JSON = "{\n" +
|
||||
" \"cluster_id\": \"" + CLUSTER_ID + "\",\n" +
|
||||
" \"cluster_name\": \"" + CLUSTER_NAME + "\",\n" +
|
||||
" \"version\": \"" + VERSION + "\",\n" +
|
||||
" \"server_time_utc\": " + SERVER_TIME_UTC + ",\n" +
|
||||
" \"standby\": " + STANDBY + ",\n" +
|
||||
" \"sealed\": " + SEALED + ",\n" +
|
||||
" \"initialized\": " + INITIALIZED + "\n" +
|
||||
"}";
|
||||
/**
|
||||
* Test creation from JSON value as returned by Vault (JSON example copied from Vault documentation).
|
||||
*/
|
||||
@Test
|
||||
public void jsonRoundtrip() {
|
||||
try {
|
||||
HealthResponse res = new ObjectMapper().readValue(RES_JSON, HealthResponse.class);
|
||||
assertThat("Parsed response is NULL", res, is(notNullValue()));
|
||||
assertThat("Incorrect cluster ID", res.getClusterID(), is(CLUSTER_ID));
|
||||
assertThat("Incorrect cluster name", res.getClusterName(), is(CLUSTER_NAME));
|
||||
assertThat("Incorrect version", res.getVersion(), is(VERSION));
|
||||
assertThat("Incorrect server time", res.getServerTimeUTC(), is(SERVER_TIME_UTC));
|
||||
assertThat("Incorrect standby state", res.isStandby(), is(STANDBY));
|
||||
assertThat("Incorrect seal state", res.isSealed(), is(SEALED));
|
||||
assertThat("Incorrect initialization state", res.isInitialized(), is(INITIALIZED));
|
||||
} catch (IOException e) {
|
||||
fail("Health deserialization failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user