Skip to content

Commit

Permalink
Use thumbprint as SSL certificate name for uniqueness
Browse files Browse the repository at this point in the history
  • Loading branch information
jianghaolu committed Dec 2, 2016
1 parent a0486da commit fa6884e
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,55 +21,55 @@ public class CertificateDetailsInner extends Resource {
/**
* Version.
*/
@JsonProperty(value = "properties.version", access = JsonProperty.Access.WRITE_ONLY)
@JsonProperty(value = "version", access = JsonProperty.Access.WRITE_ONLY)
private Integer version;

/**
* Serial Number.
*/
@JsonProperty(value = "properties.serialNumber", access = JsonProperty.Access.WRITE_ONLY)
@JsonProperty(value = "serialNumber", access = JsonProperty.Access.WRITE_ONLY)
private String serialNumber;

/**
* Thumbprint.
*/
@JsonProperty(value = "properties.thumbprint", access = JsonProperty.Access.WRITE_ONLY)
@JsonProperty(value = "thumbprint", access = JsonProperty.Access.WRITE_ONLY)
private String thumbprint;

/**
* Subject.
*/
@JsonProperty(value = "properties.subject", access = JsonProperty.Access.WRITE_ONLY)
@JsonProperty(value = "subject", access = JsonProperty.Access.WRITE_ONLY)
private String subject;

/**
* Valid from.
*/
@JsonProperty(value = "properties.notBefore", access = JsonProperty.Access.WRITE_ONLY)
@JsonProperty(value = "notBefore", access = JsonProperty.Access.WRITE_ONLY)
private DateTime notBefore;

/**
* Valid to.
*/
@JsonProperty(value = "properties.notAfter", access = JsonProperty.Access.WRITE_ONLY)
@JsonProperty(value = "notAfter", access = JsonProperty.Access.WRITE_ONLY)
private DateTime notAfter;

/**
* Signature algorithm.
*/
@JsonProperty(value = "properties.signatureAlgorithm", access = JsonProperty.Access.WRITE_ONLY)
@JsonProperty(value = "signatureAlgorithm", access = JsonProperty.Access.WRITE_ONLY)
private String signatureAlgorithm;

/**
* Issuer.
*/
@JsonProperty(value = "properties.issuer", access = JsonProperty.Access.WRITE_ONLY)
@JsonProperty(value = "issuer", access = JsonProperty.Access.WRITE_ONLY)
private String issuer;

/**
* Raw certificate data.
*/
@JsonProperty(value = "properties.rawData", access = JsonProperty.Access.WRITE_ONLY)
@JsonProperty(value = "rawData", access = JsonProperty.Access.WRITE_ONLY)
private String rawData;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
*/
package com.microsoft.azure.management.website.implementation;

import com.google.common.io.BaseEncoding;
import com.microsoft.azure.management.apigeneration.Fluent;
import com.microsoft.azure.management.keyvault.Vault;
import com.microsoft.azure.management.resources.fluentcore.arm.Region;
import com.microsoft.azure.management.resources.fluentcore.model.implementation.IndexableWrapperImpl;
import com.microsoft.azure.management.website.AppServiceCertificate;
import com.microsoft.azure.management.website.AppServiceCertificateOrder;
Expand All @@ -19,6 +21,15 @@
import rx.functions.Func1;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
* Implementation for {@link HostNameSslBinding} and its create and update interfaces.
Expand All @@ -35,6 +46,7 @@ class HostNameSslBindingImpl<

private Observable<AppServiceCertificate> newCertificate;
private AppServiceCertificateOrder.DefinitionStages.WithKeyVault certificateInDefinition;

private final AppServiceManager manager;
private final FluentImplT parent;

Expand Down Expand Up @@ -72,7 +84,8 @@ public FluentImplT attach() {

@Override
public HostNameSslBindingImpl<FluentT, FluentImplT> withPfxCertificateToUpload(final File pfxFile, final String password) {
newCertificate = manager.certificates().define(name() + "cert")
String thumbprint = getCertificateThumbprint(pfxFile.getPath(), password);
newCertificate = manager.certificates().define(getCertificateUniqueName(thumbprint, parent().region()))
.withRegion(parent().region())
.withExistingResourceGroup(parent().resourceGroupName())
.withPfxFile(pfxFile)
Expand All @@ -93,7 +106,7 @@ public HostNameSslBindingImpl<FluentT, FluentImplT> withNewStandardSslCertificat

@Override
public HostNameSslBindingImpl<FluentT, FluentImplT> withExistingAppServiceCertificateOrder(final AppServiceCertificateOrder certificateOrder) {
newCertificate = manager.certificates().define(name() + "cert")
newCertificate = manager.certificates().define(getCertificateUniqueName(certificateOrder.signedCertificate().thumbprint(), parent().region()))
.withRegion(parent().region())
.withExistingResourceGroup(parent().resourceGroupName())
.withExistingCertificateOrder(certificateOrder)
Expand Down Expand Up @@ -121,8 +134,8 @@ public HostNameSslBindingImpl<FluentT, FluentImplT> withIpBasedSsl() {
Observable<AppServiceCertificate> newCertificate() {
return newCertificate.doOnNext(new Action1<AppServiceCertificate>() {
@Override
public void call(AppServiceCertificate appServiceCertificateOrder) {
withCertificateThumbprint(appServiceCertificateOrder.thumbprint());
public void call(AppServiceCertificate appServiceCertificate) {
withCertificateThumbprint(appServiceCertificate.thumbprint());
}
});
}
Expand Down Expand Up @@ -169,4 +182,25 @@ public Observable<AppServiceCertificate> call(AppServiceCertificateOrder appServ
});
return this;
}

private String getCertificateThumbprint(String pfxPath, String password) {
try {
InputStream inStream = new FileInputStream(pfxPath);

KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(inStream, password.toCharArray());

String alias = ks.aliases().nextElement();
X509Certificate certificate = (X509Certificate) ks.getCertificate(alias);
inStream.close();
MessageDigest sha = MessageDigest.getInstance("SHA-1");
return BaseEncoding.base16().encode(sha.digest(certificate.getEncoded()));
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException ex) {
throw new RuntimeException(ex);
}
}

private String getCertificateUniqueName(String thumbprint, Region region) {
return String.format("%s##%s#", thumbprint, region.label());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -497,18 +497,11 @@ public Observable<SiteInner> call(SiteInner site) {
@Override
public Observable<SiteInner> call(final SiteInner siteInner) {
List<Observable<AppServiceCertificate>> certs = new ArrayList<>();
Map<String, HostNameSslState> sslMap = new HashMap<>(
Maps.uniqueIndex(siteInner.hostNameSslStates(), new Function<HostNameSslState, String>() {
@Override
public String apply(HostNameSslState input) {
return input.name();
}
}));
for (final HostNameSslBindingImpl<FluentT, FluentImplT> binding : sslBindingsToCreate.values()) {
certs.add(binding.newCertificate());
sslMap.put(binding.inner().name(), binding.inner().withToUpdate(true));
hostNameSslStateMap.put(binding.inner().name(), binding.inner().withToUpdate(true));
}
siteInner.withHostNameSslStates(new ArrayList<>(sslMap.values()));
siteInner.withHostNameSslStates(new ArrayList<>(hostNameSslStateMap.values()));
if (certs.isEmpty()) {
return Observable.just(siteInner);
} else {
Expand Down

0 comments on commit fa6884e

Please sign in to comment.