From 3fd40ea70237cb790487dba7e9a1becb82ad5388 Mon Sep 17 00:00:00 2001 From: Zhiyi Huang <17182306+calvinhzy@users.noreply.github.com> Date: Tue, 21 Oct 2025 16:01:52 +0800 Subject: [PATCH] add support for `az storage account network-security-perimeter-configuration list/show/reconcile` --- .../__cmd_group.py | 23 ++ .../__init__.py | 14 + .../_list.py | 352 ++++++++++++++++ .../_reconcile.py | 156 +++++++ .../_show.py | 355 ++++++++++++++++ .../recordings/test_storage_account_nsp.yaml | 388 ++++++++++++++++++ .../latest/test_storage_account_scenarios.py | 38 ++ 7 files changed, 1326 insertions(+) create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/__cmd_group.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_list.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_reconcile.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_show.py create mode 100644 src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_account_nsp.yaml diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/__cmd_group.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/__cmd_group.py new file mode 100644 index 00000000000..c1b18fa2b34 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/__cmd_group.py @@ -0,0 +1,23 @@ +# -------------------------------------------------------------------------------------------- +# 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 aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from azure.cli.core.aaz import * + + +@register_command_group( + "storage account network-security-perimeter-configuration", +) +class __CMDGroup(AAZCommandGroup): + """Manage Network Security Perimeter Configuration + """ + pass + + +__all__ = ["__CMDGroup"] diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/__init__.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/__init__.py new file mode 100644 index 00000000000..1147e219235 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/__init__.py @@ -0,0 +1,14 @@ +# -------------------------------------------------------------------------------------------- +# 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 aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from .__cmd_group import * +from ._list import * +from ._reconcile import * +from ._show import * diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_list.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_list.py new file mode 100644 index 00000000000..bd9fcea7e68 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_list.py @@ -0,0 +1,352 @@ +# -------------------------------------------------------------------------------------------- +# 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 aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from azure.cli.core.aaz import * + + +@register_command( + "storage account network-security-perimeter-configuration list", +) +class List(AAZCommand): + """List list of effective NetworkSecurityPerimeterConfiguration for storage account + + :example: List NetworkSecurityPerimeterConfiguration + az storage account network-security-perimeter-configuration list --resource-group res4410 --account-name sto8607 + """ + + _aaz_info = { + "version": "2025-01-01", + "resources": [ + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.storage/storageaccounts/{}/networksecurityperimeterconfigurations", "2025-01-01"], + ] + } + + def _handler(self, command_args): + super()._handler(command_args) + self._execute_operations() + return self._output() + + _args_schema = None + + @classmethod + def _build_arguments_schema(cls, *args, **kwargs): + if cls._args_schema is not None: + return cls._args_schema + cls._args_schema = super()._build_arguments_schema(*args, **kwargs) + + # define Arg Group "" + + _args_schema = cls._args_schema + _args_schema.account_name = AAZStrArg( + options=["--account-name"], + help="The name of the storage account within the specified resource group. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.", + required=True, + fmt=AAZStrArgFormat( + pattern="^[a-z0-9]+$", + max_length=24, + min_length=3, + ), + ) + _args_schema.resource_group = AAZResourceGroupNameArg( + required=True, + ) + return cls._args_schema + + def _execute_operations(self): + self.pre_operations() + self.NetworkSecurityPerimeterConfigurationsList(ctx=self.ctx)() + self.post_operations() + + @register_callback + def pre_operations(self): + pass + + @register_callback + def post_operations(self): + pass + + def _output(self, *args, **kwargs): + result = self.deserialize_output(self.ctx.vars.instance.value, client_flatten=True) + return result + + class NetworkSecurityPerimeterConfigurationsList(AAZHttpOperation): + CLIENT_TYPE = "MgmtClient" + + def __call__(self, *args, **kwargs): + request = self.make_request() + session = self.client.send_request(request=request, stream=False, **kwargs) + if session.http_response.status_code in [200]: + return self.on_200(session) + + return self.on_error(session.http_response) + + @property + def url(self): + return self.client.format_url( + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}/networkSecurityPerimeterConfigurations", + **self.url_parameters + ) + + @property + def method(self): + return "GET" + + @property + def error_format(self): + return "MgmtErrorFormat" + + @property + def url_parameters(self): + parameters = { + **self.serialize_url_param( + "accountName", self.ctx.args.account_name, + required=True, + ), + **self.serialize_url_param( + "resourceGroupName", self.ctx.args.resource_group, + required=True, + ), + **self.serialize_url_param( + "subscriptionId", self.ctx.subscription_id, + required=True, + ), + } + return parameters + + @property + def query_parameters(self): + parameters = { + **self.serialize_query_param( + "api-version", "2025-01-01", + required=True, + ), + } + return parameters + + @property + def header_parameters(self): + parameters = { + **self.serialize_header_param( + "Accept", "application/json", + ), + } + return parameters + + def on_200(self, session): + data = self.deserialize_http_content(session) + self.ctx.set_var( + "instance", + data, + schema_builder=self._build_schema_on_200 + ) + + _schema_on_200 = None + + @classmethod + def _build_schema_on_200(cls): + if cls._schema_on_200 is not None: + return cls._schema_on_200 + + cls._schema_on_200 = AAZObjectType() + + _schema_on_200 = cls._schema_on_200 + _schema_on_200.next_link = AAZStrType( + serialized_name="nextLink", + ) + _schema_on_200.value = AAZListType( + flags={"read_only": True}, + ) + + value = cls._schema_on_200.value + value.Element = AAZObjectType( + flags={"read_only": True}, + ) + + _element = cls._schema_on_200.value.Element + _element.id = AAZStrType( + flags={"read_only": True}, + ) + _element.name = AAZStrType( + flags={"read_only": True}, + ) + _element.properties = AAZObjectType( + flags={"client_flatten": True, "read_only": True}, + ) + _element.system_data = AAZObjectType( + serialized_name="systemData", + flags={"read_only": True}, + ) + _element.type = AAZStrType( + flags={"read_only": True}, + ) + + properties = cls._schema_on_200.value.Element.properties + properties.network_security_perimeter = AAZObjectType( + serialized_name="networkSecurityPerimeter", + flags={"read_only": True}, + ) + _ListHelper._build_schema_network_security_perimeter_read(properties.network_security_perimeter) + properties.profile = AAZObjectType( + flags={"read_only": True}, + ) + properties.provisioning_issues = AAZListType( + serialized_name="provisioningIssues", + flags={"read_only": True}, + ) + properties.provisioning_state = AAZStrType( + serialized_name="provisioningState", + flags={"read_only": True}, + ) + properties.resource_association = AAZObjectType( + serialized_name="resourceAssociation", + flags={"read_only": True}, + ) + + profile = cls._schema_on_200.value.Element.properties.profile + profile.access_rules = AAZListType( + serialized_name="accessRules", + ) + profile.access_rules_version = AAZFloatType( + serialized_name="accessRulesVersion", + ) + profile.diagnostic_settings_version = AAZFloatType( + serialized_name="diagnosticSettingsVersion", + ) + profile.enabled_log_categories = AAZListType( + serialized_name="enabledLogCategories", + ) + profile.name = AAZStrType() + + access_rules = cls._schema_on_200.value.Element.properties.profile.access_rules + access_rules.Element = AAZObjectType( + flags={"read_only": True}, + ) + + _element = cls._schema_on_200.value.Element.properties.profile.access_rules.Element + _element.name = AAZStrType() + _element.properties = AAZObjectType( + flags={"read_only": True}, + ) + + properties = cls._schema_on_200.value.Element.properties.profile.access_rules.Element.properties + properties.address_prefixes = AAZListType( + serialized_name="addressPrefixes", + ) + properties.direction = AAZStrType() + properties.fully_qualified_domain_names = AAZListType( + serialized_name="fullyQualifiedDomainNames", + flags={"read_only": True}, + ) + properties.network_security_perimeters = AAZListType( + serialized_name="networkSecurityPerimeters", + flags={"read_only": True}, + ) + properties.subscriptions = AAZListType() + + address_prefixes = cls._schema_on_200.value.Element.properties.profile.access_rules.Element.properties.address_prefixes + address_prefixes.Element = AAZStrType() + + fully_qualified_domain_names = cls._schema_on_200.value.Element.properties.profile.access_rules.Element.properties.fully_qualified_domain_names + fully_qualified_domain_names.Element = AAZStrType() + + network_security_perimeters = cls._schema_on_200.value.Element.properties.profile.access_rules.Element.properties.network_security_perimeters + network_security_perimeters.Element = AAZObjectType( + flags={"read_only": True}, + ) + _ListHelper._build_schema_network_security_perimeter_read(network_security_perimeters.Element) + + subscriptions = cls._schema_on_200.value.Element.properties.profile.access_rules.Element.properties.subscriptions + subscriptions.Element = AAZObjectType( + flags={"read_only": True}, + ) + + _element = cls._schema_on_200.value.Element.properties.profile.access_rules.Element.properties.subscriptions.Element + _element.id = AAZStrType() + + enabled_log_categories = cls._schema_on_200.value.Element.properties.profile.enabled_log_categories + enabled_log_categories.Element = AAZStrType() + + provisioning_issues = cls._schema_on_200.value.Element.properties.provisioning_issues + provisioning_issues.Element = AAZObjectType( + flags={"read_only": True}, + ) + + _element = cls._schema_on_200.value.Element.properties.provisioning_issues.Element + _element.name = AAZStrType() + _element.properties = AAZObjectType( + flags={"read_only": True}, + ) + + properties = cls._schema_on_200.value.Element.properties.provisioning_issues.Element.properties + properties.description = AAZStrType() + properties.issue_type = AAZStrType( + serialized_name="issueType", + ) + properties.severity = AAZStrType() + + resource_association = cls._schema_on_200.value.Element.properties.resource_association + resource_association.access_mode = AAZStrType( + serialized_name="accessMode", + ) + resource_association.name = AAZStrType() + + system_data = cls._schema_on_200.value.Element.system_data + system_data.created_at = AAZStrType( + serialized_name="createdAt", + ) + system_data.created_by = AAZStrType( + serialized_name="createdBy", + ) + system_data.created_by_type = AAZStrType( + serialized_name="createdByType", + ) + system_data.last_modified_at = AAZStrType( + serialized_name="lastModifiedAt", + ) + system_data.last_modified_by = AAZStrType( + serialized_name="lastModifiedBy", + ) + system_data.last_modified_by_type = AAZStrType( + serialized_name="lastModifiedByType", + ) + + return cls._schema_on_200 + + +class _ListHelper: + """Helper class for List""" + + _schema_network_security_perimeter_read = None + + @classmethod + def _build_schema_network_security_perimeter_read(cls, _schema): + if cls._schema_network_security_perimeter_read is not None: + _schema.id = cls._schema_network_security_perimeter_read.id + _schema.location = cls._schema_network_security_perimeter_read.location + _schema.perimeter_guid = cls._schema_network_security_perimeter_read.perimeter_guid + return + + cls._schema_network_security_perimeter_read = _schema_network_security_perimeter_read = AAZObjectType( + flags={"read_only": True} + ) + + network_security_perimeter_read = _schema_network_security_perimeter_read + network_security_perimeter_read.id = AAZStrType() + network_security_perimeter_read.location = AAZStrType() + network_security_perimeter_read.perimeter_guid = AAZStrType( + serialized_name="perimeterGuid", + ) + + _schema.id = cls._schema_network_security_perimeter_read.id + _schema.location = cls._schema_network_security_perimeter_read.location + _schema.perimeter_guid = cls._schema_network_security_perimeter_read.perimeter_guid + + +__all__ = ["List"] diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_reconcile.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_reconcile.py new file mode 100644 index 00000000000..99594853f4a --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_reconcile.py @@ -0,0 +1,156 @@ +# -------------------------------------------------------------------------------------------- +# 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 aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from azure.cli.core.aaz import * + + +@register_command( + "storage account network-security-perimeter-configuration reconcile", +) +class Reconcile(AAZCommand): + """Refreshes any information about the association. + + :example: Refreshes any information about the association + az storage account network-security-perimeter-configuration reconcile --resource-group res4410 --account-name sto8607 --network-security-perimeter-configuration-name dbedb4e0-40e6-4145-81f3-f1314c150774.resourceAssociation1 + """ + + _aaz_info = { + "version": "2025-01-01", + "resources": [ + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.storage/storageaccounts/{}/networksecurityperimeterconfigurations/{}/reconcile", "2025-01-01"], + ] + } + + AZ_SUPPORT_NO_WAIT = True + + def _handler(self, command_args): + super()._handler(command_args) + return self.build_lro_poller(self._execute_operations, None) + + _args_schema = None + + @classmethod + def _build_arguments_schema(cls, *args, **kwargs): + if cls._args_schema is not None: + return cls._args_schema + cls._args_schema = super()._build_arguments_schema(*args, **kwargs) + + # define Arg Group "" + + _args_schema = cls._args_schema + _args_schema.account_name = AAZStrArg( + options=["--account-name"], + help="The name of the storage account within the specified resource group. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.", + required=True, + id_part="name", + fmt=AAZStrArgFormat( + pattern="^[a-z0-9]+$", + max_length=24, + min_length=3, + ), + ) + _args_schema.network_security_perimeter_configuration_name = AAZStrArg( + options=["-n", "--name", "--network-security-perimeter-configuration-name"], + help="The name for Network Security Perimeter configuration", + required=True, + id_part="child_name_1", + fmt=AAZStrArgFormat( + pattern="^.*$", + ), + ) + _args_schema.resource_group = AAZResourceGroupNameArg( + required=True, + ) + return cls._args_schema + + def _execute_operations(self): + self.pre_operations() + yield self.NetworkSecurityPerimeterConfigurationsReconcile(ctx=self.ctx)() + self.post_operations() + + @register_callback + def pre_operations(self): + pass + + @register_callback + def post_operations(self): + pass + + class NetworkSecurityPerimeterConfigurationsReconcile(AAZHttpOperation): + CLIENT_TYPE = "MgmtClient" + + def __call__(self, *args, **kwargs): + request = self.make_request() + session = self.client.send_request(request=request, stream=False, **kwargs) + if session.http_response.status_code in [202]: + return self.client.build_lro_polling( + self.ctx.args.no_wait, + session, + None, + self.on_error, + lro_options={"final-state-via": "location"}, + path_format_arguments=self.url_parameters, + ) + + return self.on_error(session.http_response) + + @property + def url(self): + return self.client.format_url( + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}/networkSecurityPerimeterConfigurations/{networkSecurityPerimeterConfigurationName}/reconcile", + **self.url_parameters + ) + + @property + def method(self): + return "POST" + + @property + def error_format(self): + return "MgmtErrorFormat" + + @property + def url_parameters(self): + parameters = { + **self.serialize_url_param( + "accountName", self.ctx.args.account_name, + required=True, + ), + **self.serialize_url_param( + "networkSecurityPerimeterConfigurationName", self.ctx.args.network_security_perimeter_configuration_name, + required=True, + ), + **self.serialize_url_param( + "resourceGroupName", self.ctx.args.resource_group, + required=True, + ), + **self.serialize_url_param( + "subscriptionId", self.ctx.subscription_id, + required=True, + ), + } + return parameters + + @property + def query_parameters(self): + parameters = { + **self.serialize_query_param( + "api-version", "2025-01-01", + required=True, + ), + } + return parameters + + +class _ReconcileHelper: + """Helper class for Reconcile""" + + +__all__ = ["Reconcile"] diff --git a/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_show.py b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_show.py new file mode 100644 index 00000000000..f81546d961a --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/aaz/latest/storage/account/network_security_perimeter_configuration/_show.py @@ -0,0 +1,355 @@ +# -------------------------------------------------------------------------------------------- +# 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 aaz-dev-tools +# -------------------------------------------------------------------------------------------- + +# pylint: skip-file +# flake8: noqa + +from azure.cli.core.aaz import * + + +@register_command( + "storage account network-security-perimeter-configuration show", +) +class Show(AAZCommand): + """Get effective NetworkSecurityPerimeterConfiguration for association + + :example: Get effective NetworkSecurityPerimeterConfiguration for association + az storage account network-security-perimeter-configuration show --resource-group res4410 --account-name sto8607 --network-security-perimeter-configuration-name dbedb4e0-40e6-4145-81f3-f1314c150774.resourceAssociation1 + """ + + _aaz_info = { + "version": "2025-01-01", + "resources": [ + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.storage/storageaccounts/{}/networksecurityperimeterconfigurations/{}", "2025-01-01"], + ] + } + + def _handler(self, command_args): + super()._handler(command_args) + self._execute_operations() + return self._output() + + _args_schema = None + + @classmethod + def _build_arguments_schema(cls, *args, **kwargs): + if cls._args_schema is not None: + return cls._args_schema + cls._args_schema = super()._build_arguments_schema(*args, **kwargs) + + # define Arg Group "" + + _args_schema = cls._args_schema + _args_schema.account_name = AAZStrArg( + options=["--account-name"], + help="The name of the storage account within the specified resource group. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.", + required=True, + id_part="name", + fmt=AAZStrArgFormat( + pattern="^[a-z0-9]+$", + max_length=24, + min_length=3, + ), + ) + _args_schema.network_security_perimeter_configuration_name = AAZStrArg( + options=["-n", "--name", "--network-security-perimeter-configuration-name"], + help="The name for Network Security Perimeter configuration", + required=True, + id_part="child_name_1", + fmt=AAZStrArgFormat( + pattern="^.*$", + ), + ) + _args_schema.resource_group = AAZResourceGroupNameArg( + required=True, + ) + return cls._args_schema + + def _execute_operations(self): + self.pre_operations() + self.NetworkSecurityPerimeterConfigurationsGet(ctx=self.ctx)() + self.post_operations() + + @register_callback + def pre_operations(self): + pass + + @register_callback + def post_operations(self): + pass + + def _output(self, *args, **kwargs): + result = self.deserialize_output(self.ctx.vars.instance, client_flatten=True) + return result + + class NetworkSecurityPerimeterConfigurationsGet(AAZHttpOperation): + CLIENT_TYPE = "MgmtClient" + + def __call__(self, *args, **kwargs): + request = self.make_request() + session = self.client.send_request(request=request, stream=False, **kwargs) + if session.http_response.status_code in [200]: + return self.on_200(session) + + return self.on_error(session.http_response) + + @property + def url(self): + return self.client.format_url( + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}/networkSecurityPerimeterConfigurations/{networkSecurityPerimeterConfigurationName}", + **self.url_parameters + ) + + @property + def method(self): + return "GET" + + @property + def error_format(self): + return "MgmtErrorFormat" + + @property + def url_parameters(self): + parameters = { + **self.serialize_url_param( + "accountName", self.ctx.args.account_name, + required=True, + ), + **self.serialize_url_param( + "networkSecurityPerimeterConfigurationName", self.ctx.args.network_security_perimeter_configuration_name, + required=True, + ), + **self.serialize_url_param( + "resourceGroupName", self.ctx.args.resource_group, + required=True, + ), + **self.serialize_url_param( + "subscriptionId", self.ctx.subscription_id, + required=True, + ), + } + return parameters + + @property + def query_parameters(self): + parameters = { + **self.serialize_query_param( + "api-version", "2025-01-01", + required=True, + ), + } + return parameters + + @property + def header_parameters(self): + parameters = { + **self.serialize_header_param( + "Accept", "application/json", + ), + } + return parameters + + def on_200(self, session): + data = self.deserialize_http_content(session) + self.ctx.set_var( + "instance", + data, + schema_builder=self._build_schema_on_200 + ) + + _schema_on_200 = None + + @classmethod + def _build_schema_on_200(cls): + if cls._schema_on_200 is not None: + return cls._schema_on_200 + + cls._schema_on_200 = AAZObjectType( + flags={"read_only": True}, + ) + + _schema_on_200 = cls._schema_on_200 + _schema_on_200.id = AAZStrType( + flags={"read_only": True}, + ) + _schema_on_200.name = AAZStrType( + flags={"read_only": True}, + ) + _schema_on_200.properties = AAZObjectType( + flags={"client_flatten": True, "read_only": True}, + ) + _schema_on_200.system_data = AAZObjectType( + serialized_name="systemData", + flags={"read_only": True}, + ) + _schema_on_200.type = AAZStrType( + flags={"read_only": True}, + ) + + properties = cls._schema_on_200.properties + properties.network_security_perimeter = AAZObjectType( + serialized_name="networkSecurityPerimeter", + flags={"read_only": True}, + ) + _ShowHelper._build_schema_network_security_perimeter_read(properties.network_security_perimeter) + properties.profile = AAZObjectType( + flags={"read_only": True}, + ) + properties.provisioning_issues = AAZListType( + serialized_name="provisioningIssues", + flags={"read_only": True}, + ) + properties.provisioning_state = AAZStrType( + serialized_name="provisioningState", + flags={"read_only": True}, + ) + properties.resource_association = AAZObjectType( + serialized_name="resourceAssociation", + flags={"read_only": True}, + ) + + profile = cls._schema_on_200.properties.profile + profile.access_rules = AAZListType( + serialized_name="accessRules", + ) + profile.access_rules_version = AAZFloatType( + serialized_name="accessRulesVersion", + ) + profile.diagnostic_settings_version = AAZFloatType( + serialized_name="diagnosticSettingsVersion", + ) + profile.enabled_log_categories = AAZListType( + serialized_name="enabledLogCategories", + ) + profile.name = AAZStrType() + + access_rules = cls._schema_on_200.properties.profile.access_rules + access_rules.Element = AAZObjectType( + flags={"read_only": True}, + ) + + _element = cls._schema_on_200.properties.profile.access_rules.Element + _element.name = AAZStrType() + _element.properties = AAZObjectType( + flags={"read_only": True}, + ) + + properties = cls._schema_on_200.properties.profile.access_rules.Element.properties + properties.address_prefixes = AAZListType( + serialized_name="addressPrefixes", + ) + properties.direction = AAZStrType() + properties.fully_qualified_domain_names = AAZListType( + serialized_name="fullyQualifiedDomainNames", + flags={"read_only": True}, + ) + properties.network_security_perimeters = AAZListType( + serialized_name="networkSecurityPerimeters", + flags={"read_only": True}, + ) + properties.subscriptions = AAZListType() + + address_prefixes = cls._schema_on_200.properties.profile.access_rules.Element.properties.address_prefixes + address_prefixes.Element = AAZStrType() + + fully_qualified_domain_names = cls._schema_on_200.properties.profile.access_rules.Element.properties.fully_qualified_domain_names + fully_qualified_domain_names.Element = AAZStrType() + + network_security_perimeters = cls._schema_on_200.properties.profile.access_rules.Element.properties.network_security_perimeters + network_security_perimeters.Element = AAZObjectType( + flags={"read_only": True}, + ) + _ShowHelper._build_schema_network_security_perimeter_read(network_security_perimeters.Element) + + subscriptions = cls._schema_on_200.properties.profile.access_rules.Element.properties.subscriptions + subscriptions.Element = AAZObjectType( + flags={"read_only": True}, + ) + + _element = cls._schema_on_200.properties.profile.access_rules.Element.properties.subscriptions.Element + _element.id = AAZStrType() + + enabled_log_categories = cls._schema_on_200.properties.profile.enabled_log_categories + enabled_log_categories.Element = AAZStrType() + + provisioning_issues = cls._schema_on_200.properties.provisioning_issues + provisioning_issues.Element = AAZObjectType( + flags={"read_only": True}, + ) + + _element = cls._schema_on_200.properties.provisioning_issues.Element + _element.name = AAZStrType() + _element.properties = AAZObjectType( + flags={"read_only": True}, + ) + + properties = cls._schema_on_200.properties.provisioning_issues.Element.properties + properties.description = AAZStrType() + properties.issue_type = AAZStrType( + serialized_name="issueType", + ) + properties.severity = AAZStrType() + + resource_association = cls._schema_on_200.properties.resource_association + resource_association.access_mode = AAZStrType( + serialized_name="accessMode", + ) + resource_association.name = AAZStrType() + + system_data = cls._schema_on_200.system_data + system_data.created_at = AAZStrType( + serialized_name="createdAt", + ) + system_data.created_by = AAZStrType( + serialized_name="createdBy", + ) + system_data.created_by_type = AAZStrType( + serialized_name="createdByType", + ) + system_data.last_modified_at = AAZStrType( + serialized_name="lastModifiedAt", + ) + system_data.last_modified_by = AAZStrType( + serialized_name="lastModifiedBy", + ) + system_data.last_modified_by_type = AAZStrType( + serialized_name="lastModifiedByType", + ) + + return cls._schema_on_200 + + +class _ShowHelper: + """Helper class for Show""" + + _schema_network_security_perimeter_read = None + + @classmethod + def _build_schema_network_security_perimeter_read(cls, _schema): + if cls._schema_network_security_perimeter_read is not None: + _schema.id = cls._schema_network_security_perimeter_read.id + _schema.location = cls._schema_network_security_perimeter_read.location + _schema.perimeter_guid = cls._schema_network_security_perimeter_read.perimeter_guid + return + + cls._schema_network_security_perimeter_read = _schema_network_security_perimeter_read = AAZObjectType( + flags={"read_only": True} + ) + + network_security_perimeter_read = _schema_network_security_perimeter_read + network_security_perimeter_read.id = AAZStrType() + network_security_perimeter_read.location = AAZStrType() + network_security_perimeter_read.perimeter_guid = AAZStrType( + serialized_name="perimeterGuid", + ) + + _schema.id = cls._schema_network_security_perimeter_read.id + _schema.location = cls._schema_network_security_perimeter_read.location + _schema.perimeter_guid = cls._schema_network_security_perimeter_read.perimeter_guid + + +__all__ = ["Show"] diff --git a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_account_nsp.yaml b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_account_nsp.yaml new file mode 100644 index 00000000000..c822eeee7c8 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/recordings/test_storage_account_nsp.yaml @@ -0,0 +1,388 @@ +interactions: +- request: + body: '{"location": "eastus"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - group create + Connection: + - keep-alive + Content-Length: + - '22' + Content-Type: + - application/json + ParameterSetName: + - -g -l + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.12.10 (Windows-10-10.0.19045-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rgtestnsp?api-version=2024-11-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp","name":"rgtestnsp","type":"Microsoft.Resources/resourceGroups","location":"eastus","properties":{"provisioningState":"Succeeded"}}' + headers: + cache-control: + - no-cache + content-length: + - '215' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Oct 2025 07:56:17 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-writes: + - '199' + x-ms-throttling-version: + - v2 + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - storage account create + Connection: + - keep-alive + ParameterSetName: + - -n -g + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.12.10 (Windows-10-10.0.19045-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rgtestnsp?api-version=2024-11-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp","name":"rgtestnsp","type":"Microsoft.Resources/resourceGroups","location":"eastus","properties":{"provisioningState":"Succeeded"}}' + headers: + cache-control: + - no-cache + content-length: + - '215' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Oct 2025 07:56:19 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-throttling-version: + - v2 + status: + code: 200 + message: OK +- request: + body: '{"name": "satestnsp1", "type": "Microsoft.Storage/storageAccounts"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - storage account create + Connection: + - keep-alive + Content-Length: + - '67' + Content-Type: + - application/json + ParameterSetName: + - -n -g + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.12.10 (Windows-10-10.0.19045-SP0) + method: POST + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Storage/checkNameAvailability?api-version=2025-01-01 + response: + body: + string: '{"nameAvailable":false,"reason":"AlreadyExists","message":"The storage + account named satestnsp1 is already taken."}' + headers: + cache-control: + - no-cache + content-length: + - '115' + content-type: + - application/json + date: + - Tue, 21 Oct 2025 07:56:21 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - Microsoft-Azure-Storage-Resource-Provider/1.0,Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=7b31ddc4-9101-4ef0-a387-79ce181cacdb,objectId=7b1bdbe4-80ac-47f9-882b-33d6e62950ab/eastus2euap/b08b7fc6-daf3-4e5d-b554-4b9c0754bf4b + x-ms-throttling-version: + - v2 + status: + code: 200 + message: OK +- request: + body: '{"sku": {"name": "Standard_RAGRS"}, "kind": "StorageV2", "location": "eastus", + "properties": {"encryption": {"services": {"blob": {}}, "keySource": "Microsoft.Storage"}}}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - storage account create + Connection: + - keep-alive + Content-Length: + - '170' + Content-Type: + - application/json + ParameterSetName: + - -n -g + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.12.10 (Windows-10-10.0.19045-SP0) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp/providers/Microsoft.Storage/storageAccounts/satestnsp1?api-version=2025-01-01 + response: + body: + string: '{"sku":{"name":"Standard_RAGRS","tier":"Standard"},"kind":"StorageV2","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp/providers/Microsoft.Storage/storageAccounts/satestnsp1","name":"satestnsp1","type":"Microsoft.Storage/storageAccounts","location":"eastus","tags":{},"properties":{"keyCreationTime":{"key1":"2025-10-21T05:41:04.7147937Z","key2":"2025-10-21T05:41:04.7147937Z"},"allowCrossTenantReplication":false,"privateEndpointConnections":[],"minimumTlsVersion":"TLS1_0","allowBlobPublicAccess":false,"networkAcls":{"ipv6Rules":[],"bypass":"AzureServices","virtualNetworkRules":[],"ipRules":[],"defaultAction":"Allow"},"supportsHttpsTrafficOnly":true,"encryption":{"services":{"file":{"keyType":"Account","enabled":true,"lastEnabledTime":"2025-10-21T05:41:04.7147937Z"},"blob":{"keyType":"Account","enabled":true,"lastEnabledTime":"2025-10-21T05:41:04.7147937Z"}},"keySource":"Microsoft.Storage"},"accessTier":"Hot","provisioningState":"Succeeded","creationTime":"2025-10-21T05:41:04.5585481Z","primaryEndpoints":{"dfs":"https://satestnsp1.dfs.core.windows.net/","web":"https://satestnsp1.z13.web.core.windows.net/","blob":"https://satestnsp1.blob.core.windows.net/","queue":"https://satestnsp1.queue.core.windows.net/","table":"https://satestnsp1.table.core.windows.net/","file":"https://satestnsp1.file.core.windows.net/"},"primaryLocation":"eastus","statusOfPrimary":"available","secondaryLocation":"westus","statusOfSecondary":"available","secondaryEndpoints":{"dfs":"https://satestnsp1-secondary.dfs.core.windows.net/","web":"https://satestnsp1-secondary.z13.web.core.windows.net/","blob":"https://satestnsp1-secondary.blob.core.windows.net/","queue":"https://satestnsp1-secondary.queue.core.windows.net/","table":"https://satestnsp1-secondary.table.core.windows.net/"}}}' + headers: + cache-control: + - no-cache + content-length: + - '1814' + content-type: + - application/json + date: + - Tue, 21 Oct 2025 07:56:23 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - Microsoft-Azure-Storage-Resource-Provider/1.0,Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=7b31ddc4-9101-4ef0-a387-79ce181cacdb,objectId=7b1bdbe4-80ac-47f9-882b-33d6e62950ab/eastus2euap/881f1f81-dc15-4eb0-9372-e5b5b28a6cd2 + x-ms-ratelimit-remaining-subscription-writes: + - '199' + x-ms-throttling-version: + - v2 + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - storage account network-security-perimeter-configuration list + Connection: + - keep-alive + ParameterSetName: + - --account-name -g + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.12.10 (Windows-10-10.0.19045-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp/providers/Microsoft.Storage/storageAccounts/satestnsp1/networkSecurityPerimeterConfigurations?api-version=2025-01-01 + response: + body: + string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp/providers/Microsoft.Storage/storageAccounts/satestnsp1/networkSecurityPerimeterConfigurations/3f49d565-5208-4f2f-9c1e-38ef56e41d36.nspassociation1","name":"3f49d565-5208-4f2f-9c1e-38ef56e41d36.nspassociation1","type":"Microsoft.Storage/storageAccounts/networkSecurityPerimeterConfigurations","properties":{"provisioningState":"Succeeded","networkSecurityPerimeter":{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp/providers/Microsoft.Network/networkSecurityPerimeters/nsp1","perimeterGuid":"3f49d565-5208-4f2f-9c1e-38ef56e41d36","location":"eastus"},"resourceAssociation":{"name":"nspassociation1","accessMode":"Learning"},"profile":{"name":"nspprofile1","accessRulesVersion":0,"accessRules":[],"diagnosticSettingsVersion":0,"enabledLogCategories":[]}}}]}' + headers: + cache-control: + - no-cache + content-length: + - '884' + content-type: + - application/json + date: + - Tue, 21 Oct 2025 07:56:25 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - Microsoft-Azure-Storage-Resource-Provider/1.0,Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=7b31ddc4-9101-4ef0-a387-79ce181cacdb,objectId=7b1bdbe4-80ac-47f9-882b-33d6e62950ab/eastus2euap/a9f4a8ad-a037-41ee-a5f8-b3f72286ee90 + x-ms-throttling-version: + - v2 + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - storage account network-security-perimeter-configuration show + Connection: + - keep-alive + ParameterSetName: + - --account-name -g -n + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.12.10 (Windows-10-10.0.19045-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp/providers/Microsoft.Storage/storageAccounts/satestnsp1/networkSecurityPerimeterConfigurations/3f49d565-5208-4f2f-9c1e-38ef56e41d36.nspassociation1?api-version=2025-01-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp/providers/Microsoft.Storage/storageAccounts/satestnsp1/networkSecurityPerimeterConfigurations/3f49d565-5208-4f2f-9c1e-38ef56e41d36.nspassociation1","name":"3f49d565-5208-4f2f-9c1e-38ef56e41d36.nspassociation1","type":"Microsoft.Storage/storageAccounts/networkSecurityPerimeterConfigurations","properties":{"provisioningState":"Succeeded","networkSecurityPerimeter":{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp/providers/Microsoft.Network/networkSecurityPerimeters/nsp1","perimeterGuid":"3f49d565-5208-4f2f-9c1e-38ef56e41d36","location":"eastus"},"resourceAssociation":{"name":"nspassociation1","accessMode":"Learning"},"profile":{"name":"nspprofile1","accessRulesVersion":0,"accessRules":[],"diagnosticSettingsVersion":0,"enabledLogCategories":[]}}}' + headers: + cache-control: + - no-cache + connection: + - close + content-length: + - '872' + content-type: + - application/json + date: + - Tue, 21 Oct 2025 07:56:25 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - Microsoft-Azure-Storage-Resource-Provider/1.0,Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=7b31ddc4-9101-4ef0-a387-79ce181cacdb,objectId=7b1bdbe4-80ac-47f9-882b-33d6e62950ab/eastus2euap/9450df60-eb88-4616-9020-668b7f3a814d + x-ms-throttling-version: + - v2 + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - storage account network-security-perimeter-configuration reconcile + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - --account-name -g -n + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.12.10 (Windows-10-10.0.19045-SP0) + method: POST + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgtestnsp/providers/Microsoft.Storage/storageAccounts/satestnsp1/networkSecurityPerimeterConfigurations/3f49d565-5208-4f2f-9c1e-38ef56e41d36.nspassociation1/reconcile?api-version=2025-01-01 + response: + body: + string: '' + headers: + cache-control: + - no-cache + content-length: + - '0' + content-type: + - text/plain; charset=utf-8 + date: + - Tue, 21 Oct 2025 07:56:28 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Storage/locations/eastus/asyncoperations/b82f350f-9619-4add-91c8-7fc6ed74db7e?monitor=true&api-version=2025-01-01&t=638966301882833146&c=MIIHhjCCBm6gAwIBAgITHgeIzWb1oOWY4L6wkwAAB4jNZjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjUxMDE1MjEzOTU3WhcNMjYwMTEzMjEzOTU3WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALhbWoo4Zh88uhNqARFFk7KRv7EZ9cFrNm86KT0Bqr0CdreDNuRvzAVxy61P-LIgbEaim3f5zyoUR4uj_LAW78mAy0XjbqdBBIWcGI2nU_0se69ivGmXiu2GIecsTd_P2pjsXlYBKI6eU8xiBUdbVAdi0EszrxRUPoeUuySxFj-Y0rDsjxJjdO_dvh_s87gtfmLPaMaTlSZRm4hmcSZLkhwdqaPip-dIe31XWL2q1EgAheCNP3ECDiS5IIyWmIDxoA7dlTPYM0TSf9yrnSJBhmP61z2AXMcmm_xeJLWqdOh_Xlrt9FA8KbHy6Sq5cfAy7Lwb9Ssudo0slMN6TNdkXFUCAwEAAaOCBHMwggRvMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwIwCgYIKwYBBQUHAwEwPAYJKwYBBAGCNxUHBC8wLQYlKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFgh8fIENbYcQIBZAIBBjCCAcsGCCsGAQUFBwEBBIIBvTCCAbkwYwYIKwYBBQUHMAKGV2h0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2lpbmZyYS9DZXJ0cy9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDEuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwyLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMy5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDQuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwHQYDVR0OBBYEFONRpATyqBmxudoUWXjOGBKPVIE8MA4GA1UdDwEB_wQEAwIFoDCCASYGA1UdHwSCAR0wggEZMIIBFaCCARGgggENhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ1JML0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcmyGMWh0dHA6Ly9jcmwxLmFtZS5nYmwvY3JsL0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcmyGMWh0dHA6Ly9jcmwyLmFtZS5nYmwvY3JsL0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcmyGMWh0dHA6Ly9jcmwzLmFtZS5nYmwvY3JsL0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcmyGMWh0dHA6Ly9jcmw0LmFtZS5nYmwvY3JsL0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcmwwgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMB8GA1UdIwQYMBaAFPFGaMbxw_ArLX2LauGy-b41_NFBMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAQEACFtH9Ho_YyLzzefUgotLj0SQe-xV6nZG5pXZG7Zd92OHY5aMdqP1EzduYvZVvkATciIFaYf_XM1F5FftVmMPDdV_ZN0k7nf4l24Bal6l_5Z73QBENH_-56ZOs9eC3X7G_OttN0eSc_PpevxFA8Vmt80Gpb3LBAny3KPK-WfoZgFfGQPu8ScXpco5h_6tzFPrzhvVYEVFXlbpQz3dfq2g6AvysovKG6tjHeyX_pXWT12oA_JN4l_e5Y5JQ4rXspAeYt9JEaEvoly12O37FbRW5lQsqoGK3E8QjVRE2e9_BNAToAdX_OSYSQnTetO13E_-NH-t_yxmyFHZKNk5eBhJNA&s=OacBJfK6Rfs_bTt8Fy-tQy1lA7InGlqBTyC1ucVNQ5MBXhCq3X9lXk_ND2wJ8keyhzJYuMbYbxPUuTk7SndLYq-NlKUkJG-LYlErbPN-c7U3ry9FeZzmKSmHoBivPal8RyuC8zft_D3gAx1NDe8K4sE_D-0YeoU3dmspBMATd4jvdCv-hKVwVGQdPND4AVHudB-C8SHZKv9oBFI859uhU_wtZ73F8bam5BFw-tIpT3PwJ2Qq9ZB07i09RCwq_JepFKDZb4b36VyM9BIOBX7gq5u5OKI_miEcYLHwD5D75zNqKC9VUQ9YIQdkXKvMavHEtiXr-GmnGZ3RZdznE_lwzg&h=q3ZvsUuvsXO_2UqtncrGd7k2EoWT2CHQhR_tbro3AiM + pragma: + - no-cache + server: + - Microsoft-Azure-Storage-Resource-Provider/1.0,Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=7b31ddc4-9101-4ef0-a387-79ce181cacdb,objectId=7b1bdbe4-80ac-47f9-882b-33d6e62950ab/eastus2euap/16b6ba36-2c90-425d-a4b3-903297e8eae4 + x-ms-ratelimit-remaining-subscription-writes: + - '198' + x-ms-throttling-version: + - v2 + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - storage account network-security-perimeter-configuration reconcile + Connection: + - keep-alive + ParameterSetName: + - --account-name -g -n + User-Agent: + - AZURECLI/2.78.0 azsdk-python-core/1.35.0 Python/3.12.10 (Windows-10-10.0.19045-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Storage/locations/eastus/asyncoperations/b82f350f-9619-4add-91c8-7fc6ed74db7e?monitor=true&api-version=2025-01-01&t=638966301882833146&c=MIIHhjCCBm6gAwIBAgITHgeIzWb1oOWY4L6wkwAAB4jNZjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjUxMDE1MjEzOTU3WhcNMjYwMTEzMjEzOTU3WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALhbWoo4Zh88uhNqARFFk7KRv7EZ9cFrNm86KT0Bqr0CdreDNuRvzAVxy61P-LIgbEaim3f5zyoUR4uj_LAW78mAy0XjbqdBBIWcGI2nU_0se69ivGmXiu2GIecsTd_P2pjsXlYBKI6eU8xiBUdbVAdi0EszrxRUPoeUuySxFj-Y0rDsjxJjdO_dvh_s87gtfmLPaMaTlSZRm4hmcSZLkhwdqaPip-dIe31XWL2q1EgAheCNP3ECDiS5IIyWmIDxoA7dlTPYM0TSf9yrnSJBhmP61z2AXMcmm_xeJLWqdOh_Xlrt9FA8KbHy6Sq5cfAy7Lwb9Ssudo0slMN6TNdkXFUCAwEAAaOCBHMwggRvMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwIwCgYIKwYBBQUHAwEwPAYJKwYBBAGCNxUHBC8wLQYlKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFgh8fIENbYcQIBZAIBBjCCAcsGCCsGAQUFBwEBBIIBvTCCAbkwYwYIKwYBBQUHMAKGV2h0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2lpbmZyYS9DZXJ0cy9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDEuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwyLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMy5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDQuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwHQYDVR0OBBYEFONRpATyqBmxudoUWXjOGBKPVIE8MA4GA1UdDwEB_wQEAwIFoDCCASYGA1UdHwSCAR0wggEZMIIBFaCCARGgggENhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ1JML0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcmyGMWh0dHA6Ly9jcmwxLmFtZS5nYmwvY3JsL0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcmyGMWh0dHA6Ly9jcmwyLmFtZS5nYmwvY3JsL0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcmyGMWh0dHA6Ly9jcmwzLmFtZS5nYmwvY3JsL0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcmyGMWh0dHA6Ly9jcmw0LmFtZS5nYmwvY3JsL0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcmwwgZ0GA1UdIASBlTCBkjAMBgorBgEEAYI3ewEBMGYGCisGAQQBgjd7AgIwWDBWBggrBgEFBQcCAjBKHkgAMwAzAGUAMAAxADkAMgAxAC0ANABkADYANAAtADQAZgA4AGMALQBhADAANQA1AC0ANQBiAGQAYQBmAGYAZAA1AGUAMwAzAGQwDAYKKwYBBAGCN3sDAjAMBgorBgEEAYI3ewQCMB8GA1UdIwQYMBaAFPFGaMbxw_ArLX2LauGy-b41_NFBMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAQEACFtH9Ho_YyLzzefUgotLj0SQe-xV6nZG5pXZG7Zd92OHY5aMdqP1EzduYvZVvkATciIFaYf_XM1F5FftVmMPDdV_ZN0k7nf4l24Bal6l_5Z73QBENH_-56ZOs9eC3X7G_OttN0eSc_PpevxFA8Vmt80Gpb3LBAny3KPK-WfoZgFfGQPu8ScXpco5h_6tzFPrzhvVYEVFXlbpQz3dfq2g6AvysovKG6tjHeyX_pXWT12oA_JN4l_e5Y5JQ4rXspAeYt9JEaEvoly12O37FbRW5lQsqoGK3E8QjVRE2e9_BNAToAdX_OSYSQnTetO13E_-NH-t_yxmyFHZKNk5eBhJNA&s=OacBJfK6Rfs_bTt8Fy-tQy1lA7InGlqBTyC1ucVNQ5MBXhCq3X9lXk_ND2wJ8keyhzJYuMbYbxPUuTk7SndLYq-NlKUkJG-LYlErbPN-c7U3ry9FeZzmKSmHoBivPal8RyuC8zft_D3gAx1NDe8K4sE_D-0YeoU3dmspBMATd4jvdCv-hKVwVGQdPND4AVHudB-C8SHZKv9oBFI859uhU_wtZ73F8bam5BFw-tIpT3PwJ2Qq9ZB07i09RCwq_JepFKDZb4b36VyM9BIOBX7gq5u5OKI_miEcYLHwD5D75zNqKC9VUQ9YIQdkXKvMavHEtiXr-GmnGZ3RZdznE_lwzg&h=q3ZvsUuvsXO_2UqtncrGd7k2EoWT2CHQhR_tbro3AiM + response: + body: + string: '' + headers: + cache-control: + - no-cache + content-length: + - '0' + content-type: + - text/plain; charset=utf-8 + date: + - Tue, 21 Oct 2025 07:56:28 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - Microsoft-Azure-Storage-Resource-Provider/1.0,Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-operation-identifier: + - tenantId=7b31ddc4-9101-4ef0-a387-79ce181cacdb,objectId=7b1bdbe4-80ac-47f9-882b-33d6e62950ab/eastus2euap/c4b58850-f743-4edf-adb4-4ba2c3df5b42 + x-ms-throttling-version: + - v2 + status: + code: 200 + message: OK +version: 1 diff --git a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_account_scenarios.py b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_account_scenarios.py index 6c6182c4b04..df1c1f346fb 100644 --- a/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_account_scenarios.py +++ b/src/azure-cli/azure/cli/command_modules/storage/tests/latest/test_storage_account_scenarios.py @@ -2923,3 +2923,41 @@ def test_storage_sku_list(self): sku_list = self.cmd('storage sku list').get_output_in_json() assert sku_list is not None assert len(sku_list) > 0 + +class StorageAccountNetworkSecurityPerimeterConfigurationTests(StorageScenarioMixin, ScenarioTest): + @record_only() + @AllowLargeResponse(size_kb=10000) + def test_storage_account_nsp(self): + self.kwargs.update({ + 'sa': 'satestnsp1', + 'rg': 'rgtestnsp', + 'cmd': 'storage account network-security-perimeter-configuration', + 'nsp_name': 'nsp1', + 'nsp_profile_name': 'nspprofile1', + 'nsp_association_name': 'nspassociation1', + }) + self.cmd('group create -g {rg} -l eastus') + account_id = self.cmd('storage account create -n {sa} -g {rg}').get_output_in_json()['id'] + + # requires nsp extension, so run beforehand + # self.cmd('network perimeter create --name {nsp_name} --resource-group {rg}') + # nsp_profile_id = self.cmd('network perimeter profile create --name {nsp_profile_name} --resource-group {rg} ' + # '--perimeter-name {nsp_name}').get_output_in_json()['id'] + # self.kwargs.update({"account_id": account_id, "nsp_profile_id": nsp_profile_id}) + # self.cmd('network perimeter association create --name {nsp_association_name} ' + # '--perimeter-name {nsp_name} --resource-group {rg} --access-mode Learning ' + # '--private-link-resource {{id:{account_id}}} --profile {{id:{nsp_profile_id}}}') + + config_list = self.cmd('{cmd} list --account-name {sa} -g {rg}').get_output_in_json() + self.assertEqual(config_list[0]['profile']['name'], "nspprofile1") + self.assertEqual(config_list[0]['resourceAssociation']['name'], "nspassociation1") + self.assertEqual(config_list[0]['resourceAssociation']['accessMode'], "Learning") + config_name = config_list[0]['name'] + self.kwargs.update({'config_name': config_name}) + + self.cmd('{cmd} show --account-name {sa} -g {rg} -n {config_name}').assert_with_checks( + JMESPathCheck('profile.name', "nspprofile1"), + JMESPathCheck('resourceAssociation.name', "nspassociation1"), + JMESPathCheck('resourceAssociation.accessMode', "Learning")) + + self.cmd('{cmd} reconcile --account-name {sa} -g {rg} -n {config_name}')