/*
* ====================
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License("CDDL") (the "License"). You may not use this file
* except in compliance with the License.
*
* You can obtain a copy of the License at
* http://opensource.org/licenses/cddl1.php
* See the License for the specific language governing permissions and limitations
* under the License.
*
* When distributing the Covered Code, include this CDDL Header Notice in each file
* and include the License file at http://opensource.org/licenses/cddl1.php.
* If applicable, add the following below this CDDL Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
* ====================
*/
package org.identityconnectors.solaris;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.identityconnectors.common.CollectionUtil;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.common.security.GuardedString;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.solaris.test.SolarisTestBase;
import org.identityconnectors.solaris.test.SolarisTestCommon;
import org.junit.Ignore;
import org.testng.Assert;
import org.testng.annotations.Test;
public class SolarisConnectionTest extends SolarisTestBase {
private static final String TIMEOUT_BETWEEN_MSGS = "1";
private static final String LAST_ECHOED_INFO = "sausage.";
private final Log logger = Log.getLog(SolarisConnectionTest.class);
/**
* test connection to the configuration given by default credentials
* (build.groovy)
*/
@Test
public void testGoodConnection() {
SolarisConnector connector = new SolarisConnector();
connector.init(getConfiguration());
try {
connector.checkAlive();
} finally {
connector.dispose();
}
}
/**
* test that if an error occurs in the output, an exception is thrown.
*/
@Test
public void testErrorReplyScenario() {
Set<String> rejects = new HashSet<String>();
final String error = "ERROR";
rejects.add(error);
try {
getConnection().executeCommand(String.format("echo \"%s: ahoj ship\"", error), rejects);
fail("no exception thrown, when error found.");
} catch (ConnectorException e) {
// OK
}
}
@Test(enabled = false)
// TODO Fix this test
public void testErrorReplyScenarioWithTimeout() {
Set<String> rejects = new HashSet<String>();
final String errorMarker = "ERROR";
rejects.add(errorMarker);
try {
// Tougher test (it demands setting a long timeout on the
// connection.)
/*
* getConnection() .executeCommand( String.format(
* "timeout=\"%s\" && export timeout && echo \"%s: ahoj\" && sleep \"$timeout\" && echo \"ship\" && sleep \"$timeout\" && echo \"egg\" && sleep \"$timeout\" && echo \"spam\" && sleep \"$timeout\" && echo \"%s\""
* , TIMEOUT_BETWEEN_MSGS, ERROR_MARKER, LAST_ECHOED_INFO),
* rejects);
*/
// Weaker test
getConnection()
.executeCommand(
String.format(
"timeout=\"%s\" && export timeout && echo \"%s: ahoj\" && sleep \"$timeout\" && echo \"%s\"",
TIMEOUT_BETWEEN_MSGS, errorMarker, LAST_ECHOED_INFO), rejects);
fail("no exception thrown, when error found.");
} catch (ConnectorException e) {
final String exMsg = e.getMessage();
Assert.assertTrue(exMsg.contains(LAST_ECHOED_INFO), String.format(
"Buffer <%s> doesn't containt the last echoed info: '%s'.", exMsg,
LAST_ECHOED_INFO));
}
}
@Test
public void testSpecialAccepts() {
final String ahoj = "AHOJ";
final String errMarker = "ERROR";
getConnection().executeCommand(String.format("echo \"%s\"", ahoj),
Collections.<String> emptySet(), CollectionUtil.newSet(ahoj));
try {
getConnection().executeCommand(String.format("echo \"%s %s\"", errMarker, ahoj),
CollectionUtil.newSet(errMarker), CollectionUtil.newSet(ahoj));
fail("no exception thrown when error should be found in the output.");
} catch (ConnectorException ex) {
// OK
}
}
@Test
public void testSSHPubKeyConnection() {
if (!SolarisTestCommon.getProperty("unitTests.SolarisConnection.testSSHPubkeyMode",
Boolean.class)) {
logger.info("skipping testSSHPubKeyConnection test, because the resource doesn't support it.");
return;
}
// connection is recreated after every test method call so we are free
// to modify it.
SolarisConfiguration config = getConnection().getConfiguration();
config.setPassphrase(SolarisTestCommon.getProperty("rootPassphrase", GuardedString.class));
config.setPrivateKey(SolarisTestCommon.getProperty("rootPrivateKey", GuardedString.class));
config.setConnectionType(ConnectionType.SSHPUBKEY.toString());
SolarisConnection conn = new SolarisConnection(config);
String out = conn.executeCommand("echo 'ahoj ship'");
assertTrue(out.contains("ahoj ship"));
conn.dispose();
}
@Test
public void testSudoAuthorization() {
if (!SolarisTestCommon.getProperty("unitTests.SolarisConnection.testsudoAuthorization",
Boolean.class)) {
logger.info("skipping testSSHPubKeyConnection test, because the resource doesn't support it.");
return;
}
// connection is recreated after every test method call so we are free
// to modify it.
SolarisConfiguration config = getConnection().getConfiguration();
config.setSudoAuthorization(true);
SolarisConnection conn = new SolarisConnection(config);
String out = conn.executeCommand("echo 'ahoj ship'");
assertTrue(out.contains("ahoj ship"));
conn.dispose();
}
@Test
public void checkAliveTest() {
try {
getConnection().checkAlive();
} catch (Exception ex) {
fail("no exception is expected.");
}
getConnection().dispose();
try {
getConnection().checkAlive();
fail("exception should be thrown");
} catch (Exception ex) {
// OK
}
}
/**
* verify if the connector is resistant to password exploits. Password is
* invalid if it contains control characters (such as carriage return and
* newline).
*/
@Test
public void testPasswordExploit() {
// we shouldn't be able to send some special characters with the
// password!
String exploit = "nonSensePassWord \n echo 'Popeye'";
try {
getConnection().sendPassword(new GuardedString(exploit.toCharArray()));
fail("no exception thrown upon sending a password exploit.");
} catch (IllegalArgumentException ex) {
// OK
}
}
@Test
public void testConnectorConstruction() {
//
boolean isSudoAuthorization = false;
try {
isSudoAuthorization =
SolarisTestCommon.getProperty(
"unitTests.SolarisConnection.testsudoAuthorization", Boolean.class);
} catch (Exception ex) {
// OK
}
implTestConnectorConstruction(isSudoAuthorization);
}
private void implTestConnectorConstruction(boolean isSudoAuthorization) {
SolarisConfiguration config = reloadConfig(isSudoAuthorization);
// negative test: bad host
config.setHost("111.111.111.111");
try {
new SolarisConnection(config).checkAlive();
fail("Expected bad host to fail.");
} catch (Exception ex) {
// OK
}
// negative test: bad port
config = reloadConfig(isSudoAuthorization);
config.setPort(1);
try {
new SolarisConnection(config).checkAlive();
fail("Expected bad port to fail.");
} catch (Exception ex) {
// OK
}
// negative test: bad admin
config = reloadConfig(isSudoAuthorization);
if (!isSudoAuthorization) {
config.setRootUser("badAdminUser");
} else {
config.setLoginUser("badAdminUser");
}
try {
new SolarisConnection(config).checkAlive();
fail("Expected bad admin to fail.");
} catch (Exception ex) {
// OK
}
// negative test: bad admin password
// avoiding bad admin password test for SSHPubKey connection
// as it does not use the password at all.
if (!ConnectionType.toConnectionType(config.getConnectionType()).equals(
ConnectionType.SSHPUBKEY)) {
config = reloadConfig(isSudoAuthorization);
if (!isSudoAuthorization) {
config.setCredentials(new GuardedString("badPassword".toCharArray()));
} else {
config.setPassword(new GuardedString("badPassword".toCharArray()));
}
try {
new SolarisConnection(config).checkAlive();
fail("Expected bad admin password to fail.");
} catch (Exception ex) {
// OK
}
}
// negative test: bad shell prompt
config = reloadConfig(isSudoAuthorization);
if (!isSudoAuthorization) {
config.setRootShellPrompt("badRootShellPrompt");
} else {
config.setLoginShellPrompt("badLoginShellPrompt");
}
try {
new SolarisConnection(config).checkAlive();
fail("Expected bad shell prompt to fail.");
} catch (Exception ex) {
// OK
}
// negative test: bad conn type
config = reloadConfig(isSudoAuthorization);
try {
config.setConnectionType("nonExistingConnetionType");
new SolarisConnection(config).checkAlive();
fail("Expected bad connection type to fail.");
} catch (Exception ex) {
// OK
}
}
private SolarisConfiguration reloadConfig(boolean isSudoAuthorization) {
SolarisConfiguration config = getConnection().getConfiguration();
if (isSudoAuthorization) {
config.setSudoAuthorization(true);
}
return config;
}
/**
* test that repetitive open of sessions doesn't cause exception. This test
* shows if some resources are not cleaned up properly.
*
* These tests verify Issue #614. Turned off, just in cases of changes to
* SolarisConnection are these tests needed.
*/
@Test
@Ignore
public void testSessionSSHClose() {
SolarisConfiguration config = SolarisTestCommon.createConfiguration();
testSessionRepetitiveCreation(config);
}
@Test(enabled = false)
private void testSessionRepetitiveCreation(SolarisConfiguration config) {
try {
for (int i = 0; i < 100; i++) {
SolarisConnection connection = new SolarisConnection(config);
try {
// empty on purpose
} finally {
if (connection != null) {
connection.dispose();
}
}
}
} catch (Exception ex) {
fail("no exception should be thrown when cyclically calling creating and closing a connection.");
}
}
/**
* analogical to {@link SolarisConnectionTest#testSessionSSHClose()} These
* tests verify Issue #614. Turned off, just in cases of changes to
* SolarisConnection are these tests needed.
*/
@Test
@Ignore
public void testSSHPubKeySessionClose() {
if (!SolarisTestCommon.getProperty("unitTests.SolarisConnection.testSSHPubkeyMode",
Boolean.class)) {
logger.info("skipping testSSHPubKeyConnection test, because the resource doesn't support it.");
return;
}
SolarisConfiguration config = getConnection().getConfiguration();
config.setPassphrase(SolarisTestCommon.getProperty("rootPassphrase", GuardedString.class));
config.setPrivateKey(SolarisTestCommon.getProperty("rootPrivateKey", GuardedString.class));
config.setConnectionType(ConnectionType.SSHPUBKEY.toString());
testSessionRepetitiveCreation(config);
}
/**
* this test needs a 'isVersionLT10' test property defined.
*/
@Test
public void testIsVersionLT10() {
final String testPropName = "unitTests.isVersionLT10";
boolean isVersionLT10expected = false;
try {
isVersionLT10expected = SolarisTestCommon.getProperty(testPropName, Boolean.class);
} catch (IllegalArgumentException ex) {
logger.info("skipping testIsVersionLT10() because test property '" + testPropName
+ "' is not defined.");
}
assertEquals(isVersionLT10expected, getConnection().isVersionLT10());
}
@Override
public boolean createGroup() {
return false;
}
@Override
public int getCreateUsersNumber() {
return 0;
}
}