/** * 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.admin.insecure.defaults.service; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.junit.After; import org.junit.Before; import org.junit.Test; import ddf.security.SecurityConstants; public class KeystoreValidatorTest { private static final String DEFAULT_BLACKLIST_PASSWORD = "changeit"; private static final String INVALID_BLACKLIST_PASSWORD = "invalid"; private static final String BLACK_LIST = "/blacklisted.jks"; private static final Path FAKE_BLACK_LIST_PATH = Paths.get("/fakeblacklisted.jks"); private static final String INSECURE_KEYSTORE = "/insecureKeystore.jks"; private static final String FAKE_KEYSTORE = "/fakeKeystore.jks"; private static final String SECURE_KEYSTORE = "/secureKeystore.jks"; private static final String SECURE_KEYSTORE_PASSWORD = "password"; private static final String DEFAULT_KEYSTORE_PASSWORD = "changeit"; private static final String INSECURE_KEYSTORE_PASSWORD = "changeit"; private static final String INVALID_KEYSTORE_PASSWORD = "invalid"; private static final String INSECURE_TRUSTSTORE = "/insecureTruststore.jks"; private static final String SECURE_TRUSTSTORE = "/secureTruststore.jks"; private static final String DEFAULT_TRUSTSTORE_PASSWORD = "changeit"; private static final String INSECURE_TRUSTSTORE_PASSWORD = "changeit"; private static final String SECURE_TRUSTSTORE_PASSWORD = "password"; private static final String DEFAULT_KEY_PASSWORD = "changeit"; private static final String DEFAULT_ALIAS = "localhost"; private static final String DEFAULT_ROOT_CA = "ddf demo root ca"; private static final String KEYSTORE_NULL_PATH = "Unable to determine if keystore is using insecure defaults. No keystore path provided."; private static final String BLACKLIST_NULL_PATH = "No Blacklist keystore path provided"; private static final String BLACKLIST_NULL_PASS = "Password for Blacklist keystore"; private static final String DEFAULT_KEY_NULL_PASS = "No key password provided"; private static final String KEYSTORE_NULL_PASS = "No keystore password provided"; private static Properties properties; @Before public void setUp() { properties = System.getProperties(); System.setProperty(SecurityConstants.KEYSTORE_TYPE, "JKS"); } @After public void tearDown() { System.setProperties(properties); } @Test public void testInvalidPasswordForBlacklistKeystore() throws Exception { // Setup KeystoreValidator keystoreValidator = new KeystoreValidator(); Path blacklistPath = Paths.get(getClass().getResource(BLACK_LIST) .toURI()); keystoreValidator.setBlacklistKeystorePath(blacklistPath); keystoreValidator.setBlacklistKeystorePassword(INVALID_BLACKLIST_PASSWORD); Path keystorePath = Paths.get(getClass().getResource(INSECURE_KEYSTORE) .toURI()); keystoreValidator.setKeystorePath(keystorePath); keystoreValidator.setKeystorePassword(INSECURE_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(DEFAULT_KEY_PASSWORD); // Perform Test List<Alert> alerts = keystoreValidator.validate(); // Verify List<String> actualAlertMessages = getActualAlertMessages(alerts); String[] expectedAlertMessages = new String[] {String.format(KeystoreValidator.DEFAULT_KEY_PASSWORD_USED_MSG, DEFAULT_ALIAS, keystorePath, DEFAULT_KEY_PASSWORD), String.format(KeystoreValidator.DEFAULT_KEYSTORE_PASSWORD_USED_MSG, keystorePath, DEFAULT_KEYSTORE_PASSWORD), String.format(KeystoreValidator.INVALID_BLACKLIST_KEYSTORE_PASSWORD_MSG, keystorePath, blacklistPath, "Keystore was tampered with, or password was incorrect")}; assertThat(alerts.size(), is(3)); assertThat(actualAlertMessages, hasItems(expectedAlertMessages)); } @Test public void testBlacklistKeystoreDoesNotExist() throws Exception { // Setup KeystoreValidator keystoreValidator = new KeystoreValidator(); keystoreValidator.setBlacklistKeystorePath(FAKE_BLACK_LIST_PATH); keystoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); Path path = Paths.get(getClass().getResource(INSECURE_KEYSTORE) .toURI()); keystoreValidator.setKeystorePath(path); keystoreValidator.setKeystorePassword(INSECURE_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(DEFAULT_KEY_PASSWORD); // Perform Test List<Alert> alerts = keystoreValidator.validate(); // Verify assertThat(alerts.size(), is(3)); List<String> actualMessages = getActualAlertMessages(alerts); String[] expectedAlertMessages = new String[] {String.format(KeystoreValidator.DEFAULT_KEY_PASSWORD_USED_MSG, DEFAULT_ALIAS, path, DEFAULT_KEY_PASSWORD), String.format(KeystoreValidator.DEFAULT_KEYSTORE_PASSWORD_USED_MSG, path, DEFAULT_KEYSTORE_PASSWORD), String.format(KeystoreValidator.BLACKLIST_KEYSTORE_DOES_NOT_EXIST_MSG, path, FAKE_BLACK_LIST_PATH, FAKE_BLACK_LIST_PATH)}; assertThat(actualMessages, hasItems(expectedAlertMessages)); } @Test public void testKeystoreDoesNotExist() throws Exception { // Setup KeystoreValidator keystoreValidator = new KeystoreValidator(); keystoreValidator.setBlacklistKeystorePath(Paths.get(getClass().getResource(BLACK_LIST) .toURI())); keystoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); keystoreValidator.setKeystorePath(Paths.get(FAKE_KEYSTORE)); keystoreValidator.setKeystorePassword(INSECURE_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(DEFAULT_KEY_PASSWORD); // Perform Test List<Alert> alerts = keystoreValidator.validate(); // Verify assertThat(alerts.size(), is(1)); assertThat(alerts.get(0) .getMessage(), is(String.format(KeystoreValidator.KEYSTORE_DOES_NOT_EXIST_MSG, Paths.get(FAKE_KEYSTORE), ""))); } @Test public void testInvalidPasswordForKeystore() throws Exception { // Setup KeystoreValidator keystoreValidator = new KeystoreValidator(); keystoreValidator.setBlacklistKeystorePath(Paths.get(getClass().getResource(BLACK_LIST) .toURI())); keystoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); Path path = Paths.get(getClass().getResource(INSECURE_KEYSTORE) .toURI()); keystoreValidator.setKeystorePath(path); keystoreValidator.setKeystorePassword(INVALID_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(DEFAULT_KEY_PASSWORD); // Perform Test List<Alert> alerts = keystoreValidator.validate(); // Verify assertThat(alerts.size(), is(1)); assertThat(alerts.get(0) .getMessage(), is(String.format(KeystoreValidator.GENERIC_INSECURE_DEFAULTS_MSG, path) + "Keystore was tampered with, or password was incorrect.")); } @Test public void testKeystoreContainsInsecureDefaults() throws Exception { // Setup KeystoreValidator keystoreValidator = new KeystoreValidator(); keystoreValidator.setBlacklistKeystorePath(Paths.get(getClass().getResource(BLACK_LIST) .toURI())); keystoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); Path keystorePath = Paths.get(getClass().getResource(INSECURE_KEYSTORE) .toURI()); keystoreValidator.setKeystorePath(keystorePath); keystoreValidator.setKeystorePassword(INSECURE_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(DEFAULT_KEY_PASSWORD); // Perform Test List<Alert> alerts = keystoreValidator.validate(); // Verify List<String> actualAlertMessages = getActualAlertMessages(alerts); String[] expectedAlertMessages = new String[] { String.format(KeystoreValidator.CERT_CHAIN_CONTAINS_BLACKLISTED_CERT_MSG, DEFAULT_ALIAS, keystorePath, DEFAULT_ROOT_CA), String.format(KeystoreValidator.CERT_CHAIN_CONTAINS_BLACKLISTED_CERT_MSG, DEFAULT_ALIAS, keystorePath, DEFAULT_ALIAS), String.format(KeystoreValidator.CERT_IS_BLACKLISTED_MSG, DEFAULT_ROOT_CA, keystorePath, DEFAULT_ROOT_CA), String.format(KeystoreValidator.DEFAULT_KEY_PASSWORD_USED_MSG, DEFAULT_ALIAS, keystorePath, DEFAULT_KEY_PASSWORD), String.format(KeystoreValidator.DEFAULT_KEYSTORE_PASSWORD_USED_MSG, keystorePath, DEFAULT_KEYSTORE_PASSWORD)}; assertThat(alerts.size(), is(5)); assertThat(actualAlertMessages, hasItems(expectedAlertMessages)); } @Test public void testTruststoreContainsInsecureDefaults() throws Exception { // Setup KeystoreValidator truststoreValidator = new KeystoreValidator(); truststoreValidator.setBlacklistKeystorePath(Paths.get(getClass().getResource(BLACK_LIST) .toURI())); truststoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); Path path = Paths.get(getClass().getResource(INSECURE_TRUSTSTORE) .toURI()); truststoreValidator.setKeystorePath(path); truststoreValidator.setKeystorePassword(INSECURE_TRUSTSTORE_PASSWORD); truststoreValidator.setDefaultKeystorePassword(DEFAULT_TRUSTSTORE_PASSWORD); // Perform Test List<Alert> alerts = truststoreValidator.validate(); // Verify List<String> actualAlertMessages = getActualAlertMessages(alerts); String[] expectedAlertMessages = new String[] {String.format(KeystoreValidator.CERT_IS_BLACKLISTED_MSG, DEFAULT_ROOT_CA, path, DEFAULT_ROOT_CA), String.format(KeystoreValidator.DEFAULT_KEYSTORE_PASSWORD_USED_MSG, path, DEFAULT_KEYSTORE_PASSWORD)}; assertThat(alerts.size(), is(2)); assertThat(actualAlertMessages, hasItems(expectedAlertMessages)); } @Test public void testKeystoreContainsNoInsecureDefaults() throws Exception { // Setup KeystoreValidator keystoreValidator = new KeystoreValidator(); keystoreValidator.setBlacklistKeystorePath(Paths.get(getClass().getResource(BLACK_LIST) .toURI())); keystoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); keystoreValidator.setKeystorePath(Paths.get(getClass().getResource(SECURE_KEYSTORE) .toURI())); keystoreValidator.setKeystorePassword(SECURE_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(DEFAULT_KEY_PASSWORD); // Perform Test List<Alert> alerts = keystoreValidator.validate(); // Verify assertThat(alerts.size(), is(0)); } @Test public void testTruststoreContainsNoInsecureDefaults() throws Exception { // Setup KeystoreValidator truststoreValidator = new KeystoreValidator(); truststoreValidator.setBlacklistKeystorePath(Paths.get(getClass().getResource(BLACK_LIST) .toURI())); truststoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); truststoreValidator.setKeystorePath(Paths.get(getClass().getResource(SECURE_TRUSTSTORE) .toURI())); truststoreValidator.setKeystorePassword(SECURE_TRUSTSTORE_PASSWORD); truststoreValidator.setDefaultKeystorePassword(DEFAULT_TRUSTSTORE_PASSWORD); // Perform Test List<Alert> alerts = truststoreValidator.validate(); // Verify assertThat(alerts.size(), is(0)); } /** * Tests the {@link KeystoreValidator#validate()} method and its associated methods * for the case where the path is not set * * @throws Exception */ @Test public void testKeystoreNullPath() throws Exception { KeystoreValidator keystoreValidator = new KeystoreValidator(); keystoreValidator.setBlacklistKeystorePath(Paths.get(getClass().getResource(BLACK_LIST) .toURI())); keystoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); keystoreValidator.setKeystorePath(null); keystoreValidator.setKeystorePassword(SECURE_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(DEFAULT_KEY_PASSWORD); List<Alert> alerts = keystoreValidator.validate(); assertThat("Should report a warning about the keystore path.", alerts.get(0) .getMessage(), containsString(KEYSTORE_NULL_PATH)); } /** * Tests the {@link KeystoreValidator#validate()} method and its associated methods * for the case where the blacklist path is not set * * @throws Exception */ @Test public void testKeystoreNullBlacklistPath() throws Exception { KeystoreValidator keystoreValidator = new KeystoreValidator(); keystoreValidator.setBlacklistKeystorePath(null); keystoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); keystoreValidator.setKeystorePath(Paths.get(getClass().getResource(SECURE_KEYSTORE) .toURI())); keystoreValidator.setKeystorePassword(SECURE_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(DEFAULT_KEY_PASSWORD); List<Alert> alerts = keystoreValidator.validate(); assertThat("Should report a warning about the Blacklist Keystore path.", alerts.get(0) .getMessage(), containsString(BLACKLIST_NULL_PATH)); } /** * Tests the {@link KeystoreValidator#validate()} method and its associated methods * for the case where the blacklist password is not set * * @throws Exception */ @Test public void testKeystoreNullBlacklistPassword() throws Exception { KeystoreValidator keystoreValidator = new KeystoreValidator(); keystoreValidator.setBlacklistKeystorePath(Paths.get(getClass().getResource(BLACK_LIST) .toURI())); keystoreValidator.setBlacklistKeystorePassword(null); keystoreValidator.setKeystorePath(Paths.get(getClass().getResource(SECURE_KEYSTORE) .toURI())); keystoreValidator.setKeystorePassword(SECURE_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(DEFAULT_KEY_PASSWORD); List<Alert> alerts = keystoreValidator.validate(); assertThat("Should report a warning about the Blacklist Keystore password.", alerts.get(0) .getMessage(), containsString(BLACKLIST_NULL_PASS)); } /** * Tests the {@link KeystoreValidator#validate()} method and its associated methods * for the case where the default key password is not set * * @throws Exception */ @Test public void testKeystoreNullDefaultKeyPassword() throws Exception { KeystoreValidator keystoreValidator = new KeystoreValidator(); keystoreValidator.setBlacklistKeystorePath(Paths.get(getClass().getResource(BLACK_LIST) .toURI())); keystoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); keystoreValidator.setKeystorePath(Paths.get(getClass().getResource(SECURE_KEYSTORE) .toURI())); keystoreValidator.setKeystorePassword(SECURE_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(null); List<Alert> alerts = keystoreValidator.validate(); assertThat("Should report a warning about the default key password.", alerts.get(0) .getMessage(), containsString(DEFAULT_KEY_NULL_PASS)); } /** * Tests the {@link KeystoreValidator#validate()} method and its associated methods * for the case where the keystore password is not set * * @throws Exception */ @Test public void testKeystoreNullKeystorePassword() throws Exception { KeystoreValidator keystoreValidator = new KeystoreValidator(); keystoreValidator.setBlacklistKeystorePath(Paths.get(getClass().getResource(BLACK_LIST) .toURI())); keystoreValidator.setBlacklistKeystorePassword(DEFAULT_BLACKLIST_PASSWORD); keystoreValidator.setKeystorePath(Paths.get(getClass().getResource(SECURE_KEYSTORE) .toURI())); keystoreValidator.setKeystorePassword(null); keystoreValidator.setDefaultKeystorePassword(DEFAULT_KEYSTORE_PASSWORD); keystoreValidator.setDefaultKeyPassword(DEFAULT_KEY_PASSWORD); List<Alert> alerts = keystoreValidator.validate(); assertThat("Should report a warning about the keystore password.", alerts.get(0) .getMessage(), containsString(KEYSTORE_NULL_PASS)); } private List<String> getActualAlertMessages(List<Alert> alerts) { List<String> messages = new ArrayList<>(alerts.size()); for (Alert alert : alerts) { messages.add(alert.getMessage()); } return messages; } }