Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added security group support to network load balancer #2079

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -522,4 +522,4 @@ plugin_routing:
redirect: amazon.aws.sts_assume_role
module_utils:
route53:
redirect: amazon.aws.route53
redirect: amazon.aws.route53
146 changes: 135 additions & 11 deletions plugins/modules/elb_network_lb.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@
- This parameter is mutually exclusive with I(subnet_mappings).
type: list
elements: str
security_groups:
description:
- A list of the names or IDs of the security groups to assign to the load balancer.
- Required if I(state=present).
- If C([]), the VPC's default security group will be used.
type: list
elements: str
erinkdelong marked this conversation as resolved.
Show resolved Hide resolved
scheme:
description:
- Internet-facing or internal load balancer. An ELB scheme can not be modified after creation.
Expand Down Expand Up @@ -320,6 +327,11 @@
returned: when state is present
type: str
sample: internal
security_groups:
description: The IDs of the security groups for the load balancer.
returned: when state is present
type: list
sample: ['sg-0011223344']
state:
description: The state of the load balancer.
returned: when state is present
Expand Down Expand Up @@ -452,6 +464,117 @@ def delete_elb(elb_obj):

elb_obj.module.exit_json(changed=elb_obj.changed)

#creating class to allow for security groups with load balancer

class NetworkLoadBalancerWithSecurityGroups(NetworkLoadBalancer):
def __init__(self, connection, connection_ec2, module):
"""

:param connection: boto3 connection
:param module: Ansible module
"""
super().__init__(connection, module)

self.connection_ec2 = connection_ec2

# Ansible module parameters specific to NLBs
# self.type = "network"
# self.cross_zone_load_balancing = module.params.get("cross_zone_load_balancing")

# if self.elb is not None and self.elb["Type"] != "network":
# self.module.fail_json(
# msg="The load balancer type you are trying to manage is not network. Try elb_application_lb module instead.",
# )

if module.params.get("security_groups") is not None:
try:
self.security_groups = AWSRetry.jittered_backoff()(get_ec2_security_group_ids_from_names)(
module.params.get("security_groups"), self.connection_ec2, boto3=True
)
except ValueError as e:
self.module.fail_json(msg=str(e), exception=traceback.format_exc())
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e)
else:
self.security_groups = module.params.get("security_groups")

def _elb_create_params(self):
params = super()._elb_create_params()

if self.security_groups is not None:
params["SecurityGroups"] = self.security_groups

# params["Scheme"] = self.scheme

return params

def modify_elb_attributes(self):
"""
Update Network ELB attributes if required

:return:
"""

update_attributes = []

if (
self.cross_zone_load_balancing is not None
and str(self.cross_zone_load_balancing).lower() != self.elb_attributes["load_balancing_cross_zone_enabled"]
):
update_attributes.append(
{"Key": "load_balancing.cross_zone.enabled", "Value": str(self.cross_zone_load_balancing).lower()}
)
if (
self.deletion_protection is not None
and str(self.deletion_protection).lower() != self.elb_attributes["deletion_protection_enabled"]
):
update_attributes.append(
{"Key": "deletion_protection.enabled", "Value": str(self.deletion_protection).lower()}
)

if update_attributes:
try:
AWSRetry.jittered_backoff()(self.connection.modify_load_balancer_attributes)(
LoadBalancerArn=self.elb["LoadBalancerArn"], Attributes=update_attributes
)
self.changed = True
except (BotoCoreError, ClientError) as e:
# Something went wrong setting attributes. If this ELB was created during this task, delete it to leave a consistent state
if self.new_load_balancer:
AWSRetry.jittered_backoff()(self.connection.delete_load_balancer)(
LoadBalancerArn=self.elb["LoadBalancerArn"]
)
self.module.fail_json_aws(e)

def compare_security_groups(self):
"""
Compare user security groups with current ELB security groups

:return: bool True if they match otherwise False
"""

if set(self.elb["SecurityGroups"]) != set(self.security_groups):
return False
else:
return True

def modify_security_groups(self):
"""
Modify elb security groups to match module parameters
:return:
"""

try:
AWSRetry.jittered_backoff()(self.connection.set_security_groups)(
LoadBalancerArn=self.elb["LoadBalancerArn"], SecurityGroups=self.security_groups
)
except (BotoCoreError, ClientError) as e:
self.module.fail_json_aws(e)

self.changed = True




