support application security group in network security group (#54584)

This commit is contained in:
Yunge Zhu 2019-04-01 16:56:16 +08:00 committed by GitHub
parent c85e3e0794
commit 23670913ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 137 additions and 1 deletions

View file

@ -95,6 +95,22 @@ options:
- Default tags such as C(VirtualNetwork), C(AzureLoadBalancer) and C(Internet) can also be used.
- It can accept string type or a list of string type.
default: "*"
source_application_security_groups:
description:
- List of the source application security groups.
- It could be list of resource id.
- It could be list of names in same resource group.
- It could be list of dict containing resource_group and name.
- It is mutually exclusive with C(source_address_prefix) and C(source_address_prefixes).
type: list
destination_application_security_groups:
description:
- List of the destination application security groups.
- It could be list of resource id.
- It could be list of names in same resource group.
- It could be list of dict containing resource_group and name.
- It is mutually exclusive with C(destination_address_prefix) and C(destination_address_prefixes).
type: list
access:
description:
- Whether or not to allow the traffic flow.
@ -341,6 +357,7 @@ state:
try:
from msrestazure.azure_exceptions import CloudError
from msrestazure.tools import is_valid_resource_id
from azure.mgmt.network import NetworkManagementClient
except ImportError:
# This is handled in azure_rm_common
@ -373,6 +390,12 @@ def validate_rule(self, rule, rule_type=None):
check_plural('source_port_range', 'source_port_ranges')
check_plural('destination_port_range', 'destination_port_ranges')
# when source(destination)_application_security_groups set, remove the default value * of source(destination)_address_prefix
if rule.get('source_application_security_groups') and rule.get('source_address_prefix') == '*':
rule['source_address_prefix'] = None
if rule.get('destination_application_security_groups') and rule.get('destination_address_prefix') == '*':
rule['destination_address_prefix'] = None
def compare_rules_change(old_list, new_list, purge_list):
old_list = old_list or []
@ -425,6 +448,10 @@ def compare_rules(old_rule, rule):
changed = True
if set(rule.get('destination_port_ranges') or []) != set(old_rule.get('destination_port_ranges') or []):
changed = True
if set(rule.get('source_application_security_groups') or []) != set(old_rule.get('source_application_security_groups') or []):
changed = True
if set(rule.get('destination_application_security_groups') or []) != set(old_rule.get('destination_application_security_groups') or []):
changed = True
return changed
@ -446,6 +473,12 @@ def create_rule_instance(self, rule):
destination_address_prefixes=rule.get('destination_address_prefixes', None),
source_port_ranges=rule.get('source_port_ranges', None),
destination_port_ranges=rule.get('destination_port_ranges', None),
source_application_security_groups=[
self.nsg_models.ApplicationSecurityGroup(id=p)
for p in rule.get('source_application_security_groups')] if rule.get('source_application_security_groups') else None,
destination_application_security_groups=[
self.nsg_models.ApplicationSecurityGroup(id=p)
for p in rule.get('destination_application_security_groups')] if rule.get('destination_application_security_groups') else None,
access=rule.get('access', None),
priority=rule.get('priority', None),
direction=rule.get('direction', None),
@ -475,6 +508,9 @@ def create_rule_dict_from_obj(rule):
destination_port_ranges=rule.destination_port_ranges,
source_address_prefixes=rule.source_address_prefixes,
destination_address_prefixes=rule.destination_address_prefixes,
source_application_security_groups=[p.id for p in rule.source_application_security_groups] if rule.source_application_security_groups else None,
destination_application_security_groups=[
p.id for p in rule.destination_application_security_groups] if rule.destination_application_security_groups else None,
access=rule.access,
priority=rule.priority,
direction=rule.direction,
@ -522,6 +558,8 @@ rule_spec = dict(
destination_port_range=dict(type='raw', default='*'),
source_address_prefix=dict(type='raw', default='*'),
destination_address_prefix=dict(type='raw', default='*'),
source_application_security_groups=dict(type='list', elements='raw'),
destination_application_security_groups=dict(type='list', elements='raw'),
access=dict(type='str', choices=['Allow', 'Deny'], default='Allow'),
priority=dict(type='int', required=True),
direction=dict(type='str', choices=['Inbound', 'Outbound'], default='Inbound')
@ -559,8 +597,14 @@ class AzureRMSecurityGroup(AzureRMModuleBase):
state=dict()
)
mutually_exclusive = [["source_application_security_group", "source_address_prefix"],
["source_application_security_group", "source_address_prefixes"],
["destination_application_security_group", "destination_address_prefix"],
["destination_application_security_group", "destination_address_prefixes"]]
super(AzureRMSecurityGroup, self).__init__(self.module_arg_spec,
supports_check_mode=True)
supports_check_mode=True,
mutually_exclusive=mutually_exclusive)
def exec_module(self, **kwargs):
# tighten up poll interval for security groups; default 30s is an eternity
@ -585,6 +629,7 @@ class AzureRMSecurityGroup(AzureRMModuleBase):
validate_rule(self, rule)
except Exception as exc:
self.fail("Error validating rule {0} - {1}".format(rule, str(exc)))
self.convert_asg_to_id(rule)
if self.default_rules:
for rule in self.default_rules:
@ -592,6 +637,7 @@ class AzureRMSecurityGroup(AzureRMModuleBase):
validate_rule(self, rule, 'default')
except Exception as exc:
self.fail("Error validating default rule {0} - {1}".format(rule, str(exc)))
self.convert_asg_to_id(rule)
try:
nsg = self.network_client.network_security_groups.get(self.resource_group, self.name)
@ -698,6 +744,24 @@ class AzureRMSecurityGroup(AzureRMModuleBase):
raise Exception("Error deleting security group {0} - {1}".format(self.name, str(exc)))
return result
def convert_asg_to_id(self, rule):
def convert_to_id(rule, key):
if rule.get(key):
ids = []
for p in rule.get(key):
if isinstance(p, dict):
ids.append("/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Network/applicationSecurityGroups/{2}".format(
self.subscription_id, p.get('resource_group'), p.get('name')))
elif isinstance(p, str):
if is_valid_resource_id(p):
ids.append(p)
else:
ids.append("/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Network/applicationSecurityGroups/{2}".format(
self.subscription_id, self.resource_group, p))
rule[key] = ids
convert_to_id(rule, 'source_application_security_groups')
convert_to_id(rule, 'destination_application_security_groups')
def main():
AzureRMSecurityGroup()

