Azure / Azure/azure-sdk-for-java

PagedIterable<T> KeyVault Certificate listPropertiesOfCertificates does not honor the includePending optional parameter after the first page

Open
#42,988 1 comment 0 reactions 1 assignee Claimed by @vcolin7 View on GitHub
Client KeyVault needs-team-attention
Dominant language
Java
Stars
2.6k
Forks
2.2k
Avg merge
2d 8h
Merged PRs (30d)
178

Description

The call to fetch the first page sets the appropriate query parameters based on the input parameter value:
https://github.com/Azure/azure-sdk-for-java/blob/840911147fb403b6246d866999189c3875d889c6/sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/CertificateClient.java#L988-L994

But subsequent pages do not have that value set. That means, if the includePending param is set to true, it will not return all the certificates (including pending ones), if the pending certificate happens to be listed in a page other than the first.

Here's the swagger (not sure if this requires some fix to the swagger):
https://github.com/Azure/azure-rest-api-specs/blob/4a4acecea9901c29e19ba50f2d4cf65b20115b69/specification/keyvault/data-plane/Microsoft.KeyVault/stable/7.5/certificates.json#L30-L83

Sample repro:
```C#
package com.example;

import com.azure.identity.AzureCliCredential;
import com.azure.core.util.polling.LongRunningOperationStatus;
import com.azure.core.util.polling.SyncPoller;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.security.keyvault.certificates.CertificateClient;
import com.azure.security.keyvault.certificates.CertificateClientBuilder;
import com.azure.security.keyvault.certificates.models.CertificateContact;
import com.azure.security.keyvault.certificates.models.CertificateIssuer;
import com.azure.security.keyvault.certificates.models.CertificateOperation;
import com.azure.security.keyvault.certificates.models.CertificatePolicy;
import com.azure.security.keyvault.certificates.models.CertificateProperties;
import com.azure.security.keyvault.certificates.models.IssuerProperties;
import com.azure.security.keyvault.certificates.models.KeyVaultCertificate;
import com.azure.security.keyvault.certificates.models.KeyVaultCertificateWithPolicy;
import com.azure.core.util.Context;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.azure.core.credential.TokenCredential;

public class HelloAzure {
public static void main(String[] args) {

// Pre-req: Create 25 certificates first so a page is full (either through the portal or programmatically)

// Case 1: Create a certificate (either on the portal or programmatically) on the first page, and run this, right away.
// Works as expected.
// Case 2: Create a certificate (either on the portal or programmatically) on any subsequent page, and run this, right away.
// Doesn't work as expected.

// TODO: Set to your own KeyVault URL
CertificateClient certificateClient = new CertificateClientBuilder()
.vaultUrl("https://.vault.azure.net/")
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();

System.out.println("Certificates in the key vault (includePending = false):");
// Let's list all the certificates in the key vault.
for (CertificateProperties certificate : certificateClient.listPropertiesOfCertificates()) {
KeyVaultCertificate certificateWithAllProperties =
certificateClient.getCertificateVersion(certificate.getName(), certificate.getVersion());

System.out.println(certificateWithAllProperties.getProperties().getName());
}

System.out.println("Certificates in the key vault (includePending = true):");
// Let's list all the certificates in the key vault.
for (CertificateProperties certificate : certificateClient.listPropertiesOfCertificates(true, Context.NONE)) {
KeyVaultCertificate certificateWithAllProperties =
certificateClient.getCertificateVersion(certificate.getName(), certificate.getVersion());

System.out.println(certificateWithAllProperties.getProperties().getName());
}
}
}
```

```xml

4.0.0

com.example
hello-azure
1.0-SNAPSHOT
jar


11
11




com.azure
azure-identity
1.14.0


com.azure
azure-security-keyvault-certificates
4.7.0



org.slf4j
slf4j-api
1.7.32


org.slf4j
slf4j-simple
1.7.32

```

The issue is pervasive across all the `PagedIterable` methods that follow this pattern within the KeyVault SDKs, but `listPropertiesOfCertificates` and `listDeletedCertificates` (along with maybe `listRoleDefinitions` in KeyVault Administration) seem to be the only ones that have optional parameters which are settable by the SDK methods (unlike maxResults) and hence have an actual behavioral bug here.

It's possible that some other service SDKs have similar concerns here, but newer SDKs `PagedIterable` pattern, set the optional parameters appropriately in both the first and subsequent pages:
https://github.com/Azure/azure-sdk-for-java/blob/840911147fb403b6246d866999189c3875d889c6/sdk/tables/azure-data-tables/src/main/java/com/azure/data/tables/TableClient.java#L1039-L1046

Related issues in other languages:
https://github.com/Azure/azure-sdk-for-net/issues/47202
https://github.com/Azure/azure-sdk-for-cpp/issues/6235
https://github.com/Azure/azure-sdk-for-python/issues/38589
https://github.com/Azure/azure-sdk-for-go/issues/23772
https://github.com/Azure/azure-sdk-for-js/issues/31803
https://github.com/Azure/azure-sdk-for-java/issues/42988

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.