Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import org.apache.knox.gateway.audit.api.Auditor;
import org.apache.knox.gateway.audit.api.ResourceType;
import org.apache.knox.gateway.audit.log4j.audit.AuditConstants;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.filter.AbstractGatewayFilter;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.provider.federation.jwt.JWTMessages;
Expand All @@ -59,6 +58,7 @@
import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
import org.apache.knox.gateway.services.security.token.TokenServiceException;
import org.apache.knox.gateway.services.security.token.TokenStateService;
import org.apache.knox.gateway.services.security.token.TokenUtils;
import org.apache.knox.gateway.services.security.token.UnknownTokenException;
import org.apache.knox.gateway.services.security.token.impl.JWT;

Expand Down Expand Up @@ -113,35 +113,13 @@ public void init( FilterConfig filterConfig ) throws ServletException {
GatewayServices services = (GatewayServices) context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
if (services != null) {
authority = services.getService(ServiceType.TOKEN_SERVICE);
if (isServerManagedTokenStateEnabled(filterConfig)) {
if (TokenUtils.isServerManagedTokenStateEnabled(filterConfig)) {
tokenStateService = services.getService(ServiceType.TOKEN_STATE_SERVICE);
}
}
}
}

protected boolean isServerManagedTokenStateEnabled(FilterConfig filterConfig) {
boolean isServerManaged = false;

// First, check for explicit provider-level configuration
String providerParamValue = filterConfig.getInitParameter(TokenStateService.CONFIG_SERVER_MANAGED);

// If there is no provider-level configuration
if (providerParamValue == null || providerParamValue.isEmpty()) {
// Fall back to the gateway-level default
ServletContext context = filterConfig.getServletContext();
if (context != null) {
GatewayConfig config = (GatewayConfig) context.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
isServerManaged = (config != null) && config.isServerManagedTokenStateEnabled();
}
} else {
// Otherwise, apply the provider-level configuration
isServerManaged = Boolean.valueOf(providerParamValue);
}

return isServerManaged;
}

