Skip to content

Commit 91a9e81

Browse files
committed
Merged PR #38
1 parent 971a24e commit 91a9e81

File tree

24 files changed

+462
-270
lines changed

24 files changed

+462
-270
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ Once you have initialized a `VaultConfig` object, you can use it to construct an
100100
the `Vault` primary driver class:
101101

102102
```
103-
final Vault vault = new Vault(config);
103+
final Vault vault = Vault.create(config);
104104
```
105105

106106
Key Value Secret Engine Config

src/main/java/io/github/jopenlibs/vault/SslConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ private static String inputStreamToUTF8(final InputStream input) throws IOExcept
699699
}
700700

701701
/**
702-
* <p>There was a community request to make {@link Vault} and its config class serializable
702+
* <p>There was a community request to make {@link VaultImpl} and its config class serializable
703703
* (<a
704704
* href="https://github.com/BetterCloud/vault-java-driver/pull/51">https://github.com/BetterCloud/vault-java-driver/pull/51</a>).
705705
* However, this SslConfig class now contains a member field of type {@link SSLContext}, which

src/main/java/io/github/jopenlibs/vault/Vault.java

Lines changed: 28 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -18,70 +18,11 @@
1818
import java.nio.charset.StandardCharsets;
1919
import java.util.HashMap;
2020
import java.util.Map;
21-
import java.util.logging.Logger;
2221

23-
/**
24-
* <p>The Vault driver class, the primary interface through which dependent applications will
25-
* access Vault.</p>
26-
*
27-
* <p>This driver exposes a DSL, compartmentalizing the various endpoints of the HTTP API (e.g.
28-
* "/", "sys/init", "sys/seal") into separate implementation classes (e.g. <code>Logical</code>,
29-
* <code>Init</code>, etc).</p>
30-
*
31-
* <p>Example usage:</p>
32-
*
33-
* <blockquote>
34-
* <pre>{@code
35-
* final VaultConfig config = new VaultConfig
36-
* .address("http://127.0.0.1:8200")
37-
* .token("eace6676-4d78-c687-4e54-03cad00e3abf")
38-
* .build();
39-
* final Vault vault = new Vault(config);
40-
*
41-
* ...
42-
*
43-
* final Map<String, String> secrets = new HashMap<String, String>();
44-
* secrets.put("value", "world");
45-
* secrets.put("other_value", "You can store multiple name/value pairs under a given key");
46-
*
47-
* final LogicalResponse writeResponse = vault
48-
* .withRetries(5, 1000) // optional
49-
* .logical()
50-
* .write("secret/hello", secrets);
51-
*
52-
* ...
53-
*
54-
* final String value = vault.logical()
55-
* .read("secret/hello")
56-
* .getData().get("value");
57-
* }</pre>
58-
* </blockquote>
59-
*/
60-
public class Vault {
22+
public interface Vault {
6123

62-
private final VaultConfig vaultConfig;
63-
private Logger logger = Logger.getLogger(Vault.class.getCanonicalName());
64-
65-
/**
66-
* Construct a Vault driver instance with the provided config settings.
67-
*
68-
* @param vaultConfig Configuration settings for Vault interaction (e.g. server address, token,
69-
* etc) If the VaultConfig Engine version path map is not supplied in the config, default to
70-
* global KV engine version 2.
71-
*/
72-
public Vault(final VaultConfig vaultConfig) {
73-
this.vaultConfig = vaultConfig;
74-
if (this.vaultConfig.getNameSpace() != null && !this.vaultConfig.getNameSpace().isEmpty()) {
75-
logger.info(String.format(
76-
"The NameSpace %s has been bound to this Vault instance. Please keep this in mind when running operations.",
77-
this.vaultConfig.getNameSpace()));
78-
}
79-
if (this.vaultConfig.getSecretsEnginePathMap().isEmpty()
80-
&& this.vaultConfig.getGlobalEngineVersion() == null) {
81-
logger.info(
82-
"Constructing a Vault instance with no provided Engine version, defaulting to version 2.");
83-
this.vaultConfig.setEngineVersion(2);
84-
}
24+
static Vault create(VaultConfig vaultConfig){
25+
return new VaultImpl(vaultConfig);
8526
}
8627

8728
/**
@@ -93,19 +34,8 @@ public Vault(final VaultConfig vaultConfig) {
9334
* @param engineVersion Which version of the Key/Value Secret Engine to use globally (i.e. 1 or
9435
* 2)
9536
*/
96-
public Vault(final VaultConfig vaultConfig, final Integer engineVersion) {
97-
if (engineVersion < 1 || engineVersion > 2) {
98-
throw new IllegalArgumentException(
99-
"The Engine version must be '1' or '2', the version supplied was: '"
100-
+ engineVersion + "'.");
101-
}
102-
vaultConfig.setEngineVersion(engineVersion);
103-
this.vaultConfig = vaultConfig;
104-
if (this.vaultConfig.getNameSpace() != null && !this.vaultConfig.getNameSpace().isEmpty()) {
105-
logger.info(String.format(
106-
"The Namespace %s has been bound to this Vault instance. Please keep this in mind when running operations.",
107-
this.vaultConfig.getNameSpace()));
108-
}
37+
static Vault create(final VaultConfig vaultConfig, final Integer engineVersion) {
38+
return new VaultImpl(vaultConfig, engineVersion);
10939
}
11040

11141
/**
@@ -121,31 +51,10 @@ public Vault(final VaultConfig vaultConfig, final Integer engineVersion) {
12151
* fallback.
12252
* @throws VaultException If any error occurs
12353
*/
124-
public Vault(final VaultConfig vaultConfig, final Boolean useSecretsEnginePathMap,
54+
static Vault create(final VaultConfig vaultConfig, final Boolean useSecretsEnginePathMap,
12555
final Integer globalFallbackVersion)
12656
throws VaultException {
127-
this.vaultConfig = vaultConfig;
128-
if (this.vaultConfig.getNameSpace() != null && !this.vaultConfig.getNameSpace().isEmpty()) {
129-
logger.info(String.format(
130-
"The Namespace %s has been bound to this Vault instance. Please keep this in mind when running operations.",
131-
this.vaultConfig.getNameSpace()));
132-
}
133-
this.vaultConfig.setEngineVersion(globalFallbackVersion);
134-
if (useSecretsEnginePathMap && this.vaultConfig.getSecretsEnginePathMap().isEmpty()) {
135-
try {
136-
logger.info(
137-
"No secrets Engine version map was supplied, attempting to generate one.");
138-
final Map<String, String> secretsEnginePathMap = collectSecretEngineVersions();
139-
assert secretsEnginePathMap != null;
140-
this.vaultConfig.getSecretsEnginePathMap().putAll(secretsEnginePathMap);
141-
} catch (Exception e) {
142-
throw new VaultException(String.format(
143-
"An Engine KV version map was not supplied, and unable to determine " +
144-
"KV Engine " +
145-
"version, " + "due to exception: %s",
146-
e.getMessage() + ". Do you have admin rights?"));
147-
}
148-
}
57+
return new VaultImpl(vaultConfig, useSecretsEnginePathMap, globalFallbackVersion);
14958
}
15059

15160
/**
@@ -158,30 +67,30 @@ public Vault(final VaultConfig vaultConfig, final Boolean useSecretsEnginePathMa
15867
* between retries
15968
* @return This object, with maxRetries and retryIntervalMilliseconds populated
16069
*/
161-
public Vault withRetries(final int maxRetries, final int retryIntervalMilliseconds) {
162-
this.vaultConfig.setMaxRetries(maxRetries);
163-
this.vaultConfig.setRetryIntervalMilliseconds(retryIntervalMilliseconds);
164-
return this;
165-
}
70+
Vault withRetries(final int maxRetries, final int retryIntervalMilliseconds);
16671

16772
/**
16873
* Returns the implementing class for Vault's core/logical operations (e.g. read, write).
16974
*
17075
* @return The implementing class for Vault's core/logical operations (e.g. read, write)
17176
*/
172-
public Logical logical() {
173-
return new Logical(vaultConfig);
174-
}
77+
Logical logical();
17578

17679
/**
17780
* Returns the implementing class for operations on Vault's <code>/v1/auth/*</code> REST
17881
* endpoints
17982
*
18083
* @return The implementing class for Vault's auth operations.
18184
*/
182-
public Auth auth() {
183-
return new Auth(vaultConfig);
184-
}
85+
Auth auth();
86+
87+
/**
88+
* Returns the implementing class for operations on Vault's <code>/v1/sys/*</code> REST
89+
* endpoints
90+
*
91+
* @return The implementing class for Vault's auth operations.
92+
*/
93+
Sys sys();
18594

18695
/**
18796
* Returns the implementing class for operations on Vault's <code>/v1/sys/*</code> REST
@@ -199,9 +108,7 @@ public Sys sys() {
199108
*
200109
* @return The implementing class for Vault's PKI secret backend.
201110
*/
202-
public Pki pki() {
203-
return new Pki(vaultConfig);
204-
}
111+
Pki pki();
205112

206113
/**
207114
* <p>Returns the implementing class for Vault's PKI secret backend, using a custom path when
@@ -214,7 +121,7 @@ public Pki pki() {
214121
* <blockquote>
215122
* <pre>{@code
216123
* final VaultConfig config = new VaultConfig().address(...).token(...).build();
217-
* final Vault vault = new Vault(config);
124+
* final Vault vault = Vault.create(config);
218125
* final PkiResponse response = vault.pki("root-ca").createOrUpdateRole("testRole");
219126
*
220127
* assertEquals(204, response.getRestResponse().getStatus());
@@ -225,112 +132,37 @@ public Pki pki() {
225132
* <code>/v1/</code> prefix
226133
* @return The implementing class for Vault's PKI secret backend.
227134
*/
228-
public Pki pki(final String mountPath) {
229-
return new Pki(vaultConfig, mountPath);
230-
}
135+
Pki pki(final String mountPath);
231136

232-
public Database database() {
233-
return new Database(vaultConfig);
234-
}
137+
Database database();
235138

236-
public Database database(final String mountPath) {
237-
return new Database(vaultConfig, mountPath);
238-
}
139+
Database database(final String mountPath);
239140

240141
/**
241142
* @see Sys#leases()
242143
* @deprecated This method is deprecated and in future it will be removed
243144
*/
244-
public Leases leases() {
245-
return new Leases(vaultConfig);
246-
}
145+
Leases leases();
247146

248147
/**
249148
* Returns the implementing class for Vault's debug operations (e.g. raw, health).
250149
*
251150
* @return The implementing class for Vault's debug operations (e.g. raw, health)
252151
*/
253-
public Debug debug() {
254-
return new Debug(vaultConfig);
255-
}
152+
Debug debug();
256153

257154
/**
258155
* @see Sys#mounts()
259156
* @deprecated This method is deprecated and in future it will be removed
260157
*/
261-
public Mounts mounts() {
262-
return new Mounts(vaultConfig);
263-
}
158+
Mounts mounts();
264159

265160
/**
266161
* @see Sys#seal()
267162
* @deprecated This method is deprecated and in future it will be removed
268163
*/
269-
public Seal seal() {
270-
return new Seal(vaultConfig);
271-
}
272-
273-
/**
274-
* Makes a REST call to Vault, to collect information on which secret engine version (if any) is
275-
* used by each available mount point. Possibilities are:
276-
*
277-
* <ul>
278-
* <li>"2" - A mount point running on Vault 0.10 or higher, configured to use the engine 2
279-
* API</li>
280-
* <li>"1" - A mount point running on Vault 0.10 or higher, configured to use the engine 1
281-
* API</li>
282-
* <li>"unknown" - A mount point running on an older version of Vault. Can more or less be
283-
* treated as "1".</li>
284-
* </ul>
285-
* <p>
286-
* IMPORTANT: Whichever authentication mechanism is being used with the
287-
* <code>VaultConfig</code> object, that principal needs permission to access the
288-
* <code>/v1/sys/mounts</code> REST endpoint.
289-
*
290-
* @return A map of mount points (e.g. "/secret") to secret engine version numbers (e.g. "2")
291-
*/
292-
private Map<String, String> collectSecretEngineVersions() {
293-
try {
294-
final RestResponse restResponse = new Rest()//NOPMD
295-
.url(vaultConfig.getAddress() + "/v1/sys/mounts")
296-
.header("X-Vault-Token", vaultConfig.getToken())
297-
.header("X-Vault-Namespace", this.vaultConfig.getNameSpace())
298-
.header("X-Vault-Request", "true")
299-
.connectTimeoutSeconds(vaultConfig.getOpenTimeout())
300-
.readTimeoutSeconds(vaultConfig.getReadTimeout())
301-
.sslVerification(vaultConfig.getSslConfig().isVerify())
302-
.sslContext(vaultConfig.getSslConfig().getSslContext())
303-
.get();
304-
if (restResponse.getStatus() != 200) {
305-
return null;
306-
}
307-
308-
final String jsonString = new String(restResponse.getBody(), StandardCharsets.UTF_8);
309-
final Map<String, String> data = new HashMap<>();
310-
final JsonObject jsonData = Json.parse(jsonString).asObject().get("data").asObject();
311-
for (JsonObject.Member member : jsonData) {
312-
final String name = member.getName();
313-
String version = "unknown";
164+
Seal seal();
314165

315-
final JsonValue options = member.getValue().asObject().get("options");
316-
if (options != null && options.isObject()) {
317-
final JsonValue ver = options.asObject().get("version");
318-
if (ver != null && ver.isString()) {
319-
version = ver.asString();
320-
}
321-
}
322-
data.put(name, version);
323-
}
324-
return data;
325-
} catch (RestException e) {
326-
System.err.print(
327-
String.format("Unable to retrieve the KV Engine secrets, due to exception: %s",
328-
e.getMessage()));
329-
return null;
330-
}
331-
}
166+
Map<String, String> getSecretEngineVersions();
332167

333-
public Map<String, String> getSecretEngineVersions() {
334-
return this.collectSecretEngineVersions();
335-
}
336168
}

0 commit comments

Comments
 (0)