| /* |
| * 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 ); |
| } |
| } |