-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #44 from bancolombia/feature/vault-backend
feat: added vault client for secrets
- Loading branch information
Showing
24 changed files
with
1,402 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
...c/vault-async/src/main/java/co/com/bancolombia/secretsmanager/config/CacheProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package co.com.bancolombia.secretsmanager.config; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
@Builder | ||
public class CacheProperties { | ||
|
||
@Builder.Default | ||
private int expireAfter = 600; //in seconds | ||
|
||
@Builder.Default | ||
private int maxSize = 100; | ||
} |
16 changes: 16 additions & 0 deletions
16
async/vault-async/src/main/java/co/com/bancolombia/secretsmanager/config/HttpProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package co.com.bancolombia.secretsmanager.config; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
@Builder | ||
public class HttpProperties { | ||
|
||
@Builder.Default | ||
private int connectionTimeout = 5; //in seconds | ||
} |
32 changes: 32 additions & 0 deletions
32
...async/src/main/java/co/com/bancolombia/secretsmanager/config/VaultKeyStoreProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package co.com.bancolombia.secretsmanager.config; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
import java.io.File; | ||
|
||
/** | ||
* If you would like to use Vault's TLS Certificate auth backend for client side auth, then you need to provide | ||
* either: | ||
* 1) A JKS keystore containing your client-side certificate and private key, and optionally a password. | ||
* 2) PEM files containing your client-side certificate and private key | ||
*/ | ||
@Getter | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@Builder | ||
public class VaultKeyStoreProperties { | ||
|
||
// JKS file containing a client certificate and private key. | ||
private File keyStoreFile; | ||
// Password for the JKS file or resource (optional). | ||
private String keyStorePassword; | ||
|
||
// Path to an X.509 certificate in unencrypted PEM format, using UTF-8 encoding. | ||
private File clientPem; | ||
// path to an RSA private key in unencrypted PEM format, using UTF-8 encoding. | ||
private File clientKeyPem; | ||
|
||
} |
59 changes: 59 additions & 0 deletions
59
...src/main/java/co/com/bancolombia/secretsmanager/config/VaultSecretsManagerProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package co.com.bancolombia.secretsmanager.config; | ||
|
||
import lombok.*; | ||
|
||
@Getter | ||
@Setter | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@Builder(toBuilder = true) | ||
public class VaultSecretsManagerProperties { | ||
|
||
@Builder.Default | ||
private String host = "localhost"; | ||
|
||
@Builder.Default | ||
private int port = 8200; | ||
|
||
@Builder.Default | ||
private boolean ssl = false; | ||
|
||
@Builder.Default | ||
private boolean tlsAuth = false; | ||
|
||
@Builder.Default | ||
private String baseApi = "/v1"; | ||
|
||
@Builder.Default | ||
private String baseSecrets = "/kv/data/"; | ||
|
||
private String token; | ||
|
||
private String roleId; | ||
|
||
private String secretId; | ||
|
||
@Builder.Default | ||
private int engineVersion = 2; | ||
|
||
private VaultTrustStoreProperties trustStoreProperties; | ||
|
||
private VaultKeyStoreProperties keyStoreProperties; | ||
|
||
@Builder.Default | ||
private HttpProperties httpProperties = HttpProperties.builder().connectionTimeout(5).build(); | ||
|
||
@Builder.Default | ||
private CacheProperties authCacheProperties = CacheProperties.builder().expireAfter(600).maxSize(10).build(); | ||
|
||
@Builder.Default | ||
private CacheProperties secretsCacheProperties= CacheProperties.builder().expireAfter(600).maxSize(100).build(); | ||
|
||
public String buildUrl() { | ||
return String.format("%s://%s:%d%s", ssl ? "https" : "http", host, port, baseApi); | ||
} | ||
|
||
public boolean roleCredentialsProvided() { | ||
return roleId != null && !roleId.isEmpty() && secretId != null && !secretId.isEmpty(); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
...ync/src/main/java/co/com/bancolombia/secretsmanager/config/VaultTrustStoreProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package co.com.bancolombia.secretsmanager.config; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
import java.io.File; | ||
|
||
/** | ||
* Provide information about a JKS truststore, containing Vault's server-side certificate for basic SSL, using one of | ||
* the following two options: | ||
* 1) A JKS file with trustStoreJksFile attribute or | ||
* 2) Pem files using pemFile attribute | ||
*/ | ||
@Getter | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@Builder | ||
public class VaultTrustStoreProperties { | ||
|
||
/** | ||
* JKS file containing Vault server cert(s) that can be trusted. | ||
*/ | ||
private File trustStoreJksFile; | ||
|
||
/** | ||
* Supply the path to an X.509 certificate in unencrypted PEM format, using UTF-8 encoding | ||
* (defaults to "VAULT_SSL_CERT" environment variable) | ||
*/ | ||
private File pemFile; | ||
|
||
|
||
} |
83 changes: 83 additions & 0 deletions
83
...t-async/src/main/java/co/com/bancolombia/secretsmanager/connector/VaultAuthenticator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package co.com.bancolombia.secretsmanager.connector; | ||
|
||
import co.com.bancolombia.secretsmanager.api.exceptions.SecretException; | ||
import co.com.bancolombia.secretsmanager.commons.utils.GsonUtils; | ||
import co.com.bancolombia.secretsmanager.config.VaultSecretsManagerProperties; | ||
import co.com.bancolombia.secretsmanager.connector.auth.AuthResponse; | ||
import com.github.benmanes.caffeine.cache.AsyncCache; | ||
import com.github.benmanes.caffeine.cache.Caffeine; | ||
import com.google.gson.JsonObject; | ||
import reactor.core.publisher.Mono; | ||
|
||
import java.net.URI; | ||
import java.net.http.HttpClient; | ||
import java.net.http.HttpRequest; | ||
import java.net.http.HttpResponse; | ||
import java.time.Duration; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.logging.Logger; | ||
|
||
public class VaultAuthenticator { | ||
private final Logger logger = Logger.getLogger("connector.VaultAuthenticator2"); | ||
|
||
private static final String BASE_AUTH_PATH = "/auth/approle/login"; | ||
private static final String CONTENT_TYPE_HEADER = "Content-Type"; | ||
|
||
private final HttpClient httpClient; | ||
private final VaultSecretsManagerProperties properties; | ||
private final AsyncCache<String, AuthResponse> cache; | ||
|
||
public VaultAuthenticator(HttpClient httpClient, VaultSecretsManagerProperties properties) { | ||
this.httpClient = httpClient; | ||
this.properties = properties; | ||
this.cache = initCache(); | ||
} | ||
|
||
public Mono<AuthResponse> loginByAppRole() { | ||
if (!properties.roleCredentialsProvided()) { | ||
return Mono.defer(() -> | ||
Mono.error(new SecretException("Could not perform action loginByAppRole. Role id or secret id is null, please check your configuration"))); | ||
} else { | ||
return Mono.fromFuture(cache.get(properties.getRoleId(), | ||
(s, executor) -> performLoginByAppRole().toFuture().toCompletableFuture())); | ||
} | ||
} | ||
|
||
private Mono<AuthResponse> performLoginByAppRole() { | ||
return Mono.fromSupplier(() -> | ||
HttpRequest.newBuilder() | ||
.uri(URI.create(this.properties.buildUrl() + BASE_AUTH_PATH)) | ||
.timeout(Duration.ofSeconds(5)) | ||
.header(CONTENT_TYPE_HEADER, "application/json") | ||
.POST(HttpRequest.BodyPublishers.ofString(buildLoginBody())) | ||
.build() | ||
) | ||
.flatMap(request -> Mono.fromFuture(httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString()))) | ||
.flatMap(response -> response.statusCode() != 200 ? | ||
Mono.error(() -> new SecretException("Error performing authentication with vault: " + response.body())) : | ||
Mono.just(response)) | ||
.map(HttpResponse::body) | ||
.map(body -> GsonUtils.getInstance().stringToModel(body, JsonObject.class)) | ||
.map(map -> map.getAsJsonObject("auth")) | ||
.map(auth -> AuthResponse.builder() | ||
.clientToken(auth.get("client_token").getAsString()) | ||
.accessor(auth.get("accessor").getAsString()) | ||
.leaseDuration(auth.get("lease_duration").getAsLong()) | ||
.renewable(auth.get("renewable").getAsBoolean()) | ||
.build()) | ||
.doOnSuccess(authResponse -> logger.info("Successfully authenticated by app-role with vault")) | ||
.doOnError(err -> logger.severe("Error performing authentication with vault: " + err.getMessage())); | ||
} | ||
|
||
private String buildLoginBody() { | ||
return "{\"role_id\":\"" + properties.getRoleId() + "\",\"secret_id\":\"" + properties.getSecretId() + "\"}"; | ||
} | ||
|
||
private AsyncCache<String, AuthResponse> initCache() { | ||
return Caffeine.newBuilder() | ||
.maximumSize(properties.getAuthCacheProperties().getMaxSize()) | ||
.expireAfterWrite(properties.getAuthCacheProperties().getExpireAfter(), TimeUnit.SECONDS) | ||
.buildAsync(); | ||
} | ||
|
||
} |
Oops, something went wrong.