From db3c5f839d7bbf6afe708f01fdfc200d6d74e9cf Mon Sep 17 00:00:00 2001 From: singhalrohit Date: Fri, 17 Apr 2026 12:42:11 -0700 Subject: [PATCH 1/8] Fix begin_create_certificate validator to accept san_ip_addresses and san_uris - Extended the policy validator in both the sync and async CertificateClient to also accept policies that specify only san_ip_addresses or san_uris, which are valid SAN types but were previously treated as missing subject information - Added test_create_certificate_with_san_ip_and_uris (sync + async) with live recordings to verify IP-only and URI-only SAN policies succeed end-to-end - Extended test_policy_expected_errors_for_create_cert to assert that IP-only and URI-only policies no longer raise ValueError - Fixed _test_case.py and _async_test_case.py to avoid setting AZURE_CLIENT_ID/ AZURE_CLIENT_SECRET to empty strings, which newer azure-identity treats as an attempt to use ClientSecretCredential and raises ValueError --- .../azure-keyvault-certificates/CHANGELOG.md | 9 +++ .../azure-keyvault-certificates/assets.json | 2 +- .../azure/keyvault/certificates/_client.py | 9 ++- .../keyvault/certificates/aio/_client.py | 9 ++- .../tests/_async_test_case.py | 17 +++++- .../tests/_test_case.py | 17 +++++- .../tests/test_certificates_client.py | 53 ++++++++++++++++++ .../tests/test_certificates_client_async.py | 55 +++++++++++++++++++ 8 files changed, 162 insertions(+), 9 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md b/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md index 936c7986077d..2a67cda2656c 100644 --- a/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md +++ b/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md @@ -1,5 +1,14 @@ # Release History +## 4.11.1 (Unreleased) + +### Bugs Fixed + +- Fixed `CertificateClient.begin_create_certificate` (and its async counterpart) incorrectly raising + `ValueError` when a `CertificatePolicy` was created with only `san_ip_addresses` or `san_uris` and no + `subject`, `san_dns_names`, `san_emails`, or `san_user_principal_names`. IP addresses and URIs are + valid subject alternative name types and are now recognized by the client's policy validator. + ## 4.11.0 (2026-03-27) ### Features Added diff --git a/sdk/keyvault/azure-keyvault-certificates/assets.json b/sdk/keyvault/azure-keyvault-certificates/assets.json index c49a6542155e..9c1a25dfdb79 100644 --- a/sdk/keyvault/azure-keyvault-certificates/assets.json +++ b/sdk/keyvault/azure-keyvault-certificates/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "python", "TagPrefix": "python/keyvault/azure-keyvault-certificates", - "Tag": "python/keyvault/azure-keyvault-certificates_6bfbc7f623" + "Tag": "python/keyvault/azure-keyvault-certificates_a5c5c34814" } diff --git a/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/_client.py b/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/_client.py index d0f4f65fea02..6ce432f1874d 100644 --- a/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/_client.py +++ b/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/_client.py @@ -100,7 +100,14 @@ def begin_create_certificate( :caption: Create a certificate :dedent: 8 """ - if not (policy.san_emails or policy.san_user_principal_names or policy.san_dns_names or policy.subject): + if not ( + policy.san_emails + or policy.san_user_principal_names + or policy.san_dns_names + or policy.san_ip_addresses + or policy.san_uris + or policy.subject + ): raise ValueError(NO_SAN_OR_SUBJECT) polling_interval = kwargs.pop("_polling_interval", None) diff --git a/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/aio/_client.py b/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/aio/_client.py index bd6288a39369..96efea0105c8 100644 --- a/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/aio/_client.py @@ -96,7 +96,14 @@ async def create_certificate( :caption: Create a certificate :dedent: 8 """ - if not (policy.san_emails or policy.san_user_principal_names or policy.san_dns_names or policy.subject): + if not ( + policy.san_emails + or policy.san_user_principal_names + or policy.san_dns_names + or policy.san_ip_addresses + or policy.san_uris + or policy.subject + ): raise ValueError(NO_SAN_OR_SUBJECT) polling_interval = kwargs.pop("_polling_interval", None) diff --git a/sdk/keyvault/azure-keyvault-certificates/tests/_async_test_case.py b/sdk/keyvault/azure-keyvault-certificates/tests/_async_test_case.py index 6416819682f3..488356369958 100644 --- a/sdk/keyvault/azure-keyvault-certificates/tests/_async_test_case.py +++ b/sdk/keyvault/azure-keyvault-certificates/tests/_async_test_case.py @@ -20,9 +20,20 @@ def __init__(self, **kwargs) -> None: self.is_logging_enabled = kwargs.pop("logging_enable", True) if is_live(): - os.environ["AZURE_TENANT_ID"] = os.getenv("KEYVAULT_TENANT_ID", "") # empty in pipelines - os.environ["AZURE_CLIENT_ID"] = os.getenv("KEYVAULT_CLIENT_ID", "") # empty in pipelines - os.environ["AZURE_CLIENT_SECRET"] = os.getenv("KEYVAULT_CLIENT_SECRET", "") # empty for user-based auth + # Only set AZURE_* vars if the KEYVAULT_* counterpart is non-empty. + # Setting them to empty strings causes EnvironmentCredential to attempt (and fail) + # ClientSecretCredential construction. Removing them lets DefaultAzureCredential + # fall through to AzureCliCredential for developer/interactive auth. + for keyvault_var, azure_var in ( + ("KEYVAULT_TENANT_ID", "AZURE_TENANT_ID"), + ("KEYVAULT_CLIENT_ID", "AZURE_CLIENT_ID"), + ("KEYVAULT_CLIENT_SECRET", "AZURE_CLIENT_SECRET"), + ): + value = os.getenv(keyvault_var, "") + if value: + os.environ[azure_var] = value + else: + os.environ.pop(azure_var, None) def __call__(self, fn): async def _preparer(test_class, api_version, **kwargs): diff --git a/sdk/keyvault/azure-keyvault-certificates/tests/_test_case.py b/sdk/keyvault/azure-keyvault-certificates/tests/_test_case.py index 5dcc9d819140..1f2f7f1f1a25 100644 --- a/sdk/keyvault/azure-keyvault-certificates/tests/_test_case.py +++ b/sdk/keyvault/azure-keyvault-certificates/tests/_test_case.py @@ -25,9 +25,20 @@ def __init__(self, **kwargs) -> None: if is_live(): self.azure_keyvault_url = os.environ["AZURE_KEYVAULT_URL"] - os.environ["AZURE_TENANT_ID"] = os.getenv("KEYVAULT_TENANT_ID", "") # empty in pipelines - os.environ["AZURE_CLIENT_ID"] = os.getenv("KEYVAULT_CLIENT_ID", "") # empty in pipelines - os.environ["AZURE_CLIENT_SECRET"] = os.getenv("KEYVAULT_CLIENT_SECRET", "") # empty for user-based auth + # Only set AZURE_* vars if the KEYVAULT_* counterpart is non-empty. + # Setting them to empty strings causes EnvironmentCredential to attempt (and fail) + # ClientSecretCredential construction. Removing them lets DefaultAzureCredential + # fall through to AzureCliCredential for developer/interactive auth. + for keyvault_var, azure_var in ( + ("KEYVAULT_TENANT_ID", "AZURE_TENANT_ID"), + ("KEYVAULT_CLIENT_ID", "AZURE_CLIENT_ID"), + ("KEYVAULT_CLIENT_SECRET", "AZURE_CLIENT_SECRET"), + ): + value = os.getenv(keyvault_var, "") + if value: + os.environ[azure_var] = value + else: + os.environ.pop(azure_var, None) def __call__(self, fn): def _preparer(test_class, api_version, **kwargs): diff --git a/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client.py b/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client.py index 74932f3cffa8..842c916dee49 100644 --- a/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client.py +++ b/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client.py @@ -763,6 +763,41 @@ def run(*_, **__): with pytest.raises(ResourceExistsError): client.begin_create_certificate("...", CertificatePolicy.get_default()) + @pytest.mark.parametrize("api_version", only_latest) + @CertificatesClientPreparer() + @recorded_by_proxy + def test_create_certificate_with_san_ip_and_uris(self, client, **kwargs): + """Verify certificates with only san_ip_addresses or san_uris (no subject/dns) can be created.""" + # Certificate with only IP addresses in SANs + ip_cert_name = self.get_resource_name("sanIpCert") + ip_policy = CertificatePolicy( + issuer_name=WellKnownIssuerNames.self, + san_ip_addresses=["10.0.0.1", "192.168.1.1"], + content_type=CertificateContentType.pkcs12, + ) + ip_cert = client.begin_create_certificate(certificate_name=ip_cert_name, policy=ip_policy).result() + assert ip_cert.name == ip_cert_name + returned_ip_policy = client.get_certificate_policy(ip_cert_name) + assert set(returned_ip_policy.san_ip_addresses) == {"10.0.0.1", "192.168.1.1"} + assert not returned_ip_policy.san_dns_names + assert not returned_ip_policy.san_uris + client.begin_delete_certificate(ip_cert_name).wait() + + # Certificate with only URIs in SANs + uri_cert_name = self.get_resource_name("sanUriCert") + uri_policy = CertificatePolicy( + issuer_name=WellKnownIssuerNames.self, + san_uris=["https://service.example.com/api"], + content_type=CertificateContentType.pkcs12, + ) + uri_cert = client.begin_create_certificate(certificate_name=uri_cert_name, policy=uri_policy).result() + assert uri_cert.name == uri_cert_name + returned_uri_policy = client.get_certificate_policy(uri_cert_name) + assert returned_uri_policy.san_uris + assert not returned_uri_policy.san_dns_names + assert not returned_uri_policy.san_ip_addresses + client.begin_delete_certificate(uri_cert_name).wait() + @pytest.mark.parametrize("api_version", only_latest) @CertificatesClientPreparer() @recorded_by_proxy @@ -804,6 +839,24 @@ def test_policy_expected_errors_for_create_cert(): policy = CertificatePolicy(issuer_name=WellKnownIssuerNames.self) client.begin_create_certificate("...", policy=policy) + # san_ip_addresses alone should be accepted (no ValueError) + policy = CertificatePolicy(issuer_name=WellKnownIssuerNames.self, san_ip_addresses=["10.0.0.1"]) + try: + client.begin_create_certificate("...", policy=policy) + except ValueError: + pytest.fail("begin_create_certificate should not raise ValueError for san_ip_addresses-only policy") + except Exception: + pass # Expected: network/auth error since we are using a fake client + + # san_uris alone should be accepted (no ValueError) + policy = CertificatePolicy(issuer_name=WellKnownIssuerNames.self, san_uris=["https://example.com"]) + try: + client.begin_create_certificate("...", policy=policy) + except ValueError: + pytest.fail("begin_create_certificate should not raise ValueError for san_uris-only policy") + except Exception: + pass # Expected: network/auth error since we are using a fake client + def test_service_headers_allowed_in_logs(): service_headers = {"x-ms-keyvault-network-info", "x-ms-keyvault-region", "x-ms-keyvault-service-version"} diff --git a/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client_async.py b/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client_async.py index 8b0c2955451b..d866d93f202e 100644 --- a/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client_async.py +++ b/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client_async.py @@ -787,6 +787,43 @@ async def run(*_, **__): await client.create_certificate("...", CertificatePolicy.get_default()) await client.close() + @pytest.mark.asyncio + @pytest.mark.parametrize("api_version", only_latest) + @AsyncCertificatesClientPreparer() + @recorded_by_proxy_async + async def test_create_certificate_with_san_ip_and_uris(self, client, **kwargs): + """Verify certificates with only san_ip_addresses or san_uris (no subject/dns) can be created.""" + # Certificate with only IP addresses in SANs + ip_cert_name = self.get_resource_name("sanIpCert") + ip_policy = CertificatePolicy( + issuer_name=WellKnownIssuerNames.self, + san_ip_addresses=["10.0.0.1", "192.168.1.1"], + content_type=CertificateContentType.pkcs12, + ) + ip_cert = await client.create_certificate(certificate_name=ip_cert_name, policy=ip_policy) + assert ip_cert.name == ip_cert_name + returned_ip_policy = await client.get_certificate_policy(ip_cert_name) + assert set(returned_ip_policy.san_ip_addresses) == {"10.0.0.1", "192.168.1.1"} + assert not returned_ip_policy.san_dns_names + assert not returned_ip_policy.san_uris + await client.delete_certificate(ip_cert_name) + + # Certificate with only URIs in SANs + uri_cert_name = self.get_resource_name("sanUriCert") + uri_policy = CertificatePolicy( + issuer_name=WellKnownIssuerNames.self, + san_uris=["https://service.example.com/api"], + content_type=CertificateContentType.pkcs12, + ) + uri_cert = await client.create_certificate(certificate_name=uri_cert_name, policy=uri_policy) + assert uri_cert.name == uri_cert_name + returned_uri_policy = await client.get_certificate_policy(uri_cert_name) + assert returned_uri_policy.san_uris + assert not returned_uri_policy.san_dns_names + assert not returned_uri_policy.san_ip_addresses + await client.delete_certificate(uri_cert_name) + await client.close() + @pytest.mark.asyncio @pytest.mark.parametrize("api_version", only_latest) @AsyncCertificatesClientPreparer() @@ -827,6 +864,24 @@ async def test_policy_expected_errors_for_create_cert(): policy = CertificatePolicy(issuer_name=WellKnownIssuerNames.self) await client.create_certificate("...", policy=policy) + # san_ip_addresses alone should be accepted (no ValueError) + policy = CertificatePolicy(issuer_name=WellKnownIssuerNames.self, san_ip_addresses=["10.0.0.1"]) + try: + await client.create_certificate("...", policy=policy) + except ValueError: + pytest.fail("create_certificate should not raise ValueError for san_ip_addresses-only policy") + except Exception: + pass # Expected: network/auth error since we are using a fake client + + # san_uris alone should be accepted (no ValueError) + policy = CertificatePolicy(issuer_name=WellKnownIssuerNames.self, san_uris=["https://example.com"]) + try: + await client.create_certificate("...", policy=policy) + except ValueError: + pytest.fail("create_certificate should not raise ValueError for san_uris-only policy") + except Exception: + pass # Expected: network/auth error since we are using a fake client + def test_service_headers_allowed_in_logs(): service_headers = {"x-ms-keyvault-network-info", "x-ms-keyvault-region", "x-ms-keyvault-service-version"} From f5217b6029a5a3366ee6042e7cb6c29930299e84 Mon Sep 17 00:00:00 2001 From: singhalrohit Date: Fri, 17 Apr 2026 17:29:19 -0700 Subject: [PATCH 2/8] Update 4.11.1 release date to 2026-04-20 --- sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md b/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md index 2a67cda2656c..02b06bc40f0c 100644 --- a/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md +++ b/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 4.11.1 (Unreleased) +## 4.11.1 (2026-04-20) ### Bugs Fixed From 20d57ee4c7bce5e36c76b4132c56f241d8bb4ef5 Mon Sep 17 00:00:00 2001 From: singhalrohit Date: Sat, 18 Apr 2026 17:21:51 -0700 Subject: [PATCH 3/8] Bump azure-keyvault-certificates version to 4.11.1 --- .../azure/keyvault/certificates/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/_version.py b/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/_version.py index 1166529c1953..de39d939367f 100644 --- a/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/_version.py +++ b/sdk/keyvault/azure-keyvault-certificates/azure/keyvault/certificates/_version.py @@ -3,4 +3,4 @@ # Licensed under the MIT License. # ------------------------------------ -VERSION = "4.11.0" +VERSION = "4.11.1" From 98e0dd47f9cabeb10dd698834e0b430e39c750b2 Mon Sep 17 00:00:00 2001 From: singhalrohit Date: Tue, 21 Apr 2026 12:24:26 -0700 Subject: [PATCH 4/8] Replace broad except Exception with specific exceptions in test_policy_expected_errors_for_create_cert Use except (HttpResponseError, ServiceRequestError) instead of bare except Exception to avoid silently swallowing unexpected errors (AttributeError, TypeError, etc.) that could indicate a regression in the validator or call signature. Also add HttpResponseError and ServiceRequestError to azure.core.exceptions imports. --- .../tests/test_certificates_client.py | 6 +++--- .../tests/test_certificates_client_async.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client.py b/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client.py index 842c916dee49..64328d69d73f 100644 --- a/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client.py +++ b/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client.py @@ -8,7 +8,7 @@ import time from unittest.mock import Mock, patch -from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError +from azure.core.exceptions import HttpResponseError, ResourceExistsError, ResourceNotFoundError, ServiceRequestError from azure.core.pipeline.policies import SansIOHTTPPolicy from devtools_testutils import recorded_by_proxy from azure.keyvault.certificates import ( @@ -845,7 +845,7 @@ def test_policy_expected_errors_for_create_cert(): client.begin_create_certificate("...", policy=policy) except ValueError: pytest.fail("begin_create_certificate should not raise ValueError for san_ip_addresses-only policy") - except Exception: + except (HttpResponseError, ServiceRequestError): pass # Expected: network/auth error since we are using a fake client # san_uris alone should be accepted (no ValueError) @@ -854,7 +854,7 @@ def test_policy_expected_errors_for_create_cert(): client.begin_create_certificate("...", policy=policy) except ValueError: pytest.fail("begin_create_certificate should not raise ValueError for san_uris-only policy") - except Exception: + except (HttpResponseError, ServiceRequestError): pass # Expected: network/auth error since we are using a fake client diff --git a/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client_async.py b/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client_async.py index d866d93f202e..6333bdeab1b9 100644 --- a/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client_async.py +++ b/sdk/keyvault/azure-keyvault-certificates/tests/test_certificates_client_async.py @@ -8,7 +8,7 @@ import json from unittest.mock import Mock, patch -from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError +from azure.core.exceptions import HttpResponseError, ResourceExistsError, ResourceNotFoundError, ServiceRequestError from azure.core.pipeline.policies import SansIOHTTPPolicy from devtools_testutils import set_bodiless_matcher, set_custom_default_matcher from devtools_testutils.aio import recorded_by_proxy_async @@ -870,7 +870,7 @@ async def test_policy_expected_errors_for_create_cert(): await client.create_certificate("...", policy=policy) except ValueError: pytest.fail("create_certificate should not raise ValueError for san_ip_addresses-only policy") - except Exception: + except (HttpResponseError, ServiceRequestError): pass # Expected: network/auth error since we are using a fake client # san_uris alone should be accepted (no ValueError) @@ -879,7 +879,7 @@ async def test_policy_expected_errors_for_create_cert(): await client.create_certificate("...", policy=policy) except ValueError: pytest.fail("create_certificate should not raise ValueError for san_uris-only policy") - except Exception: + except (HttpResponseError, ServiceRequestError): pass # Expected: network/auth error since we are using a fake client From bce9f82a1e82876e0809d1d0705800d928d0c0f2 Mon Sep 17 00:00:00 2001 From: Kashif Khan Date: Fri, 24 Apr 2026 15:12:54 -0500 Subject: [PATCH 5/8] fix to handle loop for python3.14 --- sdk/keyvault/azure-keyvault-certificates/tests/conftest.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sdk/keyvault/azure-keyvault-certificates/tests/conftest.py b/sdk/keyvault/azure-keyvault-certificates/tests/conftest.py index a6ffda0132a0..80d461e36526 100644 --- a/sdk/keyvault/azure-keyvault-certificates/tests/conftest.py +++ b/sdk/keyvault/azure-keyvault-certificates/tests/conftest.py @@ -89,6 +89,10 @@ def immediate_return(_): @pytest.fixture(scope="session") def event_loop(request): - loop = asyncio.get_event_loop() + try: + loop = asyncio.get_event_loop() + except RuntimeError: + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) yield loop loop.close() From c0fc08eeb5ddd6f157d9b14066c20f08108116db Mon Sep 17 00:00:00 2001 From: Kashif Khan Date: Fri, 24 Apr 2026 15:35:52 -0500 Subject: [PATCH 6/8] bump pyopenssl for pypy py313 --- sdk/keyvault/azure-keyvault-certificates/dev_requirements.txt | 2 +- sdk/keyvault/azure-keyvault-certificates/pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-certificates/dev_requirements.txt b/sdk/keyvault/azure-keyvault-certificates/dev_requirements.txt index b9e0c3fa837d..1a63359bfe1d 100644 --- a/sdk/keyvault/azure-keyvault-certificates/dev_requirements.txt +++ b/sdk/keyvault/azure-keyvault-certificates/dev_requirements.txt @@ -5,4 +5,4 @@ aiohttp>=3.0 parameterized>=0.7.3 python-dateutil>=2.8.0 -pyopenssl \ No newline at end of file +pyopenssl>=25.0.0 \ No newline at end of file diff --git a/sdk/keyvault/azure-keyvault-certificates/pyproject.toml b/sdk/keyvault/azure-keyvault-certificates/pyproject.toml index 1e1c725ee585..d382598cab41 100644 --- a/sdk/keyvault/azure-keyvault-certificates/pyproject.toml +++ b/sdk/keyvault/azure-keyvault-certificates/pyproject.toml @@ -94,7 +94,7 @@ dev = [ "azure-keyvault-nspkg", "azure-sdk-tools", "parameterized>=0.7.3", - "pyopenssl", + "pyopenssl>=25.0.0", "python-dateutil>=2.8.0", ] From 153502d0af5bc9d1b7dd5bac500faf5d0994a350 Mon Sep 17 00:00:00 2001 From: Kashif Khan Date: Fri, 24 Apr 2026 16:45:28 -0500 Subject: [PATCH 7/8] revert pyopenssl bump --- sdk/keyvault/azure-keyvault-certificates/dev_requirements.txt | 2 +- sdk/keyvault/azure-keyvault-certificates/pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-certificates/dev_requirements.txt b/sdk/keyvault/azure-keyvault-certificates/dev_requirements.txt index 1a63359bfe1d..b9e0c3fa837d 100644 --- a/sdk/keyvault/azure-keyvault-certificates/dev_requirements.txt +++ b/sdk/keyvault/azure-keyvault-certificates/dev_requirements.txt @@ -5,4 +5,4 @@ aiohttp>=3.0 parameterized>=0.7.3 python-dateutil>=2.8.0 -pyopenssl>=25.0.0 \ No newline at end of file +pyopenssl \ No newline at end of file diff --git a/sdk/keyvault/azure-keyvault-certificates/pyproject.toml b/sdk/keyvault/azure-keyvault-certificates/pyproject.toml index d382598cab41..1e1c725ee585 100644 --- a/sdk/keyvault/azure-keyvault-certificates/pyproject.toml +++ b/sdk/keyvault/azure-keyvault-certificates/pyproject.toml @@ -94,7 +94,7 @@ dev = [ "azure-keyvault-nspkg", "azure-sdk-tools", "parameterized>=0.7.3", - "pyopenssl>=25.0.0", + "pyopenssl", "python-dateutil>=2.8.0", ] From d69bc8bca7ce9db5d7881347d019353da7580b19 Mon Sep 17 00:00:00 2001 From: ROHIT SINGHAL Date: Tue, 28 Apr 2026 16:48:58 -0700 Subject: [PATCH 8/8] Update release date for version 4.11.1 --- sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md b/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md index 02b06bc40f0c..6590cf5bd99f 100644 --- a/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md +++ b/sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 4.11.1 (2026-04-20) +## 4.11.1 (2026-04-29) ### Bugs Fixed