From 3b6203e60c07bb94cccbeca76e4561657997da91 Mon Sep 17 00:00:00 2001 From: Nicola Camillucci Date: Thu, 6 Aug 2026 13:53:49 +0100 Subject: [PATCH 1/4] Autogenerated 2026-07-01-preview --- .../_metadata.json | 4 +- .../apiview-properties.json | 25 +- .../administration/_generated/_client.py | 4 +- .../_generated/_configuration.py | 7 +- .../_generated/_utils/model_base.py | 72 +- .../_generated/_utils/serialization.py | 115 +- .../administration/_generated/aio/_client.py | 4 +- .../_generated/aio/_configuration.py | 7 +- .../_generated/aio/operations/_operations.py | 904 ++++++++++++-- .../_generated/models/__init__.py | 22 + .../_generated/models/_enums.py | 60 + .../_generated/models/_models.py | 262 +++- .../_generated/operations/_operations.py | 1073 +++++++++++++++-- .../administration/_generated/types.py | 268 ++++ .../_internal/challenge_auth_policy.py | 1 - .../azure-keyvault-administration/setup.py | 1 + .../tests/test_challenge_auth.py | 8 +- .../tsp-location.yaml | 2 +- 18 files changed, 2588 insertions(+), 251 deletions(-) create mode 100644 sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/types.py diff --git a/sdk/keyvault/azure-keyvault-administration/_metadata.json b/sdk/keyvault/azure-keyvault-administration/_metadata.json index 61c17df73dc9..e800d7faf935 100644 --- a/sdk/keyvault/azure-keyvault-administration/_metadata.json +++ b/sdk/keyvault/azure-keyvault-administration/_metadata.json @@ -1,6 +1,6 @@ { - "apiVersion": "2026-01-01-preview", + "apiVersion": "2026-07-01-preview", "apiVersions": { - "KeyVault": "2026-01-01-preview" + "KeyVault": "2026-07-01-preview" } } \ No newline at end of file diff --git a/sdk/keyvault/azure-keyvault-administration/apiview-properties.json b/sdk/keyvault/azure-keyvault-administration/apiview-properties.json index eac0a6a6974a..f39881f7b3c7 100644 --- a/sdk/keyvault/azure-keyvault-administration/apiview-properties.json +++ b/sdk/keyvault/azure-keyvault-administration/apiview-properties.json @@ -2,6 +2,12 @@ "CrossLanguagePackageId": "KeyVault", "CrossLanguageDefinitionId": { "azure.keyvault.administration._generated.models.EkmConnection": "KeyVault.EkmConnection", + "azure.keyvault.administration._generated.models.EkmPrivateEndpoint": "KeyVault.EkmPrivateEndpoint", + "azure.keyvault.administration._generated.models.EkmPrivateEndpointConnectionState": "KeyVault.EkmPrivateEndpointConnectionState", + "azure.keyvault.administration._generated.models.EkmPrivateEndpointCreateParameters": "KeyVault.EkmPrivateEndpointCreateParameters", + "azure.keyvault.administration._generated.models.EkmPrivateEndpointListResult": "KeyVault.EkmPrivateEndpointListResult", + "azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation": "KeyVault.EkmPrivateEndpointOperation", + "azure.keyvault.administration._generated.models.EkmPrivateEndpointProperties": "KeyVault.EkmPrivateEndpointProperties", "azure.keyvault.administration._generated.models.EkmProxyClientCertificateInfo": "KeyVault.EkmProxyClientCertificateInfo", "azure.keyvault.administration._generated.models.EkmProxyInfo": "KeyVault.EkmProxyInfo", "azure.keyvault.administration._generated.models.FullBackupOperation": "KeyVault.FullBackupOperation", @@ -31,6 +37,11 @@ "azure.keyvault.administration._generated.models.RoleScope": "KeyVault.RoleScope", "azure.keyvault.administration._generated.models.OperationStatus": "KeyVault.OperationStatus", "azure.keyvault.administration._generated.models.SettingTypeEnum": "KeyVault.SettingTypeEnum", + "azure.keyvault.administration._generated.models.EkmConnectivityMode": "KeyVault.EkmConnectivityMode", + "azure.keyvault.administration._generated.models.EkmPrivateEndpointOperationType": "KeyVault.EkmPrivateEndpointOperationType", + "azure.keyvault.administration._generated.models.OperationState": "Azure.Core.Foundations.OperationState", + "azure.keyvault.administration._generated.models.EkmPrivateEndpointProvisioningState": "KeyVault.EkmPrivateEndpointProvisioningState", + "azure.keyvault.administration._generated.models.EkmPrivateEndpointConnectionStatus": "KeyVault.EkmPrivateEndpointConnectionStatus", "azure.keyvault.administration._generated.operations.RoleDefinitionsOperations.delete": "KeyVault.RoleDefinitions.delete", "azure.keyvault.administration._generated.aio.operations.RoleDefinitionsOperations.delete": "KeyVault.RoleDefinitions.delete", "azure.keyvault.administration._generated.operations.RoleDefinitionsOperations.create_or_update": "KeyVault.RoleDefinitions.createOrUpdate", @@ -80,7 +91,17 @@ "azure.keyvault.administration._generated.KeyVaultClient.update_ekm_connection": "KeyVault.updateEkmConnection", "azure.keyvault.administration._generated.aio.KeyVaultClient.update_ekm_connection": "KeyVault.updateEkmConnection", "azure.keyvault.administration._generated.KeyVaultClient.delete_ekm_connection": "KeyVault.deleteEkmConnection", - "azure.keyvault.administration._generated.aio.KeyVaultClient.delete_ekm_connection": "KeyVault.deleteEkmConnection" + "azure.keyvault.administration._generated.aio.KeyVaultClient.delete_ekm_connection": "KeyVault.deleteEkmConnection", + "azure.keyvault.administration._generated.KeyVaultClient.get_ekm_private_endpoint_operation_status": "KeyVault.getEkmPrivateEndpointOperationStatus", + "azure.keyvault.administration._generated.aio.KeyVaultClient.get_ekm_private_endpoint_operation_status": "KeyVault.getEkmPrivateEndpointOperationStatus", + "azure.keyvault.administration._generated.KeyVaultClient.begin_create_ekm_private_endpoint": "KeyVault.createEkmPrivateEndpoint", + "azure.keyvault.administration._generated.aio.KeyVaultClient.begin_create_ekm_private_endpoint": "KeyVault.createEkmPrivateEndpoint", + "azure.keyvault.administration._generated.KeyVaultClient.begin_delete_ekm_private_endpoint": "KeyVault.deleteEkmPrivateEndpoint", + "azure.keyvault.administration._generated.aio.KeyVaultClient.begin_delete_ekm_private_endpoint": "KeyVault.deleteEkmPrivateEndpoint", + "azure.keyvault.administration._generated.KeyVaultClient.get_ekm_private_endpoint": "KeyVault.getEkmPrivateEndpoint", + "azure.keyvault.administration._generated.aio.KeyVaultClient.get_ekm_private_endpoint": "KeyVault.getEkmPrivateEndpoint", + "azure.keyvault.administration._generated.KeyVaultClient.list_ekm_private_endpoints": "KeyVault.listEkmPrivateEndpoints", + "azure.keyvault.administration._generated.aio.KeyVaultClient.list_ekm_private_endpoints": "KeyVault.listEkmPrivateEndpoints" }, - "CrossLanguageVersion": "a3023239f547" + "CrossLanguageVersion": "7c52c44e1bdf" } \ No newline at end of file diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_client.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_client.py index 091682425b8d..a9e156e4a6b4 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_client.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_client.py @@ -27,7 +27,7 @@ from azure.core.credentials import TokenCredential -class KeyVaultClient(_KeyVaultClientOperationsMixin): +class KeyVaultClient(_KeyVaultClientOperationsMixin): # pylint: disable=docstring-keyword-should-match-keyword-only """The Azure Key Vault Administration service client performs administrative operations including RBAC, BackupRestore, and settings management against the Azure Key Vault service. @@ -43,7 +43,7 @@ class KeyVaultClient(_KeyVaultClientOperationsMixin): :param credential: Credential used to authenticate requests to the service. Required. :type credential: ~azure.core.credentials.TokenCredential :keyword api_version: The API version to use for this operation. Known values are - "2026-01-01-preview" and None. Default value is None. If not set, the operation's default API + "2026-07-01-preview" and None. Default value is None. If not set, the operation's default API version will be used. Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_configuration.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_configuration.py index b6ad2b91c255..8a2d711179f9 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_configuration.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_configuration.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding=utf-8 # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. @@ -16,7 +17,7 @@ from azure.core.credentials import TokenCredential -class KeyVaultClientConfiguration: # pylint: disable=too-many-instance-attributes +class KeyVaultClientConfiguration: # pylint: disable=too-many-instance-attributes,docstring-keyword-should-match-keyword-only """Configuration for KeyVaultClient. Note that all parameters used to create this instance are saved as instance @@ -28,14 +29,14 @@ class KeyVaultClientConfiguration: # pylint: disable=too-many-instance-attribut :param credential: Credential used to authenticate requests to the service. Required. :type credential: ~azure.core.credentials.TokenCredential :keyword api_version: The API version to use for this operation. Known values are - "2026-01-01-preview" and None. Default value is None. If not set, the operation's default API + "2026-07-01-preview" and None. Default value is None. If not set, the operation's default API version will be used. Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str """ def __init__(self, vault_base_url: str, credential: "TokenCredential", **kwargs: Any) -> None: - api_version: str = kwargs.pop("api_version", "2026-01-01-preview") + api_version: str = kwargs.pop("api_version", "2026-07-01-preview") if vault_base_url is None: raise ValueError("Parameter 'vault_base_url' must not be None.") diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_utils/model_base.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_utils/model_base.py index d725c55906d3..35d5fc024978 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_utils/model_base.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_utils/model_base.py @@ -109,6 +109,29 @@ def _serialize_bytes(o, format: typing.Optional[str] = None) -> str: return encoded +def _serialize_duration(td: timedelta, format: typing.Optional[str] = None): + """Serialize a timedelta to its wire representation. + + For the ``seconds``/``milliseconds`` encodings the value is converted to a + numeric value, otherwise it falls back to an ISO 8601 duration string. + + :param timedelta td: The timedelta to serialize. + :param str format: The duration encoding format. + :rtype: int or float or str + :return: serialized duration + """ + seconds = td.total_seconds() + if format == "duration-seconds-int": + return int(seconds) + if format == "duration-seconds-float": + return seconds + if format == "duration-milliseconds-int": + return int(seconds * 1000) + if format == "duration-milliseconds-float": + return seconds * 1000 + return _timedelta_as_isostr(td) + + def _serialize_datetime(o, format: typing.Optional[str] = None): if hasattr(o, "year") and hasattr(o, "hour"): if format == "rfc7231": @@ -135,7 +158,15 @@ def _is_readonly(p): class SdkJSONEncoder(JSONEncoder): - """A JSON encoder that's capable of serializing datetime objects and bytes.""" + """A JSON encoder that's capable of serializing datetime objects and bytes. + + :param args: Additional positional arguments passed to the base ``JSONEncoder``. + :type args: typing.Any + :keyword exclude_readonly: Whether to exclude readonly properties. Defaults to False. + :paramtype exclude_readonly: bool + :keyword format: The format to use for serialization. Defaults to None. + :paramtype format: typing.Optional[str] + """ def __init__(self, *args, exclude_readonly: bool = False, format: typing.Optional[str] = None, **kwargs): super().__init__(*args, **kwargs) @@ -301,6 +332,12 @@ def _deserialize_duration(attr): return isodate.parse_duration(attr) +def _deserialize_duration_numeric(attr, unit): + if isinstance(attr, timedelta): + return attr + return timedelta(**{unit: float(attr)}) + + def _deserialize_decimal(attr): if isinstance(attr, decimal.Decimal): return attr @@ -313,6 +350,12 @@ def _deserialize_int_as_str(attr): return int(attr) +def _deserialize_bool_as_str(attr): + if isinstance(attr, bool): + return attr + return attr.lower() == "true" + + _DESERIALIZE_MAPPING = { datetime: _deserialize_datetime, date: _deserialize_date, @@ -330,12 +373,18 @@ def _deserialize_int_as_str(attr): "unix-timestamp": _deserialize_datetime_unix_timestamp, "base64": _deserialize_bytes, "base64url": _deserialize_bytes_base64, + "duration-seconds-int": functools.partial(_deserialize_duration_numeric, unit="seconds"), + "duration-seconds-float": functools.partial(_deserialize_duration_numeric, unit="seconds"), + "duration-milliseconds-int": functools.partial(_deserialize_duration_numeric, unit="milliseconds"), + "duration-milliseconds-float": functools.partial(_deserialize_duration_numeric, unit="milliseconds"), } def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None): if annotation is int and rf and rf._format == "str": return _deserialize_int_as_str + if annotation is bool and rf and rf._format == "str": + return _deserialize_bool_as_str if annotation is str and rf and rf._format in _ARRAY_ENCODE_MAPPING: return functools.partial(_deserialize_array_encoded, _ARRAY_ENCODE_MAPPING[rf._format]) if rf and rf._format: @@ -425,21 +474,21 @@ def __ne__(self, other: typing.Any) -> bool: def keys(self) -> typing.KeysView[str]: """ - :returns: a set-like object providing a view on D's keys + :returns: a set-like object providing a view on the mapping's keys :rtype: ~typing.KeysView """ return self._data.keys() def values(self) -> typing.ValuesView[typing.Any]: """ - :returns: an object providing a view on D's values + :returns: an object providing a view on the mapping's values :rtype: ~typing.ValuesView """ return self._data.values() def items(self) -> typing.ItemsView[str, typing.Any]: """ - :returns: set-like object providing a view on D's items + :returns: a set-like object providing a view on the mapping's items :rtype: ~typing.ItemsView """ return self._data.items() @@ -449,7 +498,7 @@ def get(self, key: str, default: typing.Any = None) -> typing.Any: Get the value for key if key is in the dictionary, else default. :param str key: The key to look up. :param any default: The value to return if key is not in the dictionary. Defaults to None - :returns: D[k] if k in D, else d. + :returns: The value for key if key is in the dictionary, else default. :rtype: any """ try: @@ -484,19 +533,19 @@ def popitem(self) -> tuple[str, typing.Any]: Removes and returns some (key, value) pair :returns: The (key, value) pair. :rtype: tuple - :raises KeyError: if D is empty. + :raises KeyError: if the dictionary is empty. """ return self._data.popitem() def clear(self) -> None: """ - Remove all items from D. + Remove all items from the dictionary. """ self._data.clear() def update(self, *args: typing.Any, **kwargs: typing.Any) -> None: # pylint: disable=arguments-differ """ - Updates D from mapping/iterable E and F. + Update the dictionary from a mapping or an iterable of key-value pairs. :param any args: Either a mapping object or an iterable of key-value pairs. """ self._data.update(*args, **kwargs) @@ -509,10 +558,11 @@ def setdefault(self, key: str, default: typing.Any) -> typing.Any: ... # pylint def setdefault(self, key: str, default: typing.Any = _UNSET) -> typing.Any: """ - Same as calling D.get(k, d), and setting D[k]=d if k not found + Return the value for key if key is in the dictionary; otherwise set the key to + default and return default. :param str key: The key to look up. :param any default: The value to set if key is not in the dictionary - :returns: D[k] if k in D, else d. + :returns: The value for key if key is in the dictionary, else default. :rtype: any """ if default is _UNSET: @@ -564,7 +614,7 @@ def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-m pass # Last, try datetime.timedelta try: - return _timedelta_as_isostr(o) + return _serialize_duration(o, format) except AttributeError: # This will be raised when it hits value.total_seconds in the method above pass diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_utils/serialization.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_utils/serialization.py index a088671e9c51..ae08f9d89f74 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_utils/serialization.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/_utils/serialization.py @@ -480,7 +480,11 @@ def _decode_attribute_map_key(key): class Serializer: # pylint: disable=too-many-public-methods - """Request object model serializer.""" + """Request object model serializer. + + :param classes: Mapping of model names to model types, used to resolve models during serialization. + :type classes: typing.Optional[typing.Mapping[str, type]] + """ basic_types = {str: "str", int: "int", bool: "bool", float: "float"} @@ -520,6 +524,10 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None: "rfc-1123": Serializer.serialize_rfc, "unix-time": Serializer.serialize_unix, "duration": Serializer.serialize_duration, + "duration-seconds-int": Serializer.serialize_duration_seconds_int, + "duration-seconds-float": Serializer.serialize_duration_seconds_float, + "duration-milliseconds-int": Serializer.serialize_duration_milliseconds_int, + "duration-milliseconds-float": Serializer.serialize_duration_milliseconds_float, "date": Serializer.serialize_date, "time": Serializer.serialize_time, "decimal": Serializer.serialize_decimal, @@ -1109,6 +1117,61 @@ def serialize_duration(attr, **kwargs): # pylint: disable=unused-argument attr = isodate.parse_duration(attr) return isodate.duration_isoformat(attr) + @staticmethod + def _serialize_duration_numeric(attr, scale, as_int): + """Serialize a TimeDelta into a numeric value scaled to the wire unit. + + :param TimeDelta attr: Object to be serialized. + :param int scale: Multiplier applied to total seconds (1 for seconds, 1000 for milliseconds). + :param bool as_int: Whether to truncate the result to an int. + :rtype: int or float + :return: serialized duration + """ + if isinstance(attr, str): + attr = isodate.parse_duration(attr) + value = attr.total_seconds() * scale if isinstance(attr, datetime.timedelta) else attr + return int(value) if as_int else float(value) + + @staticmethod + def serialize_duration_seconds_int(attr, **kwargs): # pylint: disable=unused-argument + """Serialize TimeDelta object into an integer number of seconds. + + :param TimeDelta attr: Object to be serialized. + :rtype: int + :return: serialized duration + """ + return Serializer._serialize_duration_numeric(attr, 1, True) + + @staticmethod + def serialize_duration_seconds_float(attr, **kwargs): # pylint: disable=unused-argument + """Serialize TimeDelta object into a floating point number of seconds. + + :param TimeDelta attr: Object to be serialized. + :rtype: float + :return: serialized duration + """ + return Serializer._serialize_duration_numeric(attr, 1, False) + + @staticmethod + def serialize_duration_milliseconds_int(attr, **kwargs): # pylint: disable=unused-argument + """Serialize TimeDelta object into an integer number of milliseconds. + + :param TimeDelta attr: Object to be serialized. + :rtype: int + :return: serialized duration + """ + return Serializer._serialize_duration_numeric(attr, 1000, True) + + @staticmethod + def serialize_duration_milliseconds_float(attr, **kwargs): # pylint: disable=unused-argument + """Serialize TimeDelta object into a floating point number of milliseconds. + + :param TimeDelta attr: Object to be serialized. + :rtype: float + :return: serialized duration + """ + return Serializer._serialize_duration_numeric(attr, 1000, False) + @staticmethod def serialize_rfc(attr, **kwargs): # pylint: disable=unused-argument """Serialize Datetime object into RFC-1123 formatted string. @@ -1381,6 +1444,10 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None: "rfc-1123": Deserializer.deserialize_rfc, "unix-time": Deserializer.deserialize_unix, "duration": Deserializer.deserialize_duration, + "duration-seconds-int": Deserializer.deserialize_duration_seconds, + "duration-seconds-float": Deserializer.deserialize_duration_seconds, + "duration-milliseconds-int": Deserializer.deserialize_duration_milliseconds, + "duration-milliseconds-float": Deserializer.deserialize_duration_milliseconds, "date": Deserializer.deserialize_date, "time": Deserializer.deserialize_time, "decimal": Deserializer.deserialize_decimal, @@ -1393,6 +1460,10 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None: } self.deserialize_expected_types = { "duration": (isodate.Duration, datetime.timedelta), + "duration-seconds-int": (isodate.Duration, datetime.timedelta), + "duration-seconds-float": (isodate.Duration, datetime.timedelta), + "duration-milliseconds-int": (isodate.Duration, datetime.timedelta), + "duration-milliseconds-float": (isodate.Duration, datetime.timedelta), "iso-8601": (datetime.datetime), } self.dependencies: dict[str, type] = dict(classes) if classes else {} @@ -1954,6 +2025,48 @@ def deserialize_duration(attr): raise DeserializationError(msg) from err return duration + @staticmethod + def _deserialize_duration_numeric(attr, unit): + """Deserialize a numeric duration value into a TimeDelta object. + + :param float attr: response value to be deserialized. + :param str unit: The wire unit, used as the ``timedelta`` keyword + (``"seconds"`` or ``"milliseconds"``). + :return: Deserialized duration + :rtype: TimeDelta + :raises DeserializationError: if value is invalid. + """ + if isinstance(attr, ET.Element): + attr = attr.text + try: + duration = datetime.timedelta(**{unit: float(attr)}) # type: ignore + except (ValueError, OverflowError, TypeError) as err: + msg = "Cannot deserialize duration object." + raise DeserializationError(msg) from err + return duration + + @staticmethod + def deserialize_duration_seconds(attr): + """Deserialize a numeric number of seconds into a TimeDelta object. + + :param float attr: response value to be deserialized. + :return: Deserialized duration + :rtype: TimeDelta + :raises DeserializationError: if value is invalid. + """ + return Deserializer._deserialize_duration_numeric(attr, "seconds") + + @staticmethod + def deserialize_duration_milliseconds(attr): + """Deserialize a numeric number of milliseconds into a TimeDelta object. + + :param float attr: response value to be deserialized. + :return: Deserialized duration + :rtype: TimeDelta + :raises DeserializationError: if value is invalid. + """ + return Deserializer._deserialize_duration_numeric(attr, "milliseconds") + @staticmethod def deserialize_date(attr): """Deserialize ISO-8601 formatted string into Date object. diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/_client.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/_client.py index b05dae06b8a0..7099ca41c060 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/_client.py @@ -27,7 +27,7 @@ from azure.core.credentials_async import AsyncTokenCredential -class KeyVaultClient(_KeyVaultClientOperationsMixin): +class KeyVaultClient(_KeyVaultClientOperationsMixin): # pylint: disable=docstring-keyword-should-match-keyword-only """The Azure Key Vault Administration service client performs administrative operations including RBAC, BackupRestore, and settings management against the Azure Key Vault service. @@ -43,7 +43,7 @@ class KeyVaultClient(_KeyVaultClientOperationsMixin): :param credential: Credential used to authenticate requests to the service. Required. :type credential: ~azure.core.credentials_async.AsyncTokenCredential :keyword api_version: The API version to use for this operation. Known values are - "2026-01-01-preview" and None. Default value is None. If not set, the operation's default API + "2026-07-01-preview" and None. Default value is None. If not set, the operation's default API version will be used. Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/_configuration.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/_configuration.py index 021f0c487b6c..caa741d4b51d 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/_configuration.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/_configuration.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding=utf-8 # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. @@ -16,7 +17,7 @@ from azure.core.credentials_async import AsyncTokenCredential -class KeyVaultClientConfiguration: # pylint: disable=too-many-instance-attributes +class KeyVaultClientConfiguration: # pylint: disable=too-many-instance-attributes,docstring-keyword-should-match-keyword-only """Configuration for KeyVaultClient. Note that all parameters used to create this instance are saved as instance @@ -28,14 +29,14 @@ class KeyVaultClientConfiguration: # pylint: disable=too-many-instance-attribut :param credential: Credential used to authenticate requests to the service. Required. :type credential: ~azure.core.credentials_async.AsyncTokenCredential :keyword api_version: The API version to use for this operation. Known values are - "2026-01-01-preview" and None. Default value is None. If not set, the operation's default API + "2026-07-01-preview" and None. Default value is None. If not set, the operation's default API version will be used. Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str """ def __init__(self, vault_base_url: str, credential: "AsyncTokenCredential", **kwargs: Any) -> None: - api_version: str = kwargs.pop("api_version", "2026-01-01-preview") + api_version: str = kwargs.pop("api_version", "2026-07-01-preview") if vault_base_url is None: raise ValueError("Parameter 'vault_base_url' must not be None.") diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/operations/_operations.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/operations/_operations.py index 9924578f5b64..128f1ebadddb 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/operations/_operations.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/aio/operations/_operations.py @@ -32,7 +32,7 @@ from azure.core.tracing.decorator_async import distributed_trace_async from azure.core.utils import case_insensitive_dict -from ... import models as _models +from ... import models as _models, types as _types from ..._utils.model_base import SdkJSONEncoder, _deserialize, _failsafe_deserialize from ..._utils.serialization import Deserializer, Serializer from ..._utils.utils import ClientMixinABC @@ -40,14 +40,19 @@ from ...operations._operations import ( build_key_vault_check_ekm_connection_request, build_key_vault_create_ekm_connection_request, + build_key_vault_create_ekm_private_endpoint_request, build_key_vault_delete_ekm_connection_request, + build_key_vault_delete_ekm_private_endpoint_request, build_key_vault_full_backup_request, build_key_vault_full_backup_status_request, build_key_vault_full_restore_operation_request, build_key_vault_get_ekm_certificate_request, build_key_vault_get_ekm_connection_request, + build_key_vault_get_ekm_private_endpoint_operation_status_request, + build_key_vault_get_ekm_private_endpoint_request, build_key_vault_get_setting_request, build_key_vault_get_settings_request, + build_key_vault_list_ekm_private_endpoints_request, build_key_vault_pre_full_backup_request, build_key_vault_pre_full_restore_operation_request, build_key_vault_restore_status_request, @@ -66,13 +71,12 @@ ) from .._configuration import KeyVaultClientConfiguration -JSON = MutableMapping[str, Any] T = TypeVar("T") ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, dict[str, Any]], Any]] List = list -class RoleDefinitionsOperations: +class RoleDefinitionsOperations: # pylint: disable=docstring-missing-param """ .. warning:: **DO NOT** instantiate this class directly. @@ -194,7 +198,7 @@ async def create_or_update( self, scope: str, role_definition_name: str, - parameters: JSON, + parameters: _types.RoleDefinitionCreateParameters, *, content_type: str = "application/json", **kwargs: Any @@ -208,7 +212,8 @@ async def create_or_update( valid GUID. Required. :type role_definition_name: str :param parameters: Parameters for the role definition. Required. - :type parameters: JSON + :type parameters: + ~azure.keyvault.administration._generated.types.RoleDefinitionCreateParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -250,7 +255,7 @@ async def create_or_update( self, scope: str, role_definition_name: str, - parameters: Union[_models.RoleDefinitionCreateParameters, JSON, IO[bytes]], + parameters: Union[_models.RoleDefinitionCreateParameters, _types.RoleDefinitionCreateParameters, IO[bytes]], **kwargs: Any ) -> _models.RoleDefinition: """Creates or updates a custom role definition. @@ -261,11 +266,11 @@ async def create_or_update( :param role_definition_name: The name of the role definition to create or update. It can be any valid GUID. Required. :type role_definition_name: str - :param parameters: Parameters for the role definition. Is one of the following types: - RoleDefinitionCreateParameters, JSON, IO[bytes] Required. + :param parameters: Parameters for the role definition. Is either a + RoleDefinitionCreateParameters type or a IO[bytes] type. Required. :type parameters: - ~azure.keyvault.administration._generated.models.RoleDefinitionCreateParameters or JSON or - IO[bytes] + ~azure.keyvault.administration._generated.models.RoleDefinitionCreateParameters or + ~azure.keyvault.administration._generated.types.RoleDefinitionCreateParameters or IO[bytes] :return: RoleDefinition. The RoleDefinition is compatible with MutableMapping :rtype: ~azure.keyvault.administration._generated.models.RoleDefinition :raises ~azure.core.exceptions.HttpResponseError: @@ -511,7 +516,7 @@ async def get_next(next_link=None): return AsyncItemPaged(get_next, extract_data) -class RoleAssignmentsOperations: +class RoleAssignmentsOperations: # pylint: disable=docstring-missing-param """ .. warning:: **DO NOT** instantiate this class directly. @@ -631,7 +636,7 @@ async def create( self, scope: str, role_assignment_name: str, - parameters: JSON, + parameters: _types.RoleAssignmentCreateParameters, *, content_type: str = "application/json", **kwargs: Any @@ -644,7 +649,8 @@ async def create( GUID. Required. :type role_assignment_name: str :param parameters: Parameters for the role assignment. Required. - :type parameters: JSON + :type parameters: + ~azure.keyvault.administration._generated.types.RoleAssignmentCreateParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -685,7 +691,7 @@ async def create( self, scope: str, role_assignment_name: str, - parameters: Union[_models.RoleAssignmentCreateParameters, JSON, IO[bytes]], + parameters: Union[_models.RoleAssignmentCreateParameters, _types.RoleAssignmentCreateParameters, IO[bytes]], **kwargs: Any ) -> _models.RoleAssignment: """Creates a role assignment. @@ -695,11 +701,11 @@ async def create( :param role_assignment_name: The name of the role assignment to create. It can be any valid GUID. Required. :type role_assignment_name: str - :param parameters: Parameters for the role assignment. Is one of the following types: - RoleAssignmentCreateParameters, JSON, IO[bytes] Required. + :param parameters: Parameters for the role assignment. Is either a + RoleAssignmentCreateParameters type or a IO[bytes] type. Required. :type parameters: - ~azure.keyvault.administration._generated.models.RoleAssignmentCreateParameters or JSON or - IO[bytes] + ~azure.keyvault.administration._generated.models.RoleAssignmentCreateParameters or + ~azure.keyvault.administration._generated.types.RoleAssignmentCreateParameters or IO[bytes] :return: RoleAssignment. The RoleAssignment is compatible with MutableMapping :rtype: ~azure.keyvault.administration._generated.models.RoleAssignment :raises ~azure.core.exceptions.HttpResponseError: @@ -1018,7 +1024,9 @@ async def full_backup_status(self, job_id: str, **kwargs: Any) -> _models.FullBa return deserialized # type: ignore async def _full_backup_initial( - self, azure_storage_blob_container_uri: Union[_models.SASTokenParameter, JSON, IO[bytes]], **kwargs: Any + self, + azure_storage_blob_container_uri: Union[_models.SASTokenParameter, _types.SASTokenParameter, IO[bytes]], + **kwargs: Any ) -> AsyncIterator[bytes]: error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -1115,14 +1123,19 @@ async def begin_full_backup( @overload async def begin_full_backup( - self, azure_storage_blob_container_uri: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + azure_storage_blob_container_uri: _types.SASTokenParameter, + *, + content_type: str = "application/json", + **kwargs: Any ) -> AsyncLROPoller[_models.FullBackupOperation]: """Creates a full backup using a user-provided SAS token to an Azure blob storage container. :param azure_storage_blob_container_uri: Azure blob shared access signature token pointing to a valid Azure blob container where full backup needs to be stored. This token needs to be valid for at least next 24 hours from the time of making this call. Required. - :type azure_storage_blob_container_uri: JSON + :type azure_storage_blob_container_uri: + ~azure.keyvault.administration._generated.types.SASTokenParameter :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -1155,16 +1168,19 @@ async def begin_full_backup( @distributed_trace_async async def begin_full_backup( - self, azure_storage_blob_container_uri: Union[_models.SASTokenParameter, JSON, IO[bytes]], **kwargs: Any + self, + azure_storage_blob_container_uri: Union[_models.SASTokenParameter, _types.SASTokenParameter, IO[bytes]], + **kwargs: Any ) -> AsyncLROPoller[_models.FullBackupOperation]: """Creates a full backup using a user-provided SAS token to an Azure blob storage container. :param azure_storage_blob_container_uri: Azure blob shared access signature token pointing to a valid Azure blob container where full backup needs to be stored. This token needs to be valid - for at least next 24 hours from the time of making this call. Is one of the following types: - SASTokenParameter, JSON, IO[bytes] Required. + for at least next 24 hours from the time of making this call. Is either a SASTokenParameter + type or a IO[bytes] type. Required. :type azure_storage_blob_container_uri: - ~azure.keyvault.administration._generated.models.SASTokenParameter or JSON or IO[bytes] + ~azure.keyvault.administration._generated.models.SASTokenParameter or + ~azure.keyvault.administration._generated.types.SASTokenParameter or IO[bytes] :return: An instance of AsyncLROPoller that returns FullBackupOperation. The FullBackupOperation is compatible with MutableMapping :rtype: @@ -1233,11 +1249,22 @@ def get_long_running_output(pipeline_response): @api_version_validation( method_added_on="7.6-preview.2", params_added_on={"7.6-preview.2": ["api_version", "content_type", "accept"]}, - api_versions_list=["7.6-preview.2", "7.6", "2025-06-01-preview", "2025-07-01", "2026-01-01-preview"], + api_versions_list=[ + "7.6-preview.2", + "7.6", + "2025-06-01-preview", + "2025-07-01", + "2026-01-01-preview", + "2026-03-01-preview", + "2026-05-01-preview", + "2026-07-01-preview", + ], ) async def _pre_full_backup_initial( self, - pre_backup_operation_parameters: Union[_models.PreBackupOperationParameters, JSON, IO[bytes]], + pre_backup_operation_parameters: Union[ + _models.PreBackupOperationParameters, _types.PreBackupOperationParameters, IO[bytes] + ], **kwargs: Any ) -> AsyncIterator[bytes]: error_map: MutableMapping = { @@ -1334,13 +1361,18 @@ async def begin_pre_full_backup( @overload async def begin_pre_full_backup( - self, pre_backup_operation_parameters: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + pre_backup_operation_parameters: _types.PreBackupOperationParameters, + *, + content_type: str = "application/json", + **kwargs: Any ) -> AsyncLROPoller[_models.FullBackupOperation]: """Pre-backup operation for checking whether the customer can perform a full backup operation. :param pre_backup_operation_parameters: Optional parameters to validate prior to performing a full backup operation. Required. - :type pre_backup_operation_parameters: JSON + :type pre_backup_operation_parameters: + ~azure.keyvault.administration._generated.types.PreBackupOperationParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -1374,21 +1406,32 @@ async def begin_pre_full_backup( @api_version_validation( method_added_on="7.6-preview.2", params_added_on={"7.6-preview.2": ["api_version", "content_type", "accept"]}, - api_versions_list=["7.6-preview.2", "7.6", "2025-06-01-preview", "2025-07-01", "2026-01-01-preview"], + api_versions_list=[ + "7.6-preview.2", + "7.6", + "2025-06-01-preview", + "2025-07-01", + "2026-01-01-preview", + "2026-03-01-preview", + "2026-05-01-preview", + "2026-07-01-preview", + ], ) async def begin_pre_full_backup( self, - pre_backup_operation_parameters: Union[_models.PreBackupOperationParameters, JSON, IO[bytes]], + pre_backup_operation_parameters: Union[ + _models.PreBackupOperationParameters, _types.PreBackupOperationParameters, IO[bytes] + ], **kwargs: Any ) -> AsyncLROPoller[_models.FullBackupOperation]: """Pre-backup operation for checking whether the customer can perform a full backup operation. :param pre_backup_operation_parameters: Optional parameters to validate prior to performing a - full backup operation. Is one of the following types: PreBackupOperationParameters, JSON, - IO[bytes] Required. + full backup operation. Is either a PreBackupOperationParameters type or a IO[bytes] type. + Required. :type pre_backup_operation_parameters: - ~azure.keyvault.administration._generated.models.PreBackupOperationParameters or JSON or - IO[bytes] + ~azure.keyvault.administration._generated.models.PreBackupOperationParameters or + ~azure.keyvault.administration._generated.types.PreBackupOperationParameters or IO[bytes] :return: An instance of AsyncLROPoller that returns FullBackupOperation. The FullBackupOperation is compatible with MutableMapping :rtype: @@ -1522,7 +1565,9 @@ async def restore_status(self, job_id: str, **kwargs: Any) -> _models.RestoreOpe return deserialized # type: ignore async def _full_restore_operation_initial( - self, restore_blob_details: Union[_models.RestoreOperationParameters, JSON, IO[bytes]], **kwargs: Any + self, + restore_blob_details: Union[_models.RestoreOperationParameters, _types.RestoreOperationParameters, IO[bytes]], + **kwargs: Any ) -> AsyncIterator[bytes]: error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -1619,14 +1664,19 @@ async def begin_full_restore_operation( @overload async def begin_full_restore_operation( - self, restore_blob_details: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + restore_blob_details: _types.RestoreOperationParameters, + *, + content_type: str = "application/json", + **kwargs: Any ) -> AsyncLROPoller[_models.RestoreOperation]: """Restores all key materials using the SAS token pointing to a previously stored Azure Blob storage backup folder. :param restore_blob_details: The Azure blob SAS token pointing to a folder where the previous successful full backup was stored. Required. - :type restore_blob_details: JSON + :type restore_blob_details: + ~azure.keyvault.administration._generated.types.RestoreOperationParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -1659,17 +1709,19 @@ async def begin_full_restore_operation( @distributed_trace_async async def begin_full_restore_operation( - self, restore_blob_details: Union[_models.RestoreOperationParameters, JSON, IO[bytes]], **kwargs: Any + self, + restore_blob_details: Union[_models.RestoreOperationParameters, _types.RestoreOperationParameters, IO[bytes]], + **kwargs: Any ) -> AsyncLROPoller[_models.RestoreOperation]: """Restores all key materials using the SAS token pointing to a previously stored Azure Blob storage backup folder. :param restore_blob_details: The Azure blob SAS token pointing to a folder where the previous - successful full backup was stored. Is one of the following types: RestoreOperationParameters, - JSON, IO[bytes] Required. + successful full backup was stored. Is either a RestoreOperationParameters type or a IO[bytes] + type. Required. :type restore_blob_details: - ~azure.keyvault.administration._generated.models.RestoreOperationParameters or JSON or - IO[bytes] + ~azure.keyvault.administration._generated.models.RestoreOperationParameters or + ~azure.keyvault.administration._generated.types.RestoreOperationParameters or IO[bytes] :return: An instance of AsyncLROPoller that returns RestoreOperation. The RestoreOperation is compatible with MutableMapping :rtype: @@ -1738,11 +1790,22 @@ def get_long_running_output(pipeline_response): @api_version_validation( method_added_on="7.6-preview.2", params_added_on={"7.6-preview.2": ["api_version", "content_type", "accept"]}, - api_versions_list=["7.6-preview.2", "7.6", "2025-06-01-preview", "2025-07-01", "2026-01-01-preview"], + api_versions_list=[ + "7.6-preview.2", + "7.6", + "2025-06-01-preview", + "2025-07-01", + "2026-01-01-preview", + "2026-03-01-preview", + "2026-05-01-preview", + "2026-07-01-preview", + ], ) async def _pre_full_restore_operation_initial( self, - pre_restore_operation_parameters: Union[_models.PreRestoreOperationParameters, JSON, IO[bytes]], + pre_restore_operation_parameters: Union[ + _models.PreRestoreOperationParameters, _types.PreRestoreOperationParameters, IO[bytes] + ], **kwargs: Any ) -> AsyncIterator[bytes]: error_map: MutableMapping = { @@ -1839,13 +1902,18 @@ async def begin_pre_full_restore_operation( @overload async def begin_pre_full_restore_operation( - self, pre_restore_operation_parameters: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + pre_restore_operation_parameters: _types.PreRestoreOperationParameters, + *, + content_type: str = "application/json", + **kwargs: Any ) -> AsyncLROPoller[_models.RestoreOperation]: """Pre-restore operation for checking whether the customer can perform a full restore operation. :param pre_restore_operation_parameters: Optional pre restore parameters to validate prior to performing a full restore operation. Required. - :type pre_restore_operation_parameters: JSON + :type pre_restore_operation_parameters: + ~azure.keyvault.administration._generated.types.PreRestoreOperationParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -1879,21 +1947,32 @@ async def begin_pre_full_restore_operation( @api_version_validation( method_added_on="7.6-preview.2", params_added_on={"7.6-preview.2": ["api_version", "content_type", "accept"]}, - api_versions_list=["7.6-preview.2", "7.6", "2025-06-01-preview", "2025-07-01", "2026-01-01-preview"], + api_versions_list=[ + "7.6-preview.2", + "7.6", + "2025-06-01-preview", + "2025-07-01", + "2026-01-01-preview", + "2026-03-01-preview", + "2026-05-01-preview", + "2026-07-01-preview", + ], ) async def begin_pre_full_restore_operation( self, - pre_restore_operation_parameters: Union[_models.PreRestoreOperationParameters, JSON, IO[bytes]], + pre_restore_operation_parameters: Union[ + _models.PreRestoreOperationParameters, _types.PreRestoreOperationParameters, IO[bytes] + ], **kwargs: Any ) -> AsyncLROPoller[_models.RestoreOperation]: """Pre-restore operation for checking whether the customer can perform a full restore operation. :param pre_restore_operation_parameters: Optional pre restore parameters to validate prior to - performing a full restore operation. Is one of the following types: - PreRestoreOperationParameters, JSON, IO[bytes] Required. + performing a full restore operation. Is either a PreRestoreOperationParameters type or a + IO[bytes] type. Required. :type pre_restore_operation_parameters: - ~azure.keyvault.administration._generated.models.PreRestoreOperationParameters or JSON or - IO[bytes] + ~azure.keyvault.administration._generated.models.PreRestoreOperationParameters or + ~azure.keyvault.administration._generated.types.PreRestoreOperationParameters or IO[bytes] :return: An instance of AsyncLROPoller that returns RestoreOperation. The RestoreOperation is compatible with MutableMapping :rtype: @@ -2030,7 +2109,9 @@ async def selective_key_restore_status(self, job_id: str, **kwargs: Any) -> _mod async def _selective_key_restore_operation_initial( self, key_name: str, - restore_blob_details: Union[_models.SelectiveKeyRestoreOperationParameters, JSON, IO[bytes]], + restore_blob_details: Union[ + _models.SelectiveKeyRestoreOperationParameters, _types.SelectiveKeyRestoreOperationParameters, IO[bytes] + ], **kwargs: Any ) -> AsyncIterator[bytes]: error_map: MutableMapping = { @@ -2132,7 +2213,12 @@ async def begin_selective_key_restore_operation( @overload async def begin_selective_key_restore_operation( - self, key_name: str, restore_blob_details: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + key_name: str, + restore_blob_details: _types.SelectiveKeyRestoreOperationParameters, + *, + content_type: str = "application/json", + **kwargs: Any ) -> AsyncLROPoller[_models.SelectiveKeyRestoreOperation]: """Restores all key versions of a given key using user supplied SAS token pointing to a previously stored Azure Blob storage backup folder. @@ -2141,7 +2227,8 @@ async def begin_selective_key_restore_operation( :type key_name: str :param restore_blob_details: The Azure blob SAS token pointing to a folder where the previous successful full backup was stored. Required. - :type restore_blob_details: JSON + :type restore_blob_details: + ~azure.keyvault.administration._generated.types.SelectiveKeyRestoreOperationParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -2178,7 +2265,9 @@ async def begin_selective_key_restore_operation( async def begin_selective_key_restore_operation( self, key_name: str, - restore_blob_details: Union[_models.SelectiveKeyRestoreOperationParameters, JSON, IO[bytes]], + restore_blob_details: Union[ + _models.SelectiveKeyRestoreOperationParameters, _types.SelectiveKeyRestoreOperationParameters, IO[bytes] + ], **kwargs: Any ) -> AsyncLROPoller[_models.SelectiveKeyRestoreOperation]: """Restores all key versions of a given key using user supplied SAS token pointing to a previously @@ -2187,11 +2276,12 @@ async def begin_selective_key_restore_operation( :param key_name: The name of the key to be restored from the user supplied backup. Required. :type key_name: str :param restore_blob_details: The Azure blob SAS token pointing to a folder where the previous - successful full backup was stored. Is one of the following types: - SelectiveKeyRestoreOperationParameters, JSON, IO[bytes] Required. + successful full backup was stored. Is either a SelectiveKeyRestoreOperationParameters type or a + IO[bytes] type. Required. :type restore_blob_details: - ~azure.keyvault.administration._generated.models.SelectiveKeyRestoreOperationParameters or JSON - or IO[bytes] + ~azure.keyvault.administration._generated.models.SelectiveKeyRestoreOperationParameters or + ~azure.keyvault.administration._generated.types.SelectiveKeyRestoreOperationParameters or + IO[bytes] :return: An instance of AsyncLROPoller that returns SelectiveKeyRestoreOperation. The SelectiveKeyRestoreOperation is compatible with MutableMapping :rtype: @@ -2287,7 +2377,12 @@ async def update_setting( @overload async def update_setting( - self, setting_name: str, parameters: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + setting_name: str, + parameters: _types.UpdateSettingRequest, + *, + content_type: str = "application/json", + **kwargs: Any ) -> _models.Setting: """Updates key vault account setting, stores it, then returns the setting name and value to the client. @@ -2298,7 +2393,7 @@ async def update_setting( Required. :type setting_name: str :param parameters: The parameters to update an account setting. Required. - :type parameters: JSON + :type parameters: ~azure.keyvault.administration._generated.types.UpdateSettingRequest :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -2331,7 +2426,10 @@ async def update_setting( @distributed_trace_async async def update_setting( - self, setting_name: str, parameters: Union[_models.UpdateSettingRequest, JSON, IO[bytes]], **kwargs: Any + self, + setting_name: str, + parameters: Union[_models.UpdateSettingRequest, _types.UpdateSettingRequest, IO[bytes]], + **kwargs: Any ) -> _models.Setting: """Updates key vault account setting, stores it, then returns the setting name and value to the client. @@ -2341,10 +2439,10 @@ async def update_setting( :param setting_name: The name of the account setting. Must be a valid settings option. Required. :type setting_name: str - :param parameters: The parameters to update an account setting. Is one of the following types: - UpdateSettingRequest, JSON, IO[bytes] Required. - :type parameters: ~azure.keyvault.administration._generated.models.UpdateSettingRequest or JSON - or IO[bytes] + :param parameters: The parameters to update an account setting. Is either a + UpdateSettingRequest type or a IO[bytes] type. Required. + :type parameters: ~azure.keyvault.administration._generated.models.UpdateSettingRequest or + ~azure.keyvault.administration._generated.types.UpdateSettingRequest or IO[bytes] :return: Setting. The Setting is compatible with MutableMapping :rtype: ~azure.keyvault.administration._generated.models.Setting :raises ~azure.core.exceptions.HttpResponseError: @@ -2556,7 +2654,7 @@ async def get_settings(self, **kwargs: Any) -> _models.SettingsListResult: @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) async def get_ekm_connection(self, **kwargs: Any) -> _models.EkmConnection: """Gets the EKM connection. @@ -2628,7 +2726,7 @@ async def get_ekm_connection(self, **kwargs: Any) -> _models.EkmConnection: @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) async def get_ekm_certificate(self, **kwargs: Any) -> _models.EkmProxyClientCertificateInfo: """Gets the EKM proxy client certificate. @@ -2701,7 +2799,7 @@ async def get_ekm_certificate(self, **kwargs: Any) -> _models.EkmProxyClientCert @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) async def check_ekm_connection(self, **kwargs: Any) -> _models.EkmProxyInfo: """Checks the connectivity and authentication with the EKM proxy. @@ -2790,7 +2888,7 @@ async def create_ekm_connection( @overload async def create_ekm_connection( - self, ekm_connection: JSON, *, content_type: str = "application/json", **kwargs: Any + self, ekm_connection: _types.EkmConnection, *, content_type: str = "application/json", **kwargs: Any ) -> _models.EkmConnection: """Creates the EKM connection. @@ -2798,7 +2896,7 @@ async def create_ekm_connection( exists, this operation fails. This operation requires ekm/write permission. :param ekm_connection: The ekmConnection to create. Required. - :type ekm_connection: JSON + :type ekm_connection: ~azure.keyvault.administration._generated.types.EkmConnection :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -2830,20 +2928,20 @@ async def create_ekm_connection( @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "content_type", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) async def create_ekm_connection( - self, ekm_connection: Union[_models.EkmConnection, JSON, IO[bytes]], **kwargs: Any + self, ekm_connection: Union[_models.EkmConnection, _types.EkmConnection, IO[bytes]], **kwargs: Any ) -> _models.EkmConnection: """Creates the EKM connection. The External Key Manager (EKM) sets up the EKM connection. If the EKM connection already exists, this operation fails. This operation requires ekm/write permission. - :param ekm_connection: The ekmConnection to create. Is one of the following types: - EkmConnection, JSON, IO[bytes] Required. - :type ekm_connection: ~azure.keyvault.administration._generated.models.EkmConnection or JSON or - IO[bytes] + :param ekm_connection: The ekmConnection to create. Is either a EkmConnection type or a + IO[bytes] type. Required. + :type ekm_connection: ~azure.keyvault.administration._generated.models.EkmConnection or + ~azure.keyvault.administration._generated.types.EkmConnection or IO[bytes] :return: EkmConnection. The EkmConnection is compatible with MutableMapping :rtype: ~azure.keyvault.administration._generated.models.EkmConnection :raises ~azure.core.exceptions.HttpResponseError: @@ -2935,7 +3033,7 @@ async def update_ekm_connection( @overload async def update_ekm_connection( - self, ekm_connection: JSON, *, content_type: str = "application/json", **kwargs: Any + self, ekm_connection: _types.EkmConnection, *, content_type: str = "application/json", **kwargs: Any ) -> _models.EkmConnection: """Updates the EKM connection. @@ -2943,7 +3041,7 @@ async def update_ekm_connection( not exist, this operation fails. This operation requires ekm/write permission. :param ekm_connection: The ekmConnection to update. Required. - :type ekm_connection: JSON + :type ekm_connection: ~azure.keyvault.administration._generated.types.EkmConnection :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -2975,20 +3073,20 @@ async def update_ekm_connection( @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "content_type", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) async def update_ekm_connection( - self, ekm_connection: Union[_models.EkmConnection, JSON, IO[bytes]], **kwargs: Any + self, ekm_connection: Union[_models.EkmConnection, _types.EkmConnection, IO[bytes]], **kwargs: Any ) -> _models.EkmConnection: """Updates the EKM connection. The External Key Manager (EKM) updates the existing EKM connection. If the EKM connection does not exist, this operation fails. This operation requires ekm/write permission. - :param ekm_connection: The ekmConnection to update. Is one of the following types: - EkmConnection, JSON, IO[bytes] Required. - :type ekm_connection: ~azure.keyvault.administration._generated.models.EkmConnection or JSON or - IO[bytes] + :param ekm_connection: The ekmConnection to update. Is either a EkmConnection type or a + IO[bytes] type. Required. + :type ekm_connection: ~azure.keyvault.administration._generated.models.EkmConnection or + ~azure.keyvault.administration._generated.types.EkmConnection or IO[bytes] :return: EkmConnection. The EkmConnection is compatible with MutableMapping :rtype: ~azure.keyvault.administration._generated.models.EkmConnection :raises ~azure.core.exceptions.HttpResponseError: @@ -3063,7 +3161,7 @@ async def update_ekm_connection( @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) async def delete_ekm_connection(self, **kwargs: Any) -> _models.EkmConnection: """Deletes the EKM connection. @@ -3130,3 +3228,633 @@ async def delete_ekm_connection(self, **kwargs: Any) -> _models.EkmConnection: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore + + @distributed_trace_async + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "operation_id", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + async def get_ekm_private_endpoint_operation_status( # pylint: disable=name-too-long + self, operation_id: str, **kwargs: Any + ) -> _models.EkmPrivateEndpointOperation: + """Gets the status of an EKM proxy private endpoint operation. + + The External Key Manager (EKM) private endpoint operation status. Returns the status of a + private endpoint create or delete operation. This operation requires ekm/read permission. + + :param operation_id: The identifier of the private endpoint operation. Required. + :type operation_id: str + :return: EkmPrivateEndpointOperation. The EkmPrivateEndpointOperation is compatible with + MutableMapping + :rtype: ~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.EkmPrivateEndpointOperation] = kwargs.pop("cls", None) + + _request = build_key_vault_get_ekm_private_endpoint_operation_status_request( + operation_id=operation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.KeyVaultError, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.EkmPrivateEndpointOperation, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "pe_name", "content_type", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + async def _create_ekm_private_endpoint_initial( + self, + pe_name: str, + parameters: Union[ + _models.EkmPrivateEndpointCreateParameters, _types.EkmPrivateEndpointCreateParameters, IO[bytes] + ], + **kwargs: Any + ) -> AsyncIterator[bytes]: + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(parameters, (IOBase, bytes)): + _content = parameters + else: + _content = json.dumps(parameters, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_key_vault_create_ekm_private_endpoint_request( + pe_name=pe_name, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = True + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [202]: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.KeyVaultError, + response, + ) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers["Azure-AsyncOperation"] = self._deserialize( + "str", response.headers.get("Azure-AsyncOperation") + ) + response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @overload + async def begin_create_ekm_private_endpoint( + self, + pe_name: str, + parameters: _models.EkmPrivateEndpointCreateParameters, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> AsyncLROPoller[_models.EkmPrivateEndpointOperation]: + """Creates an EKM proxy private endpoint. + + The External Key Manager (EKM) creates a private endpoint to the EKM proxy Private Link + Service. A pool may have up to two private endpoints. This operation requires ekm/write + permission. + + :param pe_name: The name of the private endpoint. Must be 1-24 characters, start and end with + an alphanumeric character, and contain only alphanumeric characters and hyphens. Required. + :type pe_name: str + :param parameters: The parameters to create the private endpoint. Required. + :type parameters: + ~azure.keyvault.administration._generated.models.EkmPrivateEndpointCreateParameters + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: An instance of AsyncLROPoller that returns EkmPrivateEndpointOperation. The + EkmPrivateEndpointOperation is compatible with MutableMapping + :rtype: + ~azure.core.polling.AsyncLROPoller[~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def begin_create_ekm_private_endpoint( + self, + pe_name: str, + parameters: _types.EkmPrivateEndpointCreateParameters, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> AsyncLROPoller[_models.EkmPrivateEndpointOperation]: + """Creates an EKM proxy private endpoint. + + The External Key Manager (EKM) creates a private endpoint to the EKM proxy Private Link + Service. A pool may have up to two private endpoints. This operation requires ekm/write + permission. + + :param pe_name: The name of the private endpoint. Must be 1-24 characters, start and end with + an alphanumeric character, and contain only alphanumeric characters and hyphens. Required. + :type pe_name: str + :param parameters: The parameters to create the private endpoint. Required. + :type parameters: + ~azure.keyvault.administration._generated.types.EkmPrivateEndpointCreateParameters + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: An instance of AsyncLROPoller that returns EkmPrivateEndpointOperation. The + EkmPrivateEndpointOperation is compatible with MutableMapping + :rtype: + ~azure.core.polling.AsyncLROPoller[~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def begin_create_ekm_private_endpoint( + self, pe_name: str, parameters: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> AsyncLROPoller[_models.EkmPrivateEndpointOperation]: + """Creates an EKM proxy private endpoint. + + The External Key Manager (EKM) creates a private endpoint to the EKM proxy Private Link + Service. A pool may have up to two private endpoints. This operation requires ekm/write + permission. + + :param pe_name: The name of the private endpoint. Must be 1-24 characters, start and end with + an alphanumeric character, and contain only alphanumeric characters and hyphens. Required. + :type pe_name: str + :param parameters: The parameters to create the private endpoint. Required. + :type parameters: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: An instance of AsyncLROPoller that returns EkmPrivateEndpointOperation. The + EkmPrivateEndpointOperation is compatible with MutableMapping + :rtype: + ~azure.core.polling.AsyncLROPoller[~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "pe_name", "content_type", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + async def begin_create_ekm_private_endpoint( + self, + pe_name: str, + parameters: Union[ + _models.EkmPrivateEndpointCreateParameters, _types.EkmPrivateEndpointCreateParameters, IO[bytes] + ], + **kwargs: Any + ) -> AsyncLROPoller[_models.EkmPrivateEndpointOperation]: + """Creates an EKM proxy private endpoint. + + The External Key Manager (EKM) creates a private endpoint to the EKM proxy Private Link + Service. A pool may have up to two private endpoints. This operation requires ekm/write + permission. + + :param pe_name: The name of the private endpoint. Must be 1-24 characters, start and end with + an alphanumeric character, and contain only alphanumeric characters and hyphens. Required. + :type pe_name: str + :param parameters: The parameters to create the private endpoint. Is either a + EkmPrivateEndpointCreateParameters type or a IO[bytes] type. Required. + :type parameters: + ~azure.keyvault.administration._generated.models.EkmPrivateEndpointCreateParameters or + ~azure.keyvault.administration._generated.types.EkmPrivateEndpointCreateParameters or IO[bytes] + :return: An instance of AsyncLROPoller that returns EkmPrivateEndpointOperation. The + EkmPrivateEndpointOperation is compatible with MutableMapping + :rtype: + ~azure.core.polling.AsyncLROPoller[~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.EkmPrivateEndpointOperation] = kwargs.pop("cls", None) + polling: Union[bool, AsyncPollingMethod] = kwargs.pop("polling", True) + lro_delay = kwargs.pop("polling_interval", self._config.polling_interval) + cont_token: Optional[str] = kwargs.pop("continuation_token", None) + if cont_token is None: + raw_result = await self._create_ekm_private_endpoint_initial( + pe_name=pe_name, + parameters=parameters, + content_type=content_type, + cls=lambda x, y, z: x, + headers=_headers, + params=_params, + **kwargs + ) + await raw_result.http_response.read() # type: ignore + kwargs.pop("error_map", None) + + def get_long_running_output(pipeline_response): + response_headers = {} + response = pipeline_response.http_response + response_headers["Azure-AsyncOperation"] = self._deserialize( + "str", response.headers.get("Azure-AsyncOperation") + ) + response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + + deserialized = _deserialize(_models.EkmPrivateEndpointOperation, response.json()) + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + return deserialized + + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + + if polling is True: + polling_method: AsyncPollingMethod = cast( + AsyncPollingMethod, + AsyncLROBasePolling(lro_delay, path_format_arguments=path_format_arguments, **kwargs), + ) + elif polling is False: + polling_method = cast(AsyncPollingMethod, AsyncNoPolling()) + else: + polling_method = polling + if cont_token: + return AsyncLROPoller[_models.EkmPrivateEndpointOperation].from_continuation_token( + polling_method=polling_method, + continuation_token=cont_token, + client=self._client, + deserialization_callback=get_long_running_output, + ) + return AsyncLROPoller[_models.EkmPrivateEndpointOperation]( + self._client, raw_result, get_long_running_output, polling_method # type: ignore + ) + + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "pe_name", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + async def _delete_ekm_private_endpoint_initial(self, pe_name: str, **kwargs: Any) -> AsyncIterator[bytes]: + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) + + _request = build_key_vault_delete_ekm_private_endpoint_request( + pe_name=pe_name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = True + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [202]: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.KeyVaultError, + response, + ) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers["Azure-AsyncOperation"] = self._deserialize( + "str", response.headers.get("Azure-AsyncOperation") + ) + response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace_async + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "pe_name", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + async def begin_delete_ekm_private_endpoint( + self, pe_name: str, **kwargs: Any + ) -> AsyncLROPoller[_models.EkmPrivateEndpointOperation]: + """Deletes an EKM proxy private endpoint. + + The External Key Manager (EKM) deletes an existing EKM proxy private endpoint. The operation is + rejected while an EKM connection still references the private endpoint. This operation requires + ekm/write permission. + + :param pe_name: The name of the private endpoint to delete. Required. + :type pe_name: str + :return: An instance of AsyncLROPoller that returns EkmPrivateEndpointOperation. The + EkmPrivateEndpointOperation is compatible with MutableMapping + :rtype: + ~azure.core.polling.AsyncLROPoller[~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.EkmPrivateEndpointOperation] = kwargs.pop("cls", None) + polling: Union[bool, AsyncPollingMethod] = kwargs.pop("polling", True) + lro_delay = kwargs.pop("polling_interval", self._config.polling_interval) + cont_token: Optional[str] = kwargs.pop("continuation_token", None) + if cont_token is None: + raw_result = await self._delete_ekm_private_endpoint_initial( + pe_name=pe_name, cls=lambda x, y, z: x, headers=_headers, params=_params, **kwargs + ) + await raw_result.http_response.read() # type: ignore + kwargs.pop("error_map", None) + + def get_long_running_output(pipeline_response): + response_headers = {} + response = pipeline_response.http_response + response_headers["Azure-AsyncOperation"] = self._deserialize( + "str", response.headers.get("Azure-AsyncOperation") + ) + response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + + deserialized = _deserialize(_models.EkmPrivateEndpointOperation, response.json()) + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + return deserialized + + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + + if polling is True: + polling_method: AsyncPollingMethod = cast( + AsyncPollingMethod, + AsyncLROBasePolling(lro_delay, path_format_arguments=path_format_arguments, **kwargs), + ) + elif polling is False: + polling_method = cast(AsyncPollingMethod, AsyncNoPolling()) + else: + polling_method = polling + if cont_token: + return AsyncLROPoller[_models.EkmPrivateEndpointOperation].from_continuation_token( + polling_method=polling_method, + continuation_token=cont_token, + client=self._client, + deserialization_callback=get_long_running_output, + ) + return AsyncLROPoller[_models.EkmPrivateEndpointOperation]( + self._client, raw_result, get_long_running_output, polling_method # type: ignore + ) + + @distributed_trace_async + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "pe_name", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + async def get_ekm_private_endpoint(self, pe_name: str, **kwargs: Any) -> _models.EkmPrivateEndpoint: + """Gets an EKM proxy private endpoint. + + The External Key Manager (EKM) gets an existing EKM proxy private endpoint. This operation + requires ekm/read permission. + + :param pe_name: The name of the private endpoint to get. Required. + :type pe_name: str + :return: EkmPrivateEndpoint. The EkmPrivateEndpoint is compatible with MutableMapping + :rtype: ~azure.keyvault.administration._generated.models.EkmPrivateEndpoint + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.EkmPrivateEndpoint] = kwargs.pop("cls", None) + + _request = build_key_vault_get_ekm_private_endpoint_request( + pe_name=pe_name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.KeyVaultError, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.EkmPrivateEndpoint, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @distributed_trace_async + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + async def list_ekm_private_endpoints(self, **kwargs: Any) -> _models.EkmPrivateEndpointListResult: + """Lists the EKM proxy private endpoints. + + The External Key Manager (EKM) lists all EKM proxy private endpoints on the pool. This + operation requires ekm/read permission. + + :return: EkmPrivateEndpointListResult. The EkmPrivateEndpointListResult is compatible with + MutableMapping + :rtype: ~azure.keyvault.administration._generated.models.EkmPrivateEndpointListResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.EkmPrivateEndpointListResult] = kwargs.pop("cls", None) + + _request = build_key_vault_list_ekm_private_endpoints_request( + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.KeyVaultError, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.EkmPrivateEndpointListResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/__init__.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/__init__.py index e514fe596eb4..d13377ea01ae 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/__init__.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/__init__.py @@ -15,6 +15,12 @@ from ._models import ( # type: ignore EkmConnection, + EkmPrivateEndpoint, + EkmPrivateEndpointConnectionState, + EkmPrivateEndpointCreateParameters, + EkmPrivateEndpointListResult, + EkmPrivateEndpointOperation, + EkmPrivateEndpointProperties, EkmProxyClientCertificateInfo, EkmProxyInfo, FullBackupOperation, @@ -42,6 +48,11 @@ from ._enums import ( # type: ignore DataAction, + EkmConnectivityMode, + EkmPrivateEndpointConnectionStatus, + EkmPrivateEndpointOperationType, + EkmPrivateEndpointProvisioningState, + OperationState, OperationStatus, RoleDefinitionType, RoleScope, @@ -54,6 +65,12 @@ __all__ = [ "EkmConnection", + "EkmPrivateEndpoint", + "EkmPrivateEndpointConnectionState", + "EkmPrivateEndpointCreateParameters", + "EkmPrivateEndpointListResult", + "EkmPrivateEndpointOperation", + "EkmPrivateEndpointProperties", "EkmProxyClientCertificateInfo", "EkmProxyInfo", "FullBackupOperation", @@ -78,6 +95,11 @@ "SettingsListResult", "UpdateSettingRequest", "DataAction", + "EkmConnectivityMode", + "EkmPrivateEndpointConnectionStatus", + "EkmPrivateEndpointOperationType", + "EkmPrivateEndpointProvisioningState", + "OperationState", "OperationStatus", "RoleDefinitionType", "RoleScope", diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/_enums.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/_enums.py index 5057cd87aa3a..e9ea7adb3d6b 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/_enums.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/_enums.py @@ -83,6 +83,66 @@ class DataAction(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Generate random numbers.""" +class EkmConnectivityMode(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """The connectivity mode used to reach the EKM proxy.""" + + PUBLIC = "Public" + """The EKM proxy is reachable over the public internet; host is a DNS name or IP address.""" + PRIVATE_ENDPOINT = "PrivateEndpoint" + """The EKM proxy is reachable through a private endpoint; host is the name of a private endpoint + (peName).""" + + +class EkmPrivateEndpointConnectionStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """The status of the connection between the private endpoint and the Private Link Service.""" + + PENDING = "Pending" + """The connection is awaiting approval by the Private Link Service owner.""" + APPROVED = "Approved" + """The connection has been approved by the Private Link Service owner.""" + REJECTED = "Rejected" + """The connection has been rejected by the Private Link Service owner.""" + DISCONNECTED = "Disconnected" + """The connection has been disconnected by the Private Link Service owner.""" + + +class EkmPrivateEndpointOperationType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """The type of a long-running EKM proxy private endpoint operation.""" + + CREATE = "Create" + """A private endpoint create operation.""" + DELETE = "Delete" + """A private endpoint delete operation.""" + + +class EkmPrivateEndpointProvisioningState(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """The provisioning state of the EKM proxy private endpoint.""" + + SUCCEEDED = "Succeeded" + """The private endpoint has been successfully provisioned.""" + FAILED = "Failed" + """The private endpoint provisioning failed.""" + UPDATING = "Updating" + """The private endpoint is being updated.""" + DELETING = "Deleting" + """The private endpoint is being deleted.""" + + +class OperationState(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """Enum describing allowed operation states.""" + + NOT_STARTED = "NotStarted" + """The operation has not started.""" + RUNNING = "Running" + """The operation is in progress.""" + SUCCEEDED = "Succeeded" + """The operation has completed successfully.""" + FAILED = "Failed" + """The operation has failed.""" + CANCELED = "Canceled" + """The operation has been canceled by the user.""" + + class OperationStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The status of a long-running operation.""" diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/_models.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/_models.py index 1ee73a8048d5..3e7a63b68f00 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/_models.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/models/_models.py @@ -17,7 +17,7 @@ from .. import models as _models -class EkmConnection(_Model): +class EkmConnection(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """A EkmConnection model object. :ivar host: EKM proxy FQDN (Fully Qualified Domain Name). Only allowed characters are a-z, A-Z, @@ -32,6 +32,11 @@ class EkmConnection(_Model): :ivar server_subject_common_name: The subject common name of the server certificate of EKM Proxy. :vartype server_subject_common_name: str + :ivar connectivity_mode: The connectivity mode used to reach the EKM proxy. Defaults to + "Public". In "PrivateEndpoint" mode, the host field holds the name of a private endpoint + (peName) instead of a DNS name or IP address. Known values are: "Public" and "PrivateEndpoint". + :vartype connectivity_mode: str or + ~azure.keyvault.administration._generated.models.EkmConnectivityMode """ host: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) @@ -46,6 +51,12 @@ class EkmConnection(_Model): certificates in the certificate chain, each in DER format and base64 encoded. Required.""" server_subject_common_name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The subject common name of the server certificate of EKM Proxy.""" + connectivity_mode: Optional[Union[str, "_models.EkmConnectivityMode"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """The connectivity mode used to reach the EKM proxy. Defaults to \"Public\". In + \"PrivateEndpoint\" mode, the host field holds the name of a private endpoint (peName) instead + of a DNS name or IP address. Known values are: \"Public\" and \"PrivateEndpoint\".""" @overload def __init__( @@ -55,6 +66,198 @@ def __init__( server_ca_certificates: list[bytes], path_prefix: Optional[str] = None, server_subject_common_name: Optional[str] = None, + connectivity_mode: Optional[Union[str, "_models.EkmConnectivityMode"]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class EkmPrivateEndpoint(_Model): + """An EKM proxy private endpoint. + + :ivar name: The name of the private endpoint (peName). + :vartype name: str + :ivar location: The Azure region where the private endpoint is provisioned. + :vartype location: str + :ivar provisioning_state: The provisioning state of the private endpoint. Known values are: + "Succeeded", "Failed", "Updating", and "Deleting". + :vartype provisioning_state: str or + ~azure.keyvault.administration._generated.models.EkmPrivateEndpointProvisioningState + :ivar properties: The properties of the private endpoint. + :vartype properties: + ~azure.keyvault.administration._generated.models.EkmPrivateEndpointProperties + :ivar private_link_service_connection_state: The state of the connection between the private + endpoint and the Private Link Service. + :vartype private_link_service_connection_state: + ~azure.keyvault.administration._generated.models.EkmPrivateEndpointConnectionState + """ + + name: Optional[str] = rest_field(visibility=["read"]) + """The name of the private endpoint (peName).""" + location: Optional[str] = rest_field(visibility=["read"]) + """The Azure region where the private endpoint is provisioned.""" + provisioning_state: Optional[Union[str, "_models.EkmPrivateEndpointProvisioningState"]] = rest_field( + name="provisioningState", visibility=["read"] + ) + """The provisioning state of the private endpoint. Known values are: \"Succeeded\", \"Failed\", + \"Updating\", and \"Deleting\".""" + properties: Optional["_models.EkmPrivateEndpointProperties"] = rest_field(visibility=["read"]) + """The properties of the private endpoint.""" + private_link_service_connection_state: Optional["_models.EkmPrivateEndpointConnectionState"] = rest_field( + name="privateLinkServiceConnectionState", visibility=["read"] + ) + """The state of the connection between the private endpoint and the Private Link Service.""" + + +class EkmPrivateEndpointConnectionState(_Model): + """The state of the connection between the private endpoint and the Private Link Service. + + :ivar status: The status of the private link service connection. Known values are: "Pending", + "Approved", "Rejected", and "Disconnected". + :vartype status: str or + ~azure.keyvault.administration._generated.models.EkmPrivateEndpointConnectionStatus + :ivar description: A description of the current connection state. + :vartype description: str + :ivar actions_required: Any actions required from the customer to maintain the connection. + :vartype actions_required: str + """ + + status: Optional[Union[str, "_models.EkmPrivateEndpointConnectionStatus"]] = rest_field(visibility=["read"]) + """The status of the private link service connection. Known values are: \"Pending\", \"Approved\", + \"Rejected\", and \"Disconnected\".""" + description: Optional[str] = rest_field(visibility=["read"]) + """A description of the current connection state.""" + actions_required: Optional[str] = rest_field(name="actionsRequired", visibility=["read"]) + """Any actions required from the customer to maintain the connection.""" + + +class EkmPrivateEndpointCreateParameters(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only + """Parameters to create an EKM proxy private endpoint. + + :ivar private_link_service_id: Alias of the Private Link Service that the private endpoint + connects to. Required. + :vartype private_link_service_id: str + :ivar request_message: An optional message shown to the Private Link Service owner when + approving the private endpoint connection. + :vartype request_message: str + """ + + private_link_service_id: str = rest_field( + name="privateLinkServiceId", visibility=["read", "create", "update", "delete", "query"] + ) + """Alias of the Private Link Service that the private endpoint connects to. Required.""" + request_message: Optional[str] = rest_field( + name="requestMessage", visibility=["read", "create", "update", "delete", "query"] + ) + """An optional message shown to the Private Link Service owner when approving the private endpoint + connection.""" + + @overload + def __init__( + self, + *, + private_link_service_id: str, + request_message: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class EkmPrivateEndpointListResult(_Model): + """The result of a request to list EKM proxy private endpoints. + + :ivar value: The list of EKM proxy private endpoints. + :vartype value: list[~azure.keyvault.administration._generated.models.EkmPrivateEndpoint] + """ + + value: Optional[list["_models.EkmPrivateEndpoint"]] = rest_field(visibility=["read"]) + """The list of EKM proxy private endpoints.""" + + +class EkmPrivateEndpointOperation(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only + """A long-running operation on an EKM proxy private endpoint. + + :ivar job_id: Identifier for the private endpoint operation. + :vartype job_id: str + :ivar private_endpoint_name: The name of the private endpoint (peName) the operation applies + to. + :vartype private_endpoint_name: str + :ivar operation_type: The type of the operation. Known values are: "Create" and "Delete". + :vartype operation_type: str or + ~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperationType + :ivar status: The status of the operation. Known values are: "NotStarted", "Running", + "Succeeded", "Failed", and "Canceled". + :vartype status: str or ~azure.keyvault.administration._generated.models.OperationState + :ivar status_details: The status details of the operation. + :vartype status_details: str + :ivar start_time: The start time of the operation in UTC. + :vartype start_time: ~datetime.datetime + :ivar end_time: The end time of the operation in UTC. + :vartype end_time: ~datetime.datetime + :ivar error: Error encountered, if any, during the operation. + :vartype error: ~azure.keyvault.administration._generated.models.FullBackupOperationError + """ + + job_id: Optional[str] = rest_field(name="jobId", visibility=["read", "create", "update", "delete", "query"]) + """Identifier for the private endpoint operation.""" + private_endpoint_name: Optional[str] = rest_field( + name="privateEndpointName", visibility=["read", "create", "update", "delete", "query"] + ) + """The name of the private endpoint (peName) the operation applies to.""" + operation_type: Optional[Union[str, "_models.EkmPrivateEndpointOperationType"]] = rest_field( + name="operationType", visibility=["read", "create", "update", "delete", "query"] + ) + """The type of the operation. Known values are: \"Create\" and \"Delete\".""" + status: Optional[Union[str, "_models.OperationState"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """The status of the operation. Known values are: \"NotStarted\", \"Running\", \"Succeeded\", + \"Failed\", and \"Canceled\".""" + status_details: Optional[str] = rest_field( + name="statusDetails", visibility=["read", "create", "update", "delete", "query"] + ) + """The status details of the operation.""" + start_time: Optional[datetime.datetime] = rest_field( + name="startTime", visibility=["read", "create", "update", "delete", "query"], format="unix-timestamp" + ) + """The start time of the operation in UTC.""" + end_time: Optional[datetime.datetime] = rest_field( + name="endTime", visibility=["read", "create", "update", "delete", "query"], format="unix-timestamp" + ) + """The end time of the operation in UTC.""" + error: Optional["_models.FullBackupOperationError"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Error encountered, if any, during the operation.""" + + @overload + def __init__( + self, + *, + job_id: Optional[str] = None, + private_endpoint_name: Optional[str] = None, + operation_type: Optional[Union[str, "_models.EkmPrivateEndpointOperationType"]] = None, + status: Optional[Union[str, "_models.OperationState"]] = None, + status_details: Optional[str] = None, + start_time: Optional[datetime.datetime] = None, + end_time: Optional[datetime.datetime] = None, + error: Optional["_models.FullBackupOperationError"] = None, ) -> None: ... @overload @@ -68,6 +271,25 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) +class EkmPrivateEndpointProperties(_Model): + """The properties of an EKM proxy private endpoint. + + :ivar private_link_service_id: Alias of the Private Link Service that the private endpoint + connects to. + :vartype private_link_service_id: str + :ivar private_link_service_connection_name: The name of the private link service connection, + generated by the service. + :vartype private_link_service_connection_name: str + """ + + private_link_service_id: Optional[str] = rest_field(name="privateLinkServiceId", visibility=["read"]) + """Alias of the Private Link Service that the private endpoint connects to.""" + private_link_service_connection_name: Optional[str] = rest_field( + name="privateLinkServiceConnectionName", visibility=["read"] + ) + """The name of the private link service connection, generated by the service.""" + + class EkmProxyClientCertificateInfo(_Model): """EKM proxy client certificate information. @@ -88,7 +310,7 @@ class EkmProxyClientCertificateInfo(_Model): Required.""" -class EkmProxyInfo(_Model): +class EkmProxyInfo(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """EKM proxy information. :ivar api_version: The highest version of proxy interface API supported by the EKM Proxy. @@ -137,7 +359,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class FullBackupOperation(_Model): +class FullBackupOperation(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Full backup operation. :ivar status: Status of the backup operation. Known values are: "InProgress", "Succeeded", @@ -240,7 +462,7 @@ class KeyVaultError(_Model): """The key vault server error.""" -class Permission(_Model): +class Permission(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Role definition permissions. :ivar actions: Action permissions that are granted. @@ -294,7 +516,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class PreBackupOperationParameters(_Model): +class PreBackupOperationParameters(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """The authentication method and location for the backup operation. :ivar storage_resource_uri: Azure Blob storage container Uri. @@ -340,7 +562,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class PreRestoreOperationParameters(_Model): +class PreRestoreOperationParameters(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """The authentication method and location for the restore operation. :ivar sas_token_parameters: A user-provided SAS token to an Azure blob storage container. @@ -379,7 +601,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class RestoreOperation(_Model): +class RestoreOperation(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Restore operation. :ivar status: Status of the restore operation. Known values are: "InProgress", "Succeeded", @@ -444,7 +666,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class RestoreOperationParameters(_Model): +class RestoreOperationParameters(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """The authentication method and location for the restore operation. :ivar sas_token_parameters: A user-provided SAS token to an Azure blob storage container. @@ -484,7 +706,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class RoleAssignment(_Model): +class RoleAssignment(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Role Assignments. :ivar id: The role assignment ID. @@ -527,7 +749,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class RoleAssignmentCreateParameters(_Model): +class RoleAssignmentCreateParameters(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Role assignment create parameters. :ivar properties: Role assignment properties. Required. @@ -557,7 +779,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class RoleAssignmentProperties(_Model): +class RoleAssignmentProperties(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Role assignment properties. :ivar role_definition_id: The role definition ID used in the role assignment. Required. @@ -594,7 +816,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class RoleAssignmentPropertiesWithScope(_Model): +class RoleAssignmentPropertiesWithScope(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Role assignment properties with scope. :ivar scope: The role scope. Known values are: "/" and "/keys". @@ -638,7 +860,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class RoleDefinition(_Model): +class RoleDefinition(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Role definition. :ivar id: The role definition ID. @@ -700,7 +922,7 @@ def __setattr__(self, key: str, value: Any) -> None: super().__setattr__(key, value) -class RoleDefinitionCreateParameters(_Model): +class RoleDefinitionCreateParameters(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Role definition create parameters. :ivar properties: Role definition properties. Required. @@ -730,7 +952,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class RoleDefinitionProperties(_Model): +class RoleDefinitionProperties(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Role definition properties. :ivar role_name: The role name. @@ -785,7 +1007,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class SASTokenParameter(_Model): +class SASTokenParameter(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """An authentication method and location for the operation. :ivar storage_resource_uri: Azure Blob storage container Uri. Required. @@ -831,7 +1053,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class SelectiveKeyRestoreOperation(_Model): +class SelectiveKeyRestoreOperation(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """Selective Key Restore operation. :ivar status: Status of the restore operation. Known values are: "InProgress", "Succeeded", @@ -896,7 +1118,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class SelectiveKeyRestoreOperationParameters(_Model): +class SelectiveKeyRestoreOperationParameters(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """The authentication method and location for the selective key restore operation. :ivar sas_token_parameters: A user-provided SAS token to an Azure blob storage container. @@ -934,7 +1156,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class Setting(_Model): +class Setting(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """A Key Vault account setting. :ivar name: The account setting to be updated. Required. @@ -986,7 +1208,7 @@ class SettingsListResult(_Model): """A response message containing a list of account settings with their associated value.""" -class UpdateSettingRequest(_Model): +class UpdateSettingRequest(_Model): # pylint: disable=docstring-keyword-should-match-keyword-only """The update settings request object. :ivar value: The value of the pool setting. Required. diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/operations/_operations.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/operations/_operations.py index 8b1dac9f3ee7..735c09a58522 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/operations/_operations.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/operations/_operations.py @@ -31,14 +31,13 @@ from azure.core.tracing.decorator import distributed_trace from azure.core.utils import case_insensitive_dict -from .. import models as _models +from .. import models as _models, types as _types from .._configuration import KeyVaultClientConfiguration from .._utils.model_base import SdkJSONEncoder, _deserialize, _failsafe_deserialize from .._utils.serialization import Deserializer, Serializer from .._utils.utils import ClientMixinABC from .._validation import api_version_validation -JSON = MutableMapping[str, Any] T = TypeVar("T") ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, dict[str, Any]], Any]] List = list @@ -51,7 +50,7 @@ def build_role_definitions_delete_request(scope: str, role_definition_name: str, _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -79,7 +78,7 @@ def build_role_definitions_create_or_update_request( # pylint: disable=name-too _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -106,7 +105,7 @@ def build_role_definitions_get_request(scope: str, role_definition_name: str, ** _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -131,7 +130,7 @@ def build_role_definitions_list_request(scope: str, *, filter: Optional[str] = N _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -157,7 +156,7 @@ def build_role_assignments_delete_request(scope: str, role_assignment_name: str, _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -183,7 +182,7 @@ def build_role_assignments_create_request(scope: str, role_assignment_name: str, _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -210,7 +209,7 @@ def build_role_assignments_get_request(scope: str, role_assignment_name: str, ** _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -237,7 +236,7 @@ def build_role_assignments_list_for_scope_request( # pylint: disable=name-too-l _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -265,7 +264,7 @@ def build_key_vault_full_backup_status_request( # pylint: disable=name-too-long _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -290,7 +289,7 @@ def build_key_vault_full_backup_request(**kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -312,7 +311,7 @@ def build_key_vault_pre_full_backup_request(**kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -333,7 +332,7 @@ def build_key_vault_restore_status_request(job_id: str, **kwargs: Any) -> HttpRe _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -358,7 +357,7 @@ def build_key_vault_full_restore_operation_request(**kwargs: Any) -> HttpRequest _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -380,7 +379,7 @@ def build_key_vault_pre_full_restore_operation_request(**kwargs: Any) -> HttpReq _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -403,7 +402,7 @@ def build_key_vault_selective_key_restore_status_request( # pylint: disable=nam _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -430,7 +429,7 @@ def build_key_vault_selective_key_restore_operation_request( # pylint: disable= _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -457,7 +456,7 @@ def build_key_vault_update_setting_request(setting_name: str, **kwargs: Any) -> _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -483,7 +482,7 @@ def build_key_vault_get_setting_request(setting_name: str, **kwargs: Any) -> Htt _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -507,7 +506,7 @@ def build_key_vault_get_settings_request(**kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -526,7 +525,7 @@ def build_key_vault_get_ekm_connection_request(**kwargs: Any) -> HttpRequest: # _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -545,7 +544,7 @@ def build_key_vault_get_ekm_certificate_request(**kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -564,7 +563,7 @@ def build_key_vault_check_ekm_connection_request(**kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -584,7 +583,7 @@ def build_key_vault_create_ekm_connection_request(**kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -606,7 +605,7 @@ def build_key_vault_update_ekm_connection_request(**kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -627,7 +626,7 @@ def build_key_vault_delete_ekm_connection_request(**kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-01-01-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -642,7 +641,133 @@ def build_key_vault_delete_ekm_connection_request(**kwargs: Any) -> HttpRequest: return HttpRequest(method="DELETE", url=_url, params=_params, headers=_headers, **kwargs) -class RoleDefinitionsOperations: +def build_key_vault_get_ekm_private_endpoint_operation_status_request( # pylint: disable=name-too-long + operation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/ekm/privateendpoint/operations/{operationId}" + path_format_arguments = { + "operationId": _SERIALIZER.url("operation_id", operation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_key_vault_create_ekm_private_endpoint_request( # pylint: disable=name-too-long + pe_name: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/ekm/privateendpoint/{peName}" + path_format_arguments = { + "peName": _SERIALIZER.url("pe_name", pe_name, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_key_vault_delete_ekm_private_endpoint_request( # pylint: disable=name-too-long + pe_name: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/ekm/privateendpoint/{peName}" + path_format_arguments = { + "peName": _SERIALIZER.url("pe_name", pe_name, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="DELETE", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_key_vault_get_ekm_private_endpoint_request( # pylint: disable=name-too-long + pe_name: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/ekm/privateendpoint/{peName}" + path_format_arguments = { + "peName": _SERIALIZER.url("pe_name", pe_name, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_key_vault_list_ekm_private_endpoints_request(**kwargs: Any) -> HttpRequest: # pylint: disable=name-too-long + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2026-07-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/ekm/privateendpoint" + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +class RoleDefinitionsOperations: # pylint: disable=docstring-missing-param """ .. warning:: **DO NOT** instantiate this class directly. @@ -764,7 +889,7 @@ def create_or_update( self, scope: str, role_definition_name: str, - parameters: JSON, + parameters: _types.RoleDefinitionCreateParameters, *, content_type: str = "application/json", **kwargs: Any @@ -778,7 +903,8 @@ def create_or_update( valid GUID. Required. :type role_definition_name: str :param parameters: Parameters for the role definition. Required. - :type parameters: JSON + :type parameters: + ~azure.keyvault.administration._generated.types.RoleDefinitionCreateParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -820,7 +946,7 @@ def create_or_update( self, scope: str, role_definition_name: str, - parameters: Union[_models.RoleDefinitionCreateParameters, JSON, IO[bytes]], + parameters: Union[_models.RoleDefinitionCreateParameters, _types.RoleDefinitionCreateParameters, IO[bytes]], **kwargs: Any ) -> _models.RoleDefinition: """Creates or updates a custom role definition. @@ -831,11 +957,11 @@ def create_or_update( :param role_definition_name: The name of the role definition to create or update. It can be any valid GUID. Required. :type role_definition_name: str - :param parameters: Parameters for the role definition. Is one of the following types: - RoleDefinitionCreateParameters, JSON, IO[bytes] Required. + :param parameters: Parameters for the role definition. Is either a + RoleDefinitionCreateParameters type or a IO[bytes] type. Required. :type parameters: - ~azure.keyvault.administration._generated.models.RoleDefinitionCreateParameters or JSON or - IO[bytes] + ~azure.keyvault.administration._generated.models.RoleDefinitionCreateParameters or + ~azure.keyvault.administration._generated.types.RoleDefinitionCreateParameters or IO[bytes] :return: RoleDefinition. The RoleDefinition is compatible with MutableMapping :rtype: ~azure.keyvault.administration._generated.models.RoleDefinition :raises ~azure.core.exceptions.HttpResponseError: @@ -1079,7 +1205,7 @@ def get_next(next_link=None): return ItemPaged(get_next, extract_data) -class RoleAssignmentsOperations: +class RoleAssignmentsOperations: # pylint: disable=docstring-missing-param """ .. warning:: **DO NOT** instantiate this class directly. @@ -1199,7 +1325,7 @@ def create( self, scope: str, role_assignment_name: str, - parameters: JSON, + parameters: _types.RoleAssignmentCreateParameters, *, content_type: str = "application/json", **kwargs: Any @@ -1212,7 +1338,8 @@ def create( GUID. Required. :type role_assignment_name: str :param parameters: Parameters for the role assignment. Required. - :type parameters: JSON + :type parameters: + ~azure.keyvault.administration._generated.types.RoleAssignmentCreateParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -1253,7 +1380,7 @@ def create( self, scope: str, role_assignment_name: str, - parameters: Union[_models.RoleAssignmentCreateParameters, JSON, IO[bytes]], + parameters: Union[_models.RoleAssignmentCreateParameters, _types.RoleAssignmentCreateParameters, IO[bytes]], **kwargs: Any ) -> _models.RoleAssignment: """Creates a role assignment. @@ -1263,11 +1390,11 @@ def create( :param role_assignment_name: The name of the role assignment to create. It can be any valid GUID. Required. :type role_assignment_name: str - :param parameters: Parameters for the role assignment. Is one of the following types: - RoleAssignmentCreateParameters, JSON, IO[bytes] Required. + :param parameters: Parameters for the role assignment. Is either a + RoleAssignmentCreateParameters type or a IO[bytes] type. Required. :type parameters: - ~azure.keyvault.administration._generated.models.RoleAssignmentCreateParameters or JSON or - IO[bytes] + ~azure.keyvault.administration._generated.models.RoleAssignmentCreateParameters or + ~azure.keyvault.administration._generated.types.RoleAssignmentCreateParameters or IO[bytes] :return: RoleAssignment. The RoleAssignment is compatible with MutableMapping :rtype: ~azure.keyvault.administration._generated.models.RoleAssignment :raises ~azure.core.exceptions.HttpResponseError: @@ -1586,7 +1713,9 @@ def full_backup_status(self, job_id: str, **kwargs: Any) -> _models.FullBackupOp return deserialized # type: ignore def _full_backup_initial( - self, azure_storage_blob_container_uri: Union[_models.SASTokenParameter, JSON, IO[bytes]], **kwargs: Any + self, + azure_storage_blob_container_uri: Union[_models.SASTokenParameter, _types.SASTokenParameter, IO[bytes]], + **kwargs: Any ) -> Iterator[bytes]: error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -1683,14 +1812,19 @@ def begin_full_backup( @overload def begin_full_backup( - self, azure_storage_blob_container_uri: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + azure_storage_blob_container_uri: _types.SASTokenParameter, + *, + content_type: str = "application/json", + **kwargs: Any ) -> LROPoller[_models.FullBackupOperation]: """Creates a full backup using a user-provided SAS token to an Azure blob storage container. :param azure_storage_blob_container_uri: Azure blob shared access signature token pointing to a valid Azure blob container where full backup needs to be stored. This token needs to be valid for at least next 24 hours from the time of making this call. Required. - :type azure_storage_blob_container_uri: JSON + :type azure_storage_blob_container_uri: + ~azure.keyvault.administration._generated.types.SASTokenParameter :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -1723,16 +1857,19 @@ def begin_full_backup( @distributed_trace def begin_full_backup( - self, azure_storage_blob_container_uri: Union[_models.SASTokenParameter, JSON, IO[bytes]], **kwargs: Any + self, + azure_storage_blob_container_uri: Union[_models.SASTokenParameter, _types.SASTokenParameter, IO[bytes]], + **kwargs: Any ) -> LROPoller[_models.FullBackupOperation]: """Creates a full backup using a user-provided SAS token to an Azure blob storage container. :param azure_storage_blob_container_uri: Azure blob shared access signature token pointing to a valid Azure blob container where full backup needs to be stored. This token needs to be valid - for at least next 24 hours from the time of making this call. Is one of the following types: - SASTokenParameter, JSON, IO[bytes] Required. + for at least next 24 hours from the time of making this call. Is either a SASTokenParameter + type or a IO[bytes] type. Required. :type azure_storage_blob_container_uri: - ~azure.keyvault.administration._generated.models.SASTokenParameter or JSON or IO[bytes] + ~azure.keyvault.administration._generated.models.SASTokenParameter or + ~azure.keyvault.administration._generated.types.SASTokenParameter or IO[bytes] :return: An instance of LROPoller that returns FullBackupOperation. The FullBackupOperation is compatible with MutableMapping :rtype: @@ -1800,11 +1937,22 @@ def get_long_running_output(pipeline_response): @api_version_validation( method_added_on="7.6-preview.2", params_added_on={"7.6-preview.2": ["api_version", "content_type", "accept"]}, - api_versions_list=["7.6-preview.2", "7.6", "2025-06-01-preview", "2025-07-01", "2026-01-01-preview"], + api_versions_list=[ + "7.6-preview.2", + "7.6", + "2025-06-01-preview", + "2025-07-01", + "2026-01-01-preview", + "2026-03-01-preview", + "2026-05-01-preview", + "2026-07-01-preview", + ], ) def _pre_full_backup_initial( self, - pre_backup_operation_parameters: Union[_models.PreBackupOperationParameters, JSON, IO[bytes]], + pre_backup_operation_parameters: Union[ + _models.PreBackupOperationParameters, _types.PreBackupOperationParameters, IO[bytes] + ], **kwargs: Any ) -> Iterator[bytes]: error_map: MutableMapping = { @@ -1901,13 +2049,18 @@ def begin_pre_full_backup( @overload def begin_pre_full_backup( - self, pre_backup_operation_parameters: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + pre_backup_operation_parameters: _types.PreBackupOperationParameters, + *, + content_type: str = "application/json", + **kwargs: Any ) -> LROPoller[_models.FullBackupOperation]: """Pre-backup operation for checking whether the customer can perform a full backup operation. :param pre_backup_operation_parameters: Optional parameters to validate prior to performing a full backup operation. Required. - :type pre_backup_operation_parameters: JSON + :type pre_backup_operation_parameters: + ~azure.keyvault.administration._generated.types.PreBackupOperationParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -1941,21 +2094,32 @@ def begin_pre_full_backup( @api_version_validation( method_added_on="7.6-preview.2", params_added_on={"7.6-preview.2": ["api_version", "content_type", "accept"]}, - api_versions_list=["7.6-preview.2", "7.6", "2025-06-01-preview", "2025-07-01", "2026-01-01-preview"], + api_versions_list=[ + "7.6-preview.2", + "7.6", + "2025-06-01-preview", + "2025-07-01", + "2026-01-01-preview", + "2026-03-01-preview", + "2026-05-01-preview", + "2026-07-01-preview", + ], ) def begin_pre_full_backup( self, - pre_backup_operation_parameters: Union[_models.PreBackupOperationParameters, JSON, IO[bytes]], + pre_backup_operation_parameters: Union[ + _models.PreBackupOperationParameters, _types.PreBackupOperationParameters, IO[bytes] + ], **kwargs: Any ) -> LROPoller[_models.FullBackupOperation]: """Pre-backup operation for checking whether the customer can perform a full backup operation. :param pre_backup_operation_parameters: Optional parameters to validate prior to performing a - full backup operation. Is one of the following types: PreBackupOperationParameters, JSON, - IO[bytes] Required. + full backup operation. Is either a PreBackupOperationParameters type or a IO[bytes] type. + Required. :type pre_backup_operation_parameters: - ~azure.keyvault.administration._generated.models.PreBackupOperationParameters or JSON or - IO[bytes] + ~azure.keyvault.administration._generated.models.PreBackupOperationParameters or + ~azure.keyvault.administration._generated.types.PreBackupOperationParameters or IO[bytes] :return: An instance of LROPoller that returns FullBackupOperation. The FullBackupOperation is compatible with MutableMapping :rtype: @@ -2088,7 +2252,9 @@ def restore_status(self, job_id: str, **kwargs: Any) -> _models.RestoreOperation return deserialized # type: ignore def _full_restore_operation_initial( - self, restore_blob_details: Union[_models.RestoreOperationParameters, JSON, IO[bytes]], **kwargs: Any + self, + restore_blob_details: Union[_models.RestoreOperationParameters, _types.RestoreOperationParameters, IO[bytes]], + **kwargs: Any ) -> Iterator[bytes]: error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -2185,14 +2351,19 @@ def begin_full_restore_operation( @overload def begin_full_restore_operation( - self, restore_blob_details: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + restore_blob_details: _types.RestoreOperationParameters, + *, + content_type: str = "application/json", + **kwargs: Any ) -> LROPoller[_models.RestoreOperation]: """Restores all key materials using the SAS token pointing to a previously stored Azure Blob storage backup folder. :param restore_blob_details: The Azure blob SAS token pointing to a folder where the previous successful full backup was stored. Required. - :type restore_blob_details: JSON + :type restore_blob_details: + ~azure.keyvault.administration._generated.types.RestoreOperationParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -2225,17 +2396,19 @@ def begin_full_restore_operation( @distributed_trace def begin_full_restore_operation( - self, restore_blob_details: Union[_models.RestoreOperationParameters, JSON, IO[bytes]], **kwargs: Any + self, + restore_blob_details: Union[_models.RestoreOperationParameters, _types.RestoreOperationParameters, IO[bytes]], + **kwargs: Any ) -> LROPoller[_models.RestoreOperation]: """Restores all key materials using the SAS token pointing to a previously stored Azure Blob storage backup folder. :param restore_blob_details: The Azure blob SAS token pointing to a folder where the previous - successful full backup was stored. Is one of the following types: RestoreOperationParameters, - JSON, IO[bytes] Required. + successful full backup was stored. Is either a RestoreOperationParameters type or a IO[bytes] + type. Required. :type restore_blob_details: - ~azure.keyvault.administration._generated.models.RestoreOperationParameters or JSON or - IO[bytes] + ~azure.keyvault.administration._generated.models.RestoreOperationParameters or + ~azure.keyvault.administration._generated.types.RestoreOperationParameters or IO[bytes] :return: An instance of LROPoller that returns RestoreOperation. The RestoreOperation is compatible with MutableMapping :rtype: @@ -2303,11 +2476,22 @@ def get_long_running_output(pipeline_response): @api_version_validation( method_added_on="7.6-preview.2", params_added_on={"7.6-preview.2": ["api_version", "content_type", "accept"]}, - api_versions_list=["7.6-preview.2", "7.6", "2025-06-01-preview", "2025-07-01", "2026-01-01-preview"], + api_versions_list=[ + "7.6-preview.2", + "7.6", + "2025-06-01-preview", + "2025-07-01", + "2026-01-01-preview", + "2026-03-01-preview", + "2026-05-01-preview", + "2026-07-01-preview", + ], ) def _pre_full_restore_operation_initial( self, - pre_restore_operation_parameters: Union[_models.PreRestoreOperationParameters, JSON, IO[bytes]], + pre_restore_operation_parameters: Union[ + _models.PreRestoreOperationParameters, _types.PreRestoreOperationParameters, IO[bytes] + ], **kwargs: Any ) -> Iterator[bytes]: error_map: MutableMapping = { @@ -2404,13 +2588,18 @@ def begin_pre_full_restore_operation( @overload def begin_pre_full_restore_operation( - self, pre_restore_operation_parameters: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + pre_restore_operation_parameters: _types.PreRestoreOperationParameters, + *, + content_type: str = "application/json", + **kwargs: Any ) -> LROPoller[_models.RestoreOperation]: """Pre-restore operation for checking whether the customer can perform a full restore operation. :param pre_restore_operation_parameters: Optional pre restore parameters to validate prior to performing a full restore operation. Required. - :type pre_restore_operation_parameters: JSON + :type pre_restore_operation_parameters: + ~azure.keyvault.administration._generated.types.PreRestoreOperationParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -2444,21 +2633,32 @@ def begin_pre_full_restore_operation( @api_version_validation( method_added_on="7.6-preview.2", params_added_on={"7.6-preview.2": ["api_version", "content_type", "accept"]}, - api_versions_list=["7.6-preview.2", "7.6", "2025-06-01-preview", "2025-07-01", "2026-01-01-preview"], + api_versions_list=[ + "7.6-preview.2", + "7.6", + "2025-06-01-preview", + "2025-07-01", + "2026-01-01-preview", + "2026-03-01-preview", + "2026-05-01-preview", + "2026-07-01-preview", + ], ) def begin_pre_full_restore_operation( self, - pre_restore_operation_parameters: Union[_models.PreRestoreOperationParameters, JSON, IO[bytes]], + pre_restore_operation_parameters: Union[ + _models.PreRestoreOperationParameters, _types.PreRestoreOperationParameters, IO[bytes] + ], **kwargs: Any ) -> LROPoller[_models.RestoreOperation]: """Pre-restore operation for checking whether the customer can perform a full restore operation. :param pre_restore_operation_parameters: Optional pre restore parameters to validate prior to - performing a full restore operation. Is one of the following types: - PreRestoreOperationParameters, JSON, IO[bytes] Required. + performing a full restore operation. Is either a PreRestoreOperationParameters type or a + IO[bytes] type. Required. :type pre_restore_operation_parameters: - ~azure.keyvault.administration._generated.models.PreRestoreOperationParameters or JSON or - IO[bytes] + ~azure.keyvault.administration._generated.models.PreRestoreOperationParameters or + ~azure.keyvault.administration._generated.types.PreRestoreOperationParameters or IO[bytes] :return: An instance of LROPoller that returns RestoreOperation. The RestoreOperation is compatible with MutableMapping :rtype: @@ -2594,7 +2794,9 @@ def selective_key_restore_status(self, job_id: str, **kwargs: Any) -> _models.Se def _selective_key_restore_operation_initial( self, key_name: str, - restore_blob_details: Union[_models.SelectiveKeyRestoreOperationParameters, JSON, IO[bytes]], + restore_blob_details: Union[ + _models.SelectiveKeyRestoreOperationParameters, _types.SelectiveKeyRestoreOperationParameters, IO[bytes] + ], **kwargs: Any ) -> Iterator[bytes]: error_map: MutableMapping = { @@ -2696,7 +2898,12 @@ def begin_selective_key_restore_operation( @overload def begin_selective_key_restore_operation( - self, key_name: str, restore_blob_details: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + key_name: str, + restore_blob_details: _types.SelectiveKeyRestoreOperationParameters, + *, + content_type: str = "application/json", + **kwargs: Any ) -> LROPoller[_models.SelectiveKeyRestoreOperation]: """Restores all key versions of a given key using user supplied SAS token pointing to a previously stored Azure Blob storage backup folder. @@ -2705,7 +2912,8 @@ def begin_selective_key_restore_operation( :type key_name: str :param restore_blob_details: The Azure blob SAS token pointing to a folder where the previous successful full backup was stored. Required. - :type restore_blob_details: JSON + :type restore_blob_details: + ~azure.keyvault.administration._generated.types.SelectiveKeyRestoreOperationParameters :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -2742,7 +2950,9 @@ def begin_selective_key_restore_operation( def begin_selective_key_restore_operation( self, key_name: str, - restore_blob_details: Union[_models.SelectiveKeyRestoreOperationParameters, JSON, IO[bytes]], + restore_blob_details: Union[ + _models.SelectiveKeyRestoreOperationParameters, _types.SelectiveKeyRestoreOperationParameters, IO[bytes] + ], **kwargs: Any ) -> LROPoller[_models.SelectiveKeyRestoreOperation]: """Restores all key versions of a given key using user supplied SAS token pointing to a previously @@ -2751,11 +2961,12 @@ def begin_selective_key_restore_operation( :param key_name: The name of the key to be restored from the user supplied backup. Required. :type key_name: str :param restore_blob_details: The Azure blob SAS token pointing to a folder where the previous - successful full backup was stored. Is one of the following types: - SelectiveKeyRestoreOperationParameters, JSON, IO[bytes] Required. + successful full backup was stored. Is either a SelectiveKeyRestoreOperationParameters type or a + IO[bytes] type. Required. :type restore_blob_details: - ~azure.keyvault.administration._generated.models.SelectiveKeyRestoreOperationParameters or JSON - or IO[bytes] + ~azure.keyvault.administration._generated.models.SelectiveKeyRestoreOperationParameters or + ~azure.keyvault.administration._generated.types.SelectiveKeyRestoreOperationParameters or + IO[bytes] :return: An instance of LROPoller that returns SelectiveKeyRestoreOperation. The SelectiveKeyRestoreOperation is compatible with MutableMapping :rtype: @@ -2850,7 +3061,12 @@ def update_setting( @overload def update_setting( - self, setting_name: str, parameters: JSON, *, content_type: str = "application/json", **kwargs: Any + self, + setting_name: str, + parameters: _types.UpdateSettingRequest, + *, + content_type: str = "application/json", + **kwargs: Any ) -> _models.Setting: """Updates key vault account setting, stores it, then returns the setting name and value to the client. @@ -2861,7 +3077,7 @@ def update_setting( Required. :type setting_name: str :param parameters: The parameters to update an account setting. Required. - :type parameters: JSON + :type parameters: ~azure.keyvault.administration._generated.types.UpdateSettingRequest :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -2894,7 +3110,10 @@ def update_setting( @distributed_trace def update_setting( - self, setting_name: str, parameters: Union[_models.UpdateSettingRequest, JSON, IO[bytes]], **kwargs: Any + self, + setting_name: str, + parameters: Union[_models.UpdateSettingRequest, _types.UpdateSettingRequest, IO[bytes]], + **kwargs: Any ) -> _models.Setting: """Updates key vault account setting, stores it, then returns the setting name and value to the client. @@ -2904,10 +3123,10 @@ def update_setting( :param setting_name: The name of the account setting. Must be a valid settings option. Required. :type setting_name: str - :param parameters: The parameters to update an account setting. Is one of the following types: - UpdateSettingRequest, JSON, IO[bytes] Required. - :type parameters: ~azure.keyvault.administration._generated.models.UpdateSettingRequest or JSON - or IO[bytes] + :param parameters: The parameters to update an account setting. Is either a + UpdateSettingRequest type or a IO[bytes] type. Required. + :type parameters: ~azure.keyvault.administration._generated.models.UpdateSettingRequest or + ~azure.keyvault.administration._generated.types.UpdateSettingRequest or IO[bytes] :return: Setting. The Setting is compatible with MutableMapping :rtype: ~azure.keyvault.administration._generated.models.Setting :raises ~azure.core.exceptions.HttpResponseError: @@ -3119,7 +3338,7 @@ def get_settings(self, **kwargs: Any) -> _models.SettingsListResult: @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) def get_ekm_connection(self, **kwargs: Any) -> _models.EkmConnection: """Gets the EKM connection. @@ -3191,7 +3410,7 @@ def get_ekm_connection(self, **kwargs: Any) -> _models.EkmConnection: @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) def get_ekm_certificate(self, **kwargs: Any) -> _models.EkmProxyClientCertificateInfo: """Gets the EKM proxy client certificate. @@ -3264,7 +3483,7 @@ def get_ekm_certificate(self, **kwargs: Any) -> _models.EkmProxyClientCertificat @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) def check_ekm_connection(self, **kwargs: Any) -> _models.EkmProxyInfo: """Checks the connectivity and authentication with the EKM proxy. @@ -3353,7 +3572,7 @@ def create_ekm_connection( @overload def create_ekm_connection( - self, ekm_connection: JSON, *, content_type: str = "application/json", **kwargs: Any + self, ekm_connection: _types.EkmConnection, *, content_type: str = "application/json", **kwargs: Any ) -> _models.EkmConnection: """Creates the EKM connection. @@ -3361,7 +3580,7 @@ def create_ekm_connection( exists, this operation fails. This operation requires ekm/write permission. :param ekm_connection: The ekmConnection to create. Required. - :type ekm_connection: JSON + :type ekm_connection: ~azure.keyvault.administration._generated.types.EkmConnection :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -3393,20 +3612,20 @@ def create_ekm_connection( @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "content_type", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) def create_ekm_connection( - self, ekm_connection: Union[_models.EkmConnection, JSON, IO[bytes]], **kwargs: Any + self, ekm_connection: Union[_models.EkmConnection, _types.EkmConnection, IO[bytes]], **kwargs: Any ) -> _models.EkmConnection: """Creates the EKM connection. The External Key Manager (EKM) sets up the EKM connection. If the EKM connection already exists, this operation fails. This operation requires ekm/write permission. - :param ekm_connection: The ekmConnection to create. Is one of the following types: - EkmConnection, JSON, IO[bytes] Required. - :type ekm_connection: ~azure.keyvault.administration._generated.models.EkmConnection or JSON or - IO[bytes] + :param ekm_connection: The ekmConnection to create. Is either a EkmConnection type or a + IO[bytes] type. Required. + :type ekm_connection: ~azure.keyvault.administration._generated.models.EkmConnection or + ~azure.keyvault.administration._generated.types.EkmConnection or IO[bytes] :return: EkmConnection. The EkmConnection is compatible with MutableMapping :rtype: ~azure.keyvault.administration._generated.models.EkmConnection :raises ~azure.core.exceptions.HttpResponseError: @@ -3498,7 +3717,7 @@ def update_ekm_connection( @overload def update_ekm_connection( - self, ekm_connection: JSON, *, content_type: str = "application/json", **kwargs: Any + self, ekm_connection: _types.EkmConnection, *, content_type: str = "application/json", **kwargs: Any ) -> _models.EkmConnection: """Updates the EKM connection. @@ -3506,7 +3725,7 @@ def update_ekm_connection( not exist, this operation fails. This operation requires ekm/write permission. :param ekm_connection: The ekmConnection to update. Required. - :type ekm_connection: JSON + :type ekm_connection: ~azure.keyvault.administration._generated.types.EkmConnection :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str @@ -3538,20 +3757,20 @@ def update_ekm_connection( @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "content_type", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) def update_ekm_connection( - self, ekm_connection: Union[_models.EkmConnection, JSON, IO[bytes]], **kwargs: Any + self, ekm_connection: Union[_models.EkmConnection, _types.EkmConnection, IO[bytes]], **kwargs: Any ) -> _models.EkmConnection: """Updates the EKM connection. The External Key Manager (EKM) updates the existing EKM connection. If the EKM connection does not exist, this operation fails. This operation requires ekm/write permission. - :param ekm_connection: The ekmConnection to update. Is one of the following types: - EkmConnection, JSON, IO[bytes] Required. - :type ekm_connection: ~azure.keyvault.administration._generated.models.EkmConnection or JSON or - IO[bytes] + :param ekm_connection: The ekmConnection to update. Is either a EkmConnection type or a + IO[bytes] type. Required. + :type ekm_connection: ~azure.keyvault.administration._generated.models.EkmConnection or + ~azure.keyvault.administration._generated.types.EkmConnection or IO[bytes] :return: EkmConnection. The EkmConnection is compatible with MutableMapping :rtype: ~azure.keyvault.administration._generated.models.EkmConnection :raises ~azure.core.exceptions.HttpResponseError: @@ -3626,7 +3845,7 @@ def update_ekm_connection( @api_version_validation( method_added_on="2026-01-01-preview", params_added_on={"2026-01-01-preview": ["api_version", "accept"]}, - api_versions_list=["2026-01-01-preview"], + api_versions_list=["2026-01-01-preview", "2026-03-01-preview", "2026-05-01-preview", "2026-07-01-preview"], ) def delete_ekm_connection(self, **kwargs: Any) -> _models.EkmConnection: """Deletes the EKM connection. @@ -3693,3 +3912,631 @@ def delete_ekm_connection(self, **kwargs: Any) -> _models.EkmConnection: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "operation_id", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + def get_ekm_private_endpoint_operation_status( # pylint: disable=name-too-long + self, operation_id: str, **kwargs: Any + ) -> _models.EkmPrivateEndpointOperation: + """Gets the status of an EKM proxy private endpoint operation. + + The External Key Manager (EKM) private endpoint operation status. Returns the status of a + private endpoint create or delete operation. This operation requires ekm/read permission. + + :param operation_id: The identifier of the private endpoint operation. Required. + :type operation_id: str + :return: EkmPrivateEndpointOperation. The EkmPrivateEndpointOperation is compatible with + MutableMapping + :rtype: ~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.EkmPrivateEndpointOperation] = kwargs.pop("cls", None) + + _request = build_key_vault_get_ekm_private_endpoint_operation_status_request( + operation_id=operation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.KeyVaultError, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.EkmPrivateEndpointOperation, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "pe_name", "content_type", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + def _create_ekm_private_endpoint_initial( + self, + pe_name: str, + parameters: Union[ + _models.EkmPrivateEndpointCreateParameters, _types.EkmPrivateEndpointCreateParameters, IO[bytes] + ], + **kwargs: Any + ) -> Iterator[bytes]: + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(parameters, (IOBase, bytes)): + _content = parameters + else: + _content = json.dumps(parameters, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_key_vault_create_ekm_private_endpoint_request( + pe_name=pe_name, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = True + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [202]: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.KeyVaultError, + response, + ) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers["Azure-AsyncOperation"] = self._deserialize( + "str", response.headers.get("Azure-AsyncOperation") + ) + response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @overload + def begin_create_ekm_private_endpoint( + self, + pe_name: str, + parameters: _models.EkmPrivateEndpointCreateParameters, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> LROPoller[_models.EkmPrivateEndpointOperation]: + """Creates an EKM proxy private endpoint. + + The External Key Manager (EKM) creates a private endpoint to the EKM proxy Private Link + Service. A pool may have up to two private endpoints. This operation requires ekm/write + permission. + + :param pe_name: The name of the private endpoint. Must be 1-24 characters, start and end with + an alphanumeric character, and contain only alphanumeric characters and hyphens. Required. + :type pe_name: str + :param parameters: The parameters to create the private endpoint. Required. + :type parameters: + ~azure.keyvault.administration._generated.models.EkmPrivateEndpointCreateParameters + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: An instance of LROPoller that returns EkmPrivateEndpointOperation. The + EkmPrivateEndpointOperation is compatible with MutableMapping + :rtype: + ~azure.core.polling.LROPoller[~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def begin_create_ekm_private_endpoint( + self, + pe_name: str, + parameters: _types.EkmPrivateEndpointCreateParameters, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> LROPoller[_models.EkmPrivateEndpointOperation]: + """Creates an EKM proxy private endpoint. + + The External Key Manager (EKM) creates a private endpoint to the EKM proxy Private Link + Service. A pool may have up to two private endpoints. This operation requires ekm/write + permission. + + :param pe_name: The name of the private endpoint. Must be 1-24 characters, start and end with + an alphanumeric character, and contain only alphanumeric characters and hyphens. Required. + :type pe_name: str + :param parameters: The parameters to create the private endpoint. Required. + :type parameters: + ~azure.keyvault.administration._generated.types.EkmPrivateEndpointCreateParameters + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: An instance of LROPoller that returns EkmPrivateEndpointOperation. The + EkmPrivateEndpointOperation is compatible with MutableMapping + :rtype: + ~azure.core.polling.LROPoller[~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def begin_create_ekm_private_endpoint( + self, pe_name: str, parameters: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> LROPoller[_models.EkmPrivateEndpointOperation]: + """Creates an EKM proxy private endpoint. + + The External Key Manager (EKM) creates a private endpoint to the EKM proxy Private Link + Service. A pool may have up to two private endpoints. This operation requires ekm/write + permission. + + :param pe_name: The name of the private endpoint. Must be 1-24 characters, start and end with + an alphanumeric character, and contain only alphanumeric characters and hyphens. Required. + :type pe_name: str + :param parameters: The parameters to create the private endpoint. Required. + :type parameters: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: An instance of LROPoller that returns EkmPrivateEndpointOperation. The + EkmPrivateEndpointOperation is compatible with MutableMapping + :rtype: + ~azure.core.polling.LROPoller[~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "pe_name", "content_type", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + def begin_create_ekm_private_endpoint( + self, + pe_name: str, + parameters: Union[ + _models.EkmPrivateEndpointCreateParameters, _types.EkmPrivateEndpointCreateParameters, IO[bytes] + ], + **kwargs: Any + ) -> LROPoller[_models.EkmPrivateEndpointOperation]: + """Creates an EKM proxy private endpoint. + + The External Key Manager (EKM) creates a private endpoint to the EKM proxy Private Link + Service. A pool may have up to two private endpoints. This operation requires ekm/write + permission. + + :param pe_name: The name of the private endpoint. Must be 1-24 characters, start and end with + an alphanumeric character, and contain only alphanumeric characters and hyphens. Required. + :type pe_name: str + :param parameters: The parameters to create the private endpoint. Is either a + EkmPrivateEndpointCreateParameters type or a IO[bytes] type. Required. + :type parameters: + ~azure.keyvault.administration._generated.models.EkmPrivateEndpointCreateParameters or + ~azure.keyvault.administration._generated.types.EkmPrivateEndpointCreateParameters or IO[bytes] + :return: An instance of LROPoller that returns EkmPrivateEndpointOperation. The + EkmPrivateEndpointOperation is compatible with MutableMapping + :rtype: + ~azure.core.polling.LROPoller[~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.EkmPrivateEndpointOperation] = kwargs.pop("cls", None) + polling: Union[bool, PollingMethod] = kwargs.pop("polling", True) + lro_delay = kwargs.pop("polling_interval", self._config.polling_interval) + cont_token: Optional[str] = kwargs.pop("continuation_token", None) + if cont_token is None: + raw_result = self._create_ekm_private_endpoint_initial( + pe_name=pe_name, + parameters=parameters, + content_type=content_type, + cls=lambda x, y, z: x, + headers=_headers, + params=_params, + **kwargs + ) + raw_result.http_response.read() # type: ignore + kwargs.pop("error_map", None) + + def get_long_running_output(pipeline_response): + response_headers = {} + response = pipeline_response.http_response + response_headers["Azure-AsyncOperation"] = self._deserialize( + "str", response.headers.get("Azure-AsyncOperation") + ) + response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + + deserialized = _deserialize(_models.EkmPrivateEndpointOperation, response.json()) + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + return deserialized + + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + + if polling is True: + polling_method: PollingMethod = cast( + PollingMethod, LROBasePolling(lro_delay, path_format_arguments=path_format_arguments, **kwargs) + ) + elif polling is False: + polling_method = cast(PollingMethod, NoPolling()) + else: + polling_method = polling + if cont_token: + return LROPoller[_models.EkmPrivateEndpointOperation].from_continuation_token( + polling_method=polling_method, + continuation_token=cont_token, + client=self._client, + deserialization_callback=get_long_running_output, + ) + return LROPoller[_models.EkmPrivateEndpointOperation]( + self._client, raw_result, get_long_running_output, polling_method # type: ignore + ) + + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "pe_name", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + def _delete_ekm_private_endpoint_initial(self, pe_name: str, **kwargs: Any) -> Iterator[bytes]: + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + + _request = build_key_vault_delete_ekm_private_endpoint_request( + pe_name=pe_name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = True + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [202]: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.KeyVaultError, + response, + ) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers["Azure-AsyncOperation"] = self._deserialize( + "str", response.headers.get("Azure-AsyncOperation") + ) + response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "pe_name", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + def begin_delete_ekm_private_endpoint( + self, pe_name: str, **kwargs: Any + ) -> LROPoller[_models.EkmPrivateEndpointOperation]: + """Deletes an EKM proxy private endpoint. + + The External Key Manager (EKM) deletes an existing EKM proxy private endpoint. The operation is + rejected while an EKM connection still references the private endpoint. This operation requires + ekm/write permission. + + :param pe_name: The name of the private endpoint to delete. Required. + :type pe_name: str + :return: An instance of LROPoller that returns EkmPrivateEndpointOperation. The + EkmPrivateEndpointOperation is compatible with MutableMapping + :rtype: + ~azure.core.polling.LROPoller[~azure.keyvault.administration._generated.models.EkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.EkmPrivateEndpointOperation] = kwargs.pop("cls", None) + polling: Union[bool, PollingMethod] = kwargs.pop("polling", True) + lro_delay = kwargs.pop("polling_interval", self._config.polling_interval) + cont_token: Optional[str] = kwargs.pop("continuation_token", None) + if cont_token is None: + raw_result = self._delete_ekm_private_endpoint_initial( + pe_name=pe_name, cls=lambda x, y, z: x, headers=_headers, params=_params, **kwargs + ) + raw_result.http_response.read() # type: ignore + kwargs.pop("error_map", None) + + def get_long_running_output(pipeline_response): + response_headers = {} + response = pipeline_response.http_response + response_headers["Azure-AsyncOperation"] = self._deserialize( + "str", response.headers.get("Azure-AsyncOperation") + ) + response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + + deserialized = _deserialize(_models.EkmPrivateEndpointOperation, response.json()) + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + return deserialized + + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + + if polling is True: + polling_method: PollingMethod = cast( + PollingMethod, LROBasePolling(lro_delay, path_format_arguments=path_format_arguments, **kwargs) + ) + elif polling is False: + polling_method = cast(PollingMethod, NoPolling()) + else: + polling_method = polling + if cont_token: + return LROPoller[_models.EkmPrivateEndpointOperation].from_continuation_token( + polling_method=polling_method, + continuation_token=cont_token, + client=self._client, + deserialization_callback=get_long_running_output, + ) + return LROPoller[_models.EkmPrivateEndpointOperation]( + self._client, raw_result, get_long_running_output, polling_method # type: ignore + ) + + @distributed_trace + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "pe_name", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + def get_ekm_private_endpoint(self, pe_name: str, **kwargs: Any) -> _models.EkmPrivateEndpoint: + """Gets an EKM proxy private endpoint. + + The External Key Manager (EKM) gets an existing EKM proxy private endpoint. This operation + requires ekm/read permission. + + :param pe_name: The name of the private endpoint to get. Required. + :type pe_name: str + :return: EkmPrivateEndpoint. The EkmPrivateEndpoint is compatible with MutableMapping + :rtype: ~azure.keyvault.administration._generated.models.EkmPrivateEndpoint + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.EkmPrivateEndpoint] = kwargs.pop("cls", None) + + _request = build_key_vault_get_ekm_private_endpoint_request( + pe_name=pe_name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.KeyVaultError, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.EkmPrivateEndpoint, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2026-07-01-preview", + params_added_on={"2026-07-01-preview": ["api_version", "accept"]}, + api_versions_list=["2026-07-01-preview"], + ) + def list_ekm_private_endpoints(self, **kwargs: Any) -> _models.EkmPrivateEndpointListResult: + """Lists the EKM proxy private endpoints. + + The External Key Manager (EKM) lists all EKM proxy private endpoints on the pool. This + operation requires ekm/read permission. + + :return: EkmPrivateEndpointListResult. The EkmPrivateEndpointListResult is compatible with + MutableMapping + :rtype: ~azure.keyvault.administration._generated.models.EkmPrivateEndpointListResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.EkmPrivateEndpointListResult] = kwargs.pop("cls", None) + + _request = build_key_vault_list_ekm_private_endpoints_request( + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "vaultBaseUrl": self._serialize.url( + "self._config.vault_base_url", self._config.vault_base_url, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.KeyVaultError, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.EkmPrivateEndpointListResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/types.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/types.py new file mode 100644 index 000000000000..f42ae2891807 --- /dev/null +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_generated/types.py @@ -0,0 +1,268 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from typing import TYPE_CHECKING, Union +from typing_extensions import Required, TypedDict + +if TYPE_CHECKING: + from .models import DataAction, EkmConnectivityMode, RoleScope, RoleType + + +class EkmConnection(TypedDict, total=False): + """A EkmConnection model object. + + :ivar host: EKM proxy FQDN (Fully Qualified Domain Name). Only allowed characters are a-z, A-Z, + 0-9, hyphen (-), dot (.), and colon (:). Required. + :vartype host: str + :ivar path_prefix: Optional path prefix for the EKM proxy (if any). + :vartype path_prefix: str + :ivar server_ca_certificates: The root CA certificate chain that issued the proxy server's + certificate. An array of certificates in the certificate chain, each in DER format and base64 + encoded. Required. + :vartype server_ca_certificates: list[str] + :ivar server_subject_common_name: The subject common name of the server certificate of EKM + Proxy. + :vartype server_subject_common_name: str + :ivar connectivity_mode: The connectivity mode used to reach the EKM proxy. Defaults to + "Public". In "PrivateEndpoint" mode, the host field holds the name of a private endpoint + (peName) instead of a DNS name or IP address. Known values are: "Public" and "PrivateEndpoint". + :vartype connectivity_mode: Union[str, "EkmConnectivityMode"] + """ + + host: Required[str] + """EKM proxy FQDN (Fully Qualified Domain Name). Only allowed characters are a-z, A-Z, 0-9, hyphen + (-), dot (.), and colon (:). Required.""" + path_prefix: str + """Optional path prefix for the EKM proxy (if any).""" + server_ca_certificates: Required[list[str]] + """The root CA certificate chain that issued the proxy server's certificate. An array of + certificates in the certificate chain, each in DER format and base64 encoded. Required.""" + server_subject_common_name: str + """The subject common name of the server certificate of EKM Proxy.""" + connectivity_mode: Union[str, "EkmConnectivityMode"] + """The connectivity mode used to reach the EKM proxy. Defaults to \"Public\". In + \"PrivateEndpoint\" mode, the host field holds the name of a private endpoint (peName) instead + of a DNS name or IP address. Known values are: \"Public\" and \"PrivateEndpoint\".""" + + +class EkmPrivateEndpointCreateParameters(TypedDict, total=False): + """Parameters to create an EKM proxy private endpoint. + + :ivar privateLinkServiceId: Alias of the Private Link Service that the private endpoint + connects to. Required. + :vartype privateLinkServiceId: str + :ivar requestMessage: An optional message shown to the Private Link Service owner when + approving the private endpoint connection. + :vartype requestMessage: str + """ + + privateLinkServiceId: Required[str] + """Alias of the Private Link Service that the private endpoint connects to. Required.""" + requestMessage: str + """An optional message shown to the Private Link Service owner when approving the private endpoint + connection.""" + + +class Permission(TypedDict, total=False): + """Role definition permissions. + + :ivar actions: Action permissions that are granted. + :vartype actions: list[str] + :ivar notActions: Action permissions that are excluded but not denied. They may be granted by + other role definitions assigned to a principal. + :vartype notActions: list[str] + :ivar dataActions: Data action permissions that are granted. + :vartype dataActions: list[Union[str, "DataAction"]] + :ivar notDataActions: Data action permissions that are excluded but not denied. They may be + granted by other role definitions assigned to a principal. + :vartype notDataActions: list[Union[str, "DataAction"]] + """ + + actions: list[str] + """Action permissions that are granted.""" + notActions: list[str] + """Action permissions that are excluded but not denied. They may be granted by other role + definitions assigned to a principal.""" + dataActions: list[Union[str, "DataAction"]] + """Data action permissions that are granted.""" + notDataActions: list[Union[str, "DataAction"]] + """Data action permissions that are excluded but not denied. They may be granted by other role + definitions assigned to a principal.""" + + +class PreBackupOperationParameters(TypedDict, total=False): + """The authentication method and location for the backup operation. + + :ivar storageResourceUri: Azure Blob storage container Uri. + :vartype storageResourceUri: str + :ivar token: The SAS token pointing to an Azure Blob storage container. + :vartype token: str + :ivar useManagedIdentity: Indicates which authentication method should be used. If set to true, + Managed HSM will use the configured user-assigned managed identity to authenticate with Azure + Storage. Otherwise, a SAS token has to be specified. + :vartype useManagedIdentity: bool + """ + + storageResourceUri: str + """Azure Blob storage container Uri.""" + token: str + """The SAS token pointing to an Azure Blob storage container.""" + useManagedIdentity: bool + """Indicates which authentication method should be used. If set to true, Managed HSM will use the + configured user-assigned managed identity to authenticate with Azure Storage. Otherwise, a SAS + token has to be specified.""" + + +class PreRestoreOperationParameters(TypedDict, total=False): + """The authentication method and location for the restore operation. + + :ivar sasTokenParameters: A user-provided SAS token to an Azure blob storage container. + :vartype sasTokenParameters: "SASTokenParameter" + :ivar folderToRestore: The Folder name of the blob where the previous successful full backup + was stored. + :vartype folderToRestore: str + """ + + sasTokenParameters: "SASTokenParameter" + """A user-provided SAS token to an Azure blob storage container.""" + folderToRestore: str + """The Folder name of the blob where the previous successful full backup was stored.""" + + +class RestoreOperationParameters(TypedDict, total=False): + """The authentication method and location for the restore operation. + + :ivar sasTokenParameters: A user-provided SAS token to an Azure blob storage container. + Required. + :vartype sasTokenParameters: "SASTokenParameter" + :ivar folderToRestore: The Folder name of the blob where the previous successful full backup + was stored. Required. + :vartype folderToRestore: str + """ + + sasTokenParameters: Required["SASTokenParameter"] + """A user-provided SAS token to an Azure blob storage container. Required.""" + folderToRestore: Required[str] + """The Folder name of the blob where the previous successful full backup was stored. Required.""" + + +class RoleAssignmentCreateParameters(TypedDict, total=False): + """Role assignment create parameters. + + :ivar properties: Role assignment properties. Required. + :vartype properties: "RoleAssignmentProperties" + """ + + properties: Required["RoleAssignmentProperties"] + """Role assignment properties. Required.""" + + +class RoleAssignmentProperties(TypedDict, total=False): + """Role assignment properties. + + :ivar roleDefinitionId: The role definition ID used in the role assignment. Required. + :vartype roleDefinitionId: str + :ivar principalId: The principal ID assigned to the role. This maps to the ID inside the Active + Directory. It can point to a user, service principal, or security group. Required. + :vartype principalId: str + """ + + roleDefinitionId: Required[str] + """The role definition ID used in the role assignment. Required.""" + principalId: Required[str] + """The principal ID assigned to the role. This maps to the ID inside the Active Directory. It can + point to a user, service principal, or security group. Required.""" + + +class RoleDefinitionCreateParameters(TypedDict, total=False): + """Role definition create parameters. + + :ivar properties: Role definition properties. Required. + :vartype properties: "RoleDefinitionProperties" + """ + + properties: Required["RoleDefinitionProperties"] + """Role definition properties. Required.""" + + +class RoleDefinitionProperties(TypedDict, total=False): + """Role definition properties. + + :ivar roleName: The role name. + :vartype roleName: str + :ivar description: The role definition description. + :vartype description: str + :ivar type: The role type. Known values are: "AKVBuiltInRole" and "CustomRole". + :vartype type: Union[str, "RoleType"] + :ivar permissions: Role definition permissions. + :vartype permissions: list["Permission"] + :ivar assignableScopes: Role definition assignable scopes. + :vartype assignableScopes: list[Union[str, "RoleScope"]] + """ + + roleName: str + """The role name.""" + description: str + """The role definition description.""" + type: Union[str, "RoleType"] + """The role type. Known values are: \"AKVBuiltInRole\" and \"CustomRole\".""" + permissions: list["Permission"] + """Role definition permissions.""" + assignableScopes: list[Union[str, "RoleScope"]] + """Role definition assignable scopes.""" + + +class SASTokenParameter(TypedDict, total=False): + """An authentication method and location for the operation. + + :ivar storageResourceUri: Azure Blob storage container Uri. Required. + :vartype storageResourceUri: str + :ivar token: The SAS token pointing to an Azure Blob storage container. + :vartype token: str + :ivar useManagedIdentity: Indicates which authentication method should be used. If set to true, + Managed HSM will use the configured user-assigned managed identity to authenticate with Azure + Storage. Otherwise, a SAS token has to be specified. + :vartype useManagedIdentity: bool + """ + + storageResourceUri: Required[str] + """Azure Blob storage container Uri. Required.""" + token: str + """The SAS token pointing to an Azure Blob storage container.""" + useManagedIdentity: bool + """Indicates which authentication method should be used. If set to true, Managed HSM will use the + configured user-assigned managed identity to authenticate with Azure Storage. Otherwise, a SAS + token has to be specified.""" + + +class SelectiveKeyRestoreOperationParameters(TypedDict, total=False): + """The authentication method and location for the selective key restore operation. + + :ivar sasTokenParameters: A user-provided SAS token to an Azure blob storage container. + Required. + :vartype sasTokenParameters: "SASTokenParameter" + :ivar folder: The Folder name of the blob where the previous successful full backup was stored. + Required. + :vartype folder: str + """ + + sasTokenParameters: Required["SASTokenParameter"] + """A user-provided SAS token to an Azure blob storage container. Required.""" + folder: Required[str] + """The Folder name of the blob where the previous successful full backup was stored. Required.""" + + +class UpdateSettingRequest(TypedDict, total=False): + """The update settings request object. + + :ivar value: The value of the pool setting. Required. + :vartype value: str + """ + + value: Required[str] + """The value of the pool setting. Required.""" diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_internal/challenge_auth_policy.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_internal/challenge_auth_policy.py index 0f5f99993c56..cbc538f2dc2b 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_internal/challenge_auth_policy.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_internal/challenge_auth_policy.py @@ -35,7 +35,6 @@ from .http_challenge import HttpChallenge from . import http_challenge_cache as ChallengeCache - # Key under which the original request is stashed on the per-request pipeline context during the challenge flow. # Storing this per-request (rather than on the policy instance) prevents the body of one request from leaking into a # subsequent request made by the same client. diff --git a/sdk/keyvault/azure-keyvault-administration/setup.py b/sdk/keyvault/azure-keyvault-administration/setup.py index 73d3da6f03cd..244a563f88bd 100644 --- a/sdk/keyvault/azure-keyvault-administration/setup.py +++ b/sdk/keyvault/azure-keyvault-administration/setup.py @@ -46,6 +46,7 @@ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "License :: OSI Approved :: MIT License", ], zip_safe=False, diff --git a/sdk/keyvault/azure-keyvault-administration/tests/test_challenge_auth.py b/sdk/keyvault/azure-keyvault-administration/tests/test_challenge_auth.py index 7cc3716d5c6f..c65b7f7126d4 100644 --- a/sdk/keyvault/azure-keyvault-administration/tests/test_challenge_auth.py +++ b/sdk/keyvault/azure-keyvault-administration/tests/test_challenge_auth.py @@ -52,7 +52,9 @@ def test_rejected_challenge_is_not_cached(): url = "https://example.net/backup/canary" challenge = Mock( status_code=401, - headers={"WWW-Authenticate": 'Bearer authorization="https://authority.net/tenant", resource=https://vault.azure.net'}, + headers={ + "WWW-Authenticate": 'Bearer authorization="https://authority.net/tenant", resource=https://vault.azure.net' + }, ) class Requests: @@ -85,7 +87,9 @@ async def test_rejected_challenge_is_not_cached_async(): url = "https://example.net/backup/canary" challenge = Mock( status_code=401, - headers={"WWW-Authenticate": 'Bearer authorization="https://authority.net/tenant", resource=https://vault.azure.net'}, + headers={ + "WWW-Authenticate": 'Bearer authorization="https://authority.net/tenant", resource=https://vault.azure.net' + }, ) class Requests: diff --git a/sdk/keyvault/azure-keyvault-administration/tsp-location.yaml b/sdk/keyvault/azure-keyvault-administration/tsp-location.yaml index 658ae5523886..5dc9b8e0c241 100644 --- a/sdk/keyvault/azure-keyvault-administration/tsp-location.yaml +++ b/sdk/keyvault/azure-keyvault-administration/tsp-location.yaml @@ -1,3 +1,3 @@ directory: specification/keyvault/data-plane/Administration -commit: 0aea5f5666b9d631d37074a2f9c9bd8ba0dd1eff +commit: 128edb78cca1fea736179ae1c911f9e7ad23e2cb repo: Azure/azure-rest-api-specs From 4da56f35c4c64f56410531e76dc3c864b8f34214 Mon Sep 17 00:00:00 2001 From: Nicola Camillucci Date: Fri, 7 Aug 2026 17:24:28 +0100 Subject: [PATCH 2/4] Updated EKM Client with EKM Private Endpoints --- .../CHANGELOG.md | 15 ++ .../azure-keyvault-administration/README.md | 13 +- .../azure-keyvault-administration/api.md | 150 ++++++++++++++ .../api.metadata.yml | 2 +- .../azure/keyvault/administration/__init__.py | 25 ++- .../keyvault/administration/_ekm_client.py | 118 ++++++++++- .../azure/keyvault/administration/_enums.py | 65 ++++++ .../administration/_internal/client_base.py | 3 +- .../azure/keyvault/administration/_models.py | 196 +++++++++++++++++- .../administration/aio/_ekm_client.py | 122 ++++++++++- .../samples/README.md | 8 + .../ekm_private_endpoint_operations.py | 108 ++++++++++ .../ekm_private_endpoint_operations_async.py | 107 ++++++++++ .../tests/_async_test_case.py | 4 + .../tests/_test_case.py | 4 + .../tests/conftest.py | 2 + .../tests/test_ekm_client.py | 60 +++++- .../tests/test_ekm_client_async.py | 63 +++++- 18 files changed, 1050 insertions(+), 15 deletions(-) create mode 100644 sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations.py create mode 100644 sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations_async.py diff --git a/sdk/keyvault/azure-keyvault-administration/CHANGELOG.md b/sdk/keyvault/azure-keyvault-administration/CHANGELOG.md index 4c861274a400..14848f694efd 100644 --- a/sdk/keyvault/azure-keyvault-administration/CHANGELOG.md +++ b/sdk/keyvault/azure-keyvault-administration/CHANGELOG.md @@ -4,6 +4,19 @@ ### Features Added +- Added support for service API version `2026-07-01-preview` +- Added EKM proxy private endpoint management to `KeyVaultEkmClient`. The client now exposes + `begin_create_ekm_private_endpoint`, `begin_delete_ekm_private_endpoint`, `get_ekm_private_endpoint`, + `list_ekm_private_endpoints`, and `get_ekm_private_endpoint_operation_status`. +- Added `KeyVaultEkmPrivateEndpoint`, `KeyVaultEkmPrivateEndpointConnectionState`, + `KeyVaultEkmPrivateEndpointProperties`, and `KeyVaultEkmPrivateEndpointOperation` models, along with the + `KeyVaultEkmConnectivityMode`, `KeyVaultEkmPrivateEndpointConnectionStatus`, + `KeyVaultEkmPrivateEndpointOperationStatus`, `KeyVaultEkmPrivateEndpointOperationType`, and + `KeyVaultEkmPrivateEndpointProvisioningState` enums. +- Added a `connectivity_mode` keyword argument and attribute to `KeyVaultEkmConnection`. Set this to + `KeyVaultEkmConnectivityMode.PRIVATE_ENDPOINT` to reach the EKM proxy through an EKM proxy private endpoint, in which + case `host` is the name of the private endpoint instead of a DNS name or IP address. + ### Breaking Changes ### Bugs Fixed @@ -12,6 +25,8 @@ ### Other Changes +- Key Vault API version `2026-07-01-preview` is now the default. + ## 4.8.0b2 (2026-07-08) ### Bugs Fixed diff --git a/sdk/keyvault/azure-keyvault-administration/README.md b/sdk/keyvault/azure-keyvault-administration/README.md index 7bbd2ebec1ce..4e2e670218a8 100644 --- a/sdk/keyvault/azure-keyvault-administration/README.md +++ b/sdk/keyvault/azure-keyvault-administration/README.md @@ -161,12 +161,20 @@ A `KeyVaultSettingsClient` manages Managed HSM account settings. ### KeyVaultEkmClient -A `KeyVaultEkmClient` manages the Managed HSM's External Key Manager (EKM) connection. +A `KeyVaultEkmClient` manages the Managed HSM's External Key Manager (EKM) connection and its EKM proxy private +endpoints. ### EKM Connection An EKM connection represents the connection of an Azure Managed HSM resource with an external HSM. +### EKM Proxy Private Endpoint + +An EKM proxy private endpoint lets a Managed HSM reach an EKM proxy through an Azure Private Link Service instead of +the public internet. A Managed HSM may have up to two EKM proxy private endpoints. To route an EKM connection through +one, set the connection's `host` to the private endpoint's name and its `connectivity_mode` to +`KeyVaultEkmConnectivityMode.PRIVATE_ENDPOINT`. + ## Examples This section contains code snippets covering common tasks: * Access control @@ -440,6 +448,7 @@ Several samples are available in the Azure SDK for Python GitHub repository. The - [Full backup and restore][backup_operations_sample] ([async version][backup_operations_async_sample]) - [List and update Key Vault settings][settings_operations_sample] ([async version][settings_operations_async_sample]) - [Retrieve and manage EKM connections][ekm_operations_sample] ([async version][ekm_operations_async_sample]) +- [Manage EKM proxy private endpoints][ekm_private_endpoint_operations_sample] ([async version][ekm_private_endpoint_operations_async_sample]) ### Additional documentation For more extensive documentation on Azure Key Vault, see the [API reference documentation][reference_docs]. @@ -503,6 +512,8 @@ contact opencode@microsoft.com with any additional questions or comments. [settings_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/settings_operations_async.py [ekm_operations_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/ekm_operations.py [ekm_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/ekm_operations_async.py +[ekm_private_endpoint_operations_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations.py +[ekm_private_endpoint_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations_async.py [storage_blob]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/storage/azure-storage-blob/README.md [storage_explorer]: https://learn.microsoft.com/azure/vs-azure-tools-storage-manage-with-storage-explorer diff --git a/sdk/keyvault/azure-keyvault-administration/api.md b/sdk/keyvault/azure-keyvault-administration/api.md index 7b640989b115..d16eee912e10 100644 --- a/sdk/keyvault/azure-keyvault-administration/api.md +++ b/sdk/keyvault/azure-keyvault-administration/api.md @@ -4,6 +4,7 @@ namespace azure.keyvault.administration class azure.keyvault.administration.ApiVersion(str, Enum, metaclass=CaseInsensitiveEnumMeta): V2025_07_01 = "2025-07-01" V2026_01_01_PREVIEW = "2026-01-01-preview" + V2026_07_01_PREVIEW = "2026-07-01-preview" V7_2 = "7.2" V7_3 = "7.3" V7_4 = "7.4" @@ -269,6 +270,23 @@ namespace azure.keyvault.administration **kwargs: Any ) -> None: ... + @distributed_trace + def begin_create_ekm_private_endpoint( + self, + name: str, + private_link_service_id: str, + *, + request_message: Optional[str] = ..., + **kwargs: Any + ) -> LROPoller[KeyVaultEkmPrivateEndpointOperation]: ... + + @distributed_trace + def begin_delete_ekm_private_endpoint( + self, + name: str, + **kwargs: Any + ) -> LROPoller[KeyVaultEkmPrivateEndpointOperation]: ... + @distributed_trace def check_ekm_connection(self, **kwargs: Any) -> KeyVaultEkmProxyInfo: ... @@ -290,6 +308,23 @@ namespace azure.keyvault.administration @distributed_trace def get_ekm_connection(self, **kwargs: Any) -> KeyVaultEkmConnection: ... + @distributed_trace + def get_ekm_private_endpoint( + self, + name: str, + **kwargs: Any + ) -> KeyVaultEkmPrivateEndpoint: ... + + @distributed_trace + def get_ekm_private_endpoint_operation_status( + self, + job_id: str, + **kwargs: Any + ) -> KeyVaultEkmPrivateEndpointOperation: ... + + @distributed_trace + def list_ekm_private_endpoints(self, **kwargs: Any) -> ItemPaged[KeyVaultEkmPrivateEndpoint]: ... + @distributed_trace def send_request( self, @@ -308,6 +343,7 @@ namespace azure.keyvault.administration class azure.keyvault.administration.KeyVaultEkmConnection: + connectivity_mode: Union[str, KeyVaultEkmConnectivityMode, None] host: str path_prefix: Union[str, None] server_ca_certificates: list[bytes] @@ -318,6 +354,7 @@ namespace azure.keyvault.administration host: str, server_ca_certificates: List[bytes], *, + connectivity_mode: Optional[Union[str, KeyVaultEkmConnectivityMode]] = ..., path_prefix: Optional[str] = ..., server_subject_common_name: Optional[str] = ... ) -> None: ... @@ -325,6 +362,85 @@ namespace azure.keyvault.administration def __repr__(self) -> str: ... + class azure.keyvault.administration.KeyVaultEkmConnectivityMode(str, Enum, metaclass=CaseInsensitiveEnumMeta): + PRIVATE_ENDPOINT = "PrivateEndpoint" + PUBLIC = "Public" + + + class azure.keyvault.administration.KeyVaultEkmPrivateEndpoint: + location: Union[str, None] + name: Union[str, None] + private_link_service_connection_state: Union[KeyVaultEkmPrivateEndpointConnectionState, None] + properties: Union[KeyVaultEkmPrivateEndpointProperties, None] + provisioning_state: Union[str, KeyVaultEkmPrivateEndpointProvisioningState, None] + + def __init__(self, **kwargs: Any) -> None: ... + + def __repr__(self) -> str: ... + + + class azure.keyvault.administration.KeyVaultEkmPrivateEndpointConnectionState: + actions_required: Union[str, None] + description: Union[str, None] + status: Union[str, KeyVaultEkmPrivateEndpointConnectionStatus, None] + + def __init__(self, **kwargs: Any) -> None: ... + + def __repr__(self) -> str: ... + + + class azure.keyvault.administration.KeyVaultEkmPrivateEndpointConnectionStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta): + APPROVED = "Approved" + DISCONNECTED = "Disconnected" + PENDING = "Pending" + REJECTED = "Rejected" + + + class azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperation: + end_time: Union[datetime, None] + error_code: Union[str, None] + error_message: Union[str, None] + job_id: Union[str, None] + operation_type: Union[str, KeyVaultEkmPrivateEndpointOperationType, None] + private_endpoint_name: Union[str, None] + start_time: Union[datetime, None] + status: Union[str, KeyVaultEkmPrivateEndpointOperationStatus, None] + status_details: Union[str, None] + + def __init__(self, **kwargs: Any) -> None: ... + + def __repr__(self) -> str: ... + + + class azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperationStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta): + CANCELED = "Canceled" + FAILED = "Failed" + NOT_STARTED = "NotStarted" + RUNNING = "Running" + SUCCEEDED = "Succeeded" + + + class azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperationType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + CREATE = "Create" + DELETE = "Delete" + + + class azure.keyvault.administration.KeyVaultEkmPrivateEndpointProperties: + private_link_service_connection_name: Union[str, None] + private_link_service_id: Union[str, None] + + def __init__(self, **kwargs: Any) -> None: ... + + def __repr__(self) -> str: ... + + + class azure.keyvault.administration.KeyVaultEkmPrivateEndpointProvisioningState(str, Enum, metaclass=CaseInsensitiveEnumMeta): + DELETING = "Deleting" + FAILED = "Failed" + SUCCEEDED = "Succeeded" + UPDATING = "Updating" + + class azure.keyvault.administration.KeyVaultEkmProxyClientCertificateInfo: ca_certificates: Union[list[bytes], None] subject_common_name: Union[str, None] @@ -675,6 +791,23 @@ namespace azure.keyvault.administration.aio **kwargs: Any ) -> None: ... + @distributed_trace_async + async def begin_create_ekm_private_endpoint( + self, + name: str, + private_link_service_id: str, + *, + request_message: Optional[str] = ..., + **kwargs: Any + ) -> AsyncLROPoller[KeyVaultEkmPrivateEndpointOperation]: ... + + @distributed_trace_async + async def begin_delete_ekm_private_endpoint( + self, + name: str, + **kwargs: Any + ) -> AsyncLROPoller[KeyVaultEkmPrivateEndpointOperation]: ... + @distributed_trace_async async def check_ekm_connection(self, **kwargs: Any) -> KeyVaultEkmProxyInfo: ... @@ -696,6 +829,23 @@ namespace azure.keyvault.administration.aio @distributed_trace_async async def get_ekm_connection(self, **kwargs: Any) -> KeyVaultEkmConnection: ... + @distributed_trace_async + async def get_ekm_private_endpoint( + self, + name: str, + **kwargs: Any + ) -> KeyVaultEkmPrivateEndpoint: ... + + @distributed_trace_async + async def get_ekm_private_endpoint_operation_status( + self, + job_id: str, + **kwargs: Any + ) -> KeyVaultEkmPrivateEndpointOperation: ... + + @distributed_trace + def list_ekm_private_endpoints(self, **kwargs: Any) -> AsyncItemPaged[KeyVaultEkmPrivateEndpoint]: ... + @distributed_trace_async def send_request( self, diff --git a/sdk/keyvault/azure-keyvault-administration/api.metadata.yml b/sdk/keyvault/azure-keyvault-administration/api.metadata.yml index 51c8b30dc86e..d95ae3ede0a1 100644 --- a/sdk/keyvault/azure-keyvault-administration/api.metadata.yml +++ b/sdk/keyvault/azure-keyvault-administration/api.metadata.yml @@ -1,3 +1,3 @@ -apiMdSha256: 85dc8ab302f592b946a6721db3fdc071a569e0d74fa9aae664ceef960665a0ec +apiMdSha256: a2d9996b6dbea7e5150105e13cd638d24ae423239c423a7bb69b247c061870a8 parserVersion: 0.3.28 pythonVersion: 3.13.14 diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/__init__.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/__init__.py index 71a878885286..cc6225bcaedd 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/__init__.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/__init__.py @@ -5,11 +5,24 @@ from ._access_control_client import KeyVaultAccessControlClient from ._backup_client import KeyVaultBackupClient from ._ekm_client import KeyVaultEkmClient -from ._enums import KeyVaultDataAction, KeyVaultRoleScope, KeyVaultSettingType +from ._enums import ( + KeyVaultDataAction, + KeyVaultEkmConnectivityMode, + KeyVaultEkmPrivateEndpointConnectionStatus, + KeyVaultEkmPrivateEndpointOperationStatus, + KeyVaultEkmPrivateEndpointOperationType, + KeyVaultEkmPrivateEndpointProvisioningState, + KeyVaultRoleScope, + KeyVaultSettingType, +) from ._internal.client_base import ApiVersion from ._models import ( KeyVaultBackupResult, KeyVaultEkmConnection, + KeyVaultEkmPrivateEndpoint, + KeyVaultEkmPrivateEndpointConnectionState, + KeyVaultEkmPrivateEndpointOperation, + KeyVaultEkmPrivateEndpointProperties, KeyVaultEkmProxyClientCertificateInfo, KeyVaultEkmProxyInfo, KeyVaultPermission, @@ -28,6 +41,15 @@ "KeyVaultDataAction", "KeyVaultEkmClient", "KeyVaultEkmConnection", + "KeyVaultEkmConnectivityMode", + "KeyVaultEkmPrivateEndpoint", + "KeyVaultEkmPrivateEndpointConnectionState", + "KeyVaultEkmPrivateEndpointConnectionStatus", + "KeyVaultEkmPrivateEndpointOperation", + "KeyVaultEkmPrivateEndpointOperationStatus", + "KeyVaultEkmPrivateEndpointOperationType", + "KeyVaultEkmPrivateEndpointProperties", + "KeyVaultEkmPrivateEndpointProvisioningState", "KeyVaultEkmProxyClientCertificateInfo", "KeyVaultEkmProxyInfo", "KeyVaultPermission", @@ -41,4 +63,5 @@ ] from ._version import VERSION + __version__ = VERSION diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_ekm_client.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_ekm_client.py index c3809d8f5506..6bf1422f90d8 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_ekm_client.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_ekm_client.py @@ -2,16 +2,25 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -from typing import Any +from typing import Any, Optional +from azure.core.paging import ItemPaged +from azure.core.polling import LROPoller from azure.core.tracing.decorator import distributed_trace +from ._generated.models import EkmPrivateEndpointCreateParameters from ._internal import KeyVaultClientBase -from ._models import KeyVaultEkmConnection, KeyVaultEkmProxyClientCertificateInfo, KeyVaultEkmProxyInfo +from ._models import ( + KeyVaultEkmConnection, + KeyVaultEkmPrivateEndpoint, + KeyVaultEkmPrivateEndpointOperation, + KeyVaultEkmProxyClientCertificateInfo, + KeyVaultEkmProxyInfo, +) class KeyVaultEkmClient(KeyVaultClientBase): - """Provides methods to manage Managed HSM External Key Manager (EKM) connections. + """Provides methods to manage Managed HSM External Key Manager (EKM) connections and private endpoints. :param str vault_url: URL of the vault on which the client will operate. This is also called the vault's "DNS Name". You should validate that this URL references a valid Key Vault or Managed HSM resource. @@ -21,7 +30,8 @@ class KeyVaultEkmClient(KeyVaultClientBase): :type credential: ~azure.core.credentials.TokenCredential :keyword api_version: Version of the service API to use. EKM operations require service API version - ``2026-01-01-preview`` or later. + ``2026-01-01-preview`` or later. EKM private endpoint operations require service API version + ``2026-07-01-preview`` or later. :paramtype api_version: ~azure.keyvault.administration.ApiVersion or str :keyword bool verify_challenge_resource: Whether to verify the authentication challenge resource matches the Key Vault or Managed HSM domain. Defaults to True. @@ -109,6 +119,106 @@ def check_ekm_connection(self, **kwargs: Any) -> KeyVaultEkmProxyInfo: result = self._client.check_ekm_connection(**kwargs) return KeyVaultEkmProxyInfo._from_generated(result) + @distributed_trace + def begin_create_ekm_private_endpoint( + self, name: str, private_link_service_id: str, *, request_message: Optional[str] = None, **kwargs: Any + ) -> LROPoller[KeyVaultEkmPrivateEndpointOperation]: + """Begins creating an EKM proxy private endpoint. + + A Managed HSM pool may have up to two EKM proxy private endpoints. + + :param str name: The name of the private endpoint to create. Must be 1-24 characters, start and end with an + alphanumeric character, and contain only alphanumeric characters and hyphens. + :param str private_link_service_id: Alias of the Private Link Service that the private endpoint connects to. + + :keyword request_message: An optional message shown to the Private Link Service owner when approving the + private endpoint connection. + :paramtype request_message: str or None + + :returns: An :class:`~azure.core.polling.LROPoller` instance. Call `result()` on this object to wait for the + operation to complete and get a :class:`KeyVaultEkmPrivateEndpointOperation`. + :rtype: + ~azure.core.polling.LROPoller[~azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + parameters = EkmPrivateEndpointCreateParameters( + private_link_service_id=private_link_service_id, request_message=request_message + ) + return self._client.begin_create_ekm_private_endpoint( + pe_name=name, + parameters=parameters, + cls=KeyVaultEkmPrivateEndpointOperation._from_polling_result, + **kwargs, + ) + + @distributed_trace + def begin_delete_ekm_private_endpoint( # pylint:disable=bad-option-value,delete-operation-wrong-return-type + self, name: str, **kwargs: Any + ) -> LROPoller[KeyVaultEkmPrivateEndpointOperation]: + """Begins deleting an EKM proxy private endpoint. + + The operation is rejected while an EKM connection still references the private endpoint. + + :param str name: The name of the private endpoint to delete. + + :returns: An :class:`~azure.core.polling.LROPoller` instance. Call `result()` on this object to wait for the + operation to complete and get a :class:`KeyVaultEkmPrivateEndpointOperation`. + :rtype: + ~azure.core.polling.LROPoller[~azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + return self._client.begin_delete_ekm_private_endpoint( + pe_name=name, cls=KeyVaultEkmPrivateEndpointOperation._from_polling_result, **kwargs + ) + + @distributed_trace + def get_ekm_private_endpoint(self, name: str, **kwargs: Any) -> KeyVaultEkmPrivateEndpoint: + """Gets an EKM proxy private endpoint. + + :param str name: The name of the private endpoint to get. + + :returns: The requested EKM proxy private endpoint. + :rtype: ~azure.keyvault.administration.KeyVaultEkmPrivateEndpoint + :raises ~azure.core.exceptions.HttpResponseError: + """ + result = self._client.get_ekm_private_endpoint(pe_name=name, **kwargs) + return KeyVaultEkmPrivateEndpoint._from_generated(result) + + @distributed_trace + def list_ekm_private_endpoints(self, **kwargs: Any) -> ItemPaged[KeyVaultEkmPrivateEndpoint]: + """Lists the EKM proxy private endpoints on the Managed HSM. + + :returns: A paged object containing the EKM proxy private endpoints. + :rtype: ~azure.core.paging.ItemPaged[~azure.keyvault.administration.KeyVaultEkmPrivateEndpoint] + :raises ~azure.core.exceptions.HttpResponseError: + """ + result = self._client.list_ekm_private_endpoints(**kwargs) + converted_result = [KeyVaultEkmPrivateEndpoint._from_generated(endpoint) for endpoint in result.value or []] + + # We don't actually get a paged response from the generated method, so we mock the typical iteration methods + def get_next(_=None): + return converted_result + + def extract_data(_): + return None, converted_result + + return ItemPaged(get_next, extract_data) + + @distributed_trace + def get_ekm_private_endpoint_operation_status( # pylint:disable=name-too-long + self, job_id: str, **kwargs: Any + ) -> KeyVaultEkmPrivateEndpointOperation: + """Gets the status of an EKM proxy private endpoint create or delete operation. + + :param str job_id: The identifier of the private endpoint operation. + + :returns: The status of the private endpoint operation. + :rtype: ~azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperation + :raises ~azure.core.exceptions.HttpResponseError: + """ + result = self._client.get_ekm_private_endpoint_operation_status(operation_id=job_id, **kwargs) + return KeyVaultEkmPrivateEndpointOperation._from_generated(result) + def __enter__(self) -> "KeyVaultEkmClient": self._client.__enter__() return self diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_enums.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_enums.py index 63e51e265e23..b773822ca8c3 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_enums.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_enums.py @@ -91,3 +91,68 @@ class KeyVaultSettingType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The type specifier of the setting value.""" BOOLEAN = "boolean" + + +class KeyVaultEkmConnectivityMode(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """The connectivity mode used to reach the EKM proxy.""" + + #: The EKM proxy is reachable over the public internet; the connection's host is a DNS name or IP address. + PUBLIC = "Public" + #: The EKM proxy is reachable through a private endpoint; the connection's host is the name of a private endpoint. + PRIVATE_ENDPOINT = "PrivateEndpoint" + + +class KeyVaultEkmPrivateEndpointProvisioningState( # pylint:disable=name-too-long + str, Enum, metaclass=CaseInsensitiveEnumMeta +): + """The provisioning state of an EKM proxy private endpoint.""" + + #: The private endpoint has been successfully provisioned. + SUCCEEDED = "Succeeded" + #: The private endpoint provisioning failed. + FAILED = "Failed" + #: The private endpoint is being updated. + UPDATING = "Updating" + #: The private endpoint is being deleted. + DELETING = "Deleting" + + +class KeyVaultEkmPrivateEndpointConnectionStatus( # pylint:disable=name-too-long + str, Enum, metaclass=CaseInsensitiveEnumMeta +): + """The status of the connection between an EKM proxy private endpoint and the Private Link Service.""" + + #: The connection is awaiting approval by the Private Link Service owner. + PENDING = "Pending" + #: The connection has been approved by the Private Link Service owner. + APPROVED = "Approved" + #: The connection has been rejected by the Private Link Service owner. + REJECTED = "Rejected" + #: The connection has been disconnected by the Private Link Service owner. + DISCONNECTED = "Disconnected" + + +class KeyVaultEkmPrivateEndpointOperationType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """The type of a long-running EKM proxy private endpoint operation.""" + + #: A private endpoint create operation. + CREATE = "Create" + #: A private endpoint delete operation. + DELETE = "Delete" + + +class KeyVaultEkmPrivateEndpointOperationStatus( # pylint:disable=name-too-long + str, Enum, metaclass=CaseInsensitiveEnumMeta +): + """The status of a long-running EKM proxy private endpoint operation.""" + + #: The operation has not started. + NOT_STARTED = "NotStarted" + #: The operation is in progress. + RUNNING = "Running" + #: The operation has completed successfully. + SUCCEEDED = "Succeeded" + #: The operation has failed. + FAILED = "Failed" + #: The operation has been canceled by the user. + CANCELED = "Canceled" diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_internal/client_base.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_internal/client_base.py index dcf10c5d27df..e92e36b9cdea 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_internal/client_base.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_internal/client_base.py @@ -24,6 +24,7 @@ class ApiVersion(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Key Vault API versions supported by this package""" #: this is the default version + V2026_07_01_PREVIEW = "2026-07-01-preview" V2026_01_01_PREVIEW = "2026-01-01-preview" V2025_07_01 = "2025-07-01" V7_6 = "7.6" @@ -33,7 +34,7 @@ class ApiVersion(str, Enum, metaclass=CaseInsensitiveEnumMeta): V7_2 = "7.2" -DEFAULT_VERSION = ApiVersion.V2026_01_01_PREVIEW +DEFAULT_VERSION = ApiVersion.V2026_07_01_PREVIEW _SERIALIZER = Serializer() _SERIALIZER.client_side_validation = False diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_models.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_models.py index ee2c1d8e5f59..3a719e4e4fe6 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_models.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_models.py @@ -2,13 +2,25 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +from datetime import datetime from typing import Any, Dict, List, Optional, Union from azure.core.rest import HttpResponse -from ._enums import KeyVaultSettingType +from ._enums import ( + KeyVaultEkmConnectivityMode, + KeyVaultEkmPrivateEndpointConnectionStatus, + KeyVaultEkmPrivateEndpointOperationStatus, + KeyVaultEkmPrivateEndpointOperationType, + KeyVaultEkmPrivateEndpointProvisioningState, + KeyVaultSettingType, +) from ._generated.models import ( EkmConnection, + EkmPrivateEndpoint, + EkmPrivateEndpointConnectionState, + EkmPrivateEndpointOperation, + EkmPrivateEndpointProperties, EkmProxyClientCertificateInfo, EkmProxyInfo, FullBackupOperation, @@ -252,6 +264,11 @@ class KeyVaultEkmConnection(object): :keyword str path_prefix: Optional path prefix for the EKM proxy (if any). :keyword str server_subject_common_name: The subject common name of the server certificate of the EKM proxy. + :keyword connectivity_mode: The connectivity mode used to reach the EKM proxy. Defaults to + ``KeyVaultEkmConnectivityMode.PUBLIC``. When set to + ``KeyVaultEkmConnectivityMode.PRIVATE_ENDPOINT``, ``host`` is the name of an EKM proxy + private endpoint instead of a DNS name or IP address. + :paramtype connectivity_mode: str or ~azure.keyvault.administration.KeyVaultEkmConnectivityMode or None :ivar str host: EKM proxy FQDN. :ivar list[bytes] server_ca_certificates: The root CA certificate chain that issued the proxy @@ -261,6 +278,8 @@ class KeyVaultEkmConnection(object): :ivar server_subject_common_name: The subject common name of the server certificate of the EKM proxy. :vartype server_subject_common_name: str or None + :ivar connectivity_mode: The connectivity mode used to reach the EKM proxy. + :vartype connectivity_mode: str or ~azure.keyvault.administration.KeyVaultEkmConnectivityMode or None """ def __init__( @@ -270,11 +289,13 @@ def __init__( *, path_prefix: Optional[str] = None, server_subject_common_name: Optional[str] = None, + connectivity_mode: Optional[Union[str, KeyVaultEkmConnectivityMode]] = None, ) -> None: self.host = host self.server_ca_certificates = server_ca_certificates self.path_prefix = path_prefix self.server_subject_common_name = server_subject_common_name + self.connectivity_mode = connectivity_mode def __repr__(self) -> str: return f"KeyVaultEkmConnection<{self.host}>" @@ -286,6 +307,7 @@ def _from_generated(cls, connection: EkmConnection) -> "KeyVaultEkmConnection": server_ca_certificates=connection.server_ca_certificates, path_prefix=connection.path_prefix, server_subject_common_name=connection.server_subject_common_name, + connectivity_mode=connection.connectivity_mode, ) def _to_generated(self) -> EkmConnection: @@ -294,6 +316,7 @@ def _to_generated(self) -> EkmConnection: server_ca_certificates=self.server_ca_certificates, path_prefix=self.path_prefix, server_subject_common_name=self.server_subject_common_name, + connectivity_mode=self.connectivity_mode, ) @@ -363,3 +386,174 @@ def _from_generated(cls, proxy_info: EkmProxyInfo) -> "KeyVaultEkmProxyInfo": ekm_vendor=proxy_info.ekm_vendor, ekm_product=proxy_info.ekm_product, ) + + +class KeyVaultEkmPrivateEndpointProperties(object): + """The properties of an EKM proxy private endpoint. + + :ivar private_link_service_id: Alias of the Private Link Service that the private endpoint connects to. + :vartype private_link_service_id: str or None + :ivar private_link_service_connection_name: The name of the private link service connection, generated by the + service. + :vartype private_link_service_connection_name: str or None + """ + + def __init__(self, **kwargs: Any) -> None: + self.private_link_service_id: Optional[str] = kwargs.get("private_link_service_id") + self.private_link_service_connection_name: Optional[str] = kwargs.get("private_link_service_connection_name") + + def __repr__(self) -> str: + return f"KeyVaultEkmPrivateEndpointProperties<{self.private_link_service_id}>" + + @classmethod + def _from_generated(cls, properties: EkmPrivateEndpointProperties) -> "KeyVaultEkmPrivateEndpointProperties": + return cls( + private_link_service_id=properties.private_link_service_id, + private_link_service_connection_name=properties.private_link_service_connection_name, + ) + + +class KeyVaultEkmPrivateEndpointConnectionState(object): # pylint:disable=name-too-long + """The state of the connection between an EKM proxy private endpoint and the Private Link Service. + + :ivar status: The status of the private link service connection. + :vartype status: str or ~azure.keyvault.administration.KeyVaultEkmPrivateEndpointConnectionStatus or None + :ivar description: A description of the current connection state. + :vartype description: str or None + :ivar actions_required: Any actions required from the customer to maintain the connection. + :vartype actions_required: str or None + """ + + def __init__(self, **kwargs: Any) -> None: + self.status: Optional[Union[str, KeyVaultEkmPrivateEndpointConnectionStatus]] = kwargs.get("status") + self.description: Optional[str] = kwargs.get("description") + self.actions_required: Optional[str] = kwargs.get("actions_required") + + def __repr__(self) -> str: + return f"KeyVaultEkmPrivateEndpointConnectionState<{self.status}>" + + @classmethod + def _from_generated( + cls, connection_state: EkmPrivateEndpointConnectionState + ) -> "KeyVaultEkmPrivateEndpointConnectionState": + return cls( + status=connection_state.status, + description=connection_state.description, + actions_required=connection_state.actions_required, + ) + + +class KeyVaultEkmPrivateEndpoint(object): + """An EKM proxy private endpoint. + + :ivar name: The name of the private endpoint. + :vartype name: str or None + :ivar location: The Azure region where the private endpoint is provisioned. + :vartype location: str or None + :ivar provisioning_state: The provisioning state of the private endpoint. + :vartype provisioning_state: str or + ~azure.keyvault.administration.KeyVaultEkmPrivateEndpointProvisioningState or None + :ivar properties: The properties of the private endpoint. + :vartype properties: ~azure.keyvault.administration.KeyVaultEkmPrivateEndpointProperties or None + :ivar private_link_service_connection_state: The state of the connection between the private endpoint and the + Private Link Service. + :vartype private_link_service_connection_state: + ~azure.keyvault.administration.KeyVaultEkmPrivateEndpointConnectionState or None + """ + + def __init__(self, **kwargs: Any) -> None: + self.name: Optional[str] = kwargs.get("name") + self.location: Optional[str] = kwargs.get("location") + self.provisioning_state: Optional[Union[str, KeyVaultEkmPrivateEndpointProvisioningState]] = kwargs.get( + "provisioning_state" + ) + self.properties: Optional[KeyVaultEkmPrivateEndpointProperties] = kwargs.get("properties") + self.private_link_service_connection_state: Optional[KeyVaultEkmPrivateEndpointConnectionState] = kwargs.get( + "private_link_service_connection_state" + ) + + def __repr__(self) -> str: + return f"KeyVaultEkmPrivateEndpoint<{self.name}>" + + @classmethod + def _from_generated(cls, private_endpoint: EkmPrivateEndpoint) -> "KeyVaultEkmPrivateEndpoint": + # pylint:disable=protected-access + return cls( + name=private_endpoint.name, + location=private_endpoint.location, + provisioning_state=private_endpoint.provisioning_state, + properties=( + KeyVaultEkmPrivateEndpointProperties._from_generated(private_endpoint.properties) + if private_endpoint.properties + else None + ), + private_link_service_connection_state=( + KeyVaultEkmPrivateEndpointConnectionState._from_generated( + private_endpoint.private_link_service_connection_state + ) + if private_endpoint.private_link_service_connection_state + else None + ), + ) + + +class KeyVaultEkmPrivateEndpointOperation(object): + """A long-running operation on an EKM proxy private endpoint. + + :ivar job_id: Identifier for the private endpoint operation. + :vartype job_id: str or None + :ivar private_endpoint_name: The name of the private endpoint the operation applies to. + :vartype private_endpoint_name: str or None + :ivar operation_type: The type of the operation. + :vartype operation_type: str or ~azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperationType or None + :ivar status: The status of the operation. + :vartype status: str or ~azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperationStatus or None + :ivar status_details: The status details of the operation. + :vartype status_details: str or None + :ivar start_time: The start time of the operation, in UTC. + :vartype start_time: ~datetime.datetime or None + :ivar end_time: The end time of the operation, in UTC. + :vartype end_time: ~datetime.datetime or None + :ivar error_code: The code of the error encountered, if any, during the operation. + :vartype error_code: str or None + :ivar error_message: The message of the error encountered, if any, during the operation. + :vartype error_message: str or None + """ + + # pylint:disable=unused-argument + + def __init__(self, **kwargs: Any) -> None: + self.job_id: Optional[str] = kwargs.get("job_id") + self.private_endpoint_name: Optional[str] = kwargs.get("private_endpoint_name") + self.operation_type: Optional[Union[str, KeyVaultEkmPrivateEndpointOperationType]] = kwargs.get( + "operation_type" + ) + self.status: Optional[Union[str, KeyVaultEkmPrivateEndpointOperationStatus]] = kwargs.get("status") + self.status_details: Optional[str] = kwargs.get("status_details") + self.start_time: Optional[datetime] = kwargs.get("start_time") + self.end_time: Optional[datetime] = kwargs.get("end_time") + self.error_code: Optional[str] = kwargs.get("error_code") + self.error_message: Optional[str] = kwargs.get("error_message") + + def __repr__(self) -> str: + return f"KeyVaultEkmPrivateEndpointOperation<{self.private_endpoint_name}>" + + @classmethod + def _from_generated(cls, operation: EkmPrivateEndpointOperation) -> "KeyVaultEkmPrivateEndpointOperation": + return cls( + job_id=operation.job_id, + private_endpoint_name=operation.private_endpoint_name, + operation_type=operation.operation_type, + status=operation.status, + status_details=operation.status_details, + start_time=operation.start_time, + end_time=operation.end_time, + error_code=operation.error.code if operation.error else None, + error_message=operation.error.message if operation.error else None, + ) + + @classmethod + def _from_polling_result( + cls, response: HttpResponse, deserialized_operation: EkmPrivateEndpointOperation, response_headers: Dict + ) -> "KeyVaultEkmPrivateEndpointOperation": + return cls._from_generated(deserialized_operation) diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/aio/_ekm_client.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/aio/_ekm_client.py index 66b093c9fc13..483a2fa0e4bb 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/aio/_ekm_client.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/aio/_ekm_client.py @@ -2,16 +2,26 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -from typing import Any +from typing import Any, Optional +from azure.core.async_paging import AsyncItemPaged, AsyncList +from azure.core.polling import AsyncLROPoller +from azure.core.tracing.decorator import distributed_trace from azure.core.tracing.decorator_async import distributed_trace_async +from .._generated.models import EkmPrivateEndpointCreateParameters from .._internal import AsyncKeyVaultClientBase -from .._models import KeyVaultEkmConnection, KeyVaultEkmProxyClientCertificateInfo, KeyVaultEkmProxyInfo +from .._models import ( + KeyVaultEkmConnection, + KeyVaultEkmPrivateEndpoint, + KeyVaultEkmPrivateEndpointOperation, + KeyVaultEkmProxyClientCertificateInfo, + KeyVaultEkmProxyInfo, +) class KeyVaultEkmClient(AsyncKeyVaultClientBase): - """Provides methods to manage Managed HSM External Key Manager (EKM) connections. + """Provides methods to manage Managed HSM External Key Manager (EKM) connections and private endpoints. :param str vault_url: URL of the vault on which the client will operate. This is also called the vault's "DNS Name". You should validate that this URL references a valid Key Vault or Managed HSM resource. @@ -21,7 +31,8 @@ class KeyVaultEkmClient(AsyncKeyVaultClientBase): :type credential: ~azure.core.credentials_async.AsyncTokenCredential :keyword api_version: Version of the service API to use. EKM operations require service API version - ``2026-01-01-preview`` or later. + ``2026-01-01-preview`` or later. EKM private endpoint operations require service API version + ``2026-07-01-preview`` or later. :paramtype api_version: ~azure.keyvault.administration.ApiVersion or str :keyword bool verify_challenge_resource: Whether to verify the authentication challenge resource matches the Key Vault or Managed HSM domain. Defaults to True. @@ -109,6 +120,109 @@ async def check_ekm_connection(self, **kwargs: Any) -> KeyVaultEkmProxyInfo: result = await self._client.check_ekm_connection(**kwargs) return KeyVaultEkmProxyInfo._from_generated(result) + @distributed_trace_async + async def begin_create_ekm_private_endpoint( + self, name: str, private_link_service_id: str, *, request_message: Optional[str] = None, **kwargs: Any + ) -> AsyncLROPoller[KeyVaultEkmPrivateEndpointOperation]: + """Begins creating an EKM proxy private endpoint. + + A Managed HSM pool may have up to two EKM proxy private endpoints. + + :param str name: The name of the private endpoint to create. Must be 1-24 characters, start and end with an + alphanumeric character, and contain only alphanumeric characters and hyphens. + :param str private_link_service_id: Alias of the Private Link Service that the private endpoint connects to. + + :keyword request_message: An optional message shown to the Private Link Service owner when approving the + private endpoint connection. + :paramtype request_message: str or None + + :returns: An :class:`~azure.core.polling.AsyncLROPoller` instance. Call `result()` on this object to wait for + the operation to complete and get a :class:`KeyVaultEkmPrivateEndpointOperation`. + :rtype: + ~azure.core.polling.AsyncLROPoller[~azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + parameters = EkmPrivateEndpointCreateParameters( + private_link_service_id=private_link_service_id, request_message=request_message + ) + return await self._client.begin_create_ekm_private_endpoint( + pe_name=name, + parameters=parameters, + cls=KeyVaultEkmPrivateEndpointOperation._from_polling_result, + **kwargs, + ) + + @distributed_trace_async + async def begin_delete_ekm_private_endpoint( # pylint:disable=bad-option-value,delete-operation-wrong-return-type + self, name: str, **kwargs: Any + ) -> AsyncLROPoller[KeyVaultEkmPrivateEndpointOperation]: + """Begins deleting an EKM proxy private endpoint. + + The operation is rejected while an EKM connection still references the private endpoint. + + :param str name: The name of the private endpoint to delete. + + :returns: An :class:`~azure.core.polling.AsyncLROPoller` instance. Call `result()` on this object to wait for + the operation to complete and get a :class:`KeyVaultEkmPrivateEndpointOperation`. + :rtype: + ~azure.core.polling.AsyncLROPoller[~azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + return await self._client.begin_delete_ekm_private_endpoint( + pe_name=name, cls=KeyVaultEkmPrivateEndpointOperation._from_polling_result, **kwargs + ) + + @distributed_trace_async + async def get_ekm_private_endpoint(self, name: str, **kwargs: Any) -> KeyVaultEkmPrivateEndpoint: + """Gets an EKM proxy private endpoint. + + :param str name: The name of the private endpoint to get. + + :returns: The requested EKM proxy private endpoint. + :rtype: ~azure.keyvault.administration.KeyVaultEkmPrivateEndpoint + :raises ~azure.core.exceptions.HttpResponseError: + """ + result = await self._client.get_ekm_private_endpoint(pe_name=name, **kwargs) + return KeyVaultEkmPrivateEndpoint._from_generated(result) + + @distributed_trace + def list_ekm_private_endpoints(self, **kwargs: Any) -> AsyncItemPaged[KeyVaultEkmPrivateEndpoint]: + """Lists the EKM proxy private endpoints on the Managed HSM. + + :returns: A paged object containing the EKM proxy private endpoints. + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.keyvault.administration.KeyVaultEkmPrivateEndpoint] + :raises ~azure.core.exceptions.HttpResponseError: + """ + result = self._client.list_ekm_private_endpoints(**kwargs) + + # We don't actually get a paged response from the generated method, so we mock the typical iteration methods + async def get_next(_=None): + # There's only one page of results, so we return the awaited result directly + return await result + + async def extract_data(list_result): + converted_result = [ + KeyVaultEkmPrivateEndpoint._from_generated(endpoint) for endpoint in list_result.value or [] + ] + return None, AsyncList(converted_result) + + return AsyncItemPaged(get_next, extract_data) + + @distributed_trace_async + async def get_ekm_private_endpoint_operation_status( # pylint:disable=name-too-long + self, job_id: str, **kwargs: Any + ) -> KeyVaultEkmPrivateEndpointOperation: + """Gets the status of an EKM proxy private endpoint create or delete operation. + + :param str job_id: The identifier of the private endpoint operation. + + :returns: The status of the private endpoint operation. + :rtype: ~azure.keyvault.administration.KeyVaultEkmPrivateEndpointOperation + :raises ~azure.core.exceptions.HttpResponseError: + """ + result = await self._client.get_ekm_private_endpoint_operation_status(operation_id=job_id, **kwargs) + return KeyVaultEkmPrivateEndpointOperation._from_generated(result) + async def __aenter__(self) -> "KeyVaultEkmClient": await self._client.__aenter__() return self diff --git a/sdk/keyvault/azure-keyvault-administration/samples/README.md b/sdk/keyvault/azure-keyvault-administration/samples/README.md index a28cc5af7d34..e7f56e8ab442 100644 --- a/sdk/keyvault/azure-keyvault-administration/samples/README.md +++ b/sdk/keyvault/azure-keyvault-administration/samples/README.md @@ -37,6 +37,10 @@ pip install azure-keyvault-administration azure-identity | [backup_restore_operations_async.py][backup_operations_async_sample] | full backup and restore with an async client | | [settings_operations.py][settings_operations_sample] | list and update Key Vault settings | | [settings_operations_async.py][settings_operations_async_sample] | list and update Key Vault settings with an async client | +| [ekm_operations.py][ekm_operations_sample] | create/update/delete EKM connections | +| [ekm_operations_async.py][ekm_operations_async_sample] | create/update/delete EKM connections with an async client | +| [ekm_private_endpoint_operations.py][ekm_private_endpoint_operations_sample] | create/get/list/delete EKM proxy private endpoints | +| [ekm_private_endpoint_operations_async.py][ekm_private_endpoint_operations_async_sample] | create/get/list/delete EKM proxy private endpoints with an async client | [access_control_operations_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/access_control_operations.py [access_control_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/access_control_operations_async.py @@ -44,3 +48,7 @@ pip install azure-keyvault-administration azure-identity [backup_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/backup_restore_operations_async.py [settings_operations_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/settings_operations.py [settings_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/settings_operations_async.py +[ekm_operations_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/ekm_operations.py +[ekm_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/ekm_operations_async.py +[ekm_private_endpoint_operations_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations.py +[ekm_private_endpoint_operations_async_sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations_async.py diff --git a/sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations.py b/sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations.py new file mode 100644 index 000000000000..b82018b887e6 --- /dev/null +++ b/sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations.py @@ -0,0 +1,108 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import os + +# ---------------------------------------------------------------------------------------------------------- +# Prerequisites: +# 1. A managed HSM (https://learn.microsoft.com/azure/key-vault/managed-hsm/quick-create-cli) +# +# 2. azure-keyvault-administration and azure-identity libraries (pip install these) +# +# 3. Set environment variable MANAGED_HSM_URL with the URL of your managed HSM, and PRIVATE_LINK_SERVICE_ID with the +# alias of the Private Link Service that fronts your EKM proxy. +# +# 4. Set up your environment to use azure-identity's DefaultAzureCredential. For more information about how to configure +# the DefaultAzureCredential, refer to https://aka.ms/azsdk/python/identity/docs#azure.identity.DefaultAzureCredential +# +# 5. A Private Link Service that fronts an EKM (External Key Manager) proxy. A Managed HSM pool may have up to two EKM +# proxy private endpoints. +# +# ---------------------------------------------------------------------------------------------------------- +# Sample - demonstrates Managed HSM External Key Manager (EKM) proxy private endpoint management +# +# 1. Create an EKM proxy private endpoint (begin_create_ekm_private_endpoint) +# +# 2. Read the EKM proxy private endpoint (get_ekm_private_endpoint) +# +# 3. List the EKM proxy private endpoints (list_ekm_private_endpoints) +# +# 4. Connect to the EKM proxy through the private endpoint (create_ekm_connection) +# +# 5. Delete the EKM proxy private endpoint (begin_delete_ekm_private_endpoint) +# ---------------------------------------------------------------------------------------------------------- + +# Instantiate an EKM client that will be used to call the service. +# Here we use the DefaultAzureCredential, but any azure-identity credential can be used. +from azure.identity import DefaultAzureCredential +from azure.keyvault.administration import KeyVaultEkmClient + +MANAGED_HSM_URL = os.environ["MANAGED_HSM_URL"] +PRIVATE_LINK_SERVICE_ID = os.environ["PRIVATE_LINK_SERVICE_ID"] +credential = DefaultAzureCredential() +client = KeyVaultEkmClient(vault_url=MANAGED_HSM_URL, credential=credential) + +PRIVATE_ENDPOINT_NAME = "ekm-proxy-pe" + +# First, let's create an EKM proxy private endpoint. This is a long-running operation. +print("\n.. Create EKM private endpoint") +# [START begin_create_ekm_private_endpoint] +create_poller = client.begin_create_ekm_private_endpoint( + PRIVATE_ENDPOINT_NAME, + PRIVATE_LINK_SERVICE_ID, + request_message="Please approve this connection from my Managed HSM", +) +create_operation = create_poller.result() +print(f"EKM private endpoint creation finished with status: {create_operation.status}") +# [END begin_create_ekm_private_endpoint] + +# Let's get the private endpoint we just created. The Private Link Service owner has to approve the connection +# before the private endpoint can be used by an EKM connection. +print("\n.. Get EKM private endpoint") +# [START get_ekm_private_endpoint] +private_endpoint = client.get_ekm_private_endpoint(PRIVATE_ENDPOINT_NAME) +print("Retrieved EKM private endpoint with:") +print(f"\tName: {private_endpoint.name}") +print(f"\tLocation: {private_endpoint.location}") +print(f"\tProvisioning state: {private_endpoint.provisioning_state}") +if private_endpoint.private_link_service_connection_state: + print(f"\tConnection status: {private_endpoint.private_link_service_connection_state.status}") +# [END get_ekm_private_endpoint] + +# Let's list all of the private endpoints on the Managed HSM +print("\n.. List EKM private endpoints") +# [START list_ekm_private_endpoints] +private_endpoints = client.list_ekm_private_endpoints() +for endpoint in private_endpoints: + print(f"EKM private endpoint {endpoint.name} is in state {endpoint.provisioning_state}") +# [END list_ekm_private_endpoints] + +# Once the connection is approved, an EKM connection can reach the EKM proxy through the private endpoint. To do so, +# set the connection's `host` to the private endpoint's name and its `connectivity_mode` to `PRIVATE_ENDPOINT`. +print("\n.. Create EKM connection over the private endpoint") +# [START create_private_ekm_connection] +import base64 +from azure.keyvault.administration import KeyVaultEkmConnection, KeyVaultEkmConnectivityMode + +CA_CERTIFICATE = os.environ["CA_CERTIFICATE"] +ekm_connection = KeyVaultEkmConnection( + host=PRIVATE_ENDPOINT_NAME, + server_ca_certificates=[base64.b64decode(CA_CERTIFICATE)], + path_prefix="/api/v1", + connectivity_mode=KeyVaultEkmConnectivityMode.PRIVATE_ENDPOINT, +) +created_ekm_connection = client.create_ekm_connection(connection=ekm_connection) +print(f"EKM connection created with connectivity mode: {created_ekm_connection.connectivity_mode}") +# [END create_private_ekm_connection] + +# Finally, let's delete the private endpoint. Deletion is rejected while an EKM connection still references the +# private endpoint, so we delete the EKM connection first. +print("\n.. Delete EKM private endpoint") +# [START begin_delete_ekm_private_endpoint] +client.delete_ekm_connection() +delete_poller = client.begin_delete_ekm_private_endpoint(PRIVATE_ENDPOINT_NAME) +delete_operation = delete_poller.result() +print(f"EKM private endpoint deletion finished with status: {delete_operation.status}") +# [END begin_delete_ekm_private_endpoint] diff --git a/sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations_async.py b/sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations_async.py new file mode 100644 index 000000000000..6549e02bd18e --- /dev/null +++ b/sdk/keyvault/azure-keyvault-administration/samples/ekm_private_endpoint_operations_async.py @@ -0,0 +1,107 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import asyncio +import base64 +import os + +from azure.identity.aio import DefaultAzureCredential +from azure.keyvault.administration import KeyVaultEkmConnection, KeyVaultEkmConnectivityMode +from azure.keyvault.administration.aio import KeyVaultEkmClient + +# ---------------------------------------------------------------------------------------------------------- +# Prerequisites: +# 1. A managed HSM (https://learn.microsoft.com/azure/key-vault/managed-hsm/quick-create-cli) +# +# 2. azure-keyvault-administration and azure-identity libraries (pip install these) +# +# 3. Set environment variable MANAGED_HSM_URL with the URL of your managed HSM, and PRIVATE_LINK_SERVICE_ID with the +# alias of the Private Link Service that fronts your EKM proxy. +# +# 4. Set up your environment to use azure-identity's DefaultAzureCredential. For more information about how to configure +# the DefaultAzureCredential, refer to https://aka.ms/azsdk/python/identity/docs#azure.identity.DefaultAzureCredential +# +# 5. A Private Link Service that fronts an EKM (External Key Manager) proxy. A Managed HSM pool may have up to two EKM +# proxy private endpoints. +# +# ---------------------------------------------------------------------------------------------------------- +# Sample - demonstrates Managed HSM External Key Manager (EKM) proxy private endpoint management +# +# 1. Create an EKM proxy private endpoint (begin_create_ekm_private_endpoint) +# +# 2. Read the EKM proxy private endpoint (get_ekm_private_endpoint) +# +# 3. List the EKM proxy private endpoints (list_ekm_private_endpoints) +# +# 4. Connect to the EKM proxy through the private endpoint (create_ekm_connection) +# +# 5. Delete the EKM proxy private endpoint (begin_delete_ekm_private_endpoint) +# ---------------------------------------------------------------------------------------------------------- + +PRIVATE_ENDPOINT_NAME = "ekm-proxy-pe" + + +async def run_sample(): + # Instantiate an EKM client that will be used to call the service. + # Here we use the DefaultAzureCredential, but any azure-identity credential can be used. + MANAGED_HSM_URL = os.environ["MANAGED_HSM_URL"] + PRIVATE_LINK_SERVICE_ID = os.environ["PRIVATE_LINK_SERVICE_ID"] + credential = DefaultAzureCredential() + client = KeyVaultEkmClient(vault_url=MANAGED_HSM_URL, credential=credential) + + # First, let's create an EKM proxy private endpoint. This is a long-running operation. + print("\n.. Create EKM private endpoint") + create_poller = await client.begin_create_ekm_private_endpoint( + PRIVATE_ENDPOINT_NAME, + PRIVATE_LINK_SERVICE_ID, + request_message="Please approve this connection from my Managed HSM", + ) + create_operation = await create_poller.result() + print(f"EKM private endpoint creation finished with status: {create_operation.status}") + + # Let's get the private endpoint we just created. The Private Link Service owner has to approve the connection + # before the private endpoint can be used by an EKM connection. + print("\n.. Get EKM private endpoint") + private_endpoint = await client.get_ekm_private_endpoint(PRIVATE_ENDPOINT_NAME) + print("Retrieved EKM private endpoint with:") + print(f"\tName: {private_endpoint.name}") + print(f"\tLocation: {private_endpoint.location}") + print(f"\tProvisioning state: {private_endpoint.provisioning_state}") + if private_endpoint.private_link_service_connection_state: + print(f"\tConnection status: {private_endpoint.private_link_service_connection_state.status}") + + # Let's list all of the private endpoints on the Managed HSM + print("\n.. List EKM private endpoints") + private_endpoints = client.list_ekm_private_endpoints() + async for endpoint in private_endpoints: + print(f"EKM private endpoint {endpoint.name} is in state {endpoint.provisioning_state}") + + # Once the connection is approved, an EKM connection can reach the EKM proxy through the private endpoint. To do + # so, set the connection's `host` to the private endpoint's name and its `connectivity_mode` to `PRIVATE_ENDPOINT`. + print("\n.. Create EKM connection over the private endpoint") + CA_CERTIFICATE = os.environ["CA_CERTIFICATE"] + ekm_connection = KeyVaultEkmConnection( + host=PRIVATE_ENDPOINT_NAME, + server_ca_certificates=[base64.b64decode(CA_CERTIFICATE)], + path_prefix="/api/v1", + connectivity_mode=KeyVaultEkmConnectivityMode.PRIVATE_ENDPOINT, + ) + created_ekm_connection = await client.create_ekm_connection(connection=ekm_connection) + print(f"EKM connection created with connectivity mode: {created_ekm_connection.connectivity_mode}") + + # Finally, let's delete the private endpoint. Deletion is rejected while an EKM connection still references the + # private endpoint, so we delete the EKM connection first. + print("\n.. Delete EKM private endpoint") + await client.delete_ekm_connection() + delete_poller = await client.begin_delete_ekm_private_endpoint(PRIVATE_ENDPOINT_NAME) + delete_operation = await delete_poller.result() + print(f"EKM private endpoint deletion finished with status: {delete_operation.status}") + + await client.close() + await credential.close() + + +if __name__ == "__main__": + asyncio.run(run_sample()) diff --git a/sdk/keyvault/azure-keyvault-administration/tests/_async_test_case.py b/sdk/keyvault/azure-keyvault-administration/tests/_async_test_case.py index 145e316a9a7e..455ca4be384b 100644 --- a/sdk/keyvault/azure-keyvault-administration/tests/_async_test_case.py +++ b/sdk/keyvault/azure-keyvault-administration/tests/_async_test_case.py @@ -16,6 +16,7 @@ def __init__(self, **kwargs) -> None: playback_sas_token = "fake-sas" playback_ekm_host = "fake-ekm-host" playback_ekm_certificate = "ZmFrZS1jZXJ0LWRhdGE=" + playback_private_link_service_id = "fake-private-link-service-id" if self.is_live: hsm = os.environ.get("AZURE_MANAGEDHSM_URL") @@ -27,6 +28,7 @@ def __init__(self, **kwargs) -> None: self.sas_token = os.environ.get("BLOB_STORAGE_SAS_TOKEN") self.ekm_host = os.environ.get("EKM_PROXY_HOST") self.ekm_certificate = os.environ.get("EKM_SERVER_CA_CERTIFICATE") + self.private_link_service_id = os.environ.get("EKM_PRIVATE_LINK_SERVICE_ID") else: self.managed_hsm_url = hsm_playback_url @@ -34,6 +36,7 @@ def __init__(self, **kwargs) -> None: self.sas_token = playback_sas_token self.ekm_host = playback_ekm_host self.ekm_certificate = playback_ekm_certificate + self.private_link_service_id = playback_private_link_service_id use_pwsh = os.environ.get("AZURE_TEST_USE_PWSH_AUTH", "false") use_cli = os.environ.get("AZURE_TEST_USE_CLI_AUTH", "false") @@ -147,6 +150,7 @@ async def _preparer(test_class, api_version, **kwargs): self._skip_if_not_configured(api_version) kwargs["ekm_host"] = self.ekm_host kwargs["ekm_certificate"] = self.ekm_certificate + kwargs["private_link_service_id"] = self.private_link_service_id client = self.create_ekm_client(api_version=api_version, **kwargs) async with client: diff --git a/sdk/keyvault/azure-keyvault-administration/tests/_test_case.py b/sdk/keyvault/azure-keyvault-administration/tests/_test_case.py index 5565d2c40ec6..c53fb41c6015 100644 --- a/sdk/keyvault/azure-keyvault-administration/tests/_test_case.py +++ b/sdk/keyvault/azure-keyvault-administration/tests/_test_case.py @@ -18,6 +18,7 @@ def __init__(self, **kwargs) -> None: playback_sas_token = "fake-sas" playback_ekm_host = "fake-ekm-host" playback_server_ca_certificate = "ZmFrZS1jZXJ0LWRhdGE=" + playback_private_link_service_id = "fake-private-link-service-id" if self.is_live: hsm = os.environ.get("AZURE_MANAGEDHSM_URL") @@ -29,6 +30,7 @@ def __init__(self, **kwargs) -> None: self.sas_token = os.environ.get("BLOB_STORAGE_SAS_TOKEN") self.ekm_host = os.environ.get("EKM_PROXY_HOST") self.ekm_certificate = os.environ.get("EKM_SERVER_CA_CERTIFICATE") + self.private_link_service_id = os.environ.get("EKM_PRIVATE_LINK_SERVICE_ID") else: self.managed_hsm_url = hsm_playback_url @@ -36,6 +38,7 @@ def __init__(self, **kwargs) -> None: self.sas_token = playback_sas_token self.ekm_host = playback_ekm_host self.ekm_certificate = playback_server_ca_certificate + self.private_link_service_id = playback_private_link_service_id use_pwsh = os.environ.get("AZURE_TEST_USE_PWSH_AUTH", "false") use_cli = os.environ.get("AZURE_TEST_USE_CLI_AUTH", "false") @@ -164,6 +167,7 @@ def _preparer(test_class, api_version, **kwargs): self._skip_if_not_configured(api_version) kwargs["ekm_host"] = self.ekm_host kwargs["ekm_certificate"] = self.ekm_certificate + kwargs["private_link_service_id"] = self.private_link_service_id client = self.create_ekm_client(api_version=api_version, **kwargs) with client: diff --git a/sdk/keyvault/azure-keyvault-administration/tests/conftest.py b/sdk/keyvault/azure-keyvault-administration/tests/conftest.py index 2e5906a3392c..e57252ad70a9 100644 --- a/sdk/keyvault/azure-keyvault-administration/tests/conftest.py +++ b/sdk/keyvault/azure-keyvault-administration/tests/conftest.py @@ -36,6 +36,7 @@ def add_sanitizers(test_proxy): sas_token = os.environ.get("BLOB_STORAGE_SAS_TOKEN", "fake-sas") ekm_host = os.environ.get("EKM_PROXY_HOST", "fake-ekm-host") ekm_certificate = os.environ.get("EKM_SERVER_CA_CERTIFICATE", "ZmFrZS1jZXJ0LWRhdGE=") + private_link_service_id = os.environ.get("EKM_PRIVATE_LINK_SERVICE_ID", "fake-private-link-service-id") add_general_string_sanitizer(target=azure_keyvault_url, value="https://Sanitized.vault.azure.net") add_general_string_sanitizer(target=keyvault_tenant_id, value="00000000-0000-0000-0000-000000000000") @@ -46,6 +47,7 @@ def add_sanitizers(test_proxy): add_general_string_sanitizer(target=sas_token, value="fake-sas") add_general_string_sanitizer(target=ekm_host, value="fake-ekm-host") add_general_string_sanitizer(target=ekm_certificate, value="ZmFrZS1jZXJ0LWRhdGE=") + add_general_string_sanitizer(target=private_link_service_id, value="fake-private-link-service-id") add_general_string_sanitizer(target=client_id, value="service-principal-id") # Sanitize API versions of `azure-keyvault-keys` requests add_uri_regex_sanitizer( diff --git a/sdk/keyvault/azure-keyvault-administration/tests/test_ekm_client.py b/sdk/keyvault/azure-keyvault-administration/tests/test_ekm_client.py index 422de669ad29..636a5fd1ef7d 100644 --- a/sdk/keyvault/azure-keyvault-administration/tests/test_ekm_client.py +++ b/sdk/keyvault/azure-keyvault-administration/tests/test_ekm_client.py @@ -8,7 +8,12 @@ import pytest from azure.core.exceptions import HttpResponseError -from azure.keyvault.administration import KeyVaultEkmClient, KeyVaultEkmConnection +from azure.keyvault.administration import ( + KeyVaultEkmClient, + KeyVaultEkmConnection, + KeyVaultEkmPrivateEndpointOperationStatus, + KeyVaultEkmPrivateEndpointOperationType, +) from azure.keyvault.administration._internal.client_base import DEFAULT_VERSION from devtools_testutils import recorded_by_proxy @@ -99,3 +104,56 @@ def test_ekm_connection(self, client: KeyVaultEkmClient, **kwargs): assert len(result.server_ca_certificates) == 1 assert result.path_prefix == updated_ekm_connection.path_prefix assert result.server_subject_common_name == updated_ekm_connection.server_subject_common_name + + @pytest.mark.parametrize("api_version", only_latest) + @KeyVaultEkmClientPreparer() + @recorded_by_proxy + def test_ekm_private_endpoint(self, client: KeyVaultEkmClient, **kwargs): + private_link_service_id = kwargs.pop("private_link_service_id") + if not private_link_service_id: + pytest.skip( + "An EKM Private Link Service is required for live tests. Please set the EKM_PRIVATE_LINK_SERVICE_ID environment variable." + ) + private_endpoint_name = self.get_resource_name("ekm-pe") + + # Cleanup + try: + client.begin_delete_ekm_private_endpoint(private_endpoint_name).wait() + except HttpResponseError: + pass + + # Create a private endpoint + create_operation = client.begin_create_ekm_private_endpoint( + private_endpoint_name, private_link_service_id, request_message="Please approve" + ).result() + assert create_operation is not None + assert create_operation.private_endpoint_name == private_endpoint_name + assert create_operation.operation_type == KeyVaultEkmPrivateEndpointOperationType.CREATE + assert create_operation.status == KeyVaultEkmPrivateEndpointOperationStatus.SUCCEEDED + + # Get the private endpoint + private_endpoint = client.get_ekm_private_endpoint(private_endpoint_name) + assert private_endpoint is not None + assert private_endpoint.name == private_endpoint_name + assert private_endpoint.provisioning_state is not None + assert private_endpoint.properties is not None + assert private_endpoint.properties.private_link_service_id == private_link_service_id + assert private_endpoint.private_link_service_connection_state is not None + assert private_endpoint.private_link_service_connection_state.status is not None + + # List the private endpoints + private_endpoints = list(client.list_ekm_private_endpoints()) + assert any(endpoint.name == private_endpoint_name for endpoint in private_endpoints) + + # Delete the private endpoint + delete_operation = client.begin_delete_ekm_private_endpoint(private_endpoint_name).result() + assert delete_operation is not None + assert delete_operation.private_endpoint_name == private_endpoint_name + assert delete_operation.operation_type == KeyVaultEkmPrivateEndpointOperationType.DELETE + assert delete_operation.status == KeyVaultEkmPrivateEndpointOperationStatus.SUCCEEDED + + # The delete operation's status can still be retrieved by its job ID + if delete_operation.job_id: + operation_status = client.get_ekm_private_endpoint_operation_status(delete_operation.job_id) + assert operation_status.job_id == delete_operation.job_id + assert operation_status.status == KeyVaultEkmPrivateEndpointOperationStatus.SUCCEEDED diff --git a/sdk/keyvault/azure-keyvault-administration/tests/test_ekm_client_async.py b/sdk/keyvault/azure-keyvault-administration/tests/test_ekm_client_async.py index aab45b856efb..c6c0fcbb1808 100644 --- a/sdk/keyvault/azure-keyvault-administration/tests/test_ekm_client_async.py +++ b/sdk/keyvault/azure-keyvault-administration/tests/test_ekm_client_async.py @@ -8,7 +8,11 @@ import pytest from azure.core.exceptions import HttpResponseError -from azure.keyvault.administration import KeyVaultEkmConnection +from azure.keyvault.administration import ( + KeyVaultEkmConnection, + KeyVaultEkmPrivateEndpointOperationStatus, + KeyVaultEkmPrivateEndpointOperationType, +) from azure.keyvault.administration.aio import KeyVaultEkmClient from azure.keyvault.administration._internal.client_base import DEFAULT_VERSION @@ -102,3 +106,60 @@ async def test_ekm_connection(self, client: KeyVaultEkmClient, **kwargs): assert len(result.server_ca_certificates) == 1 assert result.path_prefix == updated_ekm_connection.path_prefix assert result.server_subject_common_name == updated_ekm_connection.server_subject_common_name + + @pytest.mark.asyncio + @pytest.mark.parametrize("api_version", only_latest) + @KeyVaultEkmClientPreparer() + @recorded_by_proxy_async + async def test_ekm_private_endpoint(self, client: KeyVaultEkmClient, **kwargs): + private_link_service_id = kwargs.pop("private_link_service_id") + if not private_link_service_id: + pytest.skip( + "An EKM Private Link Service is required for live tests. Please set the EKM_PRIVATE_LINK_SERVICE_ID environment variable." + ) + private_endpoint_name = self.get_resource_name("ekm-pe") + + # Cleanup + try: + poller = await client.begin_delete_ekm_private_endpoint(private_endpoint_name) + await poller.wait() + except HttpResponseError: + pass + + # Create a private endpoint + create_poller = await client.begin_create_ekm_private_endpoint( + private_endpoint_name, private_link_service_id, request_message="Please approve" + ) + create_operation = await create_poller.result() + assert create_operation is not None + assert create_operation.private_endpoint_name == private_endpoint_name + assert create_operation.operation_type == KeyVaultEkmPrivateEndpointOperationType.CREATE + assert create_operation.status == KeyVaultEkmPrivateEndpointOperationStatus.SUCCEEDED + + # Get the private endpoint + private_endpoint = await client.get_ekm_private_endpoint(private_endpoint_name) + assert private_endpoint is not None + assert private_endpoint.name == private_endpoint_name + assert private_endpoint.provisioning_state is not None + assert private_endpoint.properties is not None + assert private_endpoint.properties.private_link_service_id == private_link_service_id + assert private_endpoint.private_link_service_connection_state is not None + assert private_endpoint.private_link_service_connection_state.status is not None + + # List the private endpoints + private_endpoint_names = [endpoint.name async for endpoint in client.list_ekm_private_endpoints()] + assert private_endpoint_name in private_endpoint_names + + # Delete the private endpoint + delete_poller = await client.begin_delete_ekm_private_endpoint(private_endpoint_name) + delete_operation = await delete_poller.result() + assert delete_operation is not None + assert delete_operation.private_endpoint_name == private_endpoint_name + assert delete_operation.operation_type == KeyVaultEkmPrivateEndpointOperationType.DELETE + assert delete_operation.status == KeyVaultEkmPrivateEndpointOperationStatus.SUCCEEDED + + # The delete operation's status can still be retrieved by its job ID + if delete_operation.job_id: + operation_status = await client.get_ekm_private_endpoint_operation_status(delete_operation.job_id) + assert operation_status.job_id == delete_operation.job_id + assert operation_status.status == KeyVaultEkmPrivateEndpointOperationStatus.SUCCEEDED From c4a2f121796233765b72467a7a1ae50dc291cda2 Mon Sep 17 00:00:00 2001 From: Nicola Camillucci Date: Thu, 10 Sep 2026 19:25:14 +0100 Subject: [PATCH 3/4] Fixed polling --- .../azure/keyvault/administration/_ekm_client.py | 15 ++++++++++++++- .../keyvault/administration/aio/_ekm_client.py | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_ekm_client.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_ekm_client.py index 6bf1422f90d8..0d209846e15f 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_ekm_client.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/_ekm_client.py @@ -6,6 +6,7 @@ from azure.core.paging import ItemPaged from azure.core.polling import LROPoller +from azure.core.polling.base_polling import LROBasePolling, OperationResourcePolling from azure.core.tracing.decorator import distributed_trace from ._generated.models import EkmPrivateEndpointCreateParameters @@ -39,6 +40,14 @@ class KeyVaultEkmClient(KeyVaultClientBase): # pylint:disable=protected-access + def _get_polling_method(self, kwargs: Any) -> LROBasePolling: + # The service reports private endpoint operation status via the `azure-asyncoperation` header, but Core's + # default algorithm looks for `operation-location` and would otherwise stop polling immediately + polling_interval = kwargs.pop("polling_interval", self._client._config.polling_interval) + return LROBasePolling( + polling_interval, lro_algorithms=[OperationResourcePolling("azure-asyncoperation")], **kwargs + ) + @distributed_trace def get_ekm_connection(self, **kwargs: Any) -> KeyVaultEkmConnection: """Gets the configured EKM connection. @@ -148,6 +157,7 @@ def begin_create_ekm_private_endpoint( pe_name=name, parameters=parameters, cls=KeyVaultEkmPrivateEndpointOperation._from_polling_result, + polling=self._get_polling_method(kwargs), **kwargs, ) @@ -168,7 +178,10 @@ def begin_delete_ekm_private_endpoint( # pylint:disable=bad-option-value,delete :raises ~azure.core.exceptions.HttpResponseError: """ return self._client.begin_delete_ekm_private_endpoint( - pe_name=name, cls=KeyVaultEkmPrivateEndpointOperation._from_polling_result, **kwargs + pe_name=name, + cls=KeyVaultEkmPrivateEndpointOperation._from_polling_result, + polling=self._get_polling_method(kwargs), + **kwargs, ) @distributed_trace diff --git a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/aio/_ekm_client.py b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/aio/_ekm_client.py index 483a2fa0e4bb..5d632e56b70f 100644 --- a/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/aio/_ekm_client.py +++ b/sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/aio/_ekm_client.py @@ -6,6 +6,8 @@ from azure.core.async_paging import AsyncItemPaged, AsyncList from azure.core.polling import AsyncLROPoller +from azure.core.polling.async_base_polling import AsyncLROBasePolling +from azure.core.polling.base_polling import OperationResourcePolling from azure.core.tracing.decorator import distributed_trace from azure.core.tracing.decorator_async import distributed_trace_async @@ -40,6 +42,14 @@ class KeyVaultEkmClient(AsyncKeyVaultClientBase): # pylint:disable=protected-access + def _get_polling_method(self, kwargs: Any) -> AsyncLROBasePolling: + # The service reports private endpoint operation status via the `azure-asyncoperation` header, but Core's + # default algorithm looks for `operation-location` and would otherwise stop polling immediately + polling_interval = kwargs.pop("polling_interval", self._client._config.polling_interval) + return AsyncLROBasePolling( + polling_interval, lro_algorithms=[OperationResourcePolling("azure-asyncoperation")], **kwargs + ) + @distributed_trace_async async def get_ekm_connection(self, **kwargs: Any) -> KeyVaultEkmConnection: """Gets the configured EKM connection. @@ -149,6 +159,7 @@ async def begin_create_ekm_private_endpoint( pe_name=name, parameters=parameters, cls=KeyVaultEkmPrivateEndpointOperation._from_polling_result, + polling=self._get_polling_method(kwargs), **kwargs, ) @@ -169,7 +180,10 @@ async def begin_delete_ekm_private_endpoint( # pylint:disable=bad-option-value, :raises ~azure.core.exceptions.HttpResponseError: """ return await self._client.begin_delete_ekm_private_endpoint( - pe_name=name, cls=KeyVaultEkmPrivateEndpointOperation._from_polling_result, **kwargs + pe_name=name, + cls=KeyVaultEkmPrivateEndpointOperation._from_polling_result, + polling=self._get_polling_method(kwargs), + **kwargs, ) @distributed_trace_async From 92003bc6e0239a0f99196475ced5067ecd37e257 Mon Sep 17 00:00:00 2001 From: Nicola Camillucci Date: Fri, 11 Sep 2026 10:11:54 +0100 Subject: [PATCH 4/4] Recorded tests --- sdk/keyvault/azure-keyvault-administration/assets.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/keyvault/azure-keyvault-administration/assets.json b/sdk/keyvault/azure-keyvault-administration/assets.json index 994168d7deb5..3fbc3867d6ff 100644 --- a/sdk/keyvault/azure-keyvault-administration/assets.json +++ b/sdk/keyvault/azure-keyvault-administration/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "python", "TagPrefix": "python/keyvault/azure-keyvault-administration", - "Tag": "python/keyvault/azure-keyvault-administration_4f95f3a7da" + "Tag": "python/keyvault/azure-keyvault-administration_d47d8124c8" }