Skip to content

Commit

Permalink
[Firewall] Support to configure intrusion detection policy and transp…
Browse files Browse the repository at this point in the history
…ort security for premium tier firewall policy (#2822)
  • Loading branch information
Jianhui Harold authored Dec 24, 2020
1 parent 3f5f62c commit fe38c41
Show file tree
Hide file tree
Showing 7 changed files with 2,080 additions and 250 deletions.
20 changes: 20 additions & 0 deletions src/azure-firewall/azext_firewall/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,26 @@
short-summary: List all Azure firewall policies.
"""

helps['network firewall policy intrusion-detection'] = """
type: group
short-summary: Manage intrusion signature rules and bypass rules
"""

helps['network firewall policy intrusion-detection add'] = """
type: command
short-summary: Add overrided intrusion signature or a bypass rule for intrusion detection
"""

helps['network firewall policy intrusion-detection list'] = """
type: command
short-summary: List all intrusion detection configuration
"""

helps['network firewall policy intrusion-detection remove'] = """
type: command
short-summary: Remove overrided intrusion signature or a bypass rule
"""

helps['network firewall policy rule-collection-group'] = """
type: group
short-summary: Manage and configure Azure firewall policy rule collection group.
Expand Down
42 changes: 37 additions & 5 deletions src/azure-firewall/azext_firewall/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
# pylint: disable=too-many-locals, too-many-branches, too-many-statements
def load_arguments(self, _):

AzureFirewallNetworkRuleProtocol, AzureFirewallRCActionType, \
AzureFirewallNatRCActionType, FirewallPolicySkuTier = \
(AzureFirewallNetworkRuleProtocol, AzureFirewallRCActionType,
AzureFirewallNatRCActionType, FirewallPolicySkuTier, FirewallPolicyIntrusionDetectionStateType,
FirewallPolicyIntrusionDetectionProtocol) = \
self.get_models('AzureFirewallNetworkRuleProtocol', 'AzureFirewallRCActionType',
'AzureFirewallNatRCActionType', 'FirewallPolicySkuTier')
'AzureFirewallNatRCActionType', 'FirewallPolicySkuTier', 'FirewallPolicyIntrusionDetectionStateType',
'FirewallPolicyIntrusionDetectionProtocol')

firewall_name_type = CLIArgumentType(options_list=['--firewall-name', '-f'], metavar='NAME', help='Azure Firewall name.', id_part='name', completer=get_resource_name_completion_list('Microsoft.Network/azureFirewalls'))
collection_name_type = CLIArgumentType(options_list=['--collection-name', '-c'], help='Name of the rule collection.', id_part='child_name_1')
Expand Down Expand Up @@ -165,6 +167,36 @@ def load_arguments(self, _):
c.argument('ip_addresses', nargs='+', help='Space-separated list of IPv4 addresses.')
c.argument('fqdns', nargs='+', help='Space-separated list of FQDNs.')

with self.argument_context('network firewall policy', arg_group='Intrustion Detection') as c:
c.argument('intrusion_detection_mode',
is_preview=True,
min_api='2020-07-01',
options_list=['--detect-mode'],
arg_type=get_enum_type(FirewallPolicyIntrusionDetectionStateType),
help='Intrusion detection general state')

with self.argument_context('network firewall policy', arg_group='Transport Security', min_api='2020-07-01', is_preview=True) as c:
c.argument('key_vault_secret_id',
help="Secret Id of (base-64 encoded unencrypted pfx) Secret or Certificate object stored in KeyVault")
c.argument('certificate_name', options_list=['--cert-name'], help='Name of the CA certificate')

with self.argument_context('network firewall policy intrusion-detection', min_api='2020-07-01') as c:
c.argument('firewall_policy_name', options_list=['--policy-name'], help='The name of the Firewall Policy.')

with self.argument_context('network firewall policy intrusion-detection', min_api='2020-07-01', arg_group='Intrusion Signature Override') as c:
c.argument('signature_mode', options_list=['--mode'], help='The signature state', arg_type=get_enum_type(FirewallPolicyIntrusionDetectionStateType))
c.argument('signature_id', help='Signature id')

