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
2 changes: 1 addition & 1 deletion eng/versioning/version_client.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ com.azure:azure-search-perf;1.0.0-beta.1;1.0.0-beta.1
com.azure:azure-security-attestation;1.2.0;1.3.0-beta.1
com.azure:azure-security-confidentialledger;1.0.38;2.0.2-beta.2
com.azure:azure-security-keyvault-administration;4.8.3;4.9.0-beta.2
com.azure:azure-security-keyvault-certificates;4.9.3;4.10.0-beta.2
com.azure:azure-security-keyvault-certificates;4.9.3;4.10.0
com.azure:azure-security-keyvault-jca;2.13.0;2.14.0-beta.1
com.azure:azure-security-test-keyvault-jca;1.0.0;1.0.0
com.azure:azure-security-keyvault-keys;4.11.3;4.12.0-beta.3
Expand Down
15 changes: 11 additions & 4 deletions sdk/keyvault/azure-security-keyvault-certificates/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
# Release History

## 4.10.0-beta.2 (Unreleased)
## 4.10.0 (2026-10-27)

### Features Added

### Breaking Changes
* `models.PlatformManaged` was added

### Bugs Fixed
#### `models.CertificatePolicy` was modified

### Other Changes
* `getPlatformManaged()` was added
* `setPlatformManaged(models.PlatformManaged)` was added
* `forPlatformManaged(models.PlatformManaged)` was added

#### `CertificateServiceVersion` was modified

* `V2026_03_01_PREVIEW` was added
* `V2026_04_01` was added and is the default service version.

## 4.9.3 (2026-10-06)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "java",
"TagPrefix": "java/keyvault/azure-security-keyvault-certificates",
"Tag": "java/keyvault/azure-security-keyvault-certificates_e04aab094e"
"Tag": "java/keyvault/azure-security-keyvault-certificates_9013b99e00"
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ private static void customizeServiceVersion(LibraryCustomization customization)
.setJavadocComment("The versions of Azure Key Vault Certificates supported by this client library.");

for (String version : Arrays.asList("7.0", "7.1", "7.2", "7.3", "7.4", "7.5", "7.6",
"2025-07-01", "2026-03-01-preview")) {
"2025-07-01", "2026-03-01-preview", "2026-04-01")) {
enumDeclaration.addEnumConstant("V" + version.replace('.', '_').replace('-', '_').toUpperCase())
.setJavadocComment("Service version {@code " + version + "}.")
.addArgument(new StringLiteralExpr(version));
Expand All @@ -142,7 +142,7 @@ private static void customizeServiceVersion(LibraryCustomization customization)
.setType("CertificateServiceVersion")
.setJavadocComment(new Javadoc(parseText("Gets the latest service version supported by this client library."))
.addBlockTag("return", "The latest {@link CertificateServiceVersion}."))
.setBody(StaticJavaParser.parseBlock("{ return V2026_03_01_PREVIEW; }"));
.setBody(StaticJavaParser.parseBlock("{ return V2026_04_01; }"));

customization.getRawEditor()
.addFile("src/main/java/com/azure/security/keyvault/certificates/CertificateServiceVersion.java",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<groupId>com.azure</groupId>
<artifactId>azure-security-keyvault-certificates</artifactId>
<version>4.10.0-beta.2</version> <!-- {x-version-update;com.azure:azure-security-keyvault-certificates;current} -->
<version>4.10.0</version> <!-- {x-version-update;com.azure:azure-security-keyvault-certificates;current} -->

<name>Microsoft Azure client library for KeyVault Certificates</name>
<description>This module contains client library for Microsoft Azure KeyVault Certificates.</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ public enum CertificateServiceVersion implements ServiceVersion {
/**
* Service version {@code 2026-03-01-preview}.
*/
V2026_03_01_PREVIEW("2026-03-01-preview");
V2026_03_01_PREVIEW("2026-03-01-preview"),
/**
* Service version {@code 2026-04-01}.
*/
V2026_04_01("2026-04-01");

private final String version;

Expand All @@ -67,6 +71,6 @@ public String getVersion() {
* @return The latest {@link CertificateServiceVersion}.
*/
public static CertificateServiceVersion getLatest() {
return V2026_03_01_PREVIEW;
return V2026_04_01;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,8 @@ public Boolean isCertificateTransparent() {
* Get the platform managed certificate configuration.
*
* <p><strong>Warning: this property is currently intended for internal (first-party) Key Vault use only.</strong>
* It is only populated when the policy was created against the preview service version
* {@code 2026-03-01-preview}. Third-party callers should not rely on this property; the underlying
* It is populated when the policy uses platform-managed configuration in service version
* {@code 2026-04-01}. Third-party callers should not rely on this property; the underlying
* service contract may change without notice.
*
* @return the platform managed certificate configuration.
Expand All @@ -444,7 +444,7 @@ public PlatformManaged getPlatformManaged() {
* Set the platform managed certificate configuration.
*
* <p><strong>Warning: this property is currently intended for internal (first-party) Key Vault use only.</strong>
* It is exposed under the preview service version {@code 2026-03-01-preview} and is not generally available.
* It is exposed in service version {@code 2026-04-01}, but the feature is not generally available.
* Third-party calls that supply a {@link PlatformManaged} configuration will be rejected by the service.
* Do not use this setter in production code.
*
Expand Down Expand Up @@ -510,7 +510,7 @@ public static CertificatePolicy getDefault() {
* that specify them when {@code platformManaged} is set.
*
* <p><strong>Warning: this factory is currently intended for internal (first-party) Key Vault use only.</strong>
* It targets the preview service version {@code 2026-03-01-preview} and is not generally available. Third-party
* It targets service version {@code 2026-04-01}, but the feature is not generally available. Third-party
* calls will be rejected by the service. Do not use in production code.
*
* @param platformManaged the platform-managed certificate configuration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* Properties of the platform managed certificate.
*
* <p><strong>Warning: this feature is currently intended for internal (first-party) Key Vault use only.</strong>
* It is exposed in the preview service version {@code 2026-03-01-preview} and is not generally available.
* It is exposed in service version {@code 2026-04-01}, but the feature is not generally available.
* Third-party calls that supply a {@link CertificatePolicy} configured via
* {@link CertificatePolicy#forPlatformManaged(PlatformManaged)} will be rejected by the service. The shape
* accepted under {@link #setMetadata(Map)} and the values accepted for {@link #setCertificateUsage(String)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
Expand Down Expand Up @@ -916,8 +917,8 @@ public void importCertificate(HttpClient httpClient, CertificateServiceVersion s
importCertificateRunner((importCertificateOptions) -> StepVerifier
.create(certificateAsyncClient.importCertificate(importCertificateOptions))
.assertNext(importedCertificate -> {
assertTrue("931dd8219585752bc915684ca3967974c400de28"
.equalsIgnoreCase(importedCertificate.getProperties().getX509ThumbprintAsString()));
assertArrayEquals(ImportCertificateFixture.getThumbprint(),
importedCertificate.getProperties().getX509Thumbprint());
assertEquals(importCertificateOptions.isEnabled(), importedCertificate.getProperties().isEnabled());

// Load the CER part into X509Certificate object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,18 @@ public void buildSyncClientTest() {

@Test
public void buildSyncClientUsingDefaultApiVersionTest() {
assertEquals("2026-04-01", CertificateServiceVersion.getLatest().getVersion());
CertificateClient certificateClient = new CertificateClientBuilder().vaultUrl(vaultUrl)
.credential(new TestUtils.TestCredential())
.httpClient(request -> Mono.just(new MockHttpResponse(request, 200)))
.httpClient(request -> {
assertEquals("api-version=2026-04-01", request.getUrl().getQuery());
return Mono.just(new MockHttpResponse(request, 404));
})
.buildClient();

assertNotNull(certificateClient);
assertEquals(CertificateClient.class.getSimpleName(), certificateClient.getClass().getSimpleName());
assertThrows(HttpResponseException.class, () -> certificateClient.getCertificate(certificateName));
}

@Test
Expand All @@ -73,13 +78,18 @@ public void buildAsyncClientTest() {

@Test
public void buildAsyncClientUsingDefaultApiVersionTest() {
assertEquals("2026-04-01", CertificateServiceVersion.getLatest().getVersion());
CertificateAsyncClient certificateAsyncClient = new CertificateClientBuilder().vaultUrl(vaultUrl)
.credential(new TestUtils.TestCredential())
.httpClient(request -> Mono.just(new MockHttpResponse(request, 200)))
.httpClient(request -> {
assertEquals("api-version=2026-04-01", request.getUrl().getQuery());
return Mono.just(new MockHttpResponse(request, 404));
})
.buildAsyncClient();

assertNotNull(certificateAsyncClient);
assertEquals(CertificateAsyncClient.class.getSimpleName(), certificateAsyncClient.getClass().getSimpleName());
assertThrows(HttpResponseException.class, () -> certificateAsyncClient.getCertificate(certificateName).block());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import java.util.Map;
import java.util.NoSuchElementException;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
Expand Down Expand Up @@ -903,8 +904,8 @@ public void importCertificate(HttpClient httpClient, CertificateServiceVersion s
KeyVaultCertificateWithPolicy importedCertificate
= certificateClient.importCertificate(importCertificateOptions);

assertTrue("931dd8219585752bc915684ca3967974c400de28"
.equalsIgnoreCase(importedCertificate.getProperties().getX509ThumbprintAsString()));
assertArrayEquals(ImportCertificateFixture.getThumbprint(),
importedCertificate.getProperties().getX509Thumbprint());
assertEquals(importCertificateOptions.isEnabled(), importedCertificate.getProperties().isEnabled());

// Load the CER part into X509Certificate object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
Expand All @@ -69,8 +68,6 @@
import java.util.function.Consumer;
import java.util.stream.Stream;

import static com.azure.security.keyvault.certificates.FakeCredentialsForTests.FAKE_CERTIFICATE;
import static com.azure.security.keyvault.certificates.FakeCredentialsForTests.FAKE_PEM_CERTIFICATE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
Expand Down Expand Up @@ -454,7 +451,7 @@ void importCertificateRunner(Consumer<ImportCertificateOptions> testRunner) {
tags.put("key", "val");

ImportCertificateOptions importCertificateOptions
= new ImportCertificateOptions(certificateName, Base64.getDecoder().decode(FAKE_CERTIFICATE))
= new ImportCertificateOptions(certificateName, ImportCertificateFixture.getPkcs12())
.setPassword(certificatePassword)
.setEnabled(true)
.setTags(tags);
Expand Down Expand Up @@ -484,7 +481,7 @@ public abstract void importPemCertificate(HttpClient httpClient, CertificateServ
throws IOException;

void importPemCertificateRunner(Consumer<ImportCertificateOptions> testRunner) {
byte[] certificateContent = FAKE_PEM_CERTIFICATE.getBytes();
byte[] certificateContent = ImportCertificateFixture.getPem();

String certificateName = testResourceNamer.randomName("importCertPem", 25);
HashMap<String, String> tags = new HashMap<>();
Expand Down Expand Up @@ -702,10 +699,12 @@ static Stream<Arguments> getTestParameters() {
static Stream<Arguments> getPlatformManagedTestParameters() {
List<Arguments> argumentsList = new ArrayList<>();

if (shouldServiceVersionBeTested(CertificateServiceVersion.V2026_03_01_PREVIEW)) {
getHttpClients().forEach(httpClient -> argumentsList
.add(Arguments.of(httpClient, CertificateServiceVersion.V2026_03_01_PREVIEW)));
}
getHttpClients().forEach(httpClient -> Arrays
.stream(new CertificateServiceVersion[] {
CertificateServiceVersion.V2026_03_01_PREVIEW,
CertificateServiceVersion.V2026_04_01 })
.filter(CertificateClientTestBase::shouldServiceVersionBeTested)
.forEach(serviceVersion -> argumentsList.add(Arguments.of(httpClient, serviceVersion))));

return argumentsList.stream();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.security.keyvault.certificates;

import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.util.Base64;
import java.util.Date;

final class ImportCertificateFixture {
private static final byte[] PKCS12;
private static final byte[] PEM;
private static final byte[] THUMBPRINT;

static {
try {
char[] password = "fakePasswordPlaceholder".toCharArray();
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(
new ByteArrayInputStream(Base64.getDecoder().decode(FakeCredentialsForTests.FAKE_CERTIFICATE)),
password);
String alias = keyStore.aliases().nextElement();
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password);
X509CertificateHolder original = new X509CertificateHolder(keyStore.getCertificate(alias).getEncoded());

// Renew the existing fake test key with fixed validity dates to avoid expired fixtures and playback drift.
X509CertificateHolder renewed
= new X509v3CertificateBuilder(original.getIssuer(), original.getSerialNumber(),
Date.from(Instant.parse("2020-01-01T00:00:00Z")), Date.from(Instant.parse("2050-01-01T00:00:00Z")),
original.getSubject(), original.getSubjectPublicKeyInfo())
.build(new JcaContentSignerBuilder("SHA256withRSA").build(privateKey));
X509Certificate certificate = new JcaX509CertificateConverter().getCertificate(renewed);
keyStore.setKeyEntry(alias, privateKey, password, new Certificate[] { certificate });
ByteArrayOutputStream output = new ByteArrayOutputStream();
keyStore.store(output, password);
PKCS12 = output.toByteArray();
Base64.Encoder encoder = Base64.getMimeEncoder(64, new byte[] { '\n' });
PEM = ("-----BEGIN CERTIFICATE-----\n" + encoder.encodeToString(certificate.getEncoded())
+ "\n-----END CERTIFICATE-----\n-----BEGIN PRIVATE KEY-----\n"
+ encoder.encodeToString(privateKey.getEncoded()) + "\n-----END PRIVATE KEY-----\n")
.getBytes(StandardCharsets.UTF_8);
THUMBPRINT = MessageDigest.getInstance("SHA-1").digest(certificate.getEncoded());
} catch (Exception exception) {
throw new ExceptionInInitializerError(exception);
}
}

private ImportCertificateFixture() {
}

static byte[] getPkcs12() {
return PKCS12.clone();
}

static byte[] getPem() {
return PEM.clone();
}

static byte[] getThumbprint() {
return THUMBPRINT.clone();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
directory: specification/keyvault/data-plane/Certificates
commit: e054e0def9d5daed1819f447be9a8f05ebdf099f
commit: 569464e8c8b02ebd1b4d939f899508467528c696
Comment thread
rohitsinghal4u marked this conversation as resolved.
repo: Azure/azure-rest-api-specs
cleanup: true
additionalDirectories:
- specification/keyvault/data-plane/Certificates/common
2 changes: 1 addition & 1 deletion sdk/keyvault/azure-security-keyvault-perf/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-security-keyvault-certificates</artifactId>
<version>4.10.0-beta.2</version> <!-- {x-version-update;com.azure:azure-security-keyvault-certificates;current} -->
<version>4.10.0</version> <!-- {x-version-update;com.azure:azure-security-keyvault-certificates;current} -->
</dependency>
<dependency>
<groupId>com.azure</groupId>
Expand Down
Loading