10 Commits

Author SHA1 Message Date
bbceee35f2 test against Vault 1.8.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-07-28 19:38:06 +02:00
3a920fe960 prepare release 0.9.5
All checks were successful
continuous-integration/drone/push Build is passing
2021-07-28 19:34:48 +02:00
eed61c4569 minor dependency updates
All checks were successful
continuous-integration/drone/push Build is passing
2021-07-27 21:25:20 +02:00
53d954ea12 deprecate all convenience methods to interact with "secret/" mount
All checks were successful
continuous-integration/drone/push Build is passing
Follow-up deprecation for the not yet deprecated wrapper methods.
2021-06-12 10:46:10 +02:00
e578591a49 deprecate convenience methods to interact with "secret/" mount (#52)
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-11 21:33:59 +02:00
de17f48be2 move builder into main package, introduce new invocation method (#51)
Some checks failed
continuous-integration/drone/push Build is failing
The builder is target of major refactoring in the 1.0 development branch
so we introduce some delegate classes and methods to prepare migration.
2021-06-11 21:15:49 +02:00
5f9950e048 prepare release 0.9.4
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-06 12:22:13 +02:00
e2c439379e switch to "main" as default branch name
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-06 12:09:28 +02:00
ce33d37396 minor dependency updates; test against Vault 1.7.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-06 12:07:02 +02:00
bdf4fc4b83 fix typo in method AppRole.Builder#wit0hTokenPeriod (#49) 2021-06-06 12:02:01 +02:00
16 changed files with 444 additions and 326 deletions

View File

@ -8,7 +8,7 @@ steps:
- mvn -B clean compile
when:
branch:
- master
- main
- develop
- feature/*
- fix/*
@ -25,15 +25,15 @@ steps:
- name: unit-integration-tests
image: maven:3-jdk-11
environment:
VAULT_VERSION: 1.7.0
VAULT_VERSION: 1.8.0
commands:
- curl -s -o vault_1.7.0_linux_amd64.zip https://releases.hashicorp.com/vault/1.7.0/vault_1.7.0_linux_amd64.zip
- curl -s https://releases.hashicorp.com/vault/1.7.0/vault_1.7.0_SHA256SUMS | grep linux_amd64 | sha256sum -c
- unzip vault_1.7.0_linux_amd64.zip
- rm vault_1.7.0_linux_amd64.zip
- curl -s -o vault_1.8.0_linux_amd64.zip https://releases.hashicorp.com/vault/1.8.0/vault_1.8.0_linux_amd64.zip
- curl -s https://releases.hashicorp.com/vault/1.8.0/vault_1.8.0_SHA256SUMS | grep linux_amd64 | sha256sum -c
- unzip vault_1.8.0_linux_amd64.zip
- rm vault_1.8.0_linux_amd64.zip
- mv vault /bin/
- mvn -B resources:testResources compiler:testCompile surefire:test
when:
branch:
- master
- main
- release/*

View File

@ -7,7 +7,7 @@ addons:
secure: "sM9OfX5jW764pn9cb2LSXArnXucKMws+eGeg5NnZxHRcGYt4hpBKLSregBSsBNzUoWVj0zNzPCpnh+UQvgxQzUerOqwEdjTBpy3SNPaxSn7UpoSg+Wz3aUmL9ugmx01b51/wMG4UCHEwTZt2tpgTPVtw8K6uSO78e0dSICCBHDnRcdQwOjMEQHIJJ/qHVRwuy/MzLCAP3W1JPZlsphZg9QsFyhB4hW97dE90joZezfocQIv2xI/r6k+BLz0pY6MxYCul0RiDumaiaej0CPvEJI/uSu//BAQjUdHw+mQgnKUYIbrn2ONOviwNfwdr94JyoZEN2B6zASUmNLjPf4AbIojDeyS+CrpQpm17EVm/Qk/Ds+Xra4PPPIcsZhiWzV0KoDUz9xLfXuRJ526VT5tDPiaeI7oETf0+8l+JIS1b399FyqHi7smzjpvC6GuKflQrbuHK4MuKzDh7WTHiqokGG4SS0wOQIaaHB3dfdwwQzPh6IM24e8CETxh3DjMeqUTU4DWmv5po55jZ934TtxVQvVN78bTG9O0zS9u+JmRY04OZ+OaXuFam6MfMUFQi0EPZzdGul/oWSibGUu3bNfVEBp60CnJwYNM/dKG6U7pJthLHvSwiQFOdKzHZ+l1jZJ4gPaXaIGqpwqVGr28ntqA/El1rytPixr2driE6bYMt5jw="
env:
- PATH=$PATH:. VAULT_VERSION=1.7.0 ANALYSIS=false
- PATH=$PATH:. VAULT_VERSION=1.8.0 ANALYSIS=false
cache:
directories:
@ -18,12 +18,12 @@ jobs:
include:
- jdk: openjdk8
- jdk: openjdk11
env: PATH=$PATH:. VAULT_VERSION=1.7.0 ANALYSIS=true
env: PATH=$PATH:. VAULT_VERSION=1.8.0 ANALYSIS=true
- jdk: openjdk16
before_script:
- |
if [[ "$TRAVIS_BRANCH" =~ ^master|(release\/.+)$ ]]; then
if [[ "$TRAVIS_BRANCH" =~ ^main|(release\/.+)$ ]]; then
wget -q https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip
wget -q -O - https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_SHA256SUMS | grep linux_amd64 | sha256sum -c
unzip vault_${VAULT_VERSION}_linux_amd64.zip
@ -33,7 +33,7 @@ before_script:
script:
- mvn -B clean compile
- |
if [[ "$TRAVIS_BRANCH" =~ ^master|(release\/.+)$ ]]; then
if [[ "$TRAVIS_BRANCH" =~ ^main|(release\/.+)$ ]]; then
mvn -B resources:testResources compiler:testCompile surefire:test -P coverage
else
mvn -B resources:testResources compiler:testCompile surefire:test -P coverage -P offline-tests

View File

@ -1,3 +1,29 @@
## 0.9.5 (2021-07-28)
### Deprecations
* Deprecate ` {read,write,delete}Secret()` convenience methods. Use `{read,write,delete}("secret/...")` instead (#52)
* Deprecated builder invocation `VaultConnectorBuilder.http()` in favor of `HTTPVaultConnector.builder()` (#51)
* Deprecated `de.stklcode.jvault.connector.builder.HTTPVaultConnectorBuilder` in favor of `de.stklcode.jvault.connector.HTTPVaultConnectorBuilder` (only package changed) (#51)
Old builders will be removed in 1.0
### Improvements
* Minor dependency updates
### Test
* Tested against Vault 1.8.0
## 0.9.4 (2021-06-06)
### Deprecations
* `AppRole.Builder#wit0hTokenPeriod()` is deprecated in favor of `#withTokenPeriod()` (#49)
### Improvements
* Minor dependency updates
### Test
* Tested against Vault 1.7.2
## 0.9.3 (2021-04-02)
### Improvements

View File

@ -1,11 +1,11 @@
# Java Vault Connector
[![Build Status](https://travis-ci.com/stklcode/jvaultconnector.svg?branch=master)](https://travis-ci.com/stklcode/jvaultconnector)
[![Build Status](https://travis-ci.com/stklcode/jvaultconnector.svg?branch=main)](https://travis-ci.com/stklcode/jvaultconnector)
[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=de.stklcode.jvault%3Ajvault-connector&metric=alert_status)](https://sonarcloud.io/dashboard?id=de.stklcode.jvault%3Ajvault-connector)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/stklcode/jvaultconnector/blob/master/LICENSE.txt)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/stklcode/jvaultconnector/blob/main/LICENSE.txt)
[![Maven Central](https://img.shields.io/maven-central/v/de.stklcode.jvault/jvault-connector.svg)](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22de.stklcode.jvault%22%20AND%20a%3A%22jvault-connector%22)
![Logo](https://raw.githubusercontent.com/stklcode/jvaultconnector/master/assets/logo.png)
![Logo](https://raw.githubusercontent.com/stklcode/jvaultconnector/main/assets/logo.png)
Java Vault Connector is a connector library for [Vault](https://www.vaultproject.io) by [Hashicorp](https://www.hashicorp.com) written in Java. The connector allows simple usage of Vault's secret store in own applications.
@ -32,7 +32,7 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
* SQL secret handling
* KV v1 and v2 support
* Connector Factory with builder pattern
* Tested against Vault 1.7.0
* Tested against Vault 1.8.0
## Maven Artifact
@ -40,7 +40,7 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
<dependency>
<groupId>de.stklcode.jvault</groupId>
<artifactId>jvault-connector</artifactId>
<version>0.9.3</version>
<version>0.9.5</version>
</dependency>
```
@ -50,21 +50,21 @@ Java Vault Connector is a connector library for [Vault](https://www.vaultproject
```java
// Instantiate using builder pattern style factory (TLS enabled by default)
VaultConnector vault = VaultConnectorBuilder.http()
VaultConnector vault = HTTPVaultConnector.builder()
.withHost("127.0.0.1")
.withPort(8200)
.withTLS()
.build();
// Instantiate with custom SSL context
VaultConnector vault = VaultConnectorBuilder.http()
VaultConnector vault = HTTPVaultConnector.builder()
.withHost("example.com")
.withPort(8200)
.withTrustedCA(Paths.get("/path/to/CA.pem"))
.build();
// Initialization from environment variables
VaultConnector vault = VaultConnectorBuilder.http()
VaultConnector vault = HTTPVaultConnector.builder()
.fromEnv()
.build();
```

31
pom.xml
View File

@ -4,7 +4,7 @@
<groupId>de.stklcode.jvault</groupId>
<artifactId>jvault-connector</artifactId>
<version>0.9.3</version>
<version>0.9.5</version>
<packaging>jar</packaging>
@ -113,13 +113,13 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.2</version>
<version>2.12.4</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.7.1</version>
<version>5.7.2</version>
<scope>test</scope>
</dependency>
<dependency>
@ -128,16 +128,10 @@
<version>2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.8.0</version>
<version>3.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
@ -149,7 +143,7 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
<version>2.11.0</version>
<scope>test</scope>
</dependency>
</dependencies>
@ -159,7 +153,7 @@
<dependency>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.8.0.2131</version>
<version>3.9.0.2155</version>
</dependency>
</dependencies>
</dependencyManagement>
@ -200,7 +194,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<version>3.3.0</version>
<configuration>
<source>1.8</source>
</configuration>
@ -224,7 +218,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<version>3.0.1</version>
<executions>
<execution>
<id>sign-artifacts</id>
@ -249,17 +243,16 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
<version>0.8.7</version>
<executions>
<execution>
<id>prepare-agent</id>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<id>default-report</id>
<goals>
<goal>report</goal>
</goals>
@ -294,7 +287,7 @@
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>6.1.5</version>
<version>6.2.2</version>
<executions>
<execution>
<goals>

View File

@ -71,6 +71,16 @@ public class HTTPVaultConnector implements VaultConnector {
private String token; // Current token.
private long tokenTTL = 0; // Expiration time for current token.
/**
* Get a new builder for a connector.
*
* @return Builder instance.
* @since 0.9.5
*/
public static HTTPVaultConnectorBuilder builder() {
return new HTTPVaultConnectorBuilder();
}
/**
* Create connector using hostname and schema.
*

View File

@ -0,0 +1,299 @@
/*
* Copyright 2016-2021 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;
import de.stklcode.jvault.connector.builder.VaultConnectorBuilder;
import de.stklcode.jvault.connector.exception.ConnectionException;
import de.stklcode.jvault.connector.exception.TlsException;
import de.stklcode.jvault.connector.exception.VaultConnectorException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
/**
* Vault Connector Builder implementation for HTTP Vault connectors.
*
* @author Stefan Kalscheuer
* @since 0.8.0
* @since 0.9.5 Package {@link de.stklcode.jvault.connector}
*/
public class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
private static final String ENV_VAULT_ADDR = "VAULT_ADDR";
private static final String ENV_VAULT_CACERT = "VAULT_CACERT";
private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN";
private static final String ENV_VAULT_MAX_RETRIES = "VAULT_MAX_RETRIES";
public static final String DEFAULT_HOST = "127.0.0.1";
public static final Integer DEFAULT_PORT = 8200;
public static final boolean DEFAULT_TLS = true;
public static final String DEFAULT_TLS_VERSION = "TLSv1.2";
public static final String DEFAULT_PREFIX = "/v1/";
public static final int DEFAULT_NUMBER_OF_RETRIES = 0;
private String host;
private Integer port;
private boolean tls;
private String tlsVersion;
private String prefix;
private X509Certificate trustedCA;
private int numberOfRetries;
private Integer timeout;
private String token;
/**
* Default empty constructor.
* Initializes factory with default values.
*/
public HTTPVaultConnectorBuilder() {
host = DEFAULT_HOST;
port = DEFAULT_PORT;
tls = DEFAULT_TLS;
tlsVersion = DEFAULT_TLS_VERSION;
prefix = DEFAULT_PREFIX;
numberOfRetries = DEFAULT_NUMBER_OF_RETRIES;
}
/**
* Set hostname (default: 127.0.0.1).
*
* @param host Hostname or IP address
* @return self
*/
public HTTPVaultConnectorBuilder withHost(final String host) {
this.host = host;
return this;
}
/**
* Set port (default: 8200).
*
* @param port Vault TCP port
* @return self
*/
public HTTPVaultConnectorBuilder withPort(final Integer port) {
this.port = port;
return this;
}
/**
* Set TLS usage (default: TRUE).
*
* @param useTLS use TLS or not
* @return self
*/
public HTTPVaultConnectorBuilder withTLS(final boolean useTLS) {
this.tls = useTLS;
return this;
}
/**
* Set TLS usage (default: TRUE).
*
* @param useTLS Use TLS or not.
* @param version Supported TLS version ({@code TLSv1.2}, {@code TLSv1.1}, {@code TLSv1.0}, {@code TLS}).
* @return self
* @since 0.8 Added version parameter (#22).
*/
public HTTPVaultConnectorBuilder withTLS(final boolean useTLS, final String version) {
this.tls = useTLS;
this.tlsVersion = version;
return this;
}
/**
* Convenience Method for TLS usage (enabled by default).
*
* @param version Supported TLS version ({@code TLSv1.2}, {@code TLSv1.1}, {@code TLSv1.0}, {@code TLS}).
* @return self
* @since 0.8 Added version parameter (#22).
*/
public HTTPVaultConnectorBuilder withTLS(final String version) {
return withTLS(true, version);
}
/**
* Convenience Method for TLS usage (enabled by default).
*
* @return self
*/
public HTTPVaultConnectorBuilder withTLS() {
return withTLS(true);
}
/**
* Convenience Method for NOT using TLS.
*
* @return self
*/
public HTTPVaultConnectorBuilder withoutTLS() {
return withTLS(false);
}
/**
* Set API prefix. Default is "/v1/" and changes should not be necessary for current state of development.
*
* @param prefix Vault API prefix (default: "/v1/"
* @return self
*/
public HTTPVaultConnectorBuilder withPrefix(final String prefix) {
this.prefix = prefix;
return this;
}
/**
* Add a trusted CA certificate for HTTPS connections.
*
* @param cert path to certificate file
* @return self
* @throws VaultConnectorException on error
* @since 0.4.0
*/
public HTTPVaultConnectorBuilder withTrustedCA(final Path cert) throws VaultConnectorException {
if (cert != null) {
return withTrustedCA(certificateFromFile(cert));
} else {
this.trustedCA = null;
}
return this;
}
/**
* Add a trusted CA certificate for HTTPS connections.
*
* @param cert path to certificate file
* @return self
* @since 0.8.0
*/
public HTTPVaultConnectorBuilder withTrustedCA(final X509Certificate cert) {
this.trustedCA = cert;
return this;
}
/**
* Set token for automatic authentication, using {@link #buildAndAuth()}.
*
* @param token Vault token
* @return self
* @since 0.6.0
*/
public HTTPVaultConnectorBuilder withToken(final String token) {
this.token = token;
return this;
}
/**
* Build connector based on the {@code }VAULT_ADDR} and {@code VAULT_CACERT} (optional) environment variables.
*
* @return self
* @throws VaultConnectorException if Vault address from environment variables is malformed
* @since 0.6.0
*/
public HTTPVaultConnectorBuilder fromEnv() throws VaultConnectorException {
/* Parse URL from environment variable */
if (System.getenv(ENV_VAULT_ADDR) != null && !System.getenv(ENV_VAULT_ADDR).trim().isEmpty()) {
try {
URL url = new URL(System.getenv(ENV_VAULT_ADDR));
this.host = url.getHost();
this.port = url.getPort();
this.tls = url.getProtocol().equals("https");
} catch (MalformedURLException e) {
throw new ConnectionException("URL provided in environment variable malformed", e);
}
}
/* Read number of retries */
if (System.getenv(ENV_VAULT_MAX_RETRIES) != null) {
try {
numberOfRetries = Integer.parseInt(System.getenv(ENV_VAULT_MAX_RETRIES));
} catch (NumberFormatException ignored) {
/* Ignore malformed values. */
}
}
/* Read token */
token = System.getenv(ENV_VAULT_TOKEN);
/* Parse certificate, if set */
if (System.getenv(ENV_VAULT_CACERT) != null && !System.getenv(ENV_VAULT_CACERT).trim().isEmpty()) {
return withTrustedCA(Paths.get(System.getenv(ENV_VAULT_CACERT)));
}
return this;
}
/**
* Define the number of retries to attempt on 5xx errors.
*
* @param numberOfRetries The number of retries to attempt on 5xx errors (default: 0)
* @return self
* @since 0.6.0
*/
public HTTPVaultConnectorBuilder withNumberOfRetries(final int numberOfRetries) {
this.numberOfRetries = numberOfRetries;
return this;
}
/**
* Define a custom timeout for the HTTP connection.
*
* @param milliseconds Timeout value in milliseconds.
* @return self
* @since 0.6.0
*/
public HTTPVaultConnectorBuilder withTimeout(final int milliseconds) {
this.timeout = milliseconds;
return this;
}
@Override
public HTTPVaultConnector build() {
return new HTTPVaultConnector(host, tls, tlsVersion, port, prefix, trustedCA, numberOfRetries, timeout);
}
@Override
public HTTPVaultConnector buildAndAuth() throws VaultConnectorException {
if (token == null) {
throw new ConnectionException("No vault token provided, unable to authenticate.");
}
HTTPVaultConnector con = build();
con.authToken(token);
return con;
}
/**
* Read given certificate file to X.509 certificate.
*
* @param certFile Path to certificate file
* @return X.509 Certificate object
* @throws TlsException on error
* @since 0.4.0
*/
private X509Certificate certificateFromFile(final Path certFile) throws TlsException {
try (InputStream is = Files.newInputStream(certFile)) {
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
} catch (IOException | CertificateException e) {
throw new TlsException("Unable to read certificate.", e);
}
}
}

View File

@ -401,7 +401,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param key Secret identifier
* @return Secret response
* @throws VaultConnectorException on error
* @deprecated Convenience method will be removed in 1.0. Use {@link #read(String)} instead with key prefix "secret/".
*/
@Deprecated
default SecretResponse readSecret(final String key) throws VaultConnectorException {
return read(PATH_SECRET + "/" + key);
}
@ -448,7 +450,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @return Metadata for the created/updated secret.
* @throws VaultConnectorException on error
* @since 0.8
* @deprecated Convenience method will be removed in 1.0. Use {@link #writeSecretData(String, String, Map)} instead with mount parameter "secret".
*/
@Deprecated
default SecretVersionResponse writeSecretData(final String key, final Map<String, Object> data) throws VaultConnectorException {
return writeSecretData(PATH_SECRET, key, data, null);
}
@ -497,7 +501,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @return Secret response
* @throws VaultConnectorException on error
* @since 0.8
* @deprecated Convenience method will be removed in 1.0. Use {@link #readSecretVersion(String, String, Integer)} instead with mount parameter "secret".
*/
@Deprecated
default SecretResponse readSecretVersion(final String key, final Integer version) throws VaultConnectorException {
return readSecretVersion(PATH_SECRET, key, version);
}
@ -526,7 +532,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @return Metadata response
* @throws VaultConnectorException on error
* @since 0.8
* @deprecated Convenience method will be removed in 1.0. Use {@link #readSecretMetadata(String, String)} instead with mount parameter "secret".
*/
@Deprecated
default MetadataResponse readSecretMetadata(final String key) throws VaultConnectorException {
return readSecretMetadata(PATH_SECRET, key);
}
@ -542,7 +550,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param casRequired Specify if Check-And-Set is required for this secret.
* @throws VaultConnectorException on error
* @since 0.8
* @deprecated Convenience method will be removed in 1.0. Use {@link #updateSecretMetadata(String, String, Integer, boolean)} instead with mount parameter "secret".
*/
@Deprecated
default void updateSecretMetadata(final String key, final Integer maxVersions, final boolean casRequired) throws VaultConnectorException {
updateSecretMetadata(PATH_SECRET, key, maxVersions, casRequired);
}
@ -594,7 +604,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param path Root path to search
* @return List of secret keys
* @throws VaultConnectorException on error
* @deprecated Convenience method will be removed in 1.0. Use {@link #list(String)} instead with key prefix "secret/".
*/
@Deprecated
default List<String> listSecrets(final String path) throws VaultConnectorException {
return list(PATH_SECRET + "/" + path);
}
@ -642,7 +654,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param key Secret path
* @param value Secret value
* @throws VaultConnectorException on error
* @deprecated Convenience method will be removed in 1.0. Use {@link #write(String, String)} instead with key prefix "secret/".
*/
@Deprecated
default void writeSecret(final String key, final String value) throws VaultConnectorException {
writeSecret(key, Collections.singletonMap("value", value));
}
@ -656,7 +670,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param data Secret content. Value must be be JSON serializable.
* @throws VaultConnectorException on error
* @since 0.5.0
* @deprecated Convenience method will be removed in 1.0. Use {@link #write(String, Map)} instead with key prefix "secret/".
*/
@Deprecated
default void writeSecret(final String key, final Map<String, Object> data) throws VaultConnectorException {
if (key == null || key.isEmpty()) {
throw new InvalidRequestException("Secret path must not be empty.");
@ -680,7 +696,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
*
* @param key Secret path
* @throws VaultConnectorException on error
* @deprecated Convenience method will be removed in 1.0. Use {@link #delete(String)} instead with key prefix "secret/".
*/
@Deprecated
default void deleteSecret(final String key) throws VaultConnectorException {
delete(PATH_SECRET + "/" + key);
}
@ -693,7 +711,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param key Secret path.
* @throws VaultConnectorException on error
* @since 0.8
* @deprecated Convenience method will be removed in 1.0. Use {@link #deleteLatestSecretVersion(String, String)} instead with mount parameter "secret".
*/
@Deprecated
default void deleteLatestSecretVersion(final String key) throws VaultConnectorException {
deleteLatestSecretVersion(PATH_SECRET, key);
}
@ -719,7 +739,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param key Secret path.
* @throws VaultConnectorException on error
* @since 0.8
* @deprecated Convenience method will be removed in 1.0. Use {@link #deleteAllSecretVersions(String)} instead with mount parameter "secret".
*/
@Deprecated
default void deleteAllSecretVersions(final String key) throws VaultConnectorException {
deleteAllSecretVersions(PATH_SECRET, key);
}
@ -746,7 +768,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param versions Versions of the secret to delete.
* @throws VaultConnectorException on error
* @since 0.8
* @deprecated Convenience method will be removed in 1.0. Use {@link #deleteSecretVersions(String, String, int...)} instead with mount parameter "secret".
*/
@Deprecated
default void deleteSecretVersions(final String key, final int... versions) throws VaultConnectorException {
deleteSecretVersions(PATH_SECRET, key, versions);
}
@ -772,7 +796,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param versions Versions of the secret to undelete.
* @throws VaultConnectorException on error
* @since 0.8
* @deprecated Convenience method will be removed in 1.0. Use {@link #undeleteSecretVersions(String, String, int...)} instead with mount parameter "secret".
*/
@Deprecated
default void undeleteSecretVersions(final String key, final int... versions) throws VaultConnectorException {
undeleteSecretVersions(PATH_SECRET, key, versions);
}
@ -797,7 +823,9 @@ public interface VaultConnector extends AutoCloseable, Serializable {
* @param versions Versions of the secret to destroy.
* @throws VaultConnectorException on error
* @since 0.8
* @deprecated Convenience method will be removed in 1.0. Use {@link #destroySecretVersions(String, String, int...)} instead with mount parameter "secret".
*/
@Deprecated
default void destroySecretVersions(final String key, final int... versions) throws VaultConnectorException {
destroySecretVersions(PATH_SECRET, key, versions);
}

View File

@ -16,283 +16,17 @@
package de.stklcode.jvault.connector.builder;
import de.stklcode.jvault.connector.HTTPVaultConnector;
import de.stklcode.jvault.connector.exception.ConnectionException;
import de.stklcode.jvault.connector.exception.TlsException;
import de.stklcode.jvault.connector.exception.VaultConnectorException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
/**
* Vault Connector Builder implementation for HTTP Vault connectors.
*
* @author Stefan Kalscheuer
* @since 0.8.0
* @since 0.9.5 Extends new class for migration purposes only.
* @deprecated Use {@link de.stklcode.jvault.connector.HTTPVaultConnectorBuilder} instead. Will be removed in 1.0
*/
public final class HTTPVaultConnectorBuilder implements VaultConnectorBuilder {
private static final String ENV_VAULT_ADDR = "VAULT_ADDR";
private static final String ENV_VAULT_CACERT = "VAULT_CACERT";
private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN";
private static final String ENV_VAULT_MAX_RETRIES = "VAULT_MAX_RETRIES";
public static final String DEFAULT_HOST = "127.0.0.1";
public static final Integer DEFAULT_PORT = 8200;
public static final boolean DEFAULT_TLS = true;
public static final String DEFAULT_TLS_VERSION = "TLSv1.2";
public static final String DEFAULT_PREFIX = "/v1/";
public static final int DEFAULT_NUMBER_OF_RETRIES = 0;
private String host;
private Integer port;
private boolean tls;
private String tlsVersion;
private String prefix;
private X509Certificate trustedCA;
private int numberOfRetries;
private Integer timeout;
private String token;
/**
* Default empty constructor.
* Initializes factory with default values.
*/
@Deprecated
public class HTTPVaultConnectorBuilder extends de.stklcode.jvault.connector.HTTPVaultConnectorBuilder {
public HTTPVaultConnectorBuilder() {
host = DEFAULT_HOST;
port = DEFAULT_PORT;
tls = DEFAULT_TLS;
tlsVersion = DEFAULT_TLS_VERSION;
prefix = DEFAULT_PREFIX;
numberOfRetries = DEFAULT_NUMBER_OF_RETRIES;
}
/**
* Set hostname (default: 127.0.0.1).
*
* @param host Hostname or IP address
* @return self
*/
public HTTPVaultConnectorBuilder withHost(final String host) {
this.host = host;
return this;
}
/**
* Set port (default: 8200).
*
* @param port Vault TCP port
* @return self
*/
public HTTPVaultConnectorBuilder withPort(final Integer port) {
this.port = port;
return this;
}
/**
* Set TLS usage (default: TRUE).
*
* @param useTLS use TLS or not
* @return self
*/
public HTTPVaultConnectorBuilder withTLS(final boolean useTLS) {
this.tls = useTLS;
return this;
}
/**
* Set TLS usage (default: TRUE).
*
* @param useTLS Use TLS or not.
* @param version Supported TLS version ({@code TLSv1.2}, {@code TLSv1.1}, {@code TLSv1.0}, {@code TLS}).
* @return self
* @since 0.8 Added version parameter (#22).
*/
public HTTPVaultConnectorBuilder withTLS(final boolean useTLS, final String version) {
this.tls = useTLS;
this.tlsVersion = version;
return this;
}
/**
* Convenience Method for TLS usage (enabled by default).
*
* @param version Supported TLS version ({@code TLSv1.2}, {@code TLSv1.1}, {@code TLSv1.0}, {@code TLS}).
* @return self
* @since 0.8 Added version parameter (#22).
*/
public HTTPVaultConnectorBuilder withTLS(final String version) {
return withTLS(true, version);
}
/**
* Convenience Method for TLS usage (enabled by default).
*
* @return self
*/
public HTTPVaultConnectorBuilder withTLS() {
return withTLS(true);
}
/**
* Convenience Method for NOT using TLS.
*
* @return self
*/
public HTTPVaultConnectorBuilder withoutTLS() {
return withTLS(false);
}
/**
* Set API prefix. Default is "/v1/" and changes should not be necessary for current state of development.
*
* @param prefix Vault API prefix (default: "/v1/"
* @return self
*/
public HTTPVaultConnectorBuilder withPrefix(final String prefix) {
this.prefix = prefix;
return this;
}
/**
* Add a trusted CA certificate for HTTPS connections.
*
* @param cert path to certificate file
* @return self
* @throws VaultConnectorException on error
* @since 0.4.0
*/
public HTTPVaultConnectorBuilder withTrustedCA(final Path cert) throws VaultConnectorException {
if (cert != null) {
return withTrustedCA(certificateFromFile(cert));
} else {
this.trustedCA = null;
}
return this;
}
/**
* Add a trusted CA certificate for HTTPS connections.
*
* @param cert path to certificate file
* @return self
* @since 0.8.0
*/
public HTTPVaultConnectorBuilder withTrustedCA(final X509Certificate cert) {
this.trustedCA = cert;
return this;
}
/**
* Set token for automatic authentication, using {@link #buildAndAuth()}.
*
* @param token Vault token
* @return self
* @since 0.6.0
*/
public HTTPVaultConnectorBuilder withToken(final String token) {
this.token = token;
return this;
}
/**
* Build connector based on the {@code }VAULT_ADDR} and {@code VAULT_CACERT} (optional) environment variables.
*
* @return self
* @throws VaultConnectorException if Vault address from environment variables is malformed
* @since 0.6.0
*/
public HTTPVaultConnectorBuilder fromEnv() throws VaultConnectorException {
/* Parse URL from environment variable */
if (System.getenv(ENV_VAULT_ADDR) != null && !System.getenv(ENV_VAULT_ADDR).trim().isEmpty()) {
try {
URL url = new URL(System.getenv(ENV_VAULT_ADDR));
this.host = url.getHost();
this.port = url.getPort();
this.tls = url.getProtocol().equals("https");
} catch (MalformedURLException e) {
throw new ConnectionException("URL provided in environment variable malformed", e);
}
}
/* Read number of retries */
if (System.getenv(ENV_VAULT_MAX_RETRIES) != null) {
try {
numberOfRetries = Integer.parseInt(System.getenv(ENV_VAULT_MAX_RETRIES));
} catch (NumberFormatException ignored) {
/* Ignore malformed values. */
}
}
/* Read token */
token = System.getenv(ENV_VAULT_TOKEN);
/* Parse certificate, if set */
if (System.getenv(ENV_VAULT_CACERT) != null && !System.getenv(ENV_VAULT_CACERT).trim().isEmpty()) {
return withTrustedCA(Paths.get(System.getenv(ENV_VAULT_CACERT)));
}
return this;
}
/**
* Define the number of retries to attempt on 5xx errors.
*
* @param numberOfRetries The number of retries to attempt on 5xx errors (default: 0)
* @return self
* @since 0.6.0
*/
public HTTPVaultConnectorBuilder withNumberOfRetries(final int numberOfRetries) {
this.numberOfRetries = numberOfRetries;
return this;
}
/**
* Define a custom timeout for the HTTP connection.
*
* @param milliseconds Timeout value in milliseconds.
* @return self
* @since 0.6.0
*/
public HTTPVaultConnectorBuilder withTimeout(final int milliseconds) {
this.timeout = milliseconds;
return this;
}
@Override
public HTTPVaultConnector build() {
return new HTTPVaultConnector(host, tls, tlsVersion, port, prefix, trustedCA, numberOfRetries, timeout);
}
@Override
public HTTPVaultConnector buildAndAuth() throws VaultConnectorException {
if (token == null) {
throw new ConnectionException("No vault token provided, unable to authenticate.");
}
HTTPVaultConnector con = build();
con.authToken(token);
return con;
}
/**
* Read given certificate file to X.509 certificate.
*
* @param certFile Path to certificate file
* @return X.509 Certificate object
* @throws TlsException on error
* @since 0.4.0
*/
private X509Certificate certificateFromFile(final Path certFile) throws TlsException {
try (InputStream is = Files.newInputStream(certFile)) {
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
} catch (IOException | CertificateException e) {
throw new TlsException("Unable to read certificate.", e);
}
super();
}
}

View File

@ -16,6 +16,7 @@
package de.stklcode.jvault.connector.builder;
import de.stklcode.jvault.connector.HTTPVaultConnector;
import de.stklcode.jvault.connector.VaultConnector;
import de.stklcode.jvault.connector.exception.VaultConnectorException;
@ -31,7 +32,9 @@ public interface VaultConnectorBuilder {
* Get Factory implementation for HTTP Vault Connector.
*
* @return HTTP Connector Factory
* @deprecated Use {@link HTTPVaultConnector#builder()} instead. This interface will be removed in 1.0
*/
@Deprecated
static HTTPVaultConnectorBuilder http() {
return new HTTPVaultConnectorBuilder();
}

View File

@ -17,7 +17,7 @@
package de.stklcode.jvault.connector.factory;
import de.stklcode.jvault.connector.HTTPVaultConnector;
import de.stklcode.jvault.connector.builder.HTTPVaultConnectorBuilder;
import de.stklcode.jvault.connector.HTTPVaultConnectorBuilder;
import de.stklcode.jvault.connector.exception.VaultConnectorException;
import javax.net.ssl.SSLContext;

View File

@ -703,21 +703,34 @@ public final class AppRole {
* @return self
* @since 0.9
*/
public Builder wit0hTokenPeriod(final Integer tokenPeriod) {
public Builder withTokenPeriod(final Integer tokenPeriod) {
this.tokenPeriod = tokenPeriod;
return this;
}
/**
* Set renewal period for generated token in seconds.
*
* @param tokenPeriod period in seconds
* @return self
* @since 0.9
* @deprecated Use {@link #withTokenPeriod(Integer)} instead.
*/
@Deprecated
public Builder wit0hTokenPeriod(final Integer tokenPeriod) {
return withTokenPeriod(tokenPeriod);
}
/**
* Set renewal period for generated token in seconds.
*
* @param period period in seconds
* @return self
* @deprecated Use {@link #wit0hTokenPeriod(Integer)} instead.
* @deprecated Use {@link #withTokenPeriod(Integer)} instead.
*/
@Deprecated
public Builder withPeriod(final Integer period) {
return wit0hTokenPeriod(period);
return withTokenPeriod(period);
}
/**

View File

@ -308,21 +308,34 @@ public final class AppRoleBuilder {
* @return self
* @since 0.9
*/
public AppRoleBuilder wit0hTokenPeriod(final Integer tokenPeriod) {
public AppRoleBuilder withTokenPeriod(final Integer tokenPeriod) {
this.tokenPeriod = tokenPeriod;
return this;
}
/**
* Set renewal period for generated token in seconds.
*
* @param tokenPeriod period in seconds
* @return self
* @since 0.9
* @deprecated Use {@link #withTokenPeriod(Integer)} instead.
*/
@Deprecated
public AppRoleBuilder wit0hTokenPeriod(final Integer tokenPeriod) {
return withTokenPeriod(tokenPeriod);
}
/**
* Set renewal period for generated token in seconds.
*
* @param period period in seconds
* @return self
* @deprecated Use {@link #wit0hTokenPeriod(Integer)} instead.
* @deprecated Use {@link #withTokenPeriod(Integer)} instead.
*/
@Deprecated
public AppRoleBuilder withPeriod(final Integer period) {
return wit0hTokenPeriod(period);
return withTokenPeriod(period);
}
/**

View File

@ -16,7 +16,6 @@
package de.stklcode.jvault.connector;
import de.stklcode.jvault.connector.builder.HTTPVaultConnectorBuilder;
import de.stklcode.jvault.connector.builder.VaultConnectorBuilder;
import de.stklcode.jvault.connector.exception.*;
import de.stklcode.jvault.connector.model.AppRole;
@ -54,7 +53,7 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
*/
@Tag("online")
class HTTPVaultConnectorTest {
private static String VAULT_VERSION = "1.7.0"; // the vault version this test is supposed to run against
private static String VAULT_VERSION = "1.8.0"; // the vault version this test is supposed to run against
private static final String KEY1 = "E38bkCm0VhUvpdCKGQpcohhD9XmcHJ/2hreOSY019Lho";
private static final String KEY2 = "O5OHwDleY3IiPdgw61cgHlhsrEm6tVJkrxhF6QAnILd1";
private static final String KEY3 = "mw7Bm3nbt/UWa/juDjjL2EPQ04kiJ0saC5JEXwJvXYsB";
@ -771,7 +770,7 @@ class HTTPVaultConnectorTest {
/* Update role model with custom flags */
AppRole role2 = AppRole.builder(roleName)
.wit0hTokenPeriod(321)
.withTokenPeriod(321)
.build();
/* Create role */

View File

@ -18,6 +18,7 @@ package de.stklcode.jvault.connector.builder;
import com.github.stefanbirkner.systemlambda.SystemLambda;
import de.stklcode.jvault.connector.HTTPVaultConnector;
import de.stklcode.jvault.connector.HTTPVaultConnectorBuilder;
import de.stklcode.jvault.connector.exception.TlsException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
@ -25,7 +26,6 @@ import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.lang.reflect.Field;
import java.nio.file.NoSuchFileException;
import java.util.concurrent.Callable;
import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable;
import static org.hamcrest.CoreMatchers.*;
@ -55,7 +55,7 @@ class HTTPVaultConnectorBuilderTest {
/* Provide address only should be enough */
withVaultEnv(VAULT_ADDR, null, null, null).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> VaultConnectorBuilder.http().fromEnv(),
() -> HTTPVaultConnector.builder().fromEnv(),
"Factory creation from minimal environment failed"
);
HTTPVaultConnector connector = builder.build();
@ -70,7 +70,7 @@ class HTTPVaultConnectorBuilderTest {
/* Provide address and number of retries */
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> VaultConnectorBuilder.http().fromEnv(),
() -> HTTPVaultConnector.builder().fromEnv(),
"Factory creation from environment failed"
);
HTTPVaultConnector connector = builder.build();
@ -87,7 +87,7 @@ class HTTPVaultConnectorBuilderTest {
withVaultEnv(VAULT_ADDR, VAULT_CACERT, VAULT_MAX_RETRIES.toString(), null).execute(() -> {
TlsException e = assertThrows(
TlsException.class,
() -> VaultConnectorBuilder.http().fromEnv(),
() -> HTTPVaultConnector.builder().fromEnv(),
"Creation with unknown cert path failed."
);
assertThat(e.getCause(), is(instanceOf(NoSuchFileException.class)));
@ -99,7 +99,7 @@ class HTTPVaultConnectorBuilderTest {
/* Automatic authentication */
withVaultEnv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN).execute(() -> {
HTTPVaultConnectorBuilder builder = assertDoesNotThrow(
() -> VaultConnectorBuilder.http().fromEnv(),
() -> HTTPVaultConnector.builder().fromEnv(),
"Factory creation from minimal environment failed"
);
assertThat("Token nor set correctly", getPrivate(builder, "token"), is(equalTo(VAULT_TOKEN)));

View File

@ -138,7 +138,7 @@ class AppRoleBuilderTest {
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
.withTokenNumUses(TOKEN_NUM_USES)
.wit0hTokenPeriod(TOKEN_PERIOD)
.withTokenPeriod(TOKEN_PERIOD)
.withTokenType(TOKEN_TYPE)
.build();
assertThat(role.getName(), is(NAME));
@ -183,7 +183,7 @@ class AppRoleBuilderTest {
.withTokenExplicitMaxTtl(TOKEN_EXPLICIT_MAX_TTL)
.withTokenNoDefaultPolicy(TOKEN_NO_DEFAULT_POLICY)
.withTokenNumUses(TOKEN_NUM_USES)
.wit0hTokenPeriod(TOKEN_PERIOD)
.withTokenPeriod(TOKEN_PERIOD)
.withTokenType(TOKEN_TYPE)
.build();
assertThat(role.getName(), is(NAME));