org.codice.ddf.security.validator.pki.PKITokenValidatorTest.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.ddf.security.validator.pki.PKITokenValidatorTest.java

Source

/**
 * 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.validator.pki;

import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import ddf.security.PropertiesLoader;
import ddf.security.SecurityConstants;
import ddf.security.SubjectUtils;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.apache.cxf.sts.STSPropertiesMBean;
import org.apache.cxf.sts.request.ReceivedToken;
import org.apache.cxf.sts.token.validator.TokenValidatorParameters;
import org.apache.cxf.sts.token.validator.TokenValidatorResponse;
import org.apache.cxf.ws.security.sts.provider.model.secext.BinarySecurityTokenType;
import org.apache.wss4j.common.crypto.Merlin;
import org.apache.wss4j.dom.WSConstants;
import org.codice.ddf.security.handler.api.PKIAuthenticationToken;
import org.codice.ddf.security.handler.api.PKIAuthenticationTokenFactory;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class PKITokenValidatorTest {

    private static Properties properties;

    private PKITokenValidator pkiTokenValidator;

    private X509Certificate[] certificates;

    private X509Certificate[] badCertificates;

    private X509Certificate[] userCertificates;

    private Merlin merlin;

    @BeforeClass
    public static void setUpBeforeClass() {
        properties = System.getProperties();
        System.setProperty(SecurityConstants.KEYSTORE_TYPE, "jks");
    }

    @AfterClass
    public static void tearDownAfterClass() {
        System.setProperties(properties);
    }

    @Before
    public void setup() {
        pkiTokenValidator = new PKITokenValidator();
        pkiTokenValidator.setSignaturePropertiesPath(
                PKITokenValidatorTest.class.getResource("/signature.properties").getPath());
        pkiTokenValidator.setRealms(Arrays.asList("karaf"));
        pkiTokenValidator.init();

        try {
            KeyStore trustStore = KeyStore.getInstance(System.getProperty("javax.net.ssl.keyStoreType"));
            InputStream trustFIS = PKITokenValidatorTest.class.getResourceAsStream("/serverKeystore.jks");
            try {
                trustStore.load(trustFIS, "changeit".toCharArray());
            } catch (CertificateException e) {
                fail(e.getMessage());
            } finally {
                IOUtils.closeQuietly(trustFIS);
            }
            Certificate[] certs = trustStore.getCertificateChain("localhost");
            certificates = new X509Certificate[certs.length];
            for (int i = 0; i < certs.length; i++) {
                certificates[i] = (X509Certificate) certs[i];
            }

            trustStore = KeyStore.getInstance(System.getProperty(SecurityConstants.KEYSTORE_TYPE));
            trustFIS = PKITokenValidatorTest.class.getResourceAsStream("/badKeystore.jks");
            try {
                trustStore.load(trustFIS, "changeit".toCharArray());
            } catch (CertificateException e) {
                fail(e.getMessage());
            } finally {
                IOUtils.closeQuietly(trustFIS);
            }
            certs = trustStore.getCertificateChain("badhost");
            badCertificates = new X509Certificate[certs.length];
            for (int i = 0; i < certs.length; i++) {
                badCertificates[i] = (X509Certificate) certs[i];
            }
            merlin = new Merlin(
                    PropertiesLoader.loadProperties(
                            PKITokenValidatorTest.class.getResource("/signature.properties").getPath()),
                    PKITokenValidator.class.getClassLoader(), null);

            KeyStore keystore = KeyStore.getInstance(System.getProperty(SecurityConstants.KEYSTORE_TYPE));
            try (InputStream keystoreIS = PKITokenValidatorTest.class.getResourceAsStream("/test-user.jks")) {
                keystore.load(keystoreIS, "changeit".toCharArray());
            }
            Certificate cert = keystore.getCertificate("test");
            userCertificates = new X509Certificate[] { (X509Certificate) cert };

        } catch (Exception e) {
            fail(e.getMessage());
        }
    }

    @Test
    public void testCanHandleToken() {
        BinarySecurityTokenType binarySecurityTokenType = new BinarySecurityTokenType();
        binarySecurityTokenType.setEncodingType(WSConstants.SOAPMESSAGE_NS + "#Base64Binary");
        binarySecurityTokenType.setValueType(PKIAuthenticationToken.PKI_TOKEN_VALUE_TYPE);
        PKIAuthenticationTokenFactory pkiAuthenticationTokenFactory = new PKIAuthenticationTokenFactory();
        pkiAuthenticationTokenFactory.setSignaturePropertiesPath(
                PKITokenValidatorTest.class.getResource("/signature.properties").getPath());
        pkiAuthenticationTokenFactory.init();
        PKIAuthenticationToken pkiAuthenticationToken = pkiAuthenticationTokenFactory
                .getTokenFromCerts(certificates, "karaf");
        binarySecurityTokenType.setValue(pkiAuthenticationToken.getEncodedCredentials());
        ReceivedToken receivedToken = mock(ReceivedToken.class);
        when(receivedToken.getToken()).thenReturn(binarySecurityTokenType);

        boolean result = pkiTokenValidator.canHandleToken(receivedToken);
        assertEquals(true, result);
    }

    @Test
    public void testCanHandleAnyRealmToken() {
        BinarySecurityTokenType binarySecurityTokenType = new BinarySecurityTokenType();
        binarySecurityTokenType.setEncodingType(WSConstants.SOAPMESSAGE_NS + "#Base64Binary");
        binarySecurityTokenType.setValueType(PKIAuthenticationToken.PKI_TOKEN_VALUE_TYPE);
        PKIAuthenticationTokenFactory pkiAuthenticationTokenFactory = new PKIAuthenticationTokenFactory();
        pkiAuthenticationTokenFactory.setSignaturePropertiesPath(
                PKITokenValidatorTest.class.getResource("/signature.properties").getPath());
        pkiAuthenticationTokenFactory.init();
        PKIAuthenticationToken pkiAuthenticationToken = pkiAuthenticationTokenFactory
                .getTokenFromCerts(certificates, "*");
        binarySecurityTokenType.setValue(pkiAuthenticationToken.getEncodedCredentials());
        ReceivedToken receivedToken = mock(ReceivedToken.class);
        when(receivedToken.getToken()).thenReturn(binarySecurityTokenType);

        boolean result = pkiTokenValidator.canHandleToken(receivedToken);
        assertEquals(true, result);
    }

    @Test
    public void testCanNotHandleToken() {
        BinarySecurityTokenType binarySecurityTokenType = new BinarySecurityTokenType();
        binarySecurityTokenType.setEncodingType(WSConstants.SOAPMESSAGE_NS + "#Base64Binary");
        binarySecurityTokenType.setValueType("randomvaluetype");
        PKIAuthenticationTokenFactory pkiAuthenticationTokenFactory = new PKIAuthenticationTokenFactory();
        pkiAuthenticationTokenFactory.setSignaturePropertiesPath(
                PKITokenValidatorTest.class.getResource("/signature.properties").getPath());
        pkiAuthenticationTokenFactory.init();
        PKIAuthenticationToken pkiAuthenticationToken = pkiAuthenticationTokenFactory
                .getTokenFromCerts(certificates, "karaf");
        binarySecurityTokenType.setValue(pkiAuthenticationToken.getEncodedCredentials());
        ReceivedToken receivedToken = mock(ReceivedToken.class);
        when(receivedToken.getToken()).thenReturn(binarySecurityTokenType);

        boolean result = pkiTokenValidator.canHandleToken(receivedToken);
        assertEquals(false, result);
    }

    @Test
    public void testValidateToken() {
        BinarySecurityTokenType binarySecurityTokenType = new BinarySecurityTokenType();
        binarySecurityTokenType.setEncodingType(WSConstants.SOAPMESSAGE_NS + "#Base64Binary");
        binarySecurityTokenType.setValueType(PKIAuthenticationToken.PKI_TOKEN_VALUE_TYPE);
        PKIAuthenticationTokenFactory pkiAuthenticationTokenFactory = new PKIAuthenticationTokenFactory();
        pkiAuthenticationTokenFactory.setSignaturePropertiesPath(
                PKITokenValidatorTest.class.getResource("/signature.properties").getPath());
        pkiAuthenticationTokenFactory.init();
        PKIAuthenticationToken pkiAuthenticationToken = pkiAuthenticationTokenFactory
                .getTokenFromCerts(certificates, "karaf");
        binarySecurityTokenType.setValue(pkiAuthenticationToken.getEncodedCredentials());
        ReceivedToken receivedToken = mock(ReceivedToken.class);
        when(receivedToken.getToken()).thenReturn(binarySecurityTokenType);
        TokenValidatorParameters tokenValidatorParameters = mock(TokenValidatorParameters.class);
        STSPropertiesMBean stsPropertiesMBean = mock(STSPropertiesMBean.class);
        when(stsPropertiesMBean.getSignatureCrypto()).thenReturn(merlin);
        when(tokenValidatorParameters.getStsProperties()).thenReturn(stsPropertiesMBean);
        when(tokenValidatorParameters.getToken()).thenReturn(receivedToken);
        doCallRealMethod().when(receivedToken).setState(any(ReceivedToken.STATE.class));
        doCallRealMethod().when(receivedToken).getState();

        TokenValidatorResponse tokenValidatorResponse = pkiTokenValidator.validateToken(tokenValidatorParameters);
        assertEquals(ReceivedToken.STATE.VALID, tokenValidatorResponse.getToken().getState());

        assertEquals("US", tokenValidatorResponse.getAdditionalProperties().get(SubjectUtils.COUNTRY_CLAIM_URI));
        verifyEmail(tokenValidatorResponse, "localhost@example.org");
    }

    @Test
    public void testValidateSubjectAlternativeNameEmailToken() throws Exception {
        BinarySecurityTokenType binarySecurityTokenType = new BinarySecurityTokenType();
        binarySecurityTokenType.setEncodingType(WSConstants.SOAPMESSAGE_NS + "#Base64Binary");
        binarySecurityTokenType.setValueType(PKIAuthenticationToken.PKI_TOKEN_VALUE_TYPE);
        PKIAuthenticationTokenFactory pkiAuthenticationTokenFactory = new PKIAuthenticationTokenFactory();
        pkiAuthenticationTokenFactory.init();
        PKIAuthenticationToken pkiAuthenticationToken = pkiAuthenticationTokenFactory
                .getTokenFromCerts(userCertificates, "karaf");
        binarySecurityTokenType.setValue(pkiAuthenticationToken.getEncodedCredentials());
        ReceivedToken receivedToken = mock(ReceivedToken.class);
        when(receivedToken.getToken()).thenReturn(binarySecurityTokenType);
        TokenValidatorParameters tokenValidatorParameters = mock(TokenValidatorParameters.class);
        STSPropertiesMBean stsPropertiesMBean = mock(STSPropertiesMBean.class);
        when(stsPropertiesMBean.getSignatureCrypto()).thenReturn(merlin);
        when(tokenValidatorParameters.getStsProperties()).thenReturn(stsPropertiesMBean);
        when(tokenValidatorParameters.getToken()).thenReturn(receivedToken);
        doCallRealMethod().when(receivedToken).setState(any(ReceivedToken.STATE.class));
        doCallRealMethod().when(receivedToken).getState();

        TokenValidatorResponse tokenValidatorResponse = pkiTokenValidator.validateToken(tokenValidatorParameters);
        assertEquals(ReceivedToken.STATE.VALID, tokenValidatorResponse.getToken().getState());

        assertEquals("US", tokenValidatorResponse.getAdditionalProperties().get(SubjectUtils.COUNTRY_CLAIM_URI));

        verifyEmail(tokenValidatorResponse, "test2@test");
    }

    @Test
    public void testValidateAnyRealmToken() {
        BinarySecurityTokenType binarySecurityTokenType = new BinarySecurityTokenType();
        binarySecurityTokenType.setEncodingType(WSConstants.SOAPMESSAGE_NS + "#Base64Binary");
        binarySecurityTokenType.setValueType(PKIAuthenticationToken.PKI_TOKEN_VALUE_TYPE);
        PKIAuthenticationTokenFactory pkiAuthenticationTokenFactory = new PKIAuthenticationTokenFactory();
        pkiAuthenticationTokenFactory.setSignaturePropertiesPath(
                PKITokenValidatorTest.class.getResource("/signature.properties").getPath());
        pkiAuthenticationTokenFactory.init();
        PKIAuthenticationToken pkiAuthenticationToken = pkiAuthenticationTokenFactory
                .getTokenFromCerts(certificates, "*");
        binarySecurityTokenType.setValue(pkiAuthenticationToken.getEncodedCredentials());
        ReceivedToken receivedToken = mock(ReceivedToken.class);
        when(receivedToken.getToken()).thenReturn(binarySecurityTokenType);
        TokenValidatorParameters tokenValidatorParameters = mock(TokenValidatorParameters.class);
        STSPropertiesMBean stsPropertiesMBean = mock(STSPropertiesMBean.class);
        when(stsPropertiesMBean.getSignatureCrypto()).thenReturn(merlin);
        when(tokenValidatorParameters.getStsProperties()).thenReturn(stsPropertiesMBean);
        when(tokenValidatorParameters.getToken()).thenReturn(receivedToken);
        doCallRealMethod().when(receivedToken).setState(any(ReceivedToken.STATE.class));
        doCallRealMethod().when(receivedToken).getState();

        TokenValidatorResponse tokenValidatorResponse = pkiTokenValidator.validateToken(tokenValidatorParameters);
        assertEquals(ReceivedToken.STATE.VALID, tokenValidatorResponse.getToken().getState());

        assertEquals("US", tokenValidatorResponse.getAdditionalProperties().get(SubjectUtils.COUNTRY_CLAIM_URI));

        verifyEmail(tokenValidatorResponse, "localhost@example.org");
    }

    @Test
    public void testNoValidateToken() {
        BinarySecurityTokenType binarySecurityTokenType = new BinarySecurityTokenType();
        binarySecurityTokenType.setEncodingType(WSConstants.SOAPMESSAGE_NS + "#Base64Binary");
        binarySecurityTokenType.setValueType(PKIAuthenticationToken.PKI_TOKEN_VALUE_TYPE);
        PKIAuthenticationTokenFactory pkiAuthenticationTokenFactory = new PKIAuthenticationTokenFactory();
        pkiAuthenticationTokenFactory.setSignaturePropertiesPath(
                PKITokenValidatorTest.class.getResource("/badSignature.properties").getPath());
        pkiAuthenticationTokenFactory.init();
        PKIAuthenticationToken pkiAuthenticationToken = pkiAuthenticationTokenFactory
                .getTokenFromCerts(badCertificates, "karaf");
        binarySecurityTokenType.setValue(pkiAuthenticationToken.getEncodedCredentials());
        ReceivedToken receivedToken = mock(ReceivedToken.class);
        when(receivedToken.getToken()).thenReturn(binarySecurityTokenType);
        TokenValidatorParameters tokenValidatorParameters = mock(TokenValidatorParameters.class);
        STSPropertiesMBean stsPropertiesMBean = mock(STSPropertiesMBean.class);
        when(stsPropertiesMBean.getSignatureCrypto()).thenReturn(merlin);
        when(tokenValidatorParameters.getStsProperties()).thenReturn(stsPropertiesMBean);
        when(tokenValidatorParameters.getToken()).thenReturn(receivedToken);
        doCallRealMethod().when(receivedToken).setState(any(ReceivedToken.STATE.class));
        doCallRealMethod().when(receivedToken).getState();

        TokenValidatorResponse tokenValidatorResponse = pkiTokenValidator.validateToken(tokenValidatorParameters);
        assertEquals(ReceivedToken.STATE.INVALID, tokenValidatorResponse.getToken().getState());
    }

    private void verifyEmail(TokenValidatorResponse tokenValidatorResponse, String emailAddress) {
        List<String> emailAddresses = (List<String>) tokenValidatorResponse.getAdditionalProperties()
                .get(SubjectUtils.EMAIL_ADDRESS_CLAIM_URI);
        assertThat(emailAddresses, hasItem(emailAddress));
    }
}