Code Samples
*Purges the deleted certificate from the key vault enabled for soft-delete. Prints out the status code from the * server response when a response has been received.
- + * * *
* certificateClient.purgeDeletedCertificate("certificateName");
@@ -823,7 +823,7 @@ public void purgeDeletedCertificate(String certificateName) {
* Code Samples
* Purges the deleted certificate from the key vault enabled for soft-delete. Prints out the status code from the
* server response when a response has been received.
-
+ *
*
*
* Response<Void> purgeResponse = certificateClient.purgeDeletedCertificateWithResponse("certificateName",
@@ -841,7 +841,7 @@ public void purgeDeletedCertificate(String certificateName) {
@ServiceMethod(returns = ReturnType.SINGLE)
public Response purgeDeletedCertificateWithResponse(String certificateName, Context context) {
return implClient.purgeDeletedCertificateWithResponse(certificateName,
- new RequestOptions().setContext(context));
+ new RequestOptions().setContext(context).addHeader("Accept", "application/json"));
}
/**
diff --git a/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/CertificateServiceVersion.java b/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/CertificateServiceVersion.java
index 87b7d760bf7c..82ad642622e6 100644
--- a/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/CertificateServiceVersion.java
+++ b/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/CertificateServiceVersion.java
@@ -37,7 +37,15 @@ public enum CertificateServiceVersion implements ServiceVersion {
/**
* Service version {@code 7.6}.
*/
- V7_6("7.6");
+ V7_6("7.6"),
+ /**
+ * Service version {@code 2025-06-01-preview}.
+ */
+ V2025_06_01_PREVIEW("2025-06-01-preview"),
+ /**
+ * Service version {@code 2025-07-01}.
+ */
+ V2025_07_01("2025-07-01");
private final String version;
diff --git a/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/implementation/CertificateClientImpl.java b/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/implementation/CertificateClientImpl.java
index a6ac254483a3..6934edb665c8 100644
--- a/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/implementation/CertificateClientImpl.java
+++ b/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/implementation/CertificateClientImpl.java
@@ -693,7 +693,7 @@ Response getDeletedCertificateSync(@HostParam("vaultBaseUrl") String
@UnexpectedResponseExceptionType(HttpResponseException.class)
Mono> purgeDeletedCertificate(@HostParam("vaultBaseUrl") String vaultBaseUrl,
@QueryParam("api-version") String apiVersion, @PathParam("certificate-name") String certificateName,
- @HeaderParam("Accept") String accept, RequestOptions requestOptions, Context context);
+ RequestOptions requestOptions, Context context);
@Delete("/deletedcertificates/{certificate-name}")
@ExpectedResponses({ 204 })
@@ -703,7 +703,7 @@ Mono> purgeDeletedCertificate(@HostParam("vaultBaseUrl") String v
@UnexpectedResponseExceptionType(HttpResponseException.class)
Response purgeDeletedCertificateSync(@HostParam("vaultBaseUrl") String vaultBaseUrl,
@QueryParam("api-version") String apiVersion, @PathParam("certificate-name") String certificateName,
- @HeaderParam("Accept") String accept, RequestOptions requestOptions, Context context);
+ RequestOptions requestOptions, Context context);
@Post("/deletedcertificates/{certificate-name}/recover")
@ExpectedResponses({ 200 })
@@ -1071,6 +1071,12 @@ public PagedIterable getCertificates(RequestOptions requestOptions)
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -1176,6 +1182,12 @@ public Mono> deleteCertificateWithResponseAsync(String cert
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -2245,6 +2257,12 @@ public Response deleteCertificateIssuerWithResponse(String issuerNam
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -2371,6 +2389,12 @@ public Mono> createCertificateWithResponseAsync(String cert
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -2499,6 +2523,12 @@ public Response createCertificateWithResponse(String certificateName
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -2576,6 +2606,12 @@ public Response createCertificateWithResponse(String certificateName
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -2681,6 +2717,12 @@ public Mono> importCertificateWithResponseAsync(String cert
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -2758,6 +2800,12 @@ public Mono> importCertificateWithResponseAsync(String cert
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3071,6 +3119,12 @@ public PagedIterable getCertificateVersions(String certificateName,
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3158,6 +3212,12 @@ public Mono> getCertificatePolicyWithResponseAsync(String c
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3245,6 +3305,12 @@ public Response getCertificatePolicyWithResponse(String certificateN
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3311,6 +3377,12 @@ public Response getCertificatePolicyWithResponse(String certificateN
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3401,6 +3473,12 @@ public Mono> updateCertificatePolicyWithResponseAsync(Strin
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3467,6 +3545,12 @@ public Mono> updateCertificatePolicyWithResponseAsync(Strin
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3557,6 +3641,12 @@ public Response updateCertificatePolicyWithResponse(String certifica
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3633,6 +3723,12 @@ public Response updateCertificatePolicyWithResponse(String certifica
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3734,6 +3830,12 @@ public Mono> updateCertificateWithResponseAsync(String cert
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3810,6 +3912,12 @@ public Mono> updateCertificateWithResponseAsync(String cert
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -3912,6 +4020,12 @@ public Response updateCertificateWithResponse(String certificateName
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -4017,6 +4131,12 @@ public Mono> getCertificateWithResponseAsync(String certifi
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -4465,6 +4585,12 @@ public Response deleteCertificateOperationWithResponse(String certif
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -4593,6 +4719,12 @@ public Mono> mergeCertificateWithResponseAsync(String certi
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -4767,6 +4899,12 @@ public Response backupCertificateWithResponse(String certificateName
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -4879,6 +5017,12 @@ public Mono> restoreCertificateWithResponseAsync(BinaryData
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -5215,6 +5359,12 @@ public PagedIterable getDeletedCertificates(RequestOptions requestOp
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -5320,6 +5470,12 @@ public Mono> getDeletedCertificateWithResponseAsync(String
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -5401,9 +5557,8 @@ public Response getDeletedCertificateWithResponse(String certificate
@ServiceMethod(returns = ReturnType.SINGLE)
public Mono> purgeDeletedCertificateWithResponseAsync(String certificateName,
RequestOptions requestOptions) {
- final String accept = "application/json";
return FluxUtil.withContext(context -> service.purgeDeletedCertificate(this.getVaultBaseUrl(),
- this.getServiceVersion().getVersion(), certificateName, accept, requestOptions, context));
+ this.getServiceVersion().getVersion(), certificateName, requestOptions, context));
}
/**
@@ -5423,9 +5578,8 @@ public Mono> purgeDeletedCertificateWithResponseAsync(String cert
*/
@ServiceMethod(returns = ReturnType.SINGLE)
public Response purgeDeletedCertificateWithResponse(String certificateName, RequestOptions requestOptions) {
- final String accept = "application/json";
return service.purgeDeletedCertificateSync(this.getVaultBaseUrl(), this.getServiceVersion().getVersion(),
- certificateName, accept, requestOptions, Context.NONE);
+ certificateName, requestOptions, Context.NONE);
}
/**
@@ -5470,6 +5624,12 @@ public Response purgeDeletedCertificateWithResponse(String certificateName
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
@@ -5572,6 +5732,12 @@ public Mono> recoverDeletedCertificateWithResponseAsync(Str
* upns (Optional): [
* String (Optional)
* ]
+ * uris (Optional): [
+ * String (Optional)
+ * ]
+ * ipAddresses (Optional): [
+ * String (Optional)
+ * ]
* }
* key_usage (Optional): [
* String(digitalSignature/nonRepudiation/keyEncipherment/dataEncipherment/keyAgreement/keyCertSign/cRLSign/encipherOnly/decipherOnly) (Optional)
diff --git a/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/models/SubjectAlternativeNames.java b/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/models/SubjectAlternativeNames.java
index 659dd3462af7..c8e236f0b497 100644
--- a/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/models/SubjectAlternativeNames.java
+++ b/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/models/SubjectAlternativeNames.java
@@ -36,6 +36,18 @@ public final class SubjectAlternativeNames implements JsonSerializable userPrincipalNames;
+ /*
+ * Uniform Resource Identifiers.
+ */
+ @Generated
+ private List uniformResourceIdentifiers;
+
+ /*
+ * IP addresses; supports IPv4 and IPv6.
+ */
+ @Generated
+ private List ipAddresses;
+
/**
* Creates an instance of SubjectAlternativeNames class.
*/
@@ -109,6 +121,50 @@ public SubjectAlternativeNames setUserPrincipalNames(List userPrincipalN
return this;
}
+ /**
+ * Get the uniformResourceIdentifiers property: Uniform Resource Identifiers.
+ *
+ * @return the uniformResourceIdentifiers value.
+ */
+ @Generated
+ public List getUniformResourceIdentifiers() {
+ return this.uniformResourceIdentifiers;
+ }
+
+ /**
+ * Set the uniformResourceIdentifiers property: Uniform Resource Identifiers.
+ *
+ * @param uniformResourceIdentifiers the uniformResourceIdentifiers value to set.
+ * @return the SubjectAlternativeNames object itself.
+ */
+ @Generated
+ public SubjectAlternativeNames setUniformResourceIdentifiers(List uniformResourceIdentifiers) {
+ this.uniformResourceIdentifiers = uniformResourceIdentifiers;
+ return this;
+ }
+
+ /**
+ * Get the ipAddresses property: IP addresses; supports IPv4 and IPv6.
+ *
+ * @return the ipAddresses value.
+ */
+ @Generated
+ public List getIpAddresses() {
+ return this.ipAddresses;
+ }
+
+ /**
+ * Set the ipAddresses property: IP addresses; supports IPv4 and IPv6.
+ *
+ * @param ipAddresses the ipAddresses value to set.
+ * @return the SubjectAlternativeNames object itself.
+ */
+ @Generated
+ public SubjectAlternativeNames setIpAddresses(List ipAddresses) {
+ this.ipAddresses = ipAddresses;
+ return this;
+ }
+
/**
* {@inheritDoc}
*/
@@ -119,6 +175,9 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeArrayField("emails", this.emails, (writer, element) -> writer.writeString(element));
jsonWriter.writeArrayField("dns_names", this.dnsNames, (writer, element) -> writer.writeString(element));
jsonWriter.writeArrayField("upns", this.userPrincipalNames, (writer, element) -> writer.writeString(element));
+ jsonWriter.writeArrayField("uris", this.uniformResourceIdentifiers,
+ (writer, element) -> writer.writeString(element));
+ jsonWriter.writeArrayField("ipAddresses", this.ipAddresses, (writer, element) -> writer.writeString(element));
return jsonWriter.writeEndObject();
}
@@ -147,6 +206,12 @@ public static SubjectAlternativeNames fromJson(JsonReader jsonReader) throws IOE
} else if ("upns".equals(fieldName)) {
List userPrincipalNames = reader.readArray(reader1 -> reader1.getString());
deserializedSubjectAlternativeNames.userPrincipalNames = userPrincipalNames;
+ } else if ("uris".equals(fieldName)) {
+ List uniformResourceIdentifiers = reader.readArray(reader1 -> reader1.getString());
+ deserializedSubjectAlternativeNames.uniformResourceIdentifiers = uniformResourceIdentifiers;
+ } else if ("ipAddresses".equals(fieldName)) {
+ List ipAddresses = reader.readArray(reader1 -> reader1.getString());
+ deserializedSubjectAlternativeNames.ipAddresses = ipAddresses;
} else {
reader.skipChildren();
}
diff --git a/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateAsyncClientTest.java b/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateAsyncClientTest.java
index 2421bb75e1f3..b7bd7a4ac43d 100644
--- a/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateAsyncClientTest.java
+++ b/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateAsyncClientTest.java
@@ -22,6 +22,7 @@
import com.azure.security.keyvault.certificates.models.DeletedCertificate;
import com.azure.security.keyvault.certificates.models.KeyVaultCertificateWithPolicy;
import com.azure.security.keyvault.certificates.models.MergeCertificateOptions;
+import com.azure.security.keyvault.certificates.models.SubjectAlternativeNames;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.Certificate;
@@ -989,6 +990,46 @@ public void mergeCertificateNotFound(HttpClient httpClient, CertificateServiceVe
e -> assertResponseException(e, ResourceNotFoundException.class, HttpURLConnection.HTTP_NOT_FOUND));
}
+ @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
+ @MethodSource("getTestParameters")
+ public void createCertificateWithSanIpAndUri(HttpClient httpClient, CertificateServiceVersion serviceVersion) {
+ // IP address and URI SAN fields require API version >= 2025-06-01-preview.
+ // Old-style versions (7.x) don't support these fields, and "7.6" > "2025" lexicographically,
+ // so we check for date-based versioning instead.
+ if (!serviceVersion.getVersion().startsWith("20")) {
+ return;
+ }
+
+ createCertificateAsyncClient(httpClient, serviceVersion);
+
+ createCertificateWithSanIpAndUriRunner((certificatePolicy) -> {
+ String certName = testResourceNamer.randomName("testSanCert", 25);
+ PollerFlux certPoller
+ = setPlaybackPollerFluxPollInterval(
+ certificateAsyncClient.beginCreateCertificate(certName, certificatePolicy));
+
+ StepVerifier.create(certPoller.last().flatMap(AsyncPollResponse::getFinalResult))
+ .assertNext(createdCert -> {
+ assertNotNull(createdCert);
+ assertEquals(certName, createdCert.getName());
+
+ SubjectAlternativeNames san = createdCert.getPolicy().getSubjectAlternativeNames();
+
+ assertNotNull(san);
+ assertNotNull(san.getIpAddresses());
+ assertEquals(2, san.getIpAddresses().size());
+ assertTrue(san.getIpAddresses().contains("10.0.0.1"));
+ assertTrue(san.getIpAddresses().contains("192.168.1.100"));
+ assertNotNull(san.getUniformResourceIdentifiers());
+ assertEquals(2, san.getUniformResourceIdentifiers().size());
+ assertTrue(san.getUniformResourceIdentifiers().contains("https://example.com/api"));
+ assertTrue(
+ san.getUniformResourceIdentifiers().contains("spiffe://cluster.local/ns/default/sa/myapp"));
+ })
+ .verifyComplete();
+ });
+ }
+
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("getTestParameters")
public void importPemCertificate(HttpClient httpClient, CertificateServiceVersion serviceVersion) {
@@ -1002,4 +1043,5 @@ public void importPemCertificate(HttpClient httpClient, CertificateServiceVersio
})
.verifyComplete());
}
+
}
diff --git a/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateClientTest.java b/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateClientTest.java
index efaef89ff4ca..0e6d5716fe92 100644
--- a/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateClientTest.java
+++ b/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateClientTest.java
@@ -27,6 +27,7 @@
import com.azure.security.keyvault.certificates.models.KeyVaultCertificate;
import com.azure.security.keyvault.certificates.models.KeyVaultCertificateWithPolicy;
import com.azure.security.keyvault.certificates.models.MergeCertificateOptions;
+import com.azure.security.keyvault.certificates.models.SubjectAlternativeNames;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.Certificate;
@@ -968,6 +969,47 @@ public void mergeCertificateNotFound(HttpClient httpClient, CertificateServiceVe
ResourceNotFoundException.class, HttpURLConnection.HTTP_NOT_FOUND);
}
+ @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
+ @MethodSource("getTestParameters")
+ public void createCertificateWithSanIpAndUri(HttpClient httpClient, CertificateServiceVersion serviceVersion) {
+ // IP address and URI SAN fields require API version >= 2025-06-01-preview.
+ // Old-style versions (7.x) don't support these fields, and "7.6" > "2025" lexicographically,
+ // so we check for date-based versioning instead.
+ if (!serviceVersion.getVersion().startsWith("20")) {
+ return;
+ }
+
+ createCertificateClient(httpClient, serviceVersion);
+
+ createCertificateWithSanIpAndUriRunner((certificatePolicy) -> {
+ String certName = testResourceNamer.randomName("testSanCert", 25);
+ SyncPoller certPoller
+ = setPlaybackSyncPollerPollInterval(
+ certificateClient.beginCreateCertificate(certName, certificatePolicy));
+
+ certPoller.waitForCompletion();
+
+ KeyVaultCertificateWithPolicy createdCert = certPoller.getFinalResult();
+
+ assertNotNull(createdCert);
+ assertEquals(certName, createdCert.getName());
+
+ SubjectAlternativeNames san = createdCert.getPolicy().getSubjectAlternativeNames();
+
+ assertNotNull(san);
+ assertNotNull(san.getIpAddresses());
+ assertEquals(2, san.getIpAddresses().size());
+ assertTrue(san.getIpAddresses().contains("10.0.0.1"));
+ assertTrue(san.getIpAddresses().contains("192.168.1.100"));
+ assertNotNull(san.getUniformResourceIdentifiers());
+ assertEquals(2, san.getUniformResourceIdentifiers().size());
+ assertTrue(san.getUniformResourceIdentifiers().contains("https://example.com/api"));
+ assertTrue(san.getUniformResourceIdentifiers().contains("spiffe://cluster.local/ns/default/sa/myapp"));
+
+ deleteAndPurgeCertificate(certName);
+ });
+ }
+
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("getTestParameters")
public void importPemCertificate(HttpClient httpClient, CertificateServiceVersion serviceVersion) {
diff --git a/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateClientTestBase.java b/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateClientTestBase.java
index a34469eafc99..bafec5f3565b 100644
--- a/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateClientTestBase.java
+++ b/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/CertificateClientTestBase.java
@@ -34,6 +34,7 @@
import com.azure.security.keyvault.certificates.models.ImportCertificateOptions;
import com.azure.security.keyvault.certificates.models.KeyVaultCertificate;
import com.azure.security.keyvault.certificates.models.LifetimeAction;
+import com.azure.security.keyvault.certificates.models.SubjectAlternativeNames;
import com.azure.security.keyvault.certificates.models.WellKnownIssuerNames;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.provider.Arguments;
@@ -452,6 +453,23 @@ void importCertificateRunner(Consumer testRunner) {
testRunner.accept(importCertificateOptions);
}
+ @Test
+ public abstract void createCertificateWithSanIpAndUri(HttpClient httpClient,
+ CertificateServiceVersion serviceVersion);
+
+ void createCertificateWithSanIpAndUriRunner(Consumer testRunner) {
+ SubjectAlternativeNames san = new SubjectAlternativeNames().setDnsNames(Arrays.asList("san-test.example.com"))
+ .setIpAddresses(Arrays.asList("10.0.0.1", "192.168.1.100"))
+ .setUniformResourceIdentifiers(
+ Arrays.asList("https://example.com/api", "spiffe://cluster.local/ns/default/sa/myapp"));
+
+ CertificatePolicy policy = new CertificatePolicy(WellKnownIssuerNames.SELF, "CN=SanIpUriTest", san)
+ .setKeyType(CertificateKeyType.RSA)
+ .setKeySize(2048);
+
+ testRunner.accept(policy);
+ }
+
@Test
public abstract void importPemCertificate(HttpClient httpClient, CertificateServiceVersion serviceVersion)
throws IOException;
diff --git a/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/models/SubjectAlternativeNamesTest.java b/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/models/SubjectAlternativeNamesTest.java
new file mode 100644
index 000000000000..58d00c0a1ba7
--- /dev/null
+++ b/sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/models/SubjectAlternativeNamesTest.java
@@ -0,0 +1,264 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.security.keyvault.certificates.models;
+
+import com.azure.json.JsonProviders;
+import com.azure.json.JsonReader;
+import com.azure.json.JsonWriter;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * Unit tests for {@link SubjectAlternativeNames}, focusing on the ipAddresses and uniformResourceIdentifiers fields.
+ */
+class SubjectAlternativeNamesTest {
+
+ @Test
+ void getAndSetIpAddresses() {
+ SubjectAlternativeNames san = new SubjectAlternativeNames();
+ assertNull(san.getIpAddresses());
+
+ List ips = Arrays.asList("10.0.0.1", "192.168.1.100", "2001:db8::1");
+ SubjectAlternativeNames result = san.setIpAddresses(ips);
+
+ assertEquals(ips, san.getIpAddresses());
+ assertEquals(san, result, "setIpAddresses should return the same instance for fluent chaining");
+ }
+
+ @Test
+ void getAndSetUniformResourceIdentifiers() {
+ SubjectAlternativeNames san = new SubjectAlternativeNames();
+ assertNull(san.getUniformResourceIdentifiers());
+
+ List uris = Arrays.asList("https://example.com", "spiffe://cluster.local/ns/default/sa/myapp");
+ SubjectAlternativeNames result = san.setUniformResourceIdentifiers(uris);
+
+ assertEquals(uris, san.getUniformResourceIdentifiers());
+ assertEquals(san, result, "setUniformResourceIdentifiers should return the same instance for fluent chaining");
+ }
+
+ @Test
+ void jsonRoundTripIpAddressesOnly() throws IOException {
+ List ips = Arrays.asList("10.0.0.1", "192.168.1.100");
+ SubjectAlternativeNames original = new SubjectAlternativeNames().setIpAddresses(ips);
+
+ SubjectAlternativeNames deserialized = roundTrip(original);
+
+ assertNotNull(deserialized);
+ assertEquals(ips, deserialized.getIpAddresses());
+ assertNull(deserialized.getEmails());
+ assertNull(deserialized.getDnsNames());
+ assertNull(deserialized.getUserPrincipalNames());
+ assertNull(deserialized.getUniformResourceIdentifiers());
+ }
+
+ @Test
+ void jsonRoundTripUniformResourceIdentifiersOnly() throws IOException {
+ List uris = Arrays.asList("https://example.com", "spiffe://cluster.local/ns/default/sa/myapp");
+ SubjectAlternativeNames original = new SubjectAlternativeNames().setUniformResourceIdentifiers(uris);
+
+ SubjectAlternativeNames deserialized = roundTrip(original);
+
+ assertNotNull(deserialized);
+ assertEquals(uris, deserialized.getUniformResourceIdentifiers());
+ assertNull(deserialized.getEmails());
+ assertNull(deserialized.getDnsNames());
+ assertNull(deserialized.getUserPrincipalNames());
+ assertNull(deserialized.getIpAddresses());
+ }
+
+ @Test
+ void jsonRoundTripIpv6Addresses() throws IOException {
+ List ips = Arrays.asList("2001:db8::1", "::1", "fe80::1%25eth0");
+ SubjectAlternativeNames original = new SubjectAlternativeNames().setIpAddresses(ips);
+
+ SubjectAlternativeNames deserialized = roundTrip(original);
+
+ assertNotNull(deserialized);
+ assertEquals(ips, deserialized.getIpAddresses());
+ }
+
+ @Test
+ void jsonRoundTripAllFields() throws IOException {
+ SubjectAlternativeNames original = new SubjectAlternativeNames().setEmails(Arrays.asList("user@example.com"))
+ .setDnsNames(Arrays.asList("example.com", "www.example.com"))
+ .setUserPrincipalNames(Arrays.asList("user@contoso.onmicrosoft.com"))
+ .setUniformResourceIdentifiers(Arrays.asList("https://example.com/api"))
+ .setIpAddresses(Arrays.asList("10.0.0.1", "2001:db8::1"));
+
+ SubjectAlternativeNames deserialized = roundTrip(original);
+
+ assertNotNull(deserialized);
+ assertEquals(original.getEmails(), deserialized.getEmails());
+ assertEquals(original.getDnsNames(), deserialized.getDnsNames());
+ assertEquals(original.getUserPrincipalNames(), deserialized.getUserPrincipalNames());
+ assertEquals(original.getUniformResourceIdentifiers(), deserialized.getUniformResourceIdentifiers());
+ assertEquals(original.getIpAddresses(), deserialized.getIpAddresses());
+ }
+
+ @Test
+ void jsonRoundTripEmptyLists() throws IOException {
+ SubjectAlternativeNames original = new SubjectAlternativeNames().setIpAddresses(Collections.emptyList())
+ .setUniformResourceIdentifiers(Collections.emptyList());
+
+ SubjectAlternativeNames deserialized = roundTrip(original);
+
+ assertNotNull(deserialized);
+ assertNotNull(deserialized.getIpAddresses());
+ assertEquals(0, deserialized.getIpAddresses().size());
+ assertNotNull(deserialized.getUniformResourceIdentifiers());
+ assertEquals(0, deserialized.getUniformResourceIdentifiers().size());
+ }
+
+ @Test
+ void jsonRoundTripSingleIpAddress() throws IOException {
+ SubjectAlternativeNames original
+ = new SubjectAlternativeNames().setIpAddresses(Collections.singletonList("127.0.0.1"));
+
+ SubjectAlternativeNames deserialized = roundTrip(original);
+
+ assertNotNull(deserialized);
+ assertEquals(1, deserialized.getIpAddresses().size());
+ assertEquals("127.0.0.1", deserialized.getIpAddresses().get(0));
+ }
+
+ @Test
+ void jsonRoundTripSingleUri() throws IOException {
+ SubjectAlternativeNames original = new SubjectAlternativeNames()
+ .setUniformResourceIdentifiers(Collections.singletonList("https://contoso.vault.azure.net"));
+
+ SubjectAlternativeNames deserialized = roundTrip(original);
+
+ assertNotNull(deserialized);
+ assertEquals(1, deserialized.getUniformResourceIdentifiers().size());
+ assertEquals("https://contoso.vault.azure.net", deserialized.getUniformResourceIdentifiers().get(0));
+ }
+
+ @Test
+ void deserializeFromJsonWithIpAddresses() throws IOException {
+ String json = "{\"ipAddresses\":[\"10.0.0.1\",\"192.168.1.100\"]}";
+
+ SubjectAlternativeNames deserialized;
+ try (JsonReader reader = JsonProviders.createReader(json)) {
+ deserialized = SubjectAlternativeNames.fromJson(reader);
+ }
+
+ assertNotNull(deserialized);
+ assertEquals(Arrays.asList("10.0.0.1", "192.168.1.100"), deserialized.getIpAddresses());
+ assertNull(deserialized.getEmails());
+ assertNull(deserialized.getDnsNames());
+ }
+
+ @Test
+ void deserializeFromJsonWithUris() throws IOException {
+ String json = "{\"uris\":[\"https://example.com\",\"spiffe://trust-domain/path\"]}";
+
+ SubjectAlternativeNames deserialized;
+ try (JsonReader reader = JsonProviders.createReader(json)) {
+ deserialized = SubjectAlternativeNames.fromJson(reader);
+ }
+
+ assertNotNull(deserialized);
+ assertEquals(Arrays.asList("https://example.com", "spiffe://trust-domain/path"),
+ deserialized.getUniformResourceIdentifiers());
+ assertNull(deserialized.getIpAddresses());
+ }
+
+ @Test
+ void deserializeFromJsonWithAllSanFields() throws IOException {
+ String json = "{" + "\"emails\":[\"user@example.com\"]," + "\"dns_names\":[\"example.com\"],"
+ + "\"upns\":[\"user@contoso.onmicrosoft.com\"]," + "\"uris\":[\"https://example.com\"],"
+ + "\"ipAddresses\":[\"10.0.0.1\"]" + "}";
+
+ SubjectAlternativeNames deserialized;
+ try (JsonReader reader = JsonProviders.createReader(json)) {
+ deserialized = SubjectAlternativeNames.fromJson(reader);
+ }
+
+ assertNotNull(deserialized);
+ assertEquals(Collections.singletonList("user@example.com"), deserialized.getEmails());
+ assertEquals(Collections.singletonList("example.com"), deserialized.getDnsNames());
+ assertEquals(Collections.singletonList("user@contoso.onmicrosoft.com"), deserialized.getUserPrincipalNames());
+ assertEquals(Collections.singletonList("https://example.com"), deserialized.getUniformResourceIdentifiers());
+ assertEquals(Collections.singletonList("10.0.0.1"), deserialized.getIpAddresses());
+ }
+
+ @Test
+ void deserializeIgnoresUnknownFields() throws IOException {
+ String json = "{\"ipAddresses\":[\"10.0.0.1\"],\"unknownField\":\"someValue\"}";
+
+ SubjectAlternativeNames deserialized;
+ try (JsonReader reader = JsonProviders.createReader(json)) {
+ deserialized = SubjectAlternativeNames.fromJson(reader);
+ }
+
+ assertNotNull(deserialized);
+ assertEquals(Collections.singletonList("10.0.0.1"), deserialized.getIpAddresses());
+ }
+
+ @Test
+ void serializeIpAddressesUsesCorrectJsonFieldName() throws IOException {
+ SubjectAlternativeNames san
+ = new SubjectAlternativeNames().setIpAddresses(Collections.singletonList("10.0.0.1"));
+
+ String json = toJsonString(san);
+
+ // The JSON field name for ipAddresses is "ipAddresses"
+ assertNotNull(json);
+ assertEquals(true, json.contains("\"ipAddresses\""));
+ assertEquals(true, json.contains("\"10.0.0.1\""));
+ }
+
+ @Test
+ void serializeUrisUsesCorrectJsonFieldName() throws IOException {
+ SubjectAlternativeNames san = new SubjectAlternativeNames()
+ .setUniformResourceIdentifiers(Collections.singletonList("https://example.com"));
+
+ String json = toJsonString(san);
+
+ // The JSON field name for uniformResourceIdentifiers is "uris"
+ assertNotNull(json);
+ assertEquals(true, json.contains("\"uris\""));
+ assertEquals(true, json.contains("\"https://example.com\""));
+ }
+
+ @Test
+ void nullFieldsAreOmittedInSerialization() throws IOException {
+ SubjectAlternativeNames san = new SubjectAlternativeNames();
+
+ String json = toJsonString(san);
+
+ // With all fields null, the JSON should be an empty object
+ assertNotNull(json);
+ assertEquals(false, json.contains("\"ipAddresses\""));
+ assertEquals(false, json.contains("\"uris\""));
+ assertEquals(false, json.contains("\"emails\""));
+ assertEquals(false, json.contains("\"dns_names\""));
+ assertEquals(false, json.contains("\"upns\""));
+ }
+
+ private static SubjectAlternativeNames roundTrip(SubjectAlternativeNames original) throws IOException {
+ String json = toJsonString(original);
+ try (JsonReader reader = JsonProviders.createReader(json)) {
+ return SubjectAlternativeNames.fromJson(reader);
+ }
+ }
+
+ private static String toJsonString(SubjectAlternativeNames san) throws IOException {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ try (JsonWriter writer = JsonProviders.createWriter(outputStream)) {
+ san.toJson(writer);
+ }
+ return outputStream.toString("UTF-8");
+ }
+}
diff --git a/sdk/keyvault/azure-security-keyvault-certificates/tsp-location.yaml b/sdk/keyvault/azure-security-keyvault-certificates/tsp-location.yaml
index 51d3add132dd..94a2837d2b59 100644
--- a/sdk/keyvault/azure-security-keyvault-certificates/tsp-location.yaml
+++ b/sdk/keyvault/azure-security-keyvault-certificates/tsp-location.yaml
@@ -1,5 +1,5 @@
directory: specification/keyvault/Security.KeyVault.Certificates
-commit: 396ab529763b7195ab089f58e2eefb011e1b290d
+commit: 35275d315efee7fa79b6661c29cb3f1c05e86b76
repo: Azure/azure-rest-api-specs
cleanup: true
additionalDirectories: