Integrate spring-javaformat

Closes gh-564.
This commit is contained in:
Mark Paluch
2020-05-28 10:18:56 +02:00
parent dba4a3facd
commit fb9fcac30d
338 changed files with 4456 additions and 6299 deletions

29
pom.xml
View File

@@ -233,6 +233,21 @@
<build>
<plugins>
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>0.0.22</version>
<executions>
<execution>
<phase>validate</phase>
<inherited>true</inherited>
<goals>
<goal>apply</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
@@ -748,13 +763,13 @@
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>spring-plugins-release</id>
<url>https://repo.spring.io/plugins-release</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<pluginRepositories>
<pluginRepository>
<id>spring-plugins-release</id>
<url>https://repo.spring.io/plugins-release</url>
</pluginRepository>
</pluginRepositories>
</project>

View File

@@ -27,7 +27,6 @@ public class VaultException extends NestedRuntimeException {
/**
* Create a {@code VaultException} with the specified detail message.
*
* @param msg the detail message.
*/
public VaultException(String msg) {
@@ -37,11 +36,11 @@ public class VaultException extends NestedRuntimeException {
/**
* Create a {@code VaultException} with the specified detail message and nested
* exception.
*
* @param msg the detail message.
* @param cause the nested exception.
*/
public VaultException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -131,5 +131,7 @@ public @interface VaultPropertySource {
* expires.
*/
ROTATE;
}
}

View File

@@ -56,8 +56,8 @@ import org.springframework.vault.core.util.PropertyTransformers;
*
* @author Mark Paluch
*/
class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar,
BeanFactoryPostProcessor, EnvironmentAware {
class VaultPropertySourceRegistrar
implements ImportBeanDefinitionRegistrar, BeanFactoryPostProcessor, EnvironmentAware {
private @Nullable Environment environment;
@@ -67,24 +67,21 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar,
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
ConfigurableEnvironment env = beanFactory.getBean(ConfigurableEnvironment.class);
MutablePropertySources propertySources = env.getPropertySources();
registerPropertySources(beanFactory
.getBeansOfType(
org.springframework.vault.core.env.VaultPropertySource.class)
.values(), propertySources);
registerPropertySources(
beanFactory.getBeansOfType(org.springframework.vault.core.env.VaultPropertySource.class).values(),
propertySources);
registerPropertySources(beanFactory.getBeansOfType(
org.springframework.vault.core.env.LeaseAwareVaultPropertySource.class)
.values(), propertySources);
registerPropertySources(beanFactory
.getBeansOfType(org.springframework.vault.core.env.LeaseAwareVaultPropertySource.class).values(),
propertySources);
}
private void registerPropertySources(
Collection<? extends PropertySource<?>> propertySources,
private void registerPropertySources(Collection<? extends PropertySource<?>> propertySources,
MutablePropertySources mutablePropertySources) {
for (PropertySource<?> vaultPropertySource : propertySources) {
@@ -98,23 +95,20 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar,
}
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata,
BeanDefinitionRegistry registry) {
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null");
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (!registry.isBeanNameInUse("VaultPropertySourceRegistrar")) {
registry.registerBeanDefinition("VaultPropertySourceRegistrar",
BeanDefinitionBuilder //
.rootBeanDefinition(VaultPropertySourceRegistrar.class) //
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE) //
.getBeanDefinition());
registry.registerBeanDefinition("VaultPropertySourceRegistrar", BeanDefinitionBuilder //
.rootBeanDefinition(VaultPropertySourceRegistrar.class) //
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE) //
.getBeanDefinition());
}
Set<AnnotationAttributes> propertySources = attributesForRepeatable(
annotationMetadata, VaultPropertySources.class.getName(),
VaultPropertySource.class.getName());
Set<AnnotationAttributes> propertySources = attributesForRepeatable(annotationMetadata,
VaultPropertySources.class.getName(), VaultPropertySource.class.getName());
int counter = 0;
@@ -124,19 +118,14 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar,
String ref = propertySource.getString("vaultTemplateRef");
String propertyNamePrefix = propertySource.getString("propertyNamePrefix");
Renewal renewal = propertySource.getEnum("renewal");
boolean ignoreSecretNotFound = propertySource
.getBoolean("ignoreSecretNotFound");
boolean ignoreSecretNotFound = propertySource.getBoolean("ignoreSecretNotFound");
Assert.isTrue(paths.length > 0,
"At least one @VaultPropertySource(value) location is required");
Assert.isTrue(paths.length > 0, "At least one @VaultPropertySource(value) location is required");
Assert.hasText(ref,
"'vaultTemplateRef' in @EnableVaultPropertySource must not be empty");
Assert.hasText(ref, "'vaultTemplateRef' in @EnableVaultPropertySource must not be empty");
PropertyTransformer propertyTransformer = StringUtils
.hasText(propertyNamePrefix)
? PropertyTransformers.propertyNamePrefix(propertyNamePrefix)
: PropertyTransformers.noop();
PropertyTransformer propertyTransformer = StringUtils.hasText(propertyNamePrefix)
? PropertyTransformers.propertyNamePrefix(propertyNamePrefix) : PropertyTransformers.noop();
for (String propertyPath : paths) {
@@ -144,9 +133,8 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar,
continue;
}
AbstractBeanDefinition beanDefinition = createBeanDefinition(ref, renewal,
propertyTransformer, ignoreSecretNotFound,
potentiallyResolveRequiredPlaceholders(propertyPath));
AbstractBeanDefinition beanDefinition = createBeanDefinition(ref, renewal, propertyTransformer,
ignoreSecretNotFound, potentiallyResolveRequiredPlaceholders(propertyPath));
do {
String beanName = "vaultPropertySource#" + counter;
@@ -164,23 +152,19 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar,
}
private String potentiallyResolveRequiredPlaceholders(String expression) {
return this.environment != null
? this.environment.resolveRequiredPlaceholders(expression)
: expression;
return this.environment != null ? this.environment.resolveRequiredPlaceholders(expression) : expression;
}
private AbstractBeanDefinition createBeanDefinition(String ref, Renewal renewal,
PropertyTransformer propertyTransformer, boolean ignoreResourceNotFound,
String propertyPath) {
PropertyTransformer propertyTransformer, boolean ignoreResourceNotFound, String propertyPath) {
BeanDefinitionBuilder builder;
if (isRenewable(renewal)) {
builder = BeanDefinitionBuilder.rootBeanDefinition(
org.springframework.vault.core.env.LeaseAwareVaultPropertySource.class);
builder = BeanDefinitionBuilder
.rootBeanDefinition(org.springframework.vault.core.env.LeaseAwareVaultPropertySource.class);
RequestedSecret requestedSecret = renewal == Renewal.ROTATE
? RequestedSecret.rotating(propertyPath)
RequestedSecret requestedSecret = renewal == Renewal.ROTATE ? RequestedSecret.rotating(propertyPath)
: RequestedSecret.renewable(propertyPath);
builder.addConstructorArgValue(propertyPath);
@@ -188,8 +172,8 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar,
builder.addConstructorArgValue(requestedSecret);
}
else {
builder = BeanDefinitionBuilder.rootBeanDefinition(
org.springframework.vault.core.env.VaultPropertySource.class);
builder = BeanDefinitionBuilder
.rootBeanDefinition(org.springframework.vault.core.env.VaultPropertySource.class);
builder.addConstructorArgValue(propertyPath);
builder.addConstructorArgReference(ref);
@@ -208,18 +192,15 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar,
}
@SuppressWarnings("unchecked")
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata,
String containerClassName, String annotationClassName) {
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata, String containerClassName,
String annotationClassName) {
Set<AnnotationAttributes> result = new LinkedHashSet<>();
addAttributesIfNotNull(result,
metadata.getAnnotationAttributes(annotationClassName, false));
addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));
Map<String, Object> container = metadata
.getAnnotationAttributes(containerClassName, false);
Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false);
if (container != null && container.containsKey("value")) {
for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container
.get("value")) {
for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container.get("value")) {
addAttributesIfNotNull(result, containedAttributes);
}
}
@@ -232,4 +213,5 @@ class VaultPropertySourceRegistrar implements ImportBeanDefinitionRegistrar,
result.add(AnnotationAttributes.fromMap(attributes));
}
}
}

View File

@@ -42,4 +42,5 @@ import org.springframework.context.annotation.Import;
public @interface VaultPropertySources {
VaultPropertySource[] value();
}

View File

