Introduce VaultLoginException.
We now throw a more specific exception (VaultLoginException) in cases login fails. Exception creation considers HTTP and other causes extracting relevant details and pulls this into a single method rather than spreading message construction in various places. See gh-203.
This commit is contained in:
@@ -22,11 +22,9 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
/**
|
||||
@@ -111,9 +109,8 @@ public class AppIdAuthentication implements ClientAuthentication,
|
||||
|
||||
return LoginTokenUtil.from(response.getAuth());
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format("Cannot login using app-id: %s",
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
catch (RestClientException e) {
|
||||
throw VaultLoginException.create("app-id", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.authentication.AppRoleAuthenticationOptions.RoleId;
|
||||
import org.springframework.vault.authentication.AppRoleAuthenticationOptions.SecretId;
|
||||
import org.springframework.vault.authentication.AppRoleTokens.AbsentSecretId;
|
||||
@@ -40,6 +39,7 @@ import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
import static org.springframework.vault.authentication.AuthenticationSteps.HttpRequestBuilder.get;
|
||||
@@ -225,13 +225,12 @@ public class AppRoleAuthentication implements ClientAuthentication,
|
||||
|
||||
return LoginTokenUtil.from(response.getAuth());
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format("Cannot login using AppRole: %s",
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
catch (RestClientException e) {
|
||||
throw VaultLoginException.create("AppRole", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getRoleId(RoleId roleId) {
|
||||
private String getRoleId(RoleId roleId) throws VaultLoginException {
|
||||
|
||||
if (roleId instanceof Provided) {
|
||||
return ((Provided) roleId).getValue();
|
||||
@@ -250,9 +249,9 @@ public class AppRoleAuthentication implements ClientAuthentication,
|
||||
return (String) entity.getBody().getRequiredData().get("role_id");
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format(
|
||||
throw new VaultLoginException(String.format(
|
||||
"Cannot get Role id using AppRole: %s",
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
VaultResponses.getError(e.getResponseBodyAsString())), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,16 +272,16 @@ public class AppRoleAuthentication implements ClientAuthentication,
|
||||
return (String) response.getRequiredData().get("role_id");
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format(
|
||||
throw new VaultLoginException(String.format(
|
||||
"Cannot unwrap Role id using AppRole: %s",
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
VaultResponses.getError(e.getResponseBodyAsString())), e);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unknown RoleId configuration: " + roleId);
|
||||
}
|
||||
|
||||
private String getSecretId(SecretId secretId) {
|
||||
private String getSecretId(SecretId secretId) throws VaultLoginException {
|
||||
|
||||
if (secretId instanceof Provided) {
|
||||
return ((Provided) secretId).getValue();
|
||||
@@ -299,9 +298,9 @@ public class AppRoleAuthentication implements ClientAuthentication,
|
||||
return (String) response.getRequiredData().get("secret_id");
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format(
|
||||
throw new VaultLoginException(String.format(
|
||||
"Cannot get Secret id using AppRole: %s",
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
VaultResponses.getError(e.getResponseBodyAsString())), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,9 +321,9 @@ public class AppRoleAuthentication implements ClientAuthentication,
|
||||
return (String) response.getRequiredData().get("secret_id");
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format(
|
||||
throw new VaultLoginException(String.format(
|
||||
"Cannot unwrap Role id using AppRole: %s",
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
VaultResponses.getError(e.getResponseBodyAsString())), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,13 +104,13 @@ public class AuthenticationStepsExecutor implements ClientAuthentication {
|
||||
}
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format(
|
||||
throw new VaultLoginException(String.format(
|
||||
"HTTP request %s in state %s failed with Status %s and body %s",
|
||||
o, state, e.getStatusCode(),
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
VaultResponses.getError(e.getResponseBodyAsString())), e);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
throw new VaultException(String.format(
|
||||
throw new VaultLoginException(String.format(
|
||||
"Authentication execution failed in %s", o), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ public class AuthenticationStepsOperator implements VaultTokenSupplier {
|
||||
stateObject));
|
||||
})
|
||||
.onErrorMap(
|
||||
t -> new VaultException(
|
||||
t -> new VaultLoginException(
|
||||
"Cannot retrieve VaultToken from authentication chain", t));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,10 +28,8 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.authentication.AuthenticationSteps.HttpRequestBuilder;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
@@ -183,9 +181,8 @@ public class AwsEc2Authentication implements ClientAuthentication,
|
||||
|
||||
return LoginTokenUtil.from(response.getAuth());
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format("Cannot login using AWS-EC2: %s",
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
catch (RestClientException e) {
|
||||
throw VaultLoginException.create("AWS-EC2", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +210,7 @@ public class AwsEc2Authentication implements ClientAuthentication,
|
||||
return login;
|
||||
}
|
||||
catch (RestClientException e) {
|
||||
throw new VaultException(String.format(
|
||||
throw new VaultLoginException(String.format(
|
||||
"Cannot obtain Identity Document from %s",
|
||||
options.getIdentityDocumentUri()), e);
|
||||
}
|
||||
|
||||
@@ -36,10 +36,9 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
/**
|
||||
@@ -134,16 +133,15 @@ public class AwsIamAuthentication implements ClientAuthentication {
|
||||
|
||||
return LoginTokenUtil.from(response.getAuth());
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format("Cannot login using AWS-IAM: %s",
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
catch (RestClientException e) {
|
||||
throw VaultLoginException.create("AWS-IAM", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -21,11 +21,9 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
import static org.springframework.vault.authentication.AuthenticationSteps.HttpRequestBuilder.post;
|
||||
@@ -87,10 +85,8 @@ public class ClientCertificateAuthentication implements ClientAuthentication,
|
||||
|
||||
return LoginTokenUtil.from(response.getAuth());
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format(
|
||||
"Cannot login using TLS certificates: %s",
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
catch (RestClientException e) {
|
||||
throw VaultLoginException.create("TLS Certificates", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
import static org.springframework.vault.authentication.AuthenticationSteps.HttpRequestBuilder.get;
|
||||
@@ -222,10 +222,8 @@ public class CubbyholeAuthentication implements ClientAuthentication,
|
||||
|
||||
return entity.getBody().getData();
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format(
|
||||
"Cannot retrieve Token from Cubbyhole: %s %s", e.getStatusCode(),
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
catch (RestClientException e) {
|
||||
throw VaultLoginException.create("Cubbyhole", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +261,7 @@ public class CubbyholeAuthentication implements ClientAuthentication,
|
||||
}
|
||||
|
||||
if (data == null || data.isEmpty()) {
|
||||
throw new VaultException(
|
||||
throw new VaultLoginException(
|
||||
String.format(
|
||||
"Cannot retrieve Token from Cubbyhole: Response at %s does not contain a token",
|
||||
options.getPath()));
|
||||
@@ -274,7 +272,7 @@ public class CubbyholeAuthentication implements ClientAuthentication,
|
||||
return VaultToken.of(token);
|
||||
}
|
||||
|
||||
throw new VaultException(
|
||||
throw new VaultLoginException(
|
||||
String.format(
|
||||
"Cannot retrieve Token from Cubbyhole: Response at %s does not contain an unique token",
|
||||
options.getPath()));
|
||||
|
||||
@@ -153,7 +153,7 @@ public class GcpComputeAuthentication extends GcpJwtAuthenticationSupport implem
|
||||
return response.getBody();
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException("Cannot obtain signed identity", e);
|
||||
throw new VaultLoginException("Cannot obtain signed identity", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport implements
|
||||
return response.getSignedJwt();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VaultException("Cannot sign JWT", e);
|
||||
throw new VaultLoginException("Cannot sign JWT", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,9 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
/**
|
||||
@@ -89,10 +87,8 @@ public abstract class GcpJwtAuthenticationSupport {
|
||||
|
||||
return LoginTokenUtil.from(response.getAuth());
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format("Cannot login using %s: %s",
|
||||
authenticationName,
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
catch (RestClientException e) {
|
||||
throw VaultLoginException.create(authenticationName, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,9 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
/**
|
||||
@@ -104,9 +103,8 @@ public class KubernetesAuthentication implements ClientAuthentication,
|
||||
|
||||
return LoginTokenUtil.from(response.getAuth());
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw new VaultException(String.format("Cannot login using kubernetes: %s",
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
catch (RestClientException e) {
|
||||
throw VaultLoginException.create("Kubernetes", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
/**
|
||||
@@ -106,6 +107,9 @@ public class LoginTokenAdapter implements ClientAuthentication {
|
||||
"Token self-lookup failed: %s %s", e.getStatusCode(),
|
||||
VaultResponses.getError(e.getResponseBodyAsString())));
|
||||
}
|
||||
catch (RestClientException e) {
|
||||
throw new VaultTokenLookupException("Token self-lookup failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
static Duration getLeaseDuration(@Nullable Number ttl) {
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.vault.authentication.AuthenticationSteps.HttpRequest;
|
||||
import org.springframework.vault.client.VaultHttpHeaders;
|
||||
@@ -100,8 +97,4 @@ public class TokenAuthentication implements ClientAuthentication,
|
||||
public AuthenticationSteps getAuthenticationSteps() {
|
||||
return createAuthenticationSteps(this.token, false);
|
||||
}
|
||||
|
||||
private static Duration getLeaseDuration(@Nullable Number ttl) {
|
||||
return ttl == null ? Duration.ZERO : Duration.ofSeconds(ttl.longValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.vault.authentication;
|
||||
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.web.client.RestClientResponseException;
|
||||
|
||||
/**
|
||||
* Exception thrown if Vault login fails. The root cause is typically attached as cause.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.1
|
||||
*/
|
||||
public class VaultLoginException extends VaultException {
|
||||
|
||||
/**
|
||||
* Create a {@code VaultLoginException} with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public VaultLoginException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code VaultLoginException} with the specified detail message and nested
|
||||
* exception.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param cause the nested exception.
|
||||
*/
|
||||
public VaultLoginException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
*/
|
||||
public static VaultLoginException create(String authMethod, Throwable cause) {
|
||||
|
||||
if (cause instanceof RestClientResponseException) {
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,23 @@ import org.springframework.vault.VaultException;
|
||||
public class VaultTokenLookupException extends VaultException {
|
||||
|
||||
/**
|
||||
* Create a {@code VaultException} with the specified detail message.
|
||||
* Create a {@code VaultTokenLookupException} with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public VaultTokenLookupException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public VaultTokenLookupException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ public class AuthenticationStepsExecutorUnitTests {
|
||||
|
||||
assertThatExceptionOfType(VaultException.class)
|
||||
.isThrownBy(() -> login(steps))
|
||||
.withMessage(
|
||||
.withMessageContaining(
|
||||
"HTTP request POST /auth/{path}/login AS class org.springframework.vault.support.VaultResponse "
|
||||
+ "in state null failed with Status 400 and body foo");
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class CubbyholeAuthenticationIntegrationTests extends
|
||||
fail("Missing VaultException");
|
||||
}
|
||||
catch (VaultException e) {
|
||||
assertThat(e).hasMessageContaining("Cannot retrieve Token from Cubbyhole")
|
||||
assertThat(e).hasMessageContaining("Cannot login using Cubbyhole")
|
||||
.hasMessageContaining("permission denied");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user