-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
972 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
## Follow API Schema | ||
|
||
```yml | ||
- name: Apply a firewall to resources | ||
hetzner.hcloud.hcloud_firewall: | ||
name: my-firewall | ||
apply_to: | ||
- type: label_selector | ||
label_selector: env=prod | ||
state: present | ||
|
||
- name: Remove a firewall from resources | ||
hetzner.hcloud.hcloud_firewall: | ||
name: my-firewall | ||
remove_from: | ||
- type: server | ||
server: 12345 | ||
state: present | ||
``` | ||
## Map the data to new arguments | ||
```yml | ||
- name: Apply a firewall to resources | ||
hetzner.hcloud.hcloud_firewall: | ||
name: my-firewall | ||
apply_to: | ||
label_selectors: | ||
- env=prod | ||
state: present | ||
|
||
- name: Remove a firewall from resources | ||
hetzner.hcloud.hcloud_firewall: | ||
name: my-firewall | ||
remove_from: | ||
servers: | ||
- 12345 | ||
state: present | ||
``` | ||
- Need to make the data returned by firewall and firewall_info consistent to this output to facilitate reusing the outputs | ||
## Create new `hcloud_firewall_resource` module to manage a firewall resource | ||
|
||
```yml | ||
- name: Apply a firewall to resources | ||
hetzner.hcloud.hcloud_firewall_resource: | ||
name: my-firewall | ||
server: 12345 | ||
state: present | ||
- name: Apply a firewall to resources | ||
hetzner.hcloud.hcloud_firewall_resource: | ||
name: my-firewall | ||
label_selector: | ||
- env=prod | ||
- key=value | ||
server: 12345 | ||
state: present | ||
- name: Remove a firewall from resources | ||
hetzner.hcloud.hcloud_firewall_resource: | ||
name: my-firewall | ||
label_selector: env=prod | ||
state: absent | ||
- name: Remove a firewall from resources | ||
hetzner.hcloud.hcloud_firewall_resource: | ||
name: my-firewall | ||
server: | ||
- 12345 | ||
state: absent | ||
# Example using firewall_info | ||
- name: Get firewall | ||
hetzner.hcloud.hcloud_firewall_info: | ||
name: my-firewall | ||
register: firewall | ||
- name: Remove a firewall from resources | ||
hetzner.hcloud.hcloud_firewall_resource: | ||
id: "{{ firewall.hcloud_firewall_info.id }}" | ||
server: "{{ firewall.hcloud_firewall_info.applied_to | json_query('[?type=="server"].server') }}" | ||
state: absent | ||
``` | ||
|
||
- Need to make the data returned by firewall and firewall_info consistent to this output to facilitate reusing the outputs | ||
- No way to define applied_to rules on firewall creation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
#!/usr/bin/python | ||
|
||
# Copyright: (c) 2023, Hetzner Cloud GmbH <[email protected]> | ||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
|
||
DOCUMENTATION = """ | ||
--- | ||
module: hcloud_firewall_info | ||
short_description: Gather infos about your Hetzner Cloud Firewalls. | ||
description: | ||
- Gather infos about your Hetzner Cloud Firewalls. | ||
author: | ||
- Jonas Lammler (@jooola) | ||
options: | ||
id: | ||
description: | ||
- The ID of the Firewall you want to get. | ||
- The module will fail if the provided ID is invalid. | ||
type: int | ||
name: | ||
description: | ||
- The name of the Firewall you want to get. | ||
type: str | ||
label_selector: | ||
description: | ||
- The label selector to filter the Firewalls you want to get. | ||
type: str | ||
extends_documentation_fragment: | ||
- hetzner.hcloud.hcloud | ||
""" | ||
|
||
EXAMPLES = """ | ||
- name: Gather hcloud firewall infos | ||
hetzner.hcloud.hcloud_firewall_info: | ||
register: output | ||
- name: Print the gathered infos | ||
debug: | ||
var: output | ||
""" | ||
|
||
RETURN = """ | ||
hcloud_firewall_info: | ||
description: List of firewalls infos | ||
returned: always | ||
type: list | ||
elements: dict | ||
contains: | ||
id: | ||
description: Numeric identifier of the Firewall | ||
returned: always | ||
type: int | ||
sample: 1937415 | ||
name: | ||
description: Name of the Firewall | ||
returned: always | ||
type: str | ||
sample: my-firewall | ||
labels: | ||
description: User-defined labels (key-value pairs) | ||
returned: always | ||
type: dict | ||
rules: | ||
description: List of Rules within this Firewall | ||
returned: always | ||
type: list | ||
elements: dict | ||
contains: | ||
description: | ||
description: User defined description of the Firewall Rule | ||
type: str | ||
returned: always | ||
direction: | ||
description: Direction of the Firewall Rule | ||
type: str | ||
returned: always | ||
sample: in | ||
protocol: | ||
description: Protocol of the Firewall Rule | ||
type: str | ||
returned: always | ||
sample: icmp | ||
port: | ||
description: Port or port range of the Firewall Rule, None if I(protocol) is icmp | ||
type: str | ||
returned: always | ||
sample: 80 | ||
source_ips: | ||
description: List of source IPs of the Firewall in CIDR notation | ||
type: list | ||
elements: str | ||
returned: always | ||
destination_ips: | ||
description: List of destination IPs of the Firewall in CIDR notation | ||
type: list | ||
elements: str | ||
returned: always | ||
applied_to: | ||
description: List of Resources the Firewall is applied to. | ||
returned: always | ||
type: list | ||
elements: dict | ||
contains: | ||
type: | ||
description: Type of the resource. | ||
type: str | ||
choices: [server, label_selector] | ||
sample: label_selector | ||
server: | ||
description: ID of the server. | ||
returned: if I(type) is server | ||
type: int | ||
sample: 12345 | ||
label_selector: | ||
description: Label selector value. | ||
if I(type) is label_selector | ||
type: str | ||
sample: key=value | ||
applied_to_resources: | ||
description: List of Resources the Firewall is applied to. | ||
returned: if I(type) is label_selector | ||
type: list | ||
elements: dict | ||
contains: | ||
type: | ||
description: Type of resource referenced. | ||
type: str | ||
choices: [server] | ||
sample: server | ||
server: | ||
description: ID of the Server. | ||
type: int | ||
sample: 12345 | ||
""" | ||
from typing import Dict, Any, List | ||
from ansible.module_utils.basic import AnsibleModule | ||
from ansible.module_utils.common.text.converters import to_native | ||
|
||
from ..module_utils.hcloud import AnsibleHCloud | ||
from ..module_utils.vendor.hcloud import HCloudException | ||
from ..module_utils.vendor.hcloud.firewalls import FirewallResource, FirewallRule | ||
|
||
|
||
class AnsibleHCloudFirewallInfo(AnsibleHCloud): | ||
def __init__(self, module): | ||
super().__init__(module, "hcloud_firewall_info") | ||
self.hcloud_firewall_info = None | ||
|
||
def _prepare_result(self) -> List[Dict[str, Any]]: | ||
tmp = [] | ||
|
||
for firewall in self.hcloud_firewall_info: | ||
if firewall is None: | ||
continue | ||
|
||
tmp.append( | ||
{ | ||
"id": to_native(firewall.id), | ||
"name": to_native(firewall.name), | ||
"labels": firewall.labels, | ||
"rules": [self._prepare_result_rule(item) for item in firewall.rules], | ||
"applied_to": [self._prepare_result_applied_to(item) for item in firewall.applied_to], | ||
} | ||
) | ||
|
||
return tmp | ||
|
||
def _prepare_result_rule(self, rule: FirewallRule) -> Dict[str, Any]: | ||
return { | ||
"direction": rule.direction, | ||
"protocol": to_native(rule.protocol), | ||
"port": to_native(rule.port) if rule.port is not None else None, | ||
"source_ips": [to_native(cidr) for cidr in rule.source_ips], | ||
"destination_ips": [to_native(cidr) for cidr in rule.destination_ips], | ||
"description": to_native(rule.description) if rule.description is not None else None, | ||
} | ||
|
||
def _prepare_result_applied_to(self, resource: FirewallResource) -> Dict[str, Any]: | ||
result = { | ||
"type": resource.type, | ||
"server": to_native(resource.server.id) if resource.server is not None else None, | ||
"label_selector": resource.label_selector.selector if resource.label_selector is not None else None, | ||
} | ||
if resource.applied_to_resources is not None: | ||
result["applied_to_resources"] = [ | ||
{ | ||
"type": item.type, | ||
"server": item.server.id if item.server is not None else None, | ||
} | ||
for item in resource.applied_to_resources | ||
] | ||
return result | ||
|
||
def get_firewalls(self): | ||
try: | ||
if self.module.params.get("id") is not None: | ||
self.hcloud_firewall_info = [self.client.firewalls.get_by_id(self.module.params.get("id"))] | ||
elif self.module.params.get("name") is not None: | ||
self.hcloud_firewall_info = [self.client.firewalls.get_by_name(self.module.params.get("name"))] | ||
else: | ||
params = {} | ||
label_selector = self.module.params.get("label_selector") | ||
if label_selector: | ||
params["label_selector"] = label_selector | ||
|
||
self.hcloud_firewall_info = self.client.firewalls.get_all(**params) | ||
|
||
except HCloudException as exception: | ||
self.fail_json_hcloud(exception) | ||
|
||
@classmethod | ||
def define_module(cls): | ||
return AnsibleModule( | ||
argument_spec=dict( | ||
id={"type": "int"}, | ||
name={"type": "str"}, | ||
label_selector={"type": "str"}, | ||
**super().base_module_arguments() | ||
), | ||
supports_check_mode=True, | ||
) | ||
|
||
|
||
def main(): | ||
module = AnsibleHCloudFirewallInfo.define_module() | ||
hcloud = AnsibleHCloudFirewallInfo(module) | ||
|
||
hcloud.get_firewalls() | ||
result = hcloud.get_result() | ||
|
||
ansible_info = {"hcloud_firewall_info": result["hcloud_firewall_info"]} | ||
module.exit_json(**ansible_info) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.