/** * Copyright (c) Codice Foundation * <p> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package org.codice.ddf.security.claims.attributequery.common; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.security.Principal; import java.util.ArrayList; import java.util.List; import javax.xml.transform.stream.StreamSource; import javax.xml.ws.Dispatch; import javax.xml.ws.Service; import org.apache.cxf.rt.security.claims.Claim; import org.apache.cxf.rt.security.claims.ClaimCollection; import org.apache.cxf.staxutils.StaxUtils; import org.apache.cxf.sts.claims.ClaimsParameters; import org.apache.cxf.sts.claims.ProcessedClaimCollection; import org.apache.wss4j.common.saml.OpenSAMLUtil; import org.codice.ddf.configuration.SystemBaseUrl; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.opensaml.core.config.InitializationException; import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.saml2.core.Assertion; import org.opensaml.saml.saml2.core.Response; import org.w3c.dom.Document; import com.google.common.base.Charsets; import com.google.common.io.Resources; import ddf.security.encryption.EncryptionService; import ddf.security.samlp.SimpleSign; import ddf.security.samlp.SystemCrypto; public class TestAttributeQueryClaimsHandler { private static final String DESTINATION = "testDestination"; private static final String ISSUER = "testIssuer"; private static final String USERNAME = "CN=testCN, OU=testOU, O=testO, L=testL, ST=testST, C=testC"; private static final String EXTERNAL_ATTRIBUTE_STORE = SystemBaseUrl.getBaseUrl(); private AttributeQueryClaimsHandlerTest spyAttributeQueryClaimsHandler; private Object signatureProperties; private Object encryptionProperties; private Service service; private Dispatch<StreamSource> dispatch; private String responseState = "ValidResponse"; private List<String> supportedClaims; private EncryptionService encryptionService; private SystemCrypto systemCrypto; private SimpleSign simpleSign; private String cannedResponse; class AttributeQueryClaimsHandlerTest extends AttributeQueryClaimsHandler { @Override protected AttributeQueryClient createAttributeQueryClient(SimpleSign simpleSign, String externalAttributeStoreUrl, String issuer, String destination) { AttributeQueryClient attributeQueryClient = null; Document responseDoc; try { responseDoc = StaxUtils.read(new ByteArrayInputStream(cannedResponse.getBytes())); XMLObject responseXmlObject = OpenSAMLUtil.fromDom(responseDoc.getDocumentElement()); Response response = (Response) responseXmlObject; // Extract Assertion from response. Assertion assertion = response.getAssertions() .get(0); // Check that response only has one assertion. assertThat(response.getAssertions() .size(), is(equalTo(1))); attributeQueryClient = mock(AttributeQueryClient.class); if (responseState.equalsIgnoreCase("ValidResponse")) { when(attributeQueryClient.query(anyString())).thenReturn(assertion); } else if (responseState.equalsIgnoreCase("NullResponse")) { when(attributeQueryClient.query(anyString())).thenReturn(null); } else if (responseState.equalsIgnoreCase("InvalidClient")) { return null; } else { when(attributeQueryClient.query(anyString())).thenThrow(new AttributeQueryException( "Invalid Response")); } return attributeQueryClient; } catch (Exception e) { fail("Could not create mock AttributeQueryClient."); } return attributeQueryClient; } } @BeforeClass public static void init() throws InitializationException { OpenSAMLUtil.initSamlEngine(); } @Before public void setUp() throws IOException { signatureProperties = mock(Object.class); encryptionProperties = mock(Object.class); service = mock(Service.class); dispatch = (Dispatch<StreamSource>) mock(Dispatch.class); encryptionService = mock(EncryptionService.class); systemCrypto = new SystemCrypto("encryption.properties", "signature.properties", encryptionService); simpleSign = new SimpleSign(systemCrypto); supportedClaims = new ArrayList<>(); supportedClaims.add("Role"); supportedClaims.add("NameIdentifier"); supportedClaims.add("Email"); AttributeQueryClaimsHandlerTest attributeQueryClaimsHandler = new AttributeQueryClaimsHandlerTest(); spyAttributeQueryClaimsHandler = spy(attributeQueryClaimsHandler); spyAttributeQueryClaimsHandler.setWsdlLocation("wsdlLocation"); spyAttributeQueryClaimsHandler.setServiceName("serviceName"); spyAttributeQueryClaimsHandler.setPortName("portName"); spyAttributeQueryClaimsHandler.setSimpleSign(simpleSign); spyAttributeQueryClaimsHandler.setSupportedClaims(supportedClaims); spyAttributeQueryClaimsHandler.setExternalAttributeStoreUrl(EXTERNAL_ATTRIBUTE_STORE); spyAttributeQueryClaimsHandler.setIssuer(ISSUER); spyAttributeQueryClaimsHandler.setDestination(DESTINATION); spyAttributeQueryClaimsHandler.setAttributeMapLocation(getClass().getClassLoader() .getResource("attributeMap.properties") .getPath()); spyAttributeQueryClaimsHandler.setSignatureProperties(signatureProperties); spyAttributeQueryClaimsHandler.setEncryptionProperties(encryptionProperties); doReturn(service).when(spyAttributeQueryClaimsHandler) .createService(); doReturn(dispatch).when(spyAttributeQueryClaimsHandler) .createDispatcher(service); cannedResponse = Resources.toString(Resources.getResource(getClass(), "/SAMLResponse.xml"), Charsets.UTF_8); } @Test public void testRetrieveClaimValues() throws Exception { ProcessedClaimCollection processedClaimCollection = retrieveClaimValues(); // Test that the claims were created and mapped correctly. assertThat(processedClaimCollection.size(), is(equalTo(3))); assertThat(processedClaimCollection.get(0) .getClaimType() .toString(), is(equalTo("Role"))); assertThat((String) processedClaimCollection.get(0) .getValues() .get(0), is(equalTo("Guest-hasMapping"))); assertThat(processedClaimCollection.get(1) .getClaimType() .toString(), is(equalTo("NameIdentifier"))); assertThat((String) processedClaimCollection.get(1) .getValues() .get(0), is(equalTo("Name-hasMapping"))); // Does not have an attribute mapping. assertThat(processedClaimCollection.get(2) .getClaimType() .toString(), is(equalTo("Email"))); assertThat((String) processedClaimCollection.get(2) .getValues() .get(0), is(equalTo("email"))); } @Test public void testRetrieveClaimValuesWithBadURI() throws Exception { cannedResponse = Resources.toString(Resources.getResource(getClass(), "/SAMLResponseBadAttribute.xml"), Charsets.UTF_8); supportedClaims.add("Bad: URI"); assertThat(retrieveClaimValues().size(), is(equalTo(0))); } @Test public void testRetrieveClaimValuesNullResponse() { responseState = "NullResponse"; assertThat(retrieveClaimValues().size(), is(equalTo(0))); } @Test public void testRetrieveClaimValuesInvalidResponseException() { responseState = "Exception"; assertThat(retrieveClaimValues().size(), is(equalTo(0))); } @Test public void testRetrieveClaimValuesInvalidClient() { responseState = "InvalidClient"; assertThat(retrieveClaimValues().size(), is(equalTo(0))); } @Test public void testRetrieveClaimsValuesNullPrincipal() { ClaimsParameters claimsParameters = mock(ClaimsParameters.class); when(claimsParameters.getPrincipal()).thenReturn(null); ClaimCollection claimCollection = new ClaimCollection(); ProcessedClaimCollection processedClaims = spyAttributeQueryClaimsHandler.retrieveClaimValues(claimCollection, claimsParameters); assertThat(processedClaims.size(), is(equalTo(0))); } @Test public void testSupportedClaimsTypes() { List<URI> supportedClaimTypes = spyAttributeQueryClaimsHandler.getSupportedClaimTypes(); assertThat(supportedClaimTypes.size(), is(equalTo(3))); assertThat(supportedClaimTypes.get(0) .toString(), is(equalTo("Role"))); assertThat(supportedClaimTypes.get(1) .toString(), is(equalTo("NameIdentifier"))); assertThat(supportedClaimTypes.get(2) .toString(), is(equalTo("Email"))); } @Test public void testSupportedClaimsTypesWithBadURI() { supportedClaims.add("Bad: URI"); assertThat(spyAttributeQueryClaimsHandler.getSupportedClaimTypes() .size(), is(equalTo(3))); } private ProcessedClaimCollection retrieveClaimValues() { ClaimCollection claimCollection = new ClaimCollection(); Claim claim = new Claim(); try { claim.setClaimType(new URI( "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")); } catch (URISyntaxException e) { fail("Could not create URI."); } claimCollection.add(claim); ClaimsParameters claimsParameters = mock(ClaimsParameters.class); Principal principal = mock(Principal.class); when(principal.getName()).thenReturn(USERNAME); when(claimsParameters.getPrincipal()).thenReturn(principal); return spyAttributeQueryClaimsHandler.retrieveClaimValues(claimCollection, claimsParameters); } }