package io.github.olivierlemasle.tests.it;

import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import io.github.olivierlemasle.ca.CA;
import io.github.olivierlemasle.ca.CSR;
import io.github.olivierlemasle.ca.CertificateAuthority;
import io.github.olivierlemasle.ca.DistinguishedName;

import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class OpenSslIT {

  @BeforeClass
  @AfterClass
  public static void clean() {
    final File caCertPath = new File("ca.cer");
    caCertPath.delete();
    final File reqPath = new File("cert.req");
    reqPath.delete();
    final File certPath = new File("cert.cer");
    certPath.delete();
  }

  @Before
  public void checkPlatform() {
    assumeFalse(TestUtils.isWindows());
    assumeTrue(TestUtils.opensslExists());
  }

  @Test
  public void completeTest() throws IOException, InterruptedException, NoSuchAlgorithmException,
      KeyStoreException, KeyManagementException, CertificateException {
    // Create a CA
    System.out.println("Generate CA...");
    final DistinguishedName caName = CA.dn("CN=CA-Test");
    final CertificateAuthority ca = CA.init().setName(caName).build();
    // Export the CA certificate
    final X509Certificate caCert = ca.getCaCertificate();
    CA.export(caCert).saveCertificate("ca.cer");
    System.out.println("CA ready. CA certificate saved to \"ca.cer\".");

    // Generate CSR using OpenSSL
    System.out.println("Generate CSR with \"CSR.csr\"...");
    generateCsr();

    // Load the generated CSR, sign it and export the resulting certificate
    System.out.println("Sign CSR...");
    final CSR csr = CA.loadCsr("CSR.csr").getCsr();
    final X509Certificate cert = ca.sign(csr);
    CA.export(cert).saveCertificate("cert.cer");
    System.out.println("CSR signed. Certificate saved to \"cert.cer\".");

    // Reload Apache2 server
    System.out.println("Reload Apache2 server");
    apache2ServerReload();
  }

  /**
   * {@code openssl req -nodes -newkey rsa:2048 -keyout private.key -out CSR.csr -subj "/CN=localhost"}
   * 
   * @throws IOException
   * @throws InterruptedException
   */
  private void generateCsr() throws IOException, InterruptedException {
    final Process process = new ProcessBuilder("openssl", "req", "-nodes", "-newkey", "rsa:2048",
        "-keyout", "private.key", "-out", "CSR.csr", "-subj", "/CN=localhost")
        .redirectError(Redirect.INHERIT)
        .redirectOutput(Redirect.INHERIT)
        .start();

    process.waitFor();
  }

  /**
   * {@code sudo service apache2 reload}
   * 
   * @throws IOException
   * @throws InterruptedException
   */
  private void apache2ServerReload() throws IOException, InterruptedException {
    final Process process = new ProcessBuilder("sudo", "service", "apache2", "reload")
        .redirectError(Redirect.INHERIT)
        .redirectOutput(Redirect.INHERIT)
        .start();

    process.waitFor();
  }

}

@@ -37,16 +37,59 @@
 ts.it;%0A%0A
+import static org.junit.Assert.assertTrue;%0A
 import s
@@ -124,16 +124,16 @@
 eFalse;%0A
-
 import s
@@ -486,32 +486,63 @@
 ementException;%0A
+import java.security.KeyStore;%0A
 import java.secu
@@ -700,24 +700,386 @@
 rtificate;%0A%0A
+import javax.net.ssl.SSLContext;%0A%0Aimport org.apache.http.HttpEntity;%0Aimport org.apache.http.client.methods.CloseableHttpResponse;%0Aimport org.apache.http.client.methods.HttpGet;%0Aimport org.apache.http.impl.client.CloseableHttpClient;%0Aimport org.apache.http.impl.client.HttpClients;%0Aimport org.apache.http.ssl.SSLContexts;%0Aimport org.apache.http.util.EntityUtils;%0A
 import org.j
@@ -2694,22 +2694,25 @@
 rintln(%22
-Reload
+Configure
  Apache2
@@ -2726,17 +2726,26 @@
 %22);%0A    
-a
+configureA
 pache2Se
@@ -2752,17 +2752,763 @@
 rver
-Reload();
+();%0A%0A    // Add the CA certificate to a truststore%0A    final KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());%0A    keystore.load(null, null);%0A    keystore.setCertificateEntry(%22cert%22, caCert);%0A    final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(keystore, null).build();%0A    // Test the HTTPS connection%0A    System.out.println(%22Test https://localhost/%22);%0A    try (CloseableHttpClient httpClient = HttpClients.custom().setSslcontext(sslContext).build();%0A        CloseableHttpResponse response = httpClient.execute(new HttpGet(%22https://localhost/%22))) %7B%0A      final HttpEntity entity = response.getEntity();%0A      final String content = EntityUtils.toString(entity);%0A      assertTrue(content.contains(%22It works%22));%0A    %7D
 %0A  %7D
@@ -4202,17 +4202,26 @@
 te void 
-a
+configureA
 pache2Se
@@ -4224,22 +4224,16 @@
 e2Server
-Reload
 () throw
@@ -4331,35 +4331,45 @@
 , %22s
-ervice%22, %22apache2%22, %22reload
+rc/test/resources/configureApache2.sh
 %22)%0A 

Test with Apache2 server