From 93d5487de40e143e4e22d3eb856543ab29b34ab5 Mon Sep 17 00:00:00 2001 From: Tomek Kaminski Date: Thu, 6 Jun 2019 15:16:36 +0200 Subject: [PATCH] DMaaPAuthFilter refactor - added client certificate handling - fixed forceAAF flag reading Issue-ID: DMAAP-1214 Signed-off-by: Tomek Kaminski Change-Id: Icaa80cc40f8c6b50f36096c205d67d14cdbebd2a --- pom.xml | 6 + .../java/org/onap/dmaap/util/DMaaPAuthFilter.java | 116 ++++++++------- .../org/onap/dmaap/util/DMaaPAuthFilterTest.java | 157 +++++++++++++++------ 3 files changed, 182 insertions(+), 97 deletions(-) diff --git a/pom.xml b/pom.xml index 24e21b4..5f697fd 100644 --- a/pom.xml +++ b/pom.xml @@ -626,6 +626,12 @@ 3.0.10-oss provided + + org.springframework + spring-test + 3.2.12.RELEASE + test + diff --git a/src/main/java/org/onap/dmaap/util/DMaaPAuthFilter.java b/src/main/java/org/onap/dmaap/util/DMaaPAuthFilter.java index 547c4cd..5c7170b 100644 --- a/src/main/java/org/onap/dmaap/util/DMaaPAuthFilter.java +++ b/src/main/java/org/onap/dmaap/util/DMaaPAuthFilter.java @@ -8,19 +8,20 @@ * 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. * ============LICENSE_END========================================================= - * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * + * *******************************************************************************/ - package org.onap.dmaap.util; +package org.onap.dmaap.util; +import com.att.ajsc.filemonitor.AJSCPropertiesMap; import java.io.IOException; import javax.servlet.FilterChain; @@ -29,62 +30,71 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import org.onap.dmaap.dmf.mr.constants.CambriaConstants; import org.onap.dmaap.dmf.mr.utils.Utils; import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; import org.springframework.stereotype.Component; import org.onap.aaf.cadi.filter.CadiFilter; -//import ajsc.external.plugins.cadi.AjscCadiFilter; -import javax.servlet.FilterConfig; /** - * This is a Servlet Filter class - * overriding the AjscCadiFilter - */ -@Component + * This is a Servlet Filter class overriding the AjscCadiFilter + */ +@Component public class DMaaPAuthFilter extends CadiFilter { - - //private Logger log = Logger.getLogger(DMaaPAuthFilter.class.toString()); - - private static final EELFLogger log = EELFManager.getInstance().getLogger(DMaaPAuthFilter.class); - - public DMaaPAuthFilter() throws Exception { - super(); - } - - /* public void init(FilterConfig filterConfig) throws ServletException { - - super.init(filterConfig); - System.out.println("---------------------------- in init method"); - }*/ - - /** - * This method will disable Cadi Authentication - * if cambria headers are present in the request - * else continue with Cadi Authentication - */ - @Override - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, - ServletException { - log.info("inside servlet filter Cambria Auth Headers checking before doing other Authentication"); - HttpServletRequest request = (HttpServletRequest) req; - boolean forceAAF = Boolean.valueOf(System.getProperty("forceAAF")); - - //if (forceAAF || null != request.getHeader("Authorization") ){ - if (Utils.isCadiEnabled()&&(forceAAF || null != request.getHeader("Authorization") || - (null != request.getHeader("AppName") && request.getHeader("AppName").equalsIgnoreCase("invenio") && - null != request.getHeader("cookie")))){ - super.doFilter(req, res, chain); - - } else { - System.setProperty("CadiAuthN", "authentication-scheme-2"); - chain.doFilter(req, res); - - - } - - } - - } + + private static final String FORCE_AAF_FLAG = "forceAAF"; + static final String X509_ATTR = "javax.servlet.request.X509Certificate"; + static final String AUTH_HEADER = "Authorization"; + static final String APP_HEADER = "AppName"; + static final String COOKIE_HEADER = "cookie"; + private static final EELFLogger log = EELFManager.getInstance().getLogger(DMaaPAuthFilter.class); + + public DMaaPAuthFilter() { + super(); + } + + /** + * This method will disable Cadi Authentication if cambria headers are present in the request else continue with + * Cadi Authentication + */ + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException { + log.info("inside servlet filter Cambria Auth Headers checking before doing other Authentication"); + if (shouldFilterWithCADI((HttpServletRequest) req)) { + super.doFilter(req, res, chain); + } else { + System.setProperty("CadiAuthN", "authentication-scheme-2"); + chain.doFilter(req, res); + } + } + + boolean shouldFilterWithCADI(HttpServletRequest request) { + return isCadiEnabled() && + (isAAFforced() || isAuthDataProvided(request) || isInvenioApp(request)); + } + + private boolean isAuthDataProvided(HttpServletRequest request) { + return (null != request.getHeader(AUTH_HEADER)) || hasClientCertificate(request); + } + + private boolean isInvenioApp(HttpServletRequest request) { + return (null != request.getHeader(APP_HEADER)) && request.getHeader(APP_HEADER).equalsIgnoreCase("invenio") && + (null != request.getHeader(COOKIE_HEADER)); + } + + private boolean hasClientCertificate(HttpServletRequest request) { + return request.getAttribute(X509_ATTR) != null; + } + + boolean isCadiEnabled() { + return Utils.isCadiEnabled(); + } + + boolean isAAFforced() { + return Boolean.valueOf(AJSCPropertiesMap.getProperty(CambriaConstants.msgRtr_prop, FORCE_AAF_FLAG)); + } + +} diff --git a/src/test/java/org/onap/dmaap/util/DMaaPAuthFilterTest.java b/src/test/java/org/onap/dmaap/util/DMaaPAuthFilterTest.java index ad94441..ff1efb0 100644 --- a/src/test/java/org/onap/dmaap/util/DMaaPAuthFilterTest.java +++ b/src/test/java/org/onap/dmaap/util/DMaaPAuthFilterTest.java @@ -20,81 +20,150 @@ package org.onap.dmaap.util; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.io.IOException; - +import javax.security.cert.X509Certificate; import javax.servlet.FilterChain; import javax.servlet.ServletException; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; - -import org.junit.After; +import org.apache.commons.codec.binary.Base64; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.Spy; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; -import com.att.ajsc.beans.PropertiesMapBean; -import org.onap.dmaap.dmf.mr.beans.DMaaPContext; -import org.onap.dmaap.dmf.mr.exception.DMaaPResponseCode; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({ PropertiesMapBean.class, DMaaPResponseCode.class }) +@RunWith(MockitoJUnitRunner.class) public class DMaaPAuthFilterTest { - @InjectMocks - DMaaPAuthFilter filter; - - @Mock - HttpServletRequest req; + @Spy + private DMaaPAuthFilter filter; - @Mock - ServletResponse res; + private MockHttpServletRequest request; - @Mock - FilterChain chain; + private MockHttpServletResponse response; @Mock - DMaaPContext dmaapContext; + private FilterChain chain; @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + request = new MockHttpServletRequest(); + response = new MockHttpServletResponse(); } - @After - public void tearDown() throws Exception { + @Test + public void doFilter_shouldNotUseCadiFilter_whenCadiNotEnabled() throws IOException, ServletException { + //given + when(filter.isCadiEnabled()).thenReturn(false); + + //when + filter.doFilter(request, response, chain); + + //then + verify(chain).doFilter(request, response); } - //@Test - public void testDoFilter() throws IOException, ServletException { + @Test + public void shouldFilterWithCADI_willBeFalse_whenCadiEnabled_noAuthData_affNotForced_notInvenioApp() { + //given + configureSettingsFlags(false); - PowerMockito.when(dmaapContext.getRequest()).thenReturn(req); - PowerMockito.when(req.getHeader("Authorization")).thenReturn("Authorization"); - // when(dmaapContext.getResponse()).thenReturn(res); - filter.doFilter(req, res, chain); - assertTrue(true); + //when + boolean filteringWithCADI = filter.shouldFilterWithCADI(request); + //then + assertFalse(filteringWithCADI); } - //@Test - public void testDoFilter_nullAuth() throws IOException, ServletException { + @Test + public void shouldFilterWithCADI_willBeTrue_whenCadiEnabled_andAAFforcedFlagSet() { + //given + configureSettingsFlags(true); + + //when + boolean filteringWithCADI = filter.shouldFilterWithCADI(request); + + //then + assertTrue(filteringWithCADI); + } - PowerMockito.when(dmaapContext.getRequest()).thenReturn(req); - PowerMockito.when(req.getHeader("Authorization")).thenReturn("Authorization"); + @Test + public void shouldFilterWithCADI_willBeTrue_whenCadiEnabled_andBasicAuthorization() { + //given + configureSettingsFlags(false); + request.addHeader(DMaaPAuthFilter.AUTH_HEADER, Base64.encodeBase64("user/pass".getBytes())); - // when(dmaapContext.getResponse()).thenReturn(res); - filter.doFilter(req, res, chain); - assertTrue(true); + //when + boolean filteringWithCADI = filter.shouldFilterWithCADI(request); + //then + assertTrue(filteringWithCADI); + } + + @Test + public void shouldFilterWithCADI_willBeTrue_whenCadiEnabled_andClientCertificate() { + //given + configureSettingsFlags(false); + request.setAttribute(DMaaPAuthFilter.X509_ATTR, new X509Certificate[]{}); + + //when + boolean filteringWithCADI = filter.shouldFilterWithCADI(request); + + //then + assertTrue(filteringWithCADI); + } + + @Test + public void shouldFilterWithCADI_willBeTrue_whenCadiEnabled_andInvenioAppWithCookie() { + //given + configureSettingsFlags(false); + request.addHeader(DMaaPAuthFilter.APP_HEADER, "invenio"); + request.addHeader(DMaaPAuthFilter.COOKIE_HEADER, "value"); + + //when + boolean filteringWithCADI = filter.shouldFilterWithCADI(request); + + //then + assertTrue(filteringWithCADI); + } + + @Test + public void shouldFilterWithCADI_willBeFalse_whenCadiEnabled_andInvenioAppWithoutCookie() { + //given + configureSettingsFlags(false); + request.addHeader(DMaaPAuthFilter.APP_HEADER, "invenio"); + + //when + boolean filteringWithCADI = filter.shouldFilterWithCADI(request); + + //then + assertFalse(filteringWithCADI); + } + + @Test + public void shouldFilterWithCADI_willBeFalse_whenCadiEnabled_andNotInvenioApp() { + //given + configureSettingsFlags(false); + request.addHeader(DMaaPAuthFilter.APP_HEADER, "application"); + + //when + boolean filteringWithCADI = filter.shouldFilterWithCADI(request); + + //then + assertFalse(filteringWithCADI); + } + + private void configureSettingsFlags(boolean isAAFforced) { + when(filter.isCadiEnabled()).thenReturn(true); + when(filter.isAAFforced()).thenReturn(isAAFforced); } - } \ No newline at end of file -- 2.16.6