();
+
+ for (String regex : regexes) {
+ patterns.add(Pattern.compile(regex));
+ }
+
+ for (String subject : subjects) {
+ boolean subjectMatched = false;
+ for (Pattern pattern : patterns) {
+ if(pattern.matcher(subject).matches()) {
+ subjectMatched = true;
+ break;
+ }
+ }
+
+ if(!subjectMatched) {
+ allSubjectsMatched = false;
+ break;
+ }
+ }
+
+ return allSubjectsMatched;
+ }
+
+ public static String getVaaSChainOption(ChainOption chainOption) {
+ switch (chainOption) {
+ case ChainOptionRootFirst:
+ return "ROOT_FIRST";
+ case ChainOptionRootLast:
+ case ChainOptionIgnore:
+ default:
+ return "EE_FIRST";
+ }
+ }
+
+ public static PEMCollection getPEMCollectionFromKeyStoreAsStream(InputStream keyStoreAsInputStream, ChainOption chainOption, String keyPassword) throws VCertException {
+ String certificateAsPem = null;
+
+ String pemFileSuffix = null;
+ if(chainOption == ChainOption.ChainOptionRootFirst)
+ pemFileSuffix = "_root-first.pem";
+ else
+ pemFileSuffix = "_root-last.pem";
+
+ PrivateKey privateKey = null;
+
+ try (ZipInputStream zis = new ZipInputStream(keyStoreAsInputStream)) {
+
+ ZipEntry zipEntry;
+ while ((zipEntry = zis.getNextEntry())!= null) {
+ String fileName = zipEntry.getName();
+ if(fileName.endsWith(".key")) {
+ PEMParser pemParser = new PEMParser(new InputStreamReader(zis));
+ privateKey = PEMCollection.decryptPKCS8PrivateKey(pemParser, keyPassword);
+ } else {
+ if(fileName.endsWith(pemFileSuffix))
+ certificateAsPem = new String(zis.readAllBytes());
+ }
+ }
+ } catch (Exception e) {
+ throw new VCertException(e);
+ }
+
+ return PEMCollection.fromResponse(
+ certificateAsPem,
+ chainOption,
+ privateKey,
+ keyPassword);
+ }
@Data
@AllArgsConstructor
diff --git a/src/main/java/com/venafi/vcert/sdk/connectors/cloud/SealedBoxUtility.java b/src/main/java/com/venafi/vcert/sdk/connectors/cloud/SealedBoxUtility.java
new file mode 100644
index 0000000..e89b616
--- /dev/null
+++ b/src/main/java/com/venafi/vcert/sdk/connectors/cloud/SealedBoxUtility.java
@@ -0,0 +1,93 @@
+/**
+ *
+ */
+package com.venafi.vcert.sdk.connectors.cloud;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import org.bouncycastle.crypto.digests.Blake2bDigest;
+
+import com.iwebpp.crypto.TweetNaclFast;
+
+
+/**
+ * The following utility is based on the SealBoxUtility code shared in the stackoverflow question
+ *
+ * How can I create or open a libsodium compatible sealed box in pure Java.
+ *
+ * The main difference is on this version is being used the
+ * org.bouncycastle.crypto.digests.Blake2bDigest from The Bouncy Castle Crypto Package For Java
+ * instead of Blake2b to get the Blake2b hash.
+ *
+ * Has also a dependency on TweetNaclFast from https://github.com/InstantWebP2P/tweetnacl-java.
+ *
+ */
+public class SealedBoxUtility {
+
+
+ public static final int CRYPTO_BOX_NONCEBYTES = 24;
+ //public static final int crypto_box_PUBLICKEYBYTES = 32;
+ //public static final int crypto_box_MACBYTES = 16;
+ //public static final int crypto_box_SEALBYTES = (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES);
+
+ // libsodium
+ // int crypto_box_seal(unsigned char *c, const unsigned char *m,
+ // unsigned long long mlen, const unsigned char *pk);
+ /**
+ * Encrypt in a sealed box
+ *
+ * @param receiverPubKey receiver public key
+ * @param clearText clear text
+ * @return encrypted message
+ * @throws GeneralSecurityException
+ */
+ public static byte[] cryptoBoxSeal(byte[] receiverPubKey, byte[] clearText) throws GeneralSecurityException {
+
+ // create ephemeral keypair for sender
+ TweetNaclFast.Box.KeyPair ephkeypair = TweetNaclFast.Box.keyPair();
+ // create nonce
+ byte[] nonce = cryptoBoxSealNonce(ephkeypair.getPublicKey(), receiverPubKey);
+ TweetNaclFast.Box box = new TweetNaclFast.Box(receiverPubKey, ephkeypair.getSecretKey());
+ byte[] ciphertext = box.box(clearText, nonce);
+ if (ciphertext == null)
+ throw new GeneralSecurityException("Could not create the crypto box");
+
+ byte[] sealedbox = null;
+ try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
+ byteArrayOutputStream.write(ephkeypair.getPublicKey());
+ byteArrayOutputStream.write(ciphertext);
+ sealedbox = byteArrayOutputStream.toByteArray();
+ } catch (IOException e) {
+ throw new GeneralSecurityException("Could not create the sealed crypto box", e);
+ }
+ return sealedbox;
+ }
+
+ /**
+ * hash the combination of senderpk + mypk into nonce using blake2b hash
+ * @param senderpk the senders public key
+ * @param mypk my own public key
+ * @return the nonce computed using Blake2b generic hash
+ */
+ public static byte[] cryptoBoxSealNonce(byte[] senderpk, byte[] mypk){
+ // C source ported from libsodium
+ // crypto_generichash_state st;
+ //
+ // crypto_generichash_init(&st, NULL, 0U, CRYPTO_BOX_NONCEBYTES);
+ // crypto_generichash_update(&st, pk1, crypto_box_PUBLICKEYBYTES);
+ // crypto_generichash_update(&st, pk2, crypto_box_PUBLICKEYBYTES);
+ // crypto_generichash_final(&st, nonce, CRYPTO_BOX_NONCEBYTES);
+ //
+ // return 0;
+ final Blake2bDigest blake2b = new Blake2bDigest( CRYPTO_BOX_NONCEBYTES*8 );
+ blake2b.update(senderpk, 0, senderpk.length);
+ blake2b.update(mypk, 0, mypk.length);
+ byte[] nonce = new byte[CRYPTO_BOX_NONCEBYTES];
+ blake2b.doFinal(nonce, 0);
+ if (nonce == null || nonce.length!=CRYPTO_BOX_NONCEBYTES) throw new IllegalArgumentException("Blake2b hashing failed");
+ return nonce;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/venafi/vcert/sdk/connectors/cloud/domain/CertificateDetails.java b/src/main/java/com/venafi/vcert/sdk/connectors/cloud/domain/CertificateDetails.java
index 6feab86..51c1b6e 100644
--- a/src/main/java/com/venafi/vcert/sdk/connectors/cloud/domain/CertificateDetails.java
+++ b/src/main/java/com/venafi/vcert/sdk/connectors/cloud/domain/CertificateDetails.java
@@ -40,6 +40,7 @@ public class CertificateDetails {
private String versionType;
private int totalInstanceCount;
private int totalActiveInstanceCount;
+ private String dekHash;
diff --git a/src/main/java/com/venafi/vcert/sdk/connectors/cloud/domain/EdgeEncryptionKey.java b/src/main/java/com/venafi/vcert/sdk/connectors/cloud/domain/EdgeEncryptionKey.java
new file mode 100644
index 0000000..22ceb20
--- /dev/null
+++ b/src/main/java/com/venafi/vcert/sdk/connectors/cloud/domain/EdgeEncryptionKey.java
@@ -0,0 +1,14 @@
+package com.venafi.vcert.sdk.connectors.cloud.domain;
+
+import java.time.OffsetDateTime;
+import lombok.Data;
+
+@Data
+public class EdgeEncryptionKey {
+
+ private String id;
+ private String companyId;
+ private String key;
+ private String keyAlgorithm;
+ private OffsetDateTime lastBackupDate;
+}
diff --git a/src/main/java/com/venafi/vcert/sdk/connectors/cloud/endpoint/KeystoreRequest.java b/src/main/java/com/venafi/vcert/sdk/connectors/cloud/endpoint/KeystoreRequest.java
new file mode 100644
index 0000000..5d4b7de
--- /dev/null
+++ b/src/main/java/com/venafi/vcert/sdk/connectors/cloud/endpoint/KeystoreRequest.java
@@ -0,0 +1,11 @@
+package com.venafi.vcert.sdk.connectors.cloud.endpoint;
+
+import lombok.Data;
+
+@Data
+public class KeystoreRequest {
+ private String exportFormat;
+ private String encryptedPrivateKeyPassphrase;
+ private String encryptedKeystorePassphrase;
+ private String certificateLabel;
+}
diff --git a/src/main/java/com/venafi/vcert/sdk/policy/api/domain/CloudPolicy.java b/src/main/java/com/venafi/vcert/sdk/policy/api/domain/CloudPolicy.java
index e6c62f2..97d9cd3 100644
--- a/src/main/java/com/venafi/vcert/sdk/policy/api/domain/CloudPolicy.java
+++ b/src/main/java/com/venafi/vcert/sdk/policy/api/domain/CloudPolicy.java
@@ -9,6 +9,11 @@
public class CloudPolicy {
private CertificateIssuingTemplate certificateIssuingTemplate;
private CAInfo caInfo;
+
+ //this attribute is not corresponding to any VaaS attribute. It only exists to indicate to the
+ // CloudPolicyToPolicyConverter class that when the domains of the PolicySpecification which is
+ //being built then they should be cleaned up of regexes or not.
+ private boolean removeRegexesFromSubjectCN;
@Data
@AllArgsConstructor
diff --git a/src/main/java/com/venafi/vcert/sdk/policy/converter/cloud/CloudPolicyToPolicyConverter.java b/src/main/java/com/venafi/vcert/sdk/policy/converter/cloud/CloudPolicyToPolicyConverter.java
index fe87aaa..2648548 100644
--- a/src/main/java/com/venafi/vcert/sdk/policy/converter/cloud/CloudPolicyToPolicyConverter.java
+++ b/src/main/java/com/venafi/vcert/sdk/policy/converter/cloud/CloudPolicyToPolicyConverter.java
@@ -37,7 +37,7 @@ private void processPolicy( PolicySpecification policySpecification, CloudPolicy
CertificateIssuingTemplate cit = cloudPolicy.certificateIssuingTemplate();
- processDomainsAndWildcard( policySpecification, cit);
+ processDomainsAndWildcard( policySpecification, cit, cloudPolicy.removeRegexesFromSubjectCN());
processMaxValidDays( policySpecification, cit);
processCertificateAuthority( policySpecification, cloudPolicy.caInfo());
@@ -48,23 +48,24 @@ private void processPolicy( PolicySpecification policySpecification, CloudPolicy
processSubjectAltNames( policySpecification, cloudPolicy);
}
- private void processDomainsAndWildcard( PolicySpecification policySpecification, CertificateIssuingTemplate cit ) throws Exception{
+ private void processDomainsAndWildcard( PolicySpecification policySpecification, CertificateIssuingTemplate cit, boolean removeRegexesFromDomains ) throws Exception{
List subjectCNRegexes = cit.subjectCNRegexes;
if ( subjectCNRegexes != null && subjectCNRegexes.size() > 0 && !subjectCNRegexes.get(0).equals(".*") ) {
Policy policy = getPolicyFromPolicySpecification( policySpecification );
- processDomains(policy, subjectCNRegexes);
-
processWildcard(policy, subjectCNRegexes);
+
+ if(removeRegexesFromDomains)
+ removeRegexesFromDomains(policy, subjectCNRegexes);
} else {
//domains will not set
}
}
- private void processDomains( Policy policy, List subjectCNRegexes) {
+ private void removeRegexesFromDomains( Policy policy, List subjectCNRegexes) {
//converting the subjectCNRegexes to domains
List domains = new ArrayList();
for (String domain : subjectCNRegexes) {
diff --git a/src/test/java/com/venafi/vcert/sdk/connectors/cloud/CloudConnectorAT.java b/src/test/java/com/venafi/vcert/sdk/connectors/cloud/CloudConnectorAT.java
index b69f74f..016f441 100644
--- a/src/test/java/com/venafi/vcert/sdk/connectors/cloud/CloudConnectorAT.java
+++ b/src/test/java/com/venafi/vcert/sdk/connectors/cloud/CloudConnectorAT.java
@@ -38,6 +38,7 @@
import com.venafi.vcert.sdk.VCertClient;
import com.venafi.vcert.sdk.VCertException;
import com.venafi.vcert.sdk.certificate.CertificateRequest;
+import com.venafi.vcert.sdk.certificate.CsrOriginOption;
import com.venafi.vcert.sdk.certificate.ImportRequest;
import com.venafi.vcert.sdk.certificate.KeyType;
import com.venafi.vcert.sdk.certificate.PEMCollection;
@@ -138,11 +139,12 @@ void requestCertificateUnrestricted() throws VCertException, UnknownHostExceptio
}
@Test
- void retrieveCertificate() throws VCertException, UnknownHostException {
+ void retrieveCertificateCSRProvided() throws VCertException, UnknownHostException {
String zoneName = System.getenv("CLOUDZONE");
ZoneConfiguration zoneConfiguration = classUnderTest.readZoneConfiguration(zoneName);
+ String cn = TestUtils.randomCN().toLowerCase();
CertificateRequest certificateRequest = new CertificateRequest()
- .subject(new CertificateRequest.PKIXName().commonName(TestUtils.randomCN())
+ .subject(new CertificateRequest.PKIXName().commonName(cn)
.organization(Collections.singletonList("Venafi, Inc."))
.organizationalUnit(Arrays.asList("Engineering", "Automated Tests"))
.country(Collections.singletonList("US")).locality(Collections.singletonList("SLC"))
@@ -155,6 +157,35 @@ void retrieveCertificate() throws VCertException, UnknownHostException {
assertThat(certificateId).isNotNull();
certificateRequest.pickupId(certificateId);
+ //certificateRequest.certId("b7a38570-48aa-11ec-9c4e-b91163bb1407");
+ PEMCollection pemCollection = classUnderTest.retrieveCertificate(certificateRequest);
+
+ assertThat(pemCollection.certificate()).isNotNull();
+ assertThat(pemCollection.chain()).hasSize(2);
+ assertThat(pemCollection.privateKey()).isNotNull();
+ }
+
+ @Test
+ void retrieveCertificateServiceGeneratedCSR() throws VCertException, UnknownHostException {
+ String zoneName = System.getenv("CLOUDZONE");
+ ZoneConfiguration zoneConfiguration = classUnderTest.readZoneConfiguration(zoneName);
+ String cn = TestUtils.randomCN().toLowerCase();
+ CertificateRequest certificateRequest = new CertificateRequest()
+ .subject(new CertificateRequest.PKIXName().commonName(cn)
+ .organization(Collections.singletonList("Venafi, Inc."))
+ .organizationalUnit(Arrays.asList("Engineering", "Automated Tests"))
+ .country(Collections.singletonList("US")).locality(Collections.singletonList("SLC"))
+ .province(Collections.singletonList("Utah")))
+ .dnsNames( Arrays.asList(new String[] {cn}))
+ .csrOrigin(CsrOriginOption.ServiceGeneratedCSR)
+ .keyPassword("tirano");
+
+ //For CSR Service Generated Request is not needed to call to generateRequest() method
+ //certificateRequest = classUnderTest.generateRequest(zoneConfiguration, certificateRequest);
+ String pickupId = classUnderTest.requestCertificate(certificateRequest, zoneConfiguration);
+ assertThat(pickupId).isNotNull();
+
+ certificateRequest.pickupId(pickupId);
PEMCollection pemCollection = classUnderTest.retrieveCertificate(certificateRequest);
assertThat(pemCollection.certificate()).isNotNull();
diff --git a/src/test/java/com/venafi/vcert/sdk/connectors/cloud/CloudConnectorTest.java b/src/test/java/com/venafi/vcert/sdk/connectors/cloud/CloudConnectorTest.java
index 7a29b39..f513066 100644
--- a/src/test/java/com/venafi/vcert/sdk/connectors/cloud/CloudConnectorTest.java
+++ b/src/test/java/com/venafi/vcert/sdk/connectors/cloud/CloudConnectorTest.java
@@ -48,6 +48,7 @@
import com.venafi.vcert.sdk.connectors.cloud.domain.CertificateIssuingTemplate;
import com.venafi.vcert.sdk.connectors.cloud.domain.CertificateIssuingTemplate.AllowedKeyType;
import com.venafi.vcert.sdk.connectors.cloud.domain.Company;
+import com.venafi.vcert.sdk.connectors.cloud.domain.EdgeEncryptionKey;
import com.venafi.vcert.sdk.connectors.cloud.domain.User;
import com.venafi.vcert.sdk.connectors.cloud.domain.UserDetails;
import com.venafi.vcert.sdk.endpoint.Authentication;
@@ -170,16 +171,23 @@ void retrieveCertificate() throws VCertException, IOException {
list.add("jackpot");
CertificateStatus status = new CertificateStatus().status("ISSUED")
.certificateIds(list);
+
+ CertificateDetails certificateDetails = new CertificateDetails().dekHash("12345");
+ EdgeEncryptionKey edgeEncryptionKey = new EdgeEncryptionKey();
+
+ cloud.certificateDetails(eq("jackpot"), eq(apiKey));
when(cloud.certificateStatus(eq("jackpot"), eq(apiKey)))
.thenReturn(status);
- when(cloud.certificateViaCSR(eq("jackpot"), eq(apiKey), eq("ROOT_FIRST")))
+ when(cloud.retrieveCertificate(eq("jackpot"), eq(apiKey), eq("ROOT_FIRST")))
.thenReturn(Response.builder()
.request(Request.create(Request.HttpMethod.GET, "http://localhost",
new HashMap>(), null, null))
.status(200)
.body(body, Charset.forName("UTF-8"))
.build());
+ when(cloud.certificateDetails(eq("jackpot"), eq(apiKey))).thenReturn(certificateDetails);
+ when(cloud.retrieveEdgeEncryptionKey(eq("12345"), eq(apiKey))).thenReturn(edgeEncryptionKey);
PEMCollection pemCollection2 = classUnderTest.retrieveCertificate(request);
assertThat(pemCollection2).isNotNull();