support application security group in network security group (#54584)
This commit is contained in:
parent
c85e3e0794
commit
23670913ba
2 changed files with 137 additions and 1 deletions
|
@ -95,6 +95,22 @@ options:
|
||||||
- Default tags such as C(VirtualNetwork), C(AzureLoadBalancer) and C(Internet) can also be used.
|
- 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.
|
- It can accept string type or a list of string type.
|
||||||
default: "*"
|
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:
|
access:
|
||||||
description:
|
description:
|
||||||
- Whether or not to allow the traffic flow.
|
- Whether or not to allow the traffic flow.
|
||||||
|
@ -341,6 +357,7 @@ state:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from msrestazure.azure_exceptions import CloudError
|
from msrestazure.azure_exceptions import CloudError
|
||||||
|
from msrestazure.tools import is_valid_resource_id
|
||||||
from azure.mgmt.network import NetworkManagementClient
|
from azure.mgmt.network import NetworkManagementClient
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# This is handled in azure_rm_common
|
# 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('source_port_range', 'source_port_ranges')
|
||||||
check_plural('destination_port_range', 'destination_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):
|
def compare_rules_change(old_list, new_list, purge_list):
|
||||||
old_list = old_list or []
|
old_list = old_list or []
|
||||||
|
@ -425,6 +448,10 @@ def compare_rules(old_rule, rule):
|
||||||
changed = True
|
changed = True
|
||||||
if set(rule.get('destination_port_ranges') or []) != set(old_rule.get('destination_port_ranges') or []):
|
if set(rule.get('destination_port_ranges') or []) != set(old_rule.get('destination_port_ranges') or []):
|
||||||
changed = True
|
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
|
return changed
|
||||||
|
|
||||||
|
|
||||||
|
@ -446,6 +473,12 @@ def create_rule_instance(self, rule):
|
||||||
destination_address_prefixes=rule.get('destination_address_prefixes', None),
|
destination_address_prefixes=rule.get('destination_address_prefixes', None),
|
||||||
source_port_ranges=rule.get('source_port_ranges', None),
|
source_port_ranges=rule.get('source_port_ranges', None),
|
||||||
destination_port_ranges=rule.get('destination_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),
|
access=rule.get('access', None),
|
||||||
priority=rule.get('priority', None),
|
priority=rule.get('priority', None),
|
||||||
direction=rule.get('direction', None),
|
direction=rule.get('direction', None),
|
||||||
|
@ -475,6 +508,9 @@ def create_rule_dict_from_obj(rule):
|
||||||
destination_port_ranges=rule.destination_port_ranges,
|
destination_port_ranges=rule.destination_port_ranges,
|
||||||
source_address_prefixes=rule.source_address_prefixes,
|
source_address_prefixes=rule.source_address_prefixes,
|
||||||
destination_address_prefixes=rule.destination_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,
|
access=rule.access,
|
||||||
priority=rule.priority,
|
priority=rule.priority,
|
||||||
direction=rule.direction,
|
direction=rule.direction,
|
||||||
|
@ -522,6 +558,8 @@ rule_spec = dict(
|
||||||
destination_port_range=dict(type='raw', default='*'),
|
destination_port_range=dict(type='raw', default='*'),
|
||||||
source_address_prefix=dict(type='raw', default='*'),
|
source_address_prefix=dict(type='raw', default='*'),
|
||||||
destination_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'),
|
access=dict(type='str', choices=['Allow', 'Deny'], default='Allow'),
|
||||||
priority=dict(type='int', required=True),
|
priority=dict(type='int', required=True),
|
||||||
direction=dict(type='str', choices=['Inbound', 'Outbound'], default='Inbound')
|
direction=dict(type='str', choices=['Inbound', 'Outbound'], default='Inbound')
|
||||||
|
@ -559,8 +597,14 @@ class AzureRMSecurityGroup(AzureRMModuleBase):
|
||||||
state=dict()
|
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,
|
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):
|
def exec_module(self, **kwargs):
|
||||||
# tighten up poll interval for security groups; default 30s is an eternity
|
# tighten up poll interval for security groups; default 30s is an eternity
|
||||||
|
@ -585,6 +629,7 @@ class AzureRMSecurityGroup(AzureRMModuleBase):
|
||||||
validate_rule(self, rule)
|
validate_rule(self, rule)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
self.fail("Error validating rule {0} - {1}".format(rule, str(exc)))
|
self.fail("Error validating rule {0} - {1}".format(rule, str(exc)))
|
||||||
|
self.convert_asg_to_id(rule)
|
||||||
|
|
||||||
if self.default_rules:
|
if self.default_rules:
|
||||||
for rule in self.default_rules:
|
for rule in self.default_rules:
|
||||||
|
@ -592,6 +637,7 @@ class AzureRMSecurityGroup(AzureRMModuleBase):
|
||||||
validate_rule(self, rule, 'default')
|
validate_rule(self, rule, 'default')
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
self.fail("Error validating default rule {0} - {1}".format(rule, str(exc)))
|
self.fail("Error validating default rule {0} - {1}".format(rule, str(exc)))
|
||||||
|
self.convert_asg_to_id(rule)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
nsg = self.network_client.network_security_groups.get(self.resource_group, self.name)
|
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)))
|
raise Exception("Error deleting security group {0} - {1}".format(self.name, str(exc)))
|
||||||
return result
|
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():
|
def main():
|
||||||
AzureRMSecurityGroup()
|
AzureRMSecurityGroup()
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
- name: Prepare random number
|
- name: Prepare random number
|
||||||
set_fact:
|
set_fact:
|
||||||
secgroupname: "sg{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}"
|
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
|
run_once: yes
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,6 +216,75 @@
|
||||||
- output.changed
|
- output.changed
|
||||||
- "{{ output.state.rules | length }} == 2"
|
- "{{ 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
|
- name: Delete all security groups
|
||||||
azure_rm_securitygroup:
|
azure_rm_securitygroup:
|
||||||
resource_group: "{{ resource_group }}"
|
resource_group: "{{ resource_group }}"
|
||||||
|
|
Loading…
Reference in a new issue