diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..8ede742 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,24 @@ +{ + "name": "ansible-dev-container-codespaces", + "image": "ghcr.io/ansible/community-ansible-dev-tools:latest", + "containerUser": "root", + "runArgs": [ + "--security-opt", + "seccomp=unconfined", + "--security-opt", + "label=disable", + "--cap-add=SYS_ADMIN", + "--cap-add=SYS_RESOURCE", + "--device", + "/dev/fuse", + "--security-opt", + "apparmor=unconfined", + "--hostname=ansible-dev-container" + ], + "updateRemoteUserUID": true, + "customizations": { + "vscode": { + "extensions": ["redhat.ansible","redhat.vscode-redhat-account"] + } + } +} diff --git a/.devcontainer/docker/devcontainer.json b/.devcontainer/docker/devcontainer.json new file mode 100644 index 0000000..391f02d --- /dev/null +++ b/.devcontainer/docker/devcontainer.json @@ -0,0 +1,24 @@ +{ + "name": "ansible-dev-container-docker", + "image": "ghcr.io/ansible/community-ansible-dev-tools:latest", + "containerUser": "root", + "runArgs": [ + "--security-opt", + "seccomp=unconfined", + "--security-opt", + "label=disable", + "--cap-add=SYS_ADMIN", + "--cap-add=SYS_RESOURCE", + "--device", + "/dev/fuse", + "--security-opt", + "apparmor=unconfined", + "--hostname=ansible-dev-container" + ], + "updateRemoteUserUID": true, + "customizations": { + "vscode": { + "extensions": ["redhat.ansible","redhat.vscode-redhat-account"] + } + } +} diff --git a/.devcontainer/podman/devcontainer.json b/.devcontainer/podman/devcontainer.json new file mode 100644 index 0000000..ebafd9f --- /dev/null +++ b/.devcontainer/podman/devcontainer.json @@ -0,0 +1,37 @@ +{ + "name": "ansible-dev-container-podman", + "image": "ghcr.io/ansible/community-ansible-dev-tools:latest", + "containerUser": "root", + "containerEnv": { + "REGISTRY_AUTH_FILE": "/container-auth.json" + }, + "runArgs": [ + "--cap-add=CAP_MKNOD", + "--cap-add=NET_ADMIN", + "--cap-add=SYS_ADMIN", + "--cap-add=SYS_RESOURCE", + "--device", + "/dev/fuse", + "--security-opt", + "seccomp=unconfined", + "--security-opt", + "label=disable", + "--security-opt", + "apparmor=unconfined", + "--security-opt", + "unmask=/sys/fs/cgroup", + "--userns=host", + "--hostname=ansible-dev-container", + "--env-file", + ".env" + ], + "customizations": { + "vscode": { + "extensions": ["redhat.ansible","redhat.vscode-redhat-account"] + } + }, + "mounts": [ + "source=${localEnv:XDG_RUNTIME_DIR}/containers/auth.json,target=/container-auth.json,type=bind,consistency=cached", + "source=${localEnv:HOME}/Dev/inventories/toallab-inventory,target=/workspaces/inventory,type=bind,consistency=cached", + ] +} diff --git a/.gitignore b/.gitignore index e2335b8..2c025ac 100644 --- a/.gitignore +++ b/.gitignore @@ -114,3 +114,4 @@ keys/ collections/ansible_collections/ .vaultpw context/ +ansible-navigator.yml diff --git a/collections/requirements.yml b/collections/requirements.old similarity index 100% rename from collections/requirements.yml rename to collections/requirements.old diff --git a/library/parse_opnsense_leases.py b/library/parse_opnsense_leases.py new file mode 100755 index 0000000..25b36fd --- /dev/null +++ b/library/parse_opnsense_leases.py @@ -0,0 +1,47 @@ +#!/usr/bin/python +import ipaddress +import yaml +import os +from collections import defaultdict + +def load_yaml_input(file_path): + with open(file_path, "r") as f: + return yaml.safe_load(f) + +def group_by_subnet(data, mask=24): + grouped = defaultdict(list) + + for record in data: + ip_str = record.get("address") + if not ip_str: + continue + try: + ip = ipaddress.ip_address(ip_str) + network = ipaddress.ip_network(f"{ip}/{mask}", strict=False) + grouped[str(network)].append(record) + except ValueError: + print(f"Skipping invalid IP: {ip_str}") + + return grouped + +def save_groups_to_yaml(grouped, output_dir="."): + os.makedirs(output_dir, exist_ok=True) + + for subnet, entries in grouped.items(): + safe_subnet = subnet.replace("/", "_") + filename = os.path.join(output_dir, f"subnet_{safe_subnet}.yaml") + with open(filename, "w") as f: + yaml.dump(entries, f, default_flow_style=False) + print(f"Saved {len(entries)} entries to {filename}") + +def main(): + input_file = "input.yaml" # change as needed + output_dir = "output_subnets" + cidr_mask = 24 # change to desired subnet size + + records = load_yaml_input(input_file) + grouped = group_by_subnet(records, cidr_mask) + save_groups_to_yaml(grouped, output_dir) + +if __name__ == "__main__": + main() diff --git a/playbooks/opnsense.yml b/playbooks/opnsense.yml index 10b0b53..88b2ccd 100644 --- a/playbooks/opnsense.yml +++ b/playbooks/opnsense.yml @@ -1,32 +1,55 @@ --- -- name: Get info on the existing host entries - hosts: localhost +- name: Configure DHCP + hosts: opnsense gather_facts: false module_defaults: group/ansibleguy.opnsense.all: - firewall: '{{ lookup("env","OPNSENSE_HOST") }}' - api_key: '{{ lookup("env","OPNSENSE_API_KEY") }}' - api_secret: '{{ lookup("env","OPNSENSE_API_SECRET") }}' - api_port: 8443 - - ansibleguy.opnsense.unbound_host: - match_fields: ['description'] - - ansibleguy.opnsense.list: - target: 'unbound_host' + firewall: "{{ opnsense_host }}" + api_key: "{{ opnsense_api_key }}" + api_secret: "{{ opnsense_api_secret }}" + ssl_verify: false + api_port: "{{ opnsense_api_port|default(omit) }}" tasks: - - name: Listing hosts # noqa args[module] - ansibleguy.opnsense.list: - target: 'unbound_host' - register: existing_entries + # TODO: Clean up subnet / reservation structure + - name: Configure KEA DHCP Server + ansibleguy.opnsense.dhcp_general: + enabled: "{{ dhcp_enabled }}" + interfaces: "{{ dhcp_interfaces }}" + delegate_to: localhost - - name: Printing entries - ansible.builtin.debug: - var: existing_entries.data + - name: Add subnet + ansibleguy.opnsense.dhcp_subnet: + subnet: "{{ item.subnet }}" + pools: "{{ item.pools }}" + auto_options: false + gateway: '{{ item.gateway }}' + dns: '{{ item.dns }}' + domain: '{{ item.domain }}' + reload: false + delegate_to: localhost + loop: "{{ dhcp_subnets }}" - - name: Generate csv from template - ansible.builtin.template: - src: ../templates/hosts.j2 - mode: "0644" - dest: "/data/output.csv" + - name: Get all dhcp_reservations_* variables from hostvars + ansible.builtin.set_fact: + all_dhcp_reservations: >- + {{ + hostvars[inventory_hostname] | dict2items + | selectattr('key', 'match', '^dhcp_reservations_') + | map(attribute='value') + | flatten + | selectattr('type', 'match', 'static') + }} + + - name: Add DHCP Reservations + ansibleguy.opnsense.dhcp_reservation: + hostname: "{{ item.hostname }}" + mac: "{{ item.mac }}" + ip: "{{ item.address }}" + subnet: "{{ item.address | ansible.utils.ipsubnet(24) }}" + description: "{{ item.description | default('') }}" + reload: false + delegate_to: localhost + loop: "{{ all_dhcp_reservations }}" + + - name: Add HAProxy \ No newline at end of file diff --git a/playbooks/output.csv b/playbooks/output.csv new file mode 100644 index 0000000..751ae52 --- /dev/null +++ b/playbooks/output.csv @@ -0,0 +1 @@ +hostname, domain, description, enabled, mx, mxprio, prio, record_type, server, value, uuid diff --git a/roles/toallab.infrastructure/README.md b/roles/toallab.infrastructure/README.md deleted file mode 100644 index 4bf50a3..0000000 --- a/roles/toallab.infrastructure/README.md +++ /dev/null @@ -1,40 +0,0 @@ -Role Name -========= - -Provisions home lab infrastructure. - -Requirements ------------- - -Really, you need my home lab setup. This role isn't really reusable in that regard. - -Role Variables --------------- - -TBD - -Dependencies ------------- - -My Home Lab - -Example Playbook ----------------- - -TODO - -Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: - - - hosts: servers - roles: - - { role: username.rolename, x: 42 } - -License -------- - -MIT - -Author Information ------------------- - -Patrick Toal - ptoal@takeflight.ca - https://toal.ca diff --git a/roles/toallab.infrastructure/defaults/main.yml b/roles/toallab.infrastructure/defaults/main.yml deleted file mode 100644 index f3ab138..0000000 --- a/roles/toallab.infrastructure/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# defaults file for toallab.infrastructure \ No newline at end of file diff --git a/roles/toallab.infrastructure/handlers/main.yml b/roles/toallab.infrastructure/handlers/main.yml deleted file mode 100644 index d827d7e..0000000 --- a/roles/toallab.infrastructure/handlers/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# handlers file for toallab.infrastructure \ No newline at end of file diff --git a/roles/toallab.infrastructure/meta/main.yml b/roles/toallab.infrastructure/meta/main.yml deleted file mode 100644 index 3a212a9..0000000 --- a/roles/toallab.infrastructure/meta/main.yml +++ /dev/null @@ -1,53 +0,0 @@ -galaxy_info: - author: your name - description: your description - company: your company (optional) - - # If the issue tracker for your role is not on github, uncomment the - # next line and provide a value - # issue_tracker_url: http://example.com/issue/tracker - - # Choose a valid license ID from https://spdx.org - some suggested licenses: - # - BSD-3-Clause (default) - # - MIT - # - GPL-2.0-or-later - # - GPL-3.0-only - # - Apache-2.0 - # - CC-BY-4.0 - license: license (GPL-2.0-or-later, MIT, etc) - - min_ansible_version: 2.4 - - # If this a Container Enabled role, provide the minimum Ansible Container version. - # min_ansible_container_version: - - # - # Provide a list of supported platforms, and for each platform a list of versions. - # If you don't wish to enumerate all versions for a particular platform, use 'all'. - # To view available platforms and versions (or releases), visit: - # https://galaxy.ansible.com/api/v1/platforms/ - # - # platforms: - # - name: Fedora - # versions: - # - all - # - 25 - # - name: SomePlatform - # versions: - # - all - # - 1.0 - # - 7 - # - 99.99 - - galaxy_tags: [] - # List tags for your role here, one per line. A tag is a keyword that describes - # and categorizes the role. Users find roles by searching for tags. Be sure to - # remove the '[]' above, if you add tags to this list. - # - # NOTE: A tag is limited to a single word comprised of alphanumeric characters. - # Maximum 20 tags per role. - -dependencies: [] - # List your role dependencies here, one per line. Be sure to remove the '[]' above, - # if you add dependencies to this list. - \ No newline at end of file diff --git a/roles/toallab.infrastructure/tasks/main.yml b/roles/toallab.infrastructure/tasks/main.yml deleted file mode 100644 index 96664fb..0000000 --- a/roles/toallab.infrastructure/tasks/main.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -# tasks file for toallab.infrastructure - -- name: Backup IOS Config - connection: network_cli - become: yes - ios_config: - backup: yes - -- name: Install base configuration - connection: network_cli - become: yes - ios_config: - lines: - - aaa new-model - - ip domain-name lan.toal.ca - - ip name-server 192.168.1.1 - - no cdp run - - lldp run - - ip ssh authentication-retries 2 - - ip ssh rsa keypair-name ssh2 - - ip ssh version 2 - - ntp server 0.ca.pool.ntp.org - - ntp server 0.pool.ntp.org - - ntp server ip 1.pool.ntp.org - -- name: Save changes - become: yes - connection: network_cli - ios_config: - save_when: changed diff --git a/roles/toallab.infrastructure/tests/inventory b/roles/toallab.infrastructure/tests/inventory deleted file mode 100644 index 878877b..0000000 --- a/roles/toallab.infrastructure/tests/inventory +++ /dev/null @@ -1,2 +0,0 @@ -localhost - diff --git a/roles/toallab.infrastructure/tests/test.yml b/roles/toallab.infrastructure/tests/test.yml deleted file mode 100644 index 72749aa..0000000 --- a/roles/toallab.infrastructure/tests/test.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- hosts: localhost - remote_user: root - roles: - - toallab.infrastructure \ No newline at end of file diff --git a/roles/toallab.infrastructure/vars/main.yml b/roles/toallab.infrastructure/vars/main.yml deleted file mode 100644 index 6c196c0..0000000 --- a/roles/toallab.infrastructure/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# vars file for toallab.infrastructure \ No newline at end of file