From 665a4fc3c982d1192ce3620e92459bc74acaef91 Mon Sep 17 00:00:00 2001 From: MansiVerma <87318680+mansi-verma-1510@users.noreply.github.com> Date: Mon, 30 Dec 2024 10:55:14 +0530 Subject: [PATCH] {cli} Changes for adding an optional field for Filtering to Azure Cli commands for flowlogs resource creation and updation (#30581) * Changes in create and update * changes in _list, _show and _wait * Changes in _delete * adding UT --------- Co-authored-by: Mansi Verma --- .../network/watcher/flow_log/_create.py | 20 ++++++- .../network/watcher/flow_log/_delete.py | 20 +++++-- .../latest/network/watcher/flow_log/_list.py | 2 + .../latest/network/watcher/flow_log/_show.py | 9 ++- .../network/watcher/flow_log/_update.py | 25 +++++--- .../latest/network/watcher/flow_log/_wait.py | 7 ++- .../network/tests/latest/test_nw_flow_log.py | 57 +++++++++++++++++++ 7 files changed, 119 insertions(+), 21 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_create.py b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_create.py index 2978d255637..447b2d5f291 100644 --- a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_create.py +++ b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_create.py @@ -40,12 +40,15 @@ class Create(AAZCommand): :example: Create a flow log with Network Interface ID (could be in other resource group) az network watcher flow-log create --location westus --name MyFlowLog --nic MyNetworkInterfaceID --storage-account account + + :example: Create or update flow log + az network watcher flow-log create --location westus --resource-group MtRGContainingVNet --name MyVNetName-flowlog --vnet MyVNetName --storage-account MyStorageAccountName --filtering-criteria "dstip=20.252.145.59 || DstPort=443" """ _aaz_info = { - "version": "2023-11-01", + "version": "2024-03-01", "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkwatchers/{}/flowlogs/{}", "2023-11-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkwatchers/{}/flowlogs/{}", "2024-03-01"], ] } @@ -127,6 +130,7 @@ def _build_arguments_schema(cls, *args, **kwargs): ) identity = cls._args_schema.identity + identity.type = AAZStrArg( options=["type"], help="The type of identity used for the resource. The type 'SystemAssigned, UserAssigned' includes both an implicitly created identity and a set of user assigned identities. The type 'None' will remove any identities from the virtual machine.", @@ -145,6 +149,11 @@ def _build_arguments_schema(cls, *args, **kwargs): # define Arg Group "Properties" _args_schema = cls._args_schema + _args_schema.filtering_criteria = AAZStrArg( + options=["--filtering-criteria"], + arg_group="Properties", + help="Optional field to filter flowlogs based on SrcIP, SrcPort, DstIP, DstPort, Protocol, Encryption, Direction and Action. If not specified, all flowlogs will be logged.", + ) _args_schema.flow_analytics_configuration = AAZObjectArg( options=["--flow-analytics-configuration"], arg_group="Properties", @@ -281,7 +290,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2023-11-01", + "api-version", "2024-03-01", required=True, ), } @@ -320,9 +329,11 @@ def content(self): if user_assigned_identities is not None: user_assigned_identities.set_elements(AAZObjectType, ".") + properties = _builder.get(".properties") if properties is not None: properties.set_prop("enabled", AAZBoolType, ".enabled") + properties.set_prop("enabledFilteringCriteria", AAZStrType, ".filtering_criteria") properties.set_prop("flowAnalyticsConfiguration", AAZObjectType, ".flow_analytics_configuration") properties.set_prop("format", AAZObjectType) properties.set_prop("retentionPolicy", AAZObjectType, ".retention_policy") @@ -421,6 +432,9 @@ def _build_schema_on_200_201(cls): properties = cls._schema_on_200_201.properties properties.enabled = AAZBoolType() + properties.enabled_filtering_criteria = AAZStrType( + serialized_name="enabledFilteringCriteria", + ) properties.flow_analytics_configuration = AAZObjectType( serialized_name="flowAnalyticsConfiguration", ) diff --git a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_delete.py b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_delete.py index ef98c86e79b..925d80abc62 100644 --- a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_delete.py +++ b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_delete.py @@ -22,9 +22,9 @@ class Delete(AAZCommand): """ _aaz_info = { - "version": "2022-01-01", + "version": "2024-03-01", "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkwatchers/{}/flowlogs/{}", "2022-01-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkwatchers/{}/flowlogs/{}", "2024-03-01"], ] } @@ -85,7 +85,7 @@ def __call__(self, *args, **kwargs): return self.client.build_lro_polling( self.ctx.args.no_wait, session, - None, + self.on_200_201, self.on_error, lro_options={"final-state-via": "location"}, path_format_arguments=self.url_parameters, @@ -99,6 +99,15 @@ def __call__(self, *args, **kwargs): lro_options={"final-state-via": "location"}, path_format_arguments=self.url_parameters, ) + if session.http_response.status_code in [200, 201]: + return self.client.build_lro_polling( + self.ctx.args.no_wait, + session, + self.on_200_201, + self.on_error, + lro_options={"final-state-via": "location"}, + path_format_arguments=self.url_parameters, + ) return self.on_error(session.http_response) @@ -143,7 +152,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2022-01-01", + "api-version", "2024-03-01", required=True, ), } @@ -152,6 +161,9 @@ def query_parameters(self): def on_204(self, session): pass + def on_200_201(self, session): + pass + class _DeleteHelper: """Helper class for Delete""" diff --git a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_list.py b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_list.py index 47144ae0e27..62a412c2853 100644 --- a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_list.py +++ b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_list.py @@ -28,6 +28,8 @@ class List(AAZCommand): ] } + AZ_SUPPORT_PAGINATION = True + def _handler(self, command_args): super()._handler(command_args) return self.build_paging(self._execute_operations, self._output) diff --git a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_show.py b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_show.py index 923172975ee..1de612847db 100644 --- a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_show.py +++ b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_show.py @@ -25,9 +25,9 @@ class Show(AAZCommand): """ _aaz_info = { - "version": "2022-01-01", + "version": "2024-03-01", "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkwatchers/{}/flowlogs/{}", "2022-01-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkwatchers/{}/flowlogs/{}", "2024-03-01"], ] } @@ -133,7 +133,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2022-01-01", + "api-version", "2024-03-01", required=True, ), } @@ -184,6 +184,9 @@ def _build_schema_on_200(cls): properties = cls._schema_on_200.properties properties.enabled = AAZBoolType() + properties.enabled_filtering_criteria = AAZStrType( + serialized_name="enabledFilteringCriteria", + ) properties.flow_analytics_configuration = AAZObjectType( serialized_name="flowAnalyticsConfiguration", ) diff --git a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_update.py b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_update.py index 53924d19c24..23ede57b4a7 100644 --- a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_update.py +++ b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_update.py @@ -40,9 +40,9 @@ class Update(AAZCommand): """ _aaz_info = { - "version": "2023-11-01", + "version": "2024-03-01", "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkwatchers/{}/flowlogs/{}", "2023-11-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkwatchers/{}/flowlogs/{}", "2024-03-01"], ] } @@ -83,9 +83,6 @@ def _build_arguments_schema(cls, *args, **kwargs): _args_schema.location = AAZResourceLocationArg( help="Location to identify the exclusive Network Watcher under a region. Only one Network Watcher can be existed per subscription and region.", nullable=True, - fmt=AAZResourceLocationArgFormat( - resource_group_arg="resource_group", - ), ) _args_schema.enabled = AAZBoolArg( options=["--enabled"], @@ -156,6 +153,12 @@ def _build_arguments_schema(cls, *args, **kwargs): # define Arg Group "Properties" _args_schema = cls._args_schema + _args_schema.filtering_criteria = AAZStrArg( + options=["--filtering-criteria"], + arg_group="Properties", + help="Update condition to filter flowlogs based on SrcIP, SrcPort, DstIP, DstPort, Protocol, Encryption, Direction and Action. If not specified, all flowlogs will be logged.", + nullable=True, + ) _args_schema.flow_analytics_configuration = AAZObjectArg( options=["--flow-analytics-configuration"], arg_group="Properties", @@ -296,7 +299,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2023-11-01", + "api-version", "2024-03-01", required=True, ), } @@ -399,7 +402,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2023-11-01", + "api-version", "2024-03-01", required=True, ), } @@ -457,7 +460,7 @@ def _update_instance(self, instance): value=instance, typ=AAZObjectType ) - _builder.set_prop("identity", AAZObjectType, ".identity") + _builder.set_prop("identity", AAZIdentityObjectType, ".identity") _builder.set_prop("location", AAZStrType, ".location") _builder.set_prop("properties", AAZObjectType, typ_kwargs={"flags": {"client_flatten": True}}) _builder.set_prop("tags", AAZDictType, ".tags") @@ -474,6 +477,7 @@ def _update_instance(self, instance): properties = _builder.get(".properties") if properties is not None: properties.set_prop("enabled", AAZBoolType, ".enabled") + properties.set_prop("enabledFilteringCriteria", AAZStrType, ".filtering_criteria") properties.set_prop("flowAnalyticsConfiguration", AAZObjectType, ".flow_analytics_configuration") properties.set_prop("format", AAZObjectType) properties.set_prop("retentionPolicy", AAZObjectType, ".retention_policy") @@ -542,7 +546,7 @@ def _build_schema_flow_log_read(cls, _schema): flags={"read_only": True}, ) flow_log_read.id = AAZStrType() - flow_log_read.identity = AAZObjectType() + flow_log_read.identity = AAZIdentityObjectType() flow_log_read.location = AAZStrType() flow_log_read.name = AAZStrType( flags={"read_only": True}, @@ -584,6 +588,9 @@ def _build_schema_flow_log_read(cls, _schema): properties = _schema_flow_log_read.properties properties.enabled = AAZBoolType() + properties.enabled_filtering_criteria = AAZStrType( + serialized_name="enabledFilteringCriteria", + ) properties.flow_analytics_configuration = AAZObjectType( serialized_name="flowAnalyticsConfiguration", ) diff --git a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_wait.py b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_wait.py index 282c53630ce..c6bf0b3c38e 100644 --- a/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_wait.py +++ b/src/azure-cli/azure/cli/command_modules/network/aaz/latest/network/watcher/flow_log/_wait.py @@ -20,7 +20,7 @@ class Wait(AAZWaitCommand): _aaz_info = { "resources": [ - ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkwatchers/{}/flowlogs/{}", "2022-01-01"], + ["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.network/networkwatchers/{}/flowlogs/{}", "2024-03-01"], ] } @@ -126,7 +126,7 @@ def url_parameters(self): def query_parameters(self): parameters = { **self.serialize_query_param( - "api-version", "2022-01-01", + "api-version", "2024-03-01", required=True, ), } @@ -177,6 +177,9 @@ def _build_schema_on_200(cls): properties = cls._schema_on_200.properties properties.enabled = AAZBoolType() + properties.enabled_filtering_criteria = AAZStrType( + serialized_name="enabledFilteringCriteria", + ) properties.flow_analytics_configuration = AAZObjectType( serialized_name="flowAnalyticsConfiguration", ) diff --git a/src/azure-cli/azure/cli/command_modules/network/tests/latest/test_nw_flow_log.py b/src/azure-cli/azure/cli/command_modules/network/tests/latest/test_nw_flow_log.py index 404230873c1..e1df3d3f2f4 100644 --- a/src/azure-cli/azure/cli/command_modules/network/tests/latest/test_nw_flow_log.py +++ b/src/azure-cli/azure/cli/command_modules/network/tests/latest/test_nw_flow_log.py @@ -106,6 +106,63 @@ def test_nw_flow_log_create_vnetfl(self, resource_group, resource_group_location self.check('retentionPolicy.enabled', False), ]) + @ResourceGroupPreparer(name_prefix='test_nw_flow_log_', location='centraluseuap') + @StorageAccountPreparer(name_prefix='testflowlog', location='centraluseuap', kind='StorageV2') + def test_nw_flow_log_create_vnetfl_with_filtering(self, resource_group, resource_group_location, storage_account): + self.kwargs.update({ + 'rg': resource_group, + 'location': resource_group_location, + 'storage_account': storage_account, + 'vnet': 'vnet1', + 'subnet': 'subnet1', + 'nic': 'nic1', + 'watcher_rg': 'NetworkWatcherRG', + 'watcher_name': 'NetworkWatcher_{}'.format(resource_group_location), + 'flow_log': 'flow_log_test', + 'filtering_criteria': 'dstip=20.252.145.59 || DstPort=8080', + 'workspace': self.create_random_name('clitest', 20), + }) + + # enable network watcher + # self.cmd('network watcher configure -g {rg} --locations {location} --enabled') + + # prepare the target resource + self.cmd('network vnet create -g {rg} -n {vnet}') + self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet} --address-prefix 10.0.0.0/24') + self.cmd('network nic create -g {rg} -n {nic} --vnet-name {vnet} --subnet {subnet}') + + # prepare workspace + workspace = self.cmd('monitor log-analytics workspace create ' + '--resource-group {rg} ' + '--location eastus ' + '--workspace-name {workspace} ').get_output_in_json() + self.kwargs.update({ + 'workspace_id': workspace['id'] + }) + + #targetId as vnet + self.cmd('network watcher flow-log create ' + '--location {location} ' + '--resource-group {rg} ' + '--vnet {vnet} ' + '--storage-account {storage_account} ' + '--filtering-criteria {filtering_criteria} ' + '--workspace {workspace_id} ' + '--name {flow_log} ') + + self.cmd('network watcher flow-log list --location {location}') + + # This output is Azure Management Resource formatted. + self.cmd('network watcher flow-log show --location {location} --name {flow_log}', checks=[ + self.check('name', self.kwargs['flow_log']), + self.check('enabledFilteringCriteria', '.*/{filtering_criteria}$'), + self.check('flowAnalyticsConfiguration.networkWatcherFlowAnalyticsConfiguration.workspaceResourceId', + self.kwargs['workspace_id']), + self.check_pattern('targetResourceId', '.*/{vnet}$'), + self.check('retentionPolicy.days', 0), + self.check('retentionPolicy.enabled', False), + ]) + @ResourceGroupPreparer(name_prefix='test_nw_flow_log_', location='centraluseuap') @StorageAccountPreparer(name_prefix='testflowlog', location='centraluseuap', kind='StorageV2') def test_nw_flow_log_create_vnetflWithManagedIdentity(self, resource_group, resource_group_location, storage_account):