Compare commits
1 Commits
main
...
feat/split
Author | SHA1 | Date | |
---|---|---|---|
1072e9b4a9
|
@@ -5,8 +5,6 @@
|
||||
|
||||
### Improvements
|
||||
* Extract API paths into a utility class (#108)
|
||||
* Encode user-provided URL parts (#109)
|
||||
* Add `token_bound_cidrs` field to `AppRoleSecret` model (#110)
|
||||
|
||||
### Fix
|
||||
* Prevent potential off-by-1 error in internal `mapOf()` helper (#107)
|
||||
|
@@ -109,11 +109,11 @@ Token token = Token.builder()
|
||||
.withDisplayName("new test token")
|
||||
.withPolicies("pol1", "pol2")
|
||||
.build();
|
||||
vault.createToken(token);
|
||||
vault.token().create(token);
|
||||
|
||||
// Create AppRole credentials
|
||||
vault.createAppRole("testrole", policyList);
|
||||
AppRoleSecretResponse secret = vault.createAppRoleSecret("testrole");
|
||||
vault.appRole().create("testrole", policyList);
|
||||
AppRoleSecretResponse secret = vault.appRole().createSecret("testrole");
|
||||
```
|
||||
|
||||
## Links
|
||||
|
2
pom.xml
2
pom.xml
@@ -3,7 +3,7 @@
|
||||
|
||||
<groupId>de.stklcode.jvault</groupId>
|
||||
<artifactId>jvault-connector</artifactId>
|
||||
<version>1.5.3-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
217
src/main/java/de/stklcode/jvault/connector/AppRoleClient.java
Normal file
217
src/main/java/de/stklcode/jvault/connector/AppRoleClient.java
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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.exception.VaultConnectorException;
|
||||
import de.stklcode.jvault.connector.model.AppRole;
|
||||
import de.stklcode.jvault.connector.model.AppRoleSecret;
|
||||
import de.stklcode.jvault.connector.model.Token;
|
||||
import de.stklcode.jvault.connector.model.TokenRole;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AppRole client interface.
|
||||
* Provides methods to interact with Vault's AppRole API.
|
||||
*
|
||||
* @since 2.0.0 extracted from {@link VaultConnector}
|
||||
*/
|
||||
public interface AppRoleClient {
|
||||
|
||||
/**
|
||||
* Register a new AppRole role from given metamodel.
|
||||
*
|
||||
* @param role The role
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean create(final AppRole role) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new AppRole role with default policy.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean create(final String roleName) throws VaultConnectorException {
|
||||
return create(roleName, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with policies.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param policies The policies to associate with
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean create(final String roleName, final List<String> policies) throws VaultConnectorException {
|
||||
return create(roleName, policies, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with default policy and custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param roleID A custom role ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean create(final String roleName, final String roleID) throws VaultConnectorException {
|
||||
return create(roleName, new ArrayList<>(), roleID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with policies and custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param policies The policies to associate with
|
||||
* @param roleID A custom role ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean create(final String roleName, final List<String> policies, final String roleID)
|
||||
throws VaultConnectorException {
|
||||
return create(AppRole.builder(roleName).withTokenPolicies(policies).withId(roleID).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete AppRole role from Vault.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
boolean delete(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return Result of the lookup
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleResponse lookup(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve ID for an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return The role ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
String getRoleID(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Set custom ID for an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param roleID The role ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean setRoleID(final String roleName, final String roleID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new random generated AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AppRoleSecretResponse createSecret(final String roleName) throws VaultConnectorException {
|
||||
return createSecret(roleName, new AppRoleSecret());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole secret with custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID A custom secret ID
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AppRoleSecretResponse createSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
return createSecret(roleName, new AppRoleSecret(secretID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole secret with custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secret The secret meta object
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse createSecret(final String roleName, final AppRoleSecret secret)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup an AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID The secret ID
|
||||
* @return Result of the lookup
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse lookupSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Destroy an AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID The secret meta object
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean destroySecret(final String roleName, final String secretID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List existing (accessible) AppRole roles.
|
||||
*
|
||||
* @return List of roles
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<String> listRoles() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List existing (accessible) secret IDs for AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return List of roles
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<String> listSecrets(final String roleName) throws VaultConnectorException;
|
||||
}
|
@@ -31,7 +31,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static de.stklcode.jvault.connector.internal.RequestHelper.encode;
|
||||
import static de.stklcode.jvault.connector.internal.VaultApiPath.*;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonMap;
|
||||
@@ -107,55 +106,11 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
authorized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SealResponse sealStatus() throws VaultConnectorException {
|
||||
return request.get(SYS_SEAL_STATUS, emptyMap(), token, SealResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void seal() throws VaultConnectorException {
|
||||
request.put(SYS_SEAL, emptyMap(), token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SealResponse unseal(final String key, final Boolean reset) throws VaultConnectorException {
|
||||
Map<String, String> param = mapOfStrings(
|
||||
"key", key,
|
||||
"reset", reset
|
||||
);
|
||||
|
||||
return request.put(SYS_UNSEAL, param, token, SealResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HealthResponse getHealth() throws VaultConnectorException {
|
||||
|
||||
return request.get(
|
||||
SYS_HEALTH,
|
||||
// Force status code to be 200, so we don't need to modify the request sequence.
|
||||
Map.of(
|
||||
"standbycode", "200", // Default: 429.
|
||||
"sealedcode", "200", // Default: 503.
|
||||
"uninitcode", "200" // Default: 501.
|
||||
),
|
||||
token,
|
||||
HealthResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isAuthorized() {
|
||||
return authorized && (tokenTTL == 0 || tokenTTL >= System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<AuthBackend> getAuthBackends() throws VaultConnectorException {
|
||||
/* Issue request and parse response */
|
||||
AuthMethodsResponse amr = request.get(SYS_AUTH, emptyMap(), token, AuthMethodsResponse.class);
|
||||
|
||||
return amr.getSupportedMethods().values().stream().map(AuthMethod::getType).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TokenResponse authToken(final String token) throws VaultConnectorException {
|
||||
/* set token */
|
||||
@@ -171,7 +126,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
public final AuthResponse authUserPass(final String username, final String password)
|
||||
throws VaultConnectorException {
|
||||
final Map<String, String> payload = singletonMap("password", password);
|
||||
return queryAuth(AUTH_USERPASS_LOGIN + encode(username), payload);
|
||||
return queryAuth(AUTH_USERPASS_LOGIN + username, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -180,7 +135,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
"role_id", roleID,
|
||||
"secret_id", secretID
|
||||
);
|
||||
return queryAuth(AUTH_APPROLE + "login", payload);
|
||||
return queryAuth(AUTH_APPROLE + LOGIN, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,142 +158,6 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
return auth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean createAppRole(final AppRole role) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(AUTH_APPROLE_ROLE + encode(role.getName()), role, token);
|
||||
|
||||
/* Set custom ID if provided */
|
||||
return !(role.getId() != null && !role.getId().isEmpty()) || setAppRoleID(role.getName(), role.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AppRoleResponse lookupAppRole(final String roleName) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
/* Request HTTP response and parse Secret */
|
||||
return request.get(
|
||||
AUTH_APPROLE_ROLE + encode(roleName),
|
||||
emptyMap(),
|
||||
token,
|
||||
AppRoleResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean deleteAppRole(final String roleName) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.deleteWithoutResponse(AUTH_APPROLE_ROLE + encode(roleName), token);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getAppRoleID(final String roleName) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
/* Issue request, parse response and extract Role ID */
|
||||
return request.get(
|
||||
AUTH_APPROLE_ROLE + encode(roleName) + "/role-id",
|
||||
emptyMap(),
|
||||
token,
|
||||
RawDataResponse.class
|
||||
).getData().get("role_id").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean setAppRoleID(final String roleName, final String roleID) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(
|
||||
AUTH_APPROLE_ROLE + encode(roleName) + "/role-id",
|
||||
singletonMap("role_id", roleID),
|
||||
token
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (secret.getId() != null && !secret.getId().isEmpty()) {
|
||||
return request.post(
|
||||
AUTH_APPROLE_ROLE + encode(roleName) + "/custom-secret-id",
|
||||
secret,
|
||||
token,
|
||||
AppRoleSecretResponse.class
|
||||
);
|
||||
} else {
|
||||
return request.post(
|
||||
AUTH_APPROLE_ROLE + encode(roleName) + "/secret-id",
|
||||
secret, token,
|
||||
AppRoleSecretResponse.class
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and parse secret response */
|
||||
return request.post(
|
||||
AUTH_APPROLE_ROLE + encode(roleName) + "/secret-id/lookup",
|
||||
new AppRoleSecret(secretID),
|
||||
token,
|
||||
AppRoleSecretResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean destroyAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(
|
||||
AUTH_APPROLE_ROLE + encode(roleName) + "/secret-id/destroy",
|
||||
new AppRoleSecret(secretID),
|
||||
token);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<String> listAppRoles() throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
SecretListResponse secrets = request.get(
|
||||
AUTH_APPROLE + "role?list=true",
|
||||
emptyMap(),
|
||||
token,
|
||||
SecretListResponse.class
|
||||
);
|
||||
|
||||
return secrets.getKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<String> listAppRoleSecrets(final String roleName) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
SecretListResponse secrets = request.get(
|
||||
AUTH_APPROLE_ROLE + encode(roleName) + "/secret-id?list=true",
|
||||
emptyMap(),
|
||||
token,
|
||||
SecretListResponse.class
|
||||
);
|
||||
|
||||
return secrets.getKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SecretResponse read(final String key) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
@@ -346,66 +165,6 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
return request.get(key, emptyMap(), token, PlainSecretResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SecretResponse readSecretVersion(final String mount, final String key, final Integer version)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
/* Request HTTP response and parse secret metadata */
|
||||
Map<String, String> args = mapOfStrings("version", version);
|
||||
|
||||
return request.get(mount + SECRET_DATA + key, args, token, MetaSecretResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MetadataResponse readSecretMetadata(final String mount, final String key)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Request HTTP response and parse secret metadata */
|
||||
return request.get(mount + SECRET_METADATA + key, emptyMap(), token, MetadataResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSecretMetadata(final String mount,
|
||||
final String key,
|
||||
final Integer maxVersions,
|
||||
final boolean casRequired) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"max_versions", maxVersions,
|
||||
"cas_required", casRequired
|
||||
);
|
||||
|
||||
write(mount + SECRET_METADATA + key, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SecretVersionResponse writeSecretData(final String mount,
|
||||
final String key,
|
||||
final Map<String, Object> data,
|
||||
final Integer cas) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (key == null || key.isEmpty()) {
|
||||
throw new InvalidRequestException("Secret path must not be empty.");
|
||||
}
|
||||
|
||||
// Add CAS value to options map if present.
|
||||
Map<String, Object> options = mapOf("cas", cas);
|
||||
|
||||
/* Issue request and parse metadata response */
|
||||
return request.post(
|
||||
mount + SECRET_DATA + key,
|
||||
Map.of(
|
||||
"data", data,
|
||||
"options", options
|
||||
),
|
||||
token,
|
||||
SecretVersionResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<String> list(final String path) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
@@ -447,63 +206,12 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
request.deleteWithoutResponse(key, token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void deleteLatestSecretVersion(final String mount, final String key) throws VaultConnectorException {
|
||||
delete(mount + SECRET_DATA + key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void deleteAllSecretVersions(final String mount, final String key) throws VaultConnectorException {
|
||||
delete(mount + SECRET_METADATA + key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void deleteSecretVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException {
|
||||
handleSecretVersions(mount, SECRET_DELETE, key, versions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void undeleteSecretVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException {
|
||||
handleSecretVersions(mount, SECRET_UNDELETE, key, versions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void destroySecretVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException {
|
||||
handleSecretVersions(mount, SECRET_DESTROY, key, versions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common method to bundle secret version operations.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param pathPart Path part to query.
|
||||
* @param key Secret key.
|
||||
* @param versions Versions to handle.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
private void handleSecretVersions(final String mount,
|
||||
final String pathPart,
|
||||
final String key,
|
||||
final int... versions) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Request HTTP response and expect empty result */
|
||||
Map<String, Object> payload = singletonMap("versions", versions);
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(mount + pathPart + key, payload, token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void revoke(final String leaseID) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.putWithoutResponse(SYS_LEASES_REVOKE + encode(leaseID), emptyMap(), token);
|
||||
request.putWithoutResponse(SYS_LEASES_REVOKE + leaseID, emptyMap(), token);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -520,21 +228,28 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AuthResponse createToken(final Token token) throws VaultConnectorException {
|
||||
return createTokenInternal(token, AUTH_TOKEN + TOKEN_CREATE);
|
||||
public KV2ClientImpl kv2() {
|
||||
return new KV2ClientImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AuthResponse createToken(final Token token, final boolean orphan) throws VaultConnectorException {
|
||||
return createTokenInternal(token, AUTH_TOKEN + TOKEN_CREATE_ORPHAN);
|
||||
public TokenClientImpl token() {
|
||||
return new TokenClientImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AuthResponse createToken(final Token token, final String role) throws VaultConnectorException {
|
||||
if (role == null || role.isEmpty()) {
|
||||
throw new InvalidRequestException("No role name specified.");
|
||||
}
|
||||
return createTokenInternal(token, AUTH_TOKEN + TOKEN_CREATE + "/" + encode(role));
|
||||
public AppRoleClient appRole() {
|
||||
return new AppRoleClientImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransitClientImpl transit() {
|
||||
return new TransitClientImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysClientImpl sys() {
|
||||
return new SysClientImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -544,124 +259,6 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
tokenTTL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token.
|
||||
* Centralized method to handle different token creation requests.
|
||||
*
|
||||
* @param token the token
|
||||
* @param path request path
|
||||
* @return the response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
private AuthResponse createTokenInternal(final Token token, final String path) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (token == null) {
|
||||
throw new InvalidRequestException("Token must be provided.");
|
||||
}
|
||||
|
||||
return request.post(path, token, this.token, AuthResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TokenResponse lookupToken(final String token) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Request HTTP response and parse Secret */
|
||||
return request.get(
|
||||
AUTH_TOKEN + TOKEN_LOOKUP,
|
||||
singletonMap("token", token),
|
||||
token,
|
||||
TokenResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createOrUpdateTokenRole(final String name, final TokenRole role) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (name == null) {
|
||||
throw new InvalidRequestException("Role name must be provided.");
|
||||
} else if (role == null) {
|
||||
throw new InvalidRequestException("Role must be provided.");
|
||||
}
|
||||
|
||||
// Issue request and expect code 204 with empty response.
|
||||
request.postWithoutResponse(AUTH_TOKEN + TOKEN_ROLES + "/" + encode(name), role, token);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TokenRoleResponse readTokenRole(final String name) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
// Request HTTP response and parse response.
|
||||
return request.get(AUTH_TOKEN + TOKEN_ROLES + "/" + encode(name), emptyMap(), token, TokenRoleResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listTokenRoles() throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
return list(AUTH_TOKEN + TOKEN_ROLES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTokenRole(final String name) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (name == null) {
|
||||
throw new InvalidRequestException("Role name must be provided.");
|
||||
}
|
||||
|
||||
// Issue request and expect code 204 with empty response.
|
||||
request.deleteWithoutResponse(AUTH_TOKEN + TOKEN_ROLES + "/" + encode(name), token);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TransitResponse transitEncrypt(final String keyName, final String plaintext)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"plaintext", plaintext
|
||||
);
|
||||
|
||||
return request.post(TRANSIT_ENCRYPT + encode(keyName), payload, token, TransitResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TransitResponse transitDecrypt(final String keyName, final String ciphertext)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"ciphertext", ciphertext
|
||||
);
|
||||
|
||||
return request.post(TRANSIT_DECRYPT + encode(keyName), payload, token, TransitResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TransitResponse transitHash(final String algorithm, final String input, final String format)
|
||||
throws VaultConnectorException {
|
||||
if (format != null && !"hex".equals(format) && !"base64".equals(format)) {
|
||||
throw new IllegalArgumentException("Unsupported format " + format);
|
||||
}
|
||||
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"input", input,
|
||||
"format", format
|
||||
);
|
||||
|
||||
return request.post(TRANSIT_HASH + encode(algorithm), payload, token, TransitResponse.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for required authorization.
|
||||
*
|
||||
@@ -711,4 +308,459 @@ public class HTTPVaultConnector implements VaultConnector {
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-client for KV v2 methods.
|
||||
*/
|
||||
public class KV2ClientImpl implements KV2Client {
|
||||
@Override
|
||||
public final SecretResponse readVersion(final String mount, final String key, final Integer version)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
/* Request HTTP response and parse secret metadata */
|
||||
Map<String, String> args = mapOfStrings("version", version);
|
||||
|
||||
return request.get(mount + SECRET_DATA + key, args, token, MetaSecretResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MetadataResponse readMetadata(final String mount, final String key)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Request HTTP response and parse secret metadata */
|
||||
return request.get(mount + SECRET_METADATA + key, emptyMap(), token, MetadataResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMetadata(final String mount,
|
||||
final String key,
|
||||
final Integer maxVersions,
|
||||
final boolean casRequired) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"max_versions", maxVersions,
|
||||
"cas_required", casRequired
|
||||
);
|
||||
|
||||
write(mount + SECRET_METADATA + key, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SecretVersionResponse writeData(final String mount,
|
||||
final String key,
|
||||
final Map<String, Object> data,
|
||||
final Integer cas) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (key == null || key.isEmpty()) {
|
||||
throw new InvalidRequestException("Secret path must not be empty.");
|
||||
}
|
||||
|
||||
// Add CAS value to options map if present.
|
||||
Map<String, Object> options = mapOf("cas", cas);
|
||||
|
||||
/* Issue request and parse metadata response */
|
||||
return request.post(
|
||||
mount + SECRET_DATA + key,
|
||||
Map.of(
|
||||
"data", data,
|
||||
"options", options
|
||||
),
|
||||
token,
|
||||
SecretVersionResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void deleteLatestVersion(final String mount, final String key) throws VaultConnectorException {
|
||||
delete(mount + SECRET_DATA + key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void deleteAllVersions(final String mount, final String key) throws VaultConnectorException {
|
||||
delete(mount + SECRET_METADATA + key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void deleteVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException {
|
||||
handleSecretVersions(mount, SECRET_DELETE, key, versions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void undeleteVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException {
|
||||
handleSecretVersions(mount, SECRET_UNDELETE, key, versions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void destroyVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException {
|
||||
handleSecretVersions(mount, SECRET_DESTROY, key, versions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common method to bundle secret version operations.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param pathPart Path part to query.
|
||||
* @param key Secret key.
|
||||
* @param versions Versions to handle.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
private void handleSecretVersions(final String mount,
|
||||
final String pathPart,
|
||||
final String key,
|
||||
final int... versions) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Request HTTP response and expect empty result */
|
||||
Map<String, Object> payload = singletonMap("versions", versions);
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(mount + pathPart + key, payload, token);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-client for token methods.
|
||||
*/
|
||||
public class TokenClientImpl implements TokenClient {
|
||||
|
||||
@Override
|
||||
public final AuthResponse create(final Token token) throws VaultConnectorException {
|
||||
return createInternal(token, AUTH_TOKEN + TOKEN_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AuthResponse create(final Token token, final boolean orphan) throws VaultConnectorException {
|
||||
return createInternal(token, AUTH_TOKEN + TOKEN_CREATE_ORPHAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AuthResponse create(final Token token, final String role) throws VaultConnectorException {
|
||||
if (role == null || role.isEmpty()) {
|
||||
throw new InvalidRequestException("No role name specified.");
|
||||
}
|
||||
return createInternal(token, AUTH_TOKEN + TOKEN_CREATE + "/" + role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token.
|
||||
* Centralized method to handle different token creation requests.
|
||||
*
|
||||
* @param token the token
|
||||
* @param path request path
|
||||
* @return the response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
private AuthResponse createInternal(final Token token, final String path) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (token == null) {
|
||||
throw new InvalidRequestException("Token must be provided.");
|
||||
}
|
||||
|
||||
return request.post(path, token, HTTPVaultConnector.this.token, AuthResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TokenResponse lookup(final String token) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Request HTTP response and parse Secret */
|
||||
return request.get(
|
||||
AUTH_TOKEN + TOKEN_LOOKUP,
|
||||
singletonMap("token", token),
|
||||
token,
|
||||
TokenResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createOrUpdateRole(final String name, final TokenRole role) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (name == null) {
|
||||
throw new InvalidRequestException("Role name must be provided.");
|
||||
} else if (role == null) {
|
||||
throw new InvalidRequestException("Role must be provided.");
|
||||
}
|
||||
|
||||
// Issue request and expect code 204 with empty response.
|
||||
request.postWithoutResponse(AUTH_TOKEN + TOKEN_ROLES + "/" + name, role, token);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TokenRoleResponse readRole(final String name) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
// Request HTTP response and parse response.
|
||||
return request.get(AUTH_TOKEN + TOKEN_ROLES + "/" + name, emptyMap(), token, TokenRoleResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listRoles() throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
return list(AUTH_TOKEN + TOKEN_ROLES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteRole(final String name) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (name == null) {
|
||||
throw new InvalidRequestException("Role name must be provided.");
|
||||
}
|
||||
|
||||
// Issue request and expect code 204 with empty response.
|
||||
request.deleteWithoutResponse(AUTH_TOKEN + TOKEN_ROLES + "/" + name, token);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-client for AppRole methods.
|
||||
*/
|
||||
public class AppRoleClientImpl implements AppRoleClient {
|
||||
|
||||
@Override
|
||||
public final boolean create(final AppRole role) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(String.format(AUTH_APPROLE_ROLE, role.getName(), ""), role, token);
|
||||
|
||||
/* Set custom ID if provided */
|
||||
return !(role.getId() != null && !role.getId().isEmpty()) || setRoleID(role.getName(), role.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AppRoleResponse lookup(final String roleName) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
/* Request HTTP response and parse Secret */
|
||||
return request.get(
|
||||
String.format(AUTH_APPROLE_ROLE, roleName, ""),
|
||||
emptyMap(),
|
||||
token,
|
||||
AppRoleResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean delete(final String roleName) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.deleteWithoutResponse(String.format(AUTH_APPROLE_ROLE, roleName, ""), token);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getRoleID(final String roleName) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
/* Issue request, parse response and extract Role ID */
|
||||
return request.get(
|
||||
String.format(AUTH_APPROLE_ROLE, roleName, "/role-id"),
|
||||
emptyMap(),
|
||||
token,
|
||||
RawDataResponse.class
|
||||
).getData().get("role_id").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean setRoleID(final String roleName, final String roleID) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(
|
||||
String.format(AUTH_APPROLE_ROLE, roleName, "/role-id"),
|
||||
singletonMap("role_id", roleID),
|
||||
token
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AppRoleSecretResponse createSecret(final String roleName, final AppRoleSecret secret)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
if (secret.getId() != null && !secret.getId().isEmpty()) {
|
||||
return request.post(
|
||||
String.format(AUTH_APPROLE_ROLE, roleName, "/custom-secret-id"),
|
||||
secret,
|
||||
token,
|
||||
AppRoleSecretResponse.class
|
||||
);
|
||||
} else {
|
||||
return request.post(
|
||||
String.format(AUTH_APPROLE_ROLE, roleName, "/secret-id"),
|
||||
secret, token,
|
||||
AppRoleSecretResponse.class
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AppRoleSecretResponse lookupSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and parse secret response */
|
||||
return request.post(
|
||||
String.format(AUTH_APPROLE_ROLE, roleName, "/secret-id/lookup"),
|
||||
new AppRoleSecret(secretID),
|
||||
token,
|
||||
AppRoleSecretResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean destroySecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
/* Issue request and expect code 204 with empty response */
|
||||
request.postWithoutResponse(
|
||||
String.format(AUTH_APPROLE_ROLE, roleName, "/secret-id/destroy"),
|
||||
new AppRoleSecret(secretID),
|
||||
token);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<String> listRoles() throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
SecretListResponse secrets = request.get(
|
||||
AUTH_APPROLE + "/role?list=true",
|
||||
emptyMap(),
|
||||
token,
|
||||
SecretListResponse.class
|
||||
);
|
||||
|
||||
return secrets.getKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<String> listSecrets(final String roleName) throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
SecretListResponse secrets = request.get(
|
||||
String.format(AUTH_APPROLE_ROLE, roleName, "/secret-id?list=true"),
|
||||
emptyMap(),
|
||||
token,
|
||||
SecretListResponse.class
|
||||
);
|
||||
|
||||
return secrets.getKeys();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-client for transit methods.
|
||||
*/
|
||||
public class TransitClientImpl implements TransitClient {
|
||||
@Override
|
||||
public final TransitResponse encrypt(final String keyName, final String plaintext)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"plaintext", plaintext
|
||||
);
|
||||
|
||||
return request.post(TRANSIT_ENCRYPT + keyName, payload, token, TransitResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TransitResponse decrypt(final String keyName, final String ciphertext)
|
||||
throws VaultConnectorException {
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"ciphertext", ciphertext
|
||||
);
|
||||
|
||||
return request.post(TRANSIT_DECRYPT + keyName, payload, token, TransitResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TransitResponse hash(final String algorithm, final String input, final String format)
|
||||
throws VaultConnectorException {
|
||||
if (format != null && !"hex".equals(format) && !"base64".equals(format)) {
|
||||
throw new IllegalArgumentException("Unsupported format " + format);
|
||||
}
|
||||
|
||||
requireAuth();
|
||||
|
||||
Map<String, Object> payload = mapOf(
|
||||
"input", input,
|
||||
"format", format
|
||||
);
|
||||
|
||||
return request.post(TRANSIT_HASH + algorithm, payload, token, TransitResponse.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-client for system methods.
|
||||
*/
|
||||
public class SysClientImpl implements SysClient {
|
||||
|
||||
@Override
|
||||
public final SealResponse sealStatus() throws VaultConnectorException {
|
||||
return request.get(SYS_SEAL_STATUS, emptyMap(), token, SealResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void seal() throws VaultConnectorException {
|
||||
request.put(SYS_SEAL, emptyMap(), token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SealResponse unseal(final String key, final Boolean reset) throws VaultConnectorException {
|
||||
Map<String, String> param = mapOfStrings(
|
||||
"key", key,
|
||||
"reset", reset
|
||||
);
|
||||
|
||||
return request.put(SYS_UNSEAL, param, token, SealResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HealthResponse getHealth() throws VaultConnectorException {
|
||||
|
||||
return request.get(
|
||||
SYS_HEALTH,
|
||||
// Force status code to be 200, so we don't need to modify the request sequence.
|
||||
Map.of(
|
||||
"standbycode", "200", // Default: 429.
|
||||
"sealedcode", "200", // Default: 503.
|
||||
"uninitcode", "200" // Default: 501.
|
||||
),
|
||||
token,
|
||||
HealthResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<AuthBackend> getAuthBackends() throws VaultConnectorException {
|
||||
/* Issue request and parse response */
|
||||
AuthMethodsResponse amr = request.get(SYS_AUTH, emptyMap(), token, AuthMethodsResponse.class);
|
||||
|
||||
return amr.getSupportedMethods().values().stream().map(AuthMethod::getType).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
200
src/main/java/de/stklcode/jvault/connector/KV2Client.java
Normal file
200
src/main/java/de/stklcode/jvault/connector/KV2Client.java
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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.exception.VaultConnectorException;
|
||||
import de.stklcode.jvault.connector.model.response.MetadataResponse;
|
||||
import de.stklcode.jvault.connector.model.response.SecretResponse;
|
||||
import de.stklcode.jvault.connector.model.response.SecretVersionResponse;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* KV v2 client interface.
|
||||
* Provides methods to interact with Vault's KV v2 API.
|
||||
*
|
||||
* @since 2.0.0 extracted from {@link VaultConnector}
|
||||
*/
|
||||
public interface KV2Client {
|
||||
|
||||
/**
|
||||
* Retrieve the latest secret data for specific version from Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/data/<key>} is read here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @return Secret response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
default SecretResponse readData(final String mount, final String key) throws VaultConnectorException {
|
||||
return readVersion(mount, key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/data/<key>} is written here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @param data Secret content. Value must be be JSON serializable.
|
||||
* @return Metadata for the created/updated secret.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
default SecretVersionResponse writeData(final String mount,
|
||||
final String key,
|
||||
final Map<String, Object> data) throws VaultConnectorException {
|
||||
return writeData(mount, key, data, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/data/<key>} is written here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @param data Secret content. Value must be be JSON serializable.
|
||||
* @param cas Use Check-And-Set operation, i.e. only allow writing if current version matches this value.
|
||||
* @return Metadata for the created/updated secret.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
SecretVersionResponse writeData(final String mount,
|
||||
final String key,
|
||||
final Map<String, Object> data,
|
||||
final Integer cas) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve secret data from Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/data/<key>} is read here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @param version Version to read. If {@code null} or zero, the latest version will be returned.
|
||||
* @return Secret response.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
SecretResponse readVersion(final String mount, final String key, final Integer version)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve secret metadata from Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/metadata/<key>} is read here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @return Metadata response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
MetadataResponse readMetadata(final String mount, final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Update secret metadata.
|
||||
* <br>
|
||||
* Path {@code <mount>/metadata/<key>} is written here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @param maxVersions Maximum number of versions (fallback to backend default if {@code null})
|
||||
* @param casRequired Specify if Check-And-Set is required for this secret.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void updateMetadata(final String mount,
|
||||
final String key,
|
||||
final Integer maxVersions,
|
||||
final boolean casRequired) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete latest version of a secret from Vault.
|
||||
* <br>
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret path.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void deleteLatestVersion(final String mount, final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete latest version of a secret from Vault.
|
||||
* <br>
|
||||
* Prefix {@code secret/} is automatically added to path.
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret path.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void deleteAllVersions(final String mount, final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete secret versions from Vault.
|
||||
* <br>
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret path.
|
||||
* @param versions Versions of the secret to delete.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void deleteVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Undelete (restore) secret versions from Vault.
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret path.
|
||||
* @param versions Versions of the secret to undelete.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void undeleteVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Destroy secret versions from Vault.
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret path.
|
||||
* @param versions Versions of the secret to destroy.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void destroyVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException;
|
||||
}
|
88
src/main/java/de/stklcode/jvault/connector/SysClient.java
Normal file
88
src/main/java/de/stklcode/jvault/connector/SysClient.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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.exception.VaultConnectorException;
|
||||
import de.stklcode.jvault.connector.model.AuthBackend;
|
||||
import de.stklcode.jvault.connector.model.Token;
|
||||
import de.stklcode.jvault.connector.model.TokenRole;
|
||||
import de.stklcode.jvault.connector.model.response.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sys client interface.
|
||||
* Provides methods to interact with Vault's system API.
|
||||
*
|
||||
* @since 2.0.0 extracted from {@link VaultConnector}
|
||||
*/
|
||||
public interface SysClient {
|
||||
|
||||
/**
|
||||
* Retrieve status of vault seal.
|
||||
*
|
||||
* @return Seal status
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
SealResponse sealStatus() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Seal vault.
|
||||
*
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
void seal() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Unseal vault.
|
||||
*
|
||||
* @param key A single master share key
|
||||
* @param reset Discard previously provided keys (optional)
|
||||
* @return Response with seal status
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
SealResponse unseal(final String key, final Boolean reset) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Unseal vault.
|
||||
*
|
||||
* @param key A single master share key
|
||||
* @return Response with seal status
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
default SealResponse unseal(final String key) throws VaultConnectorException {
|
||||
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 available authentication backends.
|
||||
*
|
||||
* @return List of backends
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<AuthBackend> getAuthBackends() throws VaultConnectorException;
|
||||
|
||||
}
|
125
src/main/java/de/stklcode/jvault/connector/TokenClient.java
Normal file
125
src/main/java/de/stklcode/jvault/connector/TokenClient.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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.exception.VaultConnectorException;
|
||||
import de.stklcode.jvault.connector.model.Token;
|
||||
import de.stklcode.jvault.connector.model.TokenRole;
|
||||
import de.stklcode.jvault.connector.model.response.AuthResponse;
|
||||
import de.stklcode.jvault.connector.model.response.TokenResponse;
|
||||
import de.stklcode.jvault.connector.model.response.TokenRoleResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Token client interface.
|
||||
* Provides methods to interact with Vault's token API.
|
||||
*
|
||||
* @since 2.0.0 extracted from {@link VaultConnector}
|
||||
*/
|
||||
public interface TokenClient {
|
||||
|
||||
/**
|
||||
* Create a new token.
|
||||
*
|
||||
* @param token the token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
AuthResponse create(final Token token) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Create a new token.
|
||||
*
|
||||
* @param token the token
|
||||
* @param orphan create orphan token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
AuthResponse create(final Token token, boolean orphan) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Create a new token for specific role.
|
||||
*
|
||||
* @param token the token
|
||||
* @param role the role name
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
AuthResponse create(final Token token, final String role) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup token information.
|
||||
*
|
||||
* @param token the token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
TokenResponse lookup(final String token) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Create a new or update an existing token role.
|
||||
*
|
||||
* @param role the role entity (name must be set)
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.9
|
||||
*/
|
||||
default boolean createOrUpdateRole(final TokenRole role) throws VaultConnectorException {
|
||||
return createOrUpdateRole(role.getName(), role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new or update an existing token role.
|
||||
*
|
||||
* @param name the role name (overrides name possibly set in role entity)
|
||||
* @param role the role entity
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.9
|
||||
*/
|
||||
boolean createOrUpdateRole(final String name, final TokenRole role) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup token information.
|
||||
*
|
||||
* @param name the role name
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.9
|
||||
*/
|
||||
TokenRoleResponse readRole(final String name) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List available token roles from Vault.
|
||||
*
|
||||
* @return List of token roles
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.9
|
||||
*/
|
||||
List<String> listRoles() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete a token role.
|
||||
*
|
||||
* @param name the role name to delete
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.9
|
||||
*/
|
||||
boolean deleteRole(final String name) throws VaultConnectorException;
|
||||
}
|
107
src/main/java/de/stklcode/jvault/connector/TransitClient.java
Normal file
107
src/main/java/de/stklcode/jvault/connector/TransitClient.java
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2016-2025 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.exception.VaultConnectorException;
|
||||
import de.stklcode.jvault.connector.model.response.TransitResponse;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* Transit client interface.
|
||||
* Provides methods to interact with Vault's transit API.
|
||||
*
|
||||
* @since 2.0.0 extracted from {@link VaultConnector}
|
||||
*/
|
||||
public interface TransitClient {
|
||||
|
||||
/**
|
||||
* Encrypt plaintext via transit engine from Vault.
|
||||
*
|
||||
* @param keyName Transit key name
|
||||
* @param plaintext Text to encrypt (Base64 encoded)
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
TransitResponse encrypt(final String keyName, final String plaintext) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Encrypt plaintext via transit engine from Vault.
|
||||
*
|
||||
* @param keyName Transit key name
|
||||
* @param plaintext Binary data to encrypt
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
default TransitResponse encrypt(final String keyName, final byte[] plaintext)
|
||||
throws VaultConnectorException {
|
||||
return encrypt(keyName, Base64.getEncoder().encodeToString(plaintext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt ciphertext via transit engine from Vault.
|
||||
*
|
||||
* @param keyName Transit key name
|
||||
* @param ciphertext Text to decrypt
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
TransitResponse decrypt(final String keyName, final String ciphertext) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Hash data in hex format via transit engine from Vault.
|
||||
*
|
||||
* @param algorithm Specifies the hash algorithm to use
|
||||
* @param input Data to hash
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
default TransitResponse hash(final String algorithm, final String input) throws VaultConnectorException {
|
||||
return hash(algorithm, input, "hex");
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash data via transit engine from Vault.
|
||||
*
|
||||
* @param algorithm Specifies the hash algorithm to use
|
||||
* @param input Data to hash (Base64 encoded)
|
||||
* @param format Specifies the output encoding (hex/base64)
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
TransitResponse hash(final String algorithm, final String input, final String format)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Hash data via transit engine from Vault.
|
||||
*
|
||||
* @param algorithm Specifies the hash algorithm to use
|
||||
* @param input Data to hash
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
default TransitResponse hash(final String algorithm, final byte[] input, final String format)
|
||||
throws VaultConnectorException {
|
||||
return hash(algorithm, Base64.getEncoder().encodeToString(input), format);
|
||||
}
|
||||
}
|
@@ -37,59 +37,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
void resetAuth();
|
||||
|
||||
/**
|
||||
* Retrieve status of vault seal.
|
||||
*
|
||||
* @return Seal status
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
SealResponse sealStatus() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Seal vault.
|
||||
*
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
void seal() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Unseal vault.
|
||||
*
|
||||
* @param key A single master share key
|
||||
* @param reset Discard previously provided keys (optional)
|
||||
* @return Response with seal status
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
SealResponse unseal(final String key, final Boolean reset) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Unseal vault.
|
||||
*
|
||||
* @param key A single master share key
|
||||
* @return Response with seal status
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
default SealResponse unseal(final String key) throws VaultConnectorException {
|
||||
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 available authentication backends.
|
||||
*
|
||||
* @return List of backends
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<AuthBackend> getAuthBackends() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Authorize to Vault using token.
|
||||
*
|
||||
@@ -132,187 +79,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
AuthResponse authAppRole(final String roleID, final String secretID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register a new AppRole role from given metamodel.
|
||||
*
|
||||
* @param role The role
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean createAppRole(final AppRole role) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new AppRole role with default policy.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName) throws VaultConnectorException {
|
||||
return createAppRole(roleName, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with policies.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param policies The policies to associate with
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName, final List<String> policies) throws VaultConnectorException {
|
||||
return createAppRole(roleName, policies, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with default policy and custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param roleID A custom role ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName, final String roleID) throws VaultConnectorException {
|
||||
return createAppRole(roleName, new ArrayList<>(), roleID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole role with policies and custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param policies The policies to associate with
|
||||
* @param roleID A custom role ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default boolean createAppRole(final String roleName, final List<String> policies, final String roleID)
|
||||
throws VaultConnectorException {
|
||||
return createAppRole(AppRole.builder(roleName).withTokenPolicies(policies).withId(roleID).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete AppRole role from Vault.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
boolean deleteAppRole(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return Result of the lookup
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleResponse lookupAppRole(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve ID for an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return The role ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
String getAppRoleID(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Set custom ID for an AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param roleID The role ID
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean setAppRoleID(final String roleName, final String roleID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Register new random generated AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AppRoleSecretResponse createAppRoleSecret(final String roleName) throws VaultConnectorException {
|
||||
return createAppRoleSecret(roleName, new AppRoleSecret());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole secret with custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID A custom secret ID
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
default AppRoleSecretResponse createAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException {
|
||||
return createAppRoleSecret(roleName, new AppRoleSecret(secretID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new AppRole secret with custom ID.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secret The secret meta object
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse createAppRoleSecret(final String roleName, final AppRoleSecret secret)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup an AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID The secret ID
|
||||
* @return Result of the lookup
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
AppRoleSecretResponse lookupAppRoleSecret(final String roleName, final String secretID)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Destroy an AppRole secret.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @param secretID The secret meta object
|
||||
* @return The secret ID
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.4.0
|
||||
*/
|
||||
boolean destroyAppRoleSecret(final String roleName, final String secretID) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List existing (accessible) AppRole roles.
|
||||
*
|
||||
* @return List of roles
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<String> listAppRoles() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List existing (accessible) secret IDs for AppRole role.
|
||||
*
|
||||
* @param roleName The role name
|
||||
* @return List of roles
|
||||
* @throws VaultConnectorException on error
|
||||
*/
|
||||
List<String> listAppRoleSecrets(final String roleName) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Get authorization status.
|
||||
*
|
||||
@@ -330,108 +96,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
SecretResponse read(final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve the latest secret data for specific version from Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/data/<key>} is read here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @return Secret response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
default SecretResponse readSecretData(final String mount, final String key) throws VaultConnectorException {
|
||||
return readSecretVersion(mount, key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/data/<key>} is written here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @param data Secret content. Value must be be JSON serializable.
|
||||
* @return Metadata for the created/updated secret.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
default SecretVersionResponse writeSecretData(final String mount,
|
||||
final String key,
|
||||
final Map<String, Object> data) throws VaultConnectorException {
|
||||
return writeSecretData(mount, key, data, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write secret to Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/data/<key>} is written here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @param data Secret content. Value must be be JSON serializable.
|
||||
* @param cas Use Check-And-Set operation, i.e. only allow writing if current version matches this value.
|
||||
* @return Metadata for the created/updated secret.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
SecretVersionResponse writeSecretData(final String mount,
|
||||
final String key,
|
||||
final Map<String, Object> data,
|
||||
final Integer cas) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve secret data from Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/data/<key>} is read here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @param version Version to read. If {@code null} or zero, the latest version will be returned.
|
||||
* @return Secret response.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
SecretResponse readSecretVersion(final String mount, final String key, final Integer version)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Retrieve secret metadata from Vault.
|
||||
* <br>
|
||||
* Path {@code <mount>/metadata/<key>} is read here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @return Metadata response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
MetadataResponse readSecretMetadata(final String mount, final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Update secret metadata.
|
||||
* <br>
|
||||
* Path {@code <mount>/metadata/<key>} is written here.
|
||||
* Only available for KV v2 secrets.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret identifier
|
||||
* @param maxVersions Maximum number of versions (fallback to backend default if {@code null})
|
||||
* @param casRequired Specify if Check-And-Set is required for this secret.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void updateSecretMetadata(final String mount,
|
||||
final String key,
|
||||
final Integer maxVersions,
|
||||
final boolean casRequired) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List available nodes from Vault.
|
||||
*
|
||||
@@ -487,71 +151,6 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
*/
|
||||
void delete(final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete latest version of a secret from Vault.
|
||||
* <br>
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret path.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void deleteLatestSecretVersion(final String mount, final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete latest version of a secret from Vault.
|
||||
* <br>
|
||||
* Prefix {@code secret/} is automatically added to path.
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret path.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void deleteAllSecretVersions(final String mount, final String key) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete secret versions from Vault.
|
||||
* <br>
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret path.
|
||||
* @param versions Versions of the secret to delete.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void deleteSecretVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Undelete (restore) secret versions from Vault.
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret path.
|
||||
* @param versions Versions of the secret to undelete.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void undeleteSecretVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Destroy secret versions from Vault.
|
||||
* Only available for KV v2 stores.
|
||||
*
|
||||
* @param mount Secret store mount point (without leading or trailing slash).
|
||||
* @param key Secret path.
|
||||
* @param versions Versions of the secret to destroy.
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.8
|
||||
*/
|
||||
void destroySecretVersions(final String mount, final String key, final int... versions)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Revoke given lease immediately.
|
||||
*
|
||||
@@ -582,170 +181,44 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
SecretResponse renew(final String leaseID, final Integer increment) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Create a new token.
|
||||
* Get client for KV v2 API.
|
||||
*
|
||||
* @param token the token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
* @return KV v2 client
|
||||
* @since 2.0.0
|
||||
*/
|
||||
AuthResponse createToken(final Token token) throws VaultConnectorException;
|
||||
KV2Client kv2();
|
||||
|
||||
/**
|
||||
* Create a new token.
|
||||
* Get client for token API.
|
||||
*
|
||||
* @param token the token
|
||||
* @param orphan create orphan token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
* @return Token client
|
||||
* @since 2.0.0
|
||||
*/
|
||||
AuthResponse createToken(final Token token, boolean orphan) throws VaultConnectorException;
|
||||
TokenClient token();
|
||||
|
||||
/**
|
||||
* Create a new token for specific role.
|
||||
* Get client for AppRole API.
|
||||
*
|
||||
* @param token the token
|
||||
* @param role the role name
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
* @return AppRole client
|
||||
* @since 2.0.0
|
||||
*/
|
||||
AuthResponse createToken(final Token token, final String role) throws VaultConnectorException;
|
||||
AppRoleClient appRole();
|
||||
|
||||
/**
|
||||
* Lookup token information.
|
||||
* Get client for transit API.
|
||||
*
|
||||
* @param token the token
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
* @return Transit client
|
||||
* @since 2.0.0
|
||||
*/
|
||||
TokenResponse lookupToken(final String token) throws VaultConnectorException;
|
||||
TransitClient transit();
|
||||
|
||||
/**
|
||||
* Create a new or update an existing token role.
|
||||
* Get client for system API.
|
||||
*
|
||||
* @param role the role entity (name must be set)
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.9
|
||||
* @return System client
|
||||
* @since 2.0.0
|
||||
*/
|
||||
default boolean createOrUpdateTokenRole(final TokenRole role) throws VaultConnectorException {
|
||||
return createOrUpdateTokenRole(role.getName(), role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new or update an existing token role.
|
||||
*
|
||||
* @param name the role name (overrides name possibly set in role entity)
|
||||
* @param role the role entity
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.9
|
||||
*/
|
||||
boolean createOrUpdateTokenRole(final String name, final TokenRole role) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Lookup token information.
|
||||
*
|
||||
* @param name the role name
|
||||
* @return the result response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.9
|
||||
*/
|
||||
TokenRoleResponse readTokenRole(final String name) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* List available token roles from Vault.
|
||||
*
|
||||
* @return List of token roles
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.9
|
||||
*/
|
||||
List<String> listTokenRoles() throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Delete a token role.
|
||||
*
|
||||
* @param name the role name to delete
|
||||
* @return {@code true} on success
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 0.9
|
||||
*/
|
||||
boolean deleteTokenRole(final String name) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Encrypt plaintext via transit engine from Vault.
|
||||
*
|
||||
* @param keyName Transit key name
|
||||
* @param plaintext Text to encrypt (Base64 encoded)
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
TransitResponse transitEncrypt(final String keyName, final String plaintext) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Encrypt plaintext via transit engine from Vault.
|
||||
*
|
||||
* @param keyName Transit key name
|
||||
* @param plaintext Binary data to encrypt
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
default TransitResponse transitEncrypt(final String keyName, final byte[] plaintext)
|
||||
throws VaultConnectorException {
|
||||
return transitEncrypt(keyName, Base64.getEncoder().encodeToString(plaintext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt ciphertext via transit engine from Vault.
|
||||
*
|
||||
* @param keyName Transit key name
|
||||
* @param ciphertext Text to decrypt
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
TransitResponse transitDecrypt(final String keyName, final String ciphertext) throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Hash data in hex format via transit engine from Vault.
|
||||
*
|
||||
* @param algorithm Specifies the hash algorithm to use
|
||||
* @param input Data to hash
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
default TransitResponse transitHash(final String algorithm, final String input) throws VaultConnectorException {
|
||||
return transitHash(algorithm, input, "hex");
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash data via transit engine from Vault.
|
||||
*
|
||||
* @param algorithm Specifies the hash algorithm to use
|
||||
* @param input Data to hash (Base64 encoded)
|
||||
* @param format Specifies the output encoding (hex/base64)
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
TransitResponse transitHash(final String algorithm, final String input, final String format)
|
||||
throws VaultConnectorException;
|
||||
|
||||
/**
|
||||
* Hash data via transit engine from Vault.
|
||||
*
|
||||
* @param algorithm Specifies the hash algorithm to use
|
||||
* @param input Data to hash
|
||||
* @return Transit response
|
||||
* @throws VaultConnectorException on error
|
||||
* @since 1.5.0
|
||||
*/
|
||||
default TransitResponse transitHash(final String algorithm, final byte[] input, final String format)
|
||||
throws VaultConnectorException {
|
||||
return transitHash(algorithm, Base64.getEncoder().encodeToString(input), format);
|
||||
}
|
||||
SysClient sys();
|
||||
|
||||
/**
|
||||
* Read credentials for MySQL backend at default mount point.
|
||||
@@ -816,4 +289,5 @@ public interface VaultConnector extends AutoCloseable, Serializable {
|
||||
throws VaultConnectorException {
|
||||
return (CredentialsResponse) read(mount + "/creds/" + role);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -25,7 +25,6 @@ import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -264,9 +263,9 @@ public final class RequestHelper implements Serializable {
|
||||
|
||||
if (!payload.isEmpty()) {
|
||||
uriBuilder.append("?").append(
|
||||
payload.entrySet().stream()
|
||||
.map(par -> encode(par.getKey()) + "=" + encode(par.getValue()))
|
||||
.collect(Collectors.joining("&"))
|
||||
payload.entrySet().stream().map(par ->
|
||||
URLEncoder.encode(par.getKey(), UTF_8) + "=" + URLEncoder.encode(par.getValue(), UTF_8)
|
||||
).collect(Collectors.joining("&"))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -308,17 +307,6 @@ public final class RequestHelper implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode URL part.
|
||||
*
|
||||
* @param part Path part to URL-encode and insert into the template
|
||||
* @return Encoded URL part
|
||||
* @since 1.5.3
|
||||
*/
|
||||
public static String encode(final String part) {
|
||||
return URLEncoder.encode(Objects.requireNonNullElse(part, ""), UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute prepared HTTP request and return result.
|
||||
*
|
||||
|
@@ -40,8 +40,8 @@ public final class VaultApiPath {
|
||||
// Auth paths
|
||||
public static final String AUTH_TOKEN = AUTH + "/token";
|
||||
public static final String AUTH_USERPASS_LOGIN = AUTH + "/userpass/login/";
|
||||
public static final String AUTH_APPROLE = AUTH + "/approle/";
|
||||
public static final String AUTH_APPROLE_ROLE = AUTH_APPROLE + "role/";
|
||||
public static final String AUTH_APPROLE = AUTH + "/approle";
|
||||
public static final String AUTH_APPROLE_ROLE = AUTH_APPROLE + "/role/%s%s";
|
||||
|
||||
// Token operations
|
||||
public static final String TOKEN_LOOKUP = "/lookup";
|
||||
@@ -57,6 +57,9 @@ public final class VaultApiPath {
|
||||
public static final String SECRET_UNDELETE = "/undelete/";
|
||||
public static final String SECRET_DESTROY = "/destroy/";
|
||||
|
||||
// Generic paths
|
||||
public static final String LOGIN = "/login";
|
||||
|
||||
// Transit engine paths
|
||||
public static final String TRANSIT_ENCRYPT = TRANSIT + "/encrypt/";
|
||||
public static final String TRANSIT_DECRYPT = TRANSIT + "/decrypt/";
|
||||
|
@@ -32,7 +32,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class AppRoleSecret implements Serializable {
|
||||
private static final long serialVersionUID = 3079272087137299819L;
|
||||
private static final long serialVersionUID = -3401074170145792641L;
|
||||
|
||||
@JsonProperty("secret_id")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@@ -47,8 +47,6 @@ public final class AppRoleSecret implements Serializable {
|
||||
|
||||
private List<String> cidrList;
|
||||
|
||||
private List<String> tokenBoundCidrs;
|
||||
|
||||
@JsonProperty(value = "creation_time", access = JsonProperty.Access.WRITE_ONLY)
|
||||
private String creationTime;
|
||||
|
||||
@@ -139,36 +137,6 @@ public final class AppRoleSecret implements Serializable {
|
||||
return String.join(",", cidrList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of bound CIDR subnets of associated tokens
|
||||
* @since 1.5.3
|
||||
*/
|
||||
public List<String> getTokenBoundCidrs() {
|
||||
return tokenBoundCidrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boundCidrList list of subnets in CIDR notation to bind role to
|
||||
* @since 1.5.3
|
||||
*/
|
||||
@JsonSetter("token_bound_cidrs")
|
||||
public void setTokenBoundCidrs(final List<String> boundCidrList) {
|
||||
this.tokenBoundCidrs = boundCidrList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of subnets in CIDR notation as comma-separated {@link String}
|
||||
* @since 1.5.3
|
||||
*/
|
||||
@JsonGetter("token_bound_cidrs")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public String getTokenBoundCidrsString() {
|
||||
if (tokenBoundCidrs == null || tokenBoundCidrs.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return String.join(",", tokenBoundCidrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Creation time
|
||||
*/
|
||||
@@ -216,7 +184,6 @@ public final class AppRoleSecret implements Serializable {
|
||||
Objects.equals(accessor, that.accessor) &&
|
||||
Objects.equals(metadata, that.metadata) &&
|
||||
Objects.equals(cidrList, that.cidrList) &&
|
||||
Objects.equals(tokenBoundCidrs, that.tokenBoundCidrs) &&
|
||||
Objects.equals(creationTime, that.creationTime) &&
|
||||
Objects.equals(expirationTime, that.expirationTime) &&
|
||||
Objects.equals(lastUpdatedTime, that.lastUpdatedTime) &&
|
||||
@@ -226,7 +193,7 @@ public final class AppRoleSecret implements Serializable {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, accessor, metadata, cidrList, tokenBoundCidrs, creationTime, expirationTime,
|
||||
lastUpdatedTime, numUses, ttl);
|
||||
return Objects.hash(id, accessor, metadata, cidrList, creationTime, expirationTime, lastUpdatedTime, numUses,
|
||||
ttl);
|
||||
}
|
||||
}
|
||||
|
@@ -95,10 +95,10 @@ class HTTPVaultConnectorIT {
|
||||
connector = builder.build();
|
||||
|
||||
// Unseal Vault and check result.
|
||||
SealResponse sealStatus = connector.unseal(KEY1);
|
||||
SealResponse sealStatus = connector.sys().unseal(KEY1);
|
||||
assumeTrue(sealStatus != null, "Seal status could not be determined after startup");
|
||||
assumeTrue(sealStatus.isSealed(), "Vault is not sealed after startup");
|
||||
sealStatus = connector.unseal(KEY2);
|
||||
sealStatus = connector.sys().unseal(KEY2);
|
||||
assumeTrue(sealStatus != null, "Seal status could not be determined");
|
||||
assumeFalse(sealStatus.isSealed(), "Vault is not unsealed");
|
||||
assumeTrue(sealStatus.isInitialized(), "Vault is not initialized"); // Initialized flag of Vault 0.11.2 (#20).
|
||||
@@ -337,7 +337,7 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Try to read accessible path with known value.
|
||||
SecretResponse res = assertDoesNotThrow(
|
||||
() -> connector.readSecretData(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readData(MOUNT_KV2, SECRET2_KEY),
|
||||
"Valid secret path could not be read"
|
||||
);
|
||||
assertNotNull(res.getMetadata(), "Metadata not populated for KV v2 secret");
|
||||
@@ -346,7 +346,7 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Try to read different version of same secret.
|
||||
res = assertDoesNotThrow(
|
||||
() -> connector.readSecretVersion(MOUNT_KV2, SECRET2_KEY, 1),
|
||||
() -> connector.kv2().readVersion(MOUNT_KV2, SECRET2_KEY, 1),
|
||||
"Valid secret version could not be read"
|
||||
);
|
||||
assertEquals(1, res.getMetadata().getVersion(), "Unexpected secret version");
|
||||
@@ -365,7 +365,7 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// First get the current version of the secret.
|
||||
MetadataResponse res = assertDoesNotThrow(
|
||||
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
"Reading secret metadata failed"
|
||||
);
|
||||
int currentVersion = res.getMetadata().getCurrentVersion();
|
||||
@@ -374,7 +374,7 @@ class HTTPVaultConnectorIT {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("value", SECRET2_VALUE3);
|
||||
SecretVersionResponse res2 = assertDoesNotThrow(
|
||||
() -> connector.writeSecretData(MOUNT_KV2, SECRET2_KEY, data),
|
||||
() -> connector.kv2().writeData(MOUNT_KV2, SECRET2_KEY, data),
|
||||
"Writing secret to KV v2 store failed"
|
||||
);
|
||||
assertEquals(currentVersion + 1, res2.getMetadata().getVersion(), "Version not updated after writing secret");
|
||||
@@ -382,7 +382,7 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Verify the content.
|
||||
SecretResponse res3 = assertDoesNotThrow(
|
||||
() -> connector.readSecretData(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readData(MOUNT_KV2, SECRET2_KEY),
|
||||
"Reading secret from KV v2 store failed"
|
||||
);
|
||||
assertEquals(SECRET2_VALUE3, res3.get("value"), "Data not updated correctly");
|
||||
@@ -391,13 +391,13 @@ class HTTPVaultConnectorIT {
|
||||
Map<String, Object> data4 = singletonMap("value", SECRET2_VALUE4);
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.writeSecretData(MOUNT_KV2, SECRET2_KEY, data4, currentVersion2 - 1),
|
||||
() -> connector.kv2().writeData(MOUNT_KV2, SECRET2_KEY, data4, currentVersion2 - 1),
|
||||
"Writing secret to KV v2 with invalid CAS value succeeded"
|
||||
);
|
||||
|
||||
// And finally with a correct CAS value.
|
||||
Map<String, Object> data5 = singletonMap("value", SECRET2_VALUE4);
|
||||
assertDoesNotThrow(() -> connector.writeSecretData(MOUNT_KV2, SECRET2_KEY, data5, currentVersion2));
|
||||
assertDoesNotThrow(() -> connector.kv2().writeData(MOUNT_KV2, SECRET2_KEY, data5, currentVersion2));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -412,7 +412,7 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Read current metadata first.
|
||||
MetadataResponse res = assertDoesNotThrow(
|
||||
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
"Reading secret metadata failed"
|
||||
);
|
||||
Integer maxVersions = res.getMetadata().getMaxVersions();
|
||||
@@ -420,13 +420,13 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Now update the metadata.
|
||||
assertDoesNotThrow(
|
||||
() -> connector.updateSecretMetadata(MOUNT_KV2, SECRET2_KEY, maxVersions + 1, true),
|
||||
() -> connector.kv2().updateMetadata(MOUNT_KV2, SECRET2_KEY, maxVersions + 1, true),
|
||||
"Updating secret metadata failed"
|
||||
);
|
||||
|
||||
// And verify the result.
|
||||
res = assertDoesNotThrow(
|
||||
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
"Reading secret metadata failed"
|
||||
);
|
||||
assertEquals(maxVersions + 1, res.getMetadata().getMaxVersions(), "Unexpected maximum number of versions");
|
||||
@@ -444,7 +444,7 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Try to read accessible path with known value.
|
||||
MetadataResponse res = assertDoesNotThrow(
|
||||
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
"Valid secret path could not be read"
|
||||
);
|
||||
assertNotNull(res.getMetadata(), "Metadata not populated for KV v2 secret");
|
||||
@@ -467,21 +467,21 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Try to delete non-existing versions.
|
||||
assertDoesNotThrow(
|
||||
() -> connector.deleteSecretVersions(MOUNT_KV2, SECRET2_KEY, 5, 42),
|
||||
() -> connector.kv2().deleteVersions(MOUNT_KV2, SECRET2_KEY, 5, 42),
|
||||
"Revealed non-existence of secret versions"
|
||||
);
|
||||
assertDoesNotThrow(
|
||||
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
"Revealed non-existence of secret versions"
|
||||
);
|
||||
|
||||
// Now delete existing version and verify.
|
||||
assertDoesNotThrow(
|
||||
() -> connector.deleteSecretVersions(MOUNT_KV2, SECRET2_KEY, 1),
|
||||
() -> connector.kv2().deleteVersions(MOUNT_KV2, SECRET2_KEY, 1),
|
||||
"Deleting existing version failed"
|
||||
);
|
||||
MetadataResponse meta = assertDoesNotThrow(
|
||||
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
"Reading deleted secret metadata failed"
|
||||
);
|
||||
assertNotNull(
|
||||
@@ -491,11 +491,11 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Undelete the just deleted version.
|
||||
assertDoesNotThrow(
|
||||
() -> connector.undeleteSecretVersions(MOUNT_KV2, SECRET2_KEY, 1),
|
||||
() -> connector.kv2().undeleteVersions(MOUNT_KV2, SECRET2_KEY, 1),
|
||||
"Undeleting existing version failed"
|
||||
);
|
||||
meta = assertDoesNotThrow(
|
||||
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
"Reading deleted secret metadata failed"
|
||||
);
|
||||
assertNull(
|
||||
@@ -505,11 +505,11 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Now destroy it.
|
||||
assertDoesNotThrow(
|
||||
() -> connector.destroySecretVersions(MOUNT_KV2, SECRET2_KEY, 1),
|
||||
() -> connector.kv2().destroyVersions(MOUNT_KV2, SECRET2_KEY, 1),
|
||||
"Destroying existing version failed"
|
||||
);
|
||||
meta = assertDoesNotThrow(
|
||||
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
"Reading destroyed secret metadata failed"
|
||||
);
|
||||
assertTrue(
|
||||
@@ -519,11 +519,11 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Delete latest version.
|
||||
assertDoesNotThrow(
|
||||
() -> connector.deleteLatestSecretVersion(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().deleteLatestVersion(MOUNT_KV2, SECRET2_KEY),
|
||||
"Deleting latest version failed"
|
||||
);
|
||||
meta = assertDoesNotThrow(
|
||||
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
"Reading deleted secret metadata failed"
|
||||
);
|
||||
assertNotNull(
|
||||
@@ -533,12 +533,12 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Delete all versions.
|
||||
assertDoesNotThrow(
|
||||
() -> connector.deleteAllSecretVersions(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().deleteAllVersions(MOUNT_KV2, SECRET2_KEY),
|
||||
"Deleting latest version failed"
|
||||
);
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.readSecretMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
() -> connector.kv2().readMetadata(MOUNT_KV2, SECRET2_KEY),
|
||||
"Reading metadata of deleted secret should not succeed"
|
||||
);
|
||||
}
|
||||
@@ -620,21 +620,21 @@ class HTTPVaultConnectorIT {
|
||||
// Try unauthorized access first.
|
||||
assumeFalse(connector.isAuthorized());
|
||||
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.listAppRoles());
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.appRole().listRoles());
|
||||
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.listAppRoleSecrets(""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.appRole().listSecrets(""));
|
||||
|
||||
// Authorize.
|
||||
authRoot();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
// Verify pre-existing rules.
|
||||
List<String> res = assertDoesNotThrow(() -> connector.listAppRoles(), "Role listing failed");
|
||||
List<String> res = assertDoesNotThrow(() -> connector.appRole().listRoles(), "Role listing failed");
|
||||
assertEquals(2, res.size(), "Unexpected number of AppRoles");
|
||||
assertTrue(res.containsAll(List.of(APPROLE_ROLE_NAME, APPROLE_ROLE2_NAME)), "Pre-configured roles not listed");
|
||||
|
||||
// Check secret IDs.
|
||||
res = assertDoesNotThrow(() -> connector.listAppRoleSecrets(APPROLE_ROLE_NAME), "AppRole secret listing failed");
|
||||
res = assertDoesNotThrow(() -> connector.appRole().listSecrets(APPROLE_ROLE_NAME), "AppRole secret listing failed");
|
||||
assertEquals(List.of(APPROLE_SECRET_ACCESSOR), res, "Pre-configured AppRole secret not listed");
|
||||
}
|
||||
|
||||
@@ -647,14 +647,14 @@ class HTTPVaultConnectorIT {
|
||||
void createAppRoleTest() {
|
||||
// Try unauthorized access first.
|
||||
assumeFalse(connector.isAuthorized());
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.createAppRole(new AppRole()));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.lookupAppRole(""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.deleteAppRole(""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.getAppRoleID(""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.setAppRoleID("", ""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.createAppRoleSecret("", ""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.lookupAppRoleSecret("", ""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.destroyAppRoleSecret("", ""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.appRole().create(new AppRole()));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.appRole().lookup(""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.appRole().delete(""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.appRole().getRoleID(""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.appRole().setRoleID("", ""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.appRole().createSecret("", ""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.appRole().lookupSecret("", ""));
|
||||
assertThrows(AuthorizationRequiredException.class, () -> connector.appRole().destroySecret("", ""));
|
||||
|
||||
// Authorize.
|
||||
authRoot();
|
||||
@@ -666,23 +666,23 @@ class HTTPVaultConnectorIT {
|
||||
AppRole role = AppRole.builder(roleName).build();
|
||||
|
||||
// Create role.
|
||||
boolean createRes = assertDoesNotThrow(() -> connector.createAppRole(role), "Role creation failed");
|
||||
boolean createRes = assertDoesNotThrow(() -> connector.appRole().create(role), "Role creation failed");
|
||||
assertTrue(createRes, "Role creation failed");
|
||||
|
||||
// Lookup role.
|
||||
AppRoleResponse res = assertDoesNotThrow(() -> connector.lookupAppRole(roleName), "Role lookup failed");
|
||||
AppRoleResponse res = assertDoesNotThrow(() -> connector.appRole().lookup(roleName), "Role lookup failed");
|
||||
assertNotNull(res.getRole(), "Role lookup returned no role");
|
||||
|
||||
// Lookup role ID.
|
||||
String roleID = assertDoesNotThrow(() -> connector.getAppRoleID(roleName), "Role ID lookup failed");
|
||||
String roleID = assertDoesNotThrow(() -> connector.appRole().getRoleID(roleName), "Role ID lookup failed");
|
||||
assertNotEquals("", roleID, "Role ID lookup returned empty ID");
|
||||
|
||||
// Set custom role ID.
|
||||
String roleID2 = "custom-role-id";
|
||||
assertDoesNotThrow(() -> connector.setAppRoleID(roleName, roleID2), "Setting custom role ID failed");
|
||||
assertDoesNotThrow(() -> connector.appRole().setRoleID(roleName, roleID2), "Setting custom role ID failed");
|
||||
|
||||
// Verify role ID.
|
||||
String res2 = assertDoesNotThrow(() -> connector.getAppRoleID(roleName), "Role ID lookup failed");
|
||||
String res2 = assertDoesNotThrow(() -> connector.appRole().getRoleID(roleName), "Role ID lookup failed");
|
||||
assertEquals(roleID2, res2, "Role ID lookup returned wrong ID");
|
||||
|
||||
// Update role model with custom flags.
|
||||
@@ -691,44 +691,44 @@ class HTTPVaultConnectorIT {
|
||||
.build();
|
||||
|
||||
// Create role.
|
||||
boolean res3 = assertDoesNotThrow(() -> connector.createAppRole(role2), "Role creation failed");
|
||||
boolean res3 = assertDoesNotThrow(() -> connector.appRole().create(role2), "Role creation failed");
|
||||
assertTrue(res3, "No result given");
|
||||
|
||||
// Lookup updated role.
|
||||
res = assertDoesNotThrow(() -> connector.lookupAppRole(roleName), "Role lookup failed");
|
||||
res = assertDoesNotThrow(() -> connector.appRole().lookup(roleName), "Role lookup failed");
|
||||
assertNotNull(res.getRole(), "Role lookup returned no role");
|
||||
assertEquals(321, res.getRole().getTokenPeriod(), "Token period not set for role");
|
||||
|
||||
// Create role by name.
|
||||
String roleName2 = "RoleByName";
|
||||
assertDoesNotThrow(() -> connector.createAppRole(roleName2), "Creation of role by name failed");
|
||||
res = assertDoesNotThrow(() -> connector.lookupAppRole(roleName2), "Creation of role by name failed");
|
||||
assertDoesNotThrow(() -> connector.appRole().create(roleName2), "Creation of role by name failed");
|
||||
res = assertDoesNotThrow(() -> connector.appRole().lookup(roleName2), "Creation of role by name failed");
|
||||
assertNotNull(res.getRole(), "Role lookuo returned not value");
|
||||
|
||||
// Create role by name with custom ID.
|
||||
String roleName3 = "RoleByName";
|
||||
String roleID3 = "RolyByNameID";
|
||||
assertDoesNotThrow(() -> connector.createAppRole(roleName3, roleID3), "Creation of role by name failed");
|
||||
res = assertDoesNotThrow(() -> connector.lookupAppRole(roleName3), "Creation of role by name failed");
|
||||
assertDoesNotThrow(() -> connector.appRole().create(roleName3, roleID3), "Creation of role by name failed");
|
||||
res = assertDoesNotThrow(() -> connector.appRole().lookup(roleName3), "Creation of role by name failed");
|
||||
assertNotNull(res.getRole(), "Role lookuo returned not value");
|
||||
|
||||
res2 = assertDoesNotThrow(() -> connector.getAppRoleID(roleName3), "Creation of role by name failed");
|
||||
res2 = assertDoesNotThrow(() -> connector.appRole().getRoleID(roleName3), "Creation of role by name failed");
|
||||
assertEquals(roleID3, res2, "Role lookuo returned wrong ID");
|
||||
|
||||
// Create role by name with policies.
|
||||
assertDoesNotThrow(
|
||||
() -> connector.createAppRole(roleName3, Collections.singletonList("testpolicy")),
|
||||
() -> connector.appRole().create(roleName3, Collections.singletonList("testpolicy")),
|
||||
"Creation of role by name failed"
|
||||
);
|
||||
res = assertDoesNotThrow(() -> connector.lookupAppRole(roleName3), "Creation of role by name failed");
|
||||
res = assertDoesNotThrow(() -> connector.appRole().lookup(roleName3), "Creation of role by name failed");
|
||||
// Note: As of Vault 0.8.3 default policy is not added automatically, so this test should return 1, not 2.
|
||||
assertEquals(List.of("testpolicy"), res.getRole().getTokenPolicies(), "Role lookup returned unexpected policies");
|
||||
|
||||
// Delete role.
|
||||
assertDoesNotThrow(() -> connector.deleteAppRole(roleName3), "Deletion of role failed");
|
||||
assertDoesNotThrow(() -> connector.appRole().delete(roleName3), "Deletion of role failed");
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.lookupAppRole(roleName3),
|
||||
() -> connector.appRole().lookup(roleName3),
|
||||
"Deleted role could be looked up"
|
||||
);
|
||||
}
|
||||
@@ -745,7 +745,7 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// Create default (random) secret for existing role.
|
||||
AppRoleSecretResponse res = assertDoesNotThrow(
|
||||
() -> connector.createAppRoleSecret(APPROLE_ROLE_NAME),
|
||||
() -> connector.appRole().createSecret(APPROLE_ROLE_NAME),
|
||||
"AppRole secret creation failed"
|
||||
);
|
||||
assertNotNull(res.getSecret(), "No secret returned");
|
||||
@@ -753,26 +753,26 @@ class HTTPVaultConnectorIT {
|
||||
// Create secret with custom ID.
|
||||
String secretID = "customSecretId";
|
||||
res = assertDoesNotThrow(
|
||||
() -> connector.createAppRoleSecret(APPROLE_ROLE_NAME, secretID),
|
||||
() -> connector.appRole().createSecret(APPROLE_ROLE_NAME, secretID),
|
||||
"AppRole secret creation failed"
|
||||
);
|
||||
assertEquals(secretID, res.getSecret().getId(), "Unexpected secret ID returned");
|
||||
|
||||
// Lookup secret.
|
||||
res = assertDoesNotThrow(
|
||||
() -> connector.lookupAppRoleSecret(APPROLE_ROLE_NAME, secretID),
|
||||
() -> connector.appRole().lookupSecret(APPROLE_ROLE_NAME, secretID),
|
||||
"AppRole secret lookup failed"
|
||||
);
|
||||
assertNotNull(res.getSecret(), "No secret information returned");
|
||||
|
||||
// Destroy secret.
|
||||
assertDoesNotThrow(
|
||||
() -> connector.destroyAppRoleSecret(APPROLE_ROLE_NAME, secretID),
|
||||
() -> connector.appRole().destroySecret(APPROLE_ROLE_NAME, secretID),
|
||||
"AppRole secret destruction failed"
|
||||
);
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.lookupAppRoleSecret(APPROLE_ROLE_NAME, secretID),
|
||||
() -> connector.appRole().lookupSecret(APPROLE_ROLE_NAME, secretID),
|
||||
"Destroyed AppRole secret successfully read"
|
||||
);
|
||||
}
|
||||
@@ -825,7 +825,7 @@ class HTTPVaultConnectorIT {
|
||||
.build();
|
||||
|
||||
// Create token.
|
||||
AuthResponse res = assertDoesNotThrow(() -> connector.createToken(token), "Token creation failed");
|
||||
AuthResponse res = assertDoesNotThrow(() -> connector.token().create(token), "Token creation failed");
|
||||
assertNotNull(res, "No result given");
|
||||
assertEquals("test-id", res.getAuth().getClientToken(), "Invalid token ID returned");
|
||||
assertEquals(List.of("root"), res.getAuth().getPolicies(), "Expected inherited root policy");
|
||||
@@ -847,7 +847,7 @@ class HTTPVaultConnectorIT {
|
||||
.withoutDefaultPolicy()
|
||||
.withMeta("foo", "bar")
|
||||
.build();
|
||||
res = assertDoesNotThrow(() -> connector.createToken(token2), "Token creation failed");
|
||||
res = assertDoesNotThrow(() -> connector.token().create(token2), "Token creation failed");
|
||||
assertEquals("test-id2", res.getAuth().getClientToken(), "Invalid token ID returned");
|
||||
assertEquals(List.of("testpolicy"), res.getAuth().getPolicies(), "Invalid policies returned");
|
||||
assertNotNull(res.getAuth().getMetadata(), "Metadata not given");
|
||||
@@ -866,7 +866,7 @@ class HTTPVaultConnectorIT {
|
||||
.build();
|
||||
InvalidResponseException e = assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.createToken(token3),
|
||||
() -> connector.token().create(token3),
|
||||
"Overwriting token should fail as of Vault 0.8.0"
|
||||
);
|
||||
assertEquals(400, e.getStatusCode());
|
||||
@@ -880,7 +880,7 @@ class HTTPVaultConnectorIT {
|
||||
.withoutDefaultPolicy()
|
||||
.withType(Token.Type.BATCH)
|
||||
.build();
|
||||
res = assertDoesNotThrow(() -> connector.createToken(token4), "Token creation failed");
|
||||
res = assertDoesNotThrow(() -> connector.token().create(token4), "Token creation failed");
|
||||
assertTrue(
|
||||
// Expecting batch token. "hvb." Prefix as of Vault 1.10, "b." before.
|
||||
res.getAuth().getClientToken().startsWith("b.") || res.getAuth().getClientToken().startsWith("hvb."),
|
||||
@@ -908,12 +908,12 @@ class HTTPVaultConnectorIT {
|
||||
.withId("my-token")
|
||||
.withType(Token.Type.SERVICE)
|
||||
.build();
|
||||
assertDoesNotThrow(() -> connector.createToken(token), "Token creation failed");
|
||||
assertDoesNotThrow(() -> connector.token().create(token), "Token creation failed");
|
||||
|
||||
authRoot();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
TokenResponse res = assertDoesNotThrow(() -> connector.lookupToken("my-token"), "Token creation failed");
|
||||
TokenResponse res = assertDoesNotThrow(() -> connector.token().lookup("my-token"), "Token creation failed");
|
||||
assertEquals(token.getId(), res.getData().getId(), "Unexpected token ID");
|
||||
assertEquals(1, res.getData().getPolicies().size(), "Unexpected number of policies");
|
||||
assertTrue(res.getData().getPolicies().contains("root"), "Unexpected policy");
|
||||
@@ -936,14 +936,14 @@ class HTTPVaultConnectorIT {
|
||||
final TokenRole role = TokenRole.builder().build();
|
||||
|
||||
boolean creationRes = assertDoesNotThrow(
|
||||
() -> connector.createOrUpdateTokenRole(roleName, role),
|
||||
() -> connector.token().createOrUpdateRole(roleName, role),
|
||||
"Token role creation failed"
|
||||
);
|
||||
assertTrue(creationRes, "Token role creation failed");
|
||||
|
||||
// Read the role.
|
||||
TokenRoleResponse res = assertDoesNotThrow(
|
||||
() -> connector.readTokenRole(roleName),
|
||||
() -> connector.token().readRole(roleName),
|
||||
"Reading token role failed"
|
||||
);
|
||||
assertNotNull(res, "Token role response must not be null");
|
||||
@@ -963,12 +963,12 @@ class HTTPVaultConnectorIT {
|
||||
.build();
|
||||
|
||||
creationRes = assertDoesNotThrow(
|
||||
() -> connector.createOrUpdateTokenRole(role2),
|
||||
() -> connector.token().createOrUpdateRole(role2),
|
||||
"Token role update failed"
|
||||
);
|
||||
assertTrue(creationRes, "Token role update failed");
|
||||
|
||||
res = assertDoesNotThrow(() -> connector.readTokenRole(roleName), "Reading token role failed");
|
||||
res = assertDoesNotThrow(() -> connector.token().readRole(roleName), "Reading token role failed");
|
||||
assertNotNull(res, "Token role response must not be null");
|
||||
assertNotNull(res.getData(), "Token role must not be null");
|
||||
assertEquals(roleName, res.getData().getName(), "Token role name not as expected");
|
||||
@@ -977,15 +977,15 @@ class HTTPVaultConnectorIT {
|
||||
assertEquals(42, res.getData().getTokenNumUses(), "Unexpected number of token uses after update");
|
||||
|
||||
// List roles.
|
||||
List<String> listRes = assertDoesNotThrow(() -> connector.listTokenRoles(), "Listing token roles failed");
|
||||
List<String> listRes = assertDoesNotThrow(() -> connector.token().listRoles(), "Listing token roles failed");
|
||||
assertNotNull(listRes, "Token role list must not be null");
|
||||
assertEquals(List.of(roleName), listRes, "Unexpected token role list");
|
||||
|
||||
// Delete the role.
|
||||
creationRes = assertDoesNotThrow(() -> connector.deleteTokenRole(roleName), "Token role deletion failed");
|
||||
creationRes = assertDoesNotThrow(() -> connector.token().deleteRole(roleName), "Token role deletion failed");
|
||||
assertTrue(creationRes, "Token role deletion failed");
|
||||
assertThrows(InvalidResponseException.class, () -> connector.readTokenRole(roleName), "Reading nonexistent token role should fail");
|
||||
assertThrows(InvalidResponseException.class, () -> connector.listTokenRoles(), "Listing nonexistent token roles should fail");
|
||||
assertThrows(InvalidResponseException.class, () -> connector.token().readRole(roleName), "Reading nonexistent token role should fail");
|
||||
assertThrows(InvalidResponseException.class, () -> connector.token().listRoles(), "Listing nonexistent token roles should fail");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1000,14 +1000,14 @@ class HTTPVaultConnectorIT {
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
TransitResponse transitResponse = assertDoesNotThrow(
|
||||
() -> connector.transitEncrypt("my-key", "dGVzdCBtZQ=="),
|
||||
() -> connector.transit().encrypt("my-key", "dGVzdCBtZQ=="),
|
||||
"Failed to encrypt via transit"
|
||||
);
|
||||
assertNotNull(transitResponse.getCiphertext());
|
||||
assertTrue(transitResponse.getCiphertext().startsWith("vault:v1:"));
|
||||
|
||||
transitResponse = assertDoesNotThrow(
|
||||
() -> connector.transitEncrypt("my-key", "test me".getBytes(UTF_8)),
|
||||
() -> connector.transit().encrypt("my-key", "test me".getBytes(UTF_8)),
|
||||
"Failed to encrypt binary data via transit"
|
||||
);
|
||||
assertNotNull(transitResponse.getCiphertext());
|
||||
@@ -1022,7 +1022,7 @@ class HTTPVaultConnectorIT {
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
TransitResponse transitResponse = assertDoesNotThrow(
|
||||
() -> connector.transitDecrypt("my-key", "vault:v1:1mhLVkBAR2nrFtIkJF/qg57DWfRj0FWgR6tvkGO8XOnL6sw="),
|
||||
() -> connector.transit().decrypt("my-key", "vault:v1:1mhLVkBAR2nrFtIkJF/qg57DWfRj0FWgR6tvkGO8XOnL6sw="),
|
||||
"Failed to decrypt via transit"
|
||||
);
|
||||
|
||||
@@ -1036,21 +1036,21 @@ class HTTPVaultConnectorIT {
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
TransitResponse transitResponse = assertDoesNotThrow(
|
||||
() -> connector.transitHash("sha2-512", "dGVzdCBtZQ=="),
|
||||
() -> connector.transit().hash("sha2-512", "dGVzdCBtZQ=="),
|
||||
"Failed to hash via transit"
|
||||
);
|
||||
|
||||
assertEquals("7677af0ee4effaa9f35e9b1e82d182f79516ab8321786baa23002de7c06851059492dd37d5fc3791f17d81d4b58198d24a6fd8bbd62c42c1c30b371da500f193", transitResponse.getSum());
|
||||
|
||||
TransitResponse transitResponseBase64 = assertDoesNotThrow(
|
||||
() -> connector.transitHash("sha2-256", "dGVzdCBtZQ==", "base64"),
|
||||
() -> connector.transit().hash("sha2-256", "dGVzdCBtZQ==", "base64"),
|
||||
"Failed to hash via transit with base64 output"
|
||||
);
|
||||
|
||||
assertEquals("5DfYkW7cvGLkfy36cXhqmZcygEy9HpnFNB4WWXKOl1M=", transitResponseBase64.getSum());
|
||||
|
||||
transitResponseBase64 = assertDoesNotThrow(
|
||||
() -> connector.transitHash("sha2-256", "test me".getBytes(UTF_8), "base64"),
|
||||
() -> connector.transit().hash("sha2-256", "test me".getBytes(UTF_8), "base64"),
|
||||
"Failed to hash binary data via transit"
|
||||
);
|
||||
|
||||
@@ -1072,7 +1072,7 @@ class HTTPVaultConnectorIT {
|
||||
assumeTrue(connector.isAuthorized());
|
||||
|
||||
List<AuthBackend> supportedBackends = assertDoesNotThrow(
|
||||
() -> connector.getAuthBackends(),
|
||||
() -> connector.sys().getAuthBackends(),
|
||||
"Could not list supported auth backends"
|
||||
);
|
||||
|
||||
@@ -1132,22 +1132,22 @@ class HTTPVaultConnectorIT {
|
||||
@Test
|
||||
@DisplayName("Seal test")
|
||||
void sealTest() throws VaultConnectorException {
|
||||
SealResponse sealStatus = connector.sealStatus();
|
||||
SealResponse sealStatus = connector.sys().sealStatus();
|
||||
assumeFalse(sealStatus.isSealed());
|
||||
|
||||
// Unauthorized sealing should fail.
|
||||
assertThrows(VaultConnectorException.class, connector::seal, "Unauthorized sealing succeeded");
|
||||
assertThrows(VaultConnectorException.class, () -> connector.sys().seal(), "Unauthorized sealing succeeded");
|
||||
assertFalse(sealStatus.isSealed(), "Vault sealed, although sealing failed");
|
||||
|
||||
// Root user should be able to seal.
|
||||
authRoot();
|
||||
assumeTrue(connector.isAuthorized());
|
||||
assertDoesNotThrow(connector::seal, "Sealing failed");
|
||||
sealStatus = connector.sealStatus();
|
||||
assertDoesNotThrow(() -> connector.sys().seal(), "Sealing failed");
|
||||
sealStatus = connector.sys().sealStatus();
|
||||
assertTrue(sealStatus.isSealed(), "Vault not sealed");
|
||||
sealStatus = connector.unseal(KEY2);
|
||||
sealStatus = connector.sys().unseal(KEY2);
|
||||
assertTrue(sealStatus.isSealed(), "Vault unsealed with only 1 key");
|
||||
sealStatus = connector.unseal(KEY3);
|
||||
sealStatus = connector.sys().unseal(KEY3);
|
||||
assertFalse(sealStatus.isSealed(), "Vault not unsealed");
|
||||
}
|
||||
|
||||
@@ -1157,7 +1157,7 @@ class HTTPVaultConnectorIT {
|
||||
@Test
|
||||
@DisplayName("Health test")
|
||||
void healthTest() {
|
||||
HealthResponse res = assertDoesNotThrow(connector::getHealth, "Retrieving health status failed");
|
||||
HealthResponse res = assertDoesNotThrow(() -> connector.sys().getHealth(), "Retrieving health status failed");
|
||||
assertNotNull(res, "Health response should be set");
|
||||
assertEquals(VAULT_VERSION, res.getVersion(), "Unexpected version");
|
||||
assertTrue(res.isInitialized(), "Unexpected init status");
|
||||
@@ -1166,11 +1166,11 @@ class HTTPVaultConnectorIT {
|
||||
|
||||
// No seal vault and verify correct status.
|
||||
authRoot();
|
||||
assertDoesNotThrow(connector::seal, "Unexpected exception on sealing");
|
||||
SealResponse sealStatus = assertDoesNotThrow(connector::sealStatus);
|
||||
assertDoesNotThrow(() -> connector.sys().seal(), "Unexpected exception on sealing");
|
||||
SealResponse sealStatus = assertDoesNotThrow(() -> connector.sys().sealStatus());
|
||||
assumeTrue(sealStatus.isSealed());
|
||||
connector.resetAuth(); // Should work unauthenticated
|
||||
res = assertDoesNotThrow(connector::getHealth, "Retrieving health status failed when sealed");
|
||||
res = assertDoesNotThrow(() -> connector.sys().getHealth(), "Retrieving health status failed when sealed");
|
||||
assertTrue(res.isSealed(), "Unexpected seal status");
|
||||
}
|
||||
|
||||
|
@@ -54,51 +54,51 @@ class HTTPVaultConnectorTest {
|
||||
*/
|
||||
@Test
|
||||
void requestExceptionTest(WireMockRuntimeInfo wireMock) throws IOException, URISyntaxException {
|
||||
HTTPVaultConnector connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withTimeout(250).build();
|
||||
try (var connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withTimeout(250).build()) {
|
||||
// Test invalid response code.
|
||||
final int responseCode = 400;
|
||||
mockHttpResponse(responseCode, "", "application/json");
|
||||
VaultConnectorException e = assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.sys().getHealth(),
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertEquals("Invalid response code", e.getMessage(), "Unexpected exception message");
|
||||
assertEquals(responseCode, ((InvalidResponseException) e).getStatusCode(), "Unexpected status code in exception");
|
||||
assertNull(((InvalidResponseException) e).getResponse(), "Response message where none was expected");
|
||||
|
||||
// Test invalid response code.
|
||||
final int responseCode = 400;
|
||||
mockHttpResponse(responseCode, "", "application/json");
|
||||
VaultConnectorException e = assertThrows(
|
||||
InvalidResponseException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertEquals("Invalid response code", e.getMessage(), "Unexpected exception message");
|
||||
assertEquals(responseCode, ((InvalidResponseException) e).getStatusCode(), "Unexpected status code in exception");
|
||||
assertNull(((InvalidResponseException) e).getResponse(), "Response message where none was expected");
|
||||
|
||||
// Simulate permission denied response.
|
||||
mockHttpResponse(responseCode, "{\"errors\":[\"permission denied\"]}", "application/json");
|
||||
assertThrows(
|
||||
PermissionDeniedException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
// Simulate permission denied response.
|
||||
mockHttpResponse(responseCode, "{\"errors\":[\"permission denied\"]}", "application/json");
|
||||
assertThrows(
|
||||
PermissionDeniedException.class,
|
||||
() -> connector.sys().getHealth(),
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
}
|
||||
|
||||
// Test exception thrown during request.
|
||||
try (ServerSocket s = new ServerSocket(0)) {
|
||||
connector = HTTPVaultConnector.builder("http://localst:" + s.getLocalPort() + "/").withTimeout(250).build();
|
||||
try (ServerSocket s = new ServerSocket(0);
|
||||
var connector = HTTPVaultConnector.builder("http://localst:" + s.getLocalPort() + "/").withTimeout(250).build()) {
|
||||
var e = assertThrows(
|
||||
ConnectionException.class,
|
||||
() -> connector.sys().getHealth(),
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
|
||||
assertInstanceOf(IOException.class, e.getCause(), "Unexpected cause");
|
||||
}
|
||||
e = assertThrows(
|
||||
ConnectionException.class,
|
||||
connector::getHealth,
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
|
||||
assertInstanceOf(IOException.class, e.getCause(), "Unexpected cause");
|
||||
|
||||
// Now simulate a failing request that succeeds on second try.
|
||||
connector = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withNumberOfRetries(1).withTimeout(250).build();
|
||||
|
||||
stubFor(
|
||||
WireMock.any(anyUrl())
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(200).withBody("{}").withHeader("Content-Type", "application/json"))
|
||||
);
|
||||
assertDoesNotThrow(connector::getHealth, "Request failed unexpectedly");
|
||||
try (var connector3 = HTTPVaultConnector.builder(wireMock.getHttpBaseUrl()).withNumberOfRetries(1).withTimeout(250).build()) {
|
||||
stubFor(
|
||||
WireMock.any(anyUrl())
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(500))
|
||||
.willReturn(aResponse().withStatus(200).withBody("{}").withHeader("Content-Type", "application/json"))
|
||||
);
|
||||
assertDoesNotThrow(() -> connector3.sys().getHealth(), "Request failed unexpectedly");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,7 +160,7 @@ class HTTPVaultConnectorTest {
|
||||
}
|
||||
ConnectionException e = assertThrows(
|
||||
ConnectionException.class,
|
||||
connector::sealStatus,
|
||||
() -> connector.sys().sealStatus(),
|
||||
"Querying seal status succeeded on invalid instance"
|
||||
);
|
||||
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
|
||||
@@ -178,7 +178,7 @@ class HTTPVaultConnectorTest {
|
||||
}
|
||||
ConnectionException e = assertThrows(
|
||||
ConnectionException.class,
|
||||
connector::getHealth,
|
||||
() -> connector.sys().getHealth(),
|
||||
"Querying health status succeeded on invalid instance"
|
||||
);
|
||||
assertEquals("Unable to connect to Vault server", e.getMessage(), "Unexpected exception message");
|
||||
@@ -196,21 +196,21 @@ class HTTPVaultConnectorTest {
|
||||
mockHttpResponse(200, "invalid", "application/json");
|
||||
|
||||
// Now test the methods.
|
||||
assertParseError(connector::sealStatus, "sealStatus() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.unseal("key"), "unseal() succeeded on invalid instance");
|
||||
assertParseError(connector::getHealth, "getHealth() succeeded on invalid instance");
|
||||
assertParseError(connector::getAuthBackends, "getAuthBackends() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.sys().sealStatus(), "sys().sealStatus() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.sys().unseal("key"), "sys().unseal() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.sys().getHealth(), "sys().getHealth() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.sys().getAuthBackends(), "sys().getAuthBackends() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.authToken("token"), "authToken() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.lookupAppRole("roleName"), "lookupAppRole() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.getAppRoleID("roleName"), "getAppRoleID() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.createAppRoleSecret("roleName"), "createAppRoleSecret() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.lookupAppRoleSecret("roleName", "secretID"), "lookupAppRoleSecret() succeeded on invalid instance");
|
||||
assertParseError(connector::listAppRoles, "listAppRoles() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.listAppRoleSecrets("roleName"), "listAppRoleSecrets() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.appRole().lookup("roleName"), "appRole().lookup() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.appRole().getRoleID("roleName"), "appRole().getRoleID() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.appRole().createSecret("roleName"), "appRole().createSecret() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.appRole().lookupSecret("roleName", "secretID"), "appRole().lookupSecret() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.appRole().listRoles(), "appRole().listRoles() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.appRole().listSecrets("roleName"), "appRole().listSecrets() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.read("key"), "read() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.list("path"), "list() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.renew("leaseID"), "renew() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.lookupToken("token"), "lookupToken() succeeded on invalid instance");
|
||||
assertParseError(() -> connector.token().lookup("token"), "token().lookup() succeeded on invalid instance");
|
||||
}
|
||||
|
||||
private void assertParseError(Executable executable, String message) {
|
||||
@@ -232,32 +232,32 @@ class HTTPVaultConnectorTest {
|
||||
// Now test the methods expecting a 204.
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.createAppRole("appID", Collections.singletonList("policy")),
|
||||
"createAppRole() with 200 response succeeded"
|
||||
() -> connector.appRole().create("appID", Collections.singletonList("policy")),
|
||||
"appRole().create() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.deleteAppRole("roleName"),
|
||||
"deleteAppRole() with 200 response succeeded"
|
||||
() -> connector.delete("roleName"),
|
||||
"appRole().delete() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.setAppRoleID("roleName", "roleID"),
|
||||
"setAppRoleID() with 200 response succeeded"
|
||||
() -> connector.appRole().setRoleID("roleName", "roleID"),
|
||||
"appRole().setRoleID() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.destroyAppRoleSecret("roleName", "secretID"),
|
||||
"destroyAppRoleSecret() with 200 response succeeded"
|
||||
() -> connector.appRole().destroySecret("roleName", "secretID"),
|
||||
"appRole().destroySecret() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
InvalidResponseException.class,
|
||||
() -> connector.destroyAppRoleSecret("roleName", "secretUD"),
|
||||
"destroyAppRoleSecret() with 200 response succeeded"
|
||||
() -> connector.appRole().destroySecret("roleName", "secretUD"),
|
||||
"appRole().destroySecret() with 200 response succeeded"
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
|
@@ -39,7 +39,6 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
"number", 1337
|
||||
);
|
||||
private static final List<String> TEST_CIDR = List.of("203.0.113.0/24", "198.51.100.0/24");
|
||||
private static final List<String> TEST_TOKEN_CIDR = List.of("192.0.2.0/24", "198.51.100.0/24");
|
||||
|
||||
AppRoleSecretTest() {
|
||||
super(AppRoleSecret.class);
|
||||
@@ -62,8 +61,6 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
assertNull(secret.getMetadata());
|
||||
assertNull(secret.getCidrList());
|
||||
assertEquals("", secret.getCidrListString());
|
||||
assertNull(secret.getTokenBoundCidrs());
|
||||
assertEquals("", secret.getTokenBoundCidrsString());
|
||||
assertNull(secret.getCreationTime());
|
||||
assertNull(secret.getExpirationTime());
|
||||
assertNull(secret.getLastUpdatedTime());
|
||||
@@ -77,8 +74,6 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
assertNull(secret.getMetadata());
|
||||
assertNull(secret.getCidrList());
|
||||
assertEquals("", secret.getCidrListString());
|
||||
assertNull(secret.getTokenBoundCidrs());
|
||||
assertEquals("", secret.getTokenBoundCidrsString());
|
||||
assertNull(secret.getCreationTime());
|
||||
assertNull(secret.getExpirationTime());
|
||||
assertNull(secret.getLastUpdatedTime());
|
||||
@@ -92,8 +87,6 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
assertEquals(TEST_META, secret.getMetadata());
|
||||
assertEquals(TEST_CIDR, secret.getCidrList());
|
||||
assertEquals(String.join(",", TEST_CIDR), secret.getCidrListString());
|
||||
assertNull(secret.getTokenBoundCidrs());
|
||||
assertEquals("", secret.getTokenBoundCidrsString());
|
||||
assertNull(secret.getCreationTime());
|
||||
assertNull(secret.getExpirationTime());
|
||||
assertNull(secret.getLastUpdatedTime());
|
||||
@@ -115,15 +108,6 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
secret.setCidrList(null);
|
||||
assertNull(secret.getCidrList());
|
||||
assertEquals("", secret.getCidrListString());
|
||||
|
||||
assertNull(secret.getTokenBoundCidrs());
|
||||
assertEquals("", secret.getTokenBoundCidrsString());
|
||||
secret.setTokenBoundCidrs(TEST_TOKEN_CIDR);
|
||||
assertEquals(TEST_TOKEN_CIDR, secret.getTokenBoundCidrs());
|
||||
assertEquals(String.join(",", TEST_TOKEN_CIDR), secret.getTokenBoundCidrsString());
|
||||
secret.setTokenBoundCidrs(null);
|
||||
assertNull(secret.getTokenBoundCidrs());
|
||||
assertEquals("", secret.getTokenBoundCidrsString());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,8 +159,7 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
|
||||
// Those fields should be deserialized from JSON though.
|
||||
String secretJson4 = "{\"secret_id\":\"abc123\",\"metadata\":{\"number\":1337,\"foo\":\"bar\"}," +
|
||||
"\"cidr_list\":[\"203.0.113.0/24\",\"198.51.100.0/24\"],\"cidr_list\":[\"192.0.2.0/24\",\"198.51.100.0/24\"]," +
|
||||
"\"secret_id_accessor\":\"TEST_ACCESSOR\"," +
|
||||
"\"cidr_list\":[\"203.0.113.0/24\",\"198.51.100.0/24\"],\"secret_id_accessor\":\"TEST_ACCESSOR\"," +
|
||||
"\"creation_time\":\"TEST_CREATION\",\"expiration_time\":\"TEST_EXPIRATION\"," +
|
||||
"\"last_updated_time\":\"TEST_LASTUPDATE\",\"secret_id_num_uses\":678,\"secret_id_ttl\":12345}";
|
||||
secret2 = assertDoesNotThrow(() -> objectMapper.readValue(secretJson4, AppRoleSecret.class), "Deserialization failed");
|
||||
@@ -198,7 +181,6 @@ class AppRoleSecretTest extends AbstractModelTest<AppRoleSecret> {
|
||||
|
||||
private static String commaSeparatedToList(String json) {
|
||||
return json.replaceAll("\"cidr_list\":\"([^\"]*)\"", "\"cidr_list\":[$1]")
|
||||
.replaceAll("\"token_bound_cidrs\":\"([^\"]*)\"", "\"token_bound_cidrs\":[$1]")
|
||||
.replaceAll("(\\d+\\.\\d+\\.\\d+\\.\\d+/\\d+)", "\"$1\"");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user