protected void configureExpectedParameters(FilterConfig filterConfig) {
expectedIssuer = filterConfig.getInitParameter(JWT_EXPECTED_ISSUER);
if (expectedIssuer == null) {
Expand Down Expand Up @@ -171,7 +149,7 @@ protected List<String> parseExpectedAudiences(String expectedAudiences) {
protected boolean tokenIsStillValid(JWT jwtToken) throws UnknownTokenException {
Date expires;
if (tokenStateService != null) {
expires = new Date(tokenStateService.getTokenExpiration(jwtToken.toString()));
expires = new Date(tokenStateService.getTokenExpiration(jwtToken));
} else {
// if there is no expiration date then the lifecycle is tied entirely to
// the cookie validity - otherwise ensure that the current time is before
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
import org.apache.knox.gateway.services.security.token.TokenServiceException;
import org.apache.knox.gateway.services.security.token.TokenStateService;
import org.apache.knox.gateway.services.security.token.TokenUtils;
import org.apache.knox.gateway.services.security.token.UnknownTokenException;
import org.apache.knox.gateway.services.security.token.impl.JWTToken;

Expand Down Expand Up @@ -59,7 +60,7 @@ public void init( FilterConfig filterConfig ) throws ServletException {
GatewayServices services = (GatewayServices) filterConfig.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
authority = services.getService(ServiceType.TOKEN_SERVICE);

if (Boolean.valueOf(filterConfig.getInitParameter(TokenStateService.CONFIG_SERVER_MANAGED))) {
if (TokenUtils.isServerManagedTokenStateEnabled(filterConfig)) {
tokenStateService = services.getService(ServiceType.TOKEN_STATE_SERVICE);
}
}
Expand Down Expand Up @@ -117,14 +118,18 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
}

private boolean isExpired(JWTToken token) throws UnknownTokenException {
return (tokenStateService != null) ? tokenStateService.isExpired(token.toString()) : (Long.parseLong(token.getExpires()) <= System.currentTimeMillis());
return (tokenStateService != null) ? tokenStateService.isExpired(token)
: (Long.parseLong(token.getExpires()) <= System.currentTimeMillis());
}

private void sendUnauthorized(ServletResponse response) throws IOException {
((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
}

private void continueWithEstablishedSecurityContext(Subject subject, final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) throws IOException, ServletException {
private void continueWithEstablishedSecurityContext(Subject subject,
final HttpServletRequest request,
final HttpServletResponse response,
final FilterChain chain) throws IOException, ServletException {
try {
Subject.doAs(
subject,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.provider.federation.jwt.filter.AbstractJWTFilter;
import org.apache.knox.gateway.services.security.token.TokenStateService;
import org.apache.knox.gateway.services.security.token.TokenUtils;
import org.apache.knox.gateway.services.security.token.UnknownTokenException;
import org.apache.knox.gateway.services.security.token.impl.JWT;
import org.easymock.EasyMock;
Expand Down Expand Up @@ -109,9 +110,7 @@ private boolean doTestServerManagedTokenState(final Boolean isEnabledAtGateway,
EasyMock.expect(fc.getServletContext()).andReturn(sc).anyTimes();
EasyMock.replay(fc);

Method m = AbstractJWTFilter.class.getDeclaredMethod("isServerManagedTokenStateEnabled", FilterConfig.class);
m.setAccessible(true);
return (Boolean) m.invoke(handler, fc);
return TokenUtils.isServerManagedTokenStateEnabled(fc);
}

@Test
Expand All @@ -129,7 +128,7 @@ public void testIsStillValidExpired() throws Exception {
@Test(expected = UnknownTokenException.class)
public void testIsStillValidUnknownToken() throws Exception {
TokenStateService tss = EasyMock.createNiceMock(TokenStateService.class);
EasyMock.expect(tss.getTokenExpiration(anyObject()))
EasyMock.expect(tss.getTokenExpiration(anyObject(JWT.class)))
.andThrow(new UnknownTokenException("eyjhbgcioi1234567890neg"))
.anyTimes();
EasyMock.replay(tss);
Expand All @@ -139,7 +138,7 @@ public void testIsStillValidUnknownToken() throws Exception {

private boolean doTestIsStillValid(final Long expiration) throws Exception {
TokenStateService tss = EasyMock.createNiceMock(TokenStateService.class);
EasyMock.expect(tss.getTokenExpiration(anyObject()))
EasyMock.expect(tss.getTokenExpiration(anyObject(JWT.class)))
.andReturn(expiration)
.anyTimes();
EasyMock.replay(tss);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import org.apache.knox.gateway.services.ServiceLifecycleException;
import org.apache.knox.gateway.services.security.AliasService;
import org.apache.knox.gateway.services.security.AliasServiceException;
import org.apache.knox.gateway.services.security.token.TokenUtils;
import org.apache.knox.gateway.services.security.token.UnknownTokenException;

import java.util.ArrayList;
Expand Down Expand Up @@ -49,120 +48,102 @@ public void init(final GatewayConfig config, final Map<String, String> options)
}

@Override
public void addToken(final String token,
long issueTime,
long expiration,
long maxLifetimeDuration) {
isValidIdentifier(token);
public void addToken(final String tokenId,
long issueTime,
long expiration,
long maxLifetimeDuration) {
isValidIdentifier(tokenId);
try {
aliasService.addAliasForCluster(AliasService.NO_CLUSTER_NAME, token, String.valueOf(expiration));
setMaxLifetime(token, issueTime, maxLifetimeDuration);
log.addedToken(TokenUtils.getTokenDisplayText(token), getTimestampDisplay(expiration));
aliasService.addAliasForCluster(AliasService.NO_CLUSTER_NAME, tokenId, String.valueOf(expiration));
setMaxLifetime(tokenId, issueTime, maxLifetimeDuration);
log.addedToken(tokenId, getTimestampDisplay(expiration));
} catch (AliasServiceException e) {
log.failedToSaveTokenState(TokenUtils.getTokenDisplayText(token), e);
log.failedToSaveTokenState(tokenId, e);
}
}

@Override
protected void setMaxLifetime(final String token, long issueTime, long maxLifetimeDuration) {
protected void setMaxLifetime(final String tokenId, long issueTime, long maxLifetimeDuration) {
try {
aliasService.addAliasForCluster(AliasService.NO_CLUSTER_NAME,
token + TOKEN_MAX_LIFETIME_POSTFIX,
tokenId + TOKEN_MAX_LIFETIME_POSTFIX,
String.valueOf(issueTime + maxLifetimeDuration));
} catch (AliasServiceException e) {
log.failedToSaveTokenState(TokenUtils.getTokenDisplayText(token), e);
log.failedToSaveTokenState(tokenId, e);
}
}

@Override
protected long getMaxLifetime(final String token) {
protected long getMaxLifetime(final String tokenId) {
long result = 0;
try {
char[] maxLifetimeStr =
aliasService.getPasswordFromAliasForCluster(AliasService.NO_CLUSTER_NAME, token + TOKEN_MAX_LIFETIME_POSTFIX);
aliasService.getPasswordFromAliasForCluster(AliasService.NO_CLUSTER_NAME,
tokenId + TOKEN_MAX_LIFETIME_POSTFIX);
if (maxLifetimeStr != null) {
result = Long.parseLong(new String(maxLifetimeStr));
}
} catch (AliasServiceException e) {
log.errorAccessingTokenState(TokenUtils.getTokenDisplayText(token), e);
log.errorAccessingTokenState(tokenId, e);
}
return result;
}

@Override
public long getTokenExpiration(final String token) throws UnknownTokenException {
public long getTokenExpiration(final String tokenId) throws UnknownTokenException {
long expiration = 0;

validateToken(tokenId);

try {
validateToken(token);
} catch (final UnknownTokenException e) {
/* if token permissiveness is enabled we check JWT token expiration when the token state is unknown */
if (permissiveValidationEnabled && getJWTTokenExpiration(token).isPresent()) {
return getJWTTokenExpiration(token).getAsLong();
} else {
throw e;
}
}
try {
char[] expStr = aliasService.getPasswordFromAliasForCluster(AliasService.NO_CLUSTER_NAME, token);
char[] expStr = aliasService.getPasswordFromAliasForCluster(AliasService.NO_CLUSTER_NAME, tokenId);
if (expStr != null) {
expiration = Long.parseLong(new String(expStr));
}
} catch (Exception e) {
log.errorAccessingTokenState(TokenUtils.getTokenDisplayText(token), e);
log.errorAccessingTokenState(tokenId, e);
}

return expiration;
}

@Override
public void revokeToken(final String token) throws UnknownTokenException {
/* no reason to keep revoked tokens around */
removeToken(token);
log.revokedToken(TokenUtils.getTokenDisplayText(token));
}

@Override
protected boolean isUnknown(final String token) {
protected boolean isUnknown(final String tokenId) {
boolean isUnknown = false;
try {
isUnknown = (aliasService.getPasswordFromAliasForCluster(AliasService.NO_CLUSTER_NAME, token) == null);
isUnknown = (aliasService.getPasswordFromAliasForCluster(AliasService.NO_CLUSTER_NAME, tokenId) == null);
} catch (AliasServiceException e) {
log.errorAccessingTokenState(TokenUtils.getTokenDisplayText(token), e);
log.errorAccessingTokenState(tokenId, e);
}
return isUnknown;
}

@Override
protected void removeToken(final String token) throws UnknownTokenException {
validateToken(token);
protected void removeToken(final String tokenId) throws UnknownTokenException {
validateToken(tokenId);

try {
aliasService.removeAliasForCluster(AliasService.NO_CLUSTER_NAME, token);
aliasService.removeAliasForCluster(AliasService.NO_CLUSTER_NAME,token + TOKEN_MAX_LIFETIME_POSTFIX);
log.removedTokenState(TokenUtils.getTokenDisplayText(token));
aliasService.removeAliasForCluster(AliasService.NO_CLUSTER_NAME, tokenId);
aliasService.removeAliasForCluster(AliasService.NO_CLUSTER_NAME, tokenId + TOKEN_MAX_LIFETIME_POSTFIX);
log.removedTokenState(tokenId);
} catch (AliasServiceException e) {
log.failedToRemoveTokenState(TokenUtils.getTokenDisplayText(token), e);
log.failedToRemoveTokenState(tokenId, e);
}
}

@Override
protected void updateExpiration(final String token, long expiration) {
if (isUnknown(token)) {
log.unknownToken(TokenUtils.getTokenDisplayText(token));
throw new IllegalArgumentException("Unknown token.");
}

protected void updateExpiration(final String tokenId, long expiration) {
try {
aliasService.removeAliasForCluster(AliasService.NO_CLUSTER_NAME, token);
aliasService.addAliasForCluster(AliasService.NO_CLUSTER_NAME, token, String.valueOf(expiration));
aliasService.removeAliasForCluster(AliasService.NO_CLUSTER_NAME, tokenId);
aliasService.addAliasForCluster(AliasService.NO_CLUSTER_NAME, tokenId, String.valueOf(expiration));
} catch (AliasServiceException e) {
log.failedToUpdateTokenExpiration(TokenUtils.getTokenDisplayText(token), e);
log.failedToUpdateTokenExpiration(tokenId, e);
}
}

@Override
protected List<String> getTokens() {
List<String> allAliases = new ArrayList();
List<String> allAliases = new ArrayList<>();
try {
allAliases = aliasService.getAliasesForCluster(AliasService.NO_CLUSTER_NAME);
/* only get the aliases that represent tokens and extract the current list of tokens */
Expand Down
Loading