View file

@ -1,6 +1,9 @@
- name: Prepare random number
set_fact:
secgroupname: "sg{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}"
asg_name1: "asg1{{ resource_group | hash('md5') | truncate(7, True, '') }}"
asg_name2: "asg2{{ resource_group | hash('md5') | truncate(7, True, '') }}"
sg_name1: "sgasg{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}"
run_once: yes
@ -213,6 +216,75 @@
- output.changed
- "{{ output.state.rules | length }} == 2"
- name: Create Application security group 1
azure_rm_applicationsecuritygroup:
resource_group: "{{ resource_group }}"
name: "{{ asg_name1 }}"
tags:
testing: testing
register: asg1
- name: Create Application security group 2
azure_rm_applicationsecuritygroup:
resource_group: "{{ resource_group_secondary }}"
name: "{{ asg_name2 }}"
tags:
testing: testing
register: asg2
- name: Create security group with application security group
azure_rm_securitygroup:
resource_group: "{{ resource_group }}"
name: "{{ sg_name1 }}"
purge_rules: yes
rules:
- name: AsgToAsg
protocol: Tcp
source_application_security_groups:
- "{{ asg1.id }}"
destination_application_security_groups:
- resource_group: "{{ resource_group_secondary }}"
name: "{{ asg_name2 }}"
destination_port_range: 22
access: Allow
priority: 101
direction: Inbound
register: output
- assert:
that:
- output.changed
- name: Create security group with application security group - Idempotent
azure_rm_securitygroup:
resource_group: "{{ resource_group }}"
name: "{{ sg_name1 }}"
purge_rules: yes
rules:
- name: AsgToAsg
protocol: Tcp
source_application_security_groups:
- "{{ asg_name1 }}"
destination_application_security_groups:
- resource_group: "{{ resource_group_secondary }}"
name: "{{ asg_name2 }}"
destination_port_range: 22
access: Allow
priority: 101
direction: Inbound
register: output
- assert:
that:
- not output.changed
- name: Delete security group
azure_rm_securitygroup:
resource_group: "{{ resource_group }}"
name: "{{ sg_name1 }}"
state: absent
- name: Delete all security groups
azure_rm_securitygroup:
resource_group: "{{ resource_group }}"