You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by sm...@apache.org on 2021/06/10 11:27:31 UTC
[knox] branch master updated: KNOX-2620 - Using the proper
signature algorithm name in JWKS endpoint (#457)
This is an automated email from the ASF dual-hosted git repository.
smolnar 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 ec66f35 KNOX-2620 - Using the proper signature algorithm name in JWKS endpoint (#457)
ec66f35 is described below
commit ec66f35ae3619afee6b86b4c254e163a8d5328bc
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Thu Jun 10 13:27:21 2021 +0200
KNOX-2620 - Using the proper signature algorithm name in JWKS endpoint (#457)
---
.../gateway/service/knoxtoken/JWKSResource.java | 21 ++--
.../service/knoxtoken/JWKSResourceTest.java | 109 ++++++++++++---------
2 files changed, 74 insertions(+), 56 deletions(-)
diff --git a/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/JWKSResource.java b/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/JWKSResource.java
index 0477dd4..0fba2c2 100644
--- a/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/JWKSResource.java
+++ b/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/JWKSResource.java
@@ -25,6 +25,8 @@ import com.nimbusds.jose.jwk.RSAKey;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.services.GatewayServices;
import org.apache.knox.gateway.services.ServiceType;
+import org.apache.knox.gateway.services.security.AliasService;
+import org.apache.knox.gateway.services.security.AliasServiceException;
import org.apache.knox.gateway.services.security.KeystoreService;
import org.apache.knox.gateway.services.security.KeystoreServiceException;
import org.apache.knox.gateway.services.security.token.TokenUtils;
@@ -50,18 +52,23 @@ import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
public class JWKSResource {
public static final String JWKS_PATH = "/jwks.json";
static final String RESOURCE_PATH = "knoxtoken/api/v1";
+ private static final String TOKEN_SIG_ALG = "knox.token.sigalg";
@Context
HttpServletRequest request;
@Context
ServletContext context;
private KeystoreService keystoreService;
+ private String signatureAlgorithm;
@PostConstruct
- public void init() {
- final GatewayServices services = (GatewayServices) context
- .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+ public void init() throws AliasServiceException {
+ final GatewayServices services = (GatewayServices) context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
keystoreService = services.getService(ServiceType.KEYSTORE_SERVICE);
+
+ final String configuredSigAlg = context.getInitParameter(TOKEN_SIG_ALG);
+ final GatewayConfig config = (GatewayConfig) context.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+ this.signatureAlgorithm = TokenUtils.getSignatureAlgorithm(configuredSigAlg, (AliasService) services.getService(ServiceType.ALIAS_SERVICE), config.getSigningKeystoreName());
}
@GET
@@ -84,7 +91,7 @@ public class JWKSResource {
final String kid = TokenUtils.getThumbprint(rsa, "SHA-256");
final RSAKey.Builder builder = new RSAKey.Builder(rsa)
.keyUse(KeyUse.SIGNATURE)
- .algorithm(new JWSAlgorithm(rsa.getAlgorithm()))
+ .algorithm(new JWSAlgorithm(this.signatureAlgorithm))
.keyID(kid);
jwks = new JWKSet(builder.build());
@@ -101,16 +108,14 @@ public class JWKSResource {
.entity(jwks.toJSONObject().toString()).build();
}
- protected RSAPublicKey getPublicKey(final String keystore)
- throws KeystoreServiceException, KeyStoreException {
+ protected RSAPublicKey getPublicKey(final String keystore) throws KeystoreServiceException, KeyStoreException {
final KeyStore ks = keystoreService.getSigningKeystore(keystore);
final Certificate cert = ks.getCertificate(getSigningKeyAlias());
return (cert != null) ? (RSAPublicKey) cert.getPublicKey() : null;
}
private String getSigningKeyAlias() {
- final GatewayConfig config = (GatewayConfig) request.getServletContext()
- .getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+ final GatewayConfig config = (GatewayConfig) context.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
final String alias = config.getSigningKeyAlias();
return (alias == null) ? GatewayConfig.DEFAULT_SIGNING_KEY_ALIAS : alias;
}
diff --git a/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/JWKSResourceTest.java b/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/JWKSResourceTest.java
index 09100e2..27963ab 100644
--- a/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/JWKSResourceTest.java
+++ b/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/JWKSResourceTest.java
@@ -17,35 +17,40 @@
*/
package org.apache.knox.gateway.service.knoxtoken;
-import com.nimbusds.jose.JOSEException;
-import com.nimbusds.jose.JWSSigner;
-import com.nimbusds.jose.JWSVerifier;
-import com.nimbusds.jose.crypto.RSASSASigner;
-import com.nimbusds.jose.crypto.RSASSAVerifier;
-import com.nimbusds.jose.jwk.JWK;
-import com.nimbusds.jose.jwk.JWKSet;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.KeyStoreSpi;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Collections;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Response;
+
+import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.services.GatewayServices;
import org.apache.knox.gateway.services.ServiceType;
+import org.apache.knox.gateway.services.security.AliasService;
import org.apache.knox.gateway.services.security.KeystoreService;
-import org.apache.knox.gateway.services.security.KeystoreServiceException;
import org.apache.knox.gateway.services.security.token.impl.JWT;
import org.apache.knox.gateway.services.security.token.impl.JWTToken;
import org.easymock.EasyMock;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.core.Response;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.KeyStoreException;
-import java.security.PublicKey;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.text.ParseException;
-import java.util.Collections;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.JWSVerifier;
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jose.crypto.RSASSAVerifier;
+import com.nimbusds.jose.jwk.JWK;
+import com.nimbusds.jose.jwk.JWKSet;
/**
* Unit tests for JWKS Resource
@@ -57,7 +62,6 @@ public class JWKSResourceTest {
private ServletContext context;
private HttpServletRequest request;
private GatewayServices services;
- private JWKSResource jwksResource;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
@@ -69,49 +73,51 @@ public class JWKSResourceTest {
privateKey = (RSAPrivateKey) KPair.getPrivate();
}
- private void init() throws KeystoreServiceException, KeyStoreException {
- final KeystoreService ks = EasyMock.createNiceMock(KeystoreService.class);
+ @Before
+ public void init() throws Exception {
services = EasyMock.createNiceMock(GatewayServices.class);
context = EasyMock.createNiceMock(ServletContext.class);
request = EasyMock.createNiceMock(HttpServletRequest.class);
- jwksResource = EasyMock.partialMockBuilder(JWKSResource.class)
- .addMockedMethod("getPublicKey", String.class).createMock();
-
- EasyMock.expect(services.getService(ServiceType.KEYSTORE_SERVICE))
- .andReturn(ks).anyTimes();
- EasyMock.expect(
- context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE))
- .andReturn(services).anyTimes();
- EasyMock.expect(jwksResource.getPublicKey(null)).andReturn(publicKey)
- .anyTimes();
- EasyMock.replay(jwksResource, context, request, services, ks);
+ final KeystoreService ks = EasyMock.createNiceMock(KeystoreService.class);
+ final KeyStoreSpi keyStoreSpi = EasyMock.createNiceMock(KeyStoreSpi.class);
+ final KeyStore keystore = new KeyStoreMock(keyStoreSpi, null, "test");
+ keystore.load(null);
+ EasyMock.expect(ks.getSigningKeystore(null)).andReturn(keystore).anyTimes();
+ final Certificate cert = EasyMock.createNiceMock(Certificate.class);
+ EasyMock.expect(keyStoreSpi.engineGetCertificate(EasyMock.anyString())).andReturn(cert).anyTimes();
+ EasyMock.expect(cert.getPublicKey()).andReturn(publicKey).anyTimes();
+ EasyMock.expect(services.getService(ServiceType.KEYSTORE_SERVICE)).andReturn(ks).anyTimes();
+ EasyMock.expect(services.getService(ServiceType.ALIAS_SERVICE)).andReturn(EasyMock.createNiceMock(AliasService.class)).anyTimes();
+ EasyMock.expect(context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE)).andReturn(services).anyTimes();
+ final GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class);
+ EasyMock.expect(config.getSigningKeyAlias()).andReturn(null).anyTimes();
+ EasyMock.expect(context.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(config).anyTimes();
+ EasyMock.replay(context, request, services, ks, keyStoreSpi, cert, config);
}
@Test
- public void testJWKSrequest()
- throws KeystoreServiceException, KeyStoreException {
- init();
- Response retResponse = jwksResource.getJwksResponse();
- Assert.assertEquals(Response.Status.OK.getStatusCode(),
- retResponse.getStatus());
+ public void testJWKSrequest() throws Exception {
+ final JWKSResource jwksResource = new JWKSResource();
+ jwksResource.context = context;
+ jwksResource.request = request;
+ jwksResource.init();
+ final Response retResponse = jwksResource.getJwksResponse();
+ Assert.assertEquals(Response.Status.OK.getStatusCode(), retResponse.getStatus());
}
/**
* End to End test that verifies the token acquired from JWKS endpoint.
- *
- * @throws KeystoreServiceException
- * @throws KeyStoreException
- * @throws ParseException
- * @throws JOSEException
*/
@Test
- public void testE2E()
- throws KeystoreServiceException, KeyStoreException, ParseException,
- JOSEException {
- init();
+ public void testE2E() throws Exception {
/* get a signed JWT token */
final JWT testToken = getTestToken("RS256");
+
+ final JWKSResource jwksResource = new JWKSResource();
+ jwksResource.context = context;
+ jwksResource.request = request;
+ jwksResource.init();
/* get JWKS keyset */
final Response retResponse = jwksResource.getJwksResponse();
@@ -142,4 +148,11 @@ public class JWKSResourceTest {
return token;
}
+ private static final class KeyStoreMock extends KeyStore {
+
+ protected KeyStoreMock(KeyStoreSpi keyStoreSpi, Provider provider, String type) {
+ super(keyStoreSpi, provider, type);
+ }
+ }
+
}
\ No newline at end of file