def main():
argument_spec = dict(
Expand Down Expand Up @@ -486,31 +609,32 @@ def main():
)

required_if = [
["state", "present", ["subnets", "subnet_mappings"], True],
["state", "present", ["subnets", "subnet_mappings"], True],
]

module = AnsibleAWSModule(
argument_spec=argument_spec,
required_if=required_if,
mutually_exclusive=[["subnets", "subnet_mappings"]],
argument_spec=argument_spec,
required_if=required_if,
mutually_exclusive=[["subnets", "subnet_mappings"]],
)

# Check for subnets or subnet_mappings if state is present
state = module.params.get("state")

# Quick check of listeners parameters
# Quick check of listeners parameters
listeners = module.params.get("listeners")
if listeners is not None:
for listener in listeners:
for key in listener.keys():
protocols_list = ["TCP", "TLS", "UDP", "TCP_UDP"]
if key == "Protocol" and listener[key] not in protocols_list:
module.fail_json(msg="'Protocol' must be either " + ", ".join(protocols_list))
for listener in listeners:
for key in listener.keys():
protocols_list = ["TCP", "TLS", "UDP", "TCP_UDP"]
if key == "Protocol" and listener[key] not in protocols_list:
module.fail_json(msg="'Protocol' must be either " + ", ".join(protocols_list))

connection = module.client("elbv2")
connection_ec2 = module.client("ec2")

elb = NetworkLoadBalancer(connection, connection_ec2, module)
# elb = NetworkLoadBalancer(connection, connection_ec2, module)
elb = NetworkLoadBalancerWithSecurityGroups(connection, connection_ec2, module)
Copy link
Member

Choose a reason for hiding this comment

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

something is broken here @erinkdelong

File "/tmp/ansible_elb_network_lb_payload_wfua5ziu/ansible_elb_network_lb_payload.zip/ansible_collections/community/aws/plugins/modules/elb_network_lb.py", line 647, in
File "/tmp/ansible_elb_network_lb_payload_wfua5ziu/ansible_elb_network_lb_payload.zip/ansible_collections/community/aws/plugins/modules/elb_network_lb.py", line 638, in main
File "/tmp/ansible_elb_network_lb_payload_wfua5ziu/ansible_elb_network_lb_payload.zip/ansible_collections/community/aws/plugins/modules/elb_network_lb.py", line 477, in init
TypeError: NetworkLoadBalancer.init() missing 1 required positional argument: 'module'


if state == "present":
create_or_update_elb(elb)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
- block:
- name: create NLB with listeners
elb_network_lb:
name: "{{ nlb_name }}"
subnets: "{{ nlb_subnets }}"
state: present
security_groups: "{{ sec_group.id }}"
listeners:
- Protocol: TCP
Port: 80
DefaultActions:
- Type: forward
TargetGroupName: "{{ tg_name }}"
- Protocol: TLS
Port: 443
Certificates:
- CertificateArn: "{{ cert.arn }}"
DefaultActions:
- Type: forward
TargetGroupName: "{{ tg_name }}"
- Protocol: UDP
Port: 13
DefaultActions:
- Type: forward
TargetGroupName: "{{ tg_tcpudp_name }}"
- Protocol: TCP_UDP
Port: 17
DefaultActions:
- Type: forward
TargetGroupName: "{{ tg_tcpudp_name }}"
register: nlb

- assert:
that:
- nlb.changed
- nlb.listeners|length == 4

- name: test idempotence creating NLB with listeners
elb_network_lb:
name: "{{ nlb_name }}"
subnets: "{{ nlb_subnets }}"
state: present
security_groups: "{{ sec_group.id }}"
listeners:
- Protocol: TCP
Port: 80
DefaultActions:
- Type: forward
TargetGroupName: "{{ tg_name }}"
- Protocol: TLS
Port: 443
Certificates:
- CertificateArn: "{{ cert.arn }}"
DefaultActions:
- Type: forward
TargetGroupName: "{{ tg_name }}"
- Protocol: UDP
Port: 13
DefaultActions:
- Type: forward
TargetGroupName: "{{ tg_tcpudp_name }}"
- Protocol: TCP_UDP
Port: 17
DefaultActions:
- Type: forward
TargetGroupName: "{{ tg_tcpudp_name }}"
register: nlb

- assert:
that:
- not nlb.changed
- nlb.listeners|length == 4
Loading