This is an automated email from the ASF dual-hosted git repository.
pzampino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new 9ee06f3 KNOX-2396 - TokenResource Renew and Revoke Should Respond
With Error Codes That Identify Specific Errors (#480)
9ee06f3 is described below
commit 9ee06f3b6b0695afbeb02fe133871ec66600cd0b
Author: Attila Magyar <[email protected]>
AuthorDate: Wed Aug 25 05:55:36 2021 +0200
KNOX-2396 - TokenResource Renew and Revoke Should Respond With Error Codes
That Identify Specific Errors (#480)
---
.../gateway/service/knoxtoken/TokenResource.java | 43 ++++++++++++++++++++--
.../knoxtoken/TokenServiceResourceTest.java | 36 +++++++++++-------
2 files changed, 62 insertions(+), 17 deletions(-)
diff --git
a/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
b/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
index 244cbe9..7bc84e4 100644
---
a/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
+++
b/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
@@ -155,6 +155,27 @@ public class TokenResource {
@Context
ServletContext context;
+ public enum ErrorCode {
+ UNKNOWN(0),
+ CONFIGURATION_ERROR(10),
+ UNAUTHORIZED(20),
+ INTERNAL_ERROR(30),
+ INVALID_TOKEN(40),
+ UNKNOWN_TOKEN(50),
+ ALREADY_DISABLED(60),
+ ALREADY_ENABLED(70);
+
+ private final int code;
+
+ ErrorCode(int code) {
+ this.code = code;
+ }
+
+ public int toInt() {
+ return code;
+ }
+ }
+
@PostConstruct
public void init() throws AliasServiceException, ServiceLifecycleException,
KeyLengthException {
@@ -393,6 +414,7 @@ public class TokenResource {
long expiration = 0;
String error = "";
+ ErrorCode errorCode = ErrorCode.UNKNOWN;
Response.Status errorStatus = Response.Status.BAD_REQUEST;
if (tokenStateService == null) {
@@ -406,8 +428,10 @@ public class TokenResource {
} catch (ParseException e) {
log.invalidToken(getTopologyName(), Tokens.getTokenDisplayText(token),
e);
error = safeGetMessage(e);
+ errorCode = ErrorCode.INVALID_TOKEN;
} catch (Exception e) {
error = safeGetMessage(e);
+ errorCode = ErrorCode.INTERNAL_ERROR;
}
} else {
String renewer = SubjectUtils.getCurrentEffectivePrincipalName();
@@ -423,13 +447,16 @@ public class TokenResource {
renewer);
} catch (ParseException e) {
log.invalidToken(getTopologyName(),
Tokens.getTokenDisplayText(token), e);
+ errorCode = ErrorCode.INVALID_TOKEN;
error = safeGetMessage(e);
} catch (Exception e) {
error = safeGetMessage(e);
+ errorCode = ErrorCode.INTERNAL_ERROR;
}
} else {
errorStatus = Response.Status.FORBIDDEN;
error = "Caller (" + renewer + ") not authorized to renew tokens.";
+ errorCode = ErrorCode.UNAUTHORIZED;
}
}
@@ -440,7 +467,7 @@ public class TokenResource {
} else {
log.badRenewalRequest(getTopologyName(),
Tokens.getTokenDisplayText(token), error);
resp = Response.status(errorStatus)
- .entity("{\n \"renewed\": \"false\",\n \"error\": \"" +
error + "\"\n}\n")
+ .entity("{\n \"renewed\": \"false\",\n \"error\": \"" +
error + "\",\n \"code\": " + errorCode.toInt() + "\n}\n")
.build();
}
@@ -454,10 +481,12 @@ public class TokenResource {
Response resp;
String error = "";
+ ErrorCode errorCode = ErrorCode.UNKNOWN;
Response.Status errorStatus = Response.Status.BAD_REQUEST;
if (tokenStateService == null) {
error = "Token revocation support is not configured";
+ errorCode = ErrorCode.CONFIGURATION_ERROR;
} else {
String renewer = SubjectUtils.getCurrentEffectivePrincipalName();
if (allowedRenewers.contains(renewer)) {
@@ -471,12 +500,15 @@ public class TokenResource {
} catch (ParseException e) {
log.invalidToken(getTopologyName(),
Tokens.getTokenDisplayText(token), e);
error = safeGetMessage(e);
+ errorCode = ErrorCode.INVALID_TOKEN;
} catch (UnknownTokenException e) {
error = safeGetMessage(e);
+ errorCode = ErrorCode.UNKNOWN_TOKEN;
}
} else {
errorStatus = Response.Status.FORBIDDEN;
error = "Caller (" + renewer + ") not authorized to revoke tokens.";
+ errorCode = ErrorCode.UNAUTHORIZED;
}
}
@@ -487,7 +519,7 @@ public class TokenResource {
} else {
log.badRevocationRequest(getTopologyName(),
Tokens.getTokenDisplayText(token), error);
resp = Response.status(errorStatus)
- .entity("{\n \"revoked\": \"false\",\n \"error\": \"" +
error + "\"\n}\n")
+ .entity("{\n \"revoked\": \"false\",\n \"error\": \"" +
error + "\",\n \"code\": " + errorCode.toInt() + "\n}\n")
.build();
}
@@ -526,28 +558,33 @@ public class TokenResource {
private Response setTokenEnabledFlag(String tokenId, boolean enabled) {
String error = "";
+ ErrorCode errorCode = ErrorCode.UNKNOWN;
if (tokenStateService == null) {
error = "Unable to " + (enabled ? "enable" : "disable") + " tokens
because token management is not configured";
+ errorCode = ErrorCode.CONFIGURATION_ERROR;
} else {
try {
final TokenMetadata tokenMetadata =
tokenStateService.getTokenMetadata(tokenId);
if (enabled && tokenMetadata.isEnabled()) {
error = "Token is already enabled";
+ errorCode = ErrorCode.ALREADY_ENABLED;
} else if (!enabled && !tokenMetadata.isEnabled()) {
error = "Token is already disabled";
+ errorCode = ErrorCode.ALREADY_DISABLED;
} else {
tokenMetadata.setEnabled(enabled);
tokenStateService.addMetadata(tokenId, tokenMetadata);
}
} catch (UnknownTokenException e) {
error = safeGetMessage(e);
+ errorCode = ErrorCode.UNKNOWN_TOKEN;
}
}
if (error.isEmpty()) {
return Response.status(Response.Status.OK).entity("{\n
\"setEnabledFlag\": \"true\",\n \"isEnabled\": \"" + enabled +
"\"\n}\n").build();
} else {
log.badSetEnabledFlagRequest(getTopologyName(),
Tokens.getTokenIDDisplayText(tokenId), error);
- return Response.status(Response.Status.BAD_REQUEST).entity("{\n
\"setEnabledFlag\": \"false\",\n \"error\": \"" + error + "\"\n}\n").build();
+ return Response.status(Response.Status.BAD_REQUEST).entity("{\n
\"setEnabledFlag\": \"false\",\n \"error\": \"" + error + "\",\n \"code\": "
+ errorCode.toInt() + "\n}\n").build();
}
}
diff --git
a/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/TokenServiceResourceTest.java
b/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/TokenServiceResourceTest.java
index 0069212..a0fded1 100644
---
a/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/TokenServiceResourceTest.java
+++
b/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/TokenServiceResourceTest.java
@@ -684,7 +684,7 @@ public class TokenServiceResourceTest {
@Test
public void testTokenRenewal_Enabled_NoRenewersNoSubject() throws Exception {
Response renewalResponse = doTestTokenRenewal(true, null, null);
- validateRenewalResponse(renewalResponse, 403, false, "Caller (null) not
authorized to renew tokens.");
+ validateRenewalResponse(renewalResponse, 403, false, "Caller (null) not
authorized to renew tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
}
@Test
@@ -694,7 +694,7 @@ public class TokenServiceResourceTest {
validateRenewalResponse(renewalResponse,
403,
false,
- "Caller (" + caller + ") not authorized to renew
tokens.");
+ "Caller (" + caller + ") not authorized to renew
tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
}
@Test
@@ -703,7 +703,7 @@ public class TokenServiceResourceTest {
validateRenewalResponse(renewalResponse,
403,
false,
- "Caller (null) not authorized to renew tokens.");
+ "Caller (null) not authorized to renew tokens.",
TokenResource.ErrorCode.UNAUTHORIZED);
}
@Test
@@ -713,7 +713,7 @@ public class TokenServiceResourceTest {
validateRenewalResponse(renewalResponse,
403,
false,
- "Caller (" + caller + ") not authorized to renew
tokens.");
+ "Caller (" + caller + ") not authorized to renew
tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
}
@Test
@@ -764,7 +764,7 @@ public class TokenServiceResourceTest {
validateRevocationResponse(renewalResponse,
400,
false,
- "Token revocation support is not configured");
+ "Token revocation support is not configured",
TokenResource.ErrorCode.CONFIGURATION_ERROR);
}
@Test
@@ -773,7 +773,7 @@ public class TokenServiceResourceTest {
validateRevocationResponse(renewalResponse,
400,
false,
- "Token revocation support is not configured");
+ "Token revocation support is not configured",
TokenResource.ErrorCode.CONFIGURATION_ERROR);
}
@Test
@@ -782,7 +782,7 @@ public class TokenServiceResourceTest {
validateRevocationResponse(renewalResponse,
403,
false,
- "Caller (null) not authorized to revoke
tokens.");
+ "Caller (null) not authorized to revoke
tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
}
@Test
@@ -792,7 +792,7 @@ public class TokenServiceResourceTest {
validateRevocationResponse(renewalResponse,
403,
false,
- "Caller (" + caller + ") not authorized to
revoke tokens.");
+ "Caller (" + caller + ") not authorized to
revoke tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
}
@Test
@@ -801,7 +801,7 @@ public class TokenServiceResourceTest {
validateRevocationResponse(renewalResponse,
403,
false,
- "Caller (null) not authorized to revoke
tokens.");
+ "Caller (null) not authorized to revoke
tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
}
@Test
@@ -811,7 +811,7 @@ public class TokenServiceResourceTest {
validateRevocationResponse(renewalResponse,
403,
false,
- "Caller (" + caller + ") not authorized to
revoke tokens.");
+ "Caller (" + caller + ") not authorized to
revoke tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
}
@Test
@@ -1220,13 +1220,14 @@ public class TokenServiceResourceTest {
}
private static void validateSuccessfulRenewalResponse(final Response
response) throws IOException {
- validateRenewalResponse(response, 200, true, null);
+ validateRenewalResponse(response, 200, true, null, null);
}
private static void validateRenewalResponse(final Response response,
final int
expectedStatusCode,
final boolean expectedResult,
- final String expectedMessage)
throws IOException {
+ final String expectedMessage,
+ final TokenResource.ErrorCode
expectedCode) throws IOException {
assertEquals(expectedStatusCode, response.getStatus());
assertTrue(response.hasEntity());
String responseContent = (String) response.getEntity();
@@ -1236,16 +1237,20 @@ public class TokenServiceResourceTest {
boolean result = Boolean.valueOf(json.get("renewed"));
assertEquals(expectedResult, result);
assertEquals(expectedMessage, json.get("error"));
+ if (expectedCode != null) {
+ assertEquals(expectedCode.toInt(), Integer.parseInt(json.get("code")));
+ }
}
private static void validateSuccessfulRevocationResponse(final Response
response) throws IOException {
- validateRevocationResponse(response, 200, true, null);
+ validateRevocationResponse(response, 200, true, null, null);
}
private static void validateRevocationResponse(final Response response,
final int
expectedStatusCode,
final boolean expectedResult,
- final String
expectedMessage) throws IOException {
+ final String
expectedMessage,
+ final TokenResource.ErrorCode
expectedCode) throws IOException {
assertEquals(expectedStatusCode, response.getStatus());
assertTrue(response.hasEntity());
String responseContent = (String) response.getEntity();
@@ -1255,6 +1260,9 @@ public class TokenServiceResourceTest {
boolean result = Boolean.valueOf(json.get("revoked"));
assertEquals(expectedResult, result);
assertEquals(expectedMessage, json.get("error"));
+ if (expectedCode != null) {
+ assertEquals(expectedCode.toInt(), Integer.parseInt(json.get("code")));
+ }
}