Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/azure-cli/azure/cli/command_modules/sql/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@
text: |
az sql db audit-policy update -g mygroup -s myserver -n mydb --state Enabled \\
--lats Enabled --lawri myworkspaceresourceid
- name: Set the fields included in audit events sent to Azure Monitor.
text: |
az sql db audit-policy update -g mygroup -s myserver -n mydb --state Enabled \\
--lats Enabled --lawri myworkspaceresourceid \\
--required-fields event_time action_id statement
- name: Disable a log analytics auditing policy.
text: |
az sql db audit-policy update -g mygroup -s myserver -n mydb
Expand Down Expand Up @@ -1490,6 +1495,11 @@
text: |
az sql server audit-policy update -g mygroup -n myserver --state Enabled \\
--lats Enabled --lawri myworkspaceresourceid
- name: Set the fields included in audit events sent to Azure Monitor.
text: |
az sql server audit-policy update -g mygroup -n myserver --state Enabled \\
--lats Enabled --lawri myworkspaceresourceid \\
--required-fields event_time action_id statement
- name: Disable a log analytics auditing policy.
text: |
az sql server audit-policy update -g mygroup -n myserver
Expand Down
12 changes: 12 additions & 0 deletions src/azure-cli/azure/cli/command_modules/sql/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,12 @@ def _configure_security_policy_storage_params(arg_ctx):
'Example: --actions FAILED_DATABASE_AUTHENTICATION_GROUP BATCH_COMPLETED_GROUP',
nargs='+')

c.argument('required_fields',
arg_group=policy_arg_group,
help='List of fields to include in audit events. Can only be specified when the Azure Monitor '
'target is enabled.',
Comment on lines +1208 to +1209
nargs='+')

c.argument('retention_days',
arg_group=policy_arg_group,
help='The number of days to retain audit logs.')
Expand Down Expand Up @@ -2056,6 +2062,12 @@ def _configure_security_policy_storage_params(arg_ctx):
'Example: --actions FAILED_DATABASE_AUTHENTICATION_GROUP BATCH_COMPLETED_GROUP',
nargs='+')

c.argument('required_fields',
arg_group=policy_arg_group,
help='List of fields to include in audit events. Can only be specified when the Azure Monitor '
'target is enabled.',
nargs='+')

c.argument('retention_days',
arg_group=policy_arg_group,
help='The number of days to retain audit logs.')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def _expansion_validator_impl(namespace):
for name in arguments:
# Get the validation map from the model type in order to determine
# whether the argument should be required
validation = model_type._validation.get(name, None) # pylint: disable=protected-access
validation = getattr(model_type, '_validation', {}).get(name, None) # pylint: disable=protected-access
required = validation.get('required', False) if validation else False
Comment on lines +47 to 48

# Generate the command line argument name from the property name
Expand Down
2 changes: 1 addition & 1 deletion src/azure-cli/azure/cli/command_modules/sql/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def load_command_table(self, _):
g.custom_show_command('show', 'transparent_data_encryptions_get')

database_encryption_protector_operations = CliCommandType(
operations_tmpl='azure.mgmt.sql.operations#DatabaseEncryptionProtectorOperations.{}',
operations_tmpl='azure.mgmt.sql.operations#DatabaseEncryptionProtectorsOperations.{}',
client_factory=get_sql_database_encryption_protector_operations)

with self.command_group('sql db tde key',
Expand Down
22 changes: 19 additions & 3 deletions src/azure-cli/azure/cli/command_modules/sql/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -2470,6 +2470,7 @@ def _audit_policy_validate_arguments(
storage_endpoint=None,
storage_account_access_key=None,
retention_days=None,
required_fields=None,
log_analytics_target_state=None,
log_analytics_workspace_resource_id=None,
event_hub_target_state=None,
Expand All @@ -2492,7 +2493,7 @@ def _audit_policy_validate_arguments(
event_hub_name is not None

if not state and not blob_storage_arguments_provided and\
not log_analytics_arguments_provided and not event_hub_arguments_provided:
not log_analytics_arguments_provided and not event_hub_arguments_provided and required_fields is None:
raise CLIError('Either state or blob storage or log analytics or event hub arguments are missing')

if _is_audit_policy_state_enabled(state) and\
Expand All @@ -2503,7 +2504,8 @@ def _audit_policy_validate_arguments(
if _is_audit_policy_state_disabled(state) and\
(blob_storage_arguments_provided or
log_analytics_arguments_provided or
event_hub_name):
event_hub_name or
required_fields is not None):
raise CLIError('No additional arguments should be provided once state is disabled')

if (_is_audit_policy_state_none_or_disabled(blob_storage_target_state)) and\
Expand Down Expand Up @@ -2883,6 +2885,7 @@ def _audit_policy_update_global_settings(
storage_endpoint=None,
storage_account_access_key=None,
audit_actions_and_groups=None,
required_fields=None,
retention_days=None,
log_analytics_target_state=None,
event_hub_target_state=None):
Expand Down Expand Up @@ -2925,6 +2928,12 @@ def _audit_policy_update_global_settings(
log_analytics_target_state=log_analytics_target_state,
event_hub_target_state=event_hub_target_state)

if required_fields is not None:
if not _is_audit_policy_state_enabled(instance.state) or not instance.is_azure_monitor_target_enabled:
raise ValidationError(
'required-fields can only be specified when auditing and the Azure Monitor target are enabled')
instance.required_fields = required_fields
Comment on lines +2931 to +2935


def _audit_policy_update_rollback(
cmd,
Expand Down Expand Up @@ -2974,6 +2983,7 @@ def _audit_policy_update(
storage_endpoint=None,
storage_account_access_key=None,
audit_actions_and_groups=None,
required_fields=None,
retention_days=None,
category_name=None,
log_analytics_target_state=None,
Expand All @@ -2990,6 +3000,7 @@ def _audit_policy_update(
storage_endpoint=storage_endpoint,
storage_account_access_key=storage_account_access_key,
retention_days=retention_days,
required_fields=required_fields,
log_analytics_target_state=log_analytics_target_state,
log_analytics_workspace_resource_id=log_analytics_workspace_resource_id,
event_hub_target_state=event_hub_target_state,
Expand Down Expand Up @@ -3034,6 +3045,7 @@ def _audit_policy_update(
storage_endpoint=storage_endpoint,
storage_account_access_key=storage_account_access_key,
audit_actions_and_groups=audit_actions_and_groups,
required_fields=required_fields,
retention_days=retention_days,
log_analytics_target_state=log_analytics_target_state,
event_hub_target_state=event_hub_target_state)
Expand Down Expand Up @@ -3065,6 +3077,7 @@ def server_audit_policy_update(
storage_endpoint=None,
storage_account_access_key=None,
audit_actions_and_groups=None,
required_fields=None,
retention_days=None,
log_analytics_target_state=None,
log_analytics_workspace_resource_id=None,
Expand All @@ -3087,6 +3100,7 @@ def server_audit_policy_update(
storage_endpoint=storage_endpoint,
storage_account_access_key=storage_account_access_key,
audit_actions_and_groups=audit_actions_and_groups,
required_fields=required_fields,
retention_days=retention_days,
category_name='SQLSecurityAuditEvents',
log_analytics_target_state=log_analytics_target_state,
Expand All @@ -3108,6 +3122,7 @@ def db_audit_policy_update(
storage_endpoint=None,
storage_account_access_key=None,
audit_actions_and_groups=None,
required_fields=None,
retention_days=None,
log_analytics_target_state=None,
log_analytics_workspace_resource_id=None,
Expand All @@ -3130,6 +3145,7 @@ def db_audit_policy_update(
storage_endpoint=storage_endpoint,
storage_account_access_key=storage_account_access_key,
audit_actions_and_groups=audit_actions_and_groups,
required_fields=required_fields,
retention_days=retention_days,
category_name='SQLSecurityAuditEvents',
log_analytics_target_state=log_analytics_target_state,
Expand Down Expand Up @@ -4502,7 +4518,7 @@ def server_create(
if minimal_tls_version is not None:
kwargs['minimal_tls_version'] = minimal_tls_version
else:
kwargs['minimal_tls_version'] = SqlServerMinimalTlsVersionType.tls_1_2
kwargs['minimal_tls_version'] = SqlServerMinimalTlsVersionType.tls_1_2.value

kwargs['key_id'] = key_id
kwargs['federated_client_id'] = federated_client_id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import unittest
from types import SimpleNamespace
from unittest.mock import MagicMock, patch

from azure.cli.core.azclierror import ValidationError
from azure.cli.core.util import CLIError
from azure.cli.command_modules.sql import custom


class SqlAuditPolicyRequiredFieldsTest(unittest.TestCase):

def _enabled_instance(self, azure_monitor_enabled):
return SimpleNamespace(
state='Enabled',
storage_endpoint=None,
storage_account_access_key=None,
is_azure_monitor_target_enabled=azure_monitor_enabled,
audit_actions_and_groups=['BATCH_COMPLETED_GROUP'])

@patch('azure.cli.command_modules.sql.custom._audit_policy_update_apply_azure_monitor_target_enabled')
@patch('azure.cli.command_modules.sql.custom._audit_policy_update_apply_blob_storage_details')
def test_required_fields_applied_when_azure_monitor_enabled(self, _, apply_azure_monitor):
instance = self._enabled_instance(azure_monitor_enabled=True)

custom._audit_policy_update_global_settings(
cmd=MagicMock(), instance=instance, required_fields=['event_time', 'statement'])

self.assertEqual(['event_time', 'statement'], instance.required_fields)
apply_azure_monitor.assert_called_once()

@patch('azure.cli.command_modules.sql.custom._audit_policy_update_apply_azure_monitor_target_enabled')
@patch('azure.cli.command_modules.sql.custom._audit_policy_update_apply_blob_storage_details')
def test_required_fields_rejected_without_azure_monitor(self, _, apply_azure_monitor):
instance = self._enabled_instance(azure_monitor_enabled=False)

with self.assertRaisesRegex(ValidationError, 'Azure Monitor target'):
custom._audit_policy_update_global_settings(
cmd=MagicMock(), instance=instance, required_fields=['event_time'])

apply_azure_monitor.assert_called_once()

def test_required_fields_alone_satisfies_argument_validation(self):
custom._audit_policy_validate_arguments(required_fields=['event_time'])

def test_no_arguments_still_fails_argument_validation(self):
with self.assertRaises(CLIError):
custom._audit_policy_validate_arguments()

def test_required_fields_rejected_when_state_disabled(self):
with self.assertRaisesRegex(CLIError, 'state is disabled'):
custom._audit_policy_validate_arguments(state='Disabled', required_fields=['event_time'])

def test_show_returns_required_fields_from_sdk(self):
required_fields = ['event_time', 'action_id']
client = MagicMock()
client.get.return_value = SimpleNamespace(state='Disabled', required_fields=required_fields)

server_result = custom.server_audit_policy_show(MagicMock(), client, 'server', 'resource-group')
self.assertEqual(required_fields, server_result.required_fields)

database_result = custom.db_audit_policy_show(MagicMock(), client, 'server', 'resource-group', 'database')
self.assertEqual(required_fields, database_result.required_fields)


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion src/azure-cli/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ dependencies = [
'azure-mgmt-servicefabric~=2.1.0',
'azure-mgmt-signalr==2.0.0b2',
'azure-mgmt-sqlvirtualmachine==1.0.0b5',
'azure-mgmt-sql==4.0.0b22',
'azure-mgmt-sql==5.0.0b2',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

janardhanrh Please take a look into this

'azure-mgmt-storage==25.0.0',
'azure-mgmt-synapse==2.1.0b5',
'azure-mgmt-trafficmanager~=1.0.0',
Expand Down
2 changes: 1 addition & 1 deletion src/azure-cli/requirements.py3.Darwin.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ azure-mgmt-servicebus==10.0.0b1
azure-mgmt-servicefabric==2.1.0
azure-mgmt-servicefabricmanagedclusters==2.1.0b3
azure-mgmt-servicelinker==1.2.0b3
azure-mgmt-sql==4.0.0b22
azure-mgmt-sql==5.0.0b2
azure-mgmt-signalr==2.0.0b2
azure-mgmt-sqlvirtualmachine==1.0.0b5
azure-mgmt-storage==25.0.0
Expand Down
2 changes: 1 addition & 1 deletion src/azure-cli/requirements.py3.Linux.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ azure-mgmt-servicebus==10.0.0b1
azure-mgmt-servicefabric==2.1.0
azure-mgmt-servicefabricmanagedclusters==2.1.0b3
azure-mgmt-servicelinker==1.2.0b3
azure-mgmt-sql==4.0.0b22
azure-mgmt-sql==5.0.0b2
azure-mgmt-signalr==2.0.0b2
azure-mgmt-sqlvirtualmachine==1.0.0b5
azure-mgmt-storage==25.0.0
Expand Down
2 changes: 1 addition & 1 deletion src/azure-cli/requirements.py3.windows.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ azure-mgmt-servicebus==10.0.0b1
azure-mgmt-servicefabric==2.1.0
azure-mgmt-servicefabricmanagedclusters==2.1.0b3
azure-mgmt-servicelinker==1.2.0b3
azure-mgmt-sql==4.0.0b22
azure-mgmt-sql==5.0.0b2
azure-mgmt-signalr==2.0.0b2
azure-mgmt-sqlvirtualmachine==1.0.0b5
azure-mgmt-storage==25.0.0
Expand Down
Loading