@@ -40,8 +40,7 @@ import org.springframework.web.client.RestOperations;
* @deprecated since 2.2. Use {@link AppRoleAuthentication}.
*/
@Deprecated
public class AppIdAuthentication
implements ClientAuthentication, AuthenticationStepsFactory {
public class AppIdAuthentication implements ClientAuthentication, AuthenticationStepsFactory {
private static final Log logger = LogFactory.getLog(AppIdAuthentication.class);
@@ -52,12 +51,10 @@ public class AppIdAuthentication
/**
* Create a {@link AppIdAuthentication} using {@link AppIdAuthenticationOptions} and
* {@link RestOperations}.
*
* @param options must not be {@literal null}.
* @param restOperations must not be {@literal null}.
*/
public AppIdAuthentication(AppIdAuthenticationOptions options,
RestOperations restOperations) {
public AppIdAuthentication(AppIdAuthenticationOptions options, RestOperations restOperations) {
Assert.notNull(options, "AppIdAuthenticationOptions must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
@@ -69,19 +66,16 @@ public class AppIdAuthentication
/**
* Creates a {@link AuthenticationSteps} for AppId authentication given
* {@link AppIdAuthenticationOptions}.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for AppId authentication.
* @since 2.0
*/
public static AuthenticationSteps createAuthenticationSteps(
AppIdAuthenticationOptions options) {
public static AuthenticationSteps createAuthenticationSteps(AppIdAuthenticationOptions options) {
Assert.notNull(options, "AppIdAuthenticationOptions must not be null");
return AuthenticationSteps
.fromSupplier(() -> getAppIdLogin(options.getAppId(),
options.getUserIdMechanism().createUserId())) //
.fromSupplier(() -> getAppIdLogin(options.getAppId(), options.getUserIdMechanism().createUserId())) //
.login(AuthenticationUtil.getLoginPath(options.getPath()));
}
@@ -92,20 +86,19 @@ public class AppIdAuthentication
@Override
public AuthenticationSteps getAuthenticationSteps() {
return createAuthenticationSteps(options);
return createAuthenticationSteps(this.options);
}
private VaultToken createTokenUsingAppId() {
Map<String, String> login = getAppIdLogin(options.getAppId(),
options.getUserIdMechanism().createUserId());
Map<String, String> login = getAppIdLogin(this.options.getAppId(),
this.options.getUserIdMechanism().createUserId());
try {
VaultResponse response = restOperations.postForObject(AuthenticationUtil.getLoginPath(options.getPath()),
login, VaultResponse.class);
VaultResponse response = this.restOperations
.postForObject(AuthenticationUtil.getLoginPath(this.options.getPath()), login, VaultResponse.class);
Assert.state(response != null && response.getAuth() != null,
"Auth field must not be null");
Assert.state(response != null && response.getAuth() != null, "Auth field must not be null");
logger.debug("Login successful using AppId authentication");
@@ -125,4 +118,5 @@ public class AppIdAuthentication
return login;
}
}

View File

@@ -50,8 +50,7 @@ public class AppIdAuthenticationOptions {
*/
private final AppIdUserIdMechanism userIdMechanism;
private AppIdAuthenticationOptions(String path, String appId,
AppIdUserIdMechanism userIdMechanism) {
private AppIdAuthenticationOptions(String path, String appId, AppIdUserIdMechanism userIdMechanism) {
this.path = path;
this.appId = appId;
@@ -69,21 +68,21 @@ public class AppIdAuthenticationOptions {
* @return the mount path.
*/
public String getPath() {
return path;
return this.path;
}
/**
* @return the AppId.
*/
public String getAppId() {
return appId;
return this.appId;
}
/**
* @return the {@link AppIdUserIdMechanism}.
*/
public AppIdUserIdMechanism getUserIdMechanism() {
return userIdMechanism;
return this.userIdMechanism;
}
/**
@@ -102,7 +101,6 @@ public class AppIdAuthenticationOptions {
/**
* Configure the mount path.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link AppIdAuthenticationOptionsBuilder}.
* @see #DEFAULT_APPID_AUTHENTICATION_PATH
@@ -117,7 +115,6 @@ public class AppIdAuthenticationOptions {
/**
* Configure the AppId.
*
* @param appId must not be empty or {@literal null}.
* @return {@code this} {@link AppIdAuthenticationOptionsBuilder}.
*/
@@ -131,12 +128,10 @@ public class AppIdAuthenticationOptions {
/**
* Configure the {@link AppIdUserIdMechanism}.
*
* @param userIdMechanism must not be {@literal null}.
* @return {@code this} {@link AppIdAuthenticationOptionsBuilder}.
*/
public AppIdAuthenticationOptionsBuilder userIdMechanism(
AppIdUserIdMechanism userIdMechanism) {
public AppIdAuthenticationOptionsBuilder userIdMechanism(AppIdUserIdMechanism userIdMechanism) {
Assert.notNull(userIdMechanism, "AppIdUserIdMechanism must not be null");
@@ -147,15 +142,16 @@ public class AppIdAuthenticationOptions {
/**
* Build a new {@link AppIdAuthenticationOptions} instance. Requires
* {@link #userIdMechanism(AppIdUserIdMechanism)} to be configured.
*
* @return a new {@link AppIdAuthenticationOptions}.
*/
public AppIdAuthenticationOptions build() {
Assert.hasText(appId, "AppId must not be empty");
Assert.notNull(userIdMechanism, "AppIdUserIdMechanism must not be null");
Assert.hasText(this.appId, "AppId must not be empty");
Assert.notNull(this.userIdMechanism, "AppIdUserIdMechanism must not be null");
return new AppIdAuthenticationOptions(path, appId, userIdMechanism);
return new AppIdAuthenticationOptions(this.path, this.appId, this.userIdMechanism);
}
}
}

View File

@@ -30,8 +30,8 @@ public interface AppIdUserIdMechanism {
/**
* Create a UserId for AppId authentication.
*
* @return the UserId.
*/
String createUserId();
}

View File

@@ -63,8 +63,7 @@ import static org.springframework.vault.authentication.AuthenticationUtil.getLog
* @see <a href="https://www.vaultproject.io/docs/auth/approle.html">Auth Backend:
* AppRole</a>
*/
public class AppRoleAuthentication
implements ClientAuthentication, AuthenticationStepsFactory {
public class AppRoleAuthentication implements ClientAuthentication, AuthenticationStepsFactory {
private static final Log logger = LogFactory.getLog(AppRoleAuthentication.class);
@@ -75,12 +74,10 @@ public class AppRoleAuthentication
/**
* Create a {@link AppRoleAuthentication} using {@link AppRoleAuthenticationOptions}
* and {@link RestOperations}.
*
* @param options must not be {@literal null}.
* @param restOperations must not be {@literal null}.
*/
public AppRoleAuthentication(AppRoleAuthenticationOptions options,
RestOperations restOperations) {
public AppRoleAuthentication(AppRoleAuthenticationOptions options, RestOperations restOperations) {
Assert.notNull(options, "AppRoleAuthenticationOptions must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
@@ -92,35 +89,30 @@ public class AppRoleAuthentication
/**
* Creates a {@link AuthenticationSteps} for AppRole authentication given
* {@link AppRoleAuthenticationOptions}.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for AppRole authentication.
* @since 2.0
*/
public static AuthenticationSteps createAuthenticationSteps(
AppRoleAuthenticationOptions options) {
public static AuthenticationSteps createAuthenticationSteps(AppRoleAuthenticationOptions options) {
Assert.notNull(options, "AppRoleAuthenticationOptions must not be null");
RoleId roleId = options.getRoleId();
SecretId secretId = options.getSecretId();
return getAuthenticationSteps(options, roleId, secretId)
.login(getLoginPath(options.getPath()));
return getAuthenticationSteps(options, roleId, secretId).login(getLoginPath(options.getPath()));
}
private static Node<Map<String, String>> getAuthenticationSteps(
AppRoleAuthenticationOptions options, RoleId roleId, SecretId secretId) {
private static Node<Map<String, String>> getAuthenticationSteps(AppRoleAuthenticationOptions options, RoleId roleId,
SecretId secretId) {
Node<String> roleIdSteps = getRoleIdSteps(options, roleId);
Node<String> secretIdSteps = getSecretIdSteps(options, secretId);
return roleIdSteps.zipWith(secretIdSteps)
.map(it -> getAppRoleLoginBody(it.getLeft(), it.getRight()));
return roleIdSteps.zipWith(secretIdSteps).map(it -> getAppRoleLoginBody(it.getLeft(), it.getRight()));
}
private static Node<String> getRoleIdSteps(AppRoleAuthenticationOptions options,
RoleId roleId) {
private static Node<String> getRoleIdSteps(AppRoleAuthenticationOptions options, RoleId roleId) {
if (roleId instanceof Provided) {
return AuthenticationSteps.fromSupplier(((Provided) roleId)::getValue);
@@ -131,24 +123,19 @@ public class AppRoleAuthentication
HttpHeaders headers = createHttpHeaders(((Pull) roleId).getInitialToken());
return AuthenticationSteps
.fromHttpRequest(get(getRoleIdIdPath(options)).with(headers)
.as(VaultResponse.class))
.map(vaultResponse -> (String) vaultResponse.getRequiredData()
.get("role_id"));
.fromHttpRequest(get(getRoleIdIdPath(options)).with(headers).as(VaultResponse.class))
.map(vaultResponse -> (String) vaultResponse.getRequiredData().get("role_id"));
}
if (roleId instanceof Wrapped) {
return unwrapResponse(options.getUnwrappingEndpoints(),
((Wrapped) roleId).getInitialToken())
.map(vaultResponse -> (String) vaultResponse.getRequiredData()
.get("role_id"));
return unwrapResponse(options.getUnwrappingEndpoints(), ((Wrapped) roleId).getInitialToken())
.map(vaultResponse -> (String) vaultResponse.getRequiredData().get("role_id"));
}
throw new IllegalArgumentException("Unknown RoleId configuration: " + roleId);
}
private static Node<String> getSecretIdSteps(AppRoleAuthenticationOptions options,
SecretId secretId) {
private static Node<String> getSecretIdSteps(AppRoleAuthenticationOptions options, SecretId secretId) {
if (secretId instanceof Provided) {
return AuthenticationSteps.fromSupplier(((Provided) secretId)::getValue);
@@ -158,31 +145,25 @@ public class AppRoleAuthentication
HttpHeaders headers = createHttpHeaders(((Pull) secretId).getInitialToken());
return AuthenticationSteps
.fromHttpRequest(post(getSecretIdPath(options)).with(headers)
.as(VaultResponse.class))
.map(vaultResponse -> (String) vaultResponse.getRequiredData()
.get("secret_id"));
.fromHttpRequest(post(getSecretIdPath(options)).with(headers).as(VaultResponse.class))
.map(vaultResponse -> (String) vaultResponse.getRequiredData().get("secret_id"));
}
if (secretId instanceof Wrapped) {
return unwrapResponse(options.getUnwrappingEndpoints(),
((Wrapped) secretId).getInitialToken())
.map(vaultResponse -> (String) vaultResponse.getRequiredData()
.get("secret_id"));
return unwrapResponse(options.getUnwrappingEndpoints(), ((Wrapped) secretId).getInitialToken())
.map(vaultResponse -> (String) vaultResponse.getRequiredData().get("secret_id"));
}
throw new IllegalArgumentException("Unknown SecretId configuration: " + secretId);
}
private static Node<VaultResponse> unwrapResponse(
UnwrappingEndpoints unwrappingEndpoints, VaultToken token) {
private static Node<VaultResponse> unwrapResponse(UnwrappingEndpoints unwrappingEndpoints, VaultToken token) {
return AuthenticationSteps
.fromHttpRequest(method(unwrappingEndpoints.getUnwrapRequestMethod(),
unwrappingEndpoints.getPath()).with(createHttpHeaders(token))
.as(VaultResponse.class))
.fromHttpRequest(method(unwrappingEndpoints.getUnwrapRequestMethod(), unwrappingEndpoints.getPath())
.with(createHttpHeaders(token)).as(VaultResponse.class))
.map(unwrappingEndpoints::unwrap);
}
@@ -193,20 +174,18 @@ public class AppRoleAuthentication
@Override
public AuthenticationSteps getAuthenticationSteps() {
return createAuthenticationSteps(options);
return createAuthenticationSteps(this.options);
}
private VaultToken createTokenUsingAppRole() {
Map<String, String> login = getAppRoleLoginBody(options.getRoleId(),
options.getSecretId());
Map<String, String> login = getAppRoleLoginBody(this.options.getRoleId(), this.options.getSecretId());
try {
VaultResponse response = restOperations.postForObject(
getLoginPath(options.getPath()), login, VaultResponse.class);
VaultResponse response = this.restOperations.postForObject(getLoginPath(this.options.getPath()), login,
VaultResponse.class);
Assert.state(response != null && response.getAuth() != null,
"Auth field must not be null");
Assert.state(response != null && response.getAuth() != null, "Auth field must not be null");
logger.debug("Login successful using AppRole authentication");
@@ -229,16 +208,13 @@ public class AppRoleAuthentication
try {
ResponseEntity<VaultResponse> entity = restOperations.exchange(
getRoleIdIdPath(options), HttpMethod.GET, createHttpEntity(token),
VaultResponse.class);
ResponseEntity<VaultResponse> entity = this.restOperations.exchange(getRoleIdIdPath(this.options),
HttpMethod.GET, createHttpEntity(token), VaultResponse.class);
return (String) entity.getBody().getRequiredData().get("role_id");
}
catch (HttpStatusCodeException e) {
throw new VaultLoginException(
String.format("Cannot get Role id using AppRole: %s",
VaultResponses.getError(e.getResponseBodyAsString())),
e);
throw new VaultLoginException(String.format("Cannot get Role id using AppRole: %s",
VaultResponses.getError(e.getResponseBodyAsString())), e);
}
}
@@ -247,22 +223,17 @@ public class AppRoleAuthentication
VaultToken token = ((Wrapped) roleId).getInitialToken();
try {
UnwrappingEndpoints unwrappingEndpoints = options
.getUnwrappingEndpoints();
ResponseEntity<VaultResponse> entity = restOperations.exchange(
unwrappingEndpoints.getPath(),
unwrappingEndpoints.getUnwrapRequestMethod(),
createHttpEntity(token), VaultResponse.class);
UnwrappingEndpoints unwrappingEndpoints = this.options.getUnwrappingEndpoints();
ResponseEntity<VaultResponse> entity = this.restOperations.exchange(unwrappingEndpoints.getPath(),
unwrappingEndpoints.getUnwrapRequestMethod(), createHttpEntity(token), VaultResponse.class);
VaultResponse response = unwrappingEndpoints.unwrap(entity.getBody());
return (String) response.getRequiredData().get("role_id");
}
catch (HttpStatusCodeException e) {
throw new VaultLoginException(
String.format("Cannot unwrap Role id using AppRole: %s",
VaultResponses.getError(e.getResponseBodyAsString())),
e);
throw new VaultLoginException(String.format("Cannot unwrap Role id using AppRole: %s",
VaultResponses.getError(e.getResponseBodyAsString())), e);
}
}
@@ -280,16 +251,13 @@ public class AppRoleAuthentication
VaultToken token = ((Pull) secretId).getInitialToken();
try {
VaultResponse response = restOperations.postForObject(
getSecretIdPath(options), createHttpEntity(token),
VaultResponse.class);
VaultResponse response = this.restOperations.postForObject(getSecretIdPath(this.options),
createHttpEntity(token), VaultResponse.class);
return (String) response.getRequiredData().get("secret_id");
}
catch (HttpStatusCodeException e) {
throw new VaultLoginException(
String.format("Cannot get Secret id using AppRole: %s",
VaultResponses.getError(e.getResponseBodyAsString())),
e);
throw new VaultLoginException(String.format("Cannot get Secret id using AppRole: %s",
VaultResponses.getError(e.getResponseBodyAsString())), e);
}
}
@@ -299,22 +267,17 @@ public class AppRoleAuthentication
try {
UnwrappingEndpoints unwrappingEndpoints = options
.getUnwrappingEndpoints();
ResponseEntity<VaultResponse> entity = restOperations.exchange(
unwrappingEndpoints.getPath(),
unwrappingEndpoints.getUnwrapRequestMethod(),
createHttpEntity(token), VaultResponse.class);
UnwrappingEndpoints unwrappingEndpoints = this.options.getUnwrappingEndpoints();
ResponseEntity<VaultResponse> entity = this.restOperations.exchange(unwrappingEndpoints.getPath(),
unwrappingEndpoints.getUnwrapRequestMethod(), createHttpEntity(token), VaultResponse.class);
VaultResponse response = unwrappingEndpoints.unwrap(entity.getBody());
return (String) response.getRequiredData().get("secret_id");
}
catch (HttpStatusCodeException e) {
throw new VaultLoginException(
String.format("Cannot unwrap Role id using AppRole: %s",
VaultResponses.getError(e.getResponseBodyAsString())),
e);
throw new VaultLoginException(String.format("Cannot unwrap Role id using AppRole: %s",
VaultResponses.getError(e.getResponseBodyAsString())), e);
}
}
@@ -346,8 +309,7 @@ public class AppRoleAuthentication
return login;
}
private static Map<String, String> getAppRoleLoginBody(String roleId,
@Nullable String secretId) {
private static Map<String, String> getAppRoleLoginBody(String roleId, @Nullable String secretId) {
Map<String, String> login = new HashMap<>();
@@ -361,12 +323,11 @@ public class AppRoleAuthentication
}
private static String getSecretIdPath(AppRoleAuthenticationOptions options) {
return String.format("auth/%s/role/%s/secret-id", options.getPath(),
options.getAppRole());
return String.format("auth/%s/role/%s/secret-id", options.getPath(), options.getAppRole());
}
private static String getRoleIdIdPath(AppRoleAuthenticationOptions options) {
return String.format("auth/%s/role/%s/role-id", options.getPath(),
options.getAppRole());
return String.format("auth/%s/role/%s/role-id", options.getPath(), options.getAppRole());
}
}

View File

@@ -74,9 +74,8 @@ public class AppRoleAuthenticationOptions {
@Deprecated
private final VaultToken initialToken;
private AppRoleAuthenticationOptions(String path, RoleId roleId, SecretId secretId,
@Nullable String appRole, UnwrappingEndpoints unwrappingEndpoints,
@Nullable VaultToken initialToken) {
private AppRoleAuthenticationOptions(String path, RoleId roleId, SecretId secretId, @Nullable String appRole,
UnwrappingEndpoints unwrappingEndpoints, @Nullable VaultToken initialToken) {
this.path = path;
this.roleId = roleId;
@@ -97,21 +96,21 @@ public class AppRoleAuthenticationOptions {
* @return the mount path.
*/
public String getPath() {
return path;
return this.path;
}
/**
* @return the RoleId.
*/
public RoleId getRoleId() {
return roleId;
return this.roleId;
}
/**
* @return the bound SecretId.
*/
public SecretId getSecretId() {
return secretId;
return this.secretId;
}
/**
@@ -120,7 +119,7 @@ public class AppRoleAuthenticationOptions {
*/
@Nullable
public String getAppRole() {
return appRole;
return this.appRole;
}
/**
@@ -128,7 +127,7 @@ public class AppRoleAuthenticationOptions {
* @since 2.2
*/
public UnwrappingEndpoints getUnwrappingEndpoints() {
return unwrappingEndpoints;
return this.unwrappingEndpoints;
}
/**
@@ -140,7 +139,7 @@ public class AppRoleAuthenticationOptions {
@Nullable
@Deprecated
public VaultToken getInitialToken() {
return initialToken;
return this.initialToken;
}
/**
@@ -176,7 +175,6 @@ public class AppRoleAuthenticationOptions {
/**
* Configure the mount path.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link AppRoleAuthenticationOptionsBuilder}.
* @see #DEFAULT_APPROLE_AUTHENTICATION_PATH
@@ -191,7 +189,6 @@ public class AppRoleAuthenticationOptions {
/**
* Configure the RoleId.
*
* @param roleId must not be empty or {@literal null}.
* @return {@code this} {@link AppRoleAuthenticationOptionsBuilder}.
* @since 2.0
@@ -206,10 +203,10 @@ public class AppRoleAuthenticationOptions {
/**
* Configure the RoleId.
*
* @param roleId must not be empty or {@literal null}.
* @return {@code this} {@link AppRoleAuthenticationOptionsBuilder}.
* @deprecated since 2.0, use {@link #roleId(AppRoleAuthenticationOptions.RoleId)}.
* @deprecated since 2.0, use
* {@link #roleId(AppRoleAuthenticationOptions.RoleId)}.
*/
@Deprecated
public AppRoleAuthenticationOptionsBuilder roleId(String roleId) {
@@ -222,7 +219,6 @@ public class AppRoleAuthenticationOptions {
/**
* Configure a {@code secretId}.
*
* @param secretId must not be empty or {@literal null}.
* @return {@code this} {@link AppRoleAuthenticationOptionsBuilder}.
* @since 2.0
@@ -237,10 +233,10 @@ public class AppRoleAuthenticationOptions {
/**
* Configure a {@code secretId}.
*
* @param secretId must not be empty or {@literal null}.
* @return {@code this} {@link AppRoleAuthenticationOptionsBuilder}.
* @deprecated since 2.0, use {@link #secretId(AppRoleAuthenticationOptions.SecretId)}.
* @deprecated since 2.0, use
* {@link #secretId(AppRoleAuthenticationOptions.SecretId)}.
*/
@Deprecated
public AppRoleAuthenticationOptionsBuilder secretId(String secretId) {
@@ -253,7 +249,6 @@ public class AppRoleAuthenticationOptions {
/**
* Configure a {@code appRole}.
*
* @param appRole must not be empty or {@literal null}.
* @return {@code this} {@link AppRoleAuthenticationOptionsBuilder}.
* @since 1.1
@@ -268,13 +263,11 @@ public class AppRoleAuthenticationOptions {
/**
* Configure the {@link UnwrappingEndpoints} to use.
*
* @param endpoints must not be {@literal null}.
* @return {@code this} {@link AppRoleAuthenticationOptionsBuilder}
* @since 2.2
*/
public AppRoleAuthenticationOptionsBuilder unwrappingEndpoints(
UnwrappingEndpoints endpoints) {
public AppRoleAuthenticationOptionsBuilder unwrappingEndpoints(UnwrappingEndpoints endpoints) {
Assert.notNull(endpoints, "UnwrappingEndpoints must not be empty");
@@ -284,7 +277,6 @@ public class AppRoleAuthenticationOptions {
/**
* Configure a {@code initialToken}.
*
* @param initialToken must not be empty or {@literal null}.
* @return {@code this} {@link AppRoleAuthenticationOptionsBuilder}.
* @since 1.1
@@ -305,47 +297,47 @@ public class AppRoleAuthenticationOptions {
* Build a new {@link AppRoleAuthenticationOptions} instance. Requires
* {@link #roleId(String)} for push mode or {@link #appRole(String)} and
* {@link #initialToken(VaultToken)} for pull mode to be configured.
*
* @return a new {@link AppRoleAuthenticationOptions}.
*/
public AppRoleAuthenticationOptions build() {
Assert.hasText(path, "Path must not be empty");
Assert.hasText(this.path, "Path must not be empty");
if (secretId == null) {
if (this.secretId == null) {
if (providedSecretId != null) {
secretId(SecretId.provided(providedSecretId));
if (this.providedSecretId != null) {
secretId(SecretId.provided(this.providedSecretId));
}
else if (initialToken != null) {
secretId(SecretId.pull(initialToken));
else if (this.initialToken != null) {
secretId(SecretId.pull(this.initialToken));
}
else {
secretId(SecretId.absent());
}
}
if (roleId == null) {
if (this.roleId == null) {
if (providedRoleId != null) {
roleId(RoleId.provided(providedRoleId));
if (this.providedRoleId != null) {
roleId(RoleId.provided(this.providedRoleId));
}
else {
Assert.notNull(initialToken,
Assert.notNull(this.initialToken,
"AppRole authentication configured for pull mode. InitialToken must not be null (pull mode)");
roleId(RoleId.pull(initialToken));
roleId(RoleId.pull(this.initialToken));
}
}
if (roleId instanceof Pull || secretId instanceof Pull) {
Assert.notNull(appRole,
if (this.roleId instanceof Pull || this.secretId instanceof Pull) {
Assert.notNull(this.appRole,
"AppRole authentication configured for pull mode. AppRole must not be null.");
}
return new AppRoleAuthenticationOptions(path, roleId, secretId, appRole,
unwrappingEndpoints, initialToken);
return new AppRoleAuthenticationOptions(this.path, this.roleId, this.secretId, this.appRole,
this.unwrappingEndpoints, this.initialToken);
}
}
/**
@@ -360,7 +352,6 @@ public class AppRoleAuthenticationOptions {
/**
* Create a {@link RoleId} object that obtains its value from unwrapping a
* response using the {@link VaultToken initial token} from a Cubbyhole.
*
* @param initialToken must not be {@literal null}.
* @return {@link RoleId} object that obtains its value from unwrapping a response
* using the {@link VaultToken initial token}.
@@ -377,7 +368,6 @@ public class AppRoleAuthenticationOptions {
* Create a {@link RoleId} that obtains its value using pull-mode, specifying a
* {@link VaultToken initial token}. The token policy must allow reading the
* roleId from {@code auth/approle/role/(role-name)/role-id}.
*
* @param initialToken must not be {@literal null}.
* @return {@link RoleId} that obtains its value using pull-mode.
*/
@@ -390,7 +380,6 @@ public class AppRoleAuthenticationOptions {
/**
* Create a {@link RoleId} that encapsulates a static {@code roleId}.
*
* @param roleId must not be {@literal null} or empty.
* @return {@link RoleId} that encapsulates a static {@code roleId}.
*/
@@ -400,6 +389,7 @@ public class AppRoleAuthenticationOptions {
return new Provided(roleId);
}
}
/**
@@ -414,7 +404,6 @@ public class AppRoleAuthenticationOptions {
/**
* Create a {@link SecretId} object that obtains its value from unwrapping a
* response using the {@link VaultToken initial token} from a Cubbyhole.
*
* @param initialToken must not be {@literal null}.
* @return {@link SecretId} object that obtains its value from unwrapping a
* response using the {@link VaultToken initial token}.
@@ -431,7 +420,6 @@ public class AppRoleAuthenticationOptions {
* Create a {@link SecretId} that obtains its value using pull-mode, specifying a
* {@link VaultToken initial token}. The token policy must allow reading the
* SecretId from {@code auth/approle/role/(role-name)/secret-id}.
*
* @param initialToken must not be {@literal null}.
* @return {@link SecretId} that obtains its value using pull-mode.
*/
@@ -444,7 +432,6 @@ public class AppRoleAuthenticationOptions {
/**
* Create a {@link SecretId} that encapsulates a static {@code secretId}.
*
* @param secretId must not be {@literal null} or empty.
* @return {@link SecretId} that encapsulates a static {@code SecretId}.
*/
@@ -458,11 +445,12 @@ public class AppRoleAuthenticationOptions {
/**
* Create a {@link SecretId} that represents an absent secretId. Using this object
* will not send a secretId during AppRole login.
*
* @return a {@link SecretId} that represents an absent secretId
*/
static SecretId absent() {
return AbsentSecretId.INSTANCE;
}
}
}

View File

@@ -31,7 +31,9 @@ class AppRoleTokens {
* Absent secretId.
*/
enum AbsentSecretId implements SecretId {
INSTANCE;
}
/**
@@ -48,6 +50,7 @@ class AppRoleTokens {
public VaultToken getInitialToken() {
return this.initialToken;
}
}
/**
@@ -64,6 +67,7 @@ class AppRoleTokens {
public VaultToken getInitialToken() {
return this.initialToken;
}
}
/**
@@ -80,5 +84,7 @@ class AppRoleTokens {
public String getValue() {
return this.value;
}
}
}

View File

@@ -46,7 +46,6 @@ public abstract class AuthenticationEventPublisher {
/**
* Add a {@link AuthenticationListener}. The listener starts receiving events as soon
* as possible.
*
* @param listener lease listener, must not be {@literal null}.
*/
public void addAuthenticationListener(AuthenticationListener listener) {
@@ -58,7 +57,6 @@ public abstract class AuthenticationEventPublisher {
/**
* Remove a {@link AuthenticationListener}.
*
* @param listener must not be {@literal null}.
*/
public void removeAuthenticationListener(AuthenticationListener listener) {
@@ -68,7 +66,6 @@ public abstract class AuthenticationEventPublisher {
/**
* Add a {@link AuthenticationErrorListener}. The listener starts receiving events as
* soon as possible.
*
* @param listener lease listener, must not be {@literal null}.
*/
public void addErrorListener(AuthenticationErrorListener listener) {
@@ -80,7 +77,6 @@ public abstract class AuthenticationEventPublisher {
/**
* Remove a {@link AuthenticationErrorListener}.
*
* @param listener must not be {@literal null}.
*/
public void removeErrorListener(AuthenticationErrorListener listener) {
@@ -89,25 +85,24 @@ public abstract class AuthenticationEventPublisher {
/**
* Dispatch the event to all {@link AuthenticationListener}s.
*
* @param authenticationEvent the event to dispatch.
*/
void dispatch(AuthenticationEvent authenticationEvent) {
for (AuthenticationListener listener : listeners) {
for (AuthenticationListener listener : this.listeners) {
listener.onAuthenticationEvent(authenticationEvent);
}
}
/**
* Dispatch the event to all {@link AuthenticationErrorListener}s.
*
* @param authenticationEvent the event to dispatch.
*/
void dispatch(AuthenticationErrorEvent authenticationEvent) {
for (AuthenticationErrorListener listener : errorListeners) {
for (AuthenticationErrorListener listener : this.errorListeners) {
listener.onAuthenticationError(authenticationEvent);
}
}
}

View File

@@ -70,7 +70,6 @@ import org.springframework.vault.support.VaultToken;
* {@link AuthenticationSteps} describes the authentication flow. Computation on the
* source data is only performed when the flow definition is interpreted by an executor.
*
*
* @author Mark Paluch
* @since 2.0
* @see AuthenticationStepsFactory
@@ -83,17 +82,15 @@ public class AuthenticationSteps {
/**
* Create a flow definition using a provided {@link VaultToken}.
*
* @param token the token to be used from this {@link AuthenticationSteps}, must not
* be {@literal null}.
* be {@literal null}.
* @return the {@link AuthenticationSteps}.
*/
public static AuthenticationSteps just(VaultToken token) {
Assert.notNull(token, "Vault token must not be null");
return new AuthenticationSteps(
new SupplierStep<>(() -> token, AuthenticationSteps.HEAD));
return new AuthenticationSteps(new SupplierStep<>(() -> token, AuthenticationSteps.HEAD));
}
/**
@@ -106,15 +103,13 @@ public class AuthenticationSteps {
Assert.notNull(request, "HttpRequest must not be null");
return new AuthenticationSteps(
new HttpRequestNode<>(request, AuthenticationSteps.HEAD));
return new AuthenticationSteps(new HttpRequestNode<>(request, AuthenticationSteps.HEAD));
}
/**
* Start flow composition from a {@link Supplier}.
*
* @param supplier supplier function that will produce the flow value, must not be
* {@literal null}.
* {@literal null}.
* @return the first {@link Node}.
*/
public static <T> Node<T> fromSupplier(Supplier<T> supplier) {
@@ -126,7 +121,6 @@ public class AuthenticationSteps {
/**
* Start flow composition from a {@link HttpRequest}.
*
* @param request the HTTP request definition, must not be {@literal null}.
* @return the first {@link Node}.
*/
@@ -143,7 +137,6 @@ public class AuthenticationSteps {
/**
* Return a {@link List} of node given a {@link PathAware} starting point.
*
* @param pathAware must not be {@literal null}.
* @return
*/
@@ -182,9 +175,8 @@ public class AuthenticationSteps {
/**
* Transform the state object into a different object.
*
* @param mappingFunction mapping function to be applied to the state object, must
* not be {@literal null}.
* not be {@literal null}.
* @param <R> resulting object type
* @return the next {@link Node}.
*/
@@ -197,7 +189,6 @@ public class AuthenticationSteps {
/**
* Combine the result from this {@link Node} and another into a {@link Pair}.
*
* @return the next {@link Node}.
* @since 2.1
*/
@@ -211,9 +202,8 @@ public class AuthenticationSteps {
/**
* Callback with the current state object.
*
* @param consumerFunction consumer function to be called with the state object,
* must not be {@literal null}.
* must not be {@literal null}.
* @return the next {@link Node}.
*/
public Node<T> onNext(Consumer<? super T> consumerFunction) {
@@ -225,7 +215,6 @@ public class AuthenticationSteps {
/**
* Request data using a {@link HttpRequest}.
*
* @param request the HTTP request definition, must not be {@literal null}.
* @return the next {@link Node}.
*/
@@ -239,9 +228,8 @@ public class AuthenticationSteps {
/**
* Terminal operation requesting a {@link VaultToken token} from Vault by posting
* the current state to Vaults {@code uriTemplate}.
*
* @param uriTemplate Vault authentication endpoint, must not be {@literal null}
* or empty.
* or empty.
* @param uriVariables URI variables for URI template expansion.
* @return the {@link AuthenticationSteps}.
*/
@@ -249,14 +237,12 @@ public class AuthenticationSteps {
Assert.hasText(uriTemplate, "URI template must not be null or empty");
return login(HttpRequestBuilder.post(uriTemplate, uriVariables)
.as(VaultResponse.class));
return login(HttpRequestBuilder.post(uriTemplate, uriVariables).as(VaultResponse.class));
}
/**
* Terminal operation requesting a {@link VaultToken token} from Vault by issuing
* a HTTP request with the current state to Vaults {@code uriTemplate}.
*
* @param request HTTP request definition.
* @return the {@link AuthenticationSteps}.
*/
@@ -270,18 +256,17 @@ public class AuthenticationSteps {
/**
* Terminal operation resulting in a {@link VaultToken token} by applying a
* mapping {@link Function} to the current state object.
*
* @param mappingFunction mapping function to be applied to the state object, must
* not be {@literal null}.
* not be {@literal null}.
* @return the {@link AuthenticationSteps}.
*/
public AuthenticationSteps login(
Function<? super T, ? extends VaultToken> mappingFunction) {
public AuthenticationSteps login(Function<? super T, ? extends VaultToken> mappingFunction) {
Assert.notNull(mappingFunction, "Mapping function must not be null");
return new AuthenticationSteps(new MapStep<>(mappingFunction, this));
}
}
/**
@@ -305,7 +290,6 @@ public class AuthenticationSteps {
/**
* Builder entry point to {@code GET} from {@code uriTemplate}.
*
* @param uriTemplate must not be {@literal null} or empty.
* @param uriVariables the variables to expand the template.
* @return a new {@link HttpRequestBuilder}.
@@ -316,7 +300,6 @@ public class AuthenticationSteps {
/**
* Builder entry point to {@code GET} from {@code uri}.
*
* @param uri must not be {@literal null}.
* @return a new {@link HttpRequestBuilder}.
*/
@@ -326,19 +309,16 @@ public class AuthenticationSteps {
/**
* Builder entry point to {@code POST} to {@code uriTemplate}.
*
* @param uriTemplate must not be {@literal null} or empty.
* @param uriVariables the variables to expand the template.
* @return a new {@link HttpRequestBuilder}.
*/
public static HttpRequestBuilder post(String uriTemplate,
String... uriVariables) {
public static HttpRequestBuilder post(String uriTemplate, String... uriVariables) {
return new HttpRequestBuilder(HttpMethod.POST, uriTemplate, uriVariables);
}
/**
* Builder entry point to {@code POST} to {@code uri}.
*
* @param uri must not be {@literal null}.
* @return a new {@link HttpRequestBuilder}.
*/
@@ -348,14 +328,12 @@ public class AuthenticationSteps {
/**
* Builder entry point to use {@link HttpMethod} for {@code uriTemplate}.
*
* @param uriTemplate must not be {@literal null} or empty.
* @param uriVariables the variables to expand the template.
* @return a new {@link HttpRequestBuilder}.
* @since 2.2
*/
public static HttpRequestBuilder method(HttpMethod method, String uriTemplate,
String... uriVariables) {
public static HttpRequestBuilder method(HttpMethod method, String uriTemplate, String... uriVariables) {
return new HttpRequestBuilder(method, uriTemplate, uriVariables);
}
@@ -364,16 +342,14 @@ public class AuthenticationSteps {
this.uri = uri;
}
private HttpRequestBuilder(HttpMethod method, @Nullable String uriTemplate,
@Nullable String[] urlVariables) {
private HttpRequestBuilder(HttpMethod method, @Nullable String uriTemplate, @Nullable String[] urlVariables) {
this.method = method;
this.uriTemplate = uriTemplate;
this.urlVariables = urlVariables;
}
private HttpRequestBuilder(HttpMethod method, @Nullable URI uri,
@Nullable String uriTemplate, @Nullable String[] urlVariables,
@Nullable HttpEntity<?> entity) {
private HttpRequestBuilder(HttpMethod method, @Nullable URI uri, @Nullable String uriTemplate,
@Nullable String[] urlVariables, @Nullable HttpEntity<?> entity) {
this.method = method;
this.uri = uri;
this.uriTemplate = uriTemplate;
@@ -383,7 +359,6 @@ public class AuthenticationSteps {
/**
* Configure a request {@link HttpEntity entity}.
*
* @param httpEntity must not be {@literal null}.
* @return a new {@link HttpRequestBuilder}.
*/
@@ -391,13 +366,11 @@ public class AuthenticationSteps {
Assert.notNull(httpEntity, "HttpEntity must not be null");
return new HttpRequestBuilder(method, uri, uriTemplate, urlVariables,
httpEntity);
return new HttpRequestBuilder(this.method, this.uri, this.uriTemplate, this.urlVariables, httpEntity);
}
/**
* Configure a request {@link HttpHeaders headers}.
*
* @param headers must not be {@literal null}.
* @return a new {@link HttpRequestBuilder}.
*/
@@ -405,7 +378,7 @@ public class AuthenticationSteps {
Assert.notNull(headers, "HttpHeaders must not be null");
return new HttpRequestBuilder(method, uri, uriTemplate, urlVariables,
return new HttpRequestBuilder(this.method, this.uri, this.uriTemplate, this.urlVariables,
new HttpEntity<>(headers));
}
@@ -420,6 +393,7 @@ public class AuthenticationSteps {
return new HttpRequest<>(this, type);
}
}
/**
@@ -456,8 +430,8 @@ public class AuthenticationSteps {
@Override
public String toString() {
return String.format("%s %s AS %s", getMethod(),
getUri() != null ? getUri() : getUriTemplate(), getResponseType());
return String.format("%s %s AS %s", getMethod(), getUri() != null ? getUri() : getUriTemplate(),
getResponseType());
}
HttpMethod getMethod() {
@@ -487,6 +461,7 @@ public class AuthenticationSteps {
Class<T> getResponseType() {
return this.responseType;
}
}
static final class HttpRequestNode<T> extends Node<T> implements PathAware {
@@ -502,7 +477,7 @@ public class AuthenticationSteps {
@Override
public String toString() {
return definition.toString();
return this.definition.toString();
}
public HttpRequest<T> getDefinition() {
@@ -520,13 +495,14 @@ public class AuthenticationSteps {
if (!(o instanceof HttpRequestNode))
return false;
HttpRequestNode<?> that = (HttpRequestNode<?>) o;
return definition.equals(that.definition) && previous.equals(that.previous);
return this.definition.equals(that.definition) && this.previous.equals(that.previous);
}
@Override
public int hashCode() {
return Objects.hash(definition, previous);
return Objects.hash(this.definition, this.previous);
}
}
static final class MapStep<I, O> extends Node<O> implements PathAware {
@@ -541,12 +517,12 @@ public class AuthenticationSteps {
}
O apply(I in) {
return mapper.apply(in);
return this.mapper.apply(in);
}
@Override
public String toString() {
return "Map: " + mapper.toString();
return "Map: " + this.mapper.toString();
}
public Function<? super I, ? extends O> getMapper() {
@@ -564,13 +540,14 @@ public class AuthenticationSteps {
if (!(o instanceof MapStep))
return false;
MapStep<?, ?> mapStep = (MapStep<?, ?>) o;
return mapper.equals(mapStep.mapper) && previous.equals(mapStep.previous);
return this.mapper.equals(mapStep.mapper) && this.previous.equals(mapStep.previous);
}
@Override
public int hashCode() {
return Objects.hash(mapper, previous);
return Objects.hash(this.mapper, this.previous);
}
}
static final class ZipStep<L, R> extends Node<Pair<L, R>> implements PathAware {
@@ -586,7 +563,7 @@ public class AuthenticationSteps {
@Override
public Node<?> getPrevious() {
return left;
return this.left;
}
@Override
@@ -609,13 +586,14 @@ public class AuthenticationSteps {
if (!(o instanceof ZipStep))
return false;
ZipStep<?, ?> zipStep = (ZipStep<?, ?>) o;
return left.equals(zipStep.left) && right.equals(zipStep.right);
return this.left.equals(zipStep.left) && this.right.equals(zipStep.right);
}
@Override
public int hashCode() {
return Objects.hash(left, right);
return Objects.hash(this.left, this.right);
}
}
static final class OnNextStep<T> extends Node<T> implements PathAware {
@@ -630,13 +608,13 @@ public class AuthenticationSteps {
}
T apply(T in) {
consumer.accept(in);
this.consumer.accept(in);
return in;
}
@Override
public String toString() {
return "Consumer: " + consumer.toString();
return "Consumer: " + this.consumer.toString();
}
public Consumer<? super T> getConsumer() {
@@ -654,13 +632,14 @@ public class AuthenticationSteps {
if (!(o instanceof OnNextStep))
return false;
OnNextStep<?> that = (OnNextStep<?>) o;
return consumer.equals(that.consumer) && previous.equals(that.previous);
return this.consumer.equals(that.consumer) && this.previous.equals(that.previous);
}
@Override
public int hashCode() {
return Objects.hash(consumer, previous);
return Objects.hash(this.consumer, this.previous);
}
}
static final class SupplierStep<T> extends Node<T> implements PathAware {
@@ -675,12 +654,12 @@ public class AuthenticationSteps {
}
public T get() {
return supplier.get();
return this.supplier.get();
}
@Override
public String toString() {
return "Supplier: " + supplier.toString();
return "Supplier: " + this.supplier.toString();
}
public Supplier<T> getSupplier() {
@@ -698,17 +677,20 @@ public class AuthenticationSteps {
if (!(o instanceof SupplierStep))
return false;
SupplierStep<?> that = (SupplierStep<?>) o;
return supplier.equals(that.supplier) && previous.equals(that.previous);
return this.supplier.equals(that.supplier) && this.previous.equals(that.previous);
}
@Override
public int hashCode() {
return Objects.hash(supplier, previous);
return Objects.hash(this.supplier, this.previous);
}
}
interface PathAware {
Node<?> getPrevious();
}
/**
@@ -731,7 +713,6 @@ public class AuthenticationSteps {
/**
* Create a new {@link Pair} given {@code left} and {@code right} values.
*
* @param left the left value.
* @param right the right value.
* @return the {@link Pair}.
@@ -742,20 +723,18 @@ public class AuthenticationSteps {
/**
* Type-safe way to get the fist object of this {@link Pair}.
*
* @return The first object
*/
public L getLeft() {
return left;
return this.left;
}
/**
* Type-safe way to get the second object of this {@link Pair}.
*
* @return The second object
*/
public R getRight() {
return right;
return this.right;
}
@Override
@@ -765,22 +744,24 @@ public class AuthenticationSteps {
if (!(o instanceof Pair))
return false;
Pair<?, ?> pair = (Pair<?, ?>) o;
return left.equals(pair.left) && right.equals(pair.right);
return this.left.equals(pair.left) && this.right.equals(pair.right);
}
@Override
public int hashCode() {
return Objects.hash(left, right);
return Objects.hash(this.left, this.right);
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(getClass().getSimpleName());
sb.append(" [left=").append(left);
sb.append(", right=").append(right);
sb.append(" [left=").append(this.left);
sb.append(", right=").append(this.right);
sb.append(']');
return sb.toString();
}
}
}

View File

@@ -56,12 +56,10 @@ public class AuthenticationStepsExecutor implements ClientAuthentication {
/**
* Create a new {@link AuthenticationStepsExecutor} given {@link AuthenticationSteps}
* and {@link RestOperations}.
*
* @param steps must not be {@literal null}.
* @param restOperations must not be {@literal null}.
*/
public AuthenticationStepsExecutor(AuthenticationSteps steps,
RestOperations restOperations) {
public AuthenticationStepsExecutor(AuthenticationSteps steps, RestOperations restOperations) {
Assert.notNull(steps, "AuthenticationSteps must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
@@ -74,7 +72,7 @@ public class AuthenticationStepsExecutor implements ClientAuthentication {
@SuppressWarnings("unchecked")
public VaultToken login() throws VaultException {
Iterable<Node<?>> steps = chain.steps;
Iterable<Node<?>> steps = this.chain.steps;
Object state = evaluate(steps);
@@ -89,9 +87,8 @@ public class AuthenticationStepsExecutor implements ClientAuthentication {
return LoginTokenUtil.from(response.getAuth());
}
throw new IllegalStateException(String.format(
"Cannot retrieve VaultToken from authentication chain. Got instead %s",
state));
throw new IllegalStateException(
String.format("Cannot retrieve VaultToken from authentication chain. Got instead %s", state));
}
private Object evaluate(Iterable<Node<?>> steps) {
@@ -101,8 +98,7 @@ public class AuthenticationStepsExecutor implements ClientAuthentication {
for (Node<?> o : steps) {
if (logger.isDebugEnabled()) {
logger.debug(
String.format("Executing %s with current state %s", o, state));
logger.debug(String.format("Executing %s with current state %s", o, state));
}
try {
@@ -127,19 +123,17 @@ public class AuthenticationStepsExecutor implements ClientAuthentication {
}
if (logger.isDebugEnabled()) {
logger.debug(
String.format("Executed %s with current state %s", o, state));
logger.debug(String.format("Executed %s with current state %s", o, state));
}
}
catch (HttpStatusCodeException e) {
throw new VaultLoginException(String.format(
"HTTP request %s in state %s failed with Status %s and body %s",
o, state, e.getRawStatusCode(),
VaultResponses.getError(e.getResponseBodyAsString())), e);
throw new VaultLoginException(
String.format("HTTP request %s in state %s failed with Status %s and body %s", o, state,
e.getRawStatusCode(), VaultResponses.getError(e.getResponseBodyAsString())),
e);
}
catch (RuntimeException e) {
throw new VaultLoginException(
String.format("Authentication execution failed in %s", o), e);
throw new VaultLoginException(String.format("Authentication execution failed in %s", o), e);
}
}
return state;
@@ -171,17 +165,14 @@ public class AuthenticationStepsExecutor implements ClientAuthentication {
if (definition.getUri() == null) {
ResponseEntity<?> exchange = restOperations.exchange(
definition.getUriTemplate(), definition.getMethod(),
getEntity(definition.getEntity(), state),
definition.getResponseType(),
ResponseEntity<?> exchange = this.restOperations.exchange(definition.getUriTemplate(),
definition.getMethod(), getEntity(definition.getEntity(), state), definition.getResponseType(),
(Object[]) definition.getUrlVariables());
return exchange.getBody();
}
ResponseEntity<?> exchange = restOperations.exchange(definition.getUri(),
definition.getMethod(), getEntity(definition.getEntity(), state),
definition.getResponseType());
ResponseEntity<?> exchange = this.restOperations.exchange(definition.getUri(), definition.getMethod(),
getEntity(definition.getEntity(), state), definition.getResponseType());
return exchange.getBody();
@@ -199,4 +190,5 @@ public class AuthenticationStepsExecutor implements ClientAuthentication {
return entity;
}
}

View File

@@ -30,8 +30,8 @@ public interface AuthenticationStepsFactory {
/**
* Get the {@link AuthenticationSteps} describing an authentication flow.
*
* @return the {@link AuthenticationSteps} describing an authentication flow.
*/
AuthenticationSteps getAuthenticationSteps();
}

View File

@@ -52,8 +52,7 @@ import org.springframework.web.reactive.function.client.WebClient.RequestBodySpe
*/
public class AuthenticationStepsOperator implements VaultTokenSupplier {
private static final Log logger = LogFactory
.getLog(AuthenticationStepsOperator.class);
private static final Log logger = LogFactory.getLog(AuthenticationStepsOperator.class);
private final AuthenticationSteps chain;
@@ -62,7 +61,6 @@ public class AuthenticationStepsOperator implements VaultTokenSupplier {
/**
* Create a new {@link AuthenticationStepsOperator} given {@link AuthenticationSteps}
* and {@link WebClient}.
*
* @param steps must not be {@literal null}.
* @param webClient must not be {@literal null}.
*/
@@ -78,7 +76,7 @@ public class AuthenticationStepsOperator implements VaultTokenSupplier {
@Override
public Mono<VaultToken> getVaultToken() throws VaultException {
Mono<Object> state = createMono(chain.steps);
Mono<Object> state = createMono(this.chain.steps);
return state.map(stateObject -> {
@@ -95,11 +93,9 @@ public class AuthenticationStepsOperator implements VaultTokenSupplier {
return LoginTokenUtil.from(response.getAuth());
}
throw new IllegalStateException(String.format(
"Cannot retrieve VaultToken from authentication chain. Got instead %s",
stateObject));
}).onErrorMap(t -> new VaultLoginException(
"Cannot retrieve VaultToken from authentication chain", t));
throw new IllegalStateException(
String.format("Cannot retrieve VaultToken from authentication chain. Got instead %s", stateObject));
}).onErrorMap(t -> new VaultLoginException("Cannot retrieve VaultToken from authentication chain", t));
}
private Mono<Object> createMono(Iterable<Node<?>> steps) {
@@ -109,19 +105,15 @@ public class AuthenticationStepsOperator implements VaultTokenSupplier {
for (Node<?> o : steps) {
if (logger.isDebugEnabled()) {
logger.debug(
String.format("Executing %s with current state %s", o, state));
logger.debug(String.format("Executing %s with current state %s", o, state));
}
if (o instanceof HttpRequestNode) {
state = state
.flatMap(stateObject -> doHttpRequest((HttpRequestNode<Object>) o,
stateObject));
state = state.flatMap(stateObject -> doHttpRequest((HttpRequestNode<Object>) o, stateObject));
}
if (o instanceof MapStep) {
state = state.map(stateObject -> doMapStep((MapStep<Object, Object>) o,
stateObject));
state = state.map(stateObject -> doMapStep((MapStep<Object, Object>) o, stateObject));
}
if (o instanceof ZipStep) {
@@ -130,18 +122,15 @@ public class AuthenticationStepsOperator implements VaultTokenSupplier {
}
if (o instanceof OnNextStep) {
state = state.doOnNext(
stateObject -> doOnNext((OnNextStep<Object>) o, stateObject));
state = state.doOnNext(stateObject -> doOnNext((OnNextStep<Object>) o, stateObject));
}
if (o instanceof SupplierStep<?>) {
state = state
.map(stateObject -> doSupplierStep((SupplierStep<Object>) o));
state = state.map(stateObject -> doSupplierStep((SupplierStep<Object>) o));
}
if (logger.isDebugEnabled()) {
logger.debug(
String.format("Executed %s with current state %s", o, state));
logger.debug(String.format("Executed %s with current state %s", o, state));
}
}
return state;
@@ -171,11 +160,11 @@ public class AuthenticationStepsOperator implements VaultTokenSupplier {
RequestBodySpec spec;
if (definition.getUri() == null) {
spec = webClient.method(definition.getMethod()).uri(
definition.getUriTemplate(), definition.getUrlVariables());
spec = this.webClient.method(definition.getMethod()).uri(definition.getUriTemplate(),
definition.getUrlVariables());
}
else {
spec = webClient.method(definition.getMethod()).uri(definition.getUri());
spec = this.webClient.method(definition.getMethod()).uri(definition.getUri());
}
for (Entry<String, List<String>> header : entity.getHeaders().entrySet()) {
@@ -183,8 +172,7 @@ public class AuthenticationStepsOperator implements VaultTokenSupplier {
}
if (entity.getBody() != null && !entity.getBody().equals(Undefinded.INSTANCE)) {
return spec.bodyValue(entity.getBody()).retrieve()
.bodyToMono(definition.getResponseType());
return spec.bodyValue(entity.getBody()).retrieve().bodyToMono(definition.getResponseType());
}
return spec.retrieve().bodyToMono(definition.getResponseType());
@@ -209,5 +197,7 @@ public class AuthenticationStepsOperator implements VaultTokenSupplier {
private Undefinded() {
}
}
}

View File

@@ -9,7 +9,6 @@ abstract class AuthenticationUtil {
/**
* Returns the login path for a {@code authMount}.
*
* @param authMount
* @return
*/
@@ -19,4 +18,5 @@ abstract class AuthenticationUtil {
private AuthenticationUtil() {
}
}

View File

@@ -46,8 +46,7 @@ import org.springframework.web.client.RestOperations;
* @see <a href="https://www.vaultproject.io/docs/auth/aws-ec2.html">Auth Backend:
* aws-ec2</a>
*/
public class AwsEc2Authentication
implements ClientAuthentication, AuthenticationStepsFactory {
public class AwsEc2Authentication implements ClientAuthentication, AuthenticationStepsFactory {
private static final Log logger = LogFactory.getLog(AwsEc2Authentication.class);
@@ -63,31 +62,26 @@ public class AwsEc2Authentication
/**
* Create a new {@link AwsEc2Authentication}.
*
* @param vaultRestOperations must not be {@literal null}.
*/
public AwsEc2Authentication(RestOperations vaultRestOperations) {
this(AwsEc2AuthenticationOptions.DEFAULT, vaultRestOperations,
vaultRestOperations);
this(AwsEc2AuthenticationOptions.DEFAULT, vaultRestOperations, vaultRestOperations);
}
/**
* Create a new {@link AwsEc2Authentication} specifying
* {@link AwsEc2AuthenticationOptions}, a Vault and an AWS-Metadata-specific
* {@link RestOperations}.
*
* @param options must not be {@literal null}.
* @param vaultRestOperations must not be {@literal null}.
* @param awsMetadataRestOperations must not be {@literal null}.
*/
public AwsEc2Authentication(AwsEc2AuthenticationOptions options,
RestOperations vaultRestOperations,
public AwsEc2Authentication(AwsEc2AuthenticationOptions options, RestOperations vaultRestOperations,
RestOperations awsMetadataRestOperations) {
Assert.notNull(options, "AwsEc2AuthenticationOptions must not be null");
Assert.notNull(vaultRestOperations, "Vault RestOperations must not be null");
Assert.notNull(awsMetadataRestOperations,
"AWS Metadata RestOperations must not be null");
Assert.notNull(awsMetadataRestOperations, "AWS Metadata RestOperations must not be null");
this.options = options;
this.vaultRestOperations = vaultRestOperations;
@@ -97,13 +91,11 @@ public class AwsEc2Authentication
/**
* Creates a {@link AuthenticationSteps} for AWS-EC2 authentication given
* {@link AwsEc2AuthenticationOptions}.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for AWS-EC2 authentication.
* @since 2.0
*/
public static AuthenticationSteps createAuthenticationSteps(
AwsEc2AuthenticationOptions options) {
public static AuthenticationSteps createAuthenticationSteps(AwsEc2AuthenticationOptions options) {
Assert.notNull(options, "AwsEc2AuthenticationOptions must not be null");
@@ -112,14 +104,11 @@ public class AwsEc2Authentication
return createAuthenticationSteps(options, nonce, () -> doCreateNonce(options));
}
protected static AuthenticationSteps createAuthenticationSteps(
AwsEc2AuthenticationOptions options, AtomicReference<char[]> nonce,
Supplier<char[]> nonceSupplier) {
protected static AuthenticationSteps createAuthenticationSteps(AwsEc2AuthenticationOptions options,
AtomicReference<char[]> nonce, Supplier<char[]> nonceSupplier) {
return AuthenticationSteps
.fromHttpRequest(HttpRequestBuilder
.get(options.getIdentityDocumentUri().toString())
.as(String.class)) //
.fromHttpRequest(HttpRequestBuilder.get(options.getIdentityDocumentUri().toString()).as(String.class)) //
.map(pkcs7 -> pkcs7.replaceAll("\\r", "")) //
.map(pkcs7 -> pkcs7.replace("\\n", "")) //
.map(pkcs7 -> {
@@ -158,19 +147,16 @@ public class AwsEc2Authentication
try {
VaultResponse response = this.vaultRestOperations.postForObject(
AuthenticationUtil.getLoginPath(options.getPath()), login, VaultResponse.class);
VaultResponse response = this.vaultRestOperations
.postForObject(AuthenticationUtil.getLoginPath(this.options.getPath()), login, VaultResponse.class);
Assert.state(response != null && response.getAuth() != null,
"Auth field must not be null");
Assert.state(response != null && response.getAuth() != null, "Auth field must not be null");
if (logger.isDebugEnabled()) {
if (response.getAuth().get("metadata") instanceof Map) {
Map<Object, Object> metadata = (Map<Object, Object>) response
.getAuth().get("metadata");
logger.debug(String.format(
"Login successful using AWS-EC2 authentication for instance %s, AMI %s",
Map<Object, Object> metadata = (Map<Object, Object>) response.getAuth().get("metadata");
logger.debug(String.format("Login successful using AWS-EC2 authentication for instance %s, AMI %s",
metadata.get("instance_id"), metadata.get("instance_id")));
}
else {
@@ -189,8 +175,8 @@ public class AwsEc2Authentication
Map<String, String> login = new HashMap<>();
if (StringUtils.hasText(options.getRole())) {
login.put("role", options.getRole());
if (StringUtils.hasText(this.options.getRole())) {
login.put("role", this.options.getRole());
}
if (Objects.equals(this.nonce.get(), EMPTY)) {
@@ -200,8 +186,8 @@ public class AwsEc2Authentication
login.put("nonce", new String(this.nonce.get()));
try {
String pkcs7 = this.awsMetadataRestOperations
.getForObject(this.options.getIdentityDocumentUri(), String.class);
String pkcs7 = this.awsMetadataRestOperations.getForObject(this.options.getIdentityDocumentUri(),
String.class);
if (StringUtils.hasText(pkcs7)) {
login.put("pkcs7", pkcs7.replaceAll("\\r", "").replace("\\n", ""));
}
@@ -210,9 +196,7 @@ public class AwsEc2Authentication
}
catch (RestClientException e) {
throw new VaultLoginException(
String.format("Cannot obtain Identity Document from %s",
options.getIdentityDocumentUri()),
e);
String.format("Cannot obtain Identity Document from %s", this.options.getIdentityDocumentUri()), e);
}
}
@@ -223,4 +207,5 @@ public class AwsEc2Authentication
private static char[] doCreateNonce(AwsEc2AuthenticationOptions options) {
return options.getNonce().getValue();
}
}

View File

@@ -69,12 +69,10 @@ public class AwsEc2AuthenticationOptions {
private final Nonce nonce;
private AwsEc2AuthenticationOptions() {
this(DEFAULT_AWS_AUTHENTICATION_PATH, DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI, "",
Nonce.generated());
this(DEFAULT_AWS_AUTHENTICATION_PATH, DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI, "", Nonce.generated());
}
private AwsEc2AuthenticationOptions(String path, URI identityDocumentUri,
@Nullable String role, Nonce nonce) {
private AwsEc2AuthenticationOptions(String path, URI identityDocumentUri, @Nullable String role, Nonce nonce) {
this.path = path;
this.identityDocumentUri = identityDocumentUri;
@@ -93,14 +91,14 @@ public class AwsEc2AuthenticationOptions {
* @return the path of the aws-ec2 authentication backend mount.
*/
public String getPath() {
return path;
return this.path;
}
/**
* @return the {@link URI} to the AWS EC2 PKCS#7-signed identity document.
*/
public URI getIdentityDocumentUri() {
return identityDocumentUri;
return this.identityDocumentUri;
}
/**
@@ -108,14 +106,14 @@ public class AwsEc2AuthenticationOptions {
*/
@Nullable
public String getRole() {
return role;
return this.role;
}
/**
* @return the configured {@link Nonce}.
*/
public Nonce getNonce() {
return nonce;
return this.nonce;
}
/**
@@ -124,6 +122,7 @@ public class AwsEc2AuthenticationOptions {
public static class AwsEc2AuthenticationOptionsBuilder {
private String path = DEFAULT_AWS_AUTHENTICATION_PATH;
private URI identityDocumentUri = DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI;
@Nullable
@@ -136,7 +135,6 @@ public class AwsEc2AuthenticationOptions {
/**
* Configure the mount path.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link AwsEc2AuthenticationOptionsBuilder}.
*/
@@ -150,13 +148,11 @@ public class AwsEc2AuthenticationOptions {
/**
* Configure the Identity Document {@link URI}.
*
* @param identityDocumentUri must not be {@literal null}.
* @return {@code this} {@link AwsEc2AuthenticationOptionsBuilder}.
* @see #DEFAULT_PKCS7_IDENTITY_DOCUMENT_URI
*/
public AwsEc2AuthenticationOptionsBuilder identityDocumentUri(
URI identityDocumentUri) {
public AwsEc2AuthenticationOptionsBuilder identityDocumentUri(URI identityDocumentUri) {
Assert.notNull(identityDocumentUri, "Identity document URI must not be null");
@@ -168,7 +164,6 @@ public class AwsEc2AuthenticationOptions {
* Configure the name of the role against which the login is being attempted.If
* role is not specified, then the login endpoint looks for a role bearing the
* name of the AMI ID of the EC2 instance that is trying to login.
*
* @param role may be empty or {@literal null}.
* @return {@code this} {@link AwsEc2AuthenticationOptionsBuilder}.
*/
@@ -181,7 +176,6 @@ public class AwsEc2AuthenticationOptions {
/**
* Configure a {@link Nonce} for login requests. Defaults to
* {@link Nonce#generated()}.
*
* @param nonce must not be {@literal null}.
* @return {@code this} {@link AwsEc2AuthenticationOptionsBuilder}.
* @since 1.1
@@ -196,16 +190,15 @@ public class AwsEc2AuthenticationOptions {
/**
* Build a new {@link AwsEc2AuthenticationOptions} instance.
*
* @return a new {@link AwsEc2AuthenticationOptions}.
*/
public AwsEc2AuthenticationOptions build() {
Assert.notNull(identityDocumentUri, "IdentityDocumentUri must not be null");
Assert.notNull(this.identityDocumentUri, "IdentityDocumentUri must not be null");
return new AwsEc2AuthenticationOptions(path, identityDocumentUri, role,
nonce);
return new AwsEc2AuthenticationOptions(this.path, this.identityDocumentUri, this.role, this.nonce);
}
}
/**
@@ -223,7 +216,6 @@ public class AwsEc2AuthenticationOptions {
/**
* Create a new generated {@link Nonce} using {@link UUID}.
*
* @return a new generated {@link Nonce} using {@link UUID}.
*/
public static Nonce generated() {
@@ -232,7 +224,6 @@ public class AwsEc2AuthenticationOptions {
/**
* Create a wrapped {@link Nonce} given a {@code nonce} value.
*
* @return a wrapped {@link Nonce} given for the {@code nonce} value.
*/
public static Nonce provided(char[] nonce) {
@@ -246,7 +237,7 @@ public class AwsEc2AuthenticationOptions {
* @return the nonce value.
*/
public char[] getValue() {
return value;
return this.value;
}
static class Generated extends Nonce {
@@ -254,6 +245,7 @@ public class AwsEc2AuthenticationOptions {
Generated() {
super(UUID.randomUUID().toString().toCharArray());
}
}
static class Provided extends Nonce {
@@ -261,6 +253,9 @@ public class AwsEc2AuthenticationOptions {
Provided(char[] nonce) {
super(nonce);
}
}
}
}

View File

@@ -66,8 +66,7 @@ import org.springframework.web.client.RestOperations;
* "https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html">AWS:
* GetCallerIdentity</a>
*/
public class AwsIamAuthentication
implements ClientAuthentication, AuthenticationStepsFactory {
public class AwsIamAuthentication implements ClientAuthentication, AuthenticationStepsFactory {
private static final Log logger = LogFactory.getLog(AwsIamAuthentication.class);
@@ -75,8 +74,7 @@ public class AwsIamAuthentication
private static final String REQUEST_BODY = "Action=GetCallerIdentity&Version=2011-06-15";
private static final String REQUEST_BODY_BASE64_ENCODED = Base64Utils
.encodeToString(REQUEST_BODY.getBytes());
private static final String REQUEST_BODY_BASE64_ENCODED = Base64Utils.encodeToString(REQUEST_BODY.getBytes());
private final AwsIamAuthenticationOptions options;
@@ -86,12 +84,10 @@ public class AwsIamAuthentication
* Create a new {@link AwsIamAuthentication} specifying
* {@link AwsIamAuthenticationOptions}, a Vault and an AWS-Metadata-specific
* {@link RestOperations}.
*
* @param options must not be {@literal null}.
* @param vaultRestOperations must not be {@literal null}.
*/
public AwsIamAuthentication(AwsIamAuthenticationOptions options,
RestOperations vaultRestOperations) {
public AwsIamAuthentication(AwsIamAuthenticationOptions options, RestOperations vaultRestOperations) {
Assert.notNull(options, "AwsIamAuthenticationOptions must not be null");
Assert.notNull(vaultRestOperations, "Vault RestOperations must not be null");
@@ -105,13 +101,11 @@ public class AwsIamAuthentication
* {@link AwsIamAuthenticationOptions}. The resulting {@link AuthenticationSteps}
* reuse eagerly-fetched {@link AWSCredentials} to prevent blocking I/O during
* authentication.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for AWS-IAM authentication.
* @since 2.2
*/
public static AuthenticationSteps createAuthenticationSteps(
AwsIamAuthenticationOptions options) {
public static AuthenticationSteps createAuthenticationSteps(AwsIamAuthenticationOptions options) {
Assert.notNull(options, "AwsIamAuthenticationOptions must not be null");
@@ -120,11 +114,10 @@ public class AwsIamAuthentication
return createAuthenticationSteps(options, credentials);
}
protected static AuthenticationSteps createAuthenticationSteps(
AwsIamAuthenticationOptions options, AWSCredentials credentials) {
protected static AuthenticationSteps createAuthenticationSteps(AwsIamAuthenticationOptions options,
AWSCredentials credentials) {
return AuthenticationSteps
.fromSupplier(() -> createRequestBody(options, credentials)) //
return AuthenticationSteps.fromSupplier(() -> createRequestBody(options, credentials)) //
.login(AuthenticationUtil.getLoginPath(options.getPath()));
}
@@ -135,8 +128,7 @@ public class AwsIamAuthentication
@Override
public AuthenticationSteps getAuthenticationSteps() {
return createAuthenticationSteps(this.options,
this.options.getCredentialsProvider().getCredentials());
return createAuthenticationSteps(this.options, this.options.getCredentialsProvider().getCredentials());
}
@SuppressWarnings("unchecked")
@@ -146,21 +138,17 @@ public class AwsIamAuthentication
try {
VaultResponse response = this.vaultRestOperations.postForObject(
AuthenticationUtil.getLoginPath(options.getPath()), login, VaultResponse.class);
VaultResponse response = this.vaultRestOperations
.postForObject(AuthenticationUtil.getLoginPath(this.options.getPath()), login, VaultResponse.class);
Assert.state(response != null && response.getAuth() != null,
"Auth field must not be null");
Assert.state(response != null && response.getAuth() != null, "Auth field must not be null");
if (logger.isDebugEnabled()) {
if (response.getAuth().get("metadata") instanceof Map) {
Map<Object, Object> metadata = (Map<Object, Object>) response
.getAuth().get("metadata");
logger.debug(String.format(
"Login successful using AWS-IAM authentication for user id %s, ARN %s",
metadata.get("client_user_id"),
metadata.get("canonical_arn")));
Map<Object, Object> metadata = (Map<Object, Object>) response.getAuth().get("metadata");
logger.debug(String.format("Login successful using AWS-IAM authentication for user id %s, ARN %s",
metadata.get("client_user_id"), metadata.get("canonical_arn")));
}
else {
logger.debug("Login successful using AWS-IAM authentication");
@@ -177,37 +165,31 @@ public class AwsIamAuthentication
/**
* Create the request body to perform a Vault login using the AWS-IAM authentication
* method.
*
* @param options must not be {@literal null}.
* @return the map containing body key-value pairs.
*/
protected static Map<String, String> createRequestBody(
AwsIamAuthenticationOptions options) {
return createRequestBody(options,
options.getCredentialsProvider().getCredentials());
protected static Map<String, String> createRequestBody(AwsIamAuthenticationOptions options) {
return createRequestBody(options, options.getCredentialsProvider().getCredentials());
}
/**
* Create the request body to perform a Vault login using the AWS-IAM authentication
* method.
*
* @param options must not be {@literal null}.
* @return the map containing body key-value pairs.
*/
private static Map<String, String> createRequestBody(
AwsIamAuthenticationOptions options, AWSCredentials credentials) {
private static Map<String, String> createRequestBody(AwsIamAuthenticationOptions options,
AWSCredentials credentials) {
Map<String, String> login = new HashMap<>();
login.put("iam_http_request_method", "POST");
login.put("iam_request_url", Base64Utils
.encodeToString(options.getEndpointUri().toString().getBytes()));
login.put("iam_request_url", Base64Utils.encodeToString(options.getEndpointUri().toString().getBytes()));
login.put("iam_request_body", REQUEST_BODY_BASE64_ENCODED);
String headerJson = getSignedHeaders(options, credentials);
login.put("iam_request_headers",
Base64Utils.encodeToString(headerJson.getBytes()));
login.put("iam_request_headers", Base64Utils.encodeToString(headerJson.getBytes()));
if (!StringUtils.isEmpty(options.getRole())) {
login.put("role", options.getRole());
@@ -215,8 +197,7 @@ public class AwsIamAuthentication
return login;
}
private static String getSignedHeaders(AwsIamAuthenticationOptions options,
AWSCredentials credentials) {
private static String getSignedHeaders(AwsIamAuthenticationOptions options, AWSCredentials credentials) {
Map<String, String> headers = createIamRequestHeaders(options);
@@ -246,14 +227,12 @@ public class AwsIamAuthentication
}
}
private static Map<String, String> createIamRequestHeaders(
AwsIamAuthenticationOptions options) {
private static Map<String, String> createIamRequestHeaders(AwsIamAuthenticationOptions options) {
Map<String, String> headers = new LinkedHashMap<>();
headers.put(HttpHeaders.CONTENT_LENGTH, "" + REQUEST_BODY.length());
headers.put(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_FORM_URLENCODED_VALUE);
headers.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
if (StringUtils.hasText(options.getServerId())) {
headers.put("X-Vault-AWS-IAM-Server-ID", options.getServerId());
@@ -261,4 +240,5 @@ public class AwsIamAuthentication
return headers;
}
}

View File

@@ -71,8 +71,7 @@ public class AwsIamAuthenticationOptions {
*/
private final URI endpointUri;
private AwsIamAuthenticationOptions(String path,
AWSCredentialsProvider credentialsProvider, @Nullable String role,
private AwsIamAuthenticationOptions(String path, AWSCredentialsProvider credentialsProvider, @Nullable String role,
@Nullable String serverId, URI endpointUri) {
this.path = path;
@@ -93,14 +92,14 @@ public class AwsIamAuthenticationOptions {
* @return the path of the aws authentication backend mount.
*/
public String getPath() {
return path;
return this.path;
}
/**
* @return the credentials provider to obtain AWS credentials.
*/
public AWSCredentialsProvider getCredentialsProvider() {
return credentialsProvider;
return this.credentialsProvider;
}
/**
@@ -108,7 +107,7 @@ public class AwsIamAuthenticationOptions {
*/
@Nullable
public String getRole() {
return role;
return this.role;
}
/**
@@ -119,7 +118,7 @@ public class AwsIamAuthenticationOptions {
*/
@Nullable
public String getServerId() {
return serverId;
return this.serverId;
}
/**
@@ -130,14 +129,14 @@ public class AwsIamAuthenticationOptions {
@Nullable
@Deprecated
public String getServerName() {
return serverId;
return this.serverId;
}
/**
* @return STS server URI.
*/
public URI getEndpointUri() {
return endpointUri;
return this.endpointUri;
}
/**
@@ -163,7 +162,6 @@ public class AwsIamAuthenticationOptions {
/**
* Configure the mount path, defaults to {@literal aws}.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link AwsIamAuthenticationOptionsBuilder}.
*/
@@ -179,13 +177,11 @@ public class AwsIamAuthenticationOptions {
* Configure static AWS credentials, required to calculate the signature. Either
* use static credentials or provide a
* {@link #credentialsProvider(AWSCredentialsProvider) credentials provider}.
*
* @param credentials must not be {@literal null}.
* @return {@code this} {@link AwsIamAuthenticationOptionsBuilder}.
* @see #credentialsProvider(AWSCredentialsProvider)
*/
public AwsIamAuthenticationOptionsBuilder credentials(
AWSCredentials credentials) {
public AwsIamAuthenticationOptionsBuilder credentials(AWSCredentials credentials) {
Assert.notNull(credentials, "Credentials must not be null");
@@ -196,16 +192,13 @@ public class AwsIamAuthenticationOptions {
* Configure an {@link AWSCredentialsProvider}, required to calculate the
* signature. Alternatively, configure static {@link #credentials(AWSCredentials)
* credentials}.
*
* @param credentialsProvider must not be {@literal null}.
* @return {@code this} {@link AwsIamAuthenticationOptionsBuilder}.
* @see #credentials(AWSCredentials)
*/
public AwsIamAuthenticationOptionsBuilder credentialsProvider(
AWSCredentialsProvider credentialsProvider) {
public AwsIamAuthenticationOptionsBuilder credentialsProvider(AWSCredentialsProvider credentialsProvider) {
Assert.notNull(credentialsProvider,
"AWSCredentialsProvider must not be null");
Assert.notNull(credentialsProvider, "AWSCredentialsProvider must not be null");
this.credentialsProvider = credentialsProvider;
return this;
@@ -215,7 +208,6 @@ public class AwsIamAuthenticationOptions {
* Configure the name of the role against which the login is being attempted. If
* role is not specified, the friendly name (i.e., role name or username) of the
* IAM principal authenticated. If a matching role is not found, login fails.
*
* @param role must not be empty or {@literal null}.
* @return {@code this} {@link AwsIamAuthenticationOptionsBuilder}.
*/
@@ -231,7 +223,6 @@ public class AwsIamAuthenticationOptions {
* Configure a server name (used for {@literal Vault-AWS-IAM-Server-ID}) that is
* included in the signature to mitigate the risk of replay attacks. Preferably
* use the Vault server DNS name.
*
* @param serverId must not be {@literal null} or empty.
* @return {@code this} {@link AwsIamAuthenticationOptionsBuilder}.
* @since 2.1
@@ -247,7 +238,6 @@ public class AwsIamAuthenticationOptions {
/**
* Configure a server name that is included in the signature to mitigate the risk
* of replay attacks. Preferably use the Vault server DNS name.
*
* @param serverName must not be {@literal null} or empty.
* @return {@code this} {@link AwsIamAuthenticationOptionsBuilder}.
*/
@@ -258,7 +248,6 @@ public class AwsIamAuthenticationOptions {
/**
* Configure an endpoint URI of the STS API, defaults to
* {@literal https://sts.amazonaws.com/}.
*
* @param endpointUri must not be {@literal null}.
* @return {@code this} {@link AwsIamAuthenticationOptionsBuilder}.
*/
@@ -272,16 +261,16 @@ public class AwsIamAuthenticationOptions {
/**
* Build a new {@link AwsIamAuthenticationOptions} instance.
*
* @return a new {@link AwsIamAuthenticationOptions}.
*/
public AwsIamAuthenticationOptions build() {
Assert.state(credentialsProvider != null,
"Credentials or CredentialProvider must not be null");
Assert.state(this.credentialsProvider != null, "Credentials or CredentialProvider must not be null");
return new AwsIamAuthenticationOptions(path, credentialsProvider, role,
serverId, endpointUri);
return new AwsIamAuthenticationOptions(this.path, this.credentialsProvider, this.role, this.serverId,
this.endpointUri);
}
}
}

View File

@@ -73,12 +73,10 @@ public class AzureMsiAuthentication implements ClientAuthentication {
/**
* Create a new {@link AzureMsiAuthentication}.
*
* @param options must not be {@literal null}.
* @param restOperations must not be {@literal null}.
*/
public AzureMsiAuthentication(AzureMsiAuthenticationOptions options,
RestOperations restOperations) {
public AzureMsiAuthentication(AzureMsiAuthenticationOptions options, RestOperations restOperations) {
this(options, restOperations, restOperations);
}
@@ -86,19 +84,16 @@ public class AzureMsiAuthentication implements ClientAuthentication {
* Create a new {@link AzureMsiAuthentication} specifying
* {@link AzureMsiAuthenticationOptions}, a Vault and an Azure-Metadata-specific
* {@link RestOperations}.
*
* @param options must not be {@literal null}.
* @param vaultRestOperations must not be {@literal null}.
* @param azureMetadataRestOperations must not be {@literal null}.
*/
public AzureMsiAuthentication(AzureMsiAuthenticationOptions options,
RestOperations vaultRestOperations,
public AzureMsiAuthentication(AzureMsiAuthenticationOptions options, RestOperations vaultRestOperations,
RestOperations azureMetadataRestOperations) {
Assert.notNull(options, "AzureAuthenticationOptions must not be null");
Assert.notNull(vaultRestOperations, "Vault RestOperations must not be null");
Assert.notNull(azureMetadataRestOperations,
"Azure Instance Metadata RestOperations must not be null");
Assert.notNull(azureMetadataRestOperations, "Azure Instance Metadata RestOperations must not be null");
this.options = options;
this.vaultRestOperations = vaultRestOperations;
@@ -108,26 +103,22 @@ public class AzureMsiAuthentication implements ClientAuthentication {
/**
* Creates a {@link AuthenticationSteps} for Azure authentication given
* {@link AzureMsiAuthenticationOptions}.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for Azure authentication.
*/
public static AuthenticationSteps createAuthenticationSteps(
AzureMsiAuthenticationOptions options) {
public static AuthenticationSteps createAuthenticationSteps(AzureMsiAuthenticationOptions options) {
Assert.notNull(options, "AzureMsiAuthenticationOptions must not be null");
return createAuthenticationSteps(options, options.getVmEnvironment());
}
protected static AuthenticationSteps createAuthenticationSteps(
AzureMsiAuthenticationOptions options,
protected static AuthenticationSteps createAuthenticationSteps(AzureMsiAuthenticationOptions options,
@Nullable AzureVmEnvironment environment) {
Node<String> msiToken = AuthenticationSteps
.fromHttpRequest(
HttpRequestBuilder.get(options.getIdentityTokenServiceUri())
.with(METADATA_HEADERS).as(Map.class)) //
.fromHttpRequest(HttpRequestBuilder.get(options.getIdentityTokenServiceUri()).with(METADATA_HEADERS)
.as(Map.class)) //
.map(token -> (String) token.get("access_token"));
Node<AzureVmEnvironment> environmentSteps;
@@ -135,8 +126,7 @@ public class AzureMsiAuthentication implements ClientAuthentication {
if (environment == null) {
environmentSteps = AuthenticationSteps
.fromHttpRequest(HttpRequestBuilder
.get(options.getInstanceMetadataServiceUri())
.fromHttpRequest(HttpRequestBuilder.get(options.getInstanceMetadataServiceUri())
.with(METADATA_HEADERS).as(Map.class)) //
.map(AzureMsiAuthentication::toAzureVmEnvironment);
}
@@ -145,8 +135,7 @@ public class AzureMsiAuthentication implements ClientAuthentication {
}
return environmentSteps.zipWith(msiToken)
.map(tuple -> getAzureLogin(options.getRole(), tuple.getLeft(),
tuple.getRight())) //
.map(tuple -> getAzureLogin(options.getRole(), tuple.getLeft(), tuple.getRight())) //
.login(AuthenticationUtil.getLoginPath(options.getPath()));
}
@@ -157,16 +146,14 @@ public class AzureMsiAuthentication implements ClientAuthentication {
private VaultToken createTokenUsingAzureMsiCompute() {
Map<String, String> login = getAzureLogin(options.getRole(), getVmEnvironment(),
getAccessToken());
Map<String, String> login = getAzureLogin(this.options.getRole(), getVmEnvironment(), getAccessToken());
try {
VaultResponse response = this.vaultRestOperations.postForObject(
AuthenticationUtil.getLoginPath(options.getPath()), login, VaultResponse.class);
VaultResponse response = this.vaultRestOperations
.postForObject(AuthenticationUtil.getLoginPath(this.options.getPath()), login, VaultResponse.class);
Assert.state(response != null && response.getAuth() != null,
"Auth field must not be null");
Assert.state(response != null && response.getAuth() != null, "Auth field must not be null");
if (logger.isDebugEnabled()) {
logger.debug("Login successful using Azure authentication");
@@ -179,8 +166,7 @@ public class AzureMsiAuthentication implements ClientAuthentication {
}
}
private static Map<String, String> getAzureLogin(String role,
AzureVmEnvironment vmEnvironment, String jwt) {
private static Map<String, String> getAzureLogin(String role, AzureVmEnvironment vmEnvironment, String jwt) {
Map<String, String> loginBody = new LinkedHashMap<>();
loginBody.put("resource_group_name", vmEnvironment.getResourceGroupName());
@@ -194,32 +180,29 @@ public class AzureMsiAuthentication implements ClientAuthentication {
private String getAccessToken() {
ResponseEntity<Map> response = this.azureMetadataRestOperations.exchange(
options.getIdentityTokenServiceUri(), HttpMethod.GET, METADATA_HEADERS,
Map.class);
ResponseEntity<Map> response = this.azureMetadataRestOperations
.exchange(this.options.getIdentityTokenServiceUri(), HttpMethod.GET, METADATA_HEADERS, Map.class);
return (String) response.getBody().get("access_token");
}
private AzureVmEnvironment getVmEnvironment() {
AzureVmEnvironment vmEnvironment = options.getVmEnvironment();
AzureVmEnvironment vmEnvironment = this.options.getVmEnvironment();
return vmEnvironment != null ? vmEnvironment : fetchAzureVmEnvironment();
}
private AzureVmEnvironment fetchAzureVmEnvironment() {
ResponseEntity<Map> response = this.azureMetadataRestOperations.exchange(
options.getInstanceMetadataServiceUri(), HttpMethod.GET, METADATA_HEADERS,
Map.class);
ResponseEntity<Map> response = this.azureMetadataRestOperations
.exchange(this.options.getInstanceMetadataServiceUri(), HttpMethod.GET, METADATA_HEADERS, Map.class);
return toAzureVmEnvironment(response.getBody());
}
@SuppressWarnings("unchecked")
private static AzureVmEnvironment toAzureVmEnvironment(
Map<String, Object> instanceMetadata) {
private static AzureVmEnvironment toAzureVmEnvironment(Map<String, Object> instanceMetadata) {
Map<String, String> compute = (Map) instanceMetadata.get("compute");
@@ -229,4 +212,5 @@ public class AzureMsiAuthentication implements ClientAuthentication {
return new AzureVmEnvironment(subscriptionId, resourceGroupName, vmName);
}
}

View File

@@ -69,9 +69,8 @@ public class AzureMsiAuthenticationOptions {
@Nullable
private final AzureVmEnvironment vmEnvironment;
private AzureMsiAuthenticationOptions(String path, String role,
URI instanceMetadataServiceUri, URI identityTokenServiceUri,
@Nullable AzureVmEnvironment vmEnvironment) {
private AzureMsiAuthenticationOptions(String path, String role, URI instanceMetadataServiceUri,
URI identityTokenServiceUri, @Nullable AzureVmEnvironment vmEnvironment) {
this.path = path;
this.role = role;
@@ -91,14 +90,14 @@ public class AzureMsiAuthenticationOptions {
* @return the path of the azure authentication backend mount.
*/
public String getPath() {
return path;
return this.path;
}
/**
* @return the role against which the login is being attempted.
*/
public String getRole() {
return role;
return this.role;
}
/**
@@ -108,21 +107,21 @@ public class AzureMsiAuthenticationOptions {
*/
@Nullable
public AzureVmEnvironment getVmEnvironment() {
return vmEnvironment;
return this.vmEnvironment;
}
/**
* @return {@link URI} to the instance metadata endpoint.
*/
public URI getInstanceMetadataServiceUri() {
return instanceMetadataServiceUri;
return this.instanceMetadataServiceUri;
}
/**
* @return {@link URI} to the token service for the managed identity.
*/
public URI getIdentityTokenServiceUri() {
return identityTokenServiceUri;
return this.identityTokenServiceUri;
}
/**
@@ -147,7 +146,6 @@ public class AzureMsiAuthenticationOptions {
/**
* Configure the mount path, defaults to {@literal azure}.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link AzureMsiAuthenticationOptionsBuilder}.
*/
@@ -161,7 +159,6 @@ public class AzureMsiAuthenticationOptions {
/**
* Configure the name of the role against which the login is being attempted.
*
* @param role must not be empty or {@literal null}.
* @return {@code this} {@link AzureMsiAuthenticationOptionsBuilder}.
*/
@@ -178,12 +175,10 @@ public class AzureMsiAuthenticationOptions {
* Environment details are passed to Vault as login body. If left unconfigured,
* {@link AzureMsiAuthentication} looks up the details from the instance metadata
* service.
*
* @param vmEnvironment must not be {@literal null}.
* @return {@code this} {@link AzureMsiAuthenticationOptionsBuilder}.
*/
public AzureMsiAuthenticationOptionsBuilder vmEnvironment(
AzureVmEnvironment vmEnvironment) {
public AzureMsiAuthenticationOptionsBuilder vmEnvironment(AzureVmEnvironment vmEnvironment) {
Assert.notNull(vmEnvironment, "AzureVmEnvironment must not be null");
@@ -193,16 +188,13 @@ public class AzureMsiAuthenticationOptions {
/**
* Configure the instance metadata {@link URI}.
*
* @param instanceMetadataServiceUri must not be {@literal null}.
* @return {@code this} {@link AzureMsiAuthenticationOptionsBuilder}.
* @see #DEFAULT_IDENTITY_TOKEN_SERVICE_URI
*/
public AzureMsiAuthenticationOptionsBuilder instanceMetadataUri(
URI instanceMetadataServiceUri) {
public AzureMsiAuthenticationOptionsBuilder instanceMetadataUri(URI instanceMetadataServiceUri) {
Assert.notNull(identityTokenServiceUri,
"Instance metadata service URI must not be null");
Assert.notNull(this.identityTokenServiceUri, "Instance metadata service URI must not be null");
this.instanceMetadataServiceUri = instanceMetadataServiceUri;
return this;
@@ -210,16 +202,13 @@ public class AzureMsiAuthenticationOptions {
/**
* Configure the managed identity service token {@link URI}.
*
* @param identityTokenServiceUri must not be {@literal null}.
* @return {@code this} {@link AzureMsiAuthenticationOptionsBuilder}.
* @see #DEFAULT_IDENTITY_TOKEN_SERVICE_URI
*/
public AzureMsiAuthenticationOptionsBuilder identityTokenServiceUri(
URI identityTokenServiceUri) {
public AzureMsiAuthenticationOptionsBuilder identityTokenServiceUri(URI identityTokenServiceUri) {
Assert.notNull(identityTokenServiceUri,
"Identity token service URI must not be null");
Assert.notNull(identityTokenServiceUri, "Identity token service URI must not be null");
this.identityTokenServiceUri = identityTokenServiceUri;
return this;
@@ -227,15 +216,16 @@ public class AzureMsiAuthenticationOptions {
/**
* Build a new {@link AzureMsiAuthenticationOptions} instance.
*
* @return a new {@link AzureMsiAuthenticationOptions}.
*/
public AzureMsiAuthenticationOptions build() {
Assert.hasText(role, "Role must not be null or empty");
Assert.hasText(this.role, "Role must not be null or empty");
return new AzureMsiAuthenticationOptions(path, role,
instanceMetadataServiceUri, identityTokenServiceUri, vmEnvironment);
return new AzureMsiAuthenticationOptions(this.path, this.role, this.instanceMetadataServiceUri,
this.identityTokenServiceUri, this.vmEnvironment);
}
}
}

View File

@@ -39,13 +39,11 @@ public class AzureVmEnvironment {
/**
* Creates a new {@link AzureVmEnvironment}.
*
* @param subscriptionId must not be {@literal null}.
* @param resourceGroupName must not be {@literal null}.
* @param vmName must not be {@literal null}.
*/
public AzureVmEnvironment(String subscriptionId, String resourceGroupName,
String vmName) {
public AzureVmEnvironment(String subscriptionId, String resourceGroupName, String vmName) {
Assert.notNull(subscriptionId, "SubscriptionId must not be null");
Assert.notNull(resourceGroupName, "Resource group name must not be null");
@@ -57,14 +55,15 @@ public class AzureVmEnvironment {
}
public String getSubscriptionId() {
return subscriptionId;
return this.subscriptionId;
}
public String getResourceGroupName() {
return resourceGroupName;
return this.resourceGroupName;
}
public String getVmName() {
return vmName;
return this.vmName;
}
}

View File

@@ -32,15 +32,13 @@ import org.springframework.vault.support.VaultToken;
* @see VaultTokenSupplier
* @see VaultToken
*/
public class CachingVaultTokenSupplier
implements VaultTokenSupplier, ReactiveSessionManager {
public class CachingVaultTokenSupplier implements VaultTokenSupplier, ReactiveSessionManager {
private static final Mono<VaultToken> EMPTY = Mono.empty();
private final VaultTokenSupplier clientAuthentication;
private final AtomicReference<Mono<VaultToken>> tokenRef = new AtomicReference<>(
EMPTY);
private final AtomicReference<Mono<VaultToken>> tokenRef = new AtomicReference<>(EMPTY);
private CachingVaultTokenSupplier(VaultTokenSupplier clientAuthentication) {
this.clientAuthentication = clientAuthentication;
@@ -49,7 +47,6 @@ public class CachingVaultTokenSupplier
/**
* Creates a new {@link CachingVaultTokenSupplier} given a {@link VaultTokenSupplier
* delegate supplier}.
*
* @param delegate must not be {@literal null}.
* @return the {@link CachingVaultTokenSupplier} for a {@link VaultTokenSupplier
* delegate supplier}.
@@ -61,10 +58,11 @@ public class CachingVaultTokenSupplier
@Override
public Mono<VaultToken> getVaultToken() throws VaultException {
if (Objects.equals(tokenRef.get(), EMPTY)) {
tokenRef.compareAndSet(EMPTY, clientAuthentication.getVaultToken().cache());
if (Objects.equals(this.tokenRef.get(), EMPTY)) {
this.tokenRef.compareAndSet(EMPTY, this.clientAuthentication.getVaultToken().cache());
}
return tokenRef.get();
return this.tokenRef.get();
}
}

View File

@@ -31,8 +31,8 @@ public interface ClientAuthentication {
/**
* Return a {@link VaultToken}. This method can optionally log into Vault to obtain a
* {@link VaultToken token}.
*
* @return a {@link VaultToken}.
*/
VaultToken login() throws VaultException;
}

View File

@@ -33,11 +33,9 @@ import static org.springframework.vault.authentication.AuthenticationSteps.HttpR
*
* @author Mark Paluch
*/
public class ClientCertificateAuthentication
implements ClientAuthentication, AuthenticationStepsFactory {
public class ClientCertificateAuthentication implements ClientAuthentication, AuthenticationStepsFactory {
private static final Log logger = LogFactory
.getLog(ClientCertificateAuthentication.class);
private static final Log logger = LogFactory.getLog(ClientCertificateAuthentication.class);
private final ClientCertificateAuthenticationOptions options;
@@ -45,7 +43,6 @@ public class ClientCertificateAuthentication
/**
* Create a {@link ClientCertificateAuthentication} using {@link RestOperations}.
*
* @param restOperations must not be {@literal null}.
*/
public ClientCertificateAuthentication(RestOperations restOperations) {
@@ -54,7 +51,6 @@ public class ClientCertificateAuthentication
/**
* Create a {@link ClientCertificateAuthentication} using {@link RestOperations}.
*
* @param options must not be {@literal null}.
* @param restOperations must not be {@literal null}.
* @since 2.2.3
@@ -62,8 +58,7 @@ public class ClientCertificateAuthentication
public ClientCertificateAuthentication(ClientCertificateAuthenticationOptions options,
RestOperations restOperations) {
Assert.notNull(options,
"ClientCertificateAuthenticationOptions must not be null");
Assert.notNull(options, "ClientCertificateAuthenticationOptions must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
this.restOperations = restOperations;
@@ -72,31 +67,25 @@ public class ClientCertificateAuthentication
/**
* Creates a {@link AuthenticationSteps} for client certificate authentication.
*
* @return {@link AuthenticationSteps} for client certificate authentication.
* @since 2.0
*/
public static AuthenticationSteps createAuthenticationSteps() {
return createAuthenticationSteps(
ClientCertificateAuthenticationOptions.builder().build());
return createAuthenticationSteps(ClientCertificateAuthenticationOptions.builder().build());
}
/**
* Creates a {@link AuthenticationSteps} for client certificate authentication.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for client certificate authentication.
* @since 2.2.3
*/
public static AuthenticationSteps createAuthenticationSteps(
ClientCertificateAuthenticationOptions options) {
public static AuthenticationSteps createAuthenticationSteps(ClientCertificateAuthenticationOptions options) {
Assert.notNull(options,
"ClientCertificateAuthenticationOptions must not be null");
Assert.notNull(options, "ClientCertificateAuthenticationOptions must not be null");
return AuthenticationSteps
.just(post(AuthenticationUtil.getLoginPath(options.getPath()))
.as(VaultResponse.class));
.just(post(AuthenticationUtil.getLoginPath(options.getPath())).as(VaultResponse.class));
}
@Override
@@ -106,15 +95,15 @@ public class ClientCertificateAuthentication
@Override
public AuthenticationSteps getAuthenticationSteps() {
return createAuthenticationSteps(options);
return createAuthenticationSteps(this.options);
}
private VaultToken createTokenUsingTlsCertAuthentication() {
try {
VaultResponse response = restOperations.postForObject(
AuthenticationUtil.getLoginPath(options.getPath()),
Collections.emptyMap(), VaultResponse.class);
VaultResponse response = this.restOperations.postForObject(
AuthenticationUtil.getLoginPath(this.options.getPath()), Collections.emptyMap(),
VaultResponse.class);
Assert.state(response.getAuth() != null, "Auth field must not be null");
@@ -126,4 +115,5 @@ public class ClientCertificateAuthentication
throw VaultLoginException.create("TLS Certificates", e);
}
}
}

View File

@@ -53,7 +53,7 @@ public class ClientCertificateAuthenticationOptions {
* @return the path of the azure authentication backend mount.
*/
public String getPath() {
return path;
return this.path;
}
/**
@@ -68,7 +68,6 @@ public class ClientCertificateAuthenticationOptions {
/**
* Configure the mount path, defaults to {@literal azure}.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link ClientCertificateAuthenticationOptionsBuilder}.
*/
@@ -82,11 +81,12 @@ public class ClientCertificateAuthenticationOptions {
/**
* Build a new {@link ClientCertificateAuthenticationOptions} instance.
*
* @return a new {@link ClientCertificateAuthenticationOptions}.
*/
public ClientCertificateAuthenticationOptions build() {
return new ClientCertificateAuthenticationOptions(path);
return new ClientCertificateAuthenticationOptions(this.path);
}
}
}

View File

@@ -31,7 +31,6 @@ public interface CredentialSupplier extends Supplier<String> {
/**
* Get a credential to be used with an authentication mechanism.
*
* @return the credential.
*/
@Override
@@ -44,7 +43,6 @@ public interface CredentialSupplier extends Supplier<String> {
* <p>
* Reusing a cached token can lead to authentication failures if the credential
* expires.
*
* @return a caching {@link CredentialSupplier}.
*/
default CredentialSupplier cached() {
@@ -53,4 +51,5 @@ public interface CredentialSupplier extends Supplier<String> {
return () -> credential;
}
}

View File

@@ -56,8 +56,7 @@ import static org.springframework.vault.authentication.AuthenticationSteps.HttpR
* wrapping_token_ttl: 0h10m0s
* wrapping_token_creation_time: 2016-09-18 20:29:48.652957077 +0200 CEST
* wrapped_accessor: 46b6aebb-187f-932a-26d7-4f3d86a68319
* </code>
* </pre>
* </code> </pre>
*
* <strong>Setup {@link CubbyholeAuthentication}</strong>
*
@@ -69,8 +68,7 @@ import static org.springframework.vault.authentication.AuthenticationSteps.HttpR
* .wrapped()
* .build();
* CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, restOperations);
* </code>
* </pre>
* </code> </pre>
*
* <h2>Stored token response usage</h2> <strong>Create a Token</strong>
*
@@ -96,8 +94,7 @@ import static org.springframework.vault.authentication.AuthenticationSteps.HttpR
*
* $ export VAULT_TOKEN=895cb88b-aef4-0e33-ba65-d50007290780
* $ vault write cubbyhole/token token=f9e30681-d46a-cdaf-aaa0-2ae0a9ad0819
* </code>
* </pre>
* </code> </pre>
*
* <strong>Setup {@link CubbyholeAuthentication}</strong>
*
@@ -109,8 +106,7 @@ import static org.springframework.vault.authentication.AuthenticationSteps.HttpR
* .path("cubbyhole/token")
* .build();
* CubbyholeAuthentication authentication = new CubbyholeAuthentication(options, restOperations);
* </code>
* </pre>
* </code> </pre>
*
* <strong>Remaining TTL/Renewability</strong>
* <p>
@@ -135,8 +131,7 @@ import static org.springframework.vault.authentication.AuthenticationSteps.HttpR
* "https://www.vaultproject.io/docs/concepts/response-wrapping.html">Response
* Wrapping</a>
*/
public class CubbyholeAuthentication
implements ClientAuthentication, AuthenticationStepsFactory {
public class CubbyholeAuthentication implements ClientAuthentication, AuthenticationStepsFactory {
private static final Log logger = LogFactory.getLog(CubbyholeAuthentication.class);
@@ -147,12 +142,10 @@ public class CubbyholeAuthentication
/**
* Create a new {@link CubbyholeAuthentication} given
* {@link CubbyholeAuthenticationOptions} and {@link RestOperations}.
*
* @param options must not be {@literal null}.
* @param restOperations must not be {@literal null}.
*/
public CubbyholeAuthentication(CubbyholeAuthenticationOptions options,
RestOperations restOperations) {
public CubbyholeAuthentication(CubbyholeAuthenticationOptions options, RestOperations restOperations) {
Assert.notNull(options, "CubbyholeAuthenticationOptions must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
@@ -164,13 +157,11 @@ public class CubbyholeAuthentication
/**
* Creates a {@link AuthenticationSteps} for cubbyhole authentication given
* {@link CubbyholeAuthenticationOptions}.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for cubbyhole authentication.
* @since 2.0
*/
public static AuthenticationSteps createAuthenticationSteps(
CubbyholeAuthenticationOptions options) {
public static AuthenticationSteps createAuthenticationSteps(CubbyholeAuthenticationOptions options) {
Assert.notNull(options, "CubbyholeAuthenticationOptions must not be null");
@@ -190,15 +181,14 @@ public class CubbyholeAuthentication
@Override
public VaultToken login() throws VaultException {
String url = getRequestPath(options);
String url = getRequestPath(this.options);
VaultResponse data = lookupToken(url);
VaultToken tokenToUse = getToken(this.options, data, url);
if (shouldEnhanceTokenWithSelfLookup(tokenToUse)) {
LoginTokenAdapter adapter = new LoginTokenAdapter(
new TokenAuthentication(tokenToUse), restOperations);
LoginTokenAdapter adapter = new LoginTokenAdapter(new TokenAuthentication(tokenToUse), this.restOperations);
tokenToUse = adapter.login();
}
@@ -208,17 +198,17 @@ public class CubbyholeAuthentication
@Override
public AuthenticationSteps getAuthenticationSteps() {
return createAuthenticationSteps(options);
return createAuthenticationSteps(this.options);
}
@Nullable
private VaultResponse lookupToken(String url) {
try {
HttpMethod unwrapMethod = getRequestMethod(options);
HttpEntity<Object> requestEntity = getRequestEntity(options);
ResponseEntity<VaultResponse> entity = restOperations.exchange(url,
unwrapMethod, requestEntity, VaultResponse.class);
HttpMethod unwrapMethod = getRequestMethod(this.options);
HttpEntity<Object> requestEntity = getRequestEntity(this.options);
ResponseEntity<VaultResponse> entity = this.restOperations.exchange(url, unwrapMethod, requestEntity,
VaultResponse.class);
Assert.state(entity.getBody() != null, "Auth response must not be null");
@@ -231,7 +221,7 @@ public class CubbyholeAuthentication
private boolean shouldEnhanceTokenWithSelfLookup(VaultToken token) {
if (!options.isSelfLookup()) {
if (!this.options.isSelfLookup()) {
return false;
}
@@ -247,8 +237,7 @@ public class CubbyholeAuthentication
return true;
}
private static HttpEntity<Object> getRequestEntity(
CubbyholeAuthenticationOptions options) {
private static HttpEntity<Object> getRequestEntity(CubbyholeAuthenticationOptions options) {
return new HttpEntity<>(VaultHttpHeaders.from(options.getInitialToken()));
}
@@ -270,13 +259,11 @@ public class CubbyholeAuthentication
return options.getPath();
}
private static VaultToken getToken(CubbyholeAuthenticationOptions options,
VaultResponse response, String url) {
private static VaultToken getToken(CubbyholeAuthenticationOptions options, VaultResponse response, String url) {
if (options.isWrappedToken()) {
VaultResponse responseToUse = options.getUnwrappingEndpoints()
.unwrap(response);
VaultResponse responseToUse = options.getUnwrappingEndpoints().unwrap(response);
Assert.state(responseToUse.getAuth() != null, "Auth field must not be null");
@@ -285,9 +272,9 @@ public class CubbyholeAuthentication
Map<String, Object> data = response.getData();
if (data == null || data.isEmpty()) {
throw new VaultLoginException(String.format(
"Cannot retrieve Token from Cubbyhole: Response at %s does not contain a token",
options.getPath()));
throw new VaultLoginException(
String.format("Cannot retrieve Token from Cubbyhole: Response at %s does not contain a token",
options.getPath()));
}
if (data.size() == 1) {
@@ -295,8 +282,8 @@ public class CubbyholeAuthentication
return VaultToken.of(token);
}
throw new VaultLoginException(String.format(
"Cannot retrieve Token from Cubbyhole: Response at %s does not contain an unique token",
url));
throw new VaultLoginException(String
.format("Cannot retrieve Token from Cubbyhole: Response at %s does not contain an unique token", url));
}
}

View File

@@ -58,8 +58,7 @@ public class CubbyholeAuthenticationOptions {
private final boolean selfLookup;
private CubbyholeAuthenticationOptions(VaultToken initialToken, String path,
UnwrappingEndpoints unwrappingEndpoints, boolean wrappedToken,
boolean selfLookup) {
UnwrappingEndpoints unwrappingEndpoints, boolean wrappedToken, boolean selfLookup) {
this.initialToken = initialToken;
this.path = path;
@@ -79,14 +78,14 @@ public class CubbyholeAuthenticationOptions {
* @return the initial {@link VaultToken} to access Cubbyhole.
*/
public VaultToken getInitialToken() {
return initialToken;
return this.initialToken;
}
/**
* @return the path of the Cubbyhole response path.
*/
public String getPath() {
return path;
return this.path;
}
/**
@@ -94,7 +93,7 @@ public class CubbyholeAuthenticationOptions {
* @since 2.2
*/
public UnwrappingEndpoints getUnwrappingEndpoints() {
return unwrappingEndpoints;
return this.unwrappingEndpoints;
}
/**
@@ -103,7 +102,7 @@ public class CubbyholeAuthenticationOptions {
* response.
*/
public boolean isWrappedToken() {
return wrappedToken;
return this.wrappedToken;
}
/**
@@ -114,7 +113,7 @@ public class CubbyholeAuthenticationOptions {
* @since 1.0.1
*/
public boolean isSelfLookup() {
return selfLookup;
return this.selfLookup;
}
/**
@@ -139,12 +138,10 @@ public class CubbyholeAuthenticationOptions {
/**
* Configure the initial {@link VaultToken} to access Cubbyhole.
*
* @param initialToken must not be {@literal null}.
* @return {@code this} {@link CubbyholeAuthenticationOptionsBuilder}.
*/
public CubbyholeAuthenticationOptionsBuilder initialToken(
VaultToken initialToken) {
public CubbyholeAuthenticationOptionsBuilder initialToken(VaultToken initialToken) {
Assert.notNull(initialToken, "Initial Vault Token must not be null");
@@ -155,7 +152,6 @@ public class CubbyholeAuthenticationOptions {
/**
* Configure the cubbyhole path, such as {@code cubbyhole/token}. Expects a token
* in the {@code data} response.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link CubbyholeAuthenticationOptionsBuilder}.
*/
@@ -169,13 +165,11 @@ public class CubbyholeAuthenticationOptions {
/**
* Configure the {@link UnwrappingEndpoints} to use.
*
* @param endpoints must not be {@literal null}.
* @return {@code this} {@link CubbyholeAuthenticationOptionsBuilder}
* @since 2.2
*/
public CubbyholeAuthenticationOptionsBuilder unwrappingEndpoints(
UnwrappingEndpoints endpoints) {
public CubbyholeAuthenticationOptionsBuilder unwrappingEndpoints(UnwrappingEndpoints endpoints) {
Assert.notNull(endpoints, "UnwrappingEndpoints must not be empty");
@@ -185,7 +179,6 @@ public class CubbyholeAuthenticationOptions {
/**
* Configure whether to use wrapped token responses.
*
* @return {@code this} {@link CubbyholeAuthenticationOptionsBuilder}.
*/
public CubbyholeAuthenticationOptionsBuilder wrapped() {
@@ -198,9 +191,8 @@ public class CubbyholeAuthenticationOptions {
/**
* Configure whether to perform a self-lookup after token retrieval. Defaults to
* {@literal true}.
*
* @param selfLookup {@literal true} to perform a self-lookup or {@literal false}
* to disable it.
* to disable it.
* @return {@code this} {@link CubbyholeAuthenticationOptionsBuilder}.
* @since 1.0.1
*/
@@ -213,16 +205,17 @@ public class CubbyholeAuthenticationOptions {
/**
* Build a new {@link CubbyholeAuthenticationOptions} instance. Requires
* {@link #path(String)} or {@link #wrapped()} to be configured.
*
* @return a new {@link CubbyholeAuthenticationOptions}.
*/
public CubbyholeAuthenticationOptions build() {
Assert.notNull(initialToken, "Initial Vault Token must not be null");
Assert.notNull(path, "Path must not be null");
Assert.notNull(this.initialToken, "Initial Vault Token must not be null");
Assert.notNull(this.path, "Path must not be null");
return new CubbyholeAuthenticationOptions(initialToken, path, endpoints,
wrappedToken, selfLookup);
return new CubbyholeAuthenticationOptions(this.initialToken, this.path, this.endpoints, this.wrappedToken,
this.selfLookup);
}
}
}

View File

@@ -29,14 +29,12 @@ import org.springframework.util.StringUtils;
* @since 2.1
* @see GcpIamAuthentication
*/
enum DefaultGcpCredentialAccessors
implements GcpProjectIdAccessor, GcpServiceAccountIdAccessor {
enum DefaultGcpCredentialAccessors implements GcpProjectIdAccessor, GcpServiceAccountIdAccessor {
INSTANCE;
/**
* Get a the service account id (email) to be placed in the signed JWT.
*
* @param credential credential object to obtain the service account id from.
* @return the service account id to use.
*/
@@ -52,7 +50,6 @@ enum DefaultGcpCredentialAccessors
/**
* Get a the GCP project id to used in Google Cloud IAM API calls.
*
* @param credential the credential object to obtain the project id from.
* @return the service account id to use.
*/
@@ -64,4 +61,5 @@ enum DefaultGcpCredentialAccessors
return StringUtils.isEmpty(credential.getServiceAccountProjectId()) ? "-"
: credential.getServiceAccountProjectId();
}
}

View File

@@ -63,12 +63,10 @@ public class GcpComputeAuthentication extends GcpJwtAuthenticationSupport
* Create a new {@link GcpComputeAuthentication} instance given
* {@link GcpComputeAuthenticationOptions} and {@link RestOperations} for Vault and
* Google API use.
*
* @param options must not be {@literal null}.
* @param vaultRestOperations must not be {@literal null}.
*/
public GcpComputeAuthentication(GcpComputeAuthenticationOptions options,
RestOperations vaultRestOperations) {
public GcpComputeAuthentication(GcpComputeAuthenticationOptions options, RestOperations vaultRestOperations) {
this(options, vaultRestOperations, vaultRestOperations);
}
@@ -76,20 +74,17 @@ public class GcpComputeAuthentication extends GcpJwtAuthenticationSupport
* Create a new {@link GcpComputeAuthentication} instance given
* {@link GcpComputeAuthenticationOptions} and {@link RestOperations} for Vault and
* Google API use.
*
* @param options must not be {@literal null}.
* @param vaultRestOperations must not be {@literal null}.
* @param googleMetadataRestOperations must not be {@literal null}.
*/
public GcpComputeAuthentication(GcpComputeAuthenticationOptions options,
RestOperations vaultRestOperations,
public GcpComputeAuthentication(GcpComputeAuthenticationOptions options, RestOperations vaultRestOperations,
RestOperations googleMetadataRestOperations) {
super(vaultRestOperations);
Assert.notNull(options, "GcpGceAuthenticationOptions must not be null");
Assert.notNull(googleMetadataRestOperations,
"Google Metadata RestOperations must not be null");
Assert.notNull(googleMetadataRestOperations, "Google Metadata RestOperations must not be null");
this.options = options;
this.googleMetadataRestOperations = googleMetadataRestOperations;
@@ -98,22 +93,19 @@ public class GcpComputeAuthentication extends GcpJwtAuthenticationSupport
/**
* Creates a {@link AuthenticationSteps} for GCE authentication given
* {@link GcpComputeAuthenticationOptions}.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for cubbyhole authentication.
*/
public static AuthenticationSteps createAuthenticationSteps(
GcpComputeAuthenticationOptions options) {
public static AuthenticationSteps createAuthenticationSteps(GcpComputeAuthenticationOptions options) {
Assert.notNull(options, "CubbyholeAuthenticationOptions must not be null");
String serviceAccount = options.getServiceAccount();
String audience = getAudience(options.getRole());
HttpRequest<String> jwtRequest = get(COMPUTE_METADATA_URL_TEMPLATE,
serviceAccount, audience, "full") //
.with(getMetadataHttpHeaders()) //
.as(String.class);
HttpRequest<String> jwtRequest = get(COMPUTE_METADATA_URL_TEMPLATE, serviceAccount, audience, "full") //
.with(getMetadataHttpHeaders()) //
.as(String.class);
return AuthenticationSteps.fromHttpRequest(jwtRequest)
//
@@ -126,13 +118,12 @@ public class GcpComputeAuthentication extends GcpJwtAuthenticationSupport
String signedJwt = signJwt();
return doLogin("GCP-GCE", signedJwt, this.options.getPath(),
this.options.getRole());
return doLogin("GCP-GCE", signedJwt, this.options.getPath(), this.options.getRole());
}
@Override
public AuthenticationSteps getAuthenticationSteps() {
return createAuthenticationSteps(options);
return createAuthenticationSteps(this.options);
}
protected String signJwt() {
@@ -146,9 +137,8 @@ public class GcpComputeAuthentication extends GcpJwtAuthenticationSupport
HttpHeaders headers = getMetadataHttpHeaders();
HttpEntity<Object> entity = new HttpEntity<>(headers);
ResponseEntity<String> response = googleMetadataRestOperations.exchange(
COMPUTE_METADATA_URL_TEMPLATE, HttpMethod.GET, entity, String.class,
urlParameters);
ResponseEntity<String> response = this.googleMetadataRestOperations.exchange(COMPUTE_METADATA_URL_TEMPLATE,
HttpMethod.GET, entity, String.class, urlParameters);
return response.getBody();
}
@@ -169,4 +159,5 @@ public class GcpComputeAuthentication extends GcpJwtAuthenticationSupport
private static String getAudience(String role) {
return String.format("https://localhost:8200/vault/%s", role);
}
}

View File

@@ -50,8 +50,7 @@ public class GcpComputeAuthenticationOptions {
*/
private final String role;
private GcpComputeAuthenticationOptions(String path, String serviceAccount,
String role) {
private GcpComputeAuthenticationOptions(String path, String serviceAccount, String role) {
this.path = path;
this.serviceAccount = serviceAccount;
@@ -69,21 +68,21 @@ public class GcpComputeAuthenticationOptions {
* @return the path of the gcp authentication backend mount.
*/
public String getPath() {
return path;
return this.path;
}
/**
* @return the GCE service account identifier.
*/
public String getServiceAccount() {
return serviceAccount;
return this.serviceAccount;
}
/**
* @return name of the role against which the login is being attempted.
*/
public String getRole() {
return role;
return this.role;
}
/**
@@ -103,7 +102,6 @@ public class GcpComputeAuthenticationOptions {
/**
* Configure the mount path, defaults to {@literal aws}.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link GcpComputeAuthenticationOptionsBuilder}.
*/
@@ -118,12 +116,10 @@ public class GcpComputeAuthenticationOptions {
/**
* Configure the service account identifier. Uses the {@code default} service
* account if left unconfigured.
*
* @param serviceAccount must not be empty or {@literal null}.
* @return {@code this} {@link GcpComputeAuthenticationOptionsBuilder}.
*/
public GcpComputeAuthenticationOptionsBuilder serviceAccount(
String serviceAccount) {
public GcpComputeAuthenticationOptionsBuilder serviceAccount(String serviceAccount) {
Assert.hasText(serviceAccount, "Service account must not be null");
@@ -133,7 +129,6 @@ public class GcpComputeAuthenticationOptions {
/**
* Configure the name of the role against which the login is being attempted.
*
* @param role must not be empty or {@literal null}.
* @return {@code this} {@link GcpComputeAuthenticationOptionsBuilder}.
*/
@@ -147,14 +142,15 @@ public class GcpComputeAuthenticationOptions {
/**
* Build a new {@link GcpComputeAuthenticationOptions} instance.
*
* @return a new {@link GcpComputeAuthenticationOptions}.
*/
public GcpComputeAuthenticationOptions build() {
Assert.notNull(role, "Role must not be null");
Assert.notNull(this.role, "Role must not be null");
return new GcpComputeAuthenticationOptions(path, serviceAccount, role);
return new GcpComputeAuthenticationOptions(this.path, this.serviceAccount, this.role);
}
}
}

View File

@@ -33,7 +33,6 @@ public interface GcpCredentialSupplier extends Supplier<GoogleCredential> {
/**
* Exception-safe helper to get {@link GoogleCredential} from {@link #getCredential}.
*
* @return the GoogleCredential for JWT signing.
*/
@Override
@@ -49,9 +48,9 @@ public interface GcpCredentialSupplier extends Supplier<GoogleCredential> {
/**
* Get a {@link GoogleCredential} for GCP IAM authentication via JWT signing.
*
* @return the {@link GoogleCredential}.
* @throws IOException if the credential lookup fails.
*/
GoogleCredential getCredential() throws IOException;
}

View File

@@ -63,8 +63,7 @@ import org.springframework.web.client.RestOperations;
* "https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signJwt">GCP:
* projects.serviceAccounts.signJwt</a>
*/
public class GcpIamAuthentication extends GcpJwtAuthenticationSupport
implements ClientAuthentication {
public class GcpIamAuthentication extends GcpJwtAuthenticationSupport implements ClientAuthentication {
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
@@ -78,12 +77,10 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport
* Create a new instance of {@link GcpIamAuthentication} given
* {@link GcpIamAuthenticationOptions} and {@link RestOperations}. This constructor
* initializes {@link GoogleApacheHttpTransport} for Google API usage.
*
* @param options must not be {@literal null}.
* @param restOperations HTTP client for for Vault login, must not be {@literal null}.
*/
public GcpIamAuthentication(GcpIamAuthenticationOptions options,
RestOperations restOperations) {
public GcpIamAuthentication(GcpIamAuthenticationOptions options, RestOperations restOperations) {
this(options, restOperations, new NetHttpTransport());
}
@@ -91,13 +88,12 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport
* Create a new instance of {@link GcpIamAuthentication} given
* {@link GcpIamAuthenticationOptions}, {@link RestOperations} and
* {@link HttpTransport}.
*
* @param options must not be {@literal null}.
* @param restOperations HTTP client for for Vault login, must not be {@literal null}.
* @param httpTransport HTTP client for Google API use, must not be {@literal null}.
*/
public GcpIamAuthentication(GcpIamAuthenticationOptions options,
RestOperations restOperations, HttpTransport httpTransport) {
public GcpIamAuthentication(GcpIamAuthenticationOptions options, RestOperations restOperations,
HttpTransport httpTransport) {
super(restOperations);
@@ -115,17 +111,16 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport
String signedJwt = signJwt();
return doLogin("GCP-IAM", signedJwt, this.options.getPath(),
this.options.getRole());
return doLogin("GCP-IAM", signedJwt, this.options.getPath(), this.options.getRole());
}
protected String signJwt() {
String projectId = getProjectId();
String serviceAccount = getServiceAccountId();
Map<String, Object> jwtPayload = getJwtPayload(options, serviceAccount);
Map<String, Object> jwtPayload = getJwtPayload(this.options, serviceAccount);
Iam iam = new Builder(httpTransport, JSON_FACTORY, credential)
Iam iam = new Builder(this.httpTransport, JSON_FACTORY, this.credential)
.setApplicationName("Spring Vault/" + getClass().getName()).build();
try {
@@ -134,9 +129,8 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport
SignJwtRequest request = new SignJwtRequest();
request.setPayload(payload);
SignJwt signJwt = iam.projects().serviceAccounts().signJwt(String
.format("projects/%s/serviceAccounts/%s", projectId, serviceAccount),
request);
SignJwt signJwt = iam.projects().serviceAccounts()
.signJwt(String.format("projects/%s/serviceAccounts/%s", projectId, serviceAccount), request);
SignJwtResponse response = signJwt.execute();
@@ -148,15 +142,14 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport
}
private String getServiceAccountId() {
return options.getServiceAccountIdAccessor().getServiceAccountId(credential);
return this.options.getServiceAccountIdAccessor().getServiceAccountId(this.credential);
}
private String getProjectId() {
return options.getProjectIdAccessor().getProjectId(credential);
return this.options.getProjectIdAccessor().getProjectId(this.credential);
}
private static Map<String, Object> getJwtPayload(GcpIamAuthenticationOptions options,
String serviceAccount) {
private static Map<String, Object> getJwtPayload(GcpIamAuthenticationOptions options, String serviceAccount) {
Instant validUntil = options.getClock().instant().plus(options.getJwtValidity());
@@ -168,4 +161,5 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport
return payload;
}
}

View File

@@ -75,9 +75,8 @@ public class GcpIamAuthenticationOptions {
*/
private final GcpProjectIdAccessor projectIdAccessor;
private GcpIamAuthenticationOptions(String path,
GcpCredentialSupplier credentialSupplier, String role, Duration jwtValidity,
Clock clock, GcpServiceAccountIdAccessor serviceAccountIdSupplier,
private GcpIamAuthenticationOptions(String path, GcpCredentialSupplier credentialSupplier, String role,
Duration jwtValidity, Clock clock, GcpServiceAccountIdAccessor serviceAccountIdSupplier,
GcpProjectIdAccessor projectIdAccessor) {
this.path = path;
@@ -100,35 +99,35 @@ public class GcpIamAuthenticationOptions {
* @return the path of the gcp authentication backend mount.
*/
public String getPath() {
return path;
return this.path;
}
/**
* @return the gcp {@link Credential} supplier.
*/
public GcpCredentialSupplier getCredentialSupplier() {
return credentialSupplier;
return this.credentialSupplier;
}
/**
* @return name of the role against which the login is being attempted.
*/
public String getRole() {
return role;
return this.role;
}
/**
* @return {@link Duration} of the JWT to generate.
*/
public Duration getJwtValidity() {
return jwtValidity;
return this.jwtValidity;
}
/**
* @return {@link Clock} used to calculate epoch seconds until the JWT expires.
*/
public Clock getClock() {
return clock;
return this.clock;
}
/**
@@ -136,7 +135,7 @@ public class GcpIamAuthenticationOptions {
* @since 2.1
*/
public GcpServiceAccountIdAccessor getServiceAccountIdAccessor() {
return serviceAccountIdAccessor;
return this.serviceAccountIdAccessor;
}
/**
@@ -144,7 +143,7 @@ public class GcpIamAuthenticationOptions {
* @since 2.1
*/
public GcpProjectIdAccessor getProjectIdAccessor() {
return projectIdAccessor;
return this.projectIdAccessor;
}
/**
@@ -173,7 +172,6 @@ public class GcpIamAuthenticationOptions {
/**
* Configure the mount path, defaults to {@literal aws}.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
*/
@@ -189,13 +187,11 @@ public class GcpIamAuthenticationOptions {
* Configure static Google credentials, required to create a signed JWT. Either
* use static credentials or provide a
* {@link #credentialSupplier(GcpCredentialSupplier) credentials provider}.
*
* @param credential must not be {@literal null}.
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
* @see #credentialSupplier(GcpCredentialSupplier)
*/
public GcpIamAuthenticationOptionsBuilder credential(
GoogleCredential credential) {
public GcpIamAuthenticationOptionsBuilder credential(GoogleCredential credential) {
Assert.notNull(credential, "Credential must not be null");
@@ -206,13 +202,11 @@ public class GcpIamAuthenticationOptions {
* Configure a {@link GcpCredentialSupplier}, required to create a signed JWT.
* Alternatively, configure static {@link #credential(GoogleCredential)
* credentials}.
*
* @param credentialSupplier must not be {@literal null}.
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
* @see #credential(GoogleCredential)
*/
public GcpIamAuthenticationOptionsBuilder credentialSupplier(
GcpCredentialSupplier credentialSupplier) {
public GcpIamAuthenticationOptionsBuilder credentialSupplier(GcpCredentialSupplier credentialSupplier) {
Assert.notNull(credentialSupplier, "GcpCredentialSupplier must not be null");
@@ -223,25 +217,21 @@ public class GcpIamAuthenticationOptions {
/**
* Configure an explicit service account id to use in GCP IAM calls. If none is
* configured, falls back to using {@link GoogleCredential#getServiceAccountId()}.
*
* @param serviceAccountId the service account id (email) to use
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
* @since 2.1
*/
public GcpIamAuthenticationOptionsBuilder serviceAccountId(
String serviceAccountId) {
public GcpIamAuthenticationOptionsBuilder serviceAccountId(String serviceAccountId) {
Assert.notNull(serviceAccountId, "Service account id may not be null");
return serviceAccountIdAccessor(
(GoogleCredential credential) -> serviceAccountId);
return serviceAccountIdAccessor((GoogleCredential credential) -> serviceAccountId);
}
/**
* Configure an {@link GcpServiceAccountIdAccessor} to obtain the service account
* id used in GCP IAM calls. If none is configured, falls back to using
* {@link GoogleCredential#getServiceAccountId()}.
*
* @param serviceAccountIdAccessor the service account id provider to use
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
* @see GcpServiceAccountIdAccessor
@@ -250,8 +240,7 @@ public class GcpIamAuthenticationOptions {
GcpIamAuthenticationOptionsBuilder serviceAccountIdAccessor(
GcpServiceAccountIdAccessor serviceAccountIdAccessor) {
Assert.notNull(serviceAccountIdAccessor,
"GcpServiceAccountIdAccessor must not be null");
Assert.notNull(serviceAccountIdAccessor, "GcpServiceAccountIdAccessor must not be null");
this.serviceAccountIdAccessor = serviceAccountIdAccessor;
return this;
@@ -261,7 +250,6 @@ public class GcpIamAuthenticationOptions {
* Configure an explicit GCP project id to use in GCP IAM API calls. If none is
* configured, falls back using
* {@link GoogleCredential#getServiceAccountProjectId()}.
*
* @param projectId the GCP project id to use in GCP IAM API calls
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
* @since 2.1
@@ -277,14 +265,12 @@ public class GcpIamAuthenticationOptions {
* Configure an {@link GcpProjectIdAccessor} to use in GCP IAM API calls. If none
* is configured, falls back using
* {@link GoogleCredential#getServiceAccountProjectId()}.
*
* @param projectIdAccessor the GCP project id supplier to use in GCP IAM API
* calls
* calls
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
* @since 2.1
*/
GcpIamAuthenticationOptionsBuilder projectIdAccessor(
GcpProjectIdAccessor projectIdAccessor) {
GcpIamAuthenticationOptionsBuilder projectIdAccessor(GcpProjectIdAccessor projectIdAccessor) {
Assert.notNull(projectIdAccessor, "GcpProjectIdAccessor must not be null");
@@ -294,7 +280,6 @@ public class GcpIamAuthenticationOptions {
/**
* Configure the name of the role against which the login is being attempted.
*
* @param role must not be empty or {@literal null}.
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
*/
@@ -309,13 +294,12 @@ public class GcpIamAuthenticationOptions {
/**
* Configure the {@link Duration} for the JWT expiration. This defaults to 15
* minutes and cannot be more than a hour.
*
* @param jwtValidity must not be {@literal null}.
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
*/
public GcpIamAuthenticationOptionsBuilder jwtValidity(Duration jwtValidity) {
Assert.hasText(role, "JWT validity duration must not be null");
Assert.hasText(this.role, "JWT validity duration must not be null");
this.jwtValidity = jwtValidity;
return this;
@@ -324,13 +308,12 @@ public class GcpIamAuthenticationOptions {
/**
* Configure the {@link Clock} used to calculate epoch seconds until the JWT
* expiration.
*
* @param clock must not be {@literal null}.
* @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}.
*/
public GcpIamAuthenticationOptionsBuilder clock(Clock clock) {
Assert.hasText(role, "Clock must not be null");
Assert.hasText(this.role, "Clock must not be null");
this.clock = clock;
return this;
@@ -338,16 +321,17 @@ public class GcpIamAuthenticationOptions {
/**
* Build a new {@link GcpIamAuthenticationOptions} instance.
*
* @return a new {@link GcpIamAuthenticationOptions}.
*/
public GcpIamAuthenticationOptions build() {
Assert.notNull(credentialSupplier, "GcpCredentialSupplier must not be null");
Assert.notNull(role, "Role must not be null");
Assert.notNull(this.credentialSupplier, "GcpCredentialSupplier must not be null");
Assert.notNull(this.role, "Role must not be null");
return new GcpIamAuthenticationOptions(path, credentialSupplier, role,
jwtValidity, clock, serviceAccountIdAccessor, projectIdAccessor);
return new GcpIamAuthenticationOptions(this.path, this.credentialSupplier, this.role, this.jwtValidity,
this.clock, this.serviceAccountIdAccessor, this.projectIdAccessor);
}
}
}

View File

@@ -35,8 +35,7 @@ import org.springframework.web.client.RestOperations;
*/
public abstract class GcpJwtAuthenticationSupport {
private static final Log logger = LogFactory
.getLog(GcpJwtAuthenticationSupport.class);
private static final Log logger = LogFactory.getLog(GcpJwtAuthenticationSupport.class);
private final RestOperations restOperations;
@@ -49,39 +48,33 @@ public abstract class GcpJwtAuthenticationSupport {
/**
* Perform the actual Vault login given {@code signedJwt}.
*
* @param authenticationName authentication name for logging.
* @param signedJwt the JSON web token.
* @param path GCP authentication mount path.
* @param role Vault role.
* @return the {@link VaultToken}.
*/
VaultToken doLogin(String authenticationName, String signedJwt, String path,
String role) {
VaultToken doLogin(String authenticationName, String signedJwt, String path, String role) {
Map<String, String> login = createRequestBody(role, signedJwt);
try {
VaultResponse response = this.restOperations.postForObject(
AuthenticationUtil.getLoginPath(path), login, VaultResponse.class);
VaultResponse response = this.restOperations.postForObject(AuthenticationUtil.getLoginPath(path), login,
VaultResponse.class);
Assert.state(response != null && response.getAuth() != null,
"Auth field must not be null");
Assert.state(response != null && response.getAuth() != null, "Auth field must not be null");
if (logger.isDebugEnabled()) {
if (response.getAuth().get("metadata") instanceof Map) {
Map<Object, Object> metadata = (Map<Object, Object>) response
.getAuth().get("metadata");
logger.debug(String.format(
"Login successful using %s authentication for user id %s",
Map<Object, Object> metadata = (Map<Object, Object>) response.getAuth().get("metadata");
logger.debug(String.format("Login successful using %s authentication for user id %s",
authenticationName, metadata.get("service_account_email")));
}
else {
logger.debug("Login successful using " + authenticationName
+ " authentication");
logger.debug("Login successful using " + authenticationName + " authentication");
}
}
@@ -101,4 +94,5 @@ public abstract class GcpJwtAuthenticationSupport {
return login;
}
}

View File

@@ -31,9 +31,9 @@ public interface GcpProjectIdAccessor {
/**
* Get a the GCP project id to used in Google Cloud IAM API calls.
*
* @param credential the credential object to obtain the project id from.
* @return the service account id to use.
*/
String getProjectId(GoogleCredential credential);
}

View File

@@ -30,9 +30,9 @@ public interface GcpServiceAccountIdAccessor {
/**
* Get a the service account id (email) to be placed in the signed JWT.
*
* @param credential credential object to obtain the service account id from.
* @return the service account id to use.
*/
String getServiceAccountId(GoogleCredential credential);
}

View File

@@ -37,4 +37,5 @@ public class IpAddressUserId implements AppIdUserIdMechanism {
throw new IllegalStateException(e);
}
}
}

View File

@@ -42,8 +42,7 @@ import org.springframework.web.client.RestOperations;
* @see <a href="https://www.vaultproject.io/docs/auth/kubernetes.html">Auth Backend:
* Kubernetes</a>
*/
public class KubernetesAuthentication
implements ClientAuthentication, AuthenticationStepsFactory {
public class KubernetesAuthentication implements ClientAuthentication, AuthenticationStepsFactory {
private static final Log logger = LogFactory.getLog(KubernetesAuthentication.class);
@@ -54,12 +53,10 @@ public class KubernetesAuthentication
/**
* Create a {@link KubernetesAuthentication} using
* {@link KubernetesAuthenticationOptions} and {@link RestOperations}.
*
* @param options must not be {@literal null}.
* @param restOperations must not be {@literal null}.
*/
public KubernetesAuthentication(KubernetesAuthenticationOptions options,
RestOperations restOperations) {
public KubernetesAuthentication(KubernetesAuthenticationOptions options, RestOperations restOperations) {
Assert.notNull(options, "KubernetesAuthenticationOptions must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
@@ -71,33 +68,28 @@ public class KubernetesAuthentication
/**
* Creates a {@link AuthenticationSteps} for kubernetes authentication given
* {@link KubernetesAuthenticationOptions}.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for kubernetes authentication.
*/
public static AuthenticationSteps createAuthenticationSteps(
KubernetesAuthenticationOptions options) {
public static AuthenticationSteps createAuthenticationSteps(KubernetesAuthenticationOptions options) {
Assert.notNull(options, "KubernetesAuthenticationOptions must not be null");
String token = options.getJwtSupplier().get();
return AuthenticationSteps
.fromSupplier(() -> getKubernetesLogin(options.getRole(), token))
return AuthenticationSteps.fromSupplier(() -> getKubernetesLogin(options.getRole(), token))
.login(AuthenticationUtil.getLoginPath(options.getPath()));
}
@Override
public VaultToken login() throws VaultException {
Map<String, String> login = getKubernetesLogin(options.getRole(),
options.getJwtSupplier().get());
Map<String, String> login = getKubernetesLogin(this.options.getRole(), this.options.getJwtSupplier().get());
try {
VaultResponse response = restOperations.postForObject(AuthenticationUtil.getLoginPath(options.getPath()),
login, VaultResponse.class);
VaultResponse response = this.restOperations
.postForObject(AuthenticationUtil.getLoginPath(this.options.getPath()), login, VaultResponse.class);
Assert.state(response != null && response.getAuth() != null,
"Auth field must not be null");
Assert.state(response != null && response.getAuth() != null, "Auth field must not be null");
logger.debug("Login successful using Kubernetes authentication");
@@ -125,4 +117,5 @@ public class KubernetesAuthentication
return login;
}
}

View File

@@ -57,8 +57,7 @@ public class KubernetesAuthenticationOptions {
*/
private final Supplier<String> jwtSupplier;
private KubernetesAuthenticationOptions(String path, String role,
Supplier<String> jwtSupplier) {
private KubernetesAuthenticationOptions(String path, String role, Supplier<String> jwtSupplier) {
this.path = path;
this.role = role;
@@ -76,21 +75,21 @@ public class KubernetesAuthenticationOptions {
* @return the path of the kubernetes authentication backend mount.
*/
public String getPath() {
return path;
return this.path;
}
/**
* @return name of the role against which the login is being attempted.
*/
public String getRole() {
return role;
return this.role;
}
/**
* @return JSON Web Token supplier.
*/
public Supplier<String> getJwtSupplier() {
return jwtSupplier;
return this.jwtSupplier;
}
/**
@@ -108,7 +107,6 @@ public class KubernetesAuthenticationOptions {
/**
* Configure the mount path.
*
* @param path must not be {@literal null} or empty.
* @return {@code this} {@link KubernetesAuthenticationOptionsBuilder}.
*/
@@ -122,9 +120,8 @@ public class KubernetesAuthenticationOptions {
/**
* Configure the role.
*
* @param role name of the role against which the login is being attempted, must
* not be {@literal null} or empty.
* not be {@literal null} or empty.
* @return {@code this} {@link KubernetesAuthenticationOptionsBuilder}.
*/
public KubernetesAuthenticationOptionsBuilder role(String role) {
@@ -137,13 +134,11 @@ public class KubernetesAuthenticationOptions {
/**
* Configure the {@link Supplier} to obtain a Kubernetes authentication token.
*
* @param jwtSupplier the supplier, must not be {@literal null}.
* @return {@code this} {@link KubernetesAuthenticationOptionsBuilder}.
* @see KubernetesJwtSupplier
*/
public KubernetesAuthenticationOptionsBuilder jwtSupplier(
Supplier<String> jwtSupplier) {
public KubernetesAuthenticationOptionsBuilder jwtSupplier(Supplier<String> jwtSupplier) {
Assert.notNull(jwtSupplier, "JwtSupplier must not be null");
@@ -153,16 +148,16 @@ public class KubernetesAuthenticationOptions {
/**
* Build a new {@link KubernetesAuthenticationOptions} instance.
*
* @return a new {@link KubernetesAuthenticationOptions}.
*/
public KubernetesAuthenticationOptions build() {
Assert.notNull(role, "Role must not be null");
Assert.notNull(this.role, "Role must not be null");
return new KubernetesAuthenticationOptions(path, role,
jwtSupplier == null ? new KubernetesServiceAccountTokenFile().cached()
: jwtSupplier);
return new KubernetesAuthenticationOptions(this.path, this.role,
this.jwtSupplier == null ? new KubernetesServiceAccountTokenFile().cached() : this.jwtSupplier);
}
}
}

View File

@@ -31,8 +31,7 @@ import org.springframework.core.io.Resource;
* @since 2.0
* @see KubernetesJwtSupplier
*/
public class KubernetesServiceAccountTokenFile extends ResourceCredentialSupplier
implements KubernetesJwtSupplier {
public class KubernetesServiceAccountTokenFile extends ResourceCredentialSupplier implements KubernetesJwtSupplier {
/**
* Default path to the service account token file.
@@ -43,9 +42,8 @@ public class KubernetesServiceAccountTokenFile extends ResourceCredentialSupplie
* Create a new {@link KubernetesServiceAccountTokenFile} pointing to the
* {@link #DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE}. Construction fails with an
* exception if the file does not exist.
*
* @throws IllegalArgumentException if the
* {@link #DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE} does not exist.
* {@link #DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE} does not exist.
*/
public KubernetesServiceAccountTokenFile() {
this(DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE);
@@ -54,7 +52,6 @@ public class KubernetesServiceAccountTokenFile extends ResourceCredentialSupplie
/**
* Create a new {@link KubernetesServiceAccountTokenFile}
* {@link KubernetesServiceAccountTokenFile} from a {@code path}.
*
* @param path path to the service account token file.
* @throws IllegalArgumentException if the{@code path} does not exist.
*/
@@ -65,7 +62,6 @@ public class KubernetesServiceAccountTokenFile extends ResourceCredentialSupplie
/**
* Create a new {@link KubernetesServiceAccountTokenFile}
* {@link KubernetesServiceAccountTokenFile} from a {@link File} handle.
*
* @param file path to the service account token file.
* @throws IllegalArgumentException if the{@code path} does not exist.
*/
@@ -76,11 +72,11 @@ public class KubernetesServiceAccountTokenFile extends ResourceCredentialSupplie
/**
* Create a new {@link KubernetesServiceAccountTokenFile}
* {@link KubernetesServiceAccountTokenFile} from a {@link Resource} handle.
*
* @param resource resource pointing to the service account token file.
* @throws IllegalArgumentException if the{@code path} does not exist.
*/
public KubernetesServiceAccountTokenFile(Resource resource) {
super(resource);
}
}

View File

@@ -102,14 +102,13 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
/**
* Create a {@link LifecycleAwareSessionManager} given {@link ClientAuthentication},
* {@link TaskScheduler} and {@link RestOperations}.
*
* @param clientAuthentication must not be {@literal null}.
* @param taskScheduler must not be {@literal null}.
* @param restOperations must not be {@literal null}.
* @since 1.0.1
*/
public LifecycleAwareSessionManager(ClientAuthentication clientAuthentication,
TaskScheduler taskScheduler, RestOperations restOperations) {
public LifecycleAwareSessionManager(ClientAuthentication clientAuthentication, TaskScheduler taskScheduler,
RestOperations restOperations) {
super(taskScheduler);
@@ -124,16 +123,14 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
/**
* Create a {@link LifecycleAwareSessionManager} given {@link ClientAuthentication},
* {@link TaskScheduler} and {@link RestOperations}.
*
* @param clientAuthentication must not be {@literal null}.
* @param taskScheduler must not be {@literal null}.
* @param restOperations must not be {@literal null}.
* @param refreshTrigger must not be {@literal null}.
* @since 1.0.1
*/
public LifecycleAwareSessionManager(ClientAuthentication clientAuthentication,
TaskScheduler taskScheduler, RestOperations restOperations,
RefreshTrigger refreshTrigger) {
public LifecycleAwareSessionManager(ClientAuthentication clientAuthentication, TaskScheduler taskScheduler,
RestOperations restOperations, RefreshTrigger refreshTrigger) {
super(taskScheduler, refreshTrigger);
@@ -151,7 +148,7 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
* session.
*/
protected Optional<TokenWrapper> getToken() {
return token;
return this.token;
}
protected void setToken(Optional<TokenWrapper> token) {
@@ -164,25 +161,23 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
Optional<TokenWrapper> token = getToken();
setToken(Optional.empty());
token.filter(TokenWrapper::isRevocable).map(TokenWrapper::getToken)
.ifPresent(this::revoke);
token.filter(TokenWrapper::isRevocable).map(TokenWrapper::getToken).ifPresent(this::revoke);
}
/**
* Revoke a {@link VaultToken}.
*
* @param token the token to revoke, must not be {@literal null}.
*/
protected void revoke(VaultToken token) {
try {
dispatch(new BeforeLoginTokenRevocationEvent(token));
restOperations.postForObject("auth/token/revoke-self",
new HttpEntity<>(VaultHttpHeaders.from(token)), Map.class);
this.restOperations.postForObject("auth/token/revoke-self", new HttpEntity<>(VaultHttpHeaders.from(token)),
Map.class);
dispatch(new AfterLoginTokenRevocationEvent(token));
}
catch (RuntimeException e) {
logger.warn("Cannot revoke VaultToken: %s", e);
this.logger.warn("Cannot revoke VaultToken: %s", e);
dispatch(new LoginTokenRevocationFailedEvent(token, e));
}
}
@@ -192,13 +187,12 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
* token was obtained before, it uses self-renewal to renew the current token.
* Client-side errors (like permission denied) indicate the token cannot be renewed
* because it's expired or simply not found.
*
* @return {@literal true} if the refresh was successful. {@literal false} if a new
* token was obtained or refresh failed.
*/
public boolean renewToken() {
logger.info("Renewing token");
this.logger.info("Renewing token");
Optional<TokenWrapper> token = getToken();
if (!token.isPresent()) {
@@ -212,22 +206,20 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
}
catch (RuntimeException e) {
VaultTokenRenewalException exception = new VaultTokenRenewalException(
format("Cannot renew token", e), e);
VaultTokenRenewalException exception = new VaultTokenRenewalException(format("Cannot renew token", e), e);
if (getLeaseStrategy().shouldDrop(exception)) {
setToken(Optional.empty());
}
if (logger.isDebugEnabled()) {
logger.debug(exception.getMessage(), exception);
if (this.logger.isDebugEnabled()) {
this.logger.debug(exception.getMessage(), exception);
}
else {
logger.warn(exception.getMessage());
this.logger.warn(exception.getMessage());
}
dispatch(
new LoginTokenRenewalFailedEvent(tokenWrapper.getToken(), exception));
dispatch(new LoginTokenRenewalFailedEvent(tokenWrapper.getToken(), exception));
return false;
}
}
@@ -235,24 +227,20 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
private boolean doRenew(TokenWrapper wrapper) {
dispatch(new BeforeLoginTokenRenewedEvent(wrapper.getToken()));
VaultResponse vaultResponse = restOperations.postForObject(
"auth/token/renew-self",
new HttpEntity<>(VaultHttpHeaders.from(wrapper.token)),
VaultResponse.class);
VaultResponse vaultResponse = this.restOperations.postForObject("auth/token/renew-self",
new HttpEntity<>(VaultHttpHeaders.from(wrapper.token)), VaultResponse.class);
LoginToken renewed = LoginTokenUtil.from(vaultResponse.getRequiredAuth());
if (isExpired(renewed)) {
if (logger.isDebugEnabled()) {
Duration validTtlThreshold = getRefreshTrigger()
.getValidTtlThreshold(renewed);
logger.info(String.format(
"Token TTL (%s) exceeded validity TTL threshold (%s). Dropping token.",
if (this.logger.isDebugEnabled()) {
Duration validTtlThreshold = getRefreshTrigger().getValidTtlThreshold(renewed);
this.logger.info(String.format("Token TTL (%s) exceeded validity TTL threshold (%s). Dropping token.",
renewed.getLeaseDuration(), validTtlThreshold));
}
else {
logger.info("Token TTL exceeded validity TTL threshold. Dropping token.");
this.logger.info("Token TTL exceeded validity TTL threshold. Dropping token.");
}
setToken(Optional.empty());
@@ -271,7 +259,7 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
if (!getToken().isPresent()) {
synchronized (lock) {
synchronized (this.lock) {
if (!getToken().isPresent()) {
doGetSessionToken();
@@ -288,25 +276,22 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
VaultToken token;
try {
token = clientAuthentication.login();
token = this.clientAuthentication.login();
}
catch (VaultException e) {
dispatch(new LoginFailedEvent(clientAuthentication, e));
dispatch(new LoginFailedEvent(this.clientAuthentication, e));
throw e;
}
TokenWrapper wrapper = new TokenWrapper(token, token instanceof LoginToken);
if (isTokenSelfLookupEnabled()
&& !ClassUtils.isAssignableValue(LoginToken.class, token)) {
if (isTokenSelfLookupEnabled() && !ClassUtils.isAssignableValue(LoginToken.class, token)) {
try {
token = LoginTokenAdapter.augmentWithSelfLookup(this.restOperations,
token);
token = LoginTokenAdapter.augmentWithSelfLookup(this.restOperations, token);
wrapper = new TokenWrapper(token, false);
}
catch (VaultTokenLookupException e) {
logger.warn(String.format("Cannot enhance VaultToken to a LoginToken: %s",
e.getMessage()));
this.logger.warn(String.format("Cannot enhance VaultToken to a LoginToken: %s", e.getMessage()));
dispatch(new AuthenticationErrorEvent(token, e));
}
}
@@ -320,7 +305,7 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
}
protected VaultToken login() {
return clientAuthentication.login();
return this.clientAuthentication.login();
}
/**
@@ -333,14 +318,13 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
.filter(it -> {
LoginToken loginToken = (LoginToken) it;
return !loginToken.getLeaseDuration().isZero()
&& loginToken.isRenewable();
return !loginToken.getLeaseDuration().isZero() && loginToken.isRenewable();
}).isPresent();
}
private void scheduleRenewal() {
logger.info("Scheduling Token renewal");
this.logger.info("Scheduling Token renewal");
Runnable task = () -> {
Optional<TokenWrapper> tokenWrapper = getToken();
@@ -359,21 +343,19 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
}
}
catch (Exception e) {
logger.error("Cannot renew VaultToken", e);
this.logger.error("Cannot renew VaultToken", e);
dispatch(new LoginTokenRenewalFailedEvent(token, e));
}
};
Optional<TokenWrapper> token = getToken();
token.ifPresent(tokenWrapper -> getTaskScheduler().schedule(task,
createTrigger(tokenWrapper)));
token.ifPresent(tokenWrapper -> getTaskScheduler().schedule(task, createTrigger(tokenWrapper)));
}
private OneShotTrigger createTrigger(TokenWrapper tokenWrapper) {
return new OneShotTrigger(getRefreshTrigger()
.nextExecutionTime((LoginToken) tokenWrapper.getToken()));
return new OneShotTrigger(getRefreshTrigger().nextExecutionTime((LoginToken) tokenWrapper.getToken()));
}
private static String format(String message, RuntimeException e) {
@@ -381,8 +363,7 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
if (e instanceof HttpStatusCodeException) {
HttpStatusCodeException hsce = (HttpStatusCodeException) e;
return String.format("%s: Status %s %s %s", message, hsce.getRawStatusCode(),
hsce.getStatusText(),
return String.format("%s: Status %s %s %s", message, hsce.getRawStatusCode(), hsce.getStatusText(),
VaultResponses.getError(hsce.getResponseBodyAsString()));
}
@@ -398,6 +379,7 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
protected static class TokenWrapper {
private final VaultToken token;
private final boolean revocable;
TokenWrapper(VaultToken token, boolean revocable) {
@@ -412,5 +394,7 @@ public class LifecycleAwareSessionManager extends LifecycleAwareSessionManagerSu
public boolean isRevocable() {
return this.revocable;
}
}
}

View File

@@ -41,16 +41,15 @@ import org.springframework.vault.support.VaultToken;
* @author Mark Paluch
* @since 2.0
*/
public abstract class LifecycleAwareSessionManagerSupport
extends AuthenticationEventPublisher {
public abstract class LifecycleAwareSessionManagerSupport extends AuthenticationEventPublisher {
/**
* Refresh 5 seconds before the token expires.
*/
public static final int REFRESH_PERIOD_BEFORE_EXPIRY = 5;
private static final RefreshTrigger DEFAULT_TRIGGER = new FixedTimeoutRefreshTrigger(
REFRESH_PERIOD_BEFORE_EXPIRY, TimeUnit.SECONDS);
private static final RefreshTrigger DEFAULT_TRIGGER = new FixedTimeoutRefreshTrigger(REFRESH_PERIOD_BEFORE_EXPIRY,
TimeUnit.SECONDS);
/**
* Logger available to subclasses.
@@ -81,7 +80,6 @@ public abstract class LifecycleAwareSessionManagerSupport
/**
* Create a {@link LifecycleAwareSessionManager} given {@link TaskScheduler}. Using
* {@link #DEFAULT_TRIGGER} to trigger refresh.
*
* @param taskScheduler must not be {@literal null}.
*/
public LifecycleAwareSessionManagerSupport(TaskScheduler taskScheduler) {
@@ -91,12 +89,10 @@ public abstract class LifecycleAwareSessionManagerSupport
/**
* Create a {@link LifecycleAwareSessionManager} given {@link TaskScheduler} and
* {@link RefreshTrigger}.
*
* @param taskScheduler must not be {@literal null}.
* @param refreshTrigger must not be {@literal null}.
*/
public LifecycleAwareSessionManagerSupport(TaskScheduler taskScheduler,
RefreshTrigger refreshTrigger) {
public LifecycleAwareSessionManagerSupport(TaskScheduler taskScheduler, RefreshTrigger refreshTrigger) {
Assert.notNull(taskScheduler, "TaskScheduler must not be null");
Assert.notNull(refreshTrigger, "RefreshTrigger must not be null");
@@ -114,21 +110,19 @@ public abstract class LifecycleAwareSessionManagerSupport
* Self-lookup for tokens without a permission to access
* {@code auth/token/lookup-self} will fail gracefully and continue without token
* renewal.
*
* @return {@literal true} to enable self-lookup, {@literal false} to disable
* self-lookup. Enabled by default.
*/
protected boolean isTokenSelfLookupEnabled() {
return tokenSelfLookupEnabled;
return this.tokenSelfLookupEnabled;
}
/**
* Enables/disables token self-lookup. Self-lookup augments {@link VaultToken}
* obtained from a {@link ClientAuthentication}. Self-lookup determines whether a
* token is renewable and its TTL.
*
* @param tokenSelfLookupEnabled {@literal true} to enable self-lookup,
* {@literal false} to disable self-lookup. Enabled by default.
* {@literal false} to disable self-lookup. Enabled by default.
*/
public void setTokenSelfLookupEnabled(boolean tokenSelfLookupEnabled) {
this.tokenSelfLookupEnabled = tokenSelfLookupEnabled;
@@ -136,7 +130,6 @@ public abstract class LifecycleAwareSessionManagerSupport
/**
* Set the {@link LeaseStrategy} for lease renewal error handling.
*
* @param leaseStrategy the {@link LeaseStrategy}, must not be {@literal null}.
* @since 2.2
*/
@@ -147,28 +140,27 @@ public abstract class LifecycleAwareSessionManagerSupport
}
LeaseStrategy getLeaseStrategy() {
return leaseStrategy;
return this.leaseStrategy;
}
/**
* @return the underlying {@link TaskScheduler}.
*/
protected TaskScheduler getTaskScheduler() {
return taskScheduler;
return this.taskScheduler;
}
/**
* @return the underlying {@link RefreshTrigger}.
*/
protected RefreshTrigger getRefreshTrigger() {
return refreshTrigger;
return this.refreshTrigger;
}
/**
* Check whether the Token falls below its
* {@link RefreshTrigger#getValidTtlThreshold(LoginToken) validity threshold}.
* Typically used to discard a token.
*
* @param loginToken must not be {@literal null}.
* @return {@literal true} if token validity falls below validity threshold,
* {@literal false} if still valid.
@@ -196,12 +188,13 @@ public abstract class LifecycleAwareSessionManagerSupport
@Nullable
public Date nextExecutionTime(TriggerContext triggerContext) {
if (fired.compareAndSet(false, true)) {
return nextExecutionTime;
if (this.fired.compareAndSet(false, true)) {
return this.nextExecutionTime;
}
return null;
}
}
/**
@@ -212,7 +205,6 @@ public abstract class LifecycleAwareSessionManagerSupport
/**
* Determine the next execution time according to the given trigger context.
*
* @param loginToken login token encapsulating renewability and lease duration.
* @return the next execution time as defined by the trigger, or {@code null} if
* the trigger won't fire anymore
@@ -222,12 +214,12 @@ public abstract class LifecycleAwareSessionManagerSupport
/**
* Returns the minimum TTL duration to consider a token valid after renewal.
* Tokens with a shorter TTL are revoked and considered expired.
*
* @param loginToken the login token after renewal.
* @return minimum TTL {@link Duration} to consider a token valid.
* @since 2.0
*/
Duration getValidTtlThreshold(LoginToken loginToken);
}
/**
@@ -242,19 +234,18 @@ public abstract class LifecycleAwareSessionManagerSupport
private static final Duration ONE_SECOND = Duration.ofSeconds(1);
private final Duration duration;
private final Duration validTtlThreshold;
/**
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
* {@code timeout} before the {@link LoginToken} expires
*
* @param timeout timeout value, non-negative long value.
* @param timeUnit must not be {@literal null}.
*/
public FixedTimeoutRefreshTrigger(long timeout, TimeUnit timeUnit) {
Assert.isTrue(timeout >= 0,
"Timeout duration must be greater or equal to zero");
Assert.isTrue(timeout >= 0, "Timeout duration must be greater or equal to zero");
Assert.notNull(timeUnit, "TimeUnit must not be null");
this.duration = Duration.ofMillis(timeUnit.toMillis(timeout));
@@ -265,7 +256,6 @@ public abstract class LifecycleAwareSessionManagerSupport
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
* {@code timeout} before the {@link LoginToken} expires. Valid TTL threshold is
* set to two seconds longer to compensate for timing issues during scheduling.
*
* @param timeout timeout value.
* @since 2.0
*/
@@ -276,17 +266,15 @@ public abstract class LifecycleAwareSessionManagerSupport
/**
* Create a new {@link FixedTimeoutRefreshTrigger} to calculate execution times of
* {@code timeout} before the {@link LoginToken} expires.
*
* @param timeout timeout value.
* @param validTtlThreshold minimum TTL duration to consider a Token as valid.
* Tokens with a shorter TTL are not used anymore. Should be greater than
* {@code timeout} to prevent token expiry.
* Tokens with a shorter TTL are not used anymore. Should be greater than
* {@code timeout} to prevent token expiry.
* @since 2.0
*/
public FixedTimeoutRefreshTrigger(Duration timeout, Duration validTtlThreshold) {
Assert.isTrue(timeout.toMillis() >= 0,
"Timeout duration must be greater or equal to zero");
Assert.isTrue(timeout.toMillis() >= 0, "Timeout duration must be greater or equal to zero");
Assert.notNull(validTtlThreshold, "Valid TTL threshold must not be null");
@@ -298,14 +286,16 @@ public abstract class LifecycleAwareSessionManagerSupport
public Date nextExecutionTime(LoginToken loginToken) {
long milliseconds = Math.max(ONE_SECOND.toMillis(),
loginToken.getLeaseDuration().toMillis() - duration.toMillis());
loginToken.getLeaseDuration().toMillis() - this.duration.toMillis());
return new Date(System.currentTimeMillis() + milliseconds);
}
@Override
public Duration getValidTtlThreshold(LoginToken loginToken) {
return validTtlThreshold;
return this.validTtlThreshold;
}
}
}

View File

@@ -44,7 +44,6 @@ public class LoginToken extends VaultToken {
/**
* Create a new {@link LoginToken}.
*
* @param token must not be {@literal null}.
* @return the created {@link VaultToken}
*/
@@ -57,7 +56,6 @@ public class LoginToken extends VaultToken {
/**
* Create a new {@link LoginToken}.
*
* @param token must not be {@literal null}.
* @return the created {@link VaultToken}
* @since 1.1
@@ -68,7 +66,6 @@ public class LoginToken extends VaultToken {
/**
* Create a new {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDurationSeconds the lease duration in seconds, must not be negative.
* @return the created {@link VaultToken}
@@ -85,7 +82,6 @@ public class LoginToken extends VaultToken {
/**
* Create a new {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDurationSeconds the lease duration in seconds, must not be negative.
* @return the created {@link VaultToken}
@@ -104,11 +100,9 @@ public class LoginToken extends VaultToken {
/**
* Create a new {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
*
* @param leaseDuration the lease duration, must not be negative and not be
* {@literal null}.
* {@literal null}.
* @return the created {@link VaultToken}
* @since 2.0
*/
@@ -124,7 +118,6 @@ public class LoginToken extends VaultToken {
/**
* Create a new renewable {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDurationSeconds the lease duration in seconds, must not be negative.
* @return the created {@link VaultToken}
@@ -142,7 +135,6 @@ public class LoginToken extends VaultToken {
/**
* Create a new renewable {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDurationSeconds the lease duration in seconds, must not be negative.
* @return the created {@link VaultToken}
@@ -162,7 +154,6 @@ public class LoginToken extends VaultToken {
/**
* Create a new renewable {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDuration the lease duration, must not be {@literal null} or negative.
* @return the created {@link VaultToken}
@@ -177,7 +168,6 @@ public class LoginToken extends VaultToken {
/**
* Create a new renewable {@link LoginToken} with a {@code leaseDurationSeconds}.
*
* @param token must not be {@literal null}.
* @param leaseDuration the lease duration, must not be {@literal null} or negative.
* @return the created {@link VaultToken}
@@ -197,23 +187,24 @@ public class LoginToken extends VaultToken {
* @return the lease duration in seconds. May be {@literal 0} if none.
*/
public Duration getLeaseDuration() {
return leaseDuration;
return this.leaseDuration;
}
/**
* @return {@literal true} if this token is renewable; {@literal false} otherwise.
*/
public boolean isRenewable() {
return renewable;
return this.renewable;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(getClass().getSimpleName());
sb.append(" [renewable=").append(renewable);
sb.append(", leaseDuration=").append(leaseDuration);
sb.append(" [renewable=").append(this.renewable);
sb.append(", leaseDuration=").append(this.leaseDuration);
sb.append(']');
return sb.toString();
}
}

View File

@@ -52,12 +52,10 @@ public class LoginTokenAdapter implements ClientAuthentication {
/**
* Create a new {@link LoginTokenAdapter} given {@link ClientAuthentication} to
* decorate and {@link RestOperations}.
*
* @param delegate must not be {@literal null}.
* @param restOperations must not be {@literal null}.
*/
public LoginTokenAdapter(ClientAuthentication delegate,
RestOperations restOperations) {
public LoginTokenAdapter(ClientAuthentication delegate, RestOperations restOperations) {
Assert.notNull(delegate, "ClientAuthentication delegate must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
@@ -68,15 +66,14 @@ public class LoginTokenAdapter implements ClientAuthentication {
@Override
public LoginToken login() throws VaultException {
return augmentWithSelfLookup(delegate.login());
return augmentWithSelfLookup(this.delegate.login());
}
private LoginToken augmentWithSelfLookup(VaultToken token) {
return augmentWithSelfLookup(this.restOperations, token);
}
static LoginToken augmentWithSelfLookup(RestOperations restOperations,
VaultToken token) {
static LoginToken augmentWithSelfLookup(RestOperations restOperations, VaultToken token) {
Map<String, Object> data = lookupSelf(restOperations, token);
@@ -90,23 +87,19 @@ public class LoginTokenAdapter implements ClientAuthentication {
return LoginToken.of(token.toCharArray(), getLeaseDuration(ttl));
}
private static Map<String, Object> lookupSelf(RestOperations restOperations,
VaultToken token) {
private static Map<String, Object> lookupSelf(RestOperations restOperations, VaultToken token) {
try {
ResponseEntity<VaultResponse> entity = restOperations.exchange(
"auth/token/lookup-self", HttpMethod.GET,
ResponseEntity<VaultResponse> entity = restOperations.exchange("auth/token/lookup-self", HttpMethod.GET,
new HttpEntity<>(VaultHttpHeaders.from(token)), VaultResponse.class);
Assert.state(entity.getBody() != null && entity.getBody().getData() != null,
"Token response is null");
Assert.state(entity.getBody() != null && entity.getBody().getData() != null, "Token response is null");
return entity.getBody().getData();
}
catch (HttpStatusCodeException e) {
throw new VaultTokenLookupException(
String.format("Token self-lookup failed: %s %s", e.getRawStatusCode(),
VaultResponses.getError(e.getResponseBodyAsString())));
throw new VaultTokenLookupException(String.format("Token self-lookup failed: %s %s", e.getRawStatusCode(),
VaultResponses.getError(e.getResponseBodyAsString())));
}
catch (RestClientException e) {
throw new VaultTokenLookupException("Token self-lookup failed", e);
@@ -116,4 +109,5 @@ public class LoginTokenAdapter implements ClientAuthentication {
static Duration getLeaseDuration(@Nullable Number ttl) {
return ttl == null ? Duration.ZERO : Duration.ofSeconds(ttl.longValue());
}
}

View File

@@ -28,13 +28,11 @@ import org.springframework.util.Assert;
final class LoginTokenUtil {
private LoginTokenUtil() {
throw new UnsupportedOperationException(
"This is a utility class and cannot be instantiated");
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
/**
* Construct a {@link LoginToken} from an auth response.
*
* @param auth {@link Map} holding a login response.
* @return the {@link LoginToken}
*/
@@ -49,7 +47,6 @@ final class LoginTokenUtil {
/**
* Construct a {@link LoginToken} from an auth response.
*
* @param auth {@link Map} holding a login response.
* @return the {@link LoginToken}
* @since 2.0
@@ -66,8 +63,7 @@ final class LoginTokenUtil {
}
if (renewable != null && renewable) {
return LoginToken.renewable(token,
Duration.ofSeconds(leaseDuration.longValue()));
return LoginToken.renewable(token, Duration.ofSeconds(leaseDuration.longValue()));
}
if (leaseDuration != null) {
@@ -76,4 +72,5 @@ final class LoginTokenUtil {
return LoginToken.of(token);
}
}

View File

@@ -57,13 +57,11 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
* Create a new {@link MacAddressUserId} using a {@code networkInterfaceIndex}. The
* index is applied to {@link NetworkInterface#getNetworkInterfaces()} to obtain the
* desired network interface.
*
* @param networkInterfaceIndex must be greater or equal to zero.
*/
public MacAddressUserId(int networkInterfaceIndex) {
Assert.isTrue(networkInterfaceIndex >= 0,
"NetworkInterfaceIndex must be greater or equal to 0");
Assert.isTrue(networkInterfaceIndex >= 0, "NetworkInterfaceIndex must be greater or equal to 0");
this.networkInterfaceHint = "" + networkInterfaceIndex;
}
@@ -72,7 +70,6 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
* Create a new {@link MacAddressUserId} using a {@code networkInterfaceName}. This
* name is compared with {@link NetworkInterface#getName()} and
* {@link NetworkInterface#getDisplayName()} to obtain the desired network interface.
*
* @param networkInterfaceName must not be {@literal null}.
*/
public MacAddressUserId(String networkInterfaceName) {
@@ -88,35 +85,29 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
try {
Optional<NetworkInterface> networkInterface = Optional.empty();
List<NetworkInterface> interfaces = Collections
.list(NetworkInterface.getNetworkInterfaces());
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
if (StringUtils.hasText(networkInterfaceHint)) {
if (StringUtils.hasText(this.networkInterfaceHint)) {
try {
networkInterface = getNetworkInterface(
Integer.parseInt(networkInterfaceHint), interfaces);
networkInterface = getNetworkInterface(Integer.parseInt(this.networkInterfaceHint), interfaces);
}
catch (NumberFormatException e) {
networkInterface = getNetworkInterface((networkInterfaceHint),
interfaces);
networkInterface = getNetworkInterface((this.networkInterfaceHint), interfaces);
}
}
if (!networkInterface.isPresent()) {
if (StringUtils.hasText(networkInterfaceHint)) {
log.warn(String.format(
"Did not find a NetworkInterface applying hint %s",
networkInterfaceHint));
if (StringUtils.hasText(this.networkInterfaceHint)) {
this.log.warn(String.format("Did not find a NetworkInterface applying hint %s",
this.networkInterfaceHint));
}
InetAddress localHost = InetAddress.getLocalHost();
networkInterface = Optional
.ofNullable(NetworkInterface.getByInetAddress(localHost));
networkInterface = Optional.ofNullable(NetworkInterface.getByInetAddress(localHost));
if (!networkInterface.filter(MacAddressUserId::hasNetworkAddress)
.isPresent()) {
if (!networkInterface.filter(MacAddressUserId::hasNetworkAddress).isPresent()) {
networkInterface = getNetworkInterfaceWithHardwareAddress(interfaces);
}
}
@@ -124,8 +115,7 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
return networkInterface.map(MacAddressUserId::getRequiredNetworkAddress) //
.map(Sha256::toHexString) //
.map(Sha256::toSha256) //
.orElseThrow(() -> new IllegalStateException(
"Cannot determine NetworkInterface"));
.orElseThrow(() -> new IllegalStateException("Cannot determine NetworkInterface"));
}
catch (IOException e) {
throw new IllegalStateException(e);
@@ -133,8 +123,7 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
}
private static Optional<NetworkInterface> getNetworkInterface(Number hint,
List<NetworkInterface> interfaces) {
private static Optional<NetworkInterface> getNetworkInterface(Number hint, List<NetworkInterface> interfaces) {
if (interfaces.size() > hint.intValue() && hint.intValue() >= 0) {
return Optional.of(interfaces.get(hint.intValue()));
@@ -143,8 +132,7 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
return Optional.empty();
}
private static Optional<NetworkInterface> getNetworkInterface(String hint,
List<NetworkInterface> interfaces) {
private static Optional<NetworkInterface> getNetworkInterface(String hint, List<NetworkInterface> interfaces) {
return interfaces.stream() //
.filter(anInterface -> matchesHint(hint, anInterface)) //
@@ -153,8 +141,7 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
private static boolean matchesHint(String hint, NetworkInterface networkInterface) {
return hint.equals(networkInterface.getDisplayName())
|| hint.equals(networkInterface.getName());
return hint.equals(networkInterface.getDisplayName()) || hint.equals(networkInterface.getName());
}
private static Optional<NetworkInterface> getNetworkInterfaceWithHardwareAddress(
@@ -172,19 +159,19 @@ public class MacAddressUserId implements AppIdUserIdMechanism {
return Optional.ofNullable(it.getHardwareAddress());
}
catch (SocketException e) {
throw new IllegalStateException(String
.format("Cannot determine hardware address for %s", it.getName()));
throw new IllegalStateException(String.format("Cannot determine hardware address for %s", it.getName()));
}
}
private static byte[] getRequiredNetworkAddress(NetworkInterface it) {
return getNetworkAddress(it) //
.orElseThrow(() -> new IllegalStateException(String.format(
"Network interface %s has no hardware address", it.getName())));
.orElseThrow(() -> new IllegalStateException(
String.format("Network interface %s has no hardware address", it.getName())));
}
private static boolean hasNetworkAddress(NetworkInterface it) {
return getNetworkAddress(it).isPresent();
}
}

View File

@@ -52,13 +52,11 @@ import org.springframework.web.client.RestOperations;
* @see RestOperations
* @see <a href="https://www.vaultproject.io/docs/auth/pcf.html">Auth Backend: PCF</a>
*/
public class PcfAuthentication
implements ClientAuthentication, AuthenticationStepsFactory {
public class PcfAuthentication implements ClientAuthentication, AuthenticationStepsFactory {
private static final Log logger = LogFactory.getLog(PcfAuthentication.class);
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
// SHA256 hash and a salt length of 222
private static final int SALT_LENGTH = 222;
@@ -70,12 +68,10 @@ public class PcfAuthentication
/**
* Create a {@link PcfAuthentication} using {@link PcfAuthenticationOptions} and
* {@link RestOperations}.
*
* @param options must not be {@literal null}.
* @param restOperations must not be {@literal null}.
*/
public PcfAuthentication(PcfAuthenticationOptions options,
RestOperations restOperations) {
public PcfAuthentication(PcfAuthenticationOptions options, RestOperations restOperations) {
Assert.notNull(options, "PcfAuthenticationOptions must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
@@ -87,36 +83,31 @@ public class PcfAuthentication
/**
* Creates a {@link AuthenticationSteps} for pcf authentication given
* {@link PcfAuthenticationOptions}.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for pcf authentication.
*/
public static AuthenticationSteps createAuthenticationSteps(
PcfAuthenticationOptions options) {
public static AuthenticationSteps createAuthenticationSteps(PcfAuthenticationOptions options) {
Assert.notNull(options, "PcfAuthenticationOptions must not be null");
String instanceCert = options.getInstanceCertSupplier().get();
String instanceKey = options.getInstanceKeySupplier().get();
return AuthenticationSteps
.fromSupplier(() -> getPcfLogin(options.getRole(), options.getClock(),
instanceCert, instanceKey)) //
.fromSupplier(() -> getPcfLogin(options.getRole(), options.getClock(), instanceCert, instanceKey)) //
.login(AuthenticationUtil.getLoginPath(options.getPath()));
}
@Override
public VaultToken login() throws VaultException {
Map<String, String> login = getPcfLogin(options.getRole(), options.getClock(),
options.getInstanceCertSupplier().get(),
options.getInstanceKeySupplier().get());
Map<String, String> login = getPcfLogin(this.options.getRole(), this.options.getClock(),
this.options.getInstanceCertSupplier().get(), this.options.getInstanceKeySupplier().get());
try {
VaultResponse response = restOperations.postForObject(AuthenticationUtil.getLoginPath(options.getPath()),
login, VaultResponse.class);
VaultResponse response = this.restOperations
.postForObject(AuthenticationUtil.getLoginPath(this.options.getPath()), login, VaultResponse.class);
Assert.state(response != null && response.getAuth() != null,
"Auth field must not be null");
Assert.state(response != null && response.getAuth() != null, "Auth field must not be null");
logger.debug("Login successful using PCF authentication");
@@ -132,8 +123,7 @@ public class PcfAuthentication
return createAuthenticationSteps(this.options);
}
private static Map<String, String> getPcfLogin(String role, Clock clock,
String instanceCert, String instanceKey) {
private static Map<String, String> getPcfLogin(String role, Clock clock, String instanceCert, String instanceKey) {
Assert.hasText(role, "Role must not be empty");
@@ -160,23 +150,20 @@ public class PcfAuthentication
}
}
private static String getMessage(String role, String signingTime,
String instanceCertPem) {
private static String getMessage(String role, String signingTime, String instanceCertPem) {
return signingTime + instanceCertPem + role;
}
private static String doSign(byte[] message, String instanceKeyPem)
throws CryptoException {
private static String doSign(byte[] message, String instanceKeyPem) throws CryptoException {
RSAPrivateKeySpec privateKey = PemObject.fromKey(instanceKeyPem).getRSAKeySpec();
PSSSigner signer = new PSSSigner(new RSAEngine(), new SHA256Digest(),
SALT_LENGTH);
PSSSigner signer = new PSSSigner(new RSAEngine(), new SHA256Digest(), SALT_LENGTH);
signer.init(true, new RSAKeyParameters(true, privateKey.getModulus(),
privateKey.getPrivateExponent()));
signer.init(true, new RSAKeyParameters(true, privateKey.getModulus(), privateKey.getPrivateExponent()));
signer.update(message, 0, message.length);
byte[] signature = signer.generateSignature();
return Base64Utils.encodeToUrlSafeString(signature);
}
}

View File

@@ -63,8 +63,8 @@ public class PcfAuthenticationOptions {
*/
private final Supplier<String> instanceKeySupplier;
private PcfAuthenticationOptions(String path, String role, Clock clock,
Supplier<String> instanceCertSupplier, Supplier<String> instanceKeySupplier) {
private PcfAuthenticationOptions(String path, String role, Clock clock, Supplier<String> instanceCertSupplier,
Supplier<String> instanceKeySupplier) {
this.path = path;
this.role = role;
this.clock = clock;
@@ -83,35 +83,35 @@ public class PcfAuthenticationOptions {
* @return the path of the pcf authentication backend mount.
*/
public String getPath() {
return path;
return this.path;
}
/**
* @return name of the role against which the login is being attempted.
*/
public String getRole() {
return role;
return this.role;
}
/**
* @return the {@link Clock}.
*/
public Clock getClock() {
return clock;
return this.clock;
}
/**
* @return the instance certificate {@link Supplier}.
*/
public Supplier<String> getInstanceCertSupplier() {
return instanceCertSupplier;
return this.instanceCertSupplier;
}
/**
* @return the instance key {@link Supplier}.
*/
public Supplier<String> getInstanceKeySupplier() {
return instanceKeySupplier;
return this.instanceKeySupplier;
}
/**
@@ -137,7 +137,6 @@ public class PcfAuthenticationOptions {
/**
* Configure the mount path.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link PcfAuthenticationOptionsBuilder}.
* @see #DEFAULT_PCF_AUTHENTICATION_PATH
@@ -152,9 +151,8 @@ public class PcfAuthenticationOptions {
/**
* Configure the role.
*
* @param role name of the role against which the login is being attempted, must
* not be {@literal null} or empty.
* not be {@literal null} or empty.
* @return {@code this} {@link PcfAuthenticationOptionsBuilder}.
*/
public PcfAuthenticationOptionsBuilder role(String role) {
@@ -167,7 +165,6 @@ public class PcfAuthenticationOptions {
/**
* Configure the {@link Clock}.
*
* @param clock must not be {@literal null}.
* @return {@code this} {@link PcfAuthenticationOptionsBuilder}.
*/
@@ -181,16 +178,13 @@ public class PcfAuthenticationOptions {
/**
* Configure the {@link Supplier} to obtain the instance certificate.
*
* @param instanceCertSupplier the supplier, must not be {@literal null}.
* @return {@code this} {@link PcfAuthenticationOptionsBuilder}.
* @see ResourceCredentialSupplier
*/
public PcfAuthenticationOptionsBuilder instanceCertificate(
Supplier<String> instanceCertSupplier) {
public PcfAuthenticationOptionsBuilder instanceCertificate(Supplier<String> instanceCertSupplier) {
Assert.notNull(instanceCertSupplier,
"Instance certificate supplier must not be null");
Assert.notNull(instanceCertSupplier, "Instance certificate supplier must not be null");
this.instanceCertSupplier = instanceCertSupplier;
return this;
@@ -198,16 +192,13 @@ public class PcfAuthenticationOptions {
/**
* Configure the {@link Supplier} to obtain the instance key.
*
* @param instanceKeySupplier the supplier, must not be {@literal null}.
* @return {@code this} {@link PcfAuthenticationOptionsBuilder}.
* @see ResourceCredentialSupplier
*/
public PcfAuthenticationOptionsBuilder instanceKey(
Supplier<String> instanceKeySupplier) {
public PcfAuthenticationOptionsBuilder instanceKey(Supplier<String> instanceKeySupplier) {
Assert.notNull(instanceKeySupplier,
"Instance certificate supplier must not be null");
Assert.notNull(instanceKeySupplier, "Instance certificate supplier must not be null");
this.instanceKeySupplier = instanceKeySupplier;
return this;
@@ -219,31 +210,28 @@ public class PcfAuthenticationOptions {
* Falls back to the instance certificate at {@code CF_INSTANCE_CERT} if
* {@link #instanceCertificate(Supplier)} is not configured respective
* {@code CF_INSTANCE_KEY} if {@link #instanceKey(Supplier)} is not configured.
*
* @return a new {@link PcfAuthenticationOptions}.
* @throws IllegalStateException if {@link #instanceCertificate(Supplier)} or
* {@link #instanceKey(Supplier)} are not set and the corresponding
* environment variable {@code CF_INSTANCE_CERT} respective
* {@code CF_INSTANCE_KEY} is not set.
* {@link #instanceKey(Supplier)} are not set and the corresponding environment
* variable {@code CF_INSTANCE_CERT} respective {@code CF_INSTANCE_KEY} is not
* set.
*/
public PcfAuthenticationOptions build() {
Assert.notNull(role, "Role must not be null");
Assert.notNull(this.role, "Role must not be null");
Supplier<String> instanceCertSupplier = this.instanceCertSupplier;
if (instanceCertSupplier == null) {
instanceCertSupplier = new ResourceCredentialSupplier(
resolveEnvVariable("CF_INSTANCE_CERT")).cached();
instanceCertSupplier = new ResourceCredentialSupplier(resolveEnvVariable("CF_INSTANCE_CERT")).cached();
}
Supplier<String> instanceKeySupplier = this.instanceKeySupplier;
if (instanceKeySupplier == null) {
instanceKeySupplier = new ResourceCredentialSupplier(
resolveEnvVariable("CF_INSTANCE_KEY")).cached();
instanceKeySupplier = new ResourceCredentialSupplier(resolveEnvVariable("CF_INSTANCE_KEY")).cached();
}
return new PcfAuthenticationOptions(path, role, clock, instanceCertSupplier,
return new PcfAuthenticationOptions(this.path, this.role, this.clock, instanceCertSupplier,
instanceKeySupplier);
}
@@ -252,11 +240,12 @@ public class PcfAuthenticationOptions {
String value = System.getenv(name);
if (StringUtils.isEmpty(value)) {
throw new IllegalStateException(
String.format("Environment variable %s not set", name));
throw new IllegalStateException(String.format("Environment variable %s not set", name));
}
return value;
}
}
}

View File

@@ -80,14 +80,13 @@ import org.springframework.web.reactive.function.client.WebClientResponseExcepti
* @see TaskScheduler
* @see AuthenticationEventPublisher
*/
public class ReactiveLifecycleAwareSessionManager
extends LifecycleAwareSessionManagerSupport
public class ReactiveLifecycleAwareSessionManager extends LifecycleAwareSessionManagerSupport
implements ReactiveSessionManager, DisposableBean {
private static final Mono<TokenWrapper> EMPTY = Mono.empty();
private static final Mono<TokenWrapper> TERMINATED = Mono
.error(new TerminatedException());
private static final Mono<TokenWrapper> TERMINATED = Mono.error(new TerminatedException());
/**
* Client authentication mechanism. Used to obtain a {@link VaultToken} or
* {@link LoginToken}.
@@ -103,19 +102,17 @@ public class ReactiveLifecycleAwareSessionManager
* The token state: Contains the currently valid token that identifies the Vault
* session.
*/
private volatile AtomicReference<Mono<TokenWrapper>> token = new AtomicReference<>(
EMPTY);
private volatile AtomicReference<Mono<TokenWrapper>> token = new AtomicReference<>(EMPTY);
/**
* Create a {@link ReactiveLifecycleAwareSessionManager} given
* {@link ClientAuthentication}, {@link TaskScheduler} and {@link WebClient}.
*
* @param clientAuthentication must not be {@literal null}.
* @param taskScheduler must not be {@literal null}.
* @param webClient must not be {@literal null}.
*/
public ReactiveLifecycleAwareSessionManager(VaultTokenSupplier clientAuthentication,
TaskScheduler taskScheduler, WebClient webClient) {
public ReactiveLifecycleAwareSessionManager(VaultTokenSupplier clientAuthentication, TaskScheduler taskScheduler,
WebClient webClient) {
super(taskScheduler);
@@ -130,15 +127,13 @@ public class ReactiveLifecycleAwareSessionManager
/**
* Create a {@link ReactiveLifecycleAwareSessionManager} given
* {@link VaultTokenSupplier}, {@link TaskScheduler} and {@link WebClient}.
*
* @param clientAuthentication must not be {@literal null}.
* @param taskScheduler must not be {@literal null}.
* @param webClient must not be {@literal null}.
* @param refreshTrigger must not be {@literal null}.
*/
public ReactiveLifecycleAwareSessionManager(VaultTokenSupplier clientAuthentication,
TaskScheduler taskScheduler, WebClient webClient,
RefreshTrigger refreshTrigger) {
public ReactiveLifecycleAwareSessionManager(VaultTokenSupplier clientAuthentication, TaskScheduler taskScheduler,
WebClient webClient, RefreshTrigger refreshTrigger) {
super(taskScheduler, refreshTrigger);
@@ -162,7 +157,6 @@ public class ReactiveLifecycleAwareSessionManager
/**
* Revoke a {@link VaultToken} now and block execution until revocation completes.
*
* @param tokenMono
*/
protected void revokeNow(Mono<TokenWrapper> tokenMono) {
@@ -171,32 +165,29 @@ public class ReactiveLifecycleAwareSessionManager
protected Mono<Void> doRevoke(Mono<TokenWrapper> tokenMono) {
return tokenMono.filter(TokenWrapper::isRevocable).map(TokenWrapper::getToken)
.flatMap(this::revoke);
return tokenMono.filter(TokenWrapper::isRevocable).map(TokenWrapper::getToken).flatMap(this::revoke);
}
/**
* Revoke a {@link VaultToken}.
*
* @param token the token to revoke, must not be {@literal null}.
*/
protected Mono<Void> revoke(VaultToken token) {
return webClient.post().uri("auth/token/revoke-self").headers(httpHeaders -> {
return this.webClient.post().uri("auth/token/revoke-self").headers(httpHeaders -> {
httpHeaders.addAll(VaultHttpHeaders.from(token));
}).retrieve().bodyToMono(String.class)
.doOnSubscribe(
ignore -> dispatch(new BeforeLoginTokenRevocationEvent(token)))
.doOnSubscribe(ignore -> dispatch(new BeforeLoginTokenRevocationEvent(token)))
.doOnNext(ignore -> dispatch(new AfterLoginTokenRevocationEvent(token)))
.onErrorResume(WebClientResponseException.class, e -> {
logger.warn(format("Could not revoke token", e));
this.logger.warn(format("Could not revoke token", e));
dispatch(new LoginTokenRevocationFailedEvent(token, e));
return Mono.empty();
}).onErrorResume(Exception.class, e -> {
logger.warn("Could not revoke token", e);
this.logger.warn("Could not revoke token", e);
dispatch(new LoginTokenRevocationFailedEvent(token, e));
return Mono.empty();
@@ -208,14 +199,13 @@ public class ReactiveLifecycleAwareSessionManager
* token was obtained before, it uses self-renewal to renew the current token.
* Client-side errors (like permission denied) indicate the token cannot be renewed
* because it's expired or simply not found.
*
* @return the {@link VaultToken} if the refresh was successful or a new token was
* obtained. {@link Mono#empty()} if a new the token expired or
* {@link Mono#error(Throwable)} if refresh failed.
*/
public Mono<VaultToken> renewToken() {
logger.info("Renewing token");
this.logger.info("Renewing token");
Mono<TokenWrapper> tokenWrapper = this.token.get();
@@ -234,38 +224,33 @@ public class ReactiveLifecycleAwareSessionManager
return doRenew(wrapper).onErrorResume(RuntimeException.class, e -> {
VaultTokenRenewalException exception = new VaultTokenRenewalException(
format("Cannot renew token", e), e);
VaultTokenRenewalException exception = new VaultTokenRenewalException(format("Cannot renew token", e), e);
if (getLeaseStrategy().shouldDrop(exception)) {
dropCurrentToken();
}
if (logger.isDebugEnabled()) {
logger.debug(exception.getMessage(), exception);
if (this.logger.isDebugEnabled()) {
this.logger.debug(exception.getMessage(), exception);
}
else {
logger.warn(exception.getMessage());
this.logger.warn(exception.getMessage());
}
dispatch(new LoginTokenRenewalFailedEvent(wrapper.getToken(), exception));
return EMPTY;
}
return EMPTY;
}
);
}
private Mono<TokenWrapper> doRenew(TokenWrapper tokenWrapper) {
Mono<VaultResponse> exchange = webClient.post().uri("auth/token/renew-self")
.headers(httpHeaders -> httpHeaders
.putAll(VaultHttpHeaders.from(tokenWrapper.token)))
.retrieve().bodyToMono(VaultResponse.class);
Mono<VaultResponse> exchange = this.webClient.post().uri("auth/token/renew-self")
.headers(httpHeaders -> httpHeaders.putAll(VaultHttpHeaders.from(tokenWrapper.token))).retrieve()
.bodyToMono(VaultResponse.class);
return exchange
.doOnSubscribe(ignore -> dispatch(
new BeforeLoginTokenRenewedEvent(tokenWrapper.getToken())))
return exchange.doOnSubscribe(ignore -> dispatch(new BeforeLoginTokenRenewedEvent(tokenWrapper.getToken())))
.handle((response, sink) -> {
LoginToken renewed = LoginTokenUtil.from(response.getRequiredAuth());
@@ -276,17 +261,15 @@ public class ReactiveLifecycleAwareSessionManager
return;
}
if (logger.isDebugEnabled()) {
if (this.logger.isDebugEnabled()) {
Duration validTtlThreshold = getRefreshTrigger()
.getValidTtlThreshold(renewed);
logger.info(String.format(
"Token TTL (%s) exceeded validity TTL threshold (%s). Dropping token.",
renewed.getLeaseDuration(), validTtlThreshold));
Duration validTtlThreshold = getRefreshTrigger().getValidTtlThreshold(renewed);
this.logger.info(
String.format("Token TTL (%s) exceeded validity TTL threshold (%s). Dropping token.",
renewed.getLeaseDuration(), validTtlThreshold));
}
else {
logger.info(
"Token TTL exceeded validity TTL threshold. Dropping token.");
this.logger.info("Token TTL exceeded validity TTL threshold. Dropping token.");
}
dropCurrentToken();
@@ -310,10 +293,9 @@ public class ReactiveLifecycleAwareSessionManager
if (tokenWrapper == EMPTY) {
Mono<TokenWrapper> obtainToken = clientAuthentication.getVaultToken()
.flatMap(this::doSelfLookup) //
Mono<TokenWrapper> obtainToken = this.clientAuthentication.getVaultToken().flatMap(this::doSelfLookup) //
.onErrorMap(it -> {
dispatch(new LoginFailedEvent(clientAuthentication, it));
dispatch(new LoginFailedEvent(this.clientAuthentication, it));
return it;
}).doOnNext(it -> {
@@ -334,16 +316,13 @@ public class ReactiveLifecycleAwareSessionManager
TokenWrapper wrapper = new TokenWrapper(token, token instanceof LoginToken);
if (isTokenSelfLookupEnabled()
&& !ClassUtils.isAssignableValue(LoginToken.class, token)) {
if (isTokenSelfLookupEnabled() && !ClassUtils.isAssignableValue(LoginToken.class, token)) {
Mono<VaultToken> loginTokenMono = augmentWithSelfLookup(this.webClient,
token);
Mono<VaultToken> loginTokenMono = augmentWithSelfLookup(this.webClient, token);
return loginTokenMono.onErrorResume(e -> {
logger.warn(String.format("Cannot enhance VaultToken to a LoginToken: %s",
e.getMessage()));
this.logger.warn(String.format("Cannot enhance VaultToken to a LoginToken: %s", e.getMessage()));
dispatch(new AuthenticationErrorEvent(token, e));
return Mono.just(token);
}).map(it -> new TokenWrapper(it, false));
@@ -362,35 +341,32 @@ public class ReactiveLifecycleAwareSessionManager
.filter(it -> {
LoginToken loginToken = (LoginToken) it;
return !loginToken.getLeaseDuration().isZero()
&& loginToken.isRenewable();
return !loginToken.getLeaseDuration().isZero() && loginToken.isRenewable();
}).isPresent();
}
private void scheduleRenewal(VaultToken token) {
logger.info("Scheduling Token renewal");
this.logger.info("Scheduling Token renewal");
Runnable task = () -> {
try {
Mono<TokenWrapper> tokenWrapper = ReactiveLifecycleAwareSessionManager.this.token
.get();
Mono<TokenWrapper> tokenWrapper = ReactiveLifecycleAwareSessionManager.this.token.get();
if (tokenWrapper == Mono.<TokenWrapper> empty()
|| tokenWrapper == TERMINATED) {
if (tokenWrapper == Mono.<TokenWrapper>empty() || tokenWrapper == TERMINATED) {
return;
}
if (isTokenRenewable(token)) {
renewToken().subscribe(this::scheduleRenewal, e -> {
logger.error("Cannot renew VaultToken", e);
this.logger.error("Cannot renew VaultToken", e);
dispatch(new LoginTokenRenewalFailedEvent(token, e));
});
}
}
catch (Exception e) {
logger.error("Cannot renew VaultToken", e);
this.logger.error("Cannot renew VaultToken", e);
dispatch(new LoginTokenRenewalFailedEvent(token, e));
}
};
@@ -400,12 +376,10 @@ public class ReactiveLifecycleAwareSessionManager
private OneShotTrigger createTrigger(VaultToken token) {
return new OneShotTrigger(
getRefreshTrigger().nextExecutionTime((LoginToken) token));
return new OneShotTrigger(getRefreshTrigger().nextExecutionTime((LoginToken) token));
}
private static Mono<VaultToken> augmentWithSelfLookup(WebClient webClient,
VaultToken token) {
private static Mono<VaultToken> augmentWithSelfLookup(WebClient webClient, VaultToken token) {
Mono<Map<String, Object>> data = lookupSelf(webClient, token);
@@ -415,27 +389,23 @@ public class ReactiveLifecycleAwareSessionManager
Number ttl = (Number) it.get("ttl");
if (renewable != null && renewable) {
return LoginToken.renewable(token.toCharArray(),
LoginTokenAdapter.getLeaseDuration(ttl));
return LoginToken.renewable(token.toCharArray(), LoginTokenAdapter.getLeaseDuration(ttl));
}
return LoginToken.of(token.toCharArray(),
LoginTokenAdapter.getLeaseDuration(ttl));
return LoginToken.of(token.toCharArray(), LoginTokenAdapter.getLeaseDuration(ttl));
});
}
private static Mono<Map<String, Object>> lookupSelf(WebClient webClient,
VaultToken token) {
private static Mono<Map<String, Object>> lookupSelf(WebClient webClient, VaultToken token) {
return webClient.get().uri("auth/token/lookup-self")
.headers(httpHeaders -> httpHeaders.putAll(VaultHttpHeaders.from(token)))
.retrieve().bodyToMono(VaultResponse.class).map(it -> {
.headers(httpHeaders -> httpHeaders.putAll(VaultHttpHeaders.from(token))).retrieve()
.bodyToMono(VaultResponse.class).map(it -> {
Assert.state(it.getData() != null, "Token response is null");
return it.getRequiredData();
}).onErrorMap(WebClientResponseException.class, e -> {
return new VaultTokenLookupException(format("Token self-lookup", e),
e);
return new VaultTokenLookupException(format("Token self-lookup", e), e);
});
}
@@ -444,8 +414,7 @@ public class ReactiveLifecycleAwareSessionManager
if (e instanceof WebClientResponseException) {
WebClientResponseException wce = (WebClientResponseException) e;
return String.format("%s: Status %s %s %s", message, wce.getRawStatusCode(),
wce.getStatusText(),
return String.format("%s: Status %s %s %s", message, wce.getRawStatusCode(), wce.getStatusText(),
VaultResponses.getError(wce.getResponseBodyAsString()));
}
@@ -461,6 +430,7 @@ public class ReactiveLifecycleAwareSessionManager
protected static class TokenWrapper {
private final VaultToken token;
private final boolean revocable;
public TokenWrapper(VaultToken token, boolean revocable) {
@@ -475,6 +445,7 @@ public class ReactiveLifecycleAwareSessionManager
public boolean isRevocable() {
return this.revocable;
}
}
/**
@@ -486,5 +457,7 @@ public class ReactiveLifecycleAwareSessionManager
super("Session manager terminated");
setStackTrace(new StackTraceElement[0]);
}
}
}

View File

@@ -37,10 +37,10 @@ public interface ReactiveSessionManager extends VaultTokenSupplier {
/**
* Obtain a session token.
*
* @return a session token.
*/
default Mono<VaultToken> getSessionToken() {
return getVaultToken();
}
}

View File

@@ -40,7 +40,6 @@ public class ResourceCredentialSupplier implements CredentialSupplier {
/**
* Create a new {@link ResourceCredentialSupplier} {@link ResourceCredentialSupplier}
* from a {@code path}.
*
* @param path path to the file holding the credential.
* @throws IllegalArgumentException if the{@code path} does not exist.
*/
@@ -51,7 +50,6 @@ public class ResourceCredentialSupplier implements CredentialSupplier {
/**
* Create a new {@link ResourceCredentialSupplier} {@link ResourceCredentialSupplier}
* from a {@link File} handle.
*
* @param file path to the file holding the credential.
* @throws IllegalArgumentException if the{@code path} does not exist.
*/
@@ -62,14 +60,12 @@ public class ResourceCredentialSupplier implements CredentialSupplier {
/**
* Create a new {@link ResourceCredentialSupplier} {@link ResourceCredentialSupplier}
* from a {@link Resource} handle.
*
* @param resource resource pointing to the resource holding the credential.
* @throws IllegalArgumentException if the {@link Resource} does not exist.
*/
public ResourceCredentialSupplier(Resource resource) {
Assert.isTrue(resource.exists(),
() -> String.format("Resource %s does not exist", resource));
Assert.isTrue(resource.exists(), () -> String.format("Resource %s does not exist", resource));
this.resource = resource;
}
@@ -81,15 +77,12 @@ public class ResourceCredentialSupplier implements CredentialSupplier {
return new String(readToken(this.resource), StandardCharsets.US_ASCII);
}
catch (IOException e) {
throw new VaultException(
String.format("Credential retrieval from %s failed", this.resource),
e);
throw new VaultException(String.format("Credential retrieval from %s failed", this.resource), e);
}
}
/**
* Read the token from {@link Resource}.
*
* @param resource the resource to read from, must not be {@literal null}.
* @return the new byte array that has been copied to (possibly empty).
* @throws IOException in case of I/O errors.
@@ -102,4 +95,5 @@ public class ResourceCredentialSupplier implements CredentialSupplier {
return StreamUtils.copyToByteArray(is);
}
}
}

View File

@@ -34,8 +34,8 @@ public interface SessionManager {
/**
* Obtain a session token.
*
* @return a session token.
*/
VaultToken getSessionToken();
}

View File

@@ -34,7 +34,6 @@ class Sha256 {
/**
* Generates a hex-encoded SHA256 checksum from the supplied {@code content}.
*
* @param content must not be {@literal null} and not empty.
* @return hex-encoded SHA256 checksum
*/
@@ -50,12 +49,10 @@ class Sha256 {
/**
* Get a MessageDigest instance for the given algorithm. Throws an
* IllegalArgumentException if <i>algorithm</i> is unknown
*
* @return MessageDigest instance
* @throws IllegalArgumentException if NoSuchAlgorithmException is thrown
*/
private static MessageDigest getMessageDigest(String algorithm)
throws IllegalArgumentException {
private static MessageDigest getMessageDigest(String algorithm) throws IllegalArgumentException {
try {
return MessageDigest.getInstance(algorithm);
}
@@ -74,4 +71,5 @@ class Sha256 {
return sb.toString();
}
}

View File

@@ -40,7 +40,6 @@ public class SimpleSessionManager implements SessionManager {
/**
* Create a new {@link SimpleSessionManager} using a {@link ClientAuthentication}.
*
* @param clientAuthentication must not be {@literal null}.
*/
public SimpleSessionManager(ClientAuthentication clientAuthentication) {
@@ -53,15 +52,15 @@ public class SimpleSessionManager implements SessionManager {
@Override
public VaultToken getSessionToken() {
if (!token.isPresent()) {
synchronized (lock) {
if (!token.isPresent()) {
token = Optional.of(clientAuthentication.login());
if (!this.token.isPresent()) {
synchronized (this.lock) {
if (!this.token.isPresent()) {
this.token = Optional.of(this.clientAuthentication.login());
}
}
}
return token
.orElseThrow(() -> new IllegalStateException("Cannot obtain VaultToken"));
return this.token.orElseThrow(() -> new IllegalStateException("Cannot obtain VaultToken"));
}
}

View File

@@ -30,7 +30,6 @@ public class StaticUserId implements AppIdUserIdMechanism {
/**
* Create a new {@link StaticUserId} for a given {@code userId}.
*
* @param userId must not be empty or {@literal null}.
*/
public StaticUserId(String userId) {
@@ -41,6 +40,7 @@ public class StaticUserId implements AppIdUserIdMechanism {
@Override
public String createUserId() {
return userId;
return this.userId;
}
}

View File

@@ -30,14 +30,12 @@ import static org.springframework.vault.authentication.AuthenticationSteps.HttpR
* @see VaultToken
* @see <a href="https://www.vaultproject.io/docs/auth/token.html">Auth Backend: Token</a>
*/
public class TokenAuthentication
implements ClientAuthentication, AuthenticationStepsFactory {
public class TokenAuthentication implements ClientAuthentication, AuthenticationStepsFactory {
private final VaultToken token;
/**
* Create a new {@link TokenAuthentication} with a static {@code token}.
*
* @param token the Vault token, must not be empty or {@literal null}.
*/
public TokenAuthentication(String token) {
@@ -49,7 +47,6 @@ public class TokenAuthentication
/**
* Create a new {@link TokenAuthentication} with a static {@code token}.
*
* @param token the Vault token, must not be {@literal null}.
*/
public TokenAuthentication(VaultToken token) {
@@ -62,27 +59,24 @@ public class TokenAuthentication
/**
* Creates a {@link AuthenticationSteps} for token authentication given
* {@link VaultToken}.
*
* @param token must not be {@literal null}.
* @param selfLookup {@literal true} to perform a self-lookup using the given
* {@link VaultToken}. Self-lookup will create a {@link LoginToken} and provide
* renewability and TTL.
* {@link VaultToken}. Self-lookup will create a {@link LoginToken} and provide
* renewability and TTL.
* @return {@link AuthenticationSteps} for token authentication.
* @since 2.0
*/
public static AuthenticationSteps createAuthenticationSteps(VaultToken token,
boolean selfLookup) {
public static AuthenticationSteps createAuthenticationSteps(VaultToken token, boolean selfLookup) {
Assert.notNull(token, "VaultToken must not be null");
if (selfLookup) {
HttpRequest<VaultResponse> httpRequest = get("auth/token/lookup-self")
.with(VaultHttpHeaders.from(token)).as(VaultResponse.class);
HttpRequest<VaultResponse> httpRequest = get("auth/token/lookup-self").with(VaultHttpHeaders.from(token))
.as(VaultResponse.class);
return AuthenticationSteps.fromHttpRequest(httpRequest)
.login(response -> LoginTokenUtil.from(token.toCharArray(),
response.getRequiredData()));
.login(response -> LoginTokenUtil.from(token.toCharArray(), response.getRequiredData()));
}
return AuthenticationSteps.just(token);
@@ -97,4 +91,5 @@ public class TokenAuthentication
public AuthenticationSteps getAuthenticationSteps() {
return createAuthenticationSteps(this.token, false);
}
}

View File

@@ -40,9 +40,7 @@ public enum UnwrappingEndpoints {
@Override
VaultResponse unwrap(VaultResponse vaultResponse) {
return VaultResponses.unwrap(
(String) vaultResponse.getRequiredData().get("response"),
VaultResponse.class);
return VaultResponses.unwrap((String) vaultResponse.getRequiredData().get("response"), VaultResponse.class);
}
@Override
@@ -75,14 +73,12 @@ public enum UnwrappingEndpoints {
/**
* Retrieve the path of the unwrapping endpoint.
*
* @return the unwrapping endpoint path.
*/
abstract String getPath();
/**
* Unwrap the response data from {@link VaultResponses}.
*
* @param response the raw response entity.
* @return unwrapped {@link VaultResponse}.
*/
@@ -90,8 +86,8 @@ public enum UnwrappingEndpoints {
/**
* Unwrapping request {@link HttpMethod method}.
*
* @return the unwrapping request {@link HttpMethod method}.
*/
abstract HttpMethod getUnwrapRequestMethod();
}

View File

@@ -29,7 +29,6 @@ public class VaultLoginException extends VaultException {
/**
* Create a {@code VaultLoginException} with the specified detail message.
*
* @param msg the detail message.
*/
public VaultLoginException(String msg) {
@@ -39,7 +38,6 @@ public class VaultLoginException extends VaultException {
/**
* Create a {@code VaultLoginException} with the specified detail message and nested
* exception.
*
* @param msg the detail message.
* @param cause the nested exception.
*/
@@ -50,7 +48,6 @@ public class VaultLoginException extends VaultException {
/**
* Create a {@link VaultLoginException} given {@code authMethod} and a
* {@link Throwable cause}.
*
* @param authMethod must not be {@literal null}.
* @param cause must not be {@literal null}.
* @return the {@link VaultLoginException}.
@@ -59,12 +56,12 @@ public class VaultLoginException extends VaultException {
if (cause instanceof RestClientResponseException) {
String response = ((RestClientResponseException) cause)
.getResponseBodyAsString();
return new VaultLoginException(String.format("Cannot login using %s: %s",
authMethod, VaultResponses.getError(response)), cause);
String response = ((RestClientResponseException) cause).getResponseBodyAsString();
return new VaultLoginException(
String.format("Cannot login using %s: %s", authMethod, VaultResponses.getError(response)), cause);
}
return new VaultLoginException(String.format("Cannot login using %s", cause));
}
}

View File

@@ -27,7 +27,6 @@ public abstract class VaultSessionManagerException extends VaultException {
/**
* Create a {@code VaultSessionManagerException} with the specified detail message.
*
* @param msg the detail message.
*/
public VaultSessionManagerException(String msg) {
@@ -37,11 +36,11 @@ public abstract class VaultSessionManagerException extends VaultException {
/**
* Create a {@code VaultSessionManagerException} with the specified detail message and
* nested exception.
*
* @param msg the detail message.
* @param cause the nested exception.
*/
public VaultSessionManagerException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -27,7 +27,6 @@ public class VaultTokenLookupException extends VaultException {
/**
* Create a {@code VaultTokenLookupException} with the specified detail message.
*
* @param msg the detail message.
*/
public VaultTokenLookupException(String msg) {
@@ -37,7 +36,6 @@ public class VaultTokenLookupException extends VaultException {
/**
* Create a {@code VaultTokenLookupException} with the specified detail message and
* nested exception.
*
* @param msg the detail message.
* @param cause the nested exception.
* @since 2.1
@@ -45,4 +43,5 @@ public class VaultTokenLookupException extends VaultException {
public VaultTokenLookupException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -25,7 +25,6 @@ public class VaultTokenRenewalException extends VaultSessionManagerException {
/**
* Create a {@code VaultTokenRenewalException} with the specified detail message.
*
* @param msg the detail message.
*/
public VaultTokenRenewalException(String msg) {
@@ -35,11 +34,11 @@ public class VaultTokenRenewalException extends VaultSessionManagerException {
/**
* Create a {@code VaultTokenRenewalException} with the specified detail message and
* nested exception.
*
* @param msg the detail message.
* @param cause the nested exception.
*/
public VaultTokenRenewalException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -33,8 +33,8 @@ public interface VaultTokenSupplier {
/**
* Return a {@link VaultToken}. This can declare a Vault login flow to obtain a
* {@link VaultToken token}.
*
* @return a {@link Mono} with the {@link VaultToken}.
*/
Mono<VaultToken> getVaultToken();
}

View File

@@ -31,11 +31,11 @@ public class AfterLoginEvent extends AuthenticationEvent {
/**
* Create a new {@link AfterLoginEvent} given {@link VaultToken}.
*
* @param source the {@link VaultToken} associated with this event, must not be
* {@literal null}.
* {@literal null}.
*/
public AfterLoginEvent(VaultToken source) {
super(source);
}
}

View File

@@ -31,11 +31,11 @@ public class AfterLoginTokenRenewedEvent extends AuthenticationEvent {
/**
* Create a new {@link AfterLoginTokenRenewedEvent} given {@link VaultToken}.
*
* @param source the {@link VaultToken} associated with this event, must not be
* {@literal null}.
* {@literal null}.
*/
public AfterLoginTokenRenewedEvent(VaultToken source) {
super(source);
}
}

View File

@@ -31,11 +31,11 @@ public class AfterLoginTokenRevocationEvent extends AuthenticationEvent {
/**
* Create a new {@link AfterLoginTokenRevocationEvent} given {@link VaultToken}.
*
* @param source the {@link VaultToken} associated with this event, must not be
* {@literal null}.
* {@literal null}.
*/
public AfterLoginTokenRevocationEvent(VaultToken source) {
super(source);
}
}

View File

@@ -37,7 +37,6 @@ public class AuthenticationErrorEvent extends ApplicationEvent {
/**
* Create a new {@link AuthenticationErrorEvent} given {@code source} and
* {@link Exception}.
*
* @param source must not be {@literal null}.
* @param exception must not be {@literal null}.
*/
@@ -47,6 +46,7 @@ public class AuthenticationErrorEvent extends ApplicationEvent {
}
public Throwable getException() {
return exception;
return this.exception;
}
}

View File

@@ -28,8 +28,8 @@ public interface AuthenticationErrorListener {
/**
* Callback for a {@link AuthenticationErrorEvent}.
*
* @param authenticationEvent the event object, must not be {@literal null}.
*/
void onAuthenticationError(AuthenticationErrorEvent authenticationEvent);
}

View File

@@ -31,9 +31,8 @@ public abstract class AuthenticationEvent extends ApplicationEvent {
/**
* Create a new {@link AuthenticationEvent} given {@link VaultToken}.
*
* @param source the {@link VaultToken} associated with this event, must not be
* {@literal null}.
* {@literal null}.
*/
protected AuthenticationEvent(VaultToken source) {
super(source);
@@ -43,4 +42,5 @@ public abstract class AuthenticationEvent extends ApplicationEvent {
public VaultToken getSource() {
return (VaultToken) super.getSource();
}
}

View File

@@ -27,8 +27,8 @@ public interface AuthenticationListener {
/**
* Callback for a {@link AuthenticationEvent}
*
* @param leaseEvent the event object, must not be {@literal null}.
*/
void onAuthenticationEvent(AuthenticationEvent leaseEvent);
}

View File

@@ -31,11 +31,11 @@ public class BeforeLoginTokenRenewedEvent extends AuthenticationEvent {
/**
* Create a new {@link BeforeLoginTokenRenewedEvent} given {@link VaultToken}.
*
* @param source the {@link VaultToken} associated with this event, must not be
* {@literal null}.
* {@literal null}.
*/
public BeforeLoginTokenRenewedEvent(VaultToken source) {
super(source);
}
}

View File

@@ -31,11 +31,11 @@ public class BeforeLoginTokenRevocationEvent extends AuthenticationEvent {
/**
* Create a new {@link BeforeLoginTokenRevocationEvent} given {@link VaultToken}.
*
* @param source the {@link VaultToken} associated with this event, must not be
* {@literal null}.
* {@literal null}.
*/
public BeforeLoginTokenRevocationEvent(VaultToken source) {
super(source);
}
}

View File

@@ -36,12 +36,12 @@ public class LoginFailedEvent extends AuthenticationErrorEvent {
/**
* Create a new {@link LoginFailedEvent} given {@link Exception}.
*
* @param source the {@link ClientAuthentication} or {@link VaultTokenSupplier}
* associated with this event, must not be {@literal null}.
* associated with this event, must not be {@literal null}.
* @param exception must not be {@literal null}.
*/
public LoginFailedEvent(Object source, Throwable exception) {
super(source, exception);
}
}

View File

@@ -31,11 +31,11 @@ public class LoginTokenExpiredEvent extends AuthenticationEvent {
/**
* Create a new {@link LoginTokenExpiredEvent} given {@link VaultToken}.
*
* @param source the {@link VaultToken} associated with this event, must not be
* {@literal null}.
* {@literal null}.
*/
public LoginTokenExpiredEvent(VaultToken source) {
super(source);
}
}

View File

@@ -32,9 +32,8 @@ public class LoginTokenRenewalFailedEvent extends AuthenticationErrorEvent {
/**
* Create a new {@link LoginTokenRenewalFailedEvent} given {@link VaultToken} and
* {@link Exception}.
*
* @param source the {@link VaultToken} associated with this event, must not be
* {@literal null}.
* {@literal null}.
* @param exception must not be {@literal null}.
*/
public LoginTokenRenewalFailedEvent(VaultToken source, Throwable exception) {
@@ -44,4 +43,5 @@ public class LoginTokenRenewalFailedEvent extends AuthenticationErrorEvent {
public VaultToken getSource() {
return (VaultToken) super.getSource();
}
}

View File

@@ -32,9 +32,8 @@ public class LoginTokenRevocationFailedEvent extends AuthenticationErrorEvent {
/**
* Create a new {@link LoginTokenRevocationFailedEvent} given {@link VaultToken} and
* {@link Exception}.
*
* @param source the {@link VaultToken} associated with this event, must not be
* {@literal null}.
* {@literal null}.
* @param exception must not be {@literal null}.
*/
public LoginTokenRevocationFailedEvent(VaultToken source, Throwable exception) {
@@ -44,4 +43,5 @@ public class LoginTokenRevocationFailedEvent extends AuthenticationErrorEvent {
public VaultToken getSource() {
return (VaultToken) super.getSource();
}
}

View File

@@ -51,15 +51,12 @@ import static org.springframework.vault.client.ClientHttpRequestFactoryFactory.h
*/
public class ClientHttpConnectorFactory {
private static final boolean REACTOR_NETTY_PRESENT = isPresent(
"reactor.netty.http.client.HttpClient");
private static final boolean REACTOR_NETTY_PRESENT = isPresent("reactor.netty.http.client.HttpClient");
private static final boolean JETTY_PRESENT = isPresent(
"org.eclipse.jetty.client.HttpClient");
private static final boolean JETTY_PRESENT = isPresent("org.eclipse.jetty.client.HttpClient");
/**
* Checks for presence of all {@code classNames} using this class' classloader.
*
* @param classNames
* @return {@literal true} if all classes are present; {@literal false} if at least
* one class cannot be found.
@@ -67,8 +64,7 @@ public class ClientHttpConnectorFactory {
private static boolean isPresent(String... classNames) {
for (String className : classNames) {
if (!ClassUtils.isPresent(className,
ClientHttpConnectorFactory.class.getClassLoader())) {
if (!ClassUtils.isPresent(className, ClientHttpConnectorFactory.class.getClassLoader())) {
return false;
}
}
@@ -79,13 +75,11 @@ public class ClientHttpConnectorFactory {
/**
* Create a {@link ClientHttpConnector} for the given {@link ClientOptions} and
* {@link SslConfiguration}.
*
* @param options must not be {@literal null}
* @param sslConfiguration must not be {@literal null}
* @return a new {@link ClientHttpConnector}.
*/
public static ClientHttpConnector create(ClientOptions options,
SslConfiguration sslConfiguration) {
public static ClientHttpConnector create(ClientOptions options, SslConfiguration sslConfiguration) {
Assert.notNull(options, "ClientOptions must not be null");
Assert.notNull(sslConfiguration, "SslConfiguration must not be null");
@@ -98,23 +92,20 @@ public class ClientHttpConnectorFactory {
return JettyClient.usingJetty(options, sslConfiguration);
}
throw new IllegalStateException(
"No supported Reactive Http Client library available (Reactor Netty, Jetty)");
throw new IllegalStateException("No supported Reactive Http Client library available (Reactor Netty, Jetty)");
}
private static void configureSsl(SslConfiguration sslConfiguration,
SslContextBuilder sslContextBuilder) {
private static void configureSsl(SslConfiguration sslConfiguration, SslContextBuilder sslContextBuilder) {
try {
if (sslConfiguration.getTrustStoreConfiguration().isPresent()) {
sslContextBuilder.trustManager(createTrustManagerFactory(
sslConfiguration.getTrustStoreConfiguration()));
sslContextBuilder
.trustManager(createTrustManagerFactory(sslConfiguration.getTrustStoreConfiguration()));
}
if (sslConfiguration.getKeyStoreConfiguration().isPresent()) {
sslContextBuilder.keyManager(createKeyManagerFactory(
sslConfiguration.getKeyStoreConfiguration(),
sslContextBuilder.keyManager(createKeyManagerFactory(sslConfiguration.getKeyStoreConfiguration(),
sslConfiguration.getKeyConfiguration()));
}
}
@@ -130,8 +121,7 @@ public class ClientHttpConnectorFactory {
*/
static class ReactorNetty {
static ClientHttpConnector usingReactorNetty(ClientOptions options,
SslConfiguration sslConfiguration) {
static ClientHttpConnector usingReactorNetty(ClientOptions options, SslConfiguration sslConfiguration) {
HttpClient client = HttpClient.create();
if (hasSslConfiguration(sslConfiguration)) {
@@ -144,21 +134,20 @@ public class ClientHttpConnectorFactory {
});
}
client = client.tcpConfiguration(
it -> it.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,
Math.toIntExact(options.getConnectionTimeout().toMillis())));
client = client.tcpConfiguration(it -> it.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,
Math.toIntExact(options.getConnectionTimeout().toMillis())));
return new ReactorClientHttpConnector(client);
}
}
static class JettyClient {
static ClientHttpConnector usingJetty(ClientOptions options,
SslConfiguration sslConfiguration) {
static ClientHttpConnector usingJetty(ClientOptions options, SslConfiguration sslConfiguration) {
try {
return new JettyClientHttpConnector(
configureClient(getHttpClient(sslConfiguration), options));
return new JettyClientHttpConnector(configureClient(getHttpClient(sslConfiguration), options));
}
catch (GeneralSecurityException | IOException e) {
throw new IllegalStateException(e);
@@ -169,15 +158,13 @@ public class ClientHttpConnectorFactory {
org.eclipse.jetty.client.HttpClient httpClient, ClientOptions options) {
httpClient.setConnectTimeout(options.getConnectionTimeout().toMillis());
httpClient.setAddressResolutionTimeout(
options.getConnectionTimeout().toMillis());
httpClient.setAddressResolutionTimeout(options.getConnectionTimeout().toMillis());
return httpClient;
}
private static org.eclipse.jetty.client.HttpClient getHttpClient(
SslConfiguration sslConfiguration) throws KeyStoreException, IOException,
NoSuchAlgorithmException, CertificateException {
private static org.eclipse.jetty.client.HttpClient getHttpClient(SslConfiguration sslConfiguration)
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
if (hasSslConfiguration(sslConfiguration)) {
@@ -195,16 +182,14 @@ public class ClientHttpConnectorFactory {
sslContextFactory.setTrustStore(keyStore);
}
SslConfiguration.KeyConfiguration keyConfiguration = sslConfiguration
.getKeyConfiguration();
SslConfiguration.KeyConfiguration keyConfiguration = sslConfiguration.getKeyConfiguration();
if (keyConfiguration.getKeyAlias() != null) {
sslContextFactory.setCertAlias(keyConfiguration.getKeyAlias());
}
if (keyConfiguration.getKeyPassword() != null) {
sslContextFactory.setKeyManagerPassword(
new String(keyConfiguration.getKeyPassword()));
sslContextFactory.setKeyManagerPassword(new String(keyConfiguration.getKeyPassword()));
}
return new org.eclipse.jetty.client.HttpClient(sslContextFactory);
@@ -212,5 +197,7 @@ public class ClientHttpConnectorFactory {
return new org.eclipse.jetty.client.HttpClient();
}
}
}

View File

@@ -80,21 +80,17 @@ import static org.springframework.vault.support.SslConfiguration.KeyConfiguratio
*/
public class ClientHttpRequestFactoryFactory {
private static final Log logger = LogFactory
.getLog(ClientHttpRequestFactoryFactory.class);
private static final Log logger = LogFactory.getLog(ClientHttpRequestFactoryFactory.class);
private static final boolean HTTP_COMPONENTS_PRESENT = isPresent(
"org.apache.http.client.HttpClient");
private static final boolean HTTP_COMPONENTS_PRESENT = isPresent("org.apache.http.client.HttpClient");
private static final boolean OKHTTP3_PRESENT = isPresent("okhttp3.OkHttpClient");
private static final boolean NETTY_PRESENT = isPresent(
"io.netty.channel.nio.NioEventLoopGroup", "io.netty.handler.ssl.SslContext",
"io.netty.handler.codec.http.HttpClientCodec");
private static final boolean NETTY_PRESENT = isPresent("io.netty.channel.nio.NioEventLoopGroup",
"io.netty.handler.ssl.SslContext", "io.netty.handler.codec.http.HttpClientCodec");
/**
* Checks for presence of all {@code classNames} using this class' classloader.
*
* @param classNames
* @return {@literal true} if all classes are present; {@literal false} if at least
* one class cannot be found.
@@ -102,8 +98,7 @@ public class ClientHttpRequestFactoryFactory {
private static boolean isPresent(String... classNames) {
for (String className : classNames) {
if (!ClassUtils.isPresent(className,
ClientHttpRequestFactoryFactory.class.getClassLoader())) {
if (!ClassUtils.isPresent(className, ClientHttpRequestFactoryFactory.class.getClassLoader())) {
return false;
}
}
@@ -114,14 +109,12 @@ public class ClientHttpRequestFactoryFactory {
/**
* Create a {@link ClientHttpRequestFactory} for the given {@link ClientOptions} and
* {@link SslConfiguration}.
*
* @param options must not be {@literal null}
* @param sslConfiguration must not be {@literal null}
* @return a new {@link ClientHttpRequestFactory}. Lifecycle beans must be initialized
* after obtaining.
*/
public static ClientHttpRequestFactory create(ClientOptions options,
SslConfiguration sslConfiguration) {
public static ClientHttpRequestFactory create(ClientOptions options, SslConfiguration sslConfiguration) {
Assert.notNull(options, "ClientOptions must not be null");
Assert.notNull(sslConfiguration, "SslConfiguration must not be null");
@@ -155,13 +148,13 @@ public class ClientHttpRequestFactoryFactory {
return new SimpleClientHttpRequestFactory();
}
static SSLContext getSSLContext(SslConfiguration sslConfiguration,
TrustManager[] trustManagers) throws GeneralSecurityException, IOException {
static SSLContext getSSLContext(SslConfiguration sslConfiguration, TrustManager[] trustManagers)
throws GeneralSecurityException, IOException {
KeyConfiguration keyConfiguration = sslConfiguration.getKeyConfiguration();
KeyManager[] keyManagers = sslConfiguration.getKeyStoreConfiguration().isPresent()
? createKeyManagerFactory(sslConfiguration.getKeyStoreConfiguration(),
keyConfiguration).getKeyManagers()
? createKeyManagerFactory(sslConfiguration.getKeyStoreConfiguration(), keyConfiguration)
.getKeyManagers()
: null;
SSLContext sslContext = SSLContext.getInstance("TLS");
@@ -174,26 +167,20 @@ public class ClientHttpRequestFactoryFactory {
throws GeneralSecurityException, IOException {
return sslConfiguration.getTrustStoreConfiguration().isPresent()
? createTrustManagerFactory(sslConfiguration.getTrustStoreConfiguration())
.getTrustManagers()
: null;
? createTrustManagerFactory(sslConfiguration.getTrustStoreConfiguration()).getTrustManagers() : null;
}
static KeyManagerFactory createKeyManagerFactory(
KeyStoreConfiguration keyStoreConfiguration,
KeyConfiguration keyConfiguration)
throws GeneralSecurityException, IOException {
static KeyManagerFactory createKeyManagerFactory(KeyStoreConfiguration keyStoreConfiguration,
KeyConfiguration keyConfiguration) throws GeneralSecurityException, IOException {
KeyStore keyStore = getKeyStore(keyStoreConfiguration);
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
char[] keyPasswordToUse = keyConfiguration.getKeyPassword();
if (keyPasswordToUse == null) {
keyPasswordToUse = keyStoreConfiguration.getStorePassword() == null
? new char[0]
keyPasswordToUse = keyStoreConfiguration.getStorePassword() == null ? new char[0]
: keyStoreConfiguration.getStorePassword();
}
@@ -207,20 +194,16 @@ public class ClientHttpRequestFactoryFactory {
}
static KeyStore getKeyStore(KeyStoreConfiguration keyStoreConfiguration)
throws KeyStoreException, IOException, NoSuchAlgorithmException,
CertificateException {
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
KeyStore keyStore = KeyStore
.getInstance(StringUtils.hasText(keyStoreConfiguration.getStoreType())
? keyStoreConfiguration.getStoreType()
: KeyStore.getDefaultType());
KeyStore keyStore = KeyStore.getInstance(StringUtils.hasText(keyStoreConfiguration.getStoreType())
? keyStoreConfiguration.getStoreType() : KeyStore.getDefaultType());
loadKeyStore(keyStoreConfiguration, keyStore);
return keyStore;
}
static TrustManagerFactory createTrustManagerFactory(
KeyStoreConfiguration keyStoreConfiguration)
static TrustManagerFactory createTrustManagerFactory(KeyStoreConfiguration keyStoreConfiguration)
throws GeneralSecurityException, IOException {
KeyStore trustStore = getKeyStore(keyStoreConfiguration);
@@ -232,8 +215,7 @@ public class ClientHttpRequestFactoryFactory {
return trustManagerFactory;
}
private static void loadKeyStore(KeyStoreConfiguration keyStoreConfiguration,
KeyStore keyStore)
private static void loadKeyStore(KeyStoreConfiguration keyStoreConfiguration, KeyStore keyStore)
throws IOException, NoSuchAlgorithmException, CertificateException {
InputStream inputStream = null;
@@ -260,31 +242,26 @@ public class ClientHttpRequestFactoryFactory {
*/
static class HttpComponents {
static ClientHttpRequestFactory usingHttpComponents(ClientOptions options,
SslConfiguration sslConfiguration)
static ClientHttpRequestFactory usingHttpComponents(ClientOptions options, SslConfiguration sslConfiguration)
throws GeneralSecurityException, IOException {
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setRoutePlanner(new SystemDefaultRoutePlanner(
DefaultSchemePortResolver.INSTANCE, ProxySelector.getDefault()));
httpClientBuilder.setRoutePlanner(
new SystemDefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE, ProxySelector.getDefault()));
if (hasSslConfiguration(sslConfiguration)) {
SSLContext sslContext = getSSLContext(sslConfiguration,
getTrustManagers(sslConfiguration));
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
sslContext);
SSLContext sslContext = getSSLContext(sslConfiguration, getTrustManagers(sslConfiguration));
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
httpClientBuilder.setSSLContext(sslContext);
}
RequestConfig requestConfig = RequestConfig.custom()
//
.setConnectTimeout(
Math.toIntExact(options.getConnectionTimeout().toMillis())) //
.setSocketTimeout(
Math.toIntExact(options.getReadTimeout().toMillis())) //
.setConnectTimeout(Math.toIntExact(options.getConnectionTimeout().toMillis())) //
.setSocketTimeout(Math.toIntExact(options.getReadTimeout().toMillis())) //
.setAuthenticationEnabled(true) //
.build();
@@ -295,6 +272,7 @@ public class ClientHttpRequestFactoryFactory {
return new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
}
}
/**
@@ -304,8 +282,7 @@ public class ClientHttpRequestFactoryFactory {
*/
static class OkHttp3 {
static ClientHttpRequestFactory usingOkHttp3(ClientOptions options,
SslConfiguration sslConfiguration)
static ClientHttpRequestFactory usingOkHttp3(ClientOptions options, SslConfiguration sslConfiguration)
throws GeneralSecurityException, IOException {
Builder builder = new Builder();
@@ -314,10 +291,9 @@ public class ClientHttpRequestFactoryFactory {
TrustManager[] trustManagers = getTrustManagers(sslConfiguration);
if (trustManagers.length != 1
|| !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException(
"Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
@@ -326,12 +302,12 @@ public class ClientHttpRequestFactoryFactory {
builder.sslSocketFactory(sslContext.getSocketFactory(), trustManager);
}
builder.connectTimeout(options.getConnectionTimeout().toMillis(),
TimeUnit.MILLISECONDS).readTimeout(
options.getReadTimeout().toMillis(), TimeUnit.MILLISECONDS);
builder.connectTimeout(options.getConnectionTimeout().toMillis(), TimeUnit.MILLISECONDS)
.readTimeout(options.getReadTimeout().toMillis(), TimeUnit.MILLISECONDS);
return new OkHttp3ClientHttpRequestFactory(builder.build());
}
}
/**
@@ -341,8 +317,7 @@ public class ClientHttpRequestFactoryFactory {
*/
static class Netty {
static ClientHttpRequestFactory usingNetty(ClientOptions options,
SslConfiguration sslConfiguration)
static ClientHttpRequestFactory usingNetty(ClientOptions options, SslConfiguration sslConfiguration)
throws GeneralSecurityException, IOException {
Netty4ClientHttpRequestFactory requestFactory = new Netty4ClientHttpRequestFactory();
@@ -353,44 +328,38 @@ public class ClientHttpRequestFactoryFactory {
.forClient();
if (sslConfiguration.getTrustStoreConfiguration().isPresent()) {
sslContextBuilder.trustManager(createTrustManagerFactory(
sslConfiguration.getTrustStoreConfiguration()));
sslContextBuilder
.trustManager(createTrustManagerFactory(sslConfiguration.getTrustStoreConfiguration()));
}
if (sslConfiguration.getKeyStoreConfiguration().isPresent()) {
sslContextBuilder.keyManager(createKeyManagerFactory(
sslConfiguration.getKeyStoreConfiguration(),
sslContextBuilder.keyManager(createKeyManagerFactory(sslConfiguration.getKeyStoreConfiguration(),
sslConfiguration.getKeyConfiguration()));
}
requestFactory.setSslContext(
sslContextBuilder.sslProvider(SslProvider.JDK).build());
requestFactory.setSslContext(sslContextBuilder.sslProvider(SslProvider.JDK).build());
}
requestFactory.setConnectTimeout(
Math.toIntExact(options.getConnectionTimeout().toMillis()));
requestFactory
.setReadTimeout(Math.toIntExact(options.getReadTimeout().toMillis()));
requestFactory.setConnectTimeout(Math.toIntExact(options.getConnectionTimeout().toMillis()));
requestFactory.setReadTimeout(Math.toIntExact(options.getReadTimeout().toMillis()));
return requestFactory;
}
}
static class KeySelectingKeyManagerFactory extends KeyManagerFactory {
KeySelectingKeyManagerFactory(KeyManagerFactory factory,
KeyConfiguration keyConfiguration) {
KeySelectingKeyManagerFactory(KeyManagerFactory factory, KeyConfiguration keyConfiguration) {
super(new KeyManagerFactorySpi() {
@Override
protected void engineInit(KeyStore keyStore, char[] chars)
throws KeyStoreException, NoSuchAlgorithmException,
UnrecoverableKeyException {
throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
factory.init(keyStore, chars);
}
@Override
protected void engineInit(
ManagerFactoryParameters managerFactoryParameters)
protected void engineInit(ManagerFactoryParameters managerFactoryParameters)
throws InvalidAlgorithmParameterException {
factory.init(managerFactoryParameters);
}
@@ -400,66 +369,64 @@ public class ClientHttpRequestFactoryFactory {
KeyManager[] keyManagers = factory.getKeyManagers();
if (keyManagers.length == 1
&& keyManagers[0] instanceof X509ExtendedKeyManager) {
if (keyManagers.length == 1 && keyManagers[0] instanceof X509ExtendedKeyManager) {
return new KeyManager[] { new KeySelectingX509KeyManager(
(X509ExtendedKeyManager) keyManagers[0],
keyConfiguration) };
(X509ExtendedKeyManager) keyManagers[0], keyConfiguration) };
}
return keyManagers;
}
}, factory.getProvider(), factory.getAlgorithm());
}
}
private static class KeySelectingX509KeyManager extends X509ExtendedKeyManager {
private final X509ExtendedKeyManager delegate;
private final KeyConfiguration keyConfiguration;
KeySelectingX509KeyManager(X509ExtendedKeyManager delegate,
KeyConfiguration keyConfiguration) {
KeySelectingX509KeyManager(X509ExtendedKeyManager delegate, KeyConfiguration keyConfiguration) {
this.delegate = delegate;
this.keyConfiguration = keyConfiguration;
}
@Override
public String[] getClientAliases(String keyType, Principal[] issuers) {
return delegate.getClientAliases(keyType, issuers);
return this.delegate.getClientAliases(keyType, issuers);
}
@Override
public String chooseClientAlias(String[] keyType, Principal[] issuers,
Socket socket) {
return keyConfiguration.getKeyAlias();
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
return this.keyConfiguration.getKeyAlias();
}
public String chooseEngineClientAlias(String[] keyType, Principal[] issuers,
SSLEngine engine) {
return keyConfiguration.getKeyAlias();
public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) {
return this.keyConfiguration.getKeyAlias();
}
@Override
public String[] getServerAliases(String keyType, Principal[] issuers) {
return delegate.getServerAliases(keyType, issuers);
return this.delegate.getServerAliases(keyType, issuers);
}
@Override
public String chooseServerAlias(String keyType, Principal[] issuers,
Socket socket) {
return delegate.chooseServerAlias(keyType, issuers, socket);
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
return this.delegate.chooseServerAlias(keyType, issuers, socket);
}
@Override
public X509Certificate[] getCertificateChain(String alias) {
return delegate.getCertificateChain(alias);
return this.delegate.getCertificateChain(alias);
}
@Override
public PrivateKey getPrivateKey(String alias) {
return delegate.getPrivateKey(alias);
return this.delegate.getPrivateKey(alias);
}
}
}

View File

@@ -46,13 +46,11 @@ public class ReactiveVaultClients {
* slash that are expanded to use {@link VaultEndpoint}.
* <p>
* Requires Jackson 2 for Object-to-JSON mapping.
*
* @param endpoint must not be {@literal null}.
* @param connector must not be {@literal null}.
* @return the configured {@link WebClient}.
*/
public static WebClient createWebClient(VaultEndpoint endpoint,
ClientHttpConnector connector) {
public static WebClient createWebClient(VaultEndpoint endpoint, ClientHttpConnector connector) {
return createWebClient(SimpleVaultEndpointProvider.of(endpoint), connector);
}
@@ -62,13 +60,11 @@ public class ReactiveVaultClients {
* slash that are expanded to use {@link VaultEndpoint}.
* <p>
* Requires Jackson 2 for Object-to-JSON mapping.
*
* @param endpointProvider must not be {@literal null}.
* @param connector must not be {@literal null}.
* @return the configured {@link WebClient}.
*/
public static WebClient createWebClient(VaultEndpointProvider endpointProvider,
ClientHttpConnector connector) {
public static WebClient createWebClient(VaultEndpointProvider endpointProvider, ClientHttpConnector connector) {
Assert.notNull(endpointProvider, "VaultEndpointProvider must not be null");
Assert.notNull(connector, "ClientHttpConnector must not be null");
@@ -82,42 +78,38 @@ public class ReactiveVaultClients {
* slash that are expanded to use {@link VaultEndpoint}.
* <p>
* Requires Jackson 2 for Object-to-JSON mapping.
*
* @param endpointProvider must not be {@literal null}.
* @param connector must not be {@literal null}.
* @return the prepared {@link WebClient.Builder}.
*/
static WebClient.Builder createWebClientBuilder(
VaultEndpointProvider endpointProvider, ClientHttpConnector connector) {
static WebClient.Builder createWebClientBuilder(VaultEndpointProvider endpointProvider,
ClientHttpConnector connector) {
Assert.notNull(endpointProvider, "VaultEndpointProvider must not be null");
Assert.notNull(connector, "ClientHttpConnector must not be null");
UriBuilderFactory uriBuilderFactory = VaultClients
.createUriBuilderFactory(endpointProvider);
UriBuilderFactory uriBuilderFactory = VaultClients.createUriBuilderFactory(endpointProvider);
ExchangeStrategies strategies = ExchangeStrategies.builder()
.codecs(configurer -> {
ExchangeStrategies strategies = ExchangeStrategies.builder().codecs(configurer -> {
CustomCodecs cc = configurer.customCodecs();
CustomCodecs cc = configurer.customCodecs();
cc.decoder(new ByteArrayDecoder());
cc.decoder(new Jackson2JsonDecoder());
cc.decoder(StringDecoder.allMimeTypes());
cc.decoder(new ByteArrayDecoder());
cc.decoder(new Jackson2JsonDecoder());
cc.decoder(StringDecoder.allMimeTypes());
cc.encoder(new ByteArrayEncoder());
cc.encoder(new Jackson2JsonEncoder());
cc.encoder(new ByteArrayEncoder());
cc.encoder(new Jackson2JsonEncoder());
}).build();
}).build();
return WebClient.builder().uriBuilderFactory(uriBuilderFactory)
.exchangeStrategies(strategies).clientConnector(connector);
return WebClient.builder().uriBuilderFactory(uriBuilderFactory).exchangeStrategies(strategies)
.clientConnector(connector);
}
/**
* Create a {@link ExchangeFilterFunction} that associates each request with a
* {@code X-Vault-Namespace} header if the header is not present.
*
* @param namespace the Vault namespace to use. Must not be {@literal null} or empty.
* @return the {@link ExchangeFilterFunction} to register with {@link WebClient}.
* @see VaultHttpHeaders#VAULT_NAMESPACE
@@ -140,4 +132,5 @@ public class ReactiveVaultClients {
});
});
}
}

View File

@@ -73,7 +73,6 @@ public class RestTemplateBuilder {
/**
* Create a new {@link RestTemplateBuilder}.
*
* @return a new {@link RestTemplateBuilder}.
*/
public static RestTemplateBuilder builder() {
@@ -82,7 +81,6 @@ public class RestTemplateBuilder {
/**
* Set the {@link VaultEndpoint} that should be used with the {@link RestTemplate}.
*
* @param endpoint the {@link VaultEndpoint} provider.
* @return {@code this} {@link RestTemplateBuilder}.
*/
@@ -93,7 +91,6 @@ public class RestTemplateBuilder {
/**
* Set the {@link VaultEndpointProvider} that should be used with the
* {@link RestTemplate}.
*
* @param provider the {@link VaultEndpoint} provider.
* @return {@code this} {@link RestTemplateBuilder}.
*/
@@ -109,7 +106,6 @@ public class RestTemplateBuilder {
/**
* Set the {@link ClientHttpRequestFactory} that should be used with the
* {@link RestTemplate}.
*
* @param requestFactory the request factory.
* @return {@code this} {@link RestTemplateBuilder}.
*/
@@ -123,15 +119,12 @@ public class RestTemplateBuilder {
/**
* Set the {@link Supplier} of {@link ClientHttpRequestFactory} that should be called
* each time we {@link #build()} a new {@link RestTemplate} instance.
*
* @param requestFactory the supplier for the request factory.
* @return {@code this} {@link RestTemplateBuilder}.
*/
public RestTemplateBuilder requestFactory(
Supplier<ClientHttpRequestFactory> requestFactory) {
public RestTemplateBuilder requestFactory(Supplier<ClientHttpRequestFactory> requestFactory) {
Assert.notNull(requestFactory,
"Supplier of ClientHttpRequestFactory must not be null");
Assert.notNull(requestFactory, "Supplier of ClientHttpRequestFactory must not be null");
this.requestFactory = requestFactory;
return this;
@@ -140,7 +133,6 @@ public class RestTemplateBuilder {
/**
* Set the {@link ResponseErrorHandler} that should be used with the
* {@link RestTemplate}.
*
* @param errorHandler the error handler to use.
* @return {@code this} {@link RestTemplateBuilder}.
*/
@@ -155,7 +147,6 @@ public class RestTemplateBuilder {
/**
* Add a default header that will be set if not already present on the outgoing
* {@link HttpRequest}.
*
* @param name the name of the header.
* @param value the header value.
* @return {@code this} {@link RestTemplateBuilder}.
@@ -173,7 +164,6 @@ public class RestTemplateBuilder {
* Add the {@link RestTemplateCustomizer RestTemplateCustomizers} that should be
* applied to the {@link RestTemplate}. Customizers are applied in the order that they
* were added.
*
* @param customizer the template customizers to add.
* @return {@code this} {@link RestTemplateBuilder}.
*/
@@ -188,13 +178,11 @@ public class RestTemplateBuilder {
* Add the {@link RestTemplateRequestCustomizer RestTemplateRequestCustomizers} that
* should be applied to the {@link ClientHttpRequest}. Customizers are applied in the
* order that they were added.
*
* @param requestCustomizers the request customizers to add.
* @return {@code this} {@link RestTemplateBuilder}.
*/
@SuppressWarnings("unchecked")
public RestTemplateBuilder requestCustomizers(
RestTemplateRequestCustomizer<?>... requestCustomizers) {
public RestTemplateBuilder requestCustomizers(RestTemplateRequestCustomizer<?>... requestCustomizers) {
Assert.notNull(requestCustomizers, "RequestCustomizers must not be null");
@@ -207,66 +195,58 @@ public class RestTemplateBuilder {
*
* Applies also {@link ResponseErrorHandler} and {@link RestTemplateCustomizer} if
* configured.
*
* @return a new {@link RestTemplate}.
*/
public RestTemplate build() {
Assert.state(this.endpointProvider != null,
"VaultEndpointProvider must not be null");
Assert.state(this.endpointProvider != null, "VaultEndpointProvider must not be null");
RestTemplate restTemplate = createTemplate();
if (errorHandler != null) {
restTemplate.setErrorHandler(errorHandler);
if (this.errorHandler != null) {
restTemplate.setErrorHandler(this.errorHandler);
}
customizers.forEach(customizer -> customizer.customize(restTemplate));
this.customizers.forEach(customizer -> customizer.customize(restTemplate));
return restTemplate;
}
/**
* Create the {@link RestTemplate} to use.
*
* @return the {@link RestTemplate} to use.
*/
protected RestTemplate createTemplate() {
ClientHttpRequestFactory requestFactory = this.requestFactory.get();
LinkedHashMap<String, String> defaultHeaders = new LinkedHashMap<>(
this.defaultHeaders);
LinkedHashMap<String, String> defaultHeaders = new LinkedHashMap<>(this.defaultHeaders);
LinkedHashSet<RestTemplateRequestCustomizer<ClientHttpRequest>> requestCustomizers = new LinkedHashSet<>(
this.requestCustomizers);
RestTemplate restTemplate = VaultClients.createRestTemplate(this.endpointProvider,
new RestTemplateBuilderClientHttpRequestFactoryWrapper(requestFactory,
requestCustomizers));
new RestTemplateBuilderClientHttpRequestFactoryWrapper(requestFactory, requestCustomizers));
restTemplate.getInterceptors()
.add((httpRequest, bytes, clientHttpRequestExecution) -> {
restTemplate.getInterceptors().add((httpRequest, bytes, clientHttpRequestExecution) -> {
HttpHeaders headers = httpRequest.getHeaders();
defaultHeaders.forEach((key, value) -> {
if (!headers.containsKey(key)) {
headers.add(key, value);
}
});
HttpHeaders headers = httpRequest.getHeaders();
defaultHeaders.forEach((key, value) -> {
if (!headers.containsKey(key)) {
headers.add(key, value);
}
});
return clientHttpRequestExecution.execute(httpRequest, bytes);
});
return clientHttpRequestExecution.execute(httpRequest, bytes);
});
return restTemplate;
}
static class RestTemplateBuilderClientHttpRequestFactoryWrapper
extends AbstractClientHttpRequestFactoryWrapper {
static class RestTemplateBuilderClientHttpRequestFactoryWrapper extends AbstractClientHttpRequestFactoryWrapper {
private final Set<RestTemplateRequestCustomizer<ClientHttpRequest>> requestCustomizers;
RestTemplateBuilderClientHttpRequestFactoryWrapper(
ClientHttpRequestFactory requestFactory,
RestTemplateBuilderClientHttpRequestFactoryWrapper(ClientHttpRequestFactory requestFactory,
Set<RestTemplateRequestCustomizer<ClientHttpRequest>> requestCustomizers) {
super(requestFactory);
@@ -283,5 +263,7 @@ public class RestTemplateBuilder {
return request;
}
}
}

View File

@@ -29,8 +29,8 @@ public interface RestTemplateCustomizer {
/**
* Callback to customize a {@link RestTemplate} instance.
*
* @param restTemplate the template to customize.
*/
void customize(RestTemplate restTemplate);
}

View File

@@ -31,8 +31,8 @@ public interface RestTemplateRequestCustomizer<T extends ClientHttpRequest> {
/**
* Customize the specified {@link ClientHttpRequest}.
*
* @param request the request to customize.
*/
void customize(T request);
}

View File

@@ -33,7 +33,6 @@ public class SimpleVaultEndpointProvider implements VaultEndpointProvider {
/**
* Creates a new {@link VaultEndpointProvider} given {@link VaultEndpoint}.
*
* @param endpoint must not be {@literal null}.
*/
public static VaultEndpointProvider of(VaultEndpoint endpoint) {
@@ -45,6 +44,7 @@ public class SimpleVaultEndpointProvider implements VaultEndpointProvider {
@Override
public VaultEndpoint getVaultEndpoint() {
return endpoint;
return this.endpoint;
}
}

View File

@@ -58,17 +58,14 @@ public class VaultClients {
* Otherwise, Vault will deny body processing.
* <p>
* Requires Jackson 2 for Object-to-JSON mapping.
*
* @param endpoint must not be {@literal null}.
* @param requestFactory must not be {@literal null}.
* @return the {@link RestTemplate}.
* @see org.springframework.http.client.Netty4ClientHttpRequestFactory
* @see MappingJackson2HttpMessageConverter
*/
public static RestTemplate createRestTemplate(VaultEndpoint endpoint,
ClientHttpRequestFactory requestFactory) {
return createRestTemplate(SimpleVaultEndpointProvider.of(endpoint),
requestFactory);
public static RestTemplate createRestTemplate(VaultEndpoint endpoint, ClientHttpRequestFactory requestFactory) {
return createRestTemplate(SimpleVaultEndpointProvider.of(endpoint), requestFactory);
}
/**
@@ -82,7 +79,6 @@ public class VaultClients {
* Otherwise, Vault will deny body processing.
* <p>
* Requires Jackson 2 for Object-to-JSON mapping.
*
* @param endpointProvider must not be {@literal null}.
* @param requestFactory must not be {@literal null}.
* @return the {@link RestTemplate}.
@@ -110,7 +106,6 @@ public class VaultClients {
* Otherwise, Vault will deny body processing.
* <p>
* Requires Jackson 2 for Object-to-JSON mapping.
*
* @return the {@link RestTemplate}.
* @see org.springframework.http.client.Netty4ClientHttpRequestFactory
* @see MappingJackson2HttpMessageConverter
@@ -124,8 +119,7 @@ public class VaultClients {
RestTemplate restTemplate = new RestTemplate(messageConverters);
restTemplate.getInterceptors()
.add((request, body, execution) -> execution.execute(request, body));
restTemplate.getInterceptors().add((request, body, execution) -> execution.execute(request, body));
return restTemplate;
}
@@ -133,15 +127,13 @@ public class VaultClients {
/**
* Create a {@link ClientHttpRequestInterceptor} that associates each request with a
* {@code X-Vault-Namespace} header if the header is not present.
*
* @param namespace the Vault namespace to use. Must not be {@literal null} or empty.
* @return the {@link ClientHttpRequestInterceptor} to register with
* {@link RestTemplate}.
* @see VaultHttpHeaders#VAULT_NAMESPACE
* @since 2.2
*/
public static ClientHttpRequestInterceptor createNamespaceInterceptor(
String namespace) {
public static ClientHttpRequestInterceptor createNamespaceInterceptor(String namespace) {
Assert.hasText(namespace, "Vault Namespace must not be empty!");
@@ -157,8 +149,7 @@ public class VaultClients {
};
}
public static UriBuilderFactory createUriBuilderFactory(
VaultEndpointProvider endpointProvider) {
public static UriBuilderFactory createUriBuilderFactory(VaultEndpointProvider endpointProvider) {
return new PrefixAwareUriBuilderFactory(endpointProvider);
}
@@ -177,27 +168,26 @@ public class VaultClients {
@Override
protected URI expandInternal(String uriTemplate, Map<String, ?> uriVariables) {
return super.expandInternal(prepareUriTemplate(getBaseUrl(), uriTemplate),
uriVariables);
return super.expandInternal(prepareUriTemplate(getBaseUrl(), uriTemplate), uriVariables);
}
@Override
protected URI expandInternal(String uriTemplate, Object... uriVariables) {
return super.expandInternal(prepareUriTemplate(getBaseUrl(), uriTemplate),
uriVariables);
return super.expandInternal(prepareUriTemplate(getBaseUrl(), uriTemplate), uriVariables);
}
@Override
public String getBaseUrl() {
if (endpointProvider != null) {
if (this.endpointProvider != null) {
VaultEndpoint endpoint = endpointProvider.getVaultEndpoint();
VaultEndpoint endpoint = this.endpointProvider.getVaultEndpoint();
return toBaseUri(endpoint);
}
return super.getBaseUrl();
}
}
/**
@@ -218,27 +208,26 @@ public class VaultClients {
return UriComponentsBuilder.fromUriString(uriTemplate);
}
VaultEndpoint endpoint = endpointProvider.getVaultEndpoint();
VaultEndpoint endpoint = this.endpointProvider.getVaultEndpoint();
String baseUri = toBaseUri(endpoint);
UriComponents uriComponents = UriComponentsBuilder
.fromUriString(prepareUriTemplate(baseUri, uriTemplate)).build();
UriComponents uriComponents = UriComponentsBuilder.fromUriString(prepareUriTemplate(baseUri, uriTemplate))
.build();
return UriComponentsBuilder.fromUriString(baseUri)
.uriComponents(uriComponents);
return UriComponentsBuilder.fromUriString(baseUri).uriComponents(uriComponents);
}
}
private static String toBaseUri(VaultEndpoint endpoint) {
return String.format("%s://%s:%s/%s", endpoint.getScheme(), endpoint.getHost(),
endpoint.getPort(), endpoint.getPath());
return String.format("%s://%s:%s/%s", endpoint.getScheme(), endpoint.getHost(), endpoint.getPort(),
endpoint.getPath());
}
/**
* Strip/add leading slashes from {@code uriTemplate} depending on whether the base
* url has a trailing slash.
*
* @param uriTemplate
* @return
*/
@@ -277,4 +266,5 @@ public class VaultClients {
return uriTemplate;
}
}

View File

@@ -59,7 +59,6 @@ public class VaultEndpoint implements Serializable {
/**
* Create a secure {@link VaultEndpoint} given a {@code host} and {@code port} using
* {@code https}.
*
* @param host must not be empty or {@literal null}.
* @param port must be a valid port in the range of 1-65535
* @return a new {@link VaultEndpoint}.
@@ -78,9 +77,8 @@ public class VaultEndpoint implements Serializable {
/**
* Create a {@link VaultEndpoint} given a {@link URI}.
*
* @param uri must contain hostname, port and scheme, must not be empty or
* {@literal null}.
* {@literal null}.
* @return a new {@link VaultEndpoint}.
*/
public static VaultEndpoint from(URI uri) {
@@ -93,12 +91,10 @@ public class VaultEndpoint implements Serializable {
vaultEndpoint.setHost(uri.getHost());
try {
vaultEndpoint.setPort(
uri.getPort() == -1 ? uri.toURL().getDefaultPort() : uri.getPort());
vaultEndpoint.setPort(uri.getPort() == -1 ? uri.toURL().getDefaultPort() : uri.getPort());
}
catch (MalformedURLException e) {
throw new IllegalArgumentException(
String.format("Can't retrieve default port from %s", uri), e);
throw new IllegalArgumentException(String.format("Can't retrieve default port from %s", uri), e);
}
vaultEndpoint.setScheme(uri.getScheme());
@@ -122,12 +118,11 @@ public class VaultEndpoint implements Serializable {
* @return the hostname.
*/
public String getHost() {
return host;
return this.host;
}
/**
* Sets the hostname.
*
* @param host must not be empty or {@literal null}.
*/
public void setHost(String host) {
@@ -138,7 +133,7 @@ public class VaultEndpoint implements Serializable {
* @return the port.
*/
public int getPort() {
return port;
return this.port;
}
/**
@@ -146,8 +141,7 @@ public class VaultEndpoint implements Serializable {
*/
public void setPort(int port) {
Assert.isTrue(port >= 1 && port <= 65535,
"Port must be a valid port in the range between 1 and 65535");
Assert.isTrue(port >= 1 && port <= 65535, "Port must be a valid port in the range between 1 and 65535");
this.port = port;
}
@@ -156,7 +150,7 @@ public class VaultEndpoint implements Serializable {
* @return the protocol scheme.
*/
public String getScheme() {
return scheme;
return this.scheme;
}
/**
@@ -164,8 +158,7 @@ public class VaultEndpoint implements Serializable {
*/
public void setScheme(String scheme) {
Assert.isTrue("http".equals(scheme) || "https".equals(scheme),
"Scheme must be http or https");
Assert.isTrue("http".equals(scheme) || "https".equals(scheme), "Scheme must be http or https");
this.scheme = scheme;
}
@@ -175,26 +168,24 @@ public class VaultEndpoint implements Serializable {
* @since 2.1
*/
public String getPath() {
return path;
return this.path;
}
/**
* @param path context path prefix. Must not be {@literal null} or empty and must not
* start with a leading slash.
* start with a leading slash.
* @since 2.1
*/
public void setPath(String path) {
Assert.hasText(path, "Path must not be null or empty");
Assert.isTrue(!path.startsWith("/"),
() -> String.format("Path %s must not start with a leading slash", path));
Assert.isTrue(!path.startsWith("/"), () -> String.format("Path %s must not start with a leading slash", path));
this.path = path;
}
/**
* Build the Vault {@link URI} based on the given {@code path}.
*
* @param path must not be empty or {@literal null}.
* @return constructed {@link URI}.
*/
@@ -204,7 +195,6 @@ public class VaultEndpoint implements Serializable {
/**
* Build the Vault URI string based on the given {@code path}.
*
* @param path must not be empty or {@literal null}.
* @return constructed URI String.
*/
@@ -212,8 +202,7 @@ public class VaultEndpoint implements Serializable {
Assert.hasText(path, "Path must not be empty");
return String.format("%s://%s:%s/%s/%s", getScheme(), getHost(), getPort(),
getPath(), path);
return String.format("%s://%s:%s/%s/%s", getScheme(), getHost(), getPort(), getPath(), path);
}
@Override
@@ -223,17 +212,18 @@ public class VaultEndpoint implements Serializable {
if (!(o instanceof VaultEndpoint))
return false;
VaultEndpoint that = (VaultEndpoint) o;
return port == that.port && host.equals(that.host) && scheme.equals(that.scheme)
&& path.equals(that.path);
return this.port == that.port && this.host.equals(that.host) && this.scheme.equals(that.scheme)
&& this.path.equals(that.path);
}
@Override
public int hashCode() {
return Objects.hash(host, port, scheme, path);
return Objects.hash(this.host, this.port, this.scheme, this.path);
}
@Override
public String toString() {
return String.format("%s://%s:%d", scheme, host, port);
return String.format("%s://%s:%d", this.scheme, this.host, this.port);
}
}

View File

@@ -27,8 +27,8 @@ public interface VaultEndpointProvider {
/**
* Provides access to {@link VaultEndpoint}.
*
* @return the {@link VaultEndpoint}.
*/
VaultEndpoint getVaultEndpoint();
}

View File

@@ -56,4 +56,5 @@ public abstract class VaultHttpHeaders {
return headers;
}
}

View File

@@ -60,13 +60,11 @@ public abstract class VaultResponses {
String message = VaultResponses.getError(e.getResponseBodyAsString());
if (StringUtils.hasText(message)) {
return new VaultException(String.format("Status %s %s: %s",
e.getRawStatusCode(), e.getStatusText(), message), e);
return new VaultException(
String.format("Status %s %s: %s", e.getRawStatusCode(), e.getStatusText(), message), e);
}
return new VaultException(
String.format("Status %s %s", e.getRawStatusCode(), e.getStatusText()),
e);
return new VaultException(String.format("Status %s %s", e.getRawStatusCode(), e.getStatusText()), e);
}
/**
@@ -83,20 +81,17 @@ public abstract class VaultResponses {
String message = VaultResponses.getError(e.getResponseBodyAsString());
if (StringUtils.hasText(message)) {
return new VaultException(String.format("Status %s %s [%s]: %s",
e.getRawStatusCode(), e.getStatusText(), path, message), e);
return new VaultException(
String.format("Status %s %s [%s]: %s", e.getRawStatusCode(), e.getStatusText(), path, message), e);
}
return new VaultException(String.format("Status %s %s [%s]", e.getRawStatusCode(),
e.getStatusText(), path), e);
return new VaultException(String.format("Status %s %s [%s]", e.getRawStatusCode(), e.getStatusText(), path), e);
}
public static VaultException buildException(HttpStatus statusCode, String path,
String message) {
public static VaultException buildException(HttpStatus statusCode, String path, String message) {
if (StringUtils.hasText(message)) {
return new VaultException(
String.format("Status %s [%s]: %s", statusCode, path, message));
return new VaultException(String.format("Status %s [%s]: %s", statusCode, path, message));
}
return new VaultException(String.format("Status %s [%s]", statusCode, path));
@@ -140,7 +135,6 @@ public abstract class VaultResponses {
/**
* Obtain the error message from a JSON response.
*
* @param json must not be {@literal null}.
* @return extracted error string.
*/
@@ -152,8 +146,7 @@ public abstract class VaultResponses {
if (json.contains("\"errors\":")) {
try {
Map<String, Object> map = OBJECT_MAPPER.readValue(json.getBytes(),
Map.class);
Map<String, Object> map = OBJECT_MAPPER.readValue(json.getBytes(), Map.class);
if (map.containsKey("errors")) {
Collection<String> errors = (Collection<String>) map.get("errors");
@@ -173,7 +166,6 @@ public abstract class VaultResponses {
/**
* Unwrap a wrapped response created by Vault Response Wrapping
*
* @param wrappedResponse the wrapped response , must not be empty or {@literal null}.
* @param responseType the type of the return value.
* @return the unwrapped response.
@@ -200,4 +192,5 @@ public abstract class VaultResponses {
throw new IllegalStateException(e);
}
}
}

View File

@@ -51,8 +51,8 @@ public class WebClientBuilder {
private @Nullable VaultEndpointProvider endpointProvider;
private Supplier<ClientHttpConnector> httpConnector = () -> ClientHttpConnectorFactory
.create(new ClientOptions(), SslConfiguration.unconfigured());
private Supplier<ClientHttpConnector> httpConnector = () -> ClientHttpConnectorFactory.create(new ClientOptions(),
SslConfiguration.unconfigured());
private final Map<String, String> defaultHeaders = new LinkedHashMap<>();
@@ -65,7 +65,6 @@ public class WebClientBuilder {
/**
* Create a new {@link WebClientBuilder}.
*
* @return a new {@link WebClientBuilder}.
*/
public static WebClientBuilder builder() {
@@ -74,7 +73,6 @@ public class WebClientBuilder {
/**
* Set the {@link VaultEndpoint} that should be used with the {@link WebClient}.
*
* @param endpoint the {@link VaultEndpoint} provider.
* @return {@code this} {@link WebClientBuilder}.
*/
@@ -85,7 +83,6 @@ public class WebClientBuilder {
/**
* Set the {@link VaultEndpointProvider} that should be used with the
* {@link WebClient}.
*
* @param provider the {@link VaultEndpoint} provider.
* @return {@code this} {@link WebClientBuilder}.
*/
@@ -100,7 +97,6 @@ public class WebClientBuilder {
/**
* Set the {@link ClientHttpConnector} that should be used with the {@link WebClient}.
*
* @param httpConnector the HTTP connector.
* @return {@code this} {@link WebClientBuilder}.
*/
@@ -114,13 +110,11 @@ public class WebClientBuilder {
/**
* Set the {@link Supplier} of {@link ClientHttpConnector} that should be called each
* time we {@link #build()} a new {@link WebClient} instance.
*
* @param httpConnector the supplier for the HTTP connector.
* @return {@code this} {@link WebClientBuilder}.
* @since 2.2.1
*/
public WebClientBuilder httpConnectorFactory(
Supplier<ClientHttpConnector> httpConnector) {
public WebClientBuilder httpConnectorFactory(Supplier<ClientHttpConnector> httpConnector) {
Assert.notNull(httpConnector, "Supplier of ClientHttpConnector must not be null");
@@ -131,7 +125,6 @@ public class WebClientBuilder {
/**
* Set the {@link Supplier} of {@link ClientHttpConnector} that should be called each
* time we {@link #build()} a new {@link WebClient} instance.
*
* @param httpConnector the supplier for the HTTP connector.
* @return {@code this} {@link WebClientBuilder}.
* @deprecated since 2.2.1 as the name is wrong, use
@@ -145,7 +138,6 @@ public class WebClientBuilder {
/**
* Add a default header that will be set if not already present on the outgoing
* {@link HttpRequest}.
*
* @param name the name of the header.
* @param value the header value.
* @return {@code this} {@link WebClientBuilder}.
@@ -162,7 +154,6 @@ public class WebClientBuilder {
/**
* Add the {@link WebClientCustomizer WebClientCustomizers} that should be applied to
* the {@link WebClient}. Customizers are applied in the order that they were added.
*
* @param customizer the client customizers to add.
* @return {@code this} {@link WebClientBuilder}.
*/
@@ -177,7 +168,6 @@ public class WebClientBuilder {
* Add the {@link ExchangeFilterFunction ExchangeFilterFunctions} that should be
* applied to the {@link ClientRequest}. {@link ExchangeFilterFunction}s are applied
* in the order that they were added.
*
* @param filterFunctions the request customizers to add.
* @return {@code this} {@link WebClientBuilder}.
*/
@@ -194,23 +184,21 @@ public class WebClientBuilder {
*
* Applies also {@link ExchangeFilterFunction} and {@link WebClientCustomizer} if
* configured.
*
* @return a new {@link WebClient}.
*/
public WebClient build() {
Assert.state(this.endpointProvider != null,
"VaultEndpointProvider must not be null");
Assert.state(this.endpointProvider != null, "VaultEndpointProvider must not be null");
WebClient.Builder builder = createWebClientBuilder();
if (!defaultHeaders.isEmpty()) {
if (!this.defaultHeaders.isEmpty()) {
Map<String, String> defaultHeaders = this.defaultHeaders;
builder.filter((request, next) -> {
return next.exchange(ClientRequest.from(request)
.headers(headers -> defaultHeaders.forEach((key, value) -> {
return next.exchange(
ClientRequest.from(request).headers(headers -> defaultHeaders.forEach((key, value) -> {
if (!headers.containsKey(key)) {
headers.add(key, value);
}
@@ -219,23 +207,22 @@ public class WebClientBuilder {
});
}
builder.filters(exchangeFilterFunctions -> exchangeFilterFunctions
.addAll(this.filterFunctions));
builder.filters(exchangeFilterFunctions -> exchangeFilterFunctions.addAll(this.filterFunctions));
customizers.forEach(customizer -> customizer.customize(builder));
this.customizers.forEach(customizer -> customizer.customize(builder));
return builder.build();
}
/**
* Create the {@link WebClient.Builder} to use.
*
* @return the {@link WebClient.Builder} to use.
*/
protected WebClient.Builder createWebClientBuilder() {
ClientHttpConnector connector = this.httpConnector.get();
return ReactiveVaultClients.createWebClientBuilder(endpointProvider, connector);
return ReactiveVaultClients.createWebClientBuilder(this.endpointProvider, connector);
}
}

View File

@@ -29,8 +29,8 @@ public interface WebClientCustomizer {
/**
* Callback to customize a {@link WebClient.Builder} instance.
*
* @param webClientBuilder the client builder to customize.
*/
void customize(WebClient.Builder webClientBuilder);
}

View File

@@ -61,13 +61,11 @@ import org.springframework.web.reactive.function.client.WebClient;
* @since 2.0
*/
@Configuration(proxyBeanMethods = false)
public abstract class AbstractReactiveVaultConfiguration
extends AbstractVaultConfiguration {
public abstract class AbstractReactiveVaultConfiguration extends AbstractVaultConfiguration {
/**
* Create a {@link WebClientBuilder} initialized with {@link VaultEndpointProvider}
* and {@link ClientHttpConnector}. May be overridden by subclasses.
*
* @return the {@link WebClientBuilder}.
* @see #vaultEndpointProvider()
* @see #clientHttpConnector()
@@ -75,13 +73,11 @@ public abstract class AbstractReactiveVaultConfiguration
*/
protected WebClientBuilder webClientBuilder(VaultEndpointProvider endpointProvider,
ClientHttpConnector httpConnector) {
return WebClientBuilder.builder().endpointProvider(endpointProvider)
.httpConnector(httpConnector);
return WebClientBuilder.builder().endpointProvider(endpointProvider).httpConnector(httpConnector);
}
/**
* Create a {@link ReactiveVaultTemplate}.
*
* @return the {@link ReactiveVaultTemplate}.
* @see #vaultEndpoint()
* @see #clientHttpConnector()
@@ -89,15 +85,13 @@ public abstract class AbstractReactiveVaultConfiguration
*/
@Bean
public ReactiveVaultTemplate reactiveVaultTemplate() {
return new ReactiveVaultTemplate(
webClientBuilder(vaultEndpointProvider(), clientHttpConnector()),
return new ReactiveVaultTemplate(webClientBuilder(vaultEndpointProvider(), clientHttpConnector()),
getReactiveSessionManager());
}
/**
* Construct a session manager adapter wrapping {@link #reactiveSessionManager()} and
* exposing imperative {@link SessionManager} on top of a reactive API.
*
* @return the {@link SessionManager} adapter.
*/
@Bean
@@ -110,7 +104,6 @@ public abstract class AbstractReactiveVaultConfiguration
* Construct a {@link ReactiveSessionManager} using {@link #vaultTokenSupplier()}.
* This {@link org.springframework.vault.authentication.ReactiveSessionManager} uses
* {@link #threadPoolTaskScheduler()}.
*
* @return the {@link VaultTokenSupplier} for Vault session token management.
* @see VaultTokenSupplier
* @see #clientAuthentication()
@@ -118,15 +111,13 @@ public abstract class AbstractReactiveVaultConfiguration
@Bean
public ReactiveSessionManager reactiveSessionManager() {
WebClient webClient = ReactiveVaultClients.createWebClient(vaultEndpoint(),
clientHttpConnector());
return new ReactiveLifecycleAwareSessionManager(vaultTokenSupplier(),
getVaultThreadPoolTaskScheduler(), webClient);
WebClient webClient = ReactiveVaultClients.createWebClient(vaultEndpoint(), clientHttpConnector());
return new ReactiveLifecycleAwareSessionManager(vaultTokenSupplier(), getVaultThreadPoolTaskScheduler(),
webClient);
}
/**
* Construct a {@link VaultTokenSupplier} using {@link #clientAuthentication()}.
*
* @return the {@link VaultTokenSupplier} for Vault session token management.
* @see VaultTokenSupplier
* @see #clientAuthentication()
@@ -147,8 +138,7 @@ public abstract class AbstractReactiveVaultConfiguration
AuthenticationStepsFactory factory = (AuthenticationStepsFactory) clientAuthentication;
WebClient webClient = ReactiveVaultClients.createWebClient(vaultEndpoint(),
clientHttpConnector());
WebClient webClient = ReactiveVaultClients.createWebClient(vaultEndpoint(), clientHttpConnector());
AuthenticationStepsOperator stepsOperator = new AuthenticationStepsOperator(
factory.getAuthenticationSteps(), webClient);
@@ -164,7 +154,6 @@ public abstract class AbstractReactiveVaultConfiguration
/**
* Create a {@link ClientHttpConnector} configured with {@link ClientOptions} and
* {@link org.springframework.vault.support.SslConfiguration}.
*
* @return the {@link ClientHttpConnector} instance.
* @see #clientOptions()
* @see #sslConfiguration()
@@ -174,8 +163,7 @@ public abstract class AbstractReactiveVaultConfiguration
}
private ReactiveSessionManager getReactiveSessionManager() {
return getBeanFactory().getBean("reactiveSessionManager",
ReactiveSessionManager.class);
return getBeanFactory().getBean("reactiveSessionManager", ReactiveSessionManager.class);
}
/**
@@ -192,7 +180,9 @@ public abstract class AbstractReactiveVaultConfiguration
@Override
public VaultToken getSessionToken() {
return sessionManager.getSessionToken().block(Duration.ofSeconds(30));
return this.sessionManager.getSessionToken().block(Duration.ofSeconds(30));
}
}
}

View File

@@ -72,7 +72,6 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
* Annotate with {@link Bean} in case you want to expose a
* {@link ClientAuthentication} instance to the
* {@link org.springframework.context.ApplicationContext}.
*
* @return the {@link ClientAuthentication} to use. Must not be {@literal null}.
*/
public abstract ClientAuthentication clientAuthentication();
@@ -80,22 +79,18 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
/**
* Create a {@link RestTemplateBuilder} initialized with {@link VaultEndpointProvider}
* and {@link ClientHttpRequestFactory}. May be overridden by subclasses.
*
* @return the {@link RestTemplateBuilder}.
* @see #vaultEndpointProvider()
* @see #clientHttpRequestFactoryWrapper()
* @since 2.2
*/
protected RestTemplateBuilder restTemplateBuilder(
VaultEndpointProvider endpointProvider,
protected RestTemplateBuilder restTemplateBuilder(VaultEndpointProvider endpointProvider,
ClientHttpRequestFactory requestFactory) {
return RestTemplateBuilder.builder().endpointProvider(endpointProvider)
.requestFactory(requestFactory);
return RestTemplateBuilder.builder().endpointProvider(endpointProvider).requestFactory(requestFactory);
}
/**
* Create a {@link VaultTemplate}.
*
* @return the {@link VaultTemplate}.
* @see #vaultEndpointProvider()
* @see #clientHttpRequestFactoryWrapper()
@@ -104,8 +99,7 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
@Bean
public VaultTemplate vaultTemplate() {
return new VaultTemplate(
restTemplateBuilder(vaultEndpointProvider(),
getClientFactoryWrapper().getClientHttpRequestFactory()),
restTemplateBuilder(vaultEndpointProvider(), getClientFactoryWrapper().getClientHttpRequestFactory()),
getBeanFactory().getBean("sessionManager", SessionManager.class));
}
@@ -113,7 +107,6 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
* Construct a {@link LifecycleAwareSessionManager} using
* {@link #clientAuthentication()}. This {@link SessionManager} uses
* {@link #threadPoolTaskScheduler()}.
*
* @return the {@link SessionManager} for Vault session management.
* @see SessionManager
* @see LifecycleAwareSessionManager
@@ -128,14 +121,13 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
Assert.notNull(clientAuthentication, "ClientAuthentication must not be null");
return new LifecycleAwareSessionManager(clientAuthentication,
getVaultThreadPoolTaskScheduler(), restOperations());
return new LifecycleAwareSessionManager(clientAuthentication, getVaultThreadPoolTaskScheduler(),
restOperations());
}
/**
* Construct a {@link SecretLeaseContainer} using {@link #vaultTemplate()} and
* {@link #threadPoolTaskScheduler()}.
*
* @return the {@link SecretLeaseContainer} to allocate, renew and rotate secrets and
* their leases.
* @see #vaultTemplate()
@@ -145,8 +137,7 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
public SecretLeaseContainer secretLeaseContainer() throws Exception {
SecretLeaseContainer secretLeaseContainer = new SecretLeaseContainer(
getBeanFactory().getBean("vaultTemplate", VaultTemplate.class),
getVaultThreadPoolTaskScheduler());
getBeanFactory().getBean("vaultTemplate", VaultTemplate.class), getVaultThreadPoolTaskScheduler());
secretLeaseContainer.afterPropertiesSet();
secretLeaseContainer.start();
@@ -162,7 +153,6 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
* to the {@link org.springframework.context.ApplicationContext}. This might be useful
* to supply managed executor instances or {@link ThreadPoolTaskScheduler}s using a
* queue/pooled threads.
*
* @return the {@link ThreadPoolTaskScheduler} to use. Must not be {@literal null}.
*/
@Bean("vaultThreadPoolTaskScheduler")
@@ -170,8 +160,7 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler
.setThreadNamePrefix("spring-vault-ThreadPoolTaskScheduler-");
threadPoolTaskScheduler.setThreadNamePrefix("spring-vault-ThreadPoolTaskScheduler-");
threadPoolTaskScheduler.setDaemon(true);
return threadPoolTaskScheduler;
@@ -181,14 +170,13 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
* Construct a {@link RestOperations} object configured for Vault session management
* and authentication usage. Can be customized by overriding
* {@link #restTemplateBuilder(VaultEndpointProvider, ClientHttpRequestFactory)}.
*
* @return the {@link RestOperations} to be used for Vault access.
* @see #vaultEndpointProvider()
* @see #clientHttpRequestFactoryWrapper()
*/
public RestOperations restOperations() {
return restTemplateBuilder(vaultEndpointProvider(),
getClientFactoryWrapper().getClientHttpRequestFactory()).build();
return restTemplateBuilder(vaultEndpointProvider(), getClientFactoryWrapper().getClientHttpRequestFactory())
.build();
}
/**
@@ -197,7 +185,6 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
* {@link ClientHttpRequestFactory} is configured with {@link ClientOptions} and
* {@link SslConfiguration} which are not necessarily applicable for the whole
* application.
*
* @return the {@link ClientFactoryWrapper} to wrap a {@link ClientHttpRequestFactory}
* instance.
* @see #clientOptions()
@@ -205,8 +192,7 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
*/
@Bean
public ClientFactoryWrapper clientHttpRequestFactoryWrapper() {
return new ClientFactoryWrapper(ClientHttpRequestFactoryFactory
.create(clientOptions(), sslConfiguration()));
return new ClientFactoryWrapper(ClientHttpRequestFactoryFactory.create(clientOptions(), sslConfiguration()));
}
/**
@@ -231,40 +217,36 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
* Return the {@link Environment} to access property sources during Spring Vault
* bootstrapping. Requires {@link #setApplicationContext(ApplicationContext)
* ApplicationContext} to be set.
*
* @return the {@link Environment} to access property sources during Spring Vault
* bootstrapping.
*/
protected Environment getEnvironment() {
Assert.state(applicationContext != null,
Assert.state(this.applicationContext != null,
"ApplicationContext must be set before accessing getEnvironment()");
return applicationContext.getEnvironment();
return this.applicationContext.getEnvironment();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
BeanFactory getBeanFactory() {
Assert.state(applicationContext != null,
Assert.state(this.applicationContext != null,
"ApplicationContext must be set before accessing getBeanFactory()");
return applicationContext;
return this.applicationContext;
}
ThreadPoolTaskScheduler getVaultThreadPoolTaskScheduler() {
return getBeanFactory().getBean("vaultThreadPoolTaskScheduler",
ThreadPoolTaskScheduler.class);
return getBeanFactory().getBean("vaultThreadPoolTaskScheduler", ThreadPoolTaskScheduler.class);
}
private ClientFactoryWrapper getClientFactoryWrapper() {
return getBeanFactory().getBean("clientHttpRequestFactoryWrapper",
ClientFactoryWrapper.class);
return getBeanFactory().getBean("clientHttpRequestFactoryWrapper", ClientFactoryWrapper.class);
}
/**
@@ -280,21 +262,23 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
@Override
public void destroy() throws Exception {
if (clientHttpRequestFactory instanceof DisposableBean) {
((DisposableBean) clientHttpRequestFactory).destroy();
if (this.clientHttpRequestFactory instanceof DisposableBean) {
((DisposableBean) this.clientHttpRequestFactory).destroy();
}
}
@Override
public void afterPropertiesSet() throws Exception {
if (clientHttpRequestFactory instanceof InitializingBean) {
((InitializingBean) clientHttpRequestFactory).afterPropertiesSet();
if (this.clientHttpRequestFactory instanceof InitializingBean) {
((InitializingBean) this.clientHttpRequestFactory).afterPropertiesSet();
}
}
public ClientHttpRequestFactory getClientHttpRequestFactory() {
return clientHttpRequestFactory;
return this.clientHttpRequestFactory;
}
}
}

View File

@@ -36,14 +36,12 @@ public class ClientHttpConnectorFactory {
/**
* Create a {@link ClientHttpConnector} for the given {@link ClientOptions} and
* {@link SslConfiguration}.
*
* @param options must not be {@literal null}
* @param sslConfiguration must not be {@literal null}
* @return a new {@link ClientHttpConnector}.
*/
public static ClientHttpConnector create(ClientOptions options,
SslConfiguration sslConfiguration) {
return org.springframework.vault.client.ClientHttpConnectorFactory.create(options,
sslConfiguration);
public static ClientHttpConnector create(ClientOptions options, SslConfiguration sslConfiguration) {
return org.springframework.vault.client.ClientHttpConnectorFactory.create(options, sslConfiguration);
}
}

View File

@@ -35,15 +35,13 @@ public class ClientHttpRequestFactoryFactory {
/**
* Create a {@link ClientHttpRequestFactory} for the given {@link ClientOptions} and
* {@link SslConfiguration}.
*
* @param options must not be {@literal null}
* @param sslConfiguration must not be {@literal null}
* @return a new {@link ClientHttpRequestFactory}. Lifecycle beans must be initialized
* after obtaining.
*/
public static ClientHttpRequestFactory create(ClientOptions options,
SslConfiguration sslConfiguration) {
return org.springframework.vault.client.ClientHttpRequestFactoryFactory
.create(options, sslConfiguration);
public static ClientHttpRequestFactory create(ClientOptions options, SslConfiguration sslConfiguration) {
return org.springframework.vault.client.ClientHttpRequestFactoryFactory.create(options, sslConfiguration);
}
}

View File

@@ -80,8 +80,7 @@ import org.springframework.web.client.RestOperations;
* &#64;Import(EnvironmentVaultConfiguration.class)
* public class MyConfiguration {
* }
* </code>
* </pre>
* </code> </pre>
*
* Supplied properties:
*
@@ -89,8 +88,7 @@ import org.springframework.web.client.RestOperations;
* <code>
* vault.uri=https://localhost:8200
* vault.token=00000000-0000-0000-0000-000000000000
* </code>
* </pre>
* </code> </pre>
*
* <h3>Property keys</h3>
*
@@ -185,13 +183,12 @@ import org.springframework.web.client.RestOperations;
* @see KubernetesAuthentication
*/
@Configuration
public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
implements ApplicationContextAware {
public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration implements ApplicationContextAware {
private static final Log logger = LogFactory
.getLog(EnvironmentVaultConfiguration.class);
private static final Log logger = LogFactory.getLog(EnvironmentVaultConfiguration.class);
private @Nullable RestOperations cachedRestOperations;
private @Nullable ApplicationContext applicationContext;
@Override
@@ -206,8 +203,7 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
super.setApplicationContext(applicationContext);
@@ -227,17 +223,16 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
@Override
public SslConfiguration sslConfiguration() {
KeyStoreConfiguration keyStoreConfiguration = getKeyStoreConfiguration(
"vault.ssl.key-store", "vault.ssl.key-store-password");
KeyStoreConfiguration keyStoreConfiguration = getKeyStoreConfiguration("vault.ssl.key-store",
"vault.ssl.key-store-password");
KeyStoreConfiguration trustStoreConfiguration = getKeyStoreConfiguration(
"vault.ssl.trust-store", "vault.ssl.trust-store-password");
KeyStoreConfiguration trustStoreConfiguration = getKeyStoreConfiguration("vault.ssl.trust-store",
"vault.ssl.trust-store-password");
return new SslConfiguration(keyStoreConfiguration, trustStoreConfiguration);
}
private KeyStoreConfiguration getKeyStoreConfiguration(String resourceProperty,
String passwordProperty) {
private KeyStoreConfiguration getKeyStoreConfiguration(String resourceProperty, String passwordProperty) {
Resource keyStore = getResource(resourceProperty);
String keyStorePassword = getProperty(passwordProperty);
@@ -256,11 +251,10 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
@Override
public ClientAuthentication clientAuthentication() {
String authentication = getProperty("vault.authentication",
AuthenticationMethod.TOKEN.name()).toUpperCase().replace('-', '_');
String authentication = getProperty("vault.authentication", AuthenticationMethod.TOKEN.name()).toUpperCase()
.replace('-', '_');
AuthenticationMethod authenticationMethod = AuthenticationMethod
.valueOf(authentication);
AuthenticationMethod authenticationMethod = AuthenticationMethod.valueOf(authentication);
switch (authenticationMethod) {
@@ -281,8 +275,7 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
case KUBERNETES:
return kubeAuthentication();
default:
throw new IllegalStateException(String.format(
"Vault authentication method %s is not supported with %s",
throw new IllegalStateException(String.format("Vault authentication method %s is not supported with %s",
authenticationMethod, getClass().getSimpleName()));
}
}
@@ -294,27 +287,23 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
protected ClientAuthentication tokenAuthentication() {
String token = getProperty("vault.token");
Assert.hasText(token,
"Vault Token authentication: Token (vault.token) must not be empty");
Assert.hasText(token, "Vault Token authentication: Token (vault.token) must not be empty");
return new TokenAuthentication(token);
}
protected ClientAuthentication appIdAuthentication() {
String appId = getProperty("vault.app-id.app-id",
getProperty("spring.application.name"));
String appId = getProperty("vault.app-id.app-id", getProperty("spring.application.name"));
String userId = getProperty("vault.app-id.user-id");
String path = getProperty("vault.app-id.app-id-path",
AppIdAuthenticationOptions.DEFAULT_APPID_AUTHENTICATION_PATH);
Assert.hasText(appId,
"Vault AppId authentication: AppId (vault.app-id.app-id) must not be empty");
Assert.hasText(userId,
"Vault AppId authentication: UserId (vault.app-id.user-id) must not be empty");
Assert.hasText(appId, "Vault AppId authentication: AppId (vault.app-id.app-id) must not be empty");
Assert.hasText(userId, "Vault AppId authentication: UserId (vault.app-id.user-id) must not be empty");
AppIdAuthenticationOptionsBuilder builder = AppIdAuthenticationOptions.builder()
.appId(appId).userIdMechanism(getAppIdUserIdMechanism(userId)).path(path);
AppIdAuthenticationOptionsBuilder builder = AppIdAuthenticationOptions.builder().appId(appId)
.userIdMechanism(getAppIdUserIdMechanism(userId)).path(path);
return new AppIdAuthentication(builder.build(), restOperations());
}
@@ -326,11 +315,10 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
String path = getProperty("vault.app-role.app-role-path",
AppRoleAuthenticationOptions.DEFAULT_APPROLE_AUTHENTICATION_PATH);
Assert.hasText(roleId,
"Vault AppRole authentication: RoleId (vault.app-role.role-id) must not be empty");
Assert.hasText(roleId, "Vault AppRole authentication: RoleId (vault.app-role.role-id) must not be empty");
AppRoleAuthenticationOptionsBuilder builder = AppRoleAuthenticationOptions
.builder().roleId(RoleId.provided(roleId)).path(path);
AppRoleAuthenticationOptionsBuilder builder = AppRoleAuthenticationOptions.builder()
.roleId(RoleId.provided(roleId)).path(path);
if (StringUtils.hasText(secretId)) {
builder = builder.secretId(SecretId.provided(secretId));
@@ -364,9 +352,8 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
"Vault AWS-EC2 authentication: Role (vault.aws-ec2.role) must not be empty");
if (StringUtils.hasText(roleId) && StringUtils.hasText(role)) {
throw new IllegalStateException(
"AWS-EC2 Authentication: Only one of Role (vault.aws-ec2.role) or"
+ " RoleId (deprecated, vault.aws-ec2.roleId) must be provided");
throw new IllegalStateException("AWS-EC2 Authentication: Only one of Role (vault.aws-ec2.role) or"
+ " RoleId (deprecated, vault.aws-ec2.roleId) must be provided");
}
if (StringUtils.hasText(roleId)) {
@@ -381,8 +368,7 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
builder.identityDocumentUri(URI.create(identityDocument));
}
return new AwsEc2Authentication(builder.build(), restOperations(),
restOperations());
return new AwsEc2Authentication(builder.build(), restOperations(), restOperations());
}
protected ClientAuthentication azureMsiAuthentication() {
@@ -394,12 +380,10 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
AzureMsiAuthenticationOptions.DEFAULT_INSTANCE_METADATA_SERVICE_URI);
URI identityTokenServiceUri = getUri("vault.azure-msi.identity-token-service",
AzureMsiAuthenticationOptions.DEFAULT_IDENTITY_TOKEN_SERVICE_URI);
Assert.hasText(role,
"Vault Azure MSI authentication: Role (vault.azure-msi.role) must not be empty");
Assert.hasText(role, "Vault Azure MSI authentication: Role (vault.azure-msi.role) must not be empty");
AzureMsiAuthenticationOptionsBuilder builder = AzureMsiAuthenticationOptions
.builder().role(role).path(path).instanceMetadataUri(metadataServiceUri)
.identityTokenServiceUri(identityTokenServiceUri);
AzureMsiAuthenticationOptionsBuilder builder = AzureMsiAuthenticationOptions.builder().role(role).path(path)
.instanceMetadataUri(metadataServiceUri).identityTokenServiceUri(identityTokenServiceUri);
return new AzureMsiAuthentication(builder.build(), restOperations());
}
@@ -407,11 +391,10 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
protected ClientAuthentication cubbyholeAuthentication() {
String token = getProperty("vault.token");
Assert.hasText(token,
"Vault Cubbyhole authentication: Initial token (vault.token) must not be empty");
Assert.hasText(token, "Vault Cubbyhole authentication: Initial token (vault.token) must not be empty");
CubbyholeAuthenticationOptionsBuilder builder = CubbyholeAuthenticationOptions
.builder().wrapped().initialToken(VaultToken.of(token));
CubbyholeAuthenticationOptionsBuilder builder = CubbyholeAuthenticationOptions.builder().wrapped()
.initialToken(VaultToken.of(token));
return new CubbyholeAuthentication(builder.build(), restOperations());
}
@@ -426,11 +409,10 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
Assert.hasText(role, "Vault Kubernetes authentication: role must not be empty");
KubernetesJwtSupplier jwtSupplier = new KubernetesServiceAccountTokenFile(
tokenFile);
KubernetesJwtSupplier jwtSupplier = new KubernetesServiceAccountTokenFile(tokenFile);
KubernetesAuthenticationOptionsBuilder builder = KubernetesAuthenticationOptions
.builder().role(role).jwtSupplier(jwtSupplier).path(path);
KubernetesAuthenticationOptionsBuilder builder = KubernetesAuthenticationOptions.builder().role(role)
.jwtSupplier(jwtSupplier).path(path);
return new KubernetesAuthentication(builder.build(), restOperations());
}
@@ -452,14 +434,19 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration
private Resource getResource(String key) {
String value = getProperty(key);
return value != null ? applicationContext.getResource(value) : null;
return value != null ? this.applicationContext.getResource(value) : null;
}
enum AppIdUserId {
IP_ADDRESS, MAC_ADDRESS;
}
enum AuthenticationMethod {
TOKEN, APPID, APPROLE, AWS_EC2, AZURE, CERT, CUBBYHOLE, KUBERNETES;
}
}

View File

@@ -52,7 +52,6 @@ public interface ReactiveVaultOperations {
/**
* Read from a Vault path. Reading data using this method is suitable for API
* calls/secret backends that do not require a request body.
*
* @param path must not be {@literal null}.
* @return the data. May be empty if the path does not exist.
*/
@@ -61,7 +60,6 @@ public interface ReactiveVaultOperations {
/**
* Read from a Vault path. Reading data using this method is suitable for API
* calls/secret backends that do not require a request body.
*
* @param path must not be {@literal null}.
* @param responseType must not be {@literal null}.
* @return the data. May be empty if the path does not exist.
@@ -70,7 +68,6 @@ public interface ReactiveVaultOperations {
/**
* Enumerate keys from a Vault path.
*
* @param path must not be {@literal null}.
* @return the data. May be empty if the path does not exist.
*/
@@ -78,7 +75,6 @@ public interface ReactiveVaultOperations {
/**
* Write to a Vault path.
*
* @param path must not be {@literal null}.
* @return the response. May be empty if the response has no body.
*/
@@ -88,7 +84,6 @@ public interface ReactiveVaultOperations {
/**
* Write to a Vault path.
*
* @param path must not be {@literal null}.
* @param body the body, may be {@literal null} if absent.
* @return the response. May be empty if the response has no body.
@@ -97,7 +92,6 @@ public interface ReactiveVaultOperations {
/**
* Delete a path.
*
* @param path must not be {@literal null}.
*/
Mono<Void> delete(String path);
@@ -106,30 +100,27 @@ public interface ReactiveVaultOperations {
* Executes a Vault {@link RestOperationsCallback}. Allows to interact with Vault
* using {@link org.springframework.web.client.RestOperations} without requiring a
* session.
*
* @param clientCallback the request.
* @return the {@link RestOperationsCallback} return value.
* @throws VaultException when a
* {@link org.springframework.web.client.HttpStatusCodeException} occurs.
* {@link org.springframework.web.client.HttpStatusCodeException} occurs.
* @throws WebClientException exceptions from
* {@link org.springframework.web.reactive.function.client.WebClient}.
* {@link org.springframework.web.reactive.function.client.WebClient}.
*/
<V, T extends Publisher<V>> T doWithVault(
Function<WebClient, ? extends T> clientCallback)
<V, T extends Publisher<V>> T doWithVault(Function<WebClient, ? extends T> clientCallback)
throws VaultException, WebClientException;
/**
* Executes a Vault {@link RestOperationsCallback}. Allows to interact with Vault in
* an authenticated session.
*
* @param sessionCallback the request.
* @return the {@link RestOperationsCallback} return value.
* @throws VaultException when a
* {@link org.springframework.web.client.HttpStatusCodeException} occurs.
* {@link org.springframework.web.client.HttpStatusCodeException} occurs.
* @throws WebClientException exceptions from
* {@link org.springframework.web.reactive.function.client.WebClient}.
* {@link org.springframework.web.reactive.function.client.WebClient}.
*/
<V, T extends Publisher<V>> T doWithSession(
Function<WebClient, ? extends T> sessionCallback)
<V, T extends Publisher<V>> T doWithSession(Function<WebClient, ? extends T> sessionCallback)
throws VaultException, WebClientException;
}

View File

@@ -75,28 +75,24 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
* {@link VaultTokenSupplier}. It is intended for usage with Vault Agent to inherit
* Vault Agent's authentication without using the {@link VaultHttpHeaders#VAULT_TOKEN
* authentication token header}.
*
* @param vaultEndpoint must not be {@literal null}.
* @param connector must not be {@literal null}.
* @since 2.2.1
*/
public ReactiveVaultTemplate(VaultEndpoint vaultEndpoint,
ClientHttpConnector connector) {
public ReactiveVaultTemplate(VaultEndpoint vaultEndpoint, ClientHttpConnector connector) {
this(SimpleVaultEndpointProvider.of(vaultEndpoint), connector);
}
/**
* Create a new {@link ReactiveVaultTemplate} with a {@link VaultEndpoint},
* {@link ClientHttpConnector} and {@link VaultTokenSupplier}.
*
* @param vaultEndpoint must not be {@literal null}.
* @param connector must not be {@literal null}.
* @param vaultTokenSupplier must not be {@literal null}.
*/
public ReactiveVaultTemplate(VaultEndpoint vaultEndpoint,
ClientHttpConnector connector, VaultTokenSupplier vaultTokenSupplier) {
this(SimpleVaultEndpointProvider.of(vaultEndpoint), connector,
vaultTokenSupplier);
public ReactiveVaultTemplate(VaultEndpoint vaultEndpoint, ClientHttpConnector connector,
VaultTokenSupplier vaultTokenSupplier) {
this(SimpleVaultEndpointProvider.of(vaultEndpoint), connector, vaultTokenSupplier);
}
/**
@@ -105,13 +101,11 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
* {@link VaultTokenSupplier}. It is intended for usage with Vault Agent to inherit
* Vault Agent's authentication without using the {@link VaultHttpHeaders#VAULT_TOKEN
* authentication token header}.
*
* @param endpointProvider must not be {@literal null}.
* @param connector must not be {@literal null}.
* @since 2.2.1
*/
public ReactiveVaultTemplate(VaultEndpointProvider endpointProvider,
ClientHttpConnector connector) {
public ReactiveVaultTemplate(VaultEndpointProvider endpointProvider, ClientHttpConnector connector) {
Assert.notNull(endpointProvider, "VaultEndpointProvider must not be null");
Assert.notNull(connector, "ClientHttpConnector must not be null");
@@ -126,13 +120,12 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
/**
* Create a new {@link ReactiveVaultTemplate} with a {@link VaultEndpointProvider},
* {@link ClientHttpConnector} and {@link VaultTokenSupplier}.
*
* @param endpointProvider must not be {@literal null}.
* @param connector must not be {@literal null}.
* @param vaultTokenSupplier must not be {@literal null}.
*/
public ReactiveVaultTemplate(VaultEndpointProvider endpointProvider,
ClientHttpConnector connector, VaultTokenSupplier vaultTokenSupplier) {
public ReactiveVaultTemplate(VaultEndpointProvider endpointProvider, ClientHttpConnector connector,
VaultTokenSupplier vaultTokenSupplier) {
Assert.notNull(endpointProvider, "VaultEndpointProvider must not be null");
Assert.notNull(connector, "ClientHttpConnector must not be null");
@@ -148,7 +141,6 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
* constructor does not use a {@link VaultTokenSupplier}. It is intended for usage
* with Vault Agent to inherit Vault Agent's authentication without using the
* {@link VaultHttpHeaders#VAULT_TOKEN authentication token header}.
*
* @param webClientBuilder must not be {@literal null}.
* @since 2.2.1
*/
@@ -166,21 +158,18 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
/**
* Create a new {@link ReactiveVaultTemplate} through a {@link WebClientBuilder}, and
* {@link VaultTokenSupplier}.
*
* @param webClientBuilder must not be {@literal null}.
* @param vaultTokenSupplier must not be {@literal null}
* @since 2.2
*/
public ReactiveVaultTemplate(WebClientBuilder webClientBuilder,
VaultTokenSupplier vaultTokenSupplier) {
public ReactiveVaultTemplate(WebClientBuilder webClientBuilder, VaultTokenSupplier vaultTokenSupplier) {
Assert.notNull(webClientBuilder, "WebClientBuilder must not be null");
Assert.notNull(vaultTokenSupplier, "VaultTokenSupplier must not be null");
this.vaultTokenSupplier = vaultTokenSupplier;
this.statelessClient = webClientBuilder.build();
this.sessionClient = webClientBuilder.build().mutate().filter(getSessionFilter())
.build();
this.sessionClient = webClientBuilder.build().mutate().filter(getSessionFilter()).build();
}
/**
@@ -189,20 +178,17 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
* {@link VaultEndpointProvider} is used to contribute host and port details for
* relative URLs typically used by the Template API. Subclasses may override this
* method to customize the {@link WebClient}.
*
* @param endpointProvider must not be {@literal null}.
* @param connector must not be {@literal null}.
* @return the {@link WebClient} used for Vault communication.
* @since 2.1
*/
protected WebClient doCreateWebClient(VaultEndpointProvider endpointProvider,
ClientHttpConnector connector) {
protected WebClient doCreateWebClient(VaultEndpointProvider endpointProvider, ClientHttpConnector connector) {
Assert.notNull(endpointProvider, "VaultEndpointProvider must not be null");
Assert.notNull(connector, "ClientHttpConnector must not be null");
return WebClientBuilder.builder().httpConnector(connector)
.endpointProvider(endpointProvider).build();
return WebClientBuilder.builder().httpConnector(connector).endpointProvider(endpointProvider).build();
}
/**
@@ -212,7 +198,6 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
* {@link VaultEndpointProvider} is used to contribute host and port details for
* relative URLs typically used by the Template API. Subclasses may override this
* method to customize the {@link WebClient}.
*
* @param endpointProvider must not be {@literal null}.
* @param connector must not be {@literal null}.
* @return the {@link WebClient} used for Vault communication.
@@ -226,19 +211,18 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
ExchangeFilterFunction filter = getSessionFilter();
return WebClientBuilder.builder().httpConnector(connector)
.endpointProvider(endpointProvider).filter(filter).build();
return WebClientBuilder.builder().httpConnector(connector).endpointProvider(endpointProvider).filter(filter)
.build();
}
private ExchangeFilterFunction getSessionFilter() {
return ofRequestProcessor(
request -> vaultTokenSupplier.getVaultToken().map(token -> {
return ofRequestProcessor(request -> this.vaultTokenSupplier.getVaultToken().map(token -> {
return ClientRequest.from(request).headers(headers -> {
headers.set(VaultHttpHeaders.VAULT_TOKEN, token.getToken());
}).build();
}));
return ClientRequest.from(request).headers(headers -> {
headers.set(VaultHttpHeaders.VAULT_TOKEN, token.getToken());
}).build();
}));
}
@Override
@@ -254,11 +238,9 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
return doWithSession(webClient -> {
ParameterizedTypeReference<VaultResponseSupport<T>> ref = VaultResponses
.getTypeReference(responseType);
ParameterizedTypeReference<VaultResponseSupport<T>> ref = VaultResponses.getTypeReference(responseType);
return webClient.get().uri(path).exchange()
.flatMap(mapResponse(ref, path, HttpMethod.GET));
return webClient.get().uri(path).exchange().flatMap(mapResponse(ref, path, HttpMethod.GET));
});
}
@@ -268,15 +250,11 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
Assert.hasText(path, "Path must not be empty");
Mono<VaultListResponse> read = doRead(
String.format("%s?list=true", path.endsWith("/") ? path : (path + "/")),
Mono<VaultListResponse> read = doRead(String.format("%s?list=true", path.endsWith("/") ? path : (path + "/")),
VaultListResponse.class);
return read
.filter(response -> response.getData() != null
&& response.getData().containsKey("keys"))
.flatMapIterable(response -> (List<String>) response.getRequiredData()
.get("keys"));
return read.filter(response -> response.getData() != null && response.getData().containsKey("keys"))
.flatMapIterable(response -> (List<String>) response.getRequiredData().get("keys"));
}
@Override
@@ -294,8 +272,7 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
else {
exchange = uri.exchange();
}
return exchange
.flatMap(mapResponse(VaultResponse.class, path, HttpMethod.POST));
return exchange.flatMap(mapResponse(VaultResponse.class, path, HttpMethod.POST));
});
}
@@ -309,14 +286,13 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
}
@Override
public <V, T extends Publisher<V>> T doWithVault(
Function<WebClient, ? extends T> clientCallback)
public <V, T extends Publisher<V>> T doWithVault(Function<WebClient, ? extends T> clientCallback)
throws VaultException, WebClientException {
Assert.notNull(clientCallback, "Client callback must not be null");
try {
return (T) clientCallback.apply(statelessClient);
return (T) clientCallback.apply(this.statelessClient);
}
catch (HttpStatusCodeException e) {
throw VaultResponses.buildException(e);
@@ -324,14 +300,13 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
}
@Override
public <V, T extends Publisher<V>> T doWithSession(
Function<WebClient, ? extends T> sessionCallback)
public <V, T extends Publisher<V>> T doWithSession(Function<WebClient, ? extends T> sessionCallback)
throws VaultException, WebClientException {
Assert.notNull(sessionCallback, "Session callback must not be null");
try {
return (T) sessionCallback.apply(sessionClient);
return (T) sessionCallback.apply(this.sessionClient);
}
catch (HttpStatusCodeException e) {
throw VaultResponses.buildException(e);
@@ -341,21 +316,18 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
private <T> Mono<T> doRead(String path, Class<T> responseType) {
return doWithSession(client -> client.get() //
.uri(path).exchange()
.flatMap(mapResponse(responseType, path, HttpMethod.GET)));
.uri(path).exchange().flatMap(mapResponse(responseType, path, HttpMethod.GET)));
}
private static <T> Function<ClientResponse, Mono<? extends T>> mapResponse(
Class<T> bodyType, String path, HttpMethod method) {
return response -> isSuccess(response) ? response.bodyToMono(bodyType)
: mapOtherwise(response, path, method);
private static <T> Function<ClientResponse, Mono<? extends T>> mapResponse(Class<T> bodyType, String path,
HttpMethod method) {
return response -> isSuccess(response) ? response.bodyToMono(bodyType) : mapOtherwise(response, path, method);
}
private static <T> Function<ClientResponse, Mono<? extends T>> mapResponse(
ParameterizedTypeReference<T> typeReference, String path, HttpMethod method) {
return response -> isSuccess(response)
? response.body(BodyExtractors.toMono(typeReference))
return response -> isSuccess(response) ? response.body(BodyExtractors.toMono(typeReference))
: mapOtherwise(response, path, method);
}
@@ -363,8 +335,7 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
return response.statusCode().is2xxSuccessful();
}
private static <T> Mono<? extends T> mapOtherwise(ClientResponse response,
String path, HttpMethod method) {
private static <T> Mono<? extends T> mapOtherwise(ClientResponse response, String path, HttpMethod method) {
if (response.statusCode() == HttpStatus.NOT_FOUND && method == HttpMethod.GET) {
return Mono.empty();
@@ -374,22 +345,23 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
String error = VaultResponses.getError(body);
return Mono.error(
VaultResponses.buildException(response.statusCode(), path, error));
return Mono.error(VaultResponses.buildException(response.statusCode(), path, error));
});
}
private static class VaultListResponse
extends VaultResponseSupport<Map<String, Object>> {
private static class VaultListResponse extends VaultResponseSupport<Map<String, Object>> {
}
private enum NoTokenSupplier implements VaultTokenSupplier {
INSTANCE;
@Override
public Mono<VaultToken> getVaultToken() {
return Mono
.error(new UnsupportedOperationException("Token retrieval disabled"));
return Mono.error(new UnsupportedOperationException("Token retrieval disabled"));
}
}
}

Some files were not shown because too many files have changed in this diff Show More