with self.argument_context('network firewall policy intrusion-detection', min_api='2020-07-01', arg_group='Traffic Bypass Rule') as c:
c.argument('bypass_rule_name', options_list=['--rule-name'], help='Name of the bypass traffic rule')
c.argument('bypass_rule_description', options_list=['--rule-description'], help='Description of the bypass traffic rule')
c.argument('bypass_rule_protocol', options_list=['--rule-protocol'], arg_type=get_enum_type(FirewallPolicyIntrusionDetectionProtocol), help='The rule bypass protocol')
c.argument('bypass_rule_source_addresses', options_list=['--rule-src-addresses'], nargs='+', help='Space-separated list of source IP addresses or ranges for this rule')
c.argument('bypass_rule_destination_addresses', options_list=['--rule-dest-addresses'], nargs='+', help='Space-separated list of destination IP addresses or ranges for this rule')
c.argument('bypass_rule_destination_ports', options_list=['--rule-dest-ports'], nargs='+', help='Space-separated list of destination ports or ranges')
c.argument('bypass_rule_source_ip_groups', options_list=['--rule-src-ip-groups'], nargs='+', help='Space-separated list of source IpGroups for this rule')
c.argument('bypass_rule_destination_ip_groups', options_list=['--rule-dest-ip-groups'], nargs='+', help='Space-separated list of destination IpGroups for this rule')

with self.argument_context('network firewall policy rule-collection-group') as c:
c.argument('firewall_policy_name', options_list=['--policy-name'], help='The name of the Firewall Policy.')
c.argument('rule_collection_group_name', options_list=['--name', '-n'], help='The name of the Firewall Policy Rule Collection Group.')
Expand Down Expand Up @@ -194,8 +226,8 @@ def load_arguments(self, _):

with self.argument_context('network firewall policy rule-collection-group collection', arg_group='Application Rule') as c:
c.argument('target_fqdns', nargs='+', help='Space-separated list of FQDNs for this rule.', validator=validate_rule_group_collection)
c.argument('target_urls', nargs='+', help='Space-separated list of target urls for this rule')
c.argument('enable_terminate_tls', arg_type=get_three_state_flag(), help='Enable flag to terminate TLS connection for this rule')
c.argument('target_urls', nargs='+', help='Space-separated list of target urls for this rule', is_preview=True, min_api='2020-07-01')
c.argument('enable_terminate_tls', arg_type=get_three_state_flag(), help='Enable flag to terminate TLS connection for this rule', is_preview=True, min_api='2020-07-01')
c.argument('fqdn_tags', nargs='+', help='Space-separated list of FQDN tags for this rule.', validator=validate_rule_group_collection)
c.argument('protocols', nargs='+', validator=validate_application_rule_protocols, help='Space-separated list of protocols and port numbers to use, in PROTOCOL=PORT format. Valid protocols are Http, Https.')

Expand Down
7 changes: 6 additions & 1 deletion src/azure-firewall/azext_firewall/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,18 @@ def load_command_table(self, _):
# endregion

# region AzureFirewallPolicies
with self.command_group('network firewall policy', network_firewall_policies_sdk, resource_type=CUSTOM_FIREWALL, is_preview=True, min_api='2019-07-01') as g:
with self.command_group('network firewall policy', network_firewall_policies_sdk, resource_type=CUSTOM_FIREWALL, min_api='2019-07-01') as g:
g.custom_command('create', 'create_azure_firewall_policies')
g.command('delete', 'delete')
g.custom_command('list', 'list_azure_firewall_policies')
g.show_command('show')
g.generic_update_command('update', custom_func_name='update_azure_firewall_policies')

with self.command_group('network firewall policy intrusion-detection', resource_type=CUSTOM_FIREWALL, min_api='2020-07-01', is_preview=True) as g:
g.custom_command('add', 'add_firewall_policy_intrusion_detection_config')
g.custom_command('remove', 'remove_firewall_policy_intrusion_detection_config')
g.custom_command('list', 'list_firewall_policy_intrusion_detection_config')

with self.command_group('network firewall policy rule-collection-group', network_firewall_policy_rule_groups, resource_type=CUSTOM_FIREWALL, is_preview=True) as g:
g.custom_command('create', 'create_azure_firewall_policy_rule_collection_group')
g.generic_update_command('update', custom_func_name='update_azure_firewall_policy_rule_collection_group')
Expand Down
146 changes: 143 additions & 3 deletions src/azure-firewall/azext_firewall/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,8 @@ def create_azure_firewall_policies(cmd, resource_group_name, firewall_policy_nam
threat_intel_mode=None, location=None, tags=None, ip_addresses=None,
fqdns=None,
dns_servers=None, enable_dns_proxy=None,
sku=None):
sku=None, intrusion_detection_mode=None,
key_vault_secret_id=None, certificate_name=None):
client = network_client_factory(cmd.cli_ctx).firewall_policies
(FirewallPolicy,
SubResource,
Expand Down Expand Up @@ -521,14 +522,32 @@ def create_azure_firewall_policies(cmd, resource_group_name, firewall_policy_nam
if sku is not None:
firewall_policy.sku = FirewallPolicySku(tier=sku)

if intrusion_detection_mode is not None:
(FirewallPolicyIntrusionDetection,
FirewallPolicyIntrusionDetectionConfiguration) = \
cmd.get_models('FirewallPolicyIntrusionDetection',
'FirewallPolicyIntrusionDetectionConfiguration')
firewall_policy.intrusion_detection = FirewallPolicyIntrusionDetection(
mode=intrusion_detection_mode,
configuration=FirewallPolicyIntrusionDetectionConfiguration()
)

if certificate_name is not None and key_vault_secret_id is not None:
FirewallPolicyTransportSecurity, FirewallPolicyCertificateAuthority = \
cmd.get_models('FirewallPolicyTransportSecurity', 'FirewallPolicyCertificateAuthority')
certificate_auth = FirewallPolicyCertificateAuthority(key_vault_secret_id=key_vault_secret_id,
name=certificate_name)
firewall_policy.transport_security = FirewallPolicyTransportSecurity(certificate_authority=certificate_auth)

return client.create_or_update(resource_group_name, firewall_policy_name, firewall_policy)


def update_azure_firewall_policies(cmd,
instance, tags=None, threat_intel_mode=None, ip_addresses=None,
fqdns=None,
dns_servers=None, enable_dns_proxy=None,
sku=None):
sku=None, intrusion_detection_mode=None,
key_vault_secret_id=None, certificate_name=None):

(FirewallPolicyThreatIntelWhitelist, FirewallPolicySku) = cmd.get_models('FirewallPolicyThreatIntelWhitelist', 'FirewallPolicySku')
if tags is not None:
Expand All @@ -552,10 +571,27 @@ def update_azure_firewall_policies(cmd,
instance.threat_intel_whitelist.ip_addresses = ip_addresses
if fqdns is not None:
instance.threat_intel_whitelist.fqdns = fqdns
if sku is not None and cmd.supported_api_version(min_api='2020-07-01'):
if cmd.supported_api_version(min_api='2020-07-01'):
if sku is not None:
instance.sku = FirewallPolicySku(tier=sku)

if intrusion_detection_mode is not None:
if instance.intrusion_detection is not None:
instance.intrusion_detection.mode = intrusion_detection_mode
else:
(FirewallPolicyIntrusionDetection, FirewallPolicyIntrusionDetectionConfiguration) = \
cmd.get_models('FirewallPolicyIntrusionDetection', 'FirewallPolicyIntrusionDetectionConfiguration')
instance.intrusion_detection = FirewallPolicyIntrusionDetection(
mode=intrusion_detection_mode,
configuration=FirewallPolicyIntrusionDetectionConfiguration()
)
if certificate_name is not None and key_vault_secret_id is not None:
FirewallPolicyTransportSecurity, FirewallPolicyCertificateAuthority = \
cmd.get_models('FirewallPolicyTransportSecurity', 'FirewallPolicyCertificateAuthority')
certificate_auth = FirewallPolicyCertificateAuthority(key_vault_secret_id=key_vault_secret_id,
name=certificate_name)
instance.transport_security = FirewallPolicyTransportSecurity(certificate_authority=certificate_auth)

return instance


Expand All @@ -566,6 +602,110 @@ def list_azure_firewall_policies(cmd, resource_group_name=None):
return client.list_all()


def add_firewall_policy_intrusion_detection_config(cmd,
resource_group_name,
firewall_policy_name,
signature_id=None,
signature_mode=None,
bypass_rule_name=None,
bypass_rule_description=None,
bypass_rule_protocol=None,
bypass_rule_source_addresses=None,
bypass_rule_destination_addresses=None,
bypass_rule_destination_ports=None,
bypass_rule_source_ip_groups=None,
bypass_rule_destination_ip_groups=None):

from azure.cli.core.azclierror import RequiredArgumentMissingError, InvalidArgumentValueError

client = network_client_factory(cmd.cli_ctx).firewall_policies
firewall_policy = client.get(resource_group_name, firewall_policy_name)

if firewall_policy.intrusion_detection is None:
raise RequiredArgumentMissingError('Intrusion detection mode is not set. Setting it by update command first')

if signature_id is not None and signature_mode is not None:
for overrided_signature in firewall_policy.intrusion_detection.configuration.signature_overrides:
if overrided_signature.id == signature_id:
raise InvalidArgumentValueError(
'Signature ID {} exists. Delete it first or try update instead'.format(signature_id))

FirewallPolicyIntrusionDetectionSignatureSpecification = \
cmd.get_models('FirewallPolicyIntrusionDetectionSignatureSpecification')
signature_override = FirewallPolicyIntrusionDetectionSignatureSpecification(
id=signature_id,
mode=signature_mode
)
firewall_policy.intrusion_detection.configuration.signature_overrides.append(signature_override)

if bypass_rule_name is not None:
FirewallPolicyIntrusionDetectionBypassTrafficSpecifications = \
cmd.get_models('FirewallPolicyIntrusionDetectionBypassTrafficSpecifications')
bypass_traffic = FirewallPolicyIntrusionDetectionBypassTrafficSpecifications(
name=bypass_rule_name,
description=bypass_rule_description,
protocol=bypass_rule_protocol,
source_addresses=bypass_rule_source_addresses,
destination_addresses=bypass_rule_destination_addresses,
destination_ports=bypass_rule_destination_ports,
source_ip_groups=bypass_rule_source_ip_groups,
destination_ip_groups=bypass_rule_destination_ip_groups,
)
firewall_policy.intrusion_detection.configuration.bypass_traffic_settings.append(bypass_traffic)

result = sdk_no_wait(False,
client.create_or_update,
resource_group_name,
firewall_policy_name,
firewall_policy).result()
return result.intrusion_detection.configuration


def list_firewall_policy_intrusion_detection_config(cmd, resource_group_name, firewall_policy_name):
client = network_client_factory(cmd.cli_ctx).firewall_policies
firewall_policy = client.get(resource_group_name, firewall_policy_name)

if firewall_policy.intrusion_detection is None:
return []

return firewall_policy.intrusion_detection.configuration


def remove_firewall_policy_intrusion_detection_config(cmd,
resource_group_name,
firewall_policy_name,
signature_id=None,
bypass_rule_name=None):
from azure.cli.core.azclierror import RequiredArgumentMissingError, InvalidArgumentValueError

client = network_client_factory(cmd.cli_ctx).firewall_policies
firewall_policy = client.get(resource_group_name, firewall_policy_name)

if firewall_policy.intrusion_detection is None:
raise RequiredArgumentMissingError('Intrusion detection mode is not set. Setting it by update command first')

if signature_id is not None:
signatures = firewall_policy.intrusion_detection.configuration.signature_overrides
new_signatures = [s for s in signatures if s.id != signature_id]
if len(signatures) == len(new_signatures):
raise InvalidArgumentValueError("Signature ID {} doesn't exist".format(signature_id))
firewall_policy.intrusion_detection.configuration.signature_overrides = new_signatures

if bypass_rule_name is not None:
bypass_settings = firewall_policy.intrusion_detection.configuration.bypass_traffic_settings
new_bypass_settings = [s for s in bypass_settings if s.name != bypass_rule_name]
if len(bypass_settings) == len(new_bypass_settings):
raise InvalidArgumentValueError("Bypass rule with name {} doesn't exist".format(signature_id))
firewall_policy.intrusion_detection.configuration.bypass_traffic_settings = new_bypass_settings

result = sdk_no_wait(False,
client.create_or_update,
resource_group_name,
firewall_policy_name,
firewall_policy).result()
return result.intrusion_detection.configuration


def create_azure_firewall_policy_rule_collection_group(cmd, resource_group_name, firewall_policy_name,
rule_collection_group_name, priority):
client = network_client_factory(cmd.cli_ctx).firewall_policy_rule_collection_groups
Expand Down
Loading

0 comments on commit fe38c41

Please sign in to comment.