Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@

package com.azure.resourcemanager.appplatform;

import com.azure.core.management.Region;
import com.azure.core.test.annotation.DoNotRecord;
import com.azure.resourcemanager.appplatform.models.RuntimeVersion;
import com.azure.resourcemanager.appplatform.models.SpringApp;
import com.azure.resourcemanager.appplatform.models.SpringAppDeployment;
import com.azure.resourcemanager.appplatform.models.SpringService;
import com.azure.resourcemanager.appservice.models.AppServiceCertificateOrder;
import com.azure.resourcemanager.appservice.models.AppServiceDomain;
import com.azure.resourcemanager.dns.models.DnsZone;
import com.azure.resourcemanager.keyvault.models.CertificatePermissions;
import com.azure.resourcemanager.keyvault.models.Secret;
import com.azure.resourcemanager.keyvault.models.SecretPermissions;
import com.azure.resourcemanager.keyvault.models.Vault;
import com.azure.resourcemanager.resources.fluentcore.arm.CountryIsoCode;
import com.azure.resourcemanager.resources.fluentcore.arm.CountryPhoneCode;
import com.azure.core.management.Region;
import com.azure.security.keyvault.certificates.CertificateClient;
import com.azure.security.keyvault.certificates.CertificateClientBuilder;
import com.azure.security.keyvault.certificates.models.ImportCertificateOptions;
Expand All @@ -28,19 +26,33 @@
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.bind.DatatypeConverter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.util.Base64;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class SpringCloudLiveOnlyTest extends AppPlatformTest {
private static final String PIGGYMETRICS_CONFIG_URL = "https://github.com/Azure-Samples/piggymetrics-config";
Expand Down Expand Up @@ -150,6 +162,14 @@ public void canCreateCustomDomainWithSsl() throws Exception {
String appName = "gateway";
Region region = Region.US_EAST;

allowAllSSL();
String cerPassword = password();
String cerPath = this.getClass().getResource("/").getPath() + domainName + ".cer";
String pfxPath = this.getClass().getResource("/").getPath() + domainName + ".pfx";
createCertificate(cerPath, pfxPath, domainName, cerPassword, "ssl." + domainName, "ssl." + domainName);

byte[] certificate = readAllBytes(new FileInputStream(pfxPath));

appPlatformManager.resourceManager().resourceGroups().define(rgName)
.withRegion(region)
.create();
Expand Down Expand Up @@ -178,17 +198,9 @@ public void canCreateCustomDomainWithSsl() throws Exception {
.withExistingDnsZone(dnsZone)
.create();

AppServiceCertificateOrder certificateOrder = appServiceManager.certificateOrders().define(certOrderName)
Vault vault = keyVaultManager.vaults().define(vaultName)
.withRegion(region)
.withExistingResourceGroup(rgName)
.withHostName(String.format("*.%s", domainName))
.withWildcardSku()
.withDomainVerification(domain)
.withNewKeyVault(vaultName, region)
.withAutoRenew(true)
.create();

Vault vault = keyVaultManager.vaults().getByResourceGroup(rgName, vaultName);
vault.update()
.defineAccessPolicy()
.forServicePrincipal(clientIdFromFile())
.allowSecretAllPermissions()
Expand All @@ -199,11 +211,7 @@ public void canCreateCustomDomainWithSsl() throws Exception {
.allowCertificatePermissions(CertificatePermissions.GET, CertificatePermissions.LIST)
.allowSecretPermissions(SecretPermissions.GET, SecretPermissions.LIST)
.attach()
.apply();

Secret secret = vault.secrets().getByName(certOrderName);

byte[] certificate = Base64.getDecoder().decode(secret.getValue());
.create();

// upload certificate
CertificateClient certificateClient = new CertificateClientBuilder()
Expand All @@ -213,12 +221,13 @@ public void canCreateCustomDomainWithSsl() throws Exception {

certificateClient.importCertificate(
new ImportCertificateOptions(certName, certificate)
.setPassword(cerPassword)
.setEnabled(true)
);

// get thumbprint
KeyStore store = KeyStore.getInstance("PKCS12");
store.load(new ByteArrayInputStream(certificate), null);
store.load(new ByteArrayInputStream(certificate), cerPassword.toCharArray());
String alias = Collections.list(store.aliases()).get(0);
String thumbprint = DatatypeConverter.printHexBinary(MessageDigest.getInstance("SHA-1").digest(store.getCertificate(alias).getEncoded()));

Expand Down Expand Up @@ -275,4 +284,123 @@ private void extraTarGzSource(File folder, URL url) throws IOException {
connection.disconnect();
}
}

private byte[] readAllBytes(InputStream inputStream) throws IOException {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
byte[] data = new byte[4096];
while (true) {
int size = inputStream.read(data);
if (size > 0) {
outputStream.write(data, 0, size);
} else {
return outputStream.toByteArray();
}
}
}
}

public static void createCertificate(String certPath, String pfxPath,
String alias, String password, String cnName, String dnsName) throws IOException {
if (new File(pfxPath).exists()) {
return;
}
String validityInDays = "3650";
String keyAlg = "RSA";
String sigAlg = "SHA1withRSA";
String keySize = "2048";
String storeType = "pkcs12";
String command = "keytool";
String jdkPath = System.getProperty("java.home");
if (jdkPath != null && !jdkPath.isEmpty()) {
jdkPath = jdkPath.concat("\\bin");
if (new File(jdkPath).isDirectory()) {
command = String.format("%s%s%s", jdkPath, File.separator, command);
}
} else {
return;
}

// Create Pfx file
String[] commandArgs = {command, "-genkey", "-alias", alias,
"-keystore", pfxPath, "-storepass", password, "-validity",
validityInDays, "-keyalg", keyAlg, "-sigalg", sigAlg, "-keysize", keySize,
"-storetype", storeType, "-dname", "CN=" + cnName, "-ext", "EKU=1.3.6.1.5.5.7.3.1"};
if (dnsName != null) {
List<String> args = new ArrayList<>(Arrays.asList(commandArgs));
args.add("-ext");
args.add("san=dns:" + dnsName);
commandArgs = args.toArray(new String[0]);
}
cmdInvocation(commandArgs, true);

// Create cer file i.e. extract public key from pfx
File pfxFile = new File(pfxPath);
if (pfxFile.exists()) {
String[] certCommandArgs = {command, "-export", "-alias", alias,
"-storetype", storeType, "-keystore", pfxPath,
"-storepass", password, "-rfc", "-file", certPath};
// output of keytool export command is going to error stream
// although command is
// executed successfully, hence ignoring error stream in this case
cmdInvocation(certCommandArgs, true);

// Check if file got created or not
File cerFile = new File(pfxPath);
if (!cerFile.exists()) {
throw new IOException(
"Error occurred while creating certificate"
+ String.join(" ", certCommandArgs));
}
} else {
throw new IOException("Error occurred while creating certificates"
+ String.join(" ", commandArgs));
}
}

public static String cmdInvocation(String[] command,
boolean ignoreErrorStream) throws IOException {
String result = "";
String error = "";

Process process = new ProcessBuilder(command).start();
try (
InputStream inputStream = process.getInputStream();
InputStream errorStream = process.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
BufferedReader ebr = new BufferedReader(new InputStreamReader(errorStream, StandardCharsets.UTF_8));
) {
result = br.readLine();
process.waitFor();
error = ebr.readLine();
if (error != null && (!error.equals(""))) {
// To do - Log error message

if (!ignoreErrorStream) {
throw new IOException(error, null);
}
}
} catch (Exception e) {
throw new RuntimeException("Exception occurred while invoking command", e);
}
return result;
}

private static void allowAllSSL() throws NoSuchAlgorithmException, KeyManagementException {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -187,19 +187,17 @@
// .withCNameRecordSet("ssl", gateway.fqdn())
// .apply();
//
// System.out.printf("Purchasing a certificate for *.%s and save to %s in key vault named %s ...%n", domainName, certOrderName, vaultName);
// AppServiceCertificateOrder certificateOrder = azureResourceManager.appServiceCertificateOrders().define(certOrderName)
// .withExistingResourceGroup(rgName)
// .withHostName(String.format("*.%s", domainName))
// .withWildcardSku()
// .withDomainVerification(domain)
// .withNewKeyVault(vaultName, region)
// .withAutoRenew(true)
// .create();
// System.out.printf("Purchased certificate: *.%s ...%n", domain.name());
// Utils.print(certificateOrder);
// // Please use a trusted certificate for actual use
// System.out.printf("Generate a self-signed certificate for ssl.%s %n", domainName);
// allowAllSSL();
// String cerPassword = password();
// String cerPath = ManageSpringCloud.class.getResource("/").getPath() + domainName + ".cer";
// String pfxPath = ManageSpringCloud.class.getClass().getResource("/").getPath() + domainName + ".pfx";
// createCertificate(cerPath, pfxPath, domainName, cerPassword, "ssl." + domainName, "ssl." + domainName);
//
// byte[] certificate = readAllBytes(new FileInputStream(pfxPath));
//
// System.out.printf("Updating key vault %s with access from %s, %s%n", vaultName, clientId, SPRING_CLOUD_SERVICE_PRINCIPAL);
// System.out.printf("Creating key vault %s with access from %s, %s%n", vaultName, clientId, SPRING_CLOUD_SERVICE_PRINCIPAL);
// Vault vault = azureResourceManager.vaults().getByResourceGroup(rgName, vaultName);
// vault.update()
// .defineAccessPolicy()
Expand All @@ -213,20 +211,13 @@
// .allowSecretPermissions(SecretPermissions.GET, SecretPermissions.LIST)
// .attach()
// .apply();
// System.out.printf("Updated key vault %s%n", vault.name());
// System.out.printf("Created key vault %s%n", vault.name());
// Utils.print(vault);
//
// Secret secret = vault.secrets().getByName(certOrderName);
//
// byte[] certificate = Base64.getDecoder().decode(secret.getValue());
//
// String thumbprint = secret.tags().get("Thumbprint");
// if (thumbprint == null || thumbprint.isEmpty()) {
// KeyStore store = KeyStore.getInstance("PKCS12");
// store.load(new ByteArrayInputStream(certificate), null);
// String alias = Collections.list(store.aliases()).get(0);
// thumbprint = DatatypeConverter.printHexBinary(MessageDigest.getInstance("SHA-1").digest(store.getCertificate(alias).getEncoded()));
// }
// KeyStore store = KeyStore.getInstance("PKCS12");
// store.load(new ByteArrayInputStream(certificate), cerPassword.toCharArray());
// String alias = Collections.list(store.aliases()).get(0);
// thumbprint = DatatypeConverter.printHexBinary(MessageDigest.getInstance("SHA-1").digest(store.getCertificate(alias).getEncoded()));
//
// System.out.printf("Get certificate: %s%n", secret.getValue());
// System.out.printf("Certificate Thumbprint: %s%n", thumbprint);
Expand All @@ -240,6 +231,7 @@
// System.out.printf("Uploading certificate to %s in key vault ...%n", certName);
// certificateClient.importCertificate(
// new ImportCertificateOptions(certName, certificate)
// .setPassword(cerPassword)
// .setEnabled(true)
// );
//
Expand Down Expand Up @@ -323,4 +315,23 @@
// connection.disconnect();
// }
// }
//
// private static void allowAllSSL() throws NoSuchAlgorithmException, KeyManagementException {
// TrustManager[] trustAllCerts = new TrustManager[]{
// new X509TrustManager() {
// public java.security.cert.X509Certificate[] getAcceptedIssuers() {
// return null;
// }
// public void checkClientTrusted(
// java.security.cert.X509Certificate[] certs, String authType) {
// }
// public void checkServerTrusted(
// java.security.cert.X509Certificate[] certs, String authType) {
// }
// }
// };
// SSLContext sslContext = SSLContext.getInstance("SSL");
// sslContext.init(null, trustAllCerts, new SecureRandom());
// HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
// }
//}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public static boolean runSample(AzureResourceManager azureResourceManager) throw

System.out.println("Creating a self-signed certificate " + pfxPath + "...");

Utils.createCertificate(cerPath, pfxPath, domainName, certPassword, "*." + domainName);
Utils.createCertificate(cerPath, pfxPath, domainName, certPassword, "*." + domainName, null);

System.out.println("Created self-signed certificate " + pfxPath);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public static boolean runSample(AzureResourceManager azureResourceManager) throw

System.out.println("Creating a self-signed certificate " + pfxPath + "...");

Utils.createCertificate(cerPath, pfxPath, domainName, certPassword, "*." + domainName);
Utils.createCertificate(cerPath, pfxPath, domainName, certPassword, "*." + domainName, null);

System.out.println("Created self-signed certificate " + pfxPath);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public static boolean runSample(AzureResourceManager azureResourceManager) throw

System.out.println("Creating a self-signed certificate " + pfxPath + "...");

Utils.createCertificate(cerPath, pfxPath, domainName, certPassword, "*." + domainName);
Utils.createCertificate(cerPath, pfxPath, domainName, certPassword, "*." + domainName, null);

System.out.println("Created self-signed certificate " + pfxPath);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
Expand Down Expand Up @@ -1589,11 +1590,12 @@ public static String getSecondaryServicePrincipalSecret(String envSecondaryServi
* @param alias User alias
* @param password alias password
* @param cnName domain name
* @param dnsName dns name in subject alternate name
* @throws Exception exceptions from the creation
* @throws IOException IO Exception
*/
public static void createCertificate(String certPath, String pfxPath,
String alias, String password, String cnName) throws IOException {
public static void createCertificate(String certPath, String pfxPath, String alias,
String password, String cnName, String dnsName) throws IOException {
if (new File(pfxPath).exists()) {
return;
}
Expand All @@ -1618,6 +1620,12 @@ public static void createCertificate(String certPath, String pfxPath,
"-keystore", pfxPath, "-storepass", password, "-validity",
validityInDays, "-keyalg", keyAlg, "-sigalg", sigAlg, "-keysize", keySize,
"-storetype", storeType, "-dname", "CN=" + cnName, "-ext", "EKU=1.3.6.1.5.5.7.3.1"};
if (dnsName != null) {
List<String> args = new ArrayList<>(Arrays.asList(commandArgs));
args.add("-ext");
args.add("san=dns:" + dnsName);
commandArgs = args.toArray(new String[0]);
}
Utils.cmdInvocation(commandArgs, true);

// Create cer file i.e. extract public key from pfx
Expand Down