Skip to content
Open
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 @@ -185,7 +185,7 @@ com.azure:azure-search-perf;1.0.0-beta.1;1.0.0-beta.1
com.azure:azure-security-attestation;1.1.39;1.2.0-beta.1
com.azure:azure-security-confidentialledger;1.0.35;1.1.0-beta.3
com.azure:azure-security-keyvault-administration;4.7.7;4.8.0
com.azure:azure-security-keyvault-certificates;4.8.7;4.9.0
com.azure:azure-security-keyvault-certificates;4.9.0;4.10.0-beta.1
com.azure:azure-security-keyvault-jca;2.11.0;2.12.0-beta.1
com.azure:azure-security-test-keyvault-jca;1.0.0;1.0.0
com.azure:azure-security-keyvault-keys;4.10.7;4.11.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Release History

## 4.10.0-beta.1 (2026-05-29)

### Features Added

- Added an experimental `models.PlatformManaged` certificate policy property for Azure Key Vault internal usage.
Any calls using this property will fail and it is not recommended to be used at this point.

## 4.9.0 (2026-05-26)

### Features Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,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")) {
"2025-07-01", "2026-03-01-preview")) {
enumDeclaration.addEnumConstant("V" + version.replace('.', '_').replace('-', '_').toUpperCase())
.setJavadocComment("Service version {@code " + version + "}.")
.addArgument(new StringLiteralExpr(version));
Expand All @@ -121,6 +121,10 @@ private static void customizeServiceVersion(LibraryCustomization customization)
.addMarkerAnnotation("Override")
.setBody(StaticJavaParser.parseBlock("{ return this.version; }"));

// Intentionally pin getLatest() to V2025_07_01. V2026_03_01_PREVIEW exposes the PlatformManaged
// certificate policy property, which is reserved for internal (1P) Key Vault use. Defaulting 3P
// customers to the preview version would invalidate existing recordings without unlocking new
// functionality for them; bump this only when a stable version supersedes V2025_07_01.
enumDeclaration.addMethod("getLatest", Modifier.Keyword.PUBLIC, Modifier.Keyword.STATIC)
.setType("CertificateServiceVersion")
.setJavadocComment(new Javadoc(parseText("Gets the latest service version supported by this client library."))
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.9.0</version> <!-- {x-version-update;com.azure:azure-security-keyvault-certificates;current} -->
<version>4.10.0-beta.1</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 @@ -41,7 +41,11 @@ public enum CertificateServiceVersion implements ServiceVersion {
/**
* Service version {@code 2025-07-01}.
*/
V2025_07_01("2025-07-01");
V2025_07_01("2025-07-01"),
/**
* Service version {@code 2026-03-01-preview}.
*/
V2026_03_01_PREVIEW("2026-03-01-preview");

private final String version;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import com.azure.security.keyvault.certificates.models.PlatformManaged;
import java.io.IOException;
import java.util.List;

Expand Down Expand Up @@ -60,6 +61,12 @@ public final class CertificatePolicy implements JsonSerializable<CertificatePoli
@Generated
private CertificateAttributes attributes;

/*
* Configuration that enables the platform to manage the certificate on behalf of the user.
*/
@Generated
private PlatformManaged platformManaged;

/**
* Creates an instance of CertificatePolicy class.
*/
Expand Down Expand Up @@ -209,6 +216,30 @@ public CertificatePolicy setAttributes(CertificateAttributes attributes) {
return this;
}

/**
* Get the platformManaged property: Configuration that enables the platform to manage the certificate on behalf of
* the user.
*
* @return the platformManaged value.
*/
@Generated
public PlatformManaged getPlatformManaged() {
return this.platformManaged;
}

/**
* Set the platformManaged property: Configuration that enables the platform to manage the certificate on behalf of
* the user.
*
* @param platformManaged the platformManaged value to set.
* @return the CertificatePolicy object itself.
*/
@Generated
public CertificatePolicy setPlatformManaged(PlatformManaged platformManaged) {
this.platformManaged = platformManaged;
return this;
}

/**
* {@inheritDoc}
*/
Expand All @@ -223,6 +254,7 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
(writer, element) -> writer.writeJson(element));
jsonWriter.writeJsonField("issuer", this.issuerParameters);
jsonWriter.writeJsonField("attributes", this.attributes);
jsonWriter.writeJsonField("platformManaged", this.platformManaged);
return jsonWriter.writeEndObject();
}

Expand Down Expand Up @@ -259,6 +291,8 @@ public static CertificatePolicy fromJson(JsonReader jsonReader) throws IOExcepti
deserializedCertificatePolicy.issuerParameters = IssuerParameters.fromJson(reader);
} else if ("attributes".equals(fieldName)) {
deserializedCertificatePolicy.attributes = CertificateAttributes.fromJson(reader);
} else if ("platformManaged".equals(fieldName)) {
deserializedCertificatePolicy.platformManaged = PlatformManaged.fromJson(reader);
} else {
reader.skipChildren();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,26 @@ public Boolean isCertificateTransparent() {
return impl.getIssuerParameters().isCertificateTransparency();
}

/**
* Get the platform managed certificate configuration.
*
* @return the platform managed certificate configuration.
*/
public PlatformManaged getPlatformManaged() {
return impl.getPlatformManaged();
}

/**
* Set the platform managed certificate configuration.
*
* @param platformManaged the platform managed certificate configuration.
* @return the updated CertificatePolicy object itself.
*/
public CertificatePolicy setPlatformManaged(PlatformManaged platformManaged) {
impl.setPlatformManaged(platformManaged);
return this;
}

/**
* Set the lifetime actions
* @param actions the lifetime actions to set.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.security.keyvault.certificates.models;

import com.azure.core.annotation.Fluent;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;

/**
* Properties of the platform managed certificate.
*/
@Fluent
public final class PlatformManaged implements JsonSerializable<PlatformManaged> {
/*
* The intended usage of the certificate.
*/
private String certificateUsage;

/*
* JSON-formatted platform managed metadata.
*/
private Map<String, Object> metadata;

/**
* Creates an instance of {@link PlatformManaged}.
*
* @param certificateUsage The intended usage of the certificate.
*/
public PlatformManaged(String certificateUsage) {
this.certificateUsage = Objects.requireNonNull(certificateUsage, "'certificateUsage' cannot be null.");
}

private PlatformManaged() {
}

/**
* Get the certificate usage.
*
* @return the certificate usage.
*/
public String getCertificateUsage() {
return this.certificateUsage;
}

/**
* Set the certificate usage.
*
* @param certificateUsage the certificate usage.
* @return the updated PlatformManaged object itself.
*/
public PlatformManaged setCertificateUsage(String certificateUsage) {
this.certificateUsage = Objects.requireNonNull(certificateUsage, "'certificateUsage' cannot be null.");
return this;
}

/**
* Get the platform managed metadata.
*
* @return the platform managed metadata.
*/
public Map<String, Object> getMetadata() {
return this.metadata;
}

/**
* Set the platform managed metadata.
*
* @param metadata the platform managed metadata.
* @return the updated PlatformManaged object itself.
*/
public PlatformManaged setMetadata(Map<String, Object> metadata) {
this.metadata = metadata;
return this;
}

@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeStringField("certificateUsage", this.certificateUsage);
if (this.metadata != null) {
jsonWriter.writeUntypedField("metadata", this.metadata);
}
return jsonWriter.writeEndObject();
}

/**
* Reads an instance of PlatformManaged from the JsonReader.
*
* @param jsonReader The JsonReader being read.
* @return An instance of PlatformManaged if the JsonReader was pointing to an instance of it, or null if it was
* pointing to JSON null.
* @throws IOException If an error occurs while reading the PlatformManaged.
*/
public static PlatformManaged fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(reader -> {
PlatformManaged deserializedPlatformManaged = new PlatformManaged();
while (reader.nextToken() != JsonToken.END_OBJECT) {
String fieldName = reader.getFieldName();
reader.nextToken();

if ("certificateUsage".equals(fieldName)) {
deserializedPlatformManaged.certificateUsage = reader.getString();
} else if ("metadata".equals(fieldName)) {
deserializedPlatformManaged.metadata = reader.readMap(JsonReader::readUntyped);
} else {
reader.skipChildren();
}
}

return deserializedPlatformManaged;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,24 @@ public void updateCertificatePolicy(HttpClient httpClient, CertificateServiceVer
});
}

@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS, allowZeroInvocations = true)
@MethodSource("getPlatformManagedTestParameters")
public void createCertificateWithPlatformManagedPolicy(HttpClient httpClient,
CertificateServiceVersion serviceVersion) {
createCertificateAsyncClient(httpClient, serviceVersion);

platformManagedCertificatePolicyRunner(certificateName -> {
CertificatePolicy policy = setupPlatformManagedPolicy();
PollerFlux<CertificateOperation, KeyVaultCertificateWithPolicy> certPoller
= setPlaybackPollerFluxPollInterval(
certificateAsyncClient.beginCreateCertificate(certificateName, policy));

StepVerifier.create(certPoller.last().flatMap(AsyncPollResponse::getFinalResult))
.assertNext(certificate -> assertPlatformManagedPolicy(policy, certificate.getPolicy()))
.verifyComplete();
});
}

@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("getTestParameters")
public void restoreCertificateFromMalformedBackup(HttpClient httpClient, CertificateServiceVersion serviceVersion) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,24 @@ public void updateCertificatePolicy(HttpClient httpClient, CertificateServiceVer
});
}

@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS, allowZeroInvocations = true)
@MethodSource("getPlatformManagedTestParameters")
public void createCertificateWithPlatformManagedPolicy(HttpClient httpClient,
CertificateServiceVersion serviceVersion) {
createCertificateClient(httpClient, serviceVersion);

platformManagedCertificatePolicyRunner(certificateName -> {
CertificatePolicy policy = setupPlatformManagedPolicy();
SyncPoller<CertificateOperation, KeyVaultCertificateWithPolicy> certPoller
= setPlaybackSyncPollerPollInterval(certificateClient.beginCreateCertificate(certificateName, policy));

certPoller.waitForCompletion();

KeyVaultCertificateWithPolicy certificate = certPoller.getFinalResult();
assertPlatformManagedPolicy(policy, certificate.getPolicy());
});
}

@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("getTestParameters")
public void restoreCertificateFromMalformedBackup(HttpClient httpClient, CertificateServiceVersion serviceVersion) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.PlatformManaged;
import com.azure.security.keyvault.certificates.models.SubjectAlternativeNames;
import com.azure.security.keyvault.certificates.models.WellKnownIssuerNames;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -287,6 +288,10 @@ void updateCertificatePolicyRunner(Consumer<String> testRunner) {
testRunner.accept(testResourceNamer.randomName(TEST_CERTIFICATE_NAME, 25));
}

void platformManagedCertificatePolicyRunner(Consumer<String> testRunner) {
testRunner.accept(testResourceNamer.randomName("platformManagedCert", 25));
}

@Test
public abstract void restoreCertificateFromMalformedBackup(HttpClient httpClient,
CertificateServiceVersion serviceVersion);
Expand Down Expand Up @@ -568,6 +573,12 @@ static CertificatePolicy setupPolicy() {
.setLifetimeActions(new LifetimeAction(CertificatePolicyAction.AUTO_RENEW).setDaysBeforeExpiry(40));
}

static CertificatePolicy setupPlatformManagedPolicy() {
return CertificatePolicy.getDefault()
.setPlatformManaged(
new PlatformManaged("serverAuth").setMetadata(Collections.singletonMap("source", "java-sdk-test")));
}

static void assertPolicy(CertificatePolicy expected, CertificatePolicy actual) {
assertEquals(expected.getKeyType(), actual.getKeyType());
assertEquals(expected.getContentType(), actual.getContentType());
Expand All @@ -583,6 +594,14 @@ static void assertPolicy(CertificatePolicy expected, CertificatePolicy actual) {
assertEquals(expected.getKeyUsage().size(), actual.getKeyUsage().size());
}

static void assertPlatformManagedPolicy(CertificatePolicy expected, CertificatePolicy actual) {
assertNotNull(actual);
assertNotNull(actual.getPlatformManaged());
assertEquals(expected.getPlatformManaged().getCertificateUsage(),
actual.getPlatformManaged().getCertificateUsage());
assertEquals(expected.getPlatformManaged().getMetadata(), actual.getPlatformManaged().getMetadata());
}

static void assertCertificate(KeyVaultCertificate expected, KeyVaultCertificate actual) {
assertEquals(expected.getId(), actual.getId());
assertEquals(expected.getKeyId(), actual.getKeyId());
Expand Down Expand Up @@ -644,6 +663,17 @@ static Stream<Arguments> getTestParameters() {
return argumentsList.stream();
}

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)));
}

return argumentsList.stream();
}

/**
* Returns whether the given service version match the rules of test framework.
*
Expand Down
Loading
Loading