http://git-wip-us.apache.org/repos/asf/ambari/blob/d5cca62c/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AmbariJWTAuthenticationFilterTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AmbariJWTAuthenticationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AmbariJWTAuthenticationFilterTest.java new file mode 100644 index 0000000..f042a70 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AmbariJWTAuthenticationFilterTest.java @@ -0,0 +1,190 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.ambari.server.security.authentication; + +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.crypto.RSASSASigner; +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; +import org.apache.ambari.server.audit.AuditLogger; +import org.apache.ambari.server.configuration.Configuration; +import org.apache.ambari.server.security.AmbariEntryPoint; +import org.apache.ambari.server.security.authorization.PermissionHelper; +import org.apache.ambari.server.security.authorization.User; +import org.apache.ambari.server.security.authorization.UserType; +import org.apache.ambari.server.security.authorization.Users; +import org.apache.ambari.server.security.authorization.jwt.JwtAuthenticationProperties; +import org.easymock.EasyMockSupport; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.servlet.FilterChain; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; + +public class AmbariJWTAuthenticationFilterTest extends EasyMockSupport { + private static RSAPublicKey publicKey; + private static RSAPrivateKey privateKey; + + @BeforeClass + public static void generateKeyPair() throws NoSuchAlgorithmException { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(512); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + publicKey = (RSAPublicKey) keyPair.getPublic(); + privateKey = (RSAPrivateKey) keyPair.getPrivate(); + } + + @Test + public void testDoFilterSuccess() throws Exception { + SignedJWT token = getSignedToken("foobar"); + + AmbariEntryPoint entryPoint = createMock(AmbariEntryPoint.class); + + JwtAuthenticationProperties properties = createMock(JwtAuthenticationProperties.class); + expect(properties.getAuthenticationProviderUrl()).andReturn("some url").once(); + expect(properties.getPublicKey()).andReturn(publicKey).once(); + expect(properties.getAudiences()).andReturn(Collections.singletonList("foobar")).once(); + expect(properties.getCookieName()).andReturn("chocolate chip").once(); + expect(properties.getOriginalUrlQueryParam()).andReturn("question").once(); + + Configuration configuration = createMock(Configuration.class); + expect(configuration.getJwtProperties()).andReturn(properties).once(); + + User user = createMock(User.class); + expect(user.getUserName()).andReturn("test-user").once(); + expect(user.getUserType()).andReturn(UserType.JWT).once(); + + Users users = createMock(Users.class); + expect(users.getUser("test-user", UserType.JWT)).andReturn(user).once(); + expect(users.getUserAuthorities("test-user", UserType.JWT)).andReturn(null).once(); + + AuditLogger auditLogger = createMock(AuditLogger.class); + expect(auditLogger.isEnabled()).andReturn(false).times(2); + + PermissionHelper permissionHelper = createMock(PermissionHelper.class); + + Cookie cookie = createMock(Cookie.class); + expect(cookie.getName()).andReturn("chocolate chip").once(); + expect(cookie.getValue()).andReturn(token.serialize()).once(); + + + HttpServletRequest servletRequest = createMock(HttpServletRequest.class); + expect(servletRequest.getCookies()).andReturn(new Cookie[]{cookie}).once(); + + HttpServletResponse servletResponse = createMock(HttpServletResponse.class); + + FilterChain filterChain = createMock(FilterChain.class); + filterChain.doFilter(servletRequest, servletResponse); + expectLastCall().once(); + + replayAll(); + + AmbariJWTAuthenticationFilter filter = new AmbariJWTAuthenticationFilter(entryPoint, configuration, users, auditLogger, permissionHelper); + filter.doFilter(servletRequest, servletResponse, filterChain); + + verifyAll(); + } + + @Test + public void testDoFilterFailure() throws Exception { + AmbariEntryPoint entryPoint = createMock(AmbariEntryPoint.class); + + JwtAuthenticationProperties properties = createMock(JwtAuthenticationProperties.class); + expect(properties.getAuthenticationProviderUrl()).andReturn("some url").once(); + expect(properties.getPublicKey()).andReturn(publicKey).once(); + expect(properties.getAudiences()).andReturn(Collections.singletonList("foobar")).once(); + expect(properties.getCookieName()).andReturn("chocolate chip").once(); + expect(properties.getOriginalUrlQueryParam()).andReturn("question").once(); + + Configuration configuration = createMock(Configuration.class); + expect(configuration.getJwtProperties()).andReturn(properties).once(); + + Users users = createMock(Users.class); + + AuditLogger auditLogger = createMock(AuditLogger.class); + expect(auditLogger.isEnabled()).andReturn(false).times(2); + + PermissionHelper permissionHelper = createMock(PermissionHelper.class); + + Cookie cookie = createMock(Cookie.class); + expect(cookie.getName()).andReturn("chocolate chip").once(); + expect(cookie.getValue()).andReturn("invalid token").once(); + + + HttpServletRequest servletRequest = createMock(HttpServletRequest.class); + expect(servletRequest.getCookies()).andReturn(new Cookie[]{cookie}).once(); + + HttpServletResponse servletResponse = createMock(HttpServletResponse.class); + + FilterChain filterChain = createMock(FilterChain.class); + filterChain.doFilter(servletRequest, servletResponse); + expectLastCall().once(); + + replayAll(); + + AmbariJWTAuthenticationFilter filter = new AmbariJWTAuthenticationFilter(entryPoint, configuration, users, auditLogger, permissionHelper); + filter.doFilter(servletRequest, servletResponse, filterChain); + + verifyAll(); + } + + + private SignedJWT getSignedToken(String audience) throws JOSEException { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(System.currentTimeMillis()); + calendar.add(Calendar.DATE, 1); //add one day + return getSignedToken(calendar.getTime(), audience); + } + + private SignedJWT getSignedToken(Date expirationTime, String audience) throws JOSEException { + RSASSASigner signer = new RSASSASigner(privateKey); + + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(System.currentTimeMillis()); + JWTClaimsSet claimsSet = new JWTClaimsSet(); + claimsSet.setSubject("test-user"); + claimsSet.setIssuer("unit-test"); + claimsSet.setIssueTime(calendar.getTime()); + + claimsSet.setExpirationTime(expirationTime); + + claimsSet.setAudience(audience); + + SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), claimsSet); + signedJWT.sign(signer); + + return signedJWT; + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/d5cca62c/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java index 1d71fe6..10de0a9 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java @@ -30,6 +30,7 @@ import org.apache.ambari.server.audit.AuditLogger; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.dao.UserDAO; +import org.apache.ambari.server.security.AmbariEntryPoint; import org.apache.ambari.server.security.TestAuthenticationFactory; import org.apache.ambari.server.state.stack.OsFamily; import org.apache.ambari.server.view.ViewRegistry; @@ -324,7 +325,8 @@ public class AmbariAuthorizationFilterTest { } }); - AmbariAuthorizationFilter filter = new AmbariAuthorizationFilter(); + AmbariAuthorizationFilter filter = new AmbariAuthorizationFilter(createNiceMock(AmbariEntryPoint.class), injector.getInstance(Configuration.class), + injector.getInstance(Users.class), injector.getInstance(AuditLogger.class), injector.getInstance(PermissionHelper.class)); injector.injectMembers(filter); filter.doFilter(request, response, chain); @@ -338,14 +340,28 @@ public class AmbariAuthorizationFilterTest { * @param authentication the authentication to use * @param urlTests map of triples: url - http method - is allowed * @param expectRedirect true if the requests should redirect to login - * @throws Exception + * @throws Exception if an exception occurs */ private void performGeneralDoFilterTest(Authentication authentication, Table<String, String, Boolean> urlTests, boolean expectRedirect) throws Exception { final SecurityContext securityContext = createNiceMock(SecurityContext.class); final FilterConfig filterConfig = createNiceMock(FilterConfig.class); + + final Configuration configuration = EasyMock.createMock(Configuration.class); + expect(configuration.getDefaultApiAuthenticatedUser()).andReturn(null).anyTimes(); + + final AuditLogger auditLogger = EasyMock.createNiceMock(AuditLogger.class); + expect(auditLogger.isEnabled()).andReturn(false).anyTimes(); + final AmbariAuthorizationFilter filter = createMockBuilder(AmbariAuthorizationFilter.class) - .addMockedMethod("getSecurityContext").addMockedMethod("getViewRegistry").withConstructor().createMock(); - injectMembers(filter); + .addMockedMethod("getSecurityContext") + .addMockedMethod("getViewRegistry") + .withConstructor(createNiceMock(AmbariEntryPoint.class), + configuration, + createNiceMock(Users.class), + auditLogger, + createNiceMock(PermissionHelper.class)) + .createMock(); + final ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class); expect(filterConfig.getInitParameter("realm")).andReturn("AuthFilter").anyTimes(); @@ -355,7 +371,7 @@ public class AmbariAuthorizationFilterTest { expect(securityContext.getAuthentication()).andReturn(authentication).anyTimes(); expect(viewRegistry.checkPermission(EasyMock.eq("DeniedView"), EasyMock.<String>anyObject(), EasyMock.<String>anyObject(), EasyMock.anyBoolean())).andReturn(false).anyTimes(); - replay(filterConfig, filter, securityContext, viewRegistry); + replay(filterConfig, filter, securityContext, viewRegistry, configuration, auditLogger); for (final Cell<String, String, Boolean> urlTest: urlTests.cellSet()) { final FilterChain chain = EasyMock.createStrictMock(FilterChain.class); @@ -399,26 +415,4 @@ public class AmbariAuthorizationFilterTest { } } } - - private void injectMembers(AmbariAuthorizationFilter filter) { - final Configuration configuration = EasyMock.createMock(Configuration.class); - expect(configuration.getDefaultApiAuthenticatedUser()).andReturn(null).anyTimes(); - final AuditLogger auditLogger = EasyMock.createNiceMock(AuditLogger.class); - expect(auditLogger.isEnabled()).andReturn(false).anyTimes(); - Injector injector = Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Configuration.class).toInstance(configuration); - bind(Users.class).toInstance(EasyMock.createMock(Users.class)); - bind(EntityManager.class).toInstance(EasyMock.createMock(EntityManager.class)); - bind(UserDAO.class).toInstance(EasyMock.createMock(UserDAO.class)); - bind(DBAccessor.class).toInstance(EasyMock.createMock(DBAccessor.class)); - bind(PasswordEncoder.class).toInstance(EasyMock.createMock(PasswordEncoder.class)); - bind(OsFamily.class).toInstance(EasyMock.createMock(OsFamily.class)); - bind(AuditLogger.class).toInstance(auditLogger); - } - }); - injector.injectMembers(filter); - replay(configuration, auditLogger); - } } http://git-wip-us.apache.org/repos/asf/ambari/blob/d5cca62c/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/jwt/JwtAuthenticationFilterTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/jwt/JwtAuthenticationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/jwt/JwtAuthenticationFilterTest.java index b08d1ac..5814203 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/jwt/JwtAuthenticationFilterTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/jwt/JwtAuthenticationFilterTest.java @@ -24,13 +24,12 @@ import com.nimbusds.jose.JWSHeader; import com.nimbusds.jose.crypto.RSASSASigner; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; +import junit.framework.Assert; import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority; import org.apache.ambari.server.security.authorization.AuthorizationHelper; import org.apache.ambari.server.security.authorization.User; import org.apache.ambari.server.security.authorization.UserType; import org.apache.ambari.server.security.authorization.Users; -import org.easymock.EasyMock; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; @@ -46,10 +45,8 @@ import javax.servlet.http.HttpServletResponse; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; -import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; @@ -57,6 +54,7 @@ import java.util.List; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createNiceMock; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; @@ -299,4 +297,75 @@ public class JwtAuthenticationFilterTest { assertEquals(false, isValid); } + + @Test + public void testShouldApplyTrue() throws JOSEException { + JwtAuthenticationProperties properties = createTestProperties(); + JwtAuthenticationFilter filter = new JwtAuthenticationFilter(properties, null, null); + + SignedJWT token = getInvalidToken(); + + Cookie cookie = createMock(Cookie.class); + expect(cookie.getName()).andReturn("non-default").atLeastOnce(); + expect(cookie.getValue()).andReturn(token.serialize()).atLeastOnce(); + + HttpServletRequest request = createMock(HttpServletRequest.class); + expect(request.getCookies()).andReturn(new Cookie[]{cookie}); + + replay(request, cookie); + + Assert.assertTrue(filter.shouldApply(request)); + + verify(request, cookie); + } + + @Test + public void testShouldApplyTrueBadToken() throws JOSEException { + JwtAuthenticationProperties properties = createTestProperties(); + JwtAuthenticationFilter filter = new JwtAuthenticationFilter(properties, null, null); + + Cookie cookie = createMock(Cookie.class); + expect(cookie.getName()).andReturn("non-default").atLeastOnce(); + expect(cookie.getValue()).andReturn("bad token").atLeastOnce(); + + HttpServletRequest request = createMock(HttpServletRequest.class); + expect(request.getCookies()).andReturn(new Cookie[]{cookie}); + + replay(request, cookie); + + Assert.assertTrue(filter.shouldApply(request)); + + verify(request, cookie); + } + + @Test + public void testShouldApplyFalseMissingCookie() throws JOSEException { + JwtAuthenticationProperties properties = createTestProperties(); + JwtAuthenticationFilter filter = new JwtAuthenticationFilter(properties, null, null); + + Cookie cookie = createMock(Cookie.class); + expect(cookie.getName()).andReturn("some-other-cookie").atLeastOnce(); + + HttpServletRequest request = createMock(HttpServletRequest.class); + expect(request.getCookies()).andReturn(new Cookie[]{cookie}); + + replay(request, cookie); + + Assert.assertFalse(filter.shouldApply(request)); + + verify(request, cookie); + } + + @Test + public void testShouldApplyFalseNotEnabled() throws JOSEException { + JwtAuthenticationFilter filter = new JwtAuthenticationFilter((JwtAuthenticationProperties) null, null, null); + + HttpServletRequest request = createMock(HttpServletRequest.class); + + replay(request); + + Assert.assertFalse(filter.shouldApply(request)); + + verify(request); + } } \ No newline at end of file