├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .github ├── Actions_Dockerfile ├── entrypoint.sh └── workflows │ └── unifi_refresh.yml ├── .gitignore ├── .terraform.lock.hcl ├── LICENSE ├── README.md ├── docs ├── networks.md └── reference │ └── unifi_networks.tf ├── json ├── .keep └── raw │ └── .keep ├── providers.tf ├── scripts ├── all.sh ├── generate_unifi_accounts.sh ├── generate_unifi_all.sh ├── generate_unifi_ap_groups.sh ├── generate_unifi_devices.sh ├── generate_unifi_dynamic_dns.sh ├── generate_unifi_firewall_groups.sh ├── generate_unifi_firewall_rules.sh ├── generate_unifi_networks.sh ├── generate_unifi_port_forward.sh ├── generate_unifi_port_profiles.sh ├── generate_unifi_radius_profiles.sh ├── generate_unifi_settings.sh ├── generate_unifi_settings_mgmt.sh ├── generate_unifi_settings_radius.sh ├── generate_unifi_settings_usg.sh ├── generate_unifi_sites.sh ├── generate_unifi_static_routes.sh ├── generate_unifi_user_groups.sh ├── generate_unifi_users.sh ├── generate_unifi_wlans.sh ├── generate_variables.sh ├── get_accounts.sh ├── get_all.sh ├── get_ap_groups.sh ├── get_devices.sh ├── get_dynamic_dns.sh ├── get_firewall_groups.sh ├── get_firewall_rules.sh ├── get_networks.sh ├── get_port_forward.sh ├── get_port_profiles.sh ├── get_radius_profiles.sh ├── get_settings.sh ├── get_sites.sh ├── get_static_routes.sh ├── get_token.sh ├── get_user_groups.sh ├── get_users.sh ├── get_wlans.sh ├── json_utils.sh ├── log_utils.sh ├── mapping_utils.sh └── terraform_utils.sh └── tests ├── Dockerfile ├── json └── raw │ └── .keep └── server.js /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the latest Microsoft universal image for Codespaces 2 | FROM mcr.microsoft.com/devcontainers/universal:latest 3 | 4 | # Install Terraform CLI 5 | RUN curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - \ 6 | && sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" \ 7 | && sudo apt-get update && sudo apt-get install terraform 8 | 9 | # Add an alias for 'tf' to call 'terraform' and set ownership to the codespace user 10 | RUN echo 'alias tf="terraform"' >> /home/codespace/.bashrc \ 11 | && echo 'alias tf="terraform"' >> /home/codespace/.profile \ 12 | # Change ownership to the codespace user 13 | && chown codespace:codespace /home/codespace/.bashrc /home/codespace/.profile 14 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unifi-management", 3 | "build": { 4 | "dockerfile": "Dockerfile", 5 | "context": ".." 6 | }, 7 | "customizations": { 8 | "vscode": { 9 | "extensions": [ 10 | "GitHub.copilot", 11 | "GitHub.copilot-chat", 12 | "HashiCorp.terraform" 13 | ] 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/Actions_Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the latest Ubuntu LTS as base image 2 | FROM ubuntu:latest 3 | 4 | # Set environment variables to avoid user interaction during package installation 5 | ENV DEBIAN_FRONTEND=noninteractive 6 | 7 | # Install necessary packages 8 | RUN apt-get update && \ 9 | apt-get install -y \ 10 | curl \ 11 | sudo \ 12 | git \ 13 | ca-certificates \ 14 | libicu-dev \ 15 | jq \ 16 | locales \ 17 | && rm -rf /var/lib/apt/lists/* 18 | 19 | # Set the locale to one that supports UTF-8 20 | RUN locale-gen en_US.UTF-8 21 | 22 | # Set environment variables for the locale 23 | ENV LANG=en_US.UTF-8 \ 24 | LANGUAGE=en_US:en \ 25 | LC_ALL=en_US.UTF-8 26 | 27 | # Create a user for the GitHub runner 28 | RUN useradd -m runner 29 | 30 | # Set working directory 31 | WORKDIR /home/runner 32 | 33 | # Download the latest GitHub Actions runner package 34 | RUN curl -o actions-runner-linux-x64-2.311.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz 35 | 36 | # Extract the installer 37 | RUN tar xzf ./actions-runner-linux-x64-2.311.0.tar.gz 38 | 39 | # Give the runner user permission to the runner directory 40 | RUN chown -R runner:runner . 41 | 42 | # Copy the entrypoint script 43 | COPY entrypoint.sh /home/runner/entrypoint.sh 44 | RUN chmod +x /home/runner/entrypoint.sh 45 | 46 | # Run the installdependencies.sh script to install .NET Core dependencies 47 | RUN ./bin/installdependencies.sh 48 | 49 | # Switch to the runner user 50 | USER runner 51 | 52 | # Set the entrypoint 53 | ENTRYPOINT ["/home/runner/entrypoint.sh"] -------------------------------------------------------------------------------- /.github/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Copy runner files from /tmp/runner_files to /home/runner 5 | cp -r /tmp/runner_files/* /home/runner/ 6 | 7 | # Change to the runner directory 8 | cd /home/runner 9 | 10 | # Check if the runner is already configured 11 | if [ ! -f ".runner" ]; then 12 | # Configure the runner 13 | ./config.sh --url ${REPO_URL} --token ${RUNNER_TOKEN} --name ${RUNNER_NAME} --work ${RUNNER_WORKDIR} --unattended --replace 14 | fi 15 | 16 | # Start the runner 17 | exec ./run.sh -------------------------------------------------------------------------------- /.github/workflows/unifi_refresh.yml: -------------------------------------------------------------------------------- 1 | name: UniFi Refresh 2 | run-name: Refresh unifi_${{ github.event.inputs.refreshType }} 3 | 4 | on: 5 | workflow_dispatch: 6 | inputs: 7 | refreshType: 8 | type: choice 9 | description: 'Select the type of refresh' 10 | options: 11 | - 'all' 12 | - 'accounts' 13 | - 'ap_groups' 14 | - 'devices' 15 | - 'dynamic_dns' 16 | - 'firewall_groups' 17 | - 'firewall_rules' 18 | - 'networks' 19 | - 'port_forward' 20 | - 'port_profiles' 21 | - 'radius_profiles' 22 | - 'settings' 23 | - 'sites' 24 | - 'static_routes' 25 | - 'user_groups' 26 | - 'users' 27 | - 'wlans' 28 | required: true 29 | 30 | permissions: 31 | contents: write 32 | pull-requests: write 33 | 34 | jobs: 35 | refresh_unifi: 36 | runs-on: self-hosted 37 | defaults: 38 | run: 39 | shell: bash 40 | 41 | steps: 42 | - name: Checkout Repository 43 | uses: actions/checkout@v4.1.1 44 | 45 | - name: Run refresh script 46 | run: | 47 | ./scripts/get_${{ github.event.inputs.refreshType }}.sh -i ${{ secrets.UNIFI_URL }} -u ${{ secrets.UNIFI_USER }} -p ${{ secrets.UNIFI_PASSWORD }} 48 | ./scripts/generate_unifi_${{ github.event.inputs.refreshType }}.sh 49 | 50 | - name: Create Pull Request 51 | uses: peter-evans/create-pull-request@v5.0.2 52 | with: 53 | token: ${{ secrets.GITHUB_TOKEN }} 54 | commit-message: "Update unifi_${{ github.event.inputs.refreshType }}" 55 | title: "[AUTO] Update unifi_${{ github.event.inputs.refreshType }}" 56 | body: 'Automated pull request to update unifi_${{ github.event.inputs.refreshType }}' 57 | branch: 'update_unifi_${{ github.event.inputs.refreshType }}-${{ github.run_id }}' 58 | base: 'main' # or the branch you want to merge into 59 | delete-branch: true 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | crash.*.log 11 | 12 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 13 | # password, private keys, and other secrets. These should not be part of version 14 | # control as they are data points which are potentially sensitive and subject 15 | # to change depending on the environment. 16 | *.tfvars 17 | *.tfvars.json 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # !example_override.tf 28 | 29 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 30 | # example: *tfplan* 31 | 32 | # Ignore CLI configuration files 33 | .terraformrc 34 | terraform.rc 35 | 36 | json/*.json 37 | json/raw/*.json 38 | 39 | log.txt -------------------------------------------------------------------------------- /.terraform.lock.hcl: -------------------------------------------------------------------------------- 1 | # This file is maintained automatically by "terraform init". 2 | # Manual edits may be lost in future updates. 3 | 4 | provider "registry.terraform.io/paultyng/unifi" { 5 | version = "0.41.0" 6 | constraints = "0.41.0" 7 | hashes = [ 8 | "h1:vE4C9E7NtYUC7otQrAvNNkDFBHqEMxkUlcqJhLWchLY=", 9 | "zh:03ddd3aee05a08e1446f75a7b3f52810181d3307728cba08ce8fb67f109a9c00", 10 | "zh:11b14b79ad02b0a55fd6116b10c0eb6fab432dd7d1f3527af0e2055adf292451", 11 | "zh:18c0eb19889927f115a1e05d64f59b4e8d530ccdf1a8b574940a86be20973564", 12 | "zh:2df9ca0c21830d2757758e574b19d0d4e54965ce80dbbfb3f124db1dac3d7e8f", 13 | "zh:36274af3b7e8b08ba69c04a226c63e0dd2ec386c583288ebd7bc2a30e349ee8f", 14 | "zh:413eb222ef30889bab33ccbfc46c9fb64307555da34eac4625d51e696ac72e1d", 15 | "zh:4839814ff9f405a13397ffadd6f1052c770b88802280a4d8cde066f9a19718c7", 16 | "zh:9547b7831852cc5b9c0fd13ab447d48539eae94582c8725ad255af36e31fb5d9", 17 | "zh:a855c89b12326eb1c89bbf292a2bb1de3651794e3409d5012076ada89aabdc8a", 18 | "zh:aef12a33b90fd77a9bf4e9d397966ccbfa4a037a648a1725074aff2db2d90fb0", 19 | "zh:b3c72a6a02e29b4d21aa0d0831a272ca7cb82c3f8c2c3c7f09fcc2d2dcd78752", 20 | "zh:c8354eaaab5f526e8e530b098544c7583a0f0b5b27d67500c7b3e9da56a3a7e5", 21 | "zh:dc29f1e70f20ce86d3c6a66c7a817616f993a1cf9d941604dfd5222a06992c4c", 22 | "zh:e772779333419f34d2c6da333c7f7d235a5a34f21ea47636b548e132aed74f3b", 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UniFi Terraform Configuration Generator 2 | 3 | ## Overview 4 | This repository facilitates the creation of a complete Terraform configuration for managing Ubiquiti UniFi environments. It leverages bash, jq, and curl to automate the extraction, manipulation, and generation of Terraform configurations specific to UniFi devices and settings. 5 | 6 | ## Getting Started 7 | 8 | ### Prerequisites 9 | - A functioning Ubiquiti UniFi setup. Tested with UDM Pro, but should work for other controllers. 10 | - Basic understanding of bash, jq, and curl. 11 | - An environment with: 12 | - connectivity to the local Unifi controller endpoint 13 | - local unifi user account with `admin` access 14 | - NOTE: `viewer` access will allow creation of some resources, but will be unable to 15 | access any sensitive fields such as controller SSH settings or radius auth settings. 16 | Results may be inconsistent. For the moment, consider this unsupported. 17 | - bash 4.0+ 18 | - Almost every major linux distribution ships with this, though the default may be something else (ksh, zsh). Run `bash` to enter the bash terminal, and `bash --version` to verify that you are on 4.0+ 19 | - Mac OS still ships with bash 3.2 as the default version. This is 10+ years out-of-date, and does not support associative arrays, which are used heavily in this project. The easiest way to correct for this is to install a newer version of bash with brew. This will not overwrite the default shell; the two exist in tandem. 20 | ```bash 21 | brew install bash 22 | ``` 23 | After installing this newer version of bash, it should be added to your `PATH` automatically, and the scripts should automatically reference it. You can verify that you are on v4.0+ by running `bash --version`: 24 | 25 | ```bash 26 | GNU bash, version 5.2.26(1)-release (x86_64-apple-darwin23.2.0) 27 | Copyright (C) 2022 Free Software Foundation, Inc. 28 | License GPLv3+: GNU GPL version 3 or later 29 | 30 | This is free software; you are free to change and redistribute it. 31 | There is NO WARRANTY, to the extent permitted by law. 32 | ``` 33 | 34 | - curl 35 | - jq 36 | - For Ubuntu, this can be achieved with the following script: 37 | ``` 38 | apt-get install -y jq 39 | ``` 40 | For Mac OS, this can be achieved with the following script: 41 | ``` 42 | brew install jq 43 | ``` 44 | - utf-8 english language support (necessary for parsing some special characters) 45 | - For Ubuntu, this can be achieved with the following script: 46 | ``` 47 | apt-get install -y locales 48 | locale-gen en_US.UTF-8 49 | LANG=en_US.UTF-8 50 | LANGUAGE=en_US:en 51 | LC_ALL=en_US.UTF-8 52 | ``` 53 | - For Mac OS, this is enabled by default 54 | 55 | ### Installation and Setup 56 | 57 | #### GitHub Codespaces (Recommended) 58 | 59 | 1. Install the GitHub CLI: https://cli.github.com/ 60 | 1. Install the Codespaces Network Bridge: https://github.com/github/gh-net 61 | 1. Fork this repository 62 | 1. Set three codespace secrets: 63 | 1. SECRET_UNIFI_IP 64 | - Example Value: 192.168.1.1 65 | 1. SECRET_UNIFI_USER 66 | - Example Value: terraform-generator 67 | 1. SECRET_UNIFI_PASSWORD 68 | - Example Value: YoUrSuP3rS3cRetP@ssW0rd 69 | 1. Launch the codespace 70 | 1. In a local terminal, execute `gh net` and connect to your codespace 71 | 1. In the codespace, execute: 72 | `./scripts/all.sh` 73 | 1. All terraform code will be generated at the root level of the repository 74 | 75 | #### Local Execution 76 | 77 | 1. Clone the repository. 78 | 1. Execute `./scripts/all.sh -i $YOURIP -u $YOURUSER -p $YOURPASSWORD` 79 | - Alternatively, set the environment variables `SECRET_UNIFI_IP` `SECRET_UNIFI_USER` and `SECRET_UNIFI_PASSWORD` and run `./scripts/all.sh` 80 | 1. All terraform code will be generated at the root level of the repository 81 | 82 | #### GitHub Actions 83 | 84 | 1. Create a github self-hosted runner, with the capabilities listed in Actions_Dockerfile, on your home network 85 | 1. A prebuilt image is available at docker.io/robbycuenot/gh-runner-ubuntu:latest, built from that file 86 | 1. Launch that container with the following environment variables: 87 | - RUNNER_TOKEN=YOURGHRUNNERTOKEN 88 | - REPO_URL=https://github.com/youraccountororganizationname 89 | - RUNNER_NAME=gh-runner-ubuntu 90 | - RUNNER_WORKDIR=_work 91 | - **NOTE:** You may want to configure persistent volumes, otherwise you will have to re-register the container 92 | every time it restarts. I've tried to lay the groundwork for mounting /home/runner, however podman permissions 93 | for volumes are frustrating as hell and I've not been able to get it working. PRs welcome if you have a fix. 94 | 1. Verify that your container has started and successfully registered with GitHub 95 | 1. Under repository settings, check `Allow GitHub Actions to create and approve pull requests`. 96 | 1. Invoke the `Unifi Refresh` workflow, selecting `all` to generate code for the entire Unifi network. 97 | 98 | ## Repository Structure 99 | 100 | ### `/scripts` 101 | This directory is the heart of the repository, containing a suite of bash scripts which interact with the UniFi Controller API to fetch and generate necessary data. These scripts use `jq` for JSON parsing and `curl` for API interactions. Key script categories include: 102 | 103 | - **Data Retrieval Scripts**: (`get_*.sh`) Fetch data from UniFi controllers for existing configurations, which can then be used in generating Terraform configurations. 104 | - **Generation Scripts**: (`generate_*.sh`) Create Terraform configuration files for various UniFi components like networks, WLANs, user groups, etc. 105 | - **Utility Scripts**: (`*_utils.sh`) Provide supporting functions such as JSON manipulation and Terraform configuration assistance. 106 | 107 | ### Other Directories and Files 108 | - `/.devcontainer`: Contains container configurations for codespaces. 109 | - `/.github/workflows`: GitHub Actions workflow for generating TF code / PRs. 110 | - `/docs`: Reference architecture documents and sample terraform files 111 | - `/json`: Folder for normalized json data. Raw responses are in `/json/raw`. Json files themselves are excluded from commits via `.gitignore`. 112 | - `/log.txt`: Logs generated at runtime. Excluded via `.gitignore`. 113 | - `/providers.tf`: Terraform provider setup. Substitute organization and workspace name as needed for Terraform Cloud 114 | - `/tests`: For now, contains a basic docker container to serve raw json responses at endpoints that mirror a network controller. TODO: Add sample json 115 | - `/README.md`: This README file. 116 | 117 | ## Contributing 118 | Contributions are welcome! Will write contribution guidelines as this project progresses. 119 | -------------------------------------------------------------------------------- /docs/networks.md: -------------------------------------------------------------------------------- 1 | # Network Reference Architecture 2 | 3 | ## Overview 4 | 5 | This document outlines the VLAN configuration for the network, detailing each VLAN's purpose, associated CIDR, and category. Terraform code for deploying this infrastructure can be found at [reference/unifi_networks.tf](reference/unifi_networks.tf) 6 | 7 | ## VLAN Configuration 8 | 9 | Below is the table of VLANs, showing their designated current CIDRs, maximum expandable CIDRs, and the number of usable IPs for each. 10 | 11 | | VLAN | VLAN Name | CIDR | Max CIDR | Category | Usable IPs | Max Usable IPs | 12 | |------|--------------|---------------|---------------|--------------------|------------|----------------| 13 | | 1 | Default | 10.0.0.1/24 | 10.0.0.1/20 | High Security | 254 | 4094 | 14 | | 16 | Management | 10.0.16.1/24 | 10.0.16.1/20 | High Security | 254 | 4094 | 15 | | 32 | Storage | 10.0.32.1/24 | 10.0.32.1/20 | High Security | 254 | 4094 | 16 | | 48 | CI/CD | 10.0.48.1/24 | 10.0.48.1/20 | High Security | 254 | 4094 | 17 | | 64 | Lab Prod | 10.0.64.1/24 | 10.0.64.1/20 | Lab Environments | 254 | 4094 | 18 | | 80 | Lab Dev | 10.0.80.1/24 | 10.0.80.1/20 | Lab Environments | 254 | 4094 | 19 | | 96 | Lab Sandbox | 10.0.96.1/24 | 10.0.96.1/20 | Lab Environments | 254 | 4094 | 20 | | 112 | Personal | 10.0.112.1/24 | 10.0.112.1/20 | Low Security | 254 | 4094 | 21 | | 128 | VPN | 10.0.128.1/24 | 10.0.128.1/20 | Low Security | 254 | 4094 | 22 | | 144 | Printers | 10.0.144.1/24 | 10.0.144.1/20 | Low Security | 254 | 4094 | 23 | | 160 | IoT | 10.0.160.1/24 | 10.0.160.1/20 | Low Security | 254 | 4094 | 24 | | 176 | Guest | 10.0.176.1/24 | 10.0.176.1/20 | Low Security | 254 | 4094 | 25 | | 192 | AWS | 10.0.192.1/24 | 10.0.192.1/20 | Cloud Environments | 254 | 4094 | 26 | | 208 | Azure | 10.0.208.1/24 | 10.0.208.1/20 | Cloud Environments | 254 | 4094 | 27 | | 224 | Google Cloud | 10.0.224.1/24 | 10.0.224.1/20 | Cloud Environments | 254 | 4094 | 28 | | | Reserved | | 10.0.240.1/20 | Reserved | | 4094 | 29 | 30 | ### Key Points: 31 | - **Current CIDR:** The subnet currently in use for each VLAN. 32 | - **Maximum CIDR:** The largest subnet space reserved for potential expansion of the corresponding VLAN. 33 | - **Category:** The type of environment or use case for each VLAN. 34 | - **Usable IPs:** The number of usable IP addresses in the current and maximum allocations. 35 | 36 | ## Conclusion 37 | 38 | This VLAN configuration is structured to provide a clear, logical, and secure network environment, catering to various requirements from high security to cloud integrations. It's designed for scalability and efficient management, ensuring that network resources are optimally utilized and future expansions can be accommodated. 39 | -------------------------------------------------------------------------------- /docs/reference/unifi_networks.tf: -------------------------------------------------------------------------------- 1 | resource "unifi_network" "default" { 2 | name = "Default" 3 | site = local.unifi_site_Default.name 4 | purpose = "corporate" 5 | network_group = "LAN" 6 | 7 | subnet = "10.0.0.1/24" 8 | 9 | dhcp_enabled = true 10 | dhcp_lease = 86400 11 | dhcp_relay_enabled = false 12 | dhcp_start = "10.0.0.100" 13 | dhcp_stop = "10.0.0.254" 14 | dhcp_v6_dns_auto = true 15 | dhcpd_boot_enabled = false 16 | domain_name = "default.lan" 17 | igmp_snooping = false 18 | internet_access_enabled = true 19 | ipv6_interface_type = "none" 20 | ipv6_ra_enable = true 21 | ipv6_ra_preferred_lifetime = 14400 22 | ipv6_ra_valid_lifetime = 86400 23 | multicast_dns = true 24 | 25 | lifecycle { 26 | prevent_destroy = true 27 | } 28 | } 29 | 30 | resource "unifi_network" "management" { 31 | name = "Management" 32 | site = local.unifi_site_Default.name 33 | purpose = "corporate" 34 | network_group = "LAN" 35 | 36 | subnet = "10.0.16.1/24" 37 | vlan_id = 16 38 | 39 | dhcp_enabled = true 40 | dhcp_lease = 86400 41 | dhcp_relay_enabled = false 42 | dhcp_start = "10.0.16.100" 43 | dhcp_stop = "10.0.16.254" 44 | dhcp_v6_dns_auto = true 45 | dhcpd_boot_enabled = false 46 | domain_name = "management.lan" 47 | igmp_snooping = false 48 | internet_access_enabled = true 49 | ipv6_interface_type = "none" 50 | ipv6_ra_enable = false 51 | ipv6_ra_preferred_lifetime = 14400 52 | ipv6_ra_valid_lifetime = 86400 53 | multicast_dns = true 54 | 55 | lifecycle { 56 | prevent_destroy = true 57 | } 58 | } 59 | 60 | resource "unifi_network" "storage" { 61 | name = "Storage" 62 | site = local.unifi_site_Default.name 63 | purpose = "corporate" 64 | network_group = "LAN" 65 | 66 | subnet = "10.0.32.1/24" 67 | vlan_id = 32 68 | 69 | dhcp_enabled = true 70 | dhcp_lease = 86400 71 | dhcp_relay_enabled = false 72 | dhcp_start = "10.0.32.100" 73 | dhcp_stop = "10.0.32.254" 74 | dhcp_v6_dns_auto = true 75 | dhcpd_boot_enabled = false 76 | domain_name = "storage.lan" 77 | igmp_snooping = false 78 | internet_access_enabled = true 79 | ipv6_interface_type = "none" 80 | ipv6_ra_enable = false 81 | ipv6_ra_preferred_lifetime = 14400 82 | ipv6_ra_valid_lifetime = 86400 83 | multicast_dns = true 84 | 85 | lifecycle { 86 | prevent_destroy = true 87 | } 88 | } 89 | 90 | resource "unifi_network" "ci_cd" { 91 | name = "CI/CD" 92 | site = local.unifi_site_Default.name 93 | purpose = "corporate" 94 | network_group = "LAN" 95 | 96 | subnet = "10.0.48.1/24" 97 | vlan_id = 48 98 | 99 | dhcp_enabled = true 100 | dhcp_lease = 86400 101 | dhcp_relay_enabled = false 102 | dhcp_start = "10.0.48.100" 103 | dhcp_stop = "10.0.48.254" 104 | dhcp_v6_dns_auto = true 105 | dhcpd_boot_enabled = false 106 | domain_name = "ci-cd.lan" 107 | igmp_snooping = false 108 | internet_access_enabled = true 109 | ipv6_interface_type = "none" 110 | ipv6_ra_enable = false 111 | ipv6_ra_preferred_lifetime = 14400 112 | ipv6_ra_valid_lifetime = 86400 113 | multicast_dns = true 114 | 115 | lifecycle { 116 | prevent_destroy = true 117 | } 118 | } 119 | 120 | resource "unifi_network" "lab_prod" { 121 | name = "Lab Prod" 122 | site = local.unifi_site_Default.name 123 | purpose = "corporate" 124 | network_group = "LAN" 125 | 126 | subnet = "10.0.64.1/24" 127 | vlan_id = 64 128 | 129 | dhcp_enabled = true 130 | dhcp_lease = 86400 131 | dhcp_relay_enabled = false 132 | dhcp_start = "10.0.64.100" 133 | dhcp_stop = "10.0.64.254" 134 | dhcp_v6_dns_auto = true 135 | dhcpd_boot_enabled = false 136 | domain_name = "lab-prod.lan" 137 | igmp_snooping = false 138 | internet_access_enabled = true 139 | ipv6_interface_type = "none" 140 | ipv6_ra_enable = false 141 | ipv6_ra_preferred_lifetime = 14400 142 | ipv6_ra_valid_lifetime = 86400 143 | multicast_dns = true 144 | 145 | lifecycle { 146 | prevent_destroy = true 147 | } 148 | } 149 | 150 | resource "unifi_network" "lab_dev" { 151 | name = "Lab Dev" 152 | site = local.unifi_site_Default.name 153 | purpose = "corporate" 154 | network_group = "LAN" 155 | 156 | subnet = "10.0.80.1/24" 157 | vlan_id = 80 158 | 159 | dhcp_enabled = true 160 | dhcp_lease = 86400 161 | dhcp_relay_enabled = false 162 | dhcp_start = "10.0.80.100" 163 | dhcp_stop = "10.0.80.254" 164 | dhcp_v6_dns_auto = true 165 | dhcpd_boot_enabled = false 166 | domain_name = "lab-dev.lan" 167 | igmp_snooping = false 168 | internet_access_enabled = true 169 | ipv6_interface_type = "none" 170 | ipv6_ra_enable = false 171 | ipv6_ra_preferred_lifetime = 14400 172 | ipv6_ra_valid_lifetime = 86400 173 | multicast_dns = true 174 | 175 | lifecycle { 176 | prevent_destroy = true 177 | } 178 | } 179 | 180 | resource "unifi_network" "lab_sandbox" { 181 | name = "Lab Sandbox" 182 | site = local.unifi_site_Default.name 183 | purpose = "corporate" 184 | network_group = "LAN" 185 | 186 | subnet = "10.0.96.1/24" 187 | vlan_id = 96 188 | 189 | dhcp_enabled = true 190 | dhcp_lease = 86400 191 | dhcp_relay_enabled = false 192 | dhcp_start = "10.0.96.100" 193 | dhcp_stop = "10.0.96.254" 194 | dhcp_v6_dns_auto = true 195 | dhcpd_boot_enabled = false 196 | domain_name = "lab-sandbox.lan" 197 | igmp_snooping = false 198 | internet_access_enabled = true 199 | ipv6_interface_type = "none" 200 | ipv6_ra_enable = false 201 | ipv6_ra_preferred_lifetime = 14400 202 | ipv6_ra_valid_lifetime = 86400 203 | multicast_dns = true 204 | 205 | lifecycle { 206 | prevent_destroy = true 207 | } 208 | } 209 | 210 | resource "unifi_network" "personal" { 211 | name = "Personal" 212 | site = local.unifi_site_Default.name 213 | purpose = "corporate" 214 | network_group = "LAN" 215 | 216 | subnet = "10.0.112.1/24" 217 | vlan_id = 112 218 | 219 | dhcp_enabled = true 220 | dhcp_lease = 86400 221 | dhcp_relay_enabled = false 222 | dhcp_start = "10.0.112.100" 223 | dhcp_stop = "10.0.112.254" 224 | dhcp_v6_dns_auto = true 225 | dhcpd_boot_enabled = false 226 | domain_name = "personal.lan" 227 | igmp_snooping = false 228 | internet_access_enabled = true 229 | ipv6_interface_type = "none" 230 | ipv6_ra_enable = false 231 | ipv6_ra_preferred_lifetime = 14400 232 | ipv6_ra_valid_lifetime = 86400 233 | multicast_dns = true 234 | 235 | lifecycle { 236 | prevent_destroy = true 237 | } 238 | } 239 | 240 | resource "unifi_network" "vpn" { 241 | name = "VPN" 242 | site = local.unifi_site_Default.name 243 | purpose = "corporate" 244 | network_group = "LAN" 245 | 246 | subnet = "10.0.128.1/24" 247 | vlan_id = 128 248 | 249 | dhcp_enabled = true 250 | dhcp_lease = 86400 251 | dhcp_relay_enabled = false 252 | dhcp_start = "10.0.128.100" 253 | dhcp_stop = "10.0.128.254" 254 | dhcp_v6_dns_auto = true 255 | dhcpd_boot_enabled = false 256 | domain_name = "vpn.lan" 257 | igmp_snooping = false 258 | internet_access_enabled = true 259 | ipv6_interface_type = "none" 260 | ipv6_ra_enable = false 261 | ipv6_ra_preferred_lifetime = 14400 262 | ipv6_ra_valid_lifetime = 86400 263 | multicast_dns = true 264 | 265 | lifecycle { 266 | prevent_destroy = true 267 | } 268 | } 269 | 270 | resource "unifi_network" "printers" { 271 | name = "Printers" 272 | site = local.unifi_site_Default.name 273 | purpose = "corporate" 274 | network_group = "LAN" 275 | 276 | subnet = "10.0.144.1/24" 277 | vlan_id = 144 278 | 279 | dhcp_enabled = true 280 | dhcp_lease = 86400 281 | dhcp_relay_enabled = false 282 | dhcp_start = "10.0.144.100" 283 | dhcp_stop = "10.0.144.254" 284 | dhcp_v6_dns_auto = true 285 | dhcpd_boot_enabled = false 286 | domain_name = "printers.lan" 287 | igmp_snooping = false 288 | internet_access_enabled = true 289 | ipv6_interface_type = "none" 290 | ipv6_ra_enable = false 291 | ipv6_ra_preferred_lifetime = 14400 292 | ipv6_ra_valid_lifetime = 86400 293 | multicast_dns = true 294 | 295 | lifecycle { 296 | prevent_destroy = true 297 | } 298 | } 299 | 300 | resource "unifi_network" "iot" { 301 | name = "IoT" 302 | site = local.unifi_site_Default.name 303 | purpose = "corporate" 304 | network_group = "LAN" 305 | 306 | subnet = "10.0.160.1/24" 307 | vlan_id = 160 308 | 309 | dhcp_enabled = true 310 | dhcp_lease = 86400 311 | dhcp_relay_enabled = false 312 | dhcp_start = "10.0.160.100" 313 | dhcp_stop = "10.0.160.254" 314 | dhcp_v6_dns_auto = true 315 | dhcpd_boot_enabled = false 316 | domain_name = "iot.lan" 317 | igmp_snooping = false 318 | internet_access_enabled = true 319 | ipv6_interface_type = "none" 320 | ipv6_ra_enable = false 321 | ipv6_ra_preferred_lifetime = 14400 322 | ipv6_ra_valid_lifetime = 86400 323 | multicast_dns = true 324 | 325 | lifecycle { 326 | prevent_destroy = true 327 | } 328 | } 329 | 330 | resource "unifi_network" "guest" { 331 | name = "Guest" 332 | site = local.unifi_site_Default.name 333 | purpose = "guest" 334 | network_group = "LAN" 335 | 336 | subnet = "10.0.176.1/24" 337 | vlan_id = 176 338 | 339 | dhcp_enabled = true 340 | dhcp_lease = 86400 341 | dhcp_relay_enabled = false 342 | dhcp_start = "10.0.176.100" 343 | dhcp_stop = "10.0.176.254" 344 | dhcp_v6_dns_auto = true 345 | dhcpd_boot_enabled = false 346 | domain_name = "guest.lan" 347 | igmp_snooping = false 348 | internet_access_enabled = true 349 | ipv6_interface_type = "none" 350 | ipv6_ra_enable = false 351 | ipv6_ra_preferred_lifetime = 14400 352 | ipv6_ra_valid_lifetime = 86400 353 | multicast_dns = true 354 | 355 | lifecycle { 356 | prevent_destroy = true 357 | } 358 | } 359 | 360 | resource "unifi_network" "aws" { 361 | name = "AWS" 362 | site = local.unifi_site_Default.name 363 | purpose = "corporate" 364 | network_group = "LAN" 365 | 366 | subnet = "10.0.192.1/24" 367 | vlan_id = 192 368 | 369 | dhcp_enabled = true 370 | dhcp_lease = 86400 371 | dhcp_relay_enabled = false 372 | dhcp_start = "10.0.192.100" 373 | dhcp_stop = "10.0.192.254" 374 | dhcp_v6_dns_auto = true 375 | dhcpd_boot_enabled = false 376 | domain_name = "aws.lan" 377 | igmp_snooping = false 378 | internet_access_enabled = true 379 | ipv6_interface_type = "none" 380 | ipv6_ra_enable = false 381 | ipv6_ra_preferred_lifetime = 14400 382 | ipv6_ra_valid_lifetime = 86400 383 | multicast_dns = true 384 | 385 | lifecycle { 386 | prevent_destroy = true 387 | } 388 | } 389 | 390 | resource "unifi_network" "azure" { 391 | name = "Azure" 392 | site = local.unifi_site_Default.name 393 | purpose = "corporate" 394 | network_group = "LAN" 395 | 396 | subnet = "10.0.208.1/24" 397 | vlan_id = 208 398 | 399 | dhcp_enabled = true 400 | dhcp_lease = 86400 401 | dhcp_relay_enabled = false 402 | dhcp_start = "10.0.208.100" 403 | dhcp_stop = "10.0.208.254" 404 | dhcp_v6_dns_auto = true 405 | dhcpd_boot_enabled = false 406 | domain_name = "azure.lan" 407 | igmp_snooping = false 408 | internet_access_enabled = true 409 | ipv6_interface_type = "none" 410 | ipv6_ra_enable = false 411 | ipv6_ra_preferred_lifetime = 14400 412 | ipv6_ra_valid_lifetime = 86400 413 | multicast_dns = true 414 | 415 | lifecycle { 416 | prevent_destroy = true 417 | } 418 | } 419 | 420 | resource "unifi_network" "google_cloud" { 421 | name = "Google Cloud" 422 | site = local.unifi_site_Default.name 423 | purpose = "corporate" 424 | network_group = "LAN" 425 | 426 | subnet = "10.0.224.1/24" 427 | vlan_id = 224 428 | 429 | dhcp_enabled = true 430 | dhcp_lease = 86400 431 | dhcp_relay_enabled = false 432 | dhcp_start = "10.0.224.100" 433 | dhcp_stop = "10.0.224.254" 434 | dhcp_v6_dns_auto = true 435 | dhcpd_boot_enabled = false 436 | domain_name = "google-cloud.lan" 437 | igmp_snooping = false 438 | internet_access_enabled = true 439 | ipv6_interface_type = "none" 440 | ipv6_ra_enable = false 441 | ipv6_ra_preferred_lifetime = 14400 442 | ipv6_ra_valid_lifetime = 86400 443 | multicast_dns = true 444 | 445 | lifecycle { 446 | prevent_destroy = true 447 | } 448 | } 449 | 450 | -------------------------------------------------------------------------------- /json/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbycuenot/unifi-tf-generator/c747be85d2a2771a6179f24e2facfb0e3cf868c5/json/.keep -------------------------------------------------------------------------------- /json/raw/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbycuenot/unifi-tf-generator/c747be85d2a2771a6179f24e2facfb0e3cf868c5/json/raw/.keep -------------------------------------------------------------------------------- /providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.6.3" 3 | cloud { 4 | organization = "example" 5 | 6 | workspaces { 7 | name = "unifi-management" 8 | } 9 | } 10 | 11 | required_providers { 12 | unifi = { 13 | source = "paultyng/unifi" 14 | version = "0.41.0" 15 | } 16 | } 17 | } 18 | 19 | provider "unifi" {} -------------------------------------------------------------------------------- /scripts/all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source ./scripts/log_utils.sh 3 | log_debug "Executing all.sh..." 4 | 5 | # Source get_token.sh to set TOKEN and UNIFI_IP 6 | source ./scripts/get_token.sh "$@" 7 | 8 | ./scripts/get_all.sh -i $UNIFI_IP -t $TOKEN 9 | ./scripts/generate_unifi_all.sh 10 | 11 | log_debug "Finished executing all.sh" 12 | -------------------------------------------------------------------------------- /scripts/generate_unifi_accounts.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility script 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/accounts.json" 9 | readonly KEYS=( 10 | "_id" 11 | "name" 12 | "tunnel_medium_type" 13 | "tunnel_type" 14 | ) 15 | 16 | write_resource() { 17 | local -n args=$1 # Use a nameref to refer to the associative array 18 | 19 | { 20 | echo "resource \"unifi_account\" \"${args[sanitized_id]}\" {" 21 | c_echo "name" " name = \"%s\"" 22 | echo " password = var.unifi_account_${args[name]}_password" 23 | echo "" 24 | c_echo "tunnel_medium_type" " tunnel_medium_type = %s" 25 | c_echo "tunnel_type" " tunnel_type = %s" 26 | echo "}" 27 | echo "" 28 | } >> unifi_accounts.tf 29 | } 30 | 31 | write_import() { 32 | local -n args=$1 33 | 34 | { 35 | echo "import {" 36 | echo " to = unifi_account.${args[sanitized_id]}" 37 | echo " id = \"${args[_id]}\"" 38 | echo "}" 39 | echo "" 40 | } >> unifi_accounts_import.tf 41 | } 42 | 43 | write_local() { 44 | local -n args=$1 45 | 46 | echo " unifi_account_${args[sanitized_name]} = unifi_account.${args[sanitized_id]}" >> unifi_accounts_map.tf 47 | } 48 | 49 | main() { 50 | # Clear existing files or create them if they don't exist 51 | > unifi_accounts.tf 52 | > unifi_accounts_import.tf 53 | > unifi_accounts_map.tf 54 | 55 | echo "locals {" > unifi_accounts_map.tf 56 | 57 | log_console_object_count "$json_file_name" 58 | 59 | # Process each line from read_json 60 | while IFS='◊' read -ra line_data; do 61 | declare -A resource_args 62 | 63 | # Map read values to associative array using KEYS 64 | for index in "${!KEYS[@]}"; do 65 | resource_args["${KEYS[index]}"]="${line_data[index]}" 66 | done 67 | 68 | # Parse additional data for Terraform identifiers 69 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 70 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 71 | 72 | log_debug " Writing object: type=account id=${resource_args[_id]} name=${resource_args[name]}" 73 | 74 | # Write the resource blocks 75 | write_resource resource_args 76 | 77 | # Write the import blocks 78 | write_import resource_args 79 | 80 | # Write the locals block 81 | write_local resource_args 82 | 83 | done < <(read_json "$json_file_name" KEYS) 84 | 85 | # Write the footer for the locals block 86 | echo "}" >> unifi_accounts_map.tf 87 | } 88 | 89 | # Execute the main function 90 | main 91 | -------------------------------------------------------------------------------- /scripts/generate_unifi_all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/log_utils.sh 4 | 5 | log_debug "Executing generate_unifi_all.sh..." 6 | 7 | ./scripts/generate_unifi_sites.sh 8 | ./scripts/generate_unifi_networks.sh 9 | ./scripts/generate_unifi_dynamic_dns.sh 10 | ./scripts/generate_unifi_user_groups.sh 11 | ./scripts/generate_unifi_users.sh 12 | ./scripts/generate_unifi_port_forward.sh 13 | 14 | # Devices and port profiles are dependent on each other 15 | # for mappings. Executing one of them redundantly will 16 | # resolve the mapping issue. 17 | if [ ! -f unifi_devices_map.tf ]; then 18 | log_console "" 19 | log_console "unifi_devices_map.tf not found. Port profiles" 20 | log_console "will be generated first, and will display a mapping error." 21 | log_console "This is expected, will be resolved when it executes again after" 22 | log_console "generating devices. Once the initial codebase has been generated," 23 | log_console "the error will resolve and port profiles will only be executed once" 24 | log_console "per run." 25 | log_console "" 26 | ./scripts/generate_unifi_port_profiles.sh 27 | ./scripts/generate_unifi_devices.sh 28 | ./scripts/generate_unifi_port_profiles.sh 29 | else 30 | ./scripts/generate_unifi_port_profiles.sh 31 | ./scripts/generate_unifi_devices.sh 32 | fi 33 | 34 | ./scripts/generate_unifi_ap_groups.sh 35 | ./scripts/generate_unifi_radius_profiles.sh 36 | ./scripts/generate_unifi_accounts.sh 37 | ./scripts/generate_unifi_wlans.sh 38 | ./scripts/generate_unifi_settings.sh 39 | ./scripts/generate_unifi_firewall_groups.sh 40 | ./scripts/generate_unifi_firewall_rules.sh 41 | ./scripts/generate_unifi_static_routes.sh 42 | ./scripts/generate_variables.sh 43 | 44 | log_debug "Finished executing generate_unifi_all.sh" 45 | -------------------------------------------------------------------------------- /scripts/generate_unifi_ap_groups.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility script 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/ap_groups.json" 9 | readonly KEYS=( 10 | "_id" 11 | "attr_hidden_id" 12 | "attr_no_delete" 13 | "device_macs" 14 | "for_wlanconf" 15 | "name" 16 | ) 17 | 18 | write_data() { 19 | local -n args=$1 # Use a nameref to refer to the associative array 20 | 21 | { 22 | echo "data \"unifi_ap_group\" \"${args[sanitized_id]}\" {" 23 | if [ "${args[attr_hidden_id]}" = "default" ]; then 24 | echo " # Commenting out name, as this is the default group" 25 | c_echo "name" " # name = \"%s\"" 26 | else 27 | c_echo "name" " name = \"%s\"" 28 | fi 29 | c_echo "attr_hidden_id" " # attr_hidden_id = \"%s\"" 30 | c_echo "attr_no_delete" " # attr_no_delete = %s" 31 | c_echo "for_wlanconf" " # for_wlanconf = %s" 32 | 33 | # Conditionally write the device_macs 34 | c_echo_macs "${args[device_macs]}" 35 | 36 | echo "}" 37 | echo "" 38 | } >> unifi_ap_groups.tf 39 | } 40 | 41 | write_local() { 42 | local -n args=$1 # Use a nameref to refer to the associative array 43 | 44 | echo " unifi_ap_group_${args[sanitized_name]} = data.unifi_ap_group.${args[sanitized_id]}" >> unifi_ap_groups_map.tf 45 | } 46 | 47 | main() { 48 | # Load the mappings for retrieving names from IDs 49 | load_device_mappings 50 | 51 | # Clear existing files or create them if they don't exist 52 | > unifi_ap_groups.tf 53 | echo "locals {" > unifi_ap_groups_map.tf 54 | 55 | log_console_object_count "$json_file_name" 56 | 57 | # Process each line from read_json 58 | while IFS='◊' read -ra line_data; do 59 | declare -A resource_args 60 | 61 | # Map read values to associative array using KEYS 62 | for index in "${!KEYS[@]}"; do 63 | resource_args["${KEYS[index]}"]="${line_data[index]}" 64 | done 65 | 66 | # Parse additional data for Terraform identifiers 67 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 68 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 69 | 70 | log_debug " Writing object: type=ap_group id=${resource_args[_id]} name=${resource_args[name]}" 71 | 72 | # Write the data blocks by passing the associative array 73 | write_data resource_args 74 | 75 | # Write the locals block by passing the associative array 76 | write_local resource_args 77 | 78 | done < <(read_json "$json_file_name" KEYS) 79 | 80 | # Write the footer for the locals block 81 | echo "}" >> unifi_ap_groups_map.tf 82 | } 83 | 84 | # Execute the main function 85 | main 86 | -------------------------------------------------------------------------------- /scripts/generate_unifi_devices.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility script 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/devices.json" 9 | readonly KEYS=( 10 | "_id" 11 | "disabled" 12 | "ip" 13 | "lan_ip" 14 | "mac" 15 | "model" 16 | "name" 17 | "port_table" 18 | ) 19 | 20 | write_resource() { 21 | local -n args=$1 # Use a nameref to refer to the associative array 22 | 23 | { 24 | echo "resource \"unifi_device\" \"${args[sanitized_mac]}\" {" 25 | 26 | c_echo "name" " name = \"%s\"" 27 | c_echo "mac" " mac = \"%s\"" 28 | echo " site = local.unifi_site_Default.name" 29 | 30 | # Commented fields 31 | c_echo "model" " # model = \"%s\"" 32 | # Handling the conditional presence of lan_ip or ip 33 | if [ -n "${args[lan_ip]}" ]; then 34 | c_echo "lan_ip" " # lan_ip = \"%s\"" 35 | else 36 | c_echo "ip" " # ip = \"%s\"" 37 | fi 38 | c_echo "disabled" " # disabled = %s" # Assuming 'disabled' value is a boolean 39 | 40 | echo "" 41 | 42 | # Conditionally write the port overrides 43 | c_echo_port_overrides "${args[port_table]}" 44 | 45 | echo " allow_adoption = false" 46 | echo " forget_on_destroy = false" 47 | echo "" 48 | echo " lifecycle {" 49 | echo " prevent_destroy = true" 50 | echo " }" 51 | echo "}" 52 | echo "" 53 | } >> unifi_devices.tf 54 | } 55 | 56 | write_import() { 57 | local -n args=$1 # Use a nameref to refer to the associative array 58 | 59 | { 60 | echo "import {" 61 | echo " to = unifi_device.${args[sanitized_mac]}" 62 | echo " id = \"${args[_id]}\"" 63 | echo "}" 64 | echo "" 65 | } >> unifi_devices_import.tf 66 | } 67 | 68 | write_local() { 69 | local -n args=$1 # Use a nameref to refer to the associative array 70 | 71 | echo " unifi_device_${args[sanitized_name]} = unifi_device.${args[sanitized_mac]}" >> unifi_devices_map.tf 72 | } 73 | 74 | 75 | main() { 76 | # Load the mappings for retrieving names from IDs 77 | load_port_profile_mappings 78 | 79 | # Clear existing files or create them if they don't exist 80 | > unifi_devices.tf 81 | > unifi_devices_import.tf 82 | > unifi_devices_map.tf 83 | 84 | # Initialize unifi_devices_map.tf with the header 85 | echo "locals {" > unifi_devices_map.tf 86 | 87 | log_console_object_count "$json_file_name" 88 | 89 | # Process each line from read_json 90 | while IFS='◊' read -ra values; do 91 | 92 | # Create an associative array from the keys and values 93 | declare -A resource_args 94 | 95 | for index in "${!KEYS[@]}"; do 96 | resource_args["${KEYS[index]}"]="${values[index]}" 97 | done 98 | 99 | # Parse additional data 100 | resource_args[sanitized_mac]="id_$(sanitize_for_terraform "${resource_args[mac]}")" 101 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 102 | 103 | log_debug " Writing object: type=device id=${resource_args[_id]} mac=${resource_args[mac]} name=${resource_args[name]}" 104 | 105 | # Write the resource blocks 106 | write_resource resource_args 107 | 108 | # Write the import blocks 109 | write_import resource_args 110 | 111 | # Write the locals block 112 | write_local resource_args 113 | 114 | done < <(read_json "$json_file_name" KEYS) 115 | 116 | # Close the locals block 117 | echo "}" >> unifi_devices_map.tf 118 | } 119 | 120 | # Execute the main function 121 | main 122 | -------------------------------------------------------------------------------- /scripts/generate_unifi_dynamic_dns.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility script 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/dynamic_dns.json" 9 | readonly KEYS=( 10 | "_id" 11 | "host_name" 12 | "interface" 13 | "login" 14 | "server" 15 | "service" 16 | "site_id" 17 | "x_password" 18 | ) 19 | 20 | write_resource() { 21 | local -n args=$1 # Use a nameref to refer to the associative array 22 | 23 | { 24 | echo "resource \"unifi_dynamic_dns\" \"${args[sanitized_id]}\" {" 25 | 26 | c_echo "host_name" " host_name = \"%s\"" 27 | c_echo "service" " service = \"%s\"" 28 | c_echo "interface" " interface = \"%s\"" 29 | # On default site, causes infinite create/destroy loop 30 | # echo " site = local.unifi_site_Default.name" 31 | echo "" 32 | c_echo "server" " server = \"%s\"" 33 | c_echo "login" " login = \"%s\"" 34 | echo " password = var.unifi_dynamic_dns_${args[sanitized_name]}_password" 35 | echo "" 36 | echo "}" 37 | echo "" 38 | } >> unifi_dynamic_dns.tf 39 | } 40 | 41 | write_import() { 42 | local -n args=$1 # Use a nameref to refer to the associative array 43 | 44 | { 45 | echo "import {" 46 | echo " to = unifi_dynamic_dns.${args[sanitized_id]}" 47 | echo " id = \"${args[_id]}\"" 48 | echo "}" 49 | echo "" 50 | } >> unifi_dynamic_dns_import.tf 51 | } 52 | 53 | write_local() { 54 | local -n args=$1 # Use a nameref to refer to the associative array 55 | 56 | echo " unifi_dynamic_dns_${args[sanitized_name]} = unifi_dynamic_dns.${args[sanitized_id]}" >> unifi_dynamic_dns_map.tf 57 | } 58 | 59 | 60 | main() { 61 | # Load the mappings for retrieving names from IDs 62 | load_site_mappings 63 | 64 | # Clear existing files or create them if they don't exist 65 | > unifi_dynamic_dns.tf 66 | > unifi_dynamic_dns_import.tf 67 | > unifi_dynamic_dns_map.tf 68 | 69 | # Initialize unifi_dynamic_dns_map.tf with the header 70 | echo "locals {" > unifi_dynamic_dns_map.tf 71 | 72 | log_console_object_count "$json_file_name" 73 | 74 | # Process each line from read_json 75 | while IFS='◊' read -ra values; do 76 | 77 | # Create an associative array from the keys and values 78 | declare -A resource_args 79 | 80 | for index in "${!KEYS[@]}"; do 81 | resource_args["${KEYS[index]}"]="${values[index]}" 82 | done 83 | 84 | # Parse additional data 85 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 86 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[service]}_${resource_args[host_name]}")" 87 | 88 | log_debug " Writing object: type=dynamic_dns id=${resource_args[_id]} service=${resource_args[service]} server=${resource_args[server]} host_name=${resource_args[host_name]}" 89 | 90 | # Write the resource blocks 91 | write_resource resource_args 92 | 93 | # Write the import blocks 94 | write_import resource_args 95 | 96 | # Write the locals block 97 | write_local resource_args 98 | 99 | done < <(read_json "$json_file_name" KEYS) 100 | 101 | # Close the locals block 102 | echo "}" >> unifi_dynamic_dns_map.tf 103 | } 104 | 105 | # Execute the main function 106 | main 107 | -------------------------------------------------------------------------------- /scripts/generate_unifi_firewall_groups.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility script 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/firewall_groups.json" 9 | readonly KEYS=( 10 | "_id" 11 | "group_members" 12 | "group_type" 13 | "name" 14 | "site_id" 15 | ) 16 | 17 | write_resource() { 18 | local -n args=$1 # Use a nameref to refer to the associative array 19 | 20 | { 21 | echo "resource \"unifi_firewall_group\" \"${args[sanitized_id]}\" {" 22 | 23 | c_echo "name" " name = \"%s\"" 24 | echo " site = local.unifi_site_Default.name" 25 | c_echo "group_type" " type = \"%s\"" 26 | c_echo_firewall_group_members "${args[group_members]}" 27 | echo "}" 28 | echo "" 29 | } >> unifi_firewall_groups.tf 30 | } 31 | 32 | write_import() { 33 | local -n args=$1 # Use a nameref to refer to the associative array 34 | 35 | { 36 | echo "import {" 37 | echo " to = unifi_firewall_group.${args[sanitized_id]}" 38 | echo " id = \"${args[_id]}\"" 39 | echo "}" 40 | echo "" 41 | } >> unifi_firewall_groups_import.tf 42 | } 43 | 44 | write_local() { 45 | local -n args=$1 # Use a nameref to refer to the associative array 46 | 47 | echo " unifi_firewall_group_${args[sanitized_name]} = unifi_firewall_group.${args[sanitized_id]}" >> unifi_firewall_groups_map.tf 48 | } 49 | 50 | main() { 51 | # Clear existing files or create them if they don't exist 52 | > unifi_firewall_groups.tf 53 | > unifi_firewall_groups_import.tf 54 | > unifi_firewall_groups_map.tf 55 | 56 | # Initialize unifi_firewall_groups_map.tf with the header 57 | echo "locals {" > unifi_firewall_groups_map.tf 58 | 59 | log_console_object_count "$json_file_name" 60 | 61 | # Process each line from read_json 62 | while IFS='◊' read -ra values; do 63 | 64 | # Create an associative array from the keys and values 65 | declare -A resource_args 66 | 67 | for index in "${!KEYS[@]}"; do 68 | resource_args["${KEYS[index]}"]="${values[index]}" 69 | done 70 | 71 | # Parse additional data 72 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 73 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 74 | 75 | log_debug " Writing object: id=${resource_args[_id]} name=${resource_args[name]}" 76 | 77 | # Write the resource blocks 78 | write_resource resource_args 79 | 80 | # Write the import blocks 81 | write_import resource_args 82 | 83 | # Write the locals block 84 | write_local resource_args 85 | 86 | done < <(read_json "$json_file_name" KEYS) 87 | 88 | # Close the locals block 89 | echo "}" >> unifi_firewall_groups_map.tf 90 | } 91 | 92 | # Execute the main function 93 | main 94 | -------------------------------------------------------------------------------- /scripts/generate_unifi_firewall_rules.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility script 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/firewall_rules.json" 9 | readonly KEYS=( 10 | "_id" 11 | "action" 12 | "dst_address" 13 | "dst_address_ipv6" 14 | "dst_firewallgroup_ids" 15 | "dst_networkconf_id" 16 | "dst_networkconf_type" 17 | "dst_port" 18 | "enabled" 19 | "icmp_typename" 20 | "icmp_v6_typename" 21 | "ipsec" 22 | "logging" 23 | "name" 24 | "protocol" 25 | "protocol_v6" 26 | "protocol_match_excepted" 27 | "rule_index" 28 | "ruleset" 29 | "setting_preference" 30 | "site_id" 31 | "src_address" 32 | "src_address_ipv6" 33 | "src_firewallgroup_ids" 34 | "src_mac_address" 35 | "src_networkconf_id" 36 | "src_networkconf_type" 37 | "src_port" 38 | "state_established" 39 | "state_invalid" 40 | "state_new" 41 | "state_related" 42 | ) 43 | 44 | write_resource() { 45 | local -n args=$1 # Use a nameref to refer to the associative array 46 | 47 | { 48 | echo "resource \"unifi_firewall_rule\" \"${args[sanitized_id]}\" {" 49 | 50 | c_echo "name" " name = \"%s\"" 51 | echo " site = local.unifi_site_Default.name" 52 | c_echo "enabled" " enabled = %s" 53 | echo "" 54 | c_echo "action" " action = \"%s\"" 55 | c_echo "rule_index" " rule_index = %s" 56 | c_echo "ruleset" " ruleset = \"%s\"" 57 | echo "" 58 | c_echo "dst_address" " dst_address = \"%s\"" 59 | c_echo "dst_address_ipv6" " dst_address_ipv6 = \"%s\"" 60 | c_echo_firewall_groups "${args[dst_firewallgroup_ids]}" "dst" 61 | c_echo "dst_network_resource" " dst_network_id = %s" 62 | c_echo "dst_networkconf_type" " dst_network_type = \"%s\"" 63 | c_echo "dst_port" " dst_port = \"%s\"" 64 | c_echo "icmp_typename" " icmp_typename = \"%s\"" 65 | c_echo "icmp_v6_typename" " icmp_v6_typename = \"%s\"" 66 | c_echo "ipsec" " ip_sec = \"%s\"" 67 | c_echo "logging" " logging = %s" 68 | c_echo "protocol" " protocol = \"%s\"" 69 | c_echo "protocol_v6" " protocol_v6 = \"%s\"" 70 | c_echo "src_address" " src_address = \"%s\"" 71 | c_echo "src_address_ipv6" " src_address_ipv6 = \"%s\"" 72 | c_echo_firewall_groups "${args[src_firewallgroup_ids]}" "src" 73 | c_echo_firewall_rule_src_mac_address "${args[src_mac_address]}" 74 | c_echo "src_network_resource" " src_network_id = %s" 75 | c_echo "src_networkconf_type" " src_network_type = \"%s\"" 76 | c_echo "src_port" " src_port = \"%s\"" 77 | c_echo "state_established" " state_established = %s" 78 | c_echo "state_invalid" " state_invalid = %s" 79 | c_echo "state_new" " state_new = %s" 80 | c_echo "state_related" " state_related = %s" 81 | echo "}" 82 | echo "" 83 | } >> unifi_firewall_rules.tf 84 | } 85 | 86 | write_import() { 87 | local -n args=$1 # Use a nameref to refer to the associative array 88 | 89 | { 90 | echo "import {" 91 | echo " to = unifi_firewall_rule.${args[sanitized_id]}" 92 | echo " id = \"${args[_id]}\"" 93 | echo "}" 94 | echo "" 95 | } >> unifi_firewall_rules_import.tf 96 | } 97 | 98 | write_local() { 99 | local -n args=$1 # Use a nameref to refer to the associative array 100 | 101 | echo " unifi_firewall_rule_${args[sanitized_name]} = unifi_firewall_rule.${args[sanitized_id]}" >> unifi_firewall_rules_map.tf 102 | } 103 | 104 | main() { 105 | # Load the mappings 106 | load_device_mappings 107 | load_firewall_group_mappings 108 | load_network_mappings 109 | load_user_mappings 110 | 111 | # Clear existing files or create them if they don't exist 112 | > unifi_firewall_rules.tf 113 | > unifi_firewall_rules_import.tf 114 | > unifi_firewall_rules_map.tf 115 | 116 | # Initialize unifi_firewall_rules_map.tf with the header 117 | echo "locals {" > unifi_firewall_rules_map.tf 118 | 119 | log_console_object_count "$json_file_name" 120 | 121 | # Process each line from read_json 122 | while IFS='◊' read -ra values; do 123 | 124 | # Create an associative array from the keys and values 125 | declare -A resource_args 126 | 127 | for index in "${!KEYS[@]}"; do 128 | resource_args["${KEYS[index]}"]="${values[index]}" 129 | done 130 | 131 | # Parse additional data 132 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 133 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 134 | if [ -n "${resource_args[dst_networkconf_id]}" ]; then 135 | resource_args[dst_network_resource]="local.${network_id_to_name[${resource_args[dst_networkconf_id]}]}.id" 136 | else 137 | resource_args[dst_network_resource]="" 138 | fi 139 | 140 | if [ -n "${resource_args[src_networkconf_id]}" ]; then 141 | resource_args[src_network_resource]="local.${network_id_to_name[${resource_args[src_networkconf_id]}]}.id" 142 | else 143 | resource_args[src_network_resource]="" 144 | fi 145 | 146 | log_debug " Writing object: id=${resource_args[_id]} name=${resource_args[name]}" 147 | 148 | # Write the resource blocks 149 | write_resource resource_args 150 | 151 | # Write the import blocks 152 | write_import resource_args 153 | 154 | # Write the locals block 155 | write_local resource_args 156 | 157 | done < <(read_json "$json_file_name" KEYS) 158 | 159 | # Close the locals block 160 | echo "}" >> unifi_firewall_rules_map.tf 161 | } 162 | 163 | # Execute the main function 164 | main 165 | -------------------------------------------------------------------------------- /scripts/generate_unifi_networks.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/networks.json" 9 | readonly KEYS=( 10 | "_id" 11 | "attr_hidden_id" 12 | "attr_no_delete" 13 | "auto_scale_enabled" 14 | "dhcp_relay_enabled" 15 | "dhcpd_boot_enabled" 16 | "dhcpd_boot_filename" 17 | "dhcpd_boot_server" 18 | "dhcpd_dns_1" 19 | "dhcpd_dns_2" 20 | "dhcpd_dns_3" 21 | "dhcpd_dns_4" 22 | "dhcpd_dns_enabled" 23 | "dhcpd_enabled" 24 | "dhcpd_gateway" 25 | "dhcpd_gateway_enabled" 26 | "dhcpd_ip_1" 27 | "dhcpd_ip_2" 28 | "dhcpd_ip_3" 29 | "dhcpd_leasetime" 30 | "dhcpd_mac_1" 31 | "dhcpd_mac_2" 32 | "dhcpd_mac_3" 33 | "dhcpd_ntp_1" 34 | "dhcpd_ntp_2" 35 | "dhcpd_ntp_enabled" 36 | "dhcpd_start" 37 | "dhcpd_stop" 38 | "dhcpd_tftp_server" 39 | "dhcpd_time_offset_enabled" 40 | "dhcpd_unifi_controller" 41 | "dhcpd_wins_1" 42 | "dhcpd_wins_2" 43 | "dhcpd_wins_enabled" 44 | "dhcpd_wpad_url" 45 | "dhcpdv6_allow_slaac" 46 | "dhcpdv6_dns_1" 47 | "dhcpdv6_dns_2" 48 | "dhcpdv6_dns_3" 49 | "dhcpdv6_dns_4" 50 | "dhcpdv6_dns_auto" 51 | "dhcpdv6_enabled" 52 | "dhcpdv6_leasetime" 53 | "dhcpdv6_start" 54 | "dhcpdv6_stop" 55 | "dhcpguard_enabled" 56 | "domain_name" 57 | "dpi_enabled" 58 | "dpigroup_id" 59 | "enabled" 60 | "exposed_to_site_vpn" 61 | "gateway_type" 62 | "igmp_fastleave" 63 | "igmp_proxy_downstream" 64 | "igmp_querier" 65 | "igmp_snooping" 66 | "igmp_supression" 67 | "internet_access_enabled" 68 | "ip_subnet" 69 | "ipsec_dynamic_routing" 70 | "ipsec_pfs" 71 | "ipv6_client_address_assignme" 72 | "ipv6_interface_type" 73 | "ipv6_pd_auto_prefixid_enable" 74 | "ipv6_pd_interface" 75 | "ipv6_pd_prefixid" 76 | "ipv6_pd_start" 77 | "ipv6_pd_stop" 78 | "ipv6_ra_enabled" 79 | "ipv6_ra_preferred_lifetime" 80 | "ipv6_ra_priority" 81 | "ipv6_ra_valid_lifetime" 82 | "ipv6_setting_preference" 83 | "ipv6_subnet" 84 | "is_nat" 85 | "l2tp_allow_weak_ciphers" 86 | "lte_lan_enabled" 87 | "mac_override" 88 | "mac_override_enabled" 89 | "mdns_enabled" 90 | "name" 91 | "nat_outbound_ip_addresses" 92 | "networkgroup" 93 | "pptpc_require_mppe" 94 | "purpose" 95 | "radiusprofile_id" 96 | "remote_site_id" 97 | "report_wan_event" 98 | "require_mschapv2" 99 | "setting_preference" 100 | "site_id" 101 | "upnp_lan_enabled" 102 | "usergroup_id" 103 | "vlan" 104 | "vlan_enabled" 105 | "vpn_client_default_route" 106 | "vpn_client_pull_dns" 107 | "wan_dhcpv6_pd_size" 108 | "wan_dns1" 109 | "wan_dns2" 110 | "wan_dns3" 111 | "wan_dns4" 112 | "wan_egress_qos" 113 | "wan_gateway" 114 | "wan_gateway_v6" 115 | "wan_ip" 116 | "wan_ipv6" 117 | "wan_netmask" 118 | "wan_networkgroup" 119 | "wan_prefixlen" 120 | "wan_provider_capabilities" 121 | "wan_smartq_enabled" 122 | "wan_type" 123 | "wan_type_v6" 124 | "wan_username" 125 | "wan_vlan_enabled" 126 | "x_wan_password" 127 | ) 128 | 129 | write_resource() { 130 | local -n args=$1 131 | 132 | { 133 | echo "resource \"unifi_network\" \"${args[sanitized_id]}\" {" 134 | c_echo "name" " name = \"%s\"" 135 | c_echo "site_resource_name" " site = local.%s.name" 136 | c_echo "purpose" " purpose = \"%s\"" 137 | c_echo "networkgroup" " network_group = \"%s\"" 138 | echo "" 139 | c_echo "ip_subnet" " subnet = \"%s\"" 140 | c_echo "ipv6_subnet" " ipv6_static_subnet = \"%s\"" 141 | c_echo "vlan" " vlan_id = %s" 142 | echo "" 143 | c_echo_dns "dhcpd_dns_1" "dhcpd_dns_2" "dhcpd_dns_3" "dhcpd_dns_4" "dhcp_dns" 144 | c_echo "dhcpd_enabled" " dhcp_enabled = %s" 145 | c_echo "dhcpd_leasetime" " dhcp_lease = %s" 146 | c_echo "dhcp_relay_enabled" " dhcp_relay_enabled = %s" 147 | c_echo "dhcpd_start" " dhcp_start = \"%s\"" 148 | c_echo "dhcpd_stop" " dhcp_stop = \"%s\"" 149 | c_echo_dns "dhcpdv6_dns_1" "dhcpdv6_dns_2" "dhcpdv6_dns_3" "dhcpdv6_dns_4" "dhcp_v6_dns" 150 | c_echo "dhcpdv6_dns_auto" " dhcp_v6_dns_auto = %s" 151 | c_echo "dhcpdv6_enabled" " dhcp_v6_enabled = %s" 152 | c_echo "dhcpdv6_start" " dhcp_v6_start = \"%s\"" 153 | c_echo "dhcpdv6_stop" " dhcp_v6_stop = \"%s\"" 154 | c_echo "dhcpd_boot_enabled" " dhcpd_boot_enabled = %s" 155 | c_echo "dhcpd_boot_filename" " dhcpd_boot_filename = \"%s\"" 156 | c_echo "dhcpd_boot_server" " dhcpd_boot_server = \"%s\"" 157 | c_echo "domain_name" " domain_name = \"%s\"" 158 | c_echo "igmp_snooping" " igmp_snooping = %s" 159 | c_echo "internet_access_enabled" " internet_access_enabled = %s" 160 | c_echo "ipv6_interface_type" " ipv6_interface_type = \"%s\"" 161 | c_echo "ipv6_pd_interface" " ipv6_pd_interface = \"%s\"" 162 | c_echo "ipv6_pd_prefixid" " ipv6_pd_prefixid = \"%s\"" 163 | c_echo "ipv6_pd_start" " ipv6_pd_start = \"%s\"" 164 | c_echo "ipv6_pd_stop" " ipv6_pd_stop = \"%s\"" 165 | c_echo "ipv6_ra_enabled" " ipv6_ra_enable = %s" 166 | c_echo "ipv6_ra_preferred_lifetime" " ipv6_ra_preferred_lifetime = %s" 167 | c_echo "ipv6_ra_priority" " ipv6_ra_priority = \"%s\"" 168 | c_echo "ipv6_ra_valid_lifetime" " ipv6_ra_valid_lifetime = %s" 169 | c_echo "mdns_enabled" " multicast_dns = %s" 170 | c_echo "wan_dhcpv6_pd_size" " wan_dhcp_v6_pd_size = %s" 171 | c_echo_dns "wan_dns1" "wan_dns2" "wan_dns3" "wan_dns4" "wan_dns" 172 | c_echo "wan_egress_qos" " wan_egress_qos = %s" 173 | c_echo "wan_gateway" " wan_gateway = \"%s\"" 174 | c_echo "wan_gateway_v6" " wan_gateway_v6 = \"%s\"" 175 | c_echo "wan_ip" " wan_ip = \"%s\"" 176 | c_echo "wan_ipv6" " wan_ipv6 = \"%s\"" 177 | c_echo "wan_netmask" " wan_netmask = \"%s\"" 178 | c_echo "wan_networkgroup" " wan_networkgroup = \"%s\"" 179 | c_echo "wan_prefixlen" " wan_prefixlen = %s" 180 | c_echo "wan_type" " wan_type = \"%s\"" 181 | c_echo "wan_type_v6" " wan_type_v6 = \"%s\"" 182 | c_echo "wan_username" " wan_username = \"%s\"" 183 | c_echo "x_wan_password" " x_wan_password = var.unifi_network_${args[sanitized_name]}_x_wan_password" 184 | echo "" 185 | echo " lifecycle {" 186 | echo " prevent_destroy = true" 187 | echo " }" 188 | echo "}" 189 | echo "" 190 | } >> unifi_networks.tf 191 | } 192 | 193 | write_import() { 194 | local -n args=$1 195 | 196 | { 197 | echo "import {" 198 | echo " to = unifi_network.${args[sanitized_id]}" 199 | echo " id = \"${args[_id]}\"" 200 | echo "}" 201 | echo "" 202 | } >> unifi_networks_import.tf 203 | } 204 | 205 | write_local() { 206 | local -n args=$1 207 | 208 | echo " unifi_network_${args[sanitized_name]} = unifi_network.${args[sanitized_id]}" >> unifi_networks_map.tf 209 | } 210 | 211 | main() { 212 | # Load the site mappings 213 | load_site_mappings 214 | 215 | # Clear existing files or create them if they don't exist 216 | > unifi_networks.tf 217 | > unifi_networks_import.tf 218 | > unifi_networks_map.tf 219 | 220 | echo "locals {" > unifi_networks_map.tf 221 | 222 | log_console_object_count "$json_file_name" 223 | 224 | # Process each line from read_json 225 | while IFS='◊' read -ra values; do 226 | 227 | # Create an associative array from the keys and values 228 | declare -A resource_args 229 | 230 | for index in "${!KEYS[@]}"; do 231 | resource_args["${KEYS[index]}"]="${values[index]}" 232 | done 233 | 234 | # Parse additional data 235 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 236 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 237 | resource_args[site_resource_name]="${site_id_to_name[${resource_args[site_id]}]}" 238 | 239 | log_debug " Writing object: id=${resource_args[_id]} name=${resource_args[name]}" 240 | 241 | # Write the resource blocks 242 | write_resource resource_args 243 | 244 | # Write the import blocks 245 | write_import resource_args 246 | 247 | # Write the locals block 248 | write_local resource_args 249 | 250 | done < <(read_json "$json_file_name" KEYS) 251 | 252 | # Close the locals block 253 | echo "}" >> unifi_networks_map.tf 254 | } 255 | 256 | # Execute the main function 257 | main 258 | -------------------------------------------------------------------------------- /scripts/generate_unifi_port_forward.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/port_forward.json" 9 | readonly KEYS=( 10 | "_id" 11 | "dst_port" 12 | "enabled" 13 | "fwd" 14 | "fwd_port" 15 | "log" 16 | "name" 17 | "pfwd_interface" 18 | "proto" 19 | "site_id" 20 | "src" 21 | ) 22 | 23 | readonly USER_KEYS=( 24 | "_id" 25 | "blocked" 26 | "dev_id_override" 27 | "fingerprint_override" 28 | "fixed_ip" 29 | "hostname" 30 | "local_dns_record" 31 | "local_dns_record_enabled" 32 | "mac" 33 | "name" 34 | "network_id" 35 | "note" 36 | "noted" 37 | "use_fixedip" 38 | ) 39 | 40 | write_resource() { 41 | local -n args=$1 42 | 43 | { 44 | echo "resource \"unifi_port_forward\" \"${args[sanitized_id]}\" {" 45 | c_echo "name" " name = \"%s\"" 46 | echo " site = local.${args[site_resource_name]}.name" 47 | echo "" 48 | c_echo "pfwd_interface" " port_forward_interface = \"%s\"" 49 | c_echo "proto" " protocol = \"%s\"" 50 | echo "" 51 | c_echo "src" " src_ip = \"%s\"" 52 | c_echo "dst_port" " dst_port = \"%s\"" 53 | if [ -n "${args[user_resource_name]}" ]; then 54 | echo " fwd_ip = local.${args[user_resource_name]}.fixed_ip" 55 | else 56 | c_echo "fwd" " fwd_ip = \"%s\"" 57 | fi 58 | c_echo "fwd_port" " fwd_port = \"%s\"" 59 | echo "" 60 | c_echo "log" " log = %s" 61 | echo "" 62 | echo " # Deprecated: To disable, remove the resource block" 63 | c_echo "enabled" " # enabled = %s" 64 | echo "}" 65 | echo "" 66 | } >> unifi_port_forward.tf 67 | } 68 | 69 | write_import() { 70 | local -n args=$1 71 | 72 | { 73 | echo "import {" 74 | echo " to = unifi_port_forward.${args[sanitized_id]}" 75 | echo " id = \"${args[_id]}\"" 76 | echo "}" 77 | echo "" 78 | } >> unifi_port_forward_import.tf 79 | } 80 | 81 | write_local() { 82 | local -n args=$1 83 | 84 | echo " unifi_port_forward_${args[sanitized_name]} = unifi_port_forward.${args[sanitized_id]}" >> unifi_port_forward_map.tf 85 | } 86 | 87 | main() { 88 | # Load the mappings for retrieving names from IDs 89 | load_site_mappings 90 | load_user_mappings 91 | 92 | # Clear existing files or create them if they don't exist 93 | > unifi_port_forward.tf 94 | > unifi_port_forward_import.tf 95 | > unifi_port_forward_map.tf 96 | 97 | # Write the header for the locals block 98 | echo "locals {" > unifi_port_forward_map.tf 99 | 100 | log_console_object_count "$json_file_name" 101 | 102 | # Build an associative array of IPs and MAC addresses from users 103 | declare -A ip_mac_array 104 | while IFS='◊' read -ra line_data; do 105 | declare -A user_args 106 | 107 | for index in "${!USER_KEYS[@]}"; do 108 | user_args["${USER_KEYS[index]}"]="${line_data[index]}" 109 | done 110 | 111 | # If the use_fixedip flag is set to true, then add the IP and MAC to the array 112 | if [ "${user_args[use_fixedip]}" = "true" ]; then 113 | ip_mac_array["${user_args[fixed_ip]}"]="${user_args[mac]}" 114 | fi 115 | done < <(read_json "json/users.json" USER_KEYS) 116 | 117 | # Process each line from read_json 118 | while IFS='◊' read -ra line_data; do 119 | declare -A resource_args 120 | 121 | for index in "${!KEYS[@]}"; do 122 | resource_args["${KEYS[index]}"]="${line_data[index]}" 123 | done 124 | 125 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 126 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 127 | resource_args[site_resource_name]="${site_id_to_name[${resource_args[site_id]}]}" 128 | if [[ -n ${ip_mac_array[${resource_args[fwd]}]} ]]; then 129 | resource_args[sanitized_fwd_mac]="$(sanitize_for_terraform "${ip_mac_array[${resource_args[fwd]}]}")" 130 | resource_args[user_resource_name]="${user_id_to_name[${resource_args[sanitized_fwd_mac]}]}" 131 | fi 132 | log_debug " Writing object: id=${resource_args[_id]} name=${resource_args[name]}" 133 | 134 | write_resource resource_args 135 | write_import resource_args 136 | write_local resource_args 137 | 138 | done < <(read_json "$json_file_name" KEYS) 139 | 140 | # Close the locals block 141 | echo "}" >> unifi_port_forward_map.tf 142 | } 143 | 144 | # Execute the main function 145 | main 146 | -------------------------------------------------------------------------------- /scripts/generate_unifi_port_profiles.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/port_profiles.json" 9 | readonly KEYS=( 10 | "_id" 11 | "autoneg" 12 | "dot1x_ctrl" 13 | "dot1x_idle_timeout" 14 | "egress_rate_limit_kbps" 15 | "egress_rate_limit_kbps_enabled" 16 | "excluded_networkconf_ids" 17 | "forward" 18 | "full_duplex" 19 | "isolation" 20 | "lldpmed_enabled" 21 | "lldpmed_notify_enabled" 22 | "name" 23 | "native_networkconf_id" 24 | "op_mode" 25 | "poe_mode" 26 | "port_keepalive_enabled" 27 | "port_security_enabled" 28 | "port_security_mac_address" 29 | "setting_preference" 30 | "site_id" 31 | "speed" 32 | "stormctrl_bcast_enabled" 33 | "stormctrl_bcast_level" 34 | "stormctrl_bcast_rate" 35 | "stormctrl_mcast_enabled" 36 | "stormctrl_mcast_level" 37 | "stormctrl_mcast_rate" 38 | "stormctrl_ucast_enabled" 39 | "stormctrl_ucast_level" 40 | "stormctrl_ucast_rate" 41 | "stp_port_mode" 42 | "tagged_vlan_mgmt" 43 | "voice_networkconf_id" 44 | ) 45 | 46 | write_resource() { 47 | local -n args=$1 48 | 49 | { 50 | echo "resource \"unifi_port_profile\" \"${args[sanitized_id]}\" {" 51 | c_echo "name" " name = \"%s\"" 52 | echo " site = local.${args[site_resource_name]}.name" 53 | c_echo "native_networkconf_id" " native_networkconf_id = local.${args[network_resource_name]}.id" 54 | echo "" 55 | c_echo "autoneg" " autoneg = %s" 56 | c_echo "dot1x_ctrl" " dot1x_ctrl = \"%s\"" 57 | c_echo "dot1x_idle_timeout" " dot1x_idle_timeout = %s" 58 | c_echo "egress_rate_limit_kbps" " egress_rate_limit_kbps = %s" 59 | c_echo "egress_rate_limit_kbps_enabled" " egress_rate_limit_kbps_enabled = %s" 60 | c_echo "forward" " forward = \"%s\"" 61 | c_echo "full_duplex" " full_duplex = %s" 62 | c_echo "isolation" " isolation = %s" 63 | c_echo "lldpmed_enabled" " lldpmed_enabled = %s" 64 | c_echo "lldpmed_notify_enabled" " lldpmed_notify_enabled = %s" 65 | c_echo "op_mode" " op_mode = \"%s\"" 66 | c_echo "poe_mode" " poe_mode = \"%s\"" 67 | c_echo "port_security_enabled" " port_security_enabled = %s" 68 | c_echo_port_security_mac_address "${args[port_security_mac_address]}" 69 | c_echo "priority_queue1_level" " priority_queue1_level = %s" 70 | c_echo "priority_queue2_level" " priority_queue2_level = %s" 71 | c_echo "priority_queue3_level" " priority_queue3_level = %s" 72 | c_echo "priority_queue4_level" " priority_queue4_level = %s" 73 | c_echo "speed" " speed = %s" 74 | c_echo "stormctrl_bcast_enabled" " stormctrl_bcast_enabled = %s" 75 | c_echo "stormctrl_bcast_level" " stormctrl_bcast_level = %s" 76 | c_echo "stormctrl_bcast_rate" " stormctrl_bcast_rate = %s" 77 | c_echo "stormctrl_mcast_enabled" " stormctrl_mcast_enabled = %s" 78 | c_echo "stormctrl_mcast_level" " stormctrl_mcast_level = %s" 79 | c_echo "stormctrl_mcast_rate" " stormctrl_mcast_rate = %s" 80 | c_echo "stormctrl_type" " stormctrl_type = \"%s\"" 81 | c_echo "stormctrl_ucast_enabled" " stormctrl_ucast_enabled = %s" 82 | c_echo "stormctrl_ucast_level" " stormctrl_ucast_level = %s" 83 | c_echo "stormctrl_ucast_rate" " stormctrl_ucast_rate = %s" 84 | c_echo "stp_port_mode" " stp_port_mode = %s" 85 | # This appears to be deprecated, in favor of excluded_networkconf_ids 86 | # c_echo "tagged_networkconf_ids" " tagged_networkconf_ids = %s" 87 | c_echo "voice_networkconf_id" " voice_networkconf_id = \"%s\"" 88 | echo "}" 89 | echo "" 90 | } >> unifi_port_profiles.tf 91 | } 92 | 93 | write_import() { 94 | local -n args=$1 95 | 96 | { 97 | echo "import {" 98 | echo " to = unifi_port_profile.${args[sanitized_id]}" 99 | echo " id = \"${args[_id]}\"" 100 | echo "}" 101 | echo "" 102 | } >> unifi_port_profiles_import.tf 103 | } 104 | 105 | write_local() { 106 | local -n args=$1 107 | 108 | echo " unifi_port_profile_${args[sanitized_name]} = unifi_port_profile.${args[sanitized_id]}" >> unifi_port_profiles_map.tf 109 | } 110 | 111 | main() { 112 | # Load the mappings for retrieving names from IDs 113 | load_device_mappings 114 | load_network_mappings 115 | load_site_mappings 116 | load_user_mappings 117 | 118 | # Clear existing files or create them if they don't exist 119 | > unifi_port_profiles.tf 120 | > unifi_port_profiles_import.tf 121 | > unifi_port_profiles_map.tf 122 | 123 | # Write the header for the locals block 124 | echo "locals {" > unifi_port_profiles_map.tf 125 | 126 | log_console_object_count "$json_file_name" 127 | 128 | # Process each line from read_json 129 | while IFS='◊' read -ra line_data; do 130 | declare -A resource_args 131 | 132 | for index in "${!KEYS[@]}"; do 133 | resource_args["${KEYS[index]}"]="${line_data[index]}" 134 | done 135 | 136 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 137 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 138 | resource_args[site_resource_name]="${site_id_to_name[${resource_args[site_id]}]}" 139 | resource_args[network_resource_name]="${network_id_to_name[${resource_args[native_networkconf_id]}]}" 140 | 141 | log_debug " Writing object: id=${resource_args[_id]} name=${resource_args[name]}" 142 | 143 | write_resource resource_args 144 | write_import resource_args 145 | write_local resource_args 146 | 147 | done < <(read_json "$json_file_name" KEYS) 148 | 149 | # Close the locals block 150 | echo "}" >> unifi_port_profiles_map.tf 151 | } 152 | 153 | # Execute the main function 154 | main 155 | -------------------------------------------------------------------------------- /scripts/generate_unifi_radius_profiles.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/radius_profiles.json" 9 | readonly KEYS=( 10 | "_id" 11 | "attr_hidden_id" 12 | "auth_servers" 13 | "interim_update_interval" 14 | "name" 15 | "site_id" 16 | "use_usg_auth_server" 17 | "vlan_enabled" 18 | "vlan_wlan_mode" 19 | ) 20 | 21 | write_data() { 22 | local -n args=$1 23 | 24 | { 25 | echo "data \"unifi_radius_profile\" \"${args[sanitized_id]}\" {" 26 | c_echo "name" " name = \"%s\"" 27 | echo "}" 28 | echo "" 29 | } >> unifi_radius_profiles.tf 30 | } 31 | 32 | write_resource() { 33 | local -n args=$1 34 | 35 | { 36 | echo "resource \"unifi_radius_profile\" \"${args[sanitized_id]}\" {" 37 | c_echo "name" " name = \"%s\"" 38 | echo " site = local.${args[site_resource_name]}.name" 39 | echo "" 40 | c_echo "use_usg_auth_server" " use_usg_auth_server = %s" 41 | c_echo "vlan_enabled" " vlan_enabled = %s" 42 | c_echo "vlan_wlan_mode" " vlan_wlan_mode = \"%s\"" 43 | c_echo "interim_update_interval" " interim_update_interval = %s" 44 | c_echo_auth_servers "${args[auth_servers]}" "${args[sanitized_name]}" 45 | echo "}" 46 | echo "" 47 | } >> unifi_radius_profiles.tf 48 | } 49 | 50 | write_import() { 51 | local -n args=$1 52 | 53 | { 54 | echo "import {" 55 | echo " to = unifi_radius_profile.${args[sanitized_id]}" 56 | echo " id = \"${args[_id]}\"" 57 | echo "}" 58 | echo "" 59 | } >> unifi_radius_profiles_import.tf 60 | } 61 | 62 | write_local() { 63 | local -n args=$1 64 | 65 | local prefix="" 66 | if [ "${args[attr_hidden_id]}" = "Default" ]; then 67 | prefix="data." 68 | fi 69 | 70 | echo " unifi_radius_profile_${args[sanitized_name]} = ${prefix}unifi_radius_profile.${args[sanitized_id]}" >> unifi_radius_profiles_map.tf 71 | } 72 | 73 | main() { 74 | load_site_mappings 75 | > unifi_radius_profiles.tf 76 | > unifi_radius_profiles_import.tf 77 | echo "locals {" > unifi_radius_profiles_map.tf 78 | 79 | log_console_object_count "$json_file_name" 80 | 81 | while IFS='◊' read -ra line_data; do 82 | declare -A resource_args 83 | 84 | for index in "${!KEYS[@]}"; do 85 | resource_args["${KEYS[index]}"]="${line_data[index]}" 86 | done 87 | 88 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 89 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 90 | resource_args[site_resource_name]="${site_id_to_name[${resource_args[site_id]}]}" 91 | 92 | log_debug " Writing object: id=${resource_args[_id]} name=${resource_args[name]}" 93 | 94 | if [ "${resource_args[attr_hidden_id]}" = "Default" ]; then 95 | write_data resource_args 96 | else 97 | write_resource resource_args 98 | write_import resource_args 99 | fi 100 | write_local resource_args 101 | 102 | done < <(read_json "$json_file_name" KEYS) 103 | 104 | echo "}" >> unifi_radius_profiles_map.tf 105 | } 106 | 107 | # Execute the main function 108 | main 109 | -------------------------------------------------------------------------------- /scripts/generate_unifi_settings.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ./scripts/generate_unifi_settings_mgmt.sh 3 | ./scripts/generate_unifi_settings_radius.sh 4 | ./scripts/generate_unifi_settings_usg.sh 5 | -------------------------------------------------------------------------------- /scripts/generate_unifi_settings_mgmt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/settings.json" 9 | readonly KEYS=( 10 | "_id" 11 | "advanced_feature_enabled" 12 | "auto_upgrade" 13 | "auto_upgrade_hour" 14 | "debug_tools_enabled" 15 | "direct_connect_enabled" 16 | "key" 17 | "site_id" 18 | "unifi_idp_enabled" 19 | "wifiman_enabled" 20 | "x_api_token" 21 | "x_mgmt_key" 22 | "x_ssh_auth_password_enabled" 23 | "x_ssh_bind_wildcard" 24 | "x_ssh_enabled" 25 | "x_ssh_keys" 26 | ) 27 | 28 | write_resource() { 29 | local -n args=$1 30 | 31 | { 32 | echo "resource \"unifi_setting_mgmt\" \"${args[sanitized_id]}\" {" 33 | echo " site = local.${site_id_to_name[${args[site_id]}]}.name" 34 | c_echo "auto_upgrade" " auto_upgrade = %s" 35 | c_echo "x_ssh_enabled" " ssh_enabled = %s" 36 | c_echo_ssh_keys "${args[x_ssh_keys]}" 37 | echo "}" 38 | echo "" 39 | } >> unifi_settings_mgmt.tf 40 | } 41 | 42 | write_import() { 43 | local -n args=$1 44 | 45 | { 46 | echo "import {" 47 | echo " to = unifi_setting_mgmt.${args[sanitized_id]}" 48 | echo " id = \"${args[_id]}\"" 49 | echo "}" 50 | echo "" 51 | } >> unifi_settings_mgmt_import.tf 52 | } 53 | 54 | main() { 55 | load_site_mappings 56 | 57 | > unifi_settings_mgmt.tf 58 | > unifi_settings_mgmt_import.tf 59 | 60 | # Process each line from read_json 61 | while IFS='◊' read -ra line_data; do 62 | declare -A resource_args 63 | 64 | for index in "${!KEYS[@]}"; do 65 | resource_args["${KEYS[index]}"]="${line_data[index]}" 66 | done 67 | 68 | # Only process entries where key is 'mgmt' 69 | if [ "${resource_args[key]}" = "mgmt" ]; then 70 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 71 | 72 | log_console "Processing settings_mgmt: 1 object..." 73 | log_debug " Writing object: type=settings_mgmt id=${resource_args[_id]}" 74 | 75 | write_resource resource_args 76 | write_import resource_args 77 | fi 78 | done < <(read_json "$json_file_name" KEYS) 79 | 80 | } 81 | 82 | # Execute the main function 83 | main 84 | -------------------------------------------------------------------------------- /scripts/generate_unifi_settings_radius.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/settings.json" 9 | readonly KEYS=( 10 | "_id" 11 | "accounting_enabled" 12 | "acct_port" 13 | "auth_port" 14 | "ca_certificate" 15 | "configure_whole_network" 16 | "dh_key" 17 | "enabled" 18 | "interim_update_interval" 19 | "key" 20 | "server_certificate" 21 | "server_certificate_key" 22 | "site_id" 23 | "tunneled_reply" 24 | "x_secret" 25 | ) 26 | 27 | write_resource() { 28 | local -n args=$1 29 | 30 | { 31 | echo "resource \"unifi_setting_radius\" \"${args[sanitized_id]}\" {" 32 | echo " site = local.${site_id_to_name[${args[site_id]}]}.name" 33 | c_echo "enabled" " enabled = %s" 34 | echo "" 35 | c_echo "accounting_enabled" " accounting_enabled = %s" 36 | c_echo "acct_port" " accounting_port = %s" 37 | c_echo "auth_port" " auth_port = %s" 38 | c_echo "interim_update_interval" " interim_update_interval = %s" 39 | echo " secret = var.unifi_setting_radius_${args[sanitized_id]}_secret" 40 | c_echo "tunneled_reply" " tunneled_reply = %s" 41 | echo "}" 42 | echo "" 43 | } >> unifi_settings_radius.tf 44 | } 45 | 46 | write_import() { 47 | local -n args=$1 48 | 49 | { 50 | echo "import {" 51 | echo " to = unifi_setting_radius.${args[sanitized_id]}" 52 | echo " id = \"${args[_id]}\"" 53 | echo "}" 54 | echo "" 55 | } >> unifi_settings_radius_import.tf 56 | } 57 | 58 | main() { 59 | load_site_mappings 60 | 61 | > unifi_settings_radius.tf 62 | > unifi_settings_radius_import.tf 63 | 64 | # Process each line from read_json 65 | while IFS='◊' read -ra line_data; do 66 | declare -A resource_args 67 | 68 | for index in "${!KEYS[@]}"; do 69 | resource_args["${KEYS[index]}"]="${line_data[index]}" 70 | done 71 | 72 | # Only process entries where key is 'radius' 73 | if [ "${resource_args[key]}" = "radius" ]; then 74 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 75 | 76 | log_console "Processing settings_radius: 1 object..." 77 | log_debug " Writing object: type=settings_radius id=${resource_args[_id]}" 78 | 79 | write_resource resource_args 80 | write_import resource_args 81 | fi 82 | done < <(read_json "$json_file_name" KEYS) 83 | 84 | } 85 | 86 | # Execute the main function 87 | main 88 | -------------------------------------------------------------------------------- /scripts/generate_unifi_settings_usg.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/settings.json" 9 | readonly KEYS=( 10 | "_id" 11 | "arp_cache_base_reachable" 12 | "arp_cache_timeout" 13 | "broadcast_ping" 14 | "dhcp_relay_server_1" 15 | "dhcp_relay_server_2" 16 | "dhcp_relay_server_3" 17 | "dhcp_relay_server_4" 18 | "dhcp_relay_server_5" 19 | "firewall_guest_default_log" 20 | "firewall_lan_default_log" 21 | "firewall_wan_default_log" 22 | "ftp_module" 23 | "geo_ip_filtering_block" 24 | "geo_ip_filtering_countries" 25 | "geo_ip_filtering_enabled" 26 | "geo_ip_filtering_traffic_direction" 27 | "gre_module" 28 | "h323_module" 29 | "icmp_timeout" 30 | "key" 31 | "mss_clamp" 32 | "offload_accounting" 33 | "offload_l2_blocking" 34 | "offload_sch" 35 | "other_timeout" 36 | "pptp_module" 37 | "receive_redirects" 38 | "send_redirects" 39 | "sip_module" 40 | "site_id" 41 | "syn_cookies" 42 | "tcp_close_timeout" 43 | "tcp_close_wait_timeout" 44 | "tcp_established_timeout" 45 | "tcp_fin_wait_timeout" 46 | "tcp_last_ack_timeout" 47 | "tcp_syn_recv_timeout" 48 | "tcp_syn_sent_timeout" 49 | "tcp_time_wait_timeout" 50 | "tftp_module" 51 | "timeout_setting_preference" 52 | "udp_other_timeout" 53 | "udp_stream_timeout" 54 | "upnp_enabled" 55 | "upnp_nat_pmp_enabled" 56 | "upnp_secure_mode" 57 | "upnp_wan_interface" 58 | ) 59 | 60 | write_resource() { 61 | local -n args=$1 62 | 63 | { 64 | echo "resource \"unifi_setting_usg\" \"${args[sanitized_id]}\" {" 65 | echo " site = local.${site_id_to_name[${args[site_id]}]}.name" 66 | echo "" 67 | c_echo_dhcp_relay_servers "${args[dhcp_relay_server_1]}" "${args[dhcp_relay_server_2]}" "${args[dhcp_relay_server_3]}" "${args[dhcp_relay_server_4]}" "${args[dhcp_relay_server_5]}" 68 | c_echo "firewall_guest_default_log" " firewall_guest_default_log = %s" 69 | c_echo "firewall_lan_default_log" " firewall_lan_default_log = %s" 70 | c_echo "firewall_wan_default_log" " firewall_wan_default_log = %s" 71 | echo "}" 72 | echo "" 73 | } >> unifi_settings_usg.tf 74 | } 75 | 76 | write_import() { 77 | local -n args=$1 78 | 79 | { 80 | echo "import {" 81 | echo " to = unifi_setting_usg.${args[sanitized_id]}" 82 | echo " id = \"${args[_id]}\"" 83 | echo "}" 84 | echo "" 85 | } >> unifi_settings_usg_import.tf 86 | } 87 | 88 | main() { 89 | load_site_mappings 90 | 91 | > unifi_settings_usg.tf 92 | > unifi_settings_usg_import.tf 93 | 94 | # Process each line from read_json 95 | while IFS='◊' read -ra line_data; do 96 | declare -A resource_args 97 | 98 | for index in "${!KEYS[@]}"; do 99 | resource_args["${KEYS[index]}"]="${line_data[index]}" 100 | done 101 | 102 | # Only process entries where key is 'radius' 103 | if [ "${resource_args[key]}" = "usg" ]; then 104 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 105 | 106 | log_console "Processing settings_usg: 1 object..." 107 | log_debug " Writing object: type=settings_usg id=${resource_args[_id]}" 108 | 109 | write_resource resource_args 110 | write_import resource_args 111 | fi 112 | done < <(read_json "$json_file_name" KEYS) 113 | 114 | } 115 | 116 | # Execute the main function 117 | main 118 | -------------------------------------------------------------------------------- /scripts/generate_unifi_sites.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility script 3 | source ./scripts/json_utils.sh 4 | source ./scripts/terraform_utils.sh 5 | 6 | readonly json_file_name="json/sites.json" 7 | readonly KEYS=( 8 | "_id" 9 | "desc" 10 | ) 11 | 12 | write_resource() { 13 | local -n args=$1 14 | 15 | { 16 | echo "resource \"unifi_site\" \"${args[sanitized_id]}\" {" 17 | echo " description = \"${args[desc]}\"" 18 | echo "" 19 | echo " lifecycle {" 20 | echo " prevent_destroy = true" 21 | echo " }" 22 | echo "}" 23 | echo "" 24 | } >> unifi_sites.tf 25 | } 26 | 27 | write_import() { 28 | local -n args=$1 29 | 30 | { 31 | echo "import {" 32 | echo " to = unifi_site.${args[sanitized_id]}" 33 | echo " id = \"${args[_id]}\"" 34 | echo "}" 35 | echo "" 36 | } >> unifi_sites_import.tf 37 | } 38 | 39 | write_local() { 40 | local -n args=$1 41 | 42 | echo " unifi_site_${args[sanitized_desc]} = unifi_site.${args[sanitized_id]}" >> unifi_sites_map.tf 43 | } 44 | 45 | main() { 46 | > unifi_sites.tf 47 | > unifi_sites_import.tf 48 | > unifi_sites_map.tf 49 | 50 | echo "locals {" > unifi_sites_map.tf 51 | 52 | log_console_object_count "$json_file_name" 53 | 54 | while IFS='◊' read -ra line_data; do 55 | declare -A resource_args 56 | 57 | for index in "${!KEYS[@]}"; do 58 | resource_args["${KEYS[index]}"]="${line_data[index]}" 59 | done 60 | 61 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 62 | resource_args[sanitized_desc]="$(sanitize_for_terraform "${resource_args[desc]}")" 63 | 64 | log_debug " Writing object: id=${resource_args[_id]} desc=${resource_args[desc]}" 65 | 66 | write_resource resource_args 67 | write_import resource_args 68 | write_local resource_args 69 | done < <(read_json "$json_file_name" KEYS) 70 | 71 | echo "}" >> unifi_sites_map.tf 72 | } 73 | 74 | # Execute the main function 75 | main 76 | -------------------------------------------------------------------------------- /scripts/generate_unifi_static_routes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility script 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/static_routes.json" 9 | readonly KEYS=( 10 | "_id" 11 | "enabled" 12 | "gateway_device" 13 | "gateway_type" 14 | "name" 15 | "site_id" 16 | "static-route_distance" 17 | "static-route_interface" 18 | "static-route_network" 19 | "static-route_nexthop" 20 | "static-route_type" 21 | "type" 22 | ) 23 | 24 | write_resource() { 25 | local -n args=$1 # Use a nameref to refer to the associative array 26 | 27 | { 28 | echo "resource \"unifi_static_route\" \"${args[sanitized_id]}\" {" 29 | 30 | c_echo "name" " name = \"%s\"" 31 | echo " site = local.unifi_site_Default.name" 32 | c_echo "enabled" " # enabled = %s" 33 | echo "" 34 | c_echo "static-route_network" " network = \"%s\"" 35 | c_echo "static-route_type" " type = \"%s\"" 36 | c_echo "static-route_distance" " distance = %s" 37 | c_echo "static_route_interface_resource_name" " interface = %s" 38 | c_echo "static-route_nexthop" " next_hop = \"%s\"" 39 | echo "}" 40 | echo "" 41 | } >> unifi_static_routes.tf 42 | } 43 | 44 | write_import() { 45 | local -n args=$1 # Use a nameref to refer to the associative array 46 | 47 | { 48 | echo "import {" 49 | echo " to = unifi_static_route.${args[sanitized_id]}" 50 | echo " id = \"${args[_id]}\"" 51 | echo "}" 52 | echo "" 53 | } >> unifi_static_routes_import.tf 54 | } 55 | 56 | write_local() { 57 | local -n args=$1 # Use a nameref to refer to the associative array 58 | 59 | echo " unifi_static_route_${args[sanitized_name]} = unifi_static_route.${args[sanitized_id]}" >> unifi_static_routes_map.tf 60 | } 61 | 62 | main() { 63 | # Load the mappings 64 | load_device_mappings 65 | load_network_mappings 66 | load_site_mappings 67 | 68 | # Clear existing files or create them if they don't exist 69 | > unifi_static_routes.tf 70 | > unifi_static_routes_import.tf 71 | > unifi_static_routes_map.tf 72 | 73 | # Initialize unifi_static_routes_map.tf with the header 74 | echo "locals {" > unifi_static_routes_map.tf 75 | 76 | log_console_object_count "$json_file_name" 77 | 78 | # Process each line from read_json 79 | while IFS='◊' read -ra values; do 80 | 81 | # Create an associative array from the keys and values 82 | declare -A resource_args 83 | 84 | for index in "${!KEYS[@]}"; do 85 | resource_args["${KEYS[index]}"]="${values[index]}" 86 | done 87 | 88 | # Parse additional data 89 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 90 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 91 | resource_args[site_resource_name]="${site_id_to_name[${resource_args[site_id]}]}" 92 | if [ -n "${resource_args[static-route_interface]}" ]; then 93 | if [ -n "${network_id_to_name[${resource_args[static-route_interface]}]}" ]; then 94 | resource_args[static_route_interface_resource_name]="local.${network_id_to_name[${resource_args[static-route_interface]}]}.id" 95 | else 96 | resource_args[static_route_interface_resource_name]="\"${resource_args[static-route_interface]}\"" 97 | fi 98 | else 99 | resource_args[static_route_interface_resource_name]="" 100 | fi 101 | 102 | log_debug " Writing object: id=${resource_args[_id]} name=${resource_args[name]}" 103 | 104 | # Write the resource blocks 105 | write_resource resource_args 106 | 107 | # Write the import blocks 108 | write_import resource_args 109 | 110 | # Write the locals block 111 | write_local resource_args 112 | 113 | done < <(read_json "$json_file_name" KEYS) 114 | 115 | # Close the locals block 116 | echo "}" >> unifi_static_routes_map.tf 117 | } 118 | 119 | # Execute the main function 120 | main 121 | -------------------------------------------------------------------------------- /scripts/generate_unifi_user_groups.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/user_groups.json" 9 | readonly KEYS=( 10 | "_id" 11 | "name" 12 | "qos_rate_max_up" 13 | "qos_rate_max_down" 14 | "site_id" 15 | ) 16 | 17 | write_resource() { 18 | local -n args=$1 19 | 20 | { 21 | echo "resource \"unifi_user_group\" \"${args[sanitized_id]}\" {" 22 | echo " name = \"${args[name]}\"" 23 | echo " qos_rate_max_up = ${args[qos_rate_max_up]}" 24 | echo " qos_rate_max_down = ${args[qos_rate_max_down]}" 25 | echo "" 26 | if [ "${site_id_to_name[${args[site_id]}]}" = "unifi_site_Default" ]; then 27 | echo " # Commenting out the default site as the provider will attempt" 28 | echo " # to destroy / create if it is included" 29 | echo "" 30 | echo " # site = local.${site_id_to_name[${args[site_id]}]}" 31 | else 32 | echo " site = local.${site_id_to_name[${args[site_id]}]}" 33 | fi 34 | echo "}" 35 | echo "" 36 | } >> unifi_user_groups.tf 37 | } 38 | 39 | write_import() { 40 | local -n args=$1 41 | 42 | { 43 | echo "import {" 44 | echo " to = unifi_user_group.${args[sanitized_id]}" 45 | echo " id = \"${args[_id]}\"" 46 | echo "}" 47 | echo "" 48 | } >> unifi_user_groups_import.tf 49 | } 50 | 51 | write_local() { 52 | local -n args=$1 53 | 54 | echo " unifi_user_group_${args[sanitized_name]} = unifi_user_group.${args[sanitized_id]}" >> unifi_user_groups_map.tf 55 | } 56 | 57 | main() { 58 | load_site_mappings 59 | 60 | > unifi_user_groups.tf 61 | > unifi_user_groups_import.tf 62 | > unifi_user_groups_map.tf 63 | 64 | echo "locals {" > unifi_user_groups_map.tf 65 | 66 | log_console_object_count "$json_file_name" 67 | 68 | while IFS=$'◊' read -ra line_data; do 69 | declare -A resource_args 70 | 71 | for index in "${!KEYS[@]}"; do 72 | resource_args["${KEYS[index]}"]="${line_data[index]}" 73 | done 74 | 75 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 76 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 77 | 78 | log_debug " Writing object: id=${resource_args[_id]} name=${resource_args[name]}" 79 | 80 | write_resource resource_args 81 | write_import resource_args 82 | write_local resource_args 83 | done < <(read_json "$json_file_name" KEYS) 84 | 85 | echo "}" >> unifi_user_groups_map.tf 86 | } 87 | 88 | # Execute the main function 89 | main 90 | -------------------------------------------------------------------------------- /scripts/generate_unifi_users.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/users.json" 9 | readonly KEYS=( 10 | "_id" 11 | "blocked" 12 | "dev_id_override" 13 | "fingerprint_override" 14 | "fixed_ip" 15 | "hostname" 16 | "local_dns_record" 17 | "local_dns_record_enabled" 18 | "mac" 19 | "name" 20 | "network_id" 21 | "note" 22 | "noted" 23 | "use_fixedip" 24 | "virtual_network_override_enabled" 25 | "virtual_network_override_id" 26 | ) 27 | 28 | write_resource() { 29 | local -n args=$1 30 | 31 | local network_resource_name="" 32 | if [ -n "${args[network_id]}" ]; then 33 | network_resource_name="${network_id_to_name[${args[network_id]}]}" 34 | fi 35 | 36 | if [ -n "${args[virtual_network_override_id]}" ] && [ "${args[virtual_network_override_enabled]}" = "true" ]; then 37 | network_override_name="${network_id_to_name[${args[virtual_network_override_id]}]}" 38 | fi 39 | 40 | { 41 | echo "resource \"unifi_user\" \"${args[sanitized_id]}\" {" 42 | echo " mac = \"${args[mac]}\"" 43 | echo " name = \"${args[escaped_name]}\"" 44 | echo " # hostname = \"${args[hostname]}\"" 45 | # If blocked is "", then set to false 46 | [ -z "${args[blocked]}" ] && args[blocked]="false" 47 | echo " blocked = ${args[blocked]}" 48 | [ "${args[noted]}" = "true" ] && [ -n "${args[note]}" ] && echo " note = \"${args[note]}\"" 49 | if [ "${args[use_fixedip]}" = "true" ]; then 50 | echo " fixed_ip = \"${args[fixed_ip]}\"" 51 | [ -n "${args[network_id]}" ] && echo " network_id = local.${network_resource_name}.id" 52 | fi 53 | [ "${args[local_dns_record_enabled]}" = "true" ] && [ -n "${args[local_dns_record]}" ] && echo " local_dns_record = \"${args[local_dns_record]}\"" 54 | [ "${args[fingerprint_override]}" = "true" ] && [ -n "${args[dev_id_override]}" ] && echo " dev_id_override = ${args[dev_id_override]}" 55 | [ -n "${args[virtual_network_override_id]}" ] && [ "${args[virtual_network_override_enabled]}" = "true" ] && echo " # virtual_network_override_id = local.${network_override_name}.id" 56 | echo " skip_forget_on_destroy = true" 57 | echo " allow_existing = true" 58 | echo "}" 59 | echo "" 60 | } >> unifi_users.tf 61 | } 62 | 63 | write_import() { 64 | local -n args=$1 65 | 66 | { 67 | echo "import {" 68 | echo " to = unifi_user.${args[sanitized_id]}" 69 | echo " id = \"${args[_id]}\"" 70 | echo "}" 71 | echo "" 72 | } >> unifi_users_import.tf 73 | } 74 | 75 | write_local() { 76 | local -n args=$1 77 | 78 | local user_name="${args[name]}" 79 | if [ -z "$user_name" ]; then 80 | user_name="${args[sanitized_id]}" 81 | else 82 | user_name="${args[sanitized_name]}" 83 | fi 84 | 85 | echo " unifi_user_${user_name} = unifi_user.${args[sanitized_id]}" >> unifi_users_map.tf 86 | } 87 | 88 | main() { 89 | load_network_mappings 90 | 91 | > unifi_users.tf 92 | > unifi_users_import.tf 93 | > unifi_users_map.tf 94 | 95 | echo "locals {" > unifi_users_map.tf 96 | 97 | log_console_object_count "$json_file_name" 98 | 99 | while IFS='◊' read -ra line_data; do 100 | declare -A resource_args 101 | 102 | for index in "${!KEYS[@]}"; do 103 | resource_args["${KEYS[index]}"]="${line_data[index]}" 104 | done 105 | 106 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[mac]}")" 107 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 108 | resource_args[escaped_name]="$(escape_quotes "${resource_args[name]}")" 109 | 110 | log_debug " Writing object: id=${resource_args[_id]} mac=${resource_args[mac]} name=${resource_args[name]}" 111 | 112 | write_resource resource_args 113 | write_import resource_args 114 | write_local resource_args 115 | done < <(read_json "$json_file_name" KEYS) 116 | 117 | echo "}" >> unifi_users_map.tf 118 | } 119 | 120 | # Execute the main function 121 | main 122 | -------------------------------------------------------------------------------- /scripts/generate_unifi_wlans.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source the utility scripts 3 | source ./scripts/json_utils.sh 4 | source ./scripts/log_utils.sh 5 | source ./scripts/mapping_utils.sh 6 | source ./scripts/terraform_utils.sh 7 | 8 | readonly json_file_name="json/wlans.json" 9 | readonly KEYS=( 10 | "_id" 11 | "ap_group_ids" 12 | "bss_transition" 13 | "fast_roaming_enabled" 14 | "hide_ssid" 15 | "is_guest" 16 | "l2_isolation" 17 | "mac_filter_enabled" 18 | "mac_filter_list" 19 | "mac_filter_policy" 20 | "mcastenhance_enabled" 21 | "minrate_na_data_rate_kbps" 22 | "minrate_ng_data_rate_kbps" 23 | "name" 24 | "networkconf_id" 25 | "no2ghz_oui" 26 | "pmf_mode" 27 | "proxy_arp" 28 | "radiusprofile_id" 29 | "schedule_with_duration" 30 | "security" 31 | "site_id" 32 | "uapsd_enabled" 33 | "usergroup_id" 34 | "wlan_band" 35 | "wpa3_support" 36 | "wpa3_transition" 37 | ) 38 | 39 | write_resource() { 40 | local -n args=$1 41 | 42 | { 43 | echo "resource \"unifi_wlan\" \"${args[sanitized_id]}\" {" 44 | echo " name = \"${args[name]}\"" 45 | 46 | if [ "${site_id_to_name[${args[site_id]}]}" = "unifi_site_Default" ]; then 47 | echo " # site = local.${site_id_to_name[${args[site_id]}]}.name" 48 | else 49 | echo " site = local.${site_id_to_name[${args[site_id]}]}.name" 50 | fi 51 | 52 | echo " security = \"${args[security]}\"" 53 | echo " user_group_id = local.${user_group_id_to_name[${args[usergroup_id]}]}.id" 54 | c_echo "is_guest" " is_guest = %s" 55 | echo " network_id = local.${network_id_to_name[${args[networkconf_id]}]}.id" 56 | if [ -n "${args[radiusprofile_id]}" ]; then 57 | echo " radius_profile_id = local.${radius_profile_id_to_name[${args[radiusprofile_id]}]}.id" 58 | fi 59 | echo " passphrase = var.unifi_wlan_${args[sanitized_name]}_passphrase" 60 | c_echo_ap_groups "${args[ap_group_ids]}" 61 | echo "" 62 | c_echo "bss_transition" " bss_transition = %s" 63 | c_echo "fast_roaming_enabled" " fast_roaming_enabled = %s" 64 | c_echo "hide_ssid" " hide_ssid = %s" 65 | c_echo "l2_isolation" " l2_isolation = %s" 66 | c_echo "mac_filter_enabled" " mac_filter_enabled = %s" 67 | c_echo_wlan_security_mac_address "${args[mac_filter_list]}" 68 | c_echo "mac_filter_policy" " mac_filter_policy = \"%s\"" 69 | c_echo "minrate_ng_data_rate" " minimum_data_rate_2g_kbps = %s" 70 | c_echo "minrate_na_data_rate" " minimum_data_rate_5g_kbps = %s" 71 | c_echo "mcastenhance_enabled" " multicast_enhance = %s" 72 | c_echo "no2ghz_oui" " no2ghz_oui = %s" 73 | c_echo "pmf_mode" " pmf_mode = \"%s\"" 74 | c_echo "proxy_arp" " proxy_arp = %s" 75 | c_echo "uapsd_enabled" " uapsd = %s" 76 | c_echo "wlan_band" " wlan_band = \"%s\"" 77 | c_echo "wpa3_support" " wpa3_support = %s" 78 | c_echo "wpa3_transition" " wpa3_transition = %s" 79 | c_echo_wlan_schedules "${args[schedule_with_duration]}" 80 | echo "}" 81 | echo "" 82 | } >> unifi_wlans.tf 83 | } 84 | 85 | write_import() { 86 | local -n args=$1 87 | 88 | { 89 | echo "import {" 90 | echo " to = unifi_wlan.${args[sanitized_id]}" 91 | echo " id = \"${args[_id]}\"" 92 | echo "}" 93 | echo "" 94 | } >> unifi_wlans_import.tf 95 | } 96 | 97 | write_local() { 98 | local -n args=$1 99 | 100 | echo " unifi_wlan_${args[sanitized_name]} = unifi_wlan.${args[sanitized_id]}" >> unifi_wlans_map.tf 101 | } 102 | 103 | main() { 104 | load_site_mappings 105 | load_user_group_mappings 106 | load_user_mappings 107 | load_device_mappings 108 | load_network_mappings 109 | load_ap_group_mappings 110 | load_radius_profile_mappings 111 | 112 | > unifi_wlans.tf 113 | > unifi_wlans_import.tf 114 | > unifi_wlans_map.tf 115 | 116 | echo "locals {" > unifi_wlans_map.tf 117 | 118 | log_console_object_count "$json_file_name" 119 | 120 | while IFS='◊' read -ra line_data; do 121 | declare -A resource_args 122 | 123 | for index in "${!KEYS[@]}"; do 124 | resource_args["${KEYS[index]}"]="${line_data[index]}" 125 | done 126 | 127 | resource_args[sanitized_id]="id_$(sanitize_for_terraform "${resource_args[_id]}")" 128 | resource_args[sanitized_name]="$(sanitize_for_terraform "${resource_args[name]}")" 129 | 130 | log_debug " Writing object: id=${resource_args[_id]} name=${resource_args[name]}" 131 | 132 | write_resource resource_args 133 | write_import resource_args 134 | write_local resource_args 135 | done < <(read_json "$json_file_name" KEYS) 136 | 137 | echo "}" >> unifi_wlans_map.tf 138 | } 139 | 140 | # Execute the main function 141 | main 142 | -------------------------------------------------------------------------------- /scripts/generate_variables.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Gather variables from all unifi_*.tf files 3 | vars=$(grep -h -o -E 'var\.[a-zA-Z0-9_-]*' unifi_*.tf | sort | uniq | sed 's/var.//g') 4 | 5 | # Clear existing files or create them if they don't exist 6 | > variables.tf 7 | 8 | # Write the variables to variables.tf 9 | for var in $vars; do 10 | echo "variable \"$var\" {" >> variables.tf 11 | echo " type = string" >> variables.tf 12 | echo " sensitive = true" >> variables.tf 13 | echo "}" >> variables.tf 14 | echo "" >> variables.tf 15 | done 16 | -------------------------------------------------------------------------------- /scripts/get_accounts.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="accounts" 3 | readonly ENDPOINT="proxy/network/v2/api/site/default/radius/users" 4 | readonly SORT_BY='sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source ./scripts/log_utils.sh 3 | log_debug "Executing get_all.sh..." 4 | 5 | # Source get_token.sh to set TOKEN and UNIFI_IP 6 | source ./scripts/get_token.sh "$@" 7 | 8 | ./scripts/get_accounts.sh -i $UNIFI_IP -t $TOKEN 9 | ./scripts/get_ap_groups.sh -i $UNIFI_IP -t $TOKEN 10 | ./scripts/get_devices.sh -i $UNIFI_IP -t $TOKEN 11 | ./scripts/get_dynamic_dns.sh -i $UNIFI_IP -t $TOKEN 12 | ./scripts/get_firewall_groups.sh -i $UNIFI_IP -t $TOKEN 13 | ./scripts/get_firewall_rules.sh -i $UNIFI_IP -t $TOKEN 14 | ./scripts/get_networks.sh -i $UNIFI_IP -t $TOKEN 15 | ./scripts/get_port_forward.sh -i $UNIFI_IP -t $TOKEN 16 | ./scripts/get_port_profiles.sh -i $UNIFI_IP -t $TOKEN 17 | ./scripts/get_radius_profiles.sh -i $UNIFI_IP -t $TOKEN 18 | ./scripts/get_settings.sh -i $UNIFI_IP -t $TOKEN 19 | ./scripts/get_sites.sh -i $UNIFI_IP -t $TOKEN 20 | ./scripts/get_static_routes.sh -i $UNIFI_IP -t $TOKEN 21 | ./scripts/get_user_groups.sh -i $UNIFI_IP -t $TOKEN 22 | ./scripts/get_users.sh -i $UNIFI_IP -t $TOKEN 23 | ./scripts/get_wlans.sh -i $UNIFI_IP -t $TOKEN 24 | 25 | log_debug "Finished executing get_all.sh" 26 | -------------------------------------------------------------------------------- /scripts/get_ap_groups.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="ap_groups" 3 | readonly ENDPOINT="proxy/network/v2/api/site/default/apgroups" 4 | readonly SORT_BY='sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_devices.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="devices" 3 | readonly ENDPOINT="proxy/network/v2/api/site/default/device" 4 | readonly SORT_BY='.network_devices | sort_by(.mac)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_dynamic_dns.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="dynamic_dns" 3 | readonly ENDPOINT="proxy/network/api/s/default/rest/dynamicdns" 4 | readonly SORT_BY='.data | sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_firewall_groups.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="firewall_groups" 3 | readonly ENDPOINT="proxy/network/api/s/default/rest/firewallgroup" 4 | readonly SORT_BY='.data | sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_firewall_rules.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="firewall_rules" 3 | readonly ENDPOINT="proxy/network/api/s/default/rest/firewallrule" 4 | readonly SORT_BY='.data | sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_networks.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="networks" 3 | readonly ENDPOINT="proxy/network/v2/api/site/default/lan/enriched-configuration" 4 | readonly SORT_BY='map(.configuration) | sort_by(.vlan)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_port_forward.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="port_forward" 3 | readonly ENDPOINT="proxy/network/api/s/default/rest/portforward" 4 | readonly SORT_BY='.data | sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_port_profiles.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="port_profiles" 3 | readonly ENDPOINT="proxy/network/api/s/default/rest/portconf" 4 | readonly SORT_BY='.data | sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_radius_profiles.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="radius_profiles" 3 | readonly ENDPOINT="proxy/network/api/s/default/rest/radiusprofile" 4 | readonly SORT_BY='.data | sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_settings.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="settings" 3 | readonly ENDPOINT="proxy/network/api/s/default/get/setting" 4 | readonly SORT_BY='.data | sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_sites.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="sites" 3 | readonly ENDPOINT="proxy/network/v2/api/info" 4 | readonly SORT_BY='.sites | sort_by(.name)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_static_routes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="static_routes" 3 | readonly ENDPOINT="proxy/network/api/s/default/rest/routing" 4 | readonly SORT_BY='.data | sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_token.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source ./scripts/log_utils.sh 3 | 4 | # Initialize variables 5 | UNIFI_IP="" 6 | UNIFI_USER="" 7 | UNIFI_PASSWORD="" 8 | UNIFI_TOKEN="" 9 | 10 | # Function to show usage 11 | usage() { 12 | log_console "Usage: $0 -i UNIFI_IP [-u UNIFI_USER -p UNIFI_PASSWORD] [-t UNIFI_TOKEN]" 13 | exit 1 14 | } 15 | 16 | # Parse command-line options 17 | while getopts "i:u:p:t:v" opt; do 18 | case $opt in 19 | i) UNIFI_IP=$OPTARG ;; 20 | u) UNIFI_USER=$OPTARG ;; 21 | p) UNIFI_PASSWORD=$OPTARG ;; 22 | t) UNIFI_TOKEN=$OPTARG ;; 23 | *) usage ;; 24 | esac 25 | done 26 | 27 | # Fallback to environment variables if no arguments are provided 28 | if [ -z "$UNIFI_IP" ]; then 29 | UNIFI_IP=$SECRET_UNIFI_IP 30 | fi 31 | if [ -z "$UNIFI_USER" ]; then 32 | UNIFI_USER=$SECRET_UNIFI_USER 33 | fi 34 | if [ -z "$UNIFI_PASSWORD" ]; then 35 | UNIFI_PASSWORD=$SECRET_UNIFI_PASSWORD 36 | fi 37 | 38 | # Check for required IP address 39 | if [ -z "$UNIFI_IP" ]; then 40 | log_console "Error: UNIFI_IP is required." 41 | usage 42 | fi 43 | 44 | # Determine login method and get/set token 45 | if [ -z "$UNIFI_TOKEN" ]; then 46 | # Login to get token 47 | log_console "Logging in..." 48 | log_debug "Attempting to get token with user credentials..." 49 | # Debug: Print the values being used (except password for security) 50 | log_debug "Using UNIFI_IP: $UNIFI_IP" 51 | log_debug "Using UNIFI_USER: $UNIFI_USER" 52 | response=$(curl -i -s -S "https://$UNIFI_IP/api/auth/login" \ 53 | -H "authority: $UNIFI_IP" \ 54 | -H 'accept: */*' \ 55 | -H 'accept-language: en-US,en' \ 56 | -H 'content-type: application/json' \ 57 | -H "origin: $UNIFI_IP" \ 58 | --data-raw "{\"username\":\"$UNIFI_USER\",\"password\":\"$UNIFI_PASSWORD\",\"token\":\"\",\"rememberMe\":false}" \ 59 | --compressed \ 60 | --insecure) 61 | 62 | # Separate headers and JSON body for logging 63 | headers=$(echo "$response" | sed -n '1,/^\r$/p') 64 | json_body=$(echo "$response" | sed -n '/^\r$/,$p' | sed '1d') 65 | 66 | log_debug "Auth Headers:" 67 | log_debug "$headers" 68 | log_debug "Auth JSON Body:" 69 | log_debug "$(echo "$json_body" | jq .)" 70 | 71 | TOKEN=$(echo "$response" | grep 'set-cookie:' | awk -F'TOKEN=' '{print $2}' | awk -F';' '{print $1}') 72 | log_debug "Obtained TOKEN: $TOKEN" 73 | elif [ -n "$UNIFI_TOKEN" ]; then 74 | # Use provided token 75 | TOKEN=$UNIFI_TOKEN 76 | log_debug "Using provided TOKEN." 77 | else 78 | log_console "Error: Either UNIFI_USER and UNIFI_PASSWORD or UNIFI_TOKEN is required." 79 | usage 80 | fi 81 | 82 | # Export TOKEN 83 | export TOKEN 84 | export UNIFI_IP 85 | 86 | # Check if TOKEN is empty and exit if it is 87 | if [ -z "$TOKEN" ]; then 88 | log_console "Error: Failed to obtain token." 89 | exit 1 90 | fi 91 | -------------------------------------------------------------------------------- /scripts/get_user_groups.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="user_groups" 3 | readonly ENDPOINT="proxy/network/api/s/default/rest/usergroup" 4 | readonly SORT_BY='.data | sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_users.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="users" 3 | readonly ENDPOINT="proxy/network/api/s/default/list/user" 4 | readonly SORT_BY='.data | sort_by(.mac // "zzzzzzzzzzzz" | ascii_downcase)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/get_wlans.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | readonly TYPE="wlans" 3 | readonly ENDPOINT="proxy/network/api/s/default/rest/wlanconf" 4 | readonly SORT_BY='.data | sort_by(._id)' 5 | 6 | source ./scripts/json_utils.sh 7 | source ./scripts/log_utils.sh 8 | 9 | log_console "Retrieving $TYPE..." 10 | 11 | source ./scripts/get_token.sh "$@" 12 | 13 | # Fetch the data 14 | raw=$(fetch_raw_json "$UNIFI_IP" "$ENDPOINT" "$TYPE" "$TOKEN") 15 | 16 | # Post-processing 17 | alphabetize_raw_json "$raw" | jq "$SORT_BY" > json/$TYPE.json 18 | log_debug "Sorted JSON saved to json/$TYPE.json" 19 | -------------------------------------------------------------------------------- /scripts/json_utils.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source ./scripts/log_utils.sh 3 | 4 | fetch_raw_json() { 5 | local unifi_ip="$1" 6 | local endpoint="$2" 7 | local filename="$3" 8 | local token="$4" 9 | 10 | log_debug "API Endpoint: https://$unifi_ip/$endpoint" 11 | local raw=$(curl -s -S "https://$unifi_ip/$endpoint" \ 12 | -H "authority: $unifi_ip" \ 13 | -H 'accept: application/json, text/plain, */*' \ 14 | -H 'accept-language: en-US,en' \ 15 | -H "cookie: TOKEN=$token" \ 16 | --compressed \ 17 | --insecure) 18 | 19 | echo "$raw" | jq > json/raw/$filename.json 20 | log_debug "Raw JSON saved to json/raw/$filename.json" 21 | 22 | echo "$raw" 23 | } 24 | 25 | # Function to sort JSON data 26 | alphabetize_raw_json() { 27 | local json_data=$1 28 | 29 | echo "$json_data" | jq ' 30 | 31 | # Define a recursive sorting function named "recursive_sort" 32 | def recursive_sort: 33 | if type == "object" then 34 | to_entries | 35 | sort_by(.key) | 36 | map({ ( .key ): (.value | recursive_sort) }) | 37 | add 38 | elif type == "array" then 39 | map(recursive_sort) 40 | else 41 | . 42 | end; 43 | 44 | recursive_sort' 45 | } 46 | 47 | # Function to read and output JSON data 48 | read_json() { 49 | local file_name="$1" 50 | local -n keys=$2 51 | 52 | log_debug_object_count "$file_name" 53 | 54 | # Helper function to create a dynamic jq filter from the KEYS array 55 | create_jq_filter() { 56 | # Defining a jq function 'parse' using heredoc for readability. 57 | # This function checks if a given field exists at the top level, 58 | # handles array types by joining their elements with commas, 59 | # or returns the field value directly. 60 | local jq_parse_function=$(cat <<'EOF' 61 | def parse(field): 62 | if (has(field)) then 63 | if (.[field] | type) == "array" then 64 | if (.[field] | length) == 0 then 65 | "" 66 | else 67 | if field == "port_table" then 68 | .[field] | tojson 69 | elif field == "x_ssh_keys" then 70 | .[field] | tojson 71 | elif field == "schedule_with_duration" then 72 | .[field] | tojson 73 | elif field == "auth_servers" then 74 | .[field] | map([.ip, .port | tostring] | join(":")) | join(",") 75 | else 76 | .[field] | join(",") 77 | end 78 | end 79 | else 80 | .[field] 81 | end 82 | else 83 | "" 84 | end; 85 | EOF 86 | ) 87 | 88 | # Start building the main jq filter command. This command will 89 | # apply the parse function to each field listed in the KEYS array. 90 | local jq_main_filter='.[] | [' 91 | 92 | # Iterate over the KEYS array, appending each key to the jq filter. 93 | for key in "${keys[@]}"; do 94 | jq_main_filter+="parse(\"$key\"), " 95 | done 96 | 97 | # Trim the trailing comma and space from the filter string, then 98 | # close the filter with a bracket and join the results with a custom delimiter. 99 | jq_main_filter=${jq_main_filter%, } 100 | jq_main_filter+="] | join(\"◊\")" 101 | 102 | # Combine the parse function and the main filter to form the complete jq filter. 103 | echo "$jq_parse_function $jq_main_filter" 104 | } 105 | 106 | # Generate the dynamic jq filter by calling the helper function. 107 | local dynamic_filter=$(create_jq_filter) 108 | 109 | # Execute the jq command with the dynamically generated filter 110 | # to process the JSON file. 111 | jq -r "$dynamic_filter" "$file_name" 112 | } 113 | -------------------------------------------------------------------------------- /scripts/log_utils.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Redirect stderr to both the console and log.txt, adding [ERROR] prefix 3 | exec 2> >(while read line; do echo "[ERROR] $line"; done | tee -a log.txt) 4 | 5 | # Function for logging 6 | log_debug() { 7 | echo "[DEBUG] $1" >> log.txt 8 | } 9 | 10 | log_console() { 11 | echo "[CONSOLE] $1" >> log.txt 12 | echo "$1" 13 | } 14 | 15 | log_debug_object_count() { 16 | local file_name="$1" 17 | local type=$(echo "$file_name" | sed 's/json\///g' | sed 's/\.json//g') 18 | 19 | count=$(jq '. | length' "$file_name") 20 | 21 | if [ "$count" -eq 1 ]; then 22 | log_debug "Reading $type: $count object found..." 23 | else 24 | log_debug "Reading $type: $count objects found..." 25 | fi 26 | } 27 | 28 | log_console_object_count() { 29 | local file_name="$1" 30 | local type=$(echo "$file_name" | sed 's/json\///g' | sed 's/\.json//g') 31 | 32 | count=$(jq '. | length' "$file_name") 33 | 34 | # Calculate the number of spaces needed 35 | local max_length=15 # length of "radius_profiles" 36 | local type_length=${#type} 37 | local num_spaces=$((max_length - type_length + 1)) # +1 for the space after the colon 38 | local spaces=$(printf '%*s' "$num_spaces") 39 | 40 | if [ "$count" -eq 1 ]; then 41 | log_console "Processing $type:$spaces$count object..." 42 | else 43 | log_console "Processing $type:$spaces$count objects..." 44 | fi 45 | } 46 | -------------------------------------------------------------------------------- /scripts/mapping_utils.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | declare -A ap_group_id_to_name 3 | declare -A device_id_to_name 4 | declare -A firewall_group_id_to_name 5 | declare -A network_id_to_name 6 | declare -A port_forward_id_to_name 7 | declare -A port_profile_id_to_name 8 | declare -A radius_profile_id_to_name 9 | declare -A site_id_to_name 10 | declare -A user_id_to_name 11 | declare -A user_group_id_to_name 12 | 13 | load_ap_group_mappings() { 14 | while IFS=' =' read -r key value; do 15 | if [[ $value =~ unifi_ap_group\.id_(.+) ]]; then 16 | local ap_group_id="${BASH_REMATCH[1]}" 17 | ap_group_id_to_name[$ap_group_id]=$key 18 | fi 19 | done < unifi_ap_groups_map.tf 20 | } 21 | 22 | load_device_mappings() { 23 | while IFS=' =' read -r key value; do 24 | if [[ $value =~ unifi_device\.id_(.+) ]]; then 25 | local device_id="${BASH_REMATCH[1]}" 26 | device_id_to_name[$device_id]=$key 27 | fi 28 | done < unifi_devices_map.tf 29 | } 30 | 31 | load_firewall_group_mappings() { 32 | while IFS=' =' read -r key value; do 33 | if [[ $value =~ unifi_firewall_group\.id_(.+) ]]; then 34 | local firewall_group_id="${BASH_REMATCH[1]}" 35 | firewall_group_id_to_name[$firewall_group_id]=$key 36 | fi 37 | done < unifi_firewall_groups_map.tf 38 | } 39 | 40 | load_network_mappings() { 41 | while IFS=' =' read -r key value; do 42 | if [[ $value =~ unifi_network\.id_(.+) ]]; then 43 | local network_id="${BASH_REMATCH[1]}" 44 | network_id_to_name[$network_id]=$key 45 | fi 46 | done < unifi_networks_map.tf 47 | } 48 | 49 | load_port_forward_mappings() { 50 | while IFS=' =' read -r key value; do 51 | if [[ $value =~ unifi_port_forward\.id_(.+) ]]; then 52 | local port_forward_id="${BASH_REMATCH[1]}" 53 | port_forward_id_to_name[$port_forward_id]=$key 54 | fi 55 | done < unifi_port_forwards_map.tf 56 | } 57 | 58 | load_port_profile_mappings() { 59 | while IFS=' =' read -r key value; do 60 | if [[ $value =~ unifi_port_profile\.id_(.+) ]]; then 61 | local port_profile_id="${BASH_REMATCH[1]}" 62 | port_profile_id_to_name[$port_profile_id]=$key 63 | fi 64 | done < unifi_port_profiles_map.tf 65 | } 66 | 67 | load_radius_profile_mappings() { 68 | while IFS=' =' read -r key value; do 69 | if [[ $value =~ unifi_radius_profile\.id_(.+) ]]; then 70 | local radius_profile_id="${BASH_REMATCH[1]}" 71 | radius_profile_id_to_name[$radius_profile_id]=$key 72 | fi 73 | done < unifi_radius_profiles_map.tf 74 | } 75 | 76 | load_site_mappings() { 77 | while IFS=' =' read -r key value; do 78 | if [[ $value =~ unifi_site\.id_(.+) ]]; then 79 | local site_id="${BASH_REMATCH[1]}" 80 | site_id_to_name[$site_id]=$key 81 | fi 82 | done < unifi_sites_map.tf 83 | } 84 | 85 | load_user_mappings() { 86 | while IFS=' =' read -r key value; do 87 | if [[ $value =~ unifi_user\.id_(.+) ]]; then 88 | local user_id="${BASH_REMATCH[1]}" 89 | user_id_to_name[$user_id]=$key 90 | fi 91 | done < unifi_users_map.tf 92 | } 93 | 94 | load_user_group_mappings() { 95 | while IFS=' =' read -r key value; do 96 | if [[ $value =~ unifi_user_group\.id_(.+) ]]; then 97 | local user_group_id="${BASH_REMATCH[1]}" 98 | user_group_id_to_name[$user_group_id]=$key 99 | fi 100 | done < unifi_user_groups_map.tf 101 | } 102 | -------------------------------------------------------------------------------- /scripts/terraform_utils.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | escape_quotes() { 3 | local string="$1" 4 | echo "${string//\"/\\\"}" 5 | } 6 | 7 | sanitize_for_terraform() { 8 | local original_name="$1" 9 | local sanitized_name=$(echo "$original_name" | sed 's/[^a-zA-Z0-9_-]/_/g') 10 | echo "$sanitized_name" 11 | } 12 | 13 | # Helper function to conditionally echo a line 14 | c_echo() { 15 | local key="$1" 16 | local format="${2:-"%s"}" 17 | if [ -n "${args[$key]}" ]; then 18 | printf "$format\n" "${args[$key]}" 19 | fi 20 | } 21 | 22 | # Helper function to conditionally echo ap groups 23 | c_echo_ap_groups() { 24 | local ap_group_ids="$1" 25 | 26 | echo " ap_group_ids = [" 27 | 28 | IFS=',' read -ra AP_GROUP_IDS <<< "$ap_group_ids" 29 | for ap_group_id in "${AP_GROUP_IDS[@]}"; do 30 | echo " local.${ap_group_id_to_name[$ap_group_id]}.id," 31 | done 32 | 33 | echo " ]" 34 | } 35 | 36 | # Helper function to conditionally echo auth servers 37 | c_echo_auth_servers() { 38 | local auth_servers="$1" 39 | local sanitized_name="$2" 40 | 41 | IFS=',' read -ra SERVERS <<< "$auth_servers" 42 | for server in "${SERVERS[@]}"; do 43 | IFS=':' read -ra DETAILS <<< "$server" 44 | echo "" 45 | echo " auth_server {" 46 | echo " ip = \"${DETAILS[0]}\"" 47 | echo " port = ${DETAILS[1]}" 48 | echo " xsecret = var.unifi_radius_profile_${sanitized_name}_x_secret" 49 | echo " }" 50 | done 51 | } 52 | 53 | # Helper function to conditionally echo DHCP relay servers 54 | c_echo_dhcp_relay_servers() { 55 | local dhcp_relay_server_1="$1" 56 | local dhcp_relay_server_2="$2" 57 | local dhcp_relay_server_3="$3" 58 | local dhcp_relay_server_4="$4" 59 | local dhcp_relay_server_5="$5" 60 | 61 | local servers=("$dhcp_relay_server_1" "$dhcp_relay_server_2" "$dhcp_relay_server_3" "$dhcp_relay_server_4" "$dhcp_relay_server_5") 62 | local output="" 63 | 64 | for server in "${servers[@]}"; do 65 | if [ -n "$server" ]; then 66 | output+="\n \"$server\"," 67 | fi 68 | done 69 | 70 | if [ -n "$output" ]; then 71 | echo -n " dhcp_relay_servers = [" 72 | echo -e "$output" 73 | echo " ]" 74 | fi 75 | } 76 | 77 | # Helper function to conditionally echo DNS values 78 | c_echo_dns() { 79 | local dns_keys=("$1" "$2" "$3" "$4") 80 | local dns_values=() 81 | local dns_name=$5 82 | for key in "${dns_keys[@]}"; do 83 | [ -n "${args[$key]}" ] && dns_values+=("${args[$key]}") 84 | done 85 | 86 | if [ ${#dns_values[@]} -gt 0 ]; then 87 | echo " $dns_name = [" 88 | for dns in "${dns_values[@]}"; do 89 | echo " \"$dns\"," 90 | done 91 | echo " ]" 92 | fi 93 | } 94 | 95 | # Helper function to conditionally echo firewall group members 96 | c_echo_firewall_group_members() { 97 | local members="$1" 98 | 99 | echo " members = [" 100 | 101 | # Split the members and store them in an array 102 | IFS=',' read -ra MEMBERS <<< "$members" 103 | 104 | # Iterate over the sorted array and print each entry 105 | for member in "${MEMBERS[@]}"; do 106 | echo " \"$member\"," 107 | done 108 | 109 | echo " ]" 110 | } 111 | 112 | # Helper function to conditionally echo firewall groups 113 | c_echo_firewall_groups() { 114 | local firewall_group_ids="$1" 115 | local src_or_dst="$2" 116 | 117 | if [ -z "$firewall_group_ids" ]; then 118 | return 119 | fi 120 | 121 | echo " ${src_or_dst}_firewall_group_ids = [" 122 | 123 | IFS=',' read -ra FIREWALL_GROUP_IDS <<< "$firewall_group_ids" 124 | for firewall_group_id in "${FIREWALL_GROUP_IDS[@]}"; do 125 | echo " local.${firewall_group_id_to_name[$firewall_group_id]}.id," 126 | done 127 | 128 | echo " ]" 129 | } 130 | 131 | c_echo_firewall_rule_src_mac_address() { 132 | local mac_address="$1" 133 | 134 | if [ -z "$mac_address" ]; then 135 | return 136 | fi 137 | 138 | 139 | local resource_id="${mac_address//:/_}" 140 | # check to see if the resource_id is in the device_id_to_name array 141 | if [ -n "${device_id_to_name[$resource_id]}" ]; then 142 | resource_name=("local.${device_id_to_name[$resource_id]}.mac") 143 | elif [ -n "${user_id_to_name[$resource_id]}" ]; then 144 | resource_name=("local.${user_id_to_name[$resource_id]}.mac") 145 | else 146 | resource_name=("\"$mac_address\"") 147 | fi 148 | 149 | echo " src_mac = $resource_name" 150 | } 151 | 152 | c_echo_macs() { 153 | local device_macs="$1" 154 | 155 | echo " # device_macs = [" 156 | 157 | # Split the MAC addresses and store them in an array 158 | IFS=',' read -ra MACS <<< "$device_macs" 159 | 160 | # Create an array to hold the device resource names 161 | local device_resource_names=() 162 | 163 | # Populate the device_resource_names array 164 | for mac in "${MACS[@]}"; do 165 | local device_id="${mac//:/_}" 166 | device_resource_names+=("local.${device_id_to_name[$device_id]}.mac") 167 | done 168 | 169 | # Sort the array alphabetically and case-insensitively 170 | IFS=$'\n' sorted_device_resource_names=($(sort -f <<< "${device_resource_names[*]}")) 171 | unset IFS 172 | 173 | # Iterate over the sorted array and print each entry 174 | for device_resource_name in "${sorted_device_resource_names[@]}"; do 175 | echo " # $device_resource_name," 176 | done 177 | 178 | echo " # ]" 179 | } 180 | 181 | # Helper function to conditionally echo port override values 182 | c_echo_port_overrides() { 183 | local port_table_json="$1" 184 | 185 | echo "$port_table_json" | jq -c '.[]' | while read -r port; do 186 | local op_mode=$(echo "$port" | jq -r '.op_mode // empty') 187 | local portconf_id=$(echo "$port" | jq -r '.portconf_id // empty') 188 | if [ -n "$op_mode" ] || [ -n "$portconf_id" ]; then 189 | local port_idx=$(echo "$port" | jq -r '.port_idx') 190 | local port_name=$(echo "$port" | jq -r '.name // empty') 191 | local aggregate_num_ports=$(echo "$port" | jq -r '.aggregate_num_ports // empty') 192 | 193 | echo " port_override {" 194 | [ -n "$port_name" ] && echo " name = \"$port_name\"" 195 | echo " number = $port_idx" 196 | [ -n "$portconf_id" ] && echo " port_profile_id = local.${port_profile_id_to_name[$portconf_id]}.id" 197 | [ -n "$op_mode" ] && echo " op_mode = \"$op_mode\"" 198 | [ -n "$aggregate_num_ports" ] && echo " aggregate_num_ports = $aggregate_num_ports" 199 | echo " }" 200 | echo "" 201 | fi 202 | done 203 | } 204 | 205 | c_echo_port_security_mac_address() { 206 | local mac_addresses="$1" 207 | 208 | if [ -z "$mac_addresses" ]; then 209 | return 210 | fi 211 | 212 | echo " port_security_mac_address = [" 213 | 214 | # Split the MAC addresses and store them in an array 215 | IFS=',' read -ra MACS <<< "$mac_addresses" 216 | 217 | # Create an array to hold the resource names, or macs if no resource name is available 218 | local resource_names=() 219 | 220 | # Populate the resource_names array 221 | for mac in "${MACS[@]}"; do 222 | local resource_id="${mac//:/_}" 223 | # check to see if the resource_id is in the device_id_to_name array 224 | if [ -n "${device_id_to_name[$resource_id]}" ]; then 225 | resource_names+=("local.${device_id_to_name[$resource_id]}.mac") 226 | elif [ -n "${user_id_to_name[$resource_id]}" ]; then 227 | resource_names+=("local.${user_id_to_name[$resource_id]}.mac") 228 | else 229 | resource_names+=("\"$mac\"") 230 | fi 231 | done 232 | 233 | # Sort the array alphabetically and case-insensitively 234 | IFS=$'\n' sorted_resource_names=($(sort -f <<< "${resource_names[*]}")) 235 | unset IFS 236 | 237 | # Iterate over the sorted array and print each entry 238 | for resource_name in "${sorted_resource_names[@]}"; do 239 | echo " $resource_name," 240 | done 241 | 242 | echo " ]" 243 | } 244 | 245 | c_echo_ssh_keys() { 246 | local ssh_keys_json="$1" 247 | 248 | # Get the length of the JSON array 249 | local length=$(echo "$ssh_keys_json" | jq '. | length') 250 | 251 | # Iterate over each object in the JSON array 252 | for ((i=0;i<$length;i++)); do 253 | local ssh_key=$(echo "$ssh_keys_json" | jq ".[$i]") 254 | 255 | echo "" 256 | echo " ssh_key {" 257 | echo " name = \"$(echo "$ssh_key" | jq -r '.name')\"" 258 | echo " comment = \"$(echo "$ssh_key" | jq -r '.comment')\"" 259 | echo " type = \"$(echo "$ssh_key" | jq -r '.type')\"" 260 | echo " key = \"$(echo "$ssh_key" | jq -r '.key')\"" 261 | echo " }" 262 | done 263 | } 264 | 265 | c_echo_wlan_security_mac_address() { 266 | local mac_addresses="$1" 267 | 268 | if [ -z "$mac_addresses" ]; then 269 | return 270 | fi 271 | 272 | echo " mac_filter_list = [" 273 | 274 | # Split the MAC addresses and store them in an array 275 | IFS=',' read -ra MACS <<< "$mac_addresses" 276 | 277 | # Create an array to hold the resource names, or macs if no resource name is available 278 | local resource_names=() 279 | 280 | # Populate the resource_names array 281 | for mac in "${MACS[@]}"; do 282 | local resource_id="${mac//:/_}" 283 | # check to see if the resource_id is in the device_id_to_name array 284 | if [ -n "${device_id_to_name[$resource_id]}" ]; then 285 | resource_names+=("local.${device_id_to_name[$resource_id]}.mac") 286 | elif [ -n "${user_id_to_name[$resource_id]}" ]; then 287 | resource_names+=("local.${user_id_to_name[$resource_id]}.mac") 288 | else 289 | resource_names+=("\"$mac\"") 290 | fi 291 | done 292 | 293 | # Sort the array alphabetically and case-insensitively 294 | IFS=$'\n' sorted_resource_names=($(sort -f <<< "${resource_names[*]}")) 295 | unset IFS 296 | 297 | # Iterate over the sorted array and print each entry 298 | for resource_name in "${sorted_resource_names[@]}"; do 299 | echo " $resource_name," 300 | done 301 | 302 | echo " ]" 303 | } 304 | 305 | # Helper function to conditionally echo wlan schedules 306 | c_echo_wlan_schedules() { 307 | local wlan_schedules_json="$1" 308 | 309 | echo "$wlan_schedules_json" | jq -c '.[]' | while read -r schedule; do 310 | local duration_minutes=$(echo "$schedule" | jq -r '.duration_minutes // empty') 311 | local name=$(echo "$schedule" | jq -r '.name // empty') 312 | local start_days_of_week=$(echo "$schedule" | jq -r '.start_days_of_week[] // empty') 313 | local start_hour=$(echo "$schedule" | jq -r '.start_hour // empty') 314 | local start_minute=$(echo "$schedule" | jq -r '.start_minute // empty') 315 | 316 | for day in $start_days_of_week; do 317 | if [ -n "$duration_minutes" ] || [ -n "$name" ] || [ -n "$day" ] || [ -n "$start_hour" ] || [ -n "$start_minute" ]; then 318 | echo "" 319 | echo " schedule {" 320 | [ -n "$duration_minutes" ] && echo " duration = $duration_minutes" 321 | [ -n "$name" ] && echo " name = \"$name\"" 322 | [ -n "$day" ] && echo " day_of_week = \"$day\"" 323 | [ -n "$start_hour" ] && echo " start_hour = $start_hour" 324 | [ -n "$start_minute" ] && echo " start_minute = $start_minute" 325 | echo " }" 326 | fi 327 | done 328 | done 329 | } 330 | -------------------------------------------------------------------------------- /tests/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:14 2 | 3 | WORKDIR /app 4 | 5 | # Copy the server files 6 | COPY . . 7 | 8 | # Install express 9 | RUN npm install express 10 | 11 | # Install openssl and generate a self-signed certificate 12 | RUN apt-get update && \ 13 | apt-get install -y openssl && \ 14 | openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" 15 | 16 | # Start the server 17 | CMD ["node", "server.js"] -------------------------------------------------------------------------------- /tests/json/raw/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbycuenot/unifi-tf-generator/c747be85d2a2771a6179f24e2facfb0e3cf868c5/tests/json/raw/.keep -------------------------------------------------------------------------------- /tests/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const https = require('https'); 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const app = express(); 6 | 7 | // Define the files and their endpoints 8 | const files = [ 9 | { type: 'accounts.json', endpoint: 'proxy/network/v2/api/site/default/radius/users' }, 10 | { type: 'ap_groups.json', endpoint: 'proxy/network/v2/api/site/default/apgroups' }, 11 | { type: 'devices.json', endpoint: 'proxy/network/v2/api/site/default/device' }, 12 | { type: 'dynamic_dns.json', endpoint: 'proxy/network/api/s/default/rest/dynamicdns' }, 13 | { type: 'firewall_groups.json', endpoint: 'proxy/network/api/s/default/rest/firewallgroup' }, 14 | { type: 'firewall_rules.json', endpoint: 'proxy/network/api/s/default/rest/firewallrule' }, 15 | { type: 'networks.json', endpoint: 'proxy/network/v2/api/site/default/lan/enriched-configuration' }, 16 | { type: 'port_forward.json', endpoint: 'proxy/network/api/s/default/rest/portforward' }, 17 | { type: 'port_profiles.json', endpoint: 'proxy/network/api/s/default/rest/portconf' }, 18 | { type: 'radius_profiles.json', endpoint: 'proxy/network/api/s/default/rest/radiusprofile' }, 19 | { type: 'settings.json', endpoint: 'proxy/network/api/s/default/get/setting' }, 20 | { type: 'sites.json', endpoint: 'proxy/network/v2/api/info' }, 21 | { type: 'static_routes.json', endpoint: 'proxy/network/api/s/default/rest/routing' }, 22 | { type: 'user_groups.json', endpoint: 'proxy/network/api/s/default/rest/usergroup' }, 23 | { type: 'users.json', endpoint: 'proxy/network/api/s/default/list/user' }, 24 | { type: 'wlans.json', endpoint: 'proxy/network/api/s/default/rest/wlanconf' }, 25 | ]; 26 | 27 | // Serve each file at its endpoint 28 | files.forEach(file => { 29 | app.get(`/${file.endpoint}`, (req, res) => { 30 | res.sendFile(path.join(__dirname, 'json/raw', file.type)); 31 | }); 32 | }); 33 | 34 | // HTTPS server options 35 | const options = { 36 | key: fs.readFileSync('key.pem'), 37 | cert: fs.readFileSync('cert.pem') 38 | }; 39 | 40 | // Create an HTTPS service identical to the HTTP service 41 | https.createServer(options, app).listen(8080, () => { 42 | console.log('Mock API server running on HTTPS port 8080'); 43 | }); --------------------------------------------------------------------------------