blob: 27ee737563ff4c3ad9d9bd57525e378408a1ec4c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); 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.
*
*/
package org.apache.directory.server;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
import javax.security.auth.x500.X500Principal;
import org.apache.directory.api.ldap.codec.api.SchemaBinaryAttributeDetector;
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.DefaultModification;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.ModificationOperation;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.util.Network;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.ldap.client.api.LdapConnectionConfig;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.directory.server.constants.ServerDNConstants;
import org.apache.directory.server.core.api.partition.PartitionNexus;
import org.apache.directory.server.core.security.CertificateUtil;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
* Test case for the UberJarMain class.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class UberJarMainTest
{
/** Flag used by connection verification thread */
private boolean verified = true;
/** The instance directory */
private File instanceDirectory;
/** The UberjarMain */
private UberjarMain uberjarMain;
private KeyStore keyStore;
@BeforeEach
public void create()
{
// Getting tmp directory
File tmpDirectory = new File( System.getProperty( "java.io.tmpdir" ) );
tmpDirectory.deleteOnExit();
// Creating an instance directory
Calendar calendar = Calendar.getInstance( TimeZone.getTimeZone( "UTC" ), Locale.ROOT );
instanceDirectory = new File( tmpDirectory, "ApacheDS-" + calendar.get( Calendar.YEAR )
+ calendar.get( Calendar.MONTH ) + calendar.get( Calendar.DATE ) + calendar.get( Calendar.HOUR )
+ calendar.get( Calendar.MINUTE ) + calendar.get( Calendar.SECOND ) );
instanceDirectory.mkdir();
// Creating the UberjarMain
uberjarMain = new UberjarMain();
try
{
// Create a temporary keystore, be sure to remove it when exiting the test
File keyStoreFile = File.createTempFile( "testStore", "ks" );
keyStoreFile.deleteOnExit();
keyStore = KeyStore.getInstance( KeyStore.getDefaultType() );
char[] keyStorePassword = "secret".toCharArray();
try ( InputStream keyStoreData = new FileInputStream( keyStoreFile ) )
{
keyStore.load( null, keyStorePassword );
}
// Generate the asymmetric keys, using EC algorithm
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( "EC" );
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// Generate the subject's name
X500Principal owner = new X500Principal( "CN=apacheds,OU=directory,O=apache,C=US" );
// Create the self-signed certificate
X509Certificate certificate = CertificateUtil.generateSelfSignedCertificate( owner, keyPair, 365,
"SHA256WithECDSA" );
keyStore.setKeyEntry( "apachedsKey", keyPair.getPrivate(), keyStorePassword, new X509Certificate[]
{ certificate } );
try ( FileOutputStream out = new FileOutputStream( keyStoreFile ) )
{
keyStore.store( out, keyStorePassword );
}
}
catch ( Exception e )
{
}
}
@AfterEach
public void delete() throws Exception
{
if ( uberjarMain != null )
{
uberjarMain.stop();
}
}
private LdapConnection createConnection() throws LdapException, UnknownHostException
{
LdapConnectionConfig configuration = new LdapConnectionConfig();
configuration.setLdapHost( Network.LOOPBACK_HOSTNAME );
configuration.setLdapPort( 10389 );
configuration.setName( ServerDNConstants.ADMIN_SYSTEM_DN );
configuration.setCredentials( PartitionNexus.ADMIN_PASSWORD_STRING );
configuration.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( null ) );
LdapConnection connection = new LdapNetworkConnection( configuration );
connection.connect();
connection.loadSchema();
// Binding on the connection
connection.bind();
return connection;
}
private Thread createServer()
{
// First start the server to initialize the example partition
uberjarMain.start( instanceDirectory.toString() );
// Creating a separate thread for the connection verification
Thread connectionVerificationThread = new Thread()
{
public void run()
{
LdapConnection connection = null;
try
{
// Creating a connection on the created server
connection = createConnection();
// Looking for the Root DSE entry
Entry rootDseEntry = connection.lookup( Dn.ROOT_DSE );
if ( rootDseEntry == null )
{
// This isn't good
verified = false;
return;
}
}
catch ( Exception e )
{
verified = false;
e.printStackTrace();
}
finally
{
try
{
connection.close();
}
catch ( Exception e )
{
// nothing we can do
}
}
};
};
return connectionVerificationThread;
}
/**
* Tests the creation of a new ApacheDS Service instance.
*
* @throws Exception
*/
@Test
public void nisTest() throws Exception
{
// First start the server to initialize the example partition
uberjarMain.start( instanceDirectory.toString() );
// Creating a separate thread for the connection verification
Thread connectionVerificationThread = new Thread()
{
public void run()
{
LdapConnection connection = null;
try
{
// Creating a connection on the created server
connection = createConnection();
connection.modify( "cn=nis,ou=schema",
new DefaultModification(
ModificationOperation.REPLACE_ATTRIBUTE, "m-disabled", "FALSE" ) );
// Reload the schema in order to be able to deal with NIS elements
connection.loadSchema();
// Ok, now try to fetch the NIS schema elements
Entry nisSchema = connection.lookup( "cn=nis,ou=schema" );
assertEquals( "FALSE", nisSchema.get( "m-disabled" ).getString() );
Entry posixAccount = connection.lookup( "m-oid=1.3.6.1.1.1.2.0,ou=objectClasses,cn=nis,ou=schema" );
if ( posixAccount == null )
{
// This isn't good
verified = false;
return;
}
}
catch ( Exception e )
{
e.printStackTrace();
verified = false;
}
finally
{
try
{
connection.close();
}
catch ( Exception e )
{
// nothing we can do
}
}
};
};
connectionVerificationThread.start();
connectionVerificationThread.join();
// Checking if verification is successful
if ( !verified )
{
fail();
}
}
/**
* Tests the creation of a new ApacheDS Service instance.
*
* @throws Exception
*/
@Test
public void serviceInstanceTest() throws Exception
{
Thread connectionVerificationThread = createServer();
// Starting the connection verification thread
// and waiting for the termination of it
connectionVerificationThread.start();
connectionVerificationThread.join();
// Checking if verification is successful
if ( !verified )
{
fail();
}
// Stop the server
uberjarMain.stop();
// Restart the server
uberjarMain.start( instanceDirectory.toString() );
LdapConnection connection = null;
try
{
// Creating a connection on the created server
connection = createConnection();
// Looking for the Root DSE entry
Entry rootDseEntry = connection.lookup( Dn.ROOT_DSE );
Entry nisSchema = connection.lookup( "cn=nis,ou=schema" );
Entry nisObjectClass = connection.lookup( "ou=objectClasses,cn=nis,ou=schema" );
Entry posixAccount = connection.lookup( "m-oid=1.3.6.1.1.1.2.0,ou=objectClasses,cn=nis,ou=schema" );
if ( rootDseEntry == null )
{
// This isn't good
verified = false;
return;
}
}
catch ( Exception e )
{
verified = false;
e.printStackTrace();
}
finally
{
try
{
connection.close();
}
catch ( Exception e )
{
// nothing we can do
}
}
}
/**
* Tests the repair of an existing ApacheDS Service instance.
*
* @throws Exception
*/
@Test
public void repairTest() throws Exception
{
// First start the server to initialize the example partition
Thread connectionVerificationThread = createServer();
// Starting the connection verification thread
// and waiting for the termination of it
connectionVerificationThread.start();
connectionVerificationThread.join();
// Checking if verification is successful
if ( !verified )
{
fail();
}
// Add a few entries to create a more complex hierarchy
// We will have :
// dc=example,dc=com
// ou=people
// ou=committers
// cn=emmanuel
// cn=kiran
// cn=stefan
// cn=radovan
// ou=pmcs
// cn=emmanuel
// cn=kiran
// cn=stefan
// ou=groups
// cn=users
LdapConnection connection = createConnection();
// First level
Entry people = new DefaultEntry(
"ou=People,dc=example,dc=com",
"objectClass: organizationalUnit",
"objectClass: top",
"ou: People" );
connection.add( people );
Entry groups = new DefaultEntry(
"ou=Groups,dc=example,dc=com",
"objectClass: organizationalUnit",
"objectClass: top",
"ou: Groups" );
connection.add( groups );
// Second level
Entry committers = new DefaultEntry(
"ou=Committers,ou=people,dc=example,dc=com",
"objectClass: organizationalUnit",
"objectClass: top",
"ou: Committers" );
connection.add( committers );
Entry pmcs = new DefaultEntry(
"ou=Pmcs,ou=people,dc=example,dc=com",
"objectClass: organizationalUnit",
"objectClass: top",
"ou: Pmcs" );
connection.add( pmcs );
Entry users = new DefaultEntry(
"ou=Users,ou=people,dc=example,dc=com",
"objectClass: organizationalUnit",
"objectClass: top",
"ou: Users" );
connection.add( users );
// Third level, committers
Entry emmanuelCommitter = new DefaultEntry(
"cn=emmanuel,ou=Committers,ou=people,dc=example,dc=com",
"objectClass: person",
"objectClass: top",
"cn: emmanuel",
"sn: Emmanuel Lecharny" );
connection.add( emmanuelCommitter );
Entry kiranCommitter = new DefaultEntry(
"cn=kiran,ou=Committers,ou=people,dc=example,dc=com",
"objectClass: person",
"objectClass: top",
"cn: kiran",
"sn: Kiran Ayyagari" );
connection.add( kiranCommitter );
Entry stefanCommitter = new DefaultEntry(
"cn=stefan,ou=Committers,ou=people,dc=example,dc=com",
"objectClass: person",
"objectClass: top",
"cn: stefan",
"sn: Stefan Seelmann" );
connection.add( stefanCommitter );
Entry radovanCommitter = new DefaultEntry(
"cn=radovan,ou=Committers,ou=people,dc=example,dc=com",
"objectClass: person",
"objectClass: top",
"cn: radovan",
"sn: Radovan Semancik" );
connection.add( radovanCommitter );
// Third level, PMCs
Entry emmanuelPmc = new DefaultEntry(
"cn=emmanuel,ou=Pmcs,ou=people,dc=example,dc=com",
"objectClass: person",
"objectClass: top",
"cn: emmanuel",
"sn: Emmanuel Lecharny" );
connection.add( emmanuelPmc );
Entry kiranPmc = new DefaultEntry(
"cn=kiran,ou=Pmcs,ou=people,dc=example,dc=com",
"objectClass: person",
"objectClass: top",
"cn: kiran",
"sn: Kiran Ayyagari" );
connection.add( kiranPmc );
Entry stefanPmc = new DefaultEntry(
"cn=stefan,ou=Pmcs,ou=people,dc=example,dc=com",
"objectClass: person",
"objectClass: top",
"cn: stefan",
"sn: Stefan Seelmann" );
connection.add( stefanPmc );
// Now, check that we have 13 entries
int entryCount = 0;
EntryCursor cursor = connection.search( "dc=example, dc=com", "(ObjectClass=*)", SearchScope.SUBTREE, "*" );
while ( cursor.next() )
{
cursor.get();
entryCount++;
}
assertEquals( 13, entryCount );
// Stop the server
uberjarMain.stop();
// Try to repair it (also starts and stops the server)
uberjarMain.repair( instanceDirectory.toString() );
// And restart it
connectionVerificationThread = createServer();
// Starting the connection verification thread
// and waiting for the termination of it
connectionVerificationThread.start();
connectionVerificationThread.join();
// Checking if verification is successful
if ( !verified )
{
fail();
}
// Check the content
connection = createConnection();
entryCount = 0;
cursor = connection.search( "dc=example, dc=com", "(ObjectClass=*)", SearchScope.SUBTREE, "*" );
while ( cursor.next() )
{
cursor.get();
entryCount++;
}
assertEquals( 13, entryCount );
}
}