diff --git a/Changelog.md b/Changelog.md new file mode 100644 index 0000000..c4a3fc3 --- /dev/null +++ b/Changelog.md @@ -0,0 +1,6 @@ +## 1.0.0 + +Initial Release + +Enhacements: +- Reference already preconfigured Hub \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2bb9ad2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/README.md b/README.md index 41ab382..4c82290 100644 --- a/README.md +++ b/README.md @@ -1,169 +1,226 @@ -# Network as Code for Unified Branch – `nac-branch` +# 🌐 Network as Code for Unified Branch – Branch as Code (`nac-branch`) -## πŸ“˜ Introduction +This repository delivers the **Network as Code for Unified Branch – Branch as Code** capability (Release 1, November 2025). +It automates provisioning of cloud-managed branch infrastructure β€” security appliances, switches, and Wi-Fi access points β€” using repeatable, version-controlled Terraform artifacts instead of manual dashboard configuration. -This initial release of **Unified Branch – Branch as Code** (referred to as **Release 1, Early Availability**) introduces the provisioning of branch network infrastructureβ€”**security appliances**, **switches**, and **Wi-Fi access points**β€”holistically using **Network as Code (NAC)** concepts, practices, and procedures. +All artifacts are aligned with **Cisco Validated Designs (CVDs)** and optimized for **greenfield deployments** (new branch networks configured as VPN spokes). +The provided code supports importing pre-configured organizations and hubs. -➑️ Check the [Unified Branch - Branch as Code Design Guide: Release 1 - Early Availability](docs/Readme.md) to learn more about the deployment model supported. +## πŸ“š More Information -➑️ The provided templates include configuration for both VPN Hubs and Branches (Spokes). Support for importing existing VPN Hub network configurations will be considered in future releases. +- [Unified Branch – Branch as Code Design Guide](docs/Readme.md) +- [Cisco Validated Design](https://www.cisco.com/c/en/us/solutions/design-zone/campus-branch.html) +- [Cisco Unified Branch Solution Brief](https://www.cisco.com/c/en/us/td/docs/solutions/CVD/Campus/Unifiedbranch_solution_brief_0813v4.html) +- [Branch as Code Documentation](https://netascode.cisco.com/docs/guides/branch/00_overview/) +- [Dashboard Device Initial Onboarding Flow and Best Practices](docs/Device_Onboarding_Flow.md) -➑️ See the [Cisco Unified Branch Solution Brief](https://www.cisco.com/c/en/us/td/docs/solutions/CVD/Campus/Unifiedbranch_solution_brief_0813v4.html) for a high-level overview of the Cisco Unified Branch solution. +## 🧰 Prerequisites ---- +You will need: -## 🧰 Requirements +1. A **Meraki API key** with configuration permissions. + *(Dashboard β†’ Organization β†’ Settings β†’ Dashboard API access)* + β†’ [API access documentation](https://documentation.meraki.com/General_Administration/Other_Topics/The_Cisco_Meraki_Dashboard_API#Enable_API_access) +2. Branch or Pod **variable data** (serial numbers, IP addressing schema, VLAN IDs, hostnames, etc.) +3. **Environment variables** for credentials and secrets. + Secrets may also be stored in a secret manager or Terraform variable file, depending on your policy. -To make use of this repository, you will need: +πŸ›‘οΈ [Learn more about variables in Branch as Code](https://netascode.cisco.com/docs/guides/branch/04_fundamentals-nac-bac/#understanding-variables-used-in-branch-as-code) -* βœ… A **Meraki API Key** -* βœ… **Hardware Serial Numbers** for the setup (as described in the [Network Design Section] (docs/Readme.md) -* βœ… Network Variables (e.g. **Network Name**, **Hostnames**, **IP Addressing Schema**, etc.) -* βœ… Enviromental Variables - the setup is configured with following enviromental variables: - MERAKI_API_KEY - v3_auth_pass - v3_priv_pass - local_status_page_password - snmp_passphrase - domain - org_name +## πŸ“ Repository Structure ---- - -## πŸ“ File Structure - -``` -nac-branch/ +```bash +nac-branch-terraform/ +β”œβ”€β”€ Changelog.md +β”œβ”€β”€ Readme.md +β”œβ”€β”€ main.tf +β”œβ”€β”€ schema.yaml πŸ”Ή β”œβ”€β”€ data/ β”œβ”€β”€ docs/ -β”œβ”€β”€ workspaces/ -β”œβ”€β”€ Readme.md -└── main.tf +β”œβ”€β”€ tests/ πŸ”Ή +β”œβ”€β”€ .rules/ πŸ”Ή +└── workspaces/ ``` +**Legend** +πŸ”Ή - The complete set of schema and tests is available through the **Services as Code** subscription. Custom rules that can be created and adapted for each customer. -### `data/` -Contains YAML configuration files used for [Network as Code](https://netascode.cisco.com). This includes organization-wide settings, templates, and variable definitions. +**File and folder overview:** -Contents: +- **Changelog.md** – release notes and change history +- **Readme.md** – this document +- **main.tf** – primary Terraform configuration defining NAC resources and modules +- **schema.yaml** – defines the YAML data model (sections, allowed keys, types, relationships) +- **data/** – YAML configuration files for [Branch as Code](https://netascode.cisco.com/docs/guides/branch/04_fundamentals-nac-bac/#data) +- **docs/** – reference diagrams and design documentation +- **tests/** – example automated tests for integration with CI/CD pipelines +- **rules/** – custom semantic rule definitions for policy enforcement +- **workspaces/** – environment-specific configurations for **branch template resolution** -``` -data/ -β”œβ”€β”€ org_global.nac.yaml -β”œβ”€β”€ pods_variables.nac.yaml -β”œβ”€β”€ templates-appliance-related.nac.yaml -β”œβ”€β”€ templates-inventory-related.nac.yaml -└── templates-network-related.nac.yaml -``` +**🧩 `data/` Folder Overview** -* **`org_global.nac.yaml`** - Defines organization-level settings such as login security, policy objects, SNMP settings, etc. +- **org_global.nac.yaml** – organization-level baseline: login security, policy objects, SNMP, etc. +- **pods_variables.nac.yaml** – branch-specific variables (name, hostnames, addressing, VLANs). + πŸ‘‰ *This is typically the only file you modify when deploying new branches.* +- **templates-*.nac.yaml** – modular configuration templates segmented by technology domain. Inline documentation is included. Some templates include predefined values for common use cases but are intended to be modified to reflect the customer’s specific environment. +> ⚠️ These are **Network as Code templates**, not Meraki configuration templates. They are **CVD-aligned** and designed to work with the [Network as Code Meraki Terraform](https://registry.terraform.io/modules/netascode/nac-meraki) modules. -* **`pods_variables.nac.yaml`** - Contains branch-specific variables like **Branch Name**, **Hostnames**, **IP addressing**, etc. +## πŸš€ Deployment Workflow -* **`templates-*-related.nac.yaml`** - Define reusable templates for **appliance**, **inventory**, and **network** components. +![Branch as Code High-Level Deployment Flow](docs/images/steps.png) - πŸ”Έ Wireless configuration is part of the **network-related** templates. +### 1. Fork the Repository ---- +Fork this repository into your organization’s workspace. +Avoid cloning directly from the upstream if you plan to customize. -### `docs/` +``` +# Replace with your GitHub username or org +git clone https://github.com//nac-branch.git +cd nac-branch +git remote add upstream https://github.com/netascode/nac-branch.git +git fetch upstream +``` -Stores reference diagrams and documentation such as Design Guide. +### 2. Export Required Environment Variables ---- +Export all required environment variables before running Terraform: -### `workspaces/` +```bash +# Device serial numbers +export Appliance=YOUR_APPLIANCE_SERIAL +export AP=YOUR_AP1_SERIAL +export AP2=YOUR_AP2_SERIAL +export Switch1=YOUR_SWITCH1_SERIAL +export Switch2=YOUR_SWITCH2_SERIAL + +# Organization identification +export org_name="Your Meraki Org Name" +export domain="YourDomainIdentifier" + +# Admin credentials +export org_admin="admin-username" +export org_admin_email="admin@example.com" + +# SNMPv3 credentials +export v3_auth_pass="CHANGE_ME_AUTH" +export v3_priv_pass="CHANGE_ME_PRIV" +export snmp_username="snmpUser" +export snmp_passphrase="CHANGE_ME_SNMP" + +# Local device access credentials +export local_status_page_username="statusUser" +export local_status_page_password="CHANGE_ME_STATUS" +export local_page_username="localUser" +export local_page_password="CHANGE_ME_LOCAL" + +# RADIUS secrets +export radius_accounting_server1_secret="CHANGE_ME_RADIUS_ACCT" +export radius_server1_secret="CHANGE_ME_RADIUS_AUTH" + +# Meraki API key (least privilege recommended) +export MERAKI_API_KEY="REPLACE_WITH_API_KEY" +``` -Contains environment-specific configuration files and is used for **branch template resolution**. +πŸ’‘ *Tip:* Use a `.env` file and source it (`source ./set_env_vars.sh`). +Ensure `.env` is excluded via `.gitignore`. You may also integrate a secrets manager. -The Terraform module invoked in this folder will: +### 3. 🧩 Configure Your Branch Variables -* Load templates and variable values from `/data` -* Merge them into a single file: `merged_configuration.nac.yaml` +Navigate to the `data/` folder and update: ---- +- `pods_variables.nac.yaml` – define branch/pod variables (serials, VLANs, etc.) -### `README.md` +A sample configuration is provided for reference. -This file. Provides an overview of the project and usage instructions. +### 4. 🧠 Render Templates ---- +Render configuration templates using your defined variables. +This step does **not** push any configuration to Meraki β€” it only builds the merged YAML that stays in memory. -### `main.tf` +> Note: the `workspaces/` directory is not a Terraform deployment workspace for Meraki resources; it is only used locally to render the merged YAML configuration. + +```bash +cd workspaces +terraform init +terraform apply +``` -Primary **Terraform configuration file**. It defines infrastructure resources and modules for the NAC deployment. +βœ… Output: `merged_configuration.nac.yaml` generated in `workspaces/`. ---- -## πŸš€ How to Use This Repository +### 5. πŸ” [Optional] Validate Configuration (`nac-validate`) +Validate the merged YAML before deployment to catch syntax or semantic issues early. +As part of the toolkit, we can use [nac-validate](https://github.com/netascode/nac-validate/blob/main/README.md) CLI tool to perform syntactic and semantic validation of YAML files. -### 1. Clone or Fork the Repository +Install (requires Python 3.10+): ```bash -git clone -cd nac-branch +pip install nac-validate ``` -### 2. Export Your Meraki API Key and other enviromental variables +Run validation: ```bash -export MERAKI_API_KEY=ABC1234 -export v3_auth_pass=ABC1234 -export v3_priv_pass=ABC1234 -export local_status_page_password=ABC1234 -export snmp_passphrase=ABC1234 -export domain=ABC1234 -export org_name=ABC1234 +nac-validate --non-strict ./workspaces/merged_configuration.nac.yaml ``` -### 3. Edit Your Configuration Files +> The `--non-strict` flag is used here since the sample schema omits certain keys. Remove it when validating against a complete schema. + +πŸ’‘ *VS Code users:* install the [YAML Language Support by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) extension for real-time validation. -Navigate to the `data/` folder and update the following: +πŸ‘‰ Learn more about [Configuration Validation.](https://netascode.cisco.com/docs/guides/concepts/validation/) -* `pods_variables.nac.yaml` – set your desired branch variables -* `org_global.nac.yaml` – set your org-level configuration -Sample configuration is included for reference. Make sure to use correct serial numbers. +### 6. πŸ—ΊοΈ Plan Terraform Deployment -### 4. Run Workspace Terraform +Generate the Terraform plan to preview intended changes: ```bash -cd workspaces +cd .. terraform init -terraform apply +terraform plan ``` -βœ… This generates a `merged_configuration.nac.yaml` in the `workspaces/` folder. +⚠️ The included configuration uses **local state**. +For team usage, configure a **remote backend** (e.g., Terraform Cloud, GitLab CI) with state locking to prevent concurrency issues. + -πŸ’‘ **Tip**: If you're using **VSCode**, install the [YAML Language Support by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) extension to catch YAML syntax errors early. +### 7. πŸš€ Apply Configuration -### 5. Run Root-Level Terraform +Apply the configuration to push changes to the Meraki Dashboard: ```bash -cd .. -terraform init -terraform plan +terraform apply ``` -⚠️ The included `main.tf` assumes **local tfstate storage**. If you are using **GitLab CI**, **Terraform Cloud**, or another backend, update the backend block accordingly. -### 6. Apply the Configuration +### 8. βœ… [Optional] Post-Deployment Tests (`nac-test`) + +Run post-change tests to confirm that the Meraki Dashboard matches the intended configuration. For this we make use of [nac-test](https://github.com/netascode/nac-test) CLI tool. + ```bash -terraform apply +pip install nac-test ``` -πŸŽ‰ This will push the configuration to the **Meraki Dashboard**. +Run: + +```bash +nac-test -d workspaces/merged_configuration.nac.yaml -t ./tests/templates -o ./tests/results +``` + +Passing `nac-test` confirms configuration integrity and reproducibility. +πŸ‘‰ Learn more about [Configuration Testing.](https://netascode.cisco.com/docs/guides/concepts/testing/) + +## πŸ’¬ Issues & Feedback ---- +We welcome your feedback! +If you encounter issues or have suggestions, please open a **Issue** in this repository. -Let us know if you encounter any issues or have suggestions to improve this workflow by raising PR/Issue within the repository. diff --git a/data/org_global.nac.yaml b/data/org_global.nac.yaml index 1a1f392..657d281 100644 --- a/data/org_global.nac.yaml +++ b/data/org_global.nac.yaml @@ -8,9 +8,9 @@ meraki: managed: false login_security: enforce_password_expiration: false # Boolean indicating whether users are forced to change their password every X number of days. - password_expiration_days: 30 # Number of days after which users will be forced to change their password. + password_expiration_days: 40 # Number of days after which users will be forced to change their password. enforce_different_passwords: true # Boolean indicating whether users, when setting a new password, are forced to choose a new password that is different from any past passwords. - num_different_passwords: 5 # Number of recent passwords that new password must be distinct from. + num_different_passwords: 3 # Number of recent passwords that new password must be distinct from. enforce_strong_passwords: true # Boolean indicating whether users will be forced to choose strong passwords for their accounts. Strong passwords are at least 8 characters that contain 3 of the following: number, uppercase letter, lowercase letter, and symbol enforce_account_lockout: true # Boolean indicating whether users' Dashboard accounts will be locked out after a specified number of consecutive failed login attempts. account_lockout_attempts: 5 # Number of consecutive failed login attempts after which users' accounts will be locked. @@ -22,33 +22,32 @@ meraki: api_authentication: enabled: false ranges: [] - ## snmp queries, traps are network level setting and will part of the network tempalte snmp: - v2c: true + v2c: false v3: true v3_auth_mode: MD5 v3_auth_pass: !env v3_auth_pass v3_priv_mode: AES128 v3_priv_pass: !env v3_priv_pass peer_ips: [] - policy_objects: - - name: test cidr - category: network - type: cidr - cidr: 10.0.0.0/24 - - name: test fqdn - category: network - type: fqdn - fqdn: www.cisco.com - policy_objects_groups: - - name: test cidr - category: NetworkObjectGroup - object_names: - - test cidr # This references the "test" policy object by name - - name: test fqdn - category: NetworkObjectGroup - object_names: - - test fqdn # This references the "test" policy object by name + # policy_objects: + # - name: test cidr + # category: network + # type: cidr + # cidr: 10.0.0.0/24 + # - name: test fqdn + # category: network + # type: fqdn + # fqdn: www.cisco.com + # policy_objects_groups: + # - name: test cidr + # category: NetworkObjectGroup + # object_names: + # - test cidr # This references the "test" policy object by name + # - name: test fqdn + # category: NetworkObjectGroup + # object_names: + # - test fqdn # This references the "test" policy object by name appliance: vpn_firewall_rules: rules: diff --git a/data/pods_variables.nac.yaml b/data/pods_variables.nac.yaml index 8503502..d726023 100644 --- a/data/pods_variables.nac.yaml +++ b/data/pods_variables.nac.yaml @@ -1,22 +1,27 @@ # The below code does the following: # -# This YAML file defines an organization named -# "CX Meraki Lab". It further defines/creates a -# network named "Unified Branch 1", representing a -# single small branch, under the organization: +# This YAML file defines an organization. +# It further defines/creates a network, +# representing a single small branch, under the organization: # # For the network created, it assigns values to variables # previously defined in templates within the following # YAML files: # -# - templates-appliance-related.nac.yaml -# - templates-appliance-related.nac.yaml +# - templates-appliance.nac.yaml +# - templates-inventory.nac.yaml # - templates-network-related.nac.yaml +# - templates-switch.nac.yaml +# - templates-wireless.nac.yaml +# - templates-wan-uplinks.nac.yaml +# - templates-wan-ts.nac.yaml +# - templates-wan-connectivity.nac.yaml +# - templates-internet-policies.nac.yaml # # Note that these templates are not related to templates # configured within the Cisco (formerly Meraki) dashboard. # -# Finally, for the network created, it assigns values +# Finally, for the network created, it assigns values # to the variables which were defined within the template # definitions in the YAML files. # @@ -26,231 +31,301 @@ meraki: administrator: name: admin organizations: - # + # # The below code does the following: # - # Defines / creates an organization named with - # hardcoded name of "CX Meraki Lab", along with - # a single branch network. + # Defines / creates an organization named with the name specified as + # an environmental variable, along with a single branch network + # hardcoded with the name Unified Branch 2. # - name: !env org_name managed: false networks: - # + # # The below code does the following: # - # Defines/creates the spoke network named "Unified Branch 1". + # Defines/creates the spoke network named "Unified Branch 2". + # + # ===================================================================== + # HOW TO USE THESE TEMPLATES + # ===================================================================== + # + # 1. SELECT A TEMPLATE: + # Choose the appropriate template from templates-xxx-related.nac.yaml + # based on your configuration needs. + # + # 2. REFERENCE THE TEMPLATE: + # In your network configuration, reference the template name: + # networks: + # - name: "Your-Network" + # templates: + # - name: wan_dhcp_dhcp # Or whichever template you need # - # Assigns the following templates from the associated YAML - # files as follows: + # 3. DEFINE VARIABLES: + # Create a pod with the necessary variables as shown in these examples + # Only include the variables required by your selected template # - # From templates-appliance-related.nac.yaml + # 4. APPLY CONFIGURATION: + # The terraform provider will merge the template with your variables + # to create the final configuration + # + # ===================================================================== + # VARIABLES AND TEMPLATES USED + # Assigns the following templates from the associated YAML files as follows: + # ===================================================================== + # + # From templates-appliance.nac.yaml # - app_settings # - app_spoke + # - app_ports # - app_vlans # - app_fw - # - app_ts # - app_content # - app_intrusion # - app_malware - # - tfsteering # - app_static_routes # - # From templates-inventory-related.nac.yaml - # - sb112 + # From templates_internet-policies.nac.yaml + # - internet_policies + # + # From templates-inventory.nac.yaml + # - small_branch_inventory # # From templates-network-related.nac.yaml - # - product_types - # - snmp - # - syslog - # - network_settings - # - nw_switch + # - nw_setup + # - nw_management + # - group_policies + # + # From templates-switch.nac.yaml + # - switch + # - switch_stacks + # + # From templates-wan-connectivity.nac.yaml + # - appl_comonitoring + # + # From templates-wan-ts.nac.yaml + # - app_ts + # + # From templates-wan-uplinks.nac.yaml + # - wan_dhcp_dhcp + # - wan_static_dhcp + # - wan_dhcp_static + # - wan_static_static + # - wan_ppoe_dhcp + # - wan_dhcp_ppoe + # - wan_ppoe_ppoe + # - wan_vlan_vlan + # - wan_vlan_static_dhcp + # - wan_ipv4_dhcp_dhcp + # - wan_ipv4_static_dhcp + # - wan_p2p_31 + # - wan_enterprise_vlan + # + # From templates-wireless.nac.yaml # - wireless # - # Assigns values to the variables defined within the - # associated templates as follows: - # - # From snmp - # - snmp_username - # - # From syslog - # - syslog_server - # - # From network_settings - # - local_status_page_username - # - # From sb112 - # - appliance-01 - # - appliance-01-serial - # - switch-01 - # - switch-01-serial - # - ap-01 - # - ap-01-serial - # - ap-02 - # - ap-02-serial - # - lat - # - lng - # - address - # - # From app_spoke & app_vlans - # - vlan10_subnet - # - vlan20_subnet - # - vlan30_subnet - # - # From app_vlans - # - vlan10_appliance_ip - # - vlan10_dhcp_start - # - vlan10_dhcp_end - # - vlan20_appliance_ip - # - vlan20_dhcp_start - # - vlan20_dhcp_end - # - vlan30_appliance_ip - # - vlan30_dhcp_start - # - vlan30_dhcp_end + # ------------------------------------------------------------------ + # Assigns the following variables from the associated templates as follows: + # + # From the templates within the wan-uplinks.nac.yaml file: + # + # APPLIANCE: + # - appliance_01_serial: String - Device serial number (format: QXXX-XXXX-XXXX) + # - appliance_01_name: String - Descriptive device name + # + # WAN1 CONFIGURATION: + # - wan1_enabled: Boolean - Enable/disable WAN1 (default: true) + # - wan1_vlan_enabled: Boolean - Enable VLAN tagging (default: false) + # - wan1_vlan_id: Integer - VLAN ID (1-4094) + # - wan1_pppoe_enabled: Boolean - Enable PPPoE (default: false) + # - wan1_pppoe_auth_enabled: Boolean - Enable PPPoE authentication (default: true) + # - wan1_pppoe_username: String - PPPoE username + # - wan1_pppoe_password: String - PPPoE password (5-64 characters) + # - wan1_ipv4_mode: String - "dynamic" or "static" + # - wan1_ipv4_address: String - IPv4 address with CIDR (e.g., "192.168.1.10/24") + # - wan1_ipv4_gateway: String - IPv4 gateway address + # - wan1_ipv4_dns: List - DNS servers (e.g., ["8.8.8.8", "8.8.4.4"]) + # - wan1_ipv6_address: String - IPv6 address with prefix (e.g., "2001:db8::10/64") + # - wan1_ipv6_gateway: String - IPv6 gateway address + # - wan1_ipv6_dns: List - IPv6 DNS servers + # + # WAN2 CONFIGURATION: + # - wan2_enabled: Boolean - Enable/disable WAN2 (default: true) + # - wan2_vlan_enabled: Boolean - Enable VLAN tagging (default: false) + # - wan2_vlan_id: Integer - VLAN ID (1-4094) + # - wan2_pppoe_enabled: Boolean - Enable PPPoE (default: false) + # - wan2_pppoe_auth_enabled: Boolean - Enable PPPoE authentication (default: true) + # - wan2_pppoe_username: String - PPPoE username + # - wan2_pppoe_password: String - PPPoE password (5-64 characters) + # - wan2_ipv4_mode: String - "dynamic" or "static" + # - wan2_ipv4_address: String - IPv4 address with CIDR + # - wan2_ipv4_gateway: String - IPv4 gateway address + # - wan2_ipv4_dns: List - DNS servers + # - wan2_ipv6_address: String - IPv6 address with prefix + # - wan2_ipv6_gateway: String - IPv6 gateway address + # - wan2_ipv6_dns: List - IPv6 DNS servers + # + # ------------------------------------------------------------------ + # + # From app_ts template: + # - wan_limit_up: Integer (min=0, max=1000000) - MX upstream per-client rate-limit (0 = unlimited) + # - wan_limit_down: Integer (min=0, max=1000000) - MX downstream per-client rate-limit (0 = unlimited) + # - wan1_limit_up: Integer (min=0, max=1000000) - MX WAN1 interface upstream rate-limit (0 = unlimited) + # - wan1_limit_down: Integer (min=0, max=1000000) - MX WAN1 interface downstream rate-limit (0 = unlimited) + # - wan2_limit_up: Integer (min=0, max=1000000) - MX WAN2 interface upstream rate-limit (0 = unlimited) + # - wan2_limit_down: Integer (min=0, max=1000000) - MX WAN2 interface downstream rate-limit (0 = unlimited) + # + # From app_spoke, app_vlans, & internet_policies templates: + # - vlan10_subnet: String - IPv4 address with CIDR of VLAN 10 (Date) + # - vlan20_subnet: String - IPv4 address with CIDR of VLAN 20 (Voice) + + # From app_spoke & app_vlans tempates: + # - vlan30_subnet: String - IPv4 address with CIDR of VLAN 30 (Iot) + # - vlan50_subnet: String - IPv4 address with CIDR of VLAN 50 (Guest) + # - vlan999_subnet: String - IPv4 address with CIDR ov VLAN 999 (Infra) + # + # From app_vlans template: + # - vlan10_appliance_ip: String - IPv4 address of MX for VLAN 10 (Data) + # - vlan20_appliance_ip: String - IPv4 address of MX for VLAN 20 (Voice) + # - vlan30_appliance_ip: String - IPv4 address of MX for VLAN 30 (Iot) + # - vlan50_appliance_ip: String - IPv4 address of MX for VLAN 50 (Guest) + # - vlan999_appliance_ip: String - IPv4 address of MX for VLAN 999 (Infra) + # - corp_dhcp_server1: String - IPv4 address of remote DHCP Server 1 + # - corp_dhcp_server2: String - IPv4 address of remote DHCP Server 2 + # + # From app_static_routes template: + # - static_route1_subnet: String - IPv4 address with CIDR + # - static_route1_gw: String - IPv4 gateway address + # - static_route2_subnet: String - IPv4 address with CIDR + # - static_route2_gw: String - IPv4 gateway address + # + # From small_branch_inventory template: + # - appliance_01_name: String - Descriptive device name for MX + # - appliance_01_serial: String - Device serial number for MX + # - lat: String - Latitude coordinates for devices in the network + # - lng: String - Longitude coordinates for devices in the network + # - address: String - Location address for devices in the network + # - access_switch_01_name: String - Descriptive device name for first switch + # - access_switch_01_serial: String - Device serial number for first switch + # - access_switch_02_name: String - Descriptive device name for second switch + # - access_switch_02_serial: String - Device serial number for second switch + # - ap_01_name: String - Descriptive device name for first AP + # - ap_01_serial: String - Device serial number for first AP + # - ap_02_name: String - Descriptive device name for second AP + # - ap_02_serial: String - Device serial number for second AP + # + # From nw_setup template: + # - time_zone: String - Time Zone (ex. America/Los_Angeles) + # - network_notes: String + # + # From nw_management template: + # - syslog_server: String - IPv4 address of remote syslog server + # - syslog_port: Integer (min=1, max=65535) - Syslog server port + # - netflow_server: String - IPv4 address of remote NetFlow server + # - netflow_port: Integer (min=1, max=65535) - NetFlow server port + # + # From group_policies template: + # - data_vlan_group_policy: String - Group policy name for device assignment to VLAN 10 (Data) + # - voice_vlan_group_policy: String - Group policy name for device assignment to VLAN 20 (Voice) + # - iot_vlan_group_policy: String - Group policy name for device assignment to VLAN 30 (Iot) + # + # From switch and wireless templates: + # - radius_accounting_server1_host: String - IPv4 address of the first RADIUS accounting server + # - radius_accounting_server1_port: Integer (min=1, max=65535) - First RADIUS accounting server port + # - radius_server1_host: String - IPv4 address of the first RADIUS server + # - radius_server1_port: Integer (min=1, max=65535) - First RADIUS server port + # + # From switch template: + # - switch_mtu_size: Integer (min=1, max=9578) - MTU size of the switch + # - access_stack_01_name: String - Descriptive name for the switch stack + # - access_switch_01_name String - Descriptive name for first switch in the stack + # - access_switch_02_name String - Descriptive name for second switch in the stack # # From wireless - # - ap-tag1 - # - ap-tag1-vlan-id - # - ap-tag2 - # - ap-tag2-vlan-id - # - default-vlan-id-data - # - default-vlan-id-voice - # - data_ssid_schedules_enabled - # - voice_ssid_schedules_enabled - # - guest_ssid_schedules_enabled - # - # From app_static_routes - # - static_route1_subnet - # - static_route1_gw - # - static_route2_subnet - # - static_route2_gw - # - - name: Unified Branch 1 - templates: [product_types, snmp, syslog, network_settings, nw_switch, sb112, wireless, app_settings, app_spoke, app_vlans, app_fw, app_ts,app_content, app_intrusion, app_mal, tfsteering, app_static_routes, appl_comonitoring] + # - data_wireless_ssid_name: String - Descriptive name for the SSID corresponding to employee traffic + # - guest_wireless_ssid_name: String - Descriptive name for the SSID corresponding to guest traffic + # - data_ssid_schedules_enabled: Boolean - Enable Data SSID unavailability schedule + # - guest_ssid_schedules_enabled: Boolean - Enable Guest SSID unavailability schedule + # - guest_wireless_client_bw_down: Integer (min=0, max=1000000) - Guest SSID upstream per-client rate-limit (0 = unlimited) + # - guest_wireless_client_bw_up: Integer (min=0, max=1000000) - Guest SSID downstream per-client rate-limit (0 = unlimited) + # - guest_wireless_ssid_bw_down: Integer (min=0, max=1000000) - Guest SSID upstream rate-limit (0 = unlimited) + # - guest_wireless_ssid_bw_up: Integer (min=0, max=1000000) - Guest SSID upstream rate-limit (0 = unlimited) + # - guest_ssid_welcome_message: String - Message displayed in Guest SSID pass-through splash page + # + - name: Unified Branch 2 + templates: [nw_setup, nw_management, app_ports, switch, small_branch_inventory, wan_dhcp_dhcp, wireless, app_settings, app_spoke, app_vlans, app_fw, app_ts,app_content, app_intrusion, app_mal, internet_policies, app_static_routes, group_policies] variables: - snmp_username: user1 syslog_server: 3.4.5.6 - local_status_page_username: admin - appliance-01: Branch1-appliance-01 - switch-01: Branch1-Cat9300-01 - ap-01: Branch1-ap-01 - ap-02: Branch1-ap-02 - appliance-01-serial: ABCD-EFGH-IJKL - switch-01-serial: ABCD-EFGH-IJKL - ap-01-serial: ABCD-EFGH-IJKL - ap-02-serial: ABCD-EFGH-IJKL + syslog_port: 514 + # netflow_server: 4.5.6.7 + # netflow_port: 2055 + appliance_01_name: Branch2-appliance-01 + access_switch_01_name: Branch2-Cat9300-01 + access_switch_02_name: Branch2-Cat9300-02 + access_stack_01_name: Access-Stack-01 + ap_01_name: Branch2-ap-01 + ap_02_name: Branch2-ap-02 + appliance_01_serial: !env Appliance + access_switch_01_serial: !env Switch1 + access_switch_02_serial: !env Switch2 + ap_01_serial: !env AP + ap_02_serial: !env AP2 lat: 37.41809510000001 lng: -122.098531 + wan1_enabled: true + wan2_enabled: true address: Wake Forest, N.C. - vlan10_subnet: 10.1.10.0/24 - vlan10_appliance_ip: 10.1.10.1 - vlan10_dhcp_start: 10.1.10.40 - vlan10_dhcp_end: 10.1.10.50 - vlan20_subnet: 10.1.20.0/24 - vlan20_appliance_ip: 10.1.20.1 - vlan20_dhcp_start: 10.1.20.40 - vlan20_dhcp_end: 10.1.20.50 - vlan30_subnet: 10.1.30.0/24 - vlan30_appliance_ip: 10.1.30.1 - vlan30_dhcp_start: 10.1.30.40 - vlan30_dhcp_end: 10.1.30.50 + vlan10_subnet: 10.2.10.0/24 + vlan10_appliance_ip: 10.2.10.1 + vlan20_subnet: 10.2.20.0/24 + vlan20_appliance_ip: 10.2.20.1 + vlan30_subnet: 10.2.30.0/24 + vlan30_appliance_ip: 10.2.30.1 + vlan50_subnet: 10.2.50.0/24 + vlan50_appliance_ip: 10.2.50.1 + vlan999_appliance_ip: 10.2.255.1 + vlan999_subnet: 10.2.255.0/24 hub_network_name: Unified Hub - ap-tag1: ap-group1 - ap-tag2: ap-group2 - default-vlan-id-data: 10 - default-vlan-id-voice: 20 - ap-tag1-vlan-id: 11 - ap-tag2-vlan-id: 12 + data_wireless_ssid_name: Data + data_vlan_group_policy: Employees + voice_vlan_group_policy: Voice + iot_vlan_group_policy: Iot data_ssid_schedules_enabled: true - voice_ssid_schedules_enabled: true + guest_wireless_ssid_name: Guest + guest_wireless_client_bw_down: 0 + guest_wireless_client_bw_up: 0 + guest_wireless_ssid_bw_down: 0 + guest_wireless_ssid_bw_up: 0 guest_ssid_schedules_enabled: true + guest_ssid_welcome_message: Unauthorized access is prohibited. + radius_accounting_server1_host: 172.16.2.1 + radius_accounting_server1_port: 1813 + radius_accounting_server2_host: 172.16.2.2 + radius_server1_host: 172.16.2.1 + radius_server1_port: 1812 + radius_server2_host: 172.16.2.2 static_route1_subnet: 10.101.10.0/24 - static_route1_gw: 10.1.10.2 + static_route1_gw: 10.2.10.2 # static_route1_enabled: true static_route2_subnet: 10.101.20.0/24 - static_route2_gw: 10.1.20.2 + static_route2_gw: 10.2.20.2 # static_route2_enabled: true splash_reply_to_email_address: example@example.com - # - # The below code does the following: - # - # Defines/creates the hub network named "Unified Hub". - # - # Assigns the following templates from the associated YAML - # files as follows: - # - # From templates-appliance-related.nac.yaml - # - app_settings - # - app_hub - # - app_vlans - # - # From templates-network-related.nac.yaml - # - product_types - # - snmp - # - syslog - # - network_settings - # - # Assigns values to the variables defined within the - # associated templates as follows: - # - # From snmp - # - snmp_username - # - # From syslog - # - syslog_server - # - # From network_settings - # - local_status_page_username - # - # From hub (found in templates-inventory-related.nac.yaml) - # - appliance-01-serial - # - appliance-01 - # - lat - # - lng - # - address - # - # From app_hub & app_vlans - # - vlan10_subnet - # - vlan20_subnet - # - vlan30_subnet - # - # From app_vlans - # - vlan10_appliance_ip - # - vlan10_dhcp_start - # - vlan10_dhcp_end - # - vlan20_appliance_ip - # - vlan20_dhcp_start - # - vlan20_dhcp_end - # - vlan30_appliance_ip - # - vlan30_dhcp_start - # - vlan30_dhcp_end - # + switch_mtu_size: 9176 + time_zone: America/New_York + network_notes: This is a small branch network created via Netascode. + wan_limit_down: 0 + wan_limit_up: 0 + wan1_limit_down: 400000 + wan1_limit_up: 400000 + wan2_limit_down: 500000 + wan2_limit_up: 500000 + # + # The below code does the following: + # + # Defines/creates the hub network named "Unified Hub". + # + # Managed is set to false - this makes the module aware of it for lookups without trying to create it. + # - name: Unified Hub - templates: [product_types, hub, snmp, syslog, app_settings, network_settings, app_hub, app_vlans] - variables: - snmp_username: user1 - syslog_server: 3.4.5.6 - local_status_page_username: admin - appliance-01-serial: ABCD-EFGH-IJKL - appliance-01: Hub - vlan10_subnet: 10.1.1.0/24 - vlan10_appliance_ip: 10.1.1.1 - vlan10_dhcp_start: 10.1.1.40 - vlan10_dhcp_end: 10.1.1.50 - vlan20_subnet: 10.1.2.0/24 - vlan20_appliance_ip: 10.1.2.1 - vlan20_dhcp_start: 10.1.2.40 - vlan20_dhcp_end: 10.1.2.50 - vlan30_subnet: 10.1.3.0/24 - vlan30_appliance_ip: 10.1.3.1 - vlan30_dhcp_start: 10.1.3.40 - vlan30_dhcp_end: 10.1.3.50 - ap-tag1: ap-group1 - ap-tag2: ap-group2 - default-vlan-id-data: 10 - default-vlan-id-voice: 20 - ap-tag1-vlan-id: 11 - ap-tag2-vlan-id: 12 - lat: 37.41809510000001 - lng: -122.098531 - address: Cary, N.C. + managed: false diff --git a/data/templates-appliance.nac.yaml b/data/templates-appliance.nac.yaml new file mode 100644 index 0000000..ec41e21 --- /dev/null +++ b/data/templates-appliance.nac.yaml @@ -0,0 +1,410 @@ +# The below code does the following: +# +# This YAML file defines templates which provide the following set of +# Unified Branch services applicable to the secure router (security appliance): +# +# - Appliance settings - defined in the app_settings template +# - AutoVPN configuration (spoke) - defined in the app_spoke template +# - Hub settings - defined in the app_hub template +# - Port configuration - defined in the app_ports template +# - VLAN configuration - defined in the app_vlans template +# - Firewall configuration - defined in the app_fw template +# - Content filtering - defined in the app_content template +# - Intrusion prevention - defined in the app_intrusion template +# - Malware prevention - defined in the app_mal template +# - Static route configuration - defined in the app_static_routes template +# +# Note that these templates are not related to templates +# configured within the Cisco (formerly Meraki) dashboard. +# +meraki: + template: + networks: + # + # The below code does the following: + # + # Security appliance settings configuration template for branch networks. + # + # Sets the security appliance for routed mode operation, tracks clients by + # MAC address, and enables dynamic DNS for accessing the security appliance. + # + - name: app_settings + appliance: + settings: + client_tracking_method: "MAC address" + deployment_mode: routed + dynamic_dns: + prefix: "my-network" + enabled: true + # + # The below code does the following: + # + # Security appliance AutoVPN configuration template for the hub network. + # + # Configures the network to which the template is applied as a hub and advertises the + # VLAN 10 (Data), VLAN 20 (Voice), VLAN 30 (Iot), and VLAN 999 (Infra) subnets across + # the VPN to the cloud. IP address and subnets for VLANs are specified as variables + # which are defined in the pods_variables.nac.yaml file. + # + # Note this template may be unused as the hub name is imported in the current release. + # + - name: app_hub + appliance: + vpn_site_to_site_vpn: + mode: hub + subnets: + - local_subnet: ${vlan10_subnet} + use_vpn: true + - local_subnet: ${vlan20_subnet} + use_vpn: true + - local_subnet: ${vlan30_subnet} + use_vpn: true + - local_subnet: ${vlan999_subnet} + use_vpn: true + # + # The below code does the following: + # + # Security appliance AutoVPN configuration template for branch networks. + # + # Configures the branch network to which the template is applied as a spoke with + # a single hub. The name of the hub, which is specified as a variable, is also + # the default route for all spoke networks. + # + # Advertises the VLAN 10 (data), VLAN 20 (voice), VLAN 30 (iot), and VLAN 999 + # (infra) subnets across the VPN to the cloud. VLAN 50 (Guest) is not advertised + # across the VPN. The default VLAN (VLAN 1) is automatically configured by the + # MX and does not appear within the YAML below. + # + # IP address and subnets for VLANs are specified as variables which are defined + # in the pods_variables.nac.yaml file. + # + - name: app_spoke + appliance: + vpn_site_to_site_vpn: + mode: spoke + hubs: + - hub_network_name: ${hub_network_name} + use_default_route: true + subnets: + - local_subnet: ${vlan10_subnet} + use_vpn: true + - local_subnet: ${vlan20_subnet} + use_vpn: true + - local_subnet: ${vlan30_subnet} + use_vpn: true + - local_subnet: ${vlan50_subnet} + use_vpn: false + - local_subnet: ${vlan999_subnet} + use_vpn: true + # + # The below code does the following: + # + # Security appliance LAN port configuration template. + # Configures and enables LAN ports 5, 6, 13, & 14 as trunks to the branch switch. + # These ports are specific to the MX85 secure router. For MX95/105 secure routers + # the SFP LAN ports are ports 9 & 10. If you are using an MX67 with two WAN ports, + # the LAN port range is ports 3 - 5. If you are using an MX68 the LAN port range + # is ports 3 - 12, with ports 11 & 12 supporting POE+. Depending upon the secure + # router model you are deploying, you will need to change the port_id_ranges you wish + # to enable and configure as trunks. + # + # Allows VLANs 1, 10, 20, 30, 50, and 999. Native VLAN 1 on the trunk serves to allow + # devices downstream of the security appliance to initially get IP addresses and + # communicate with the Cisco (formerly Meraki) cloud. Upon receiving their configurations, + # devices downstream of the secure router are configured with VLAN 999 (infra) as their + # manangement VLAN. VLANs 10, 20, 30, and 50 correspond to Data, Voice, IoT, and Guest VLANs. + # + - name: app_ports + appliance: + ports: + - port_id_ranges: + - from: 5 + to: 6 + - from: 13 + to: 14 + enabled: true + type: trunk + allowed_vlans: "1,10,20,30,50,999" + vlan: 1 + # + # The below code does the following: + # + # Security appliance VLAN configuration template. + # + # This template hardcodes the configuration for 5 VLANs - VLAN 10 (Data) + # VLAN 20 (Voice), VLAN 30 (IoT), VLAN 50 (Guest), and VLAN 999 (infra). + # For each VLAN, the IPv4 subnet and address of the security appliance + # are defined as variables. The VLAN names are hardcoded. + # IPv6 is disabled for each VLAN. + # + # For VLANs 10 (Data), 20 (Voice), and 30 (IoT) the configuration specifies + # relaying DHCP back to centralized corporate DHCP servers, configured as + # variables. + # + # For VLANs 30 (Guest), and 999 (Infra), a separate DHCP server instance is + # configured within each VLAN to assign IP addresses to client devices for the VLAN, + # with the following example configuration: + # + # - Mandatory IP address assignment for VLAN 30 (Guest) only + # - DNS server specified as openDNS + # - No DHCP boot options specified + # - DHCP lease time of 1 day + # - Fixed IP address assignments for VLAN 999 (Infra) corresponding to the + # management interfaces of the switch and AP. This is to ensure these + # devices have a consistent IP address for sourcing syslog, NetFlow, snmp, etc. + # + - name: app_vlans + appliance: + vlans: + - vlan_id: 10 + name: "Data" + subnet: ${vlan10_subnet} + appliance_ip: ${vlan10_appliance_ip} + ipv6: + enabled: false + dhcp_handling: "Run a DHCP server" + # dhcp_handling: "Relay DHCP to another server" + # dhcp_relay_server_ips: + # - ${corp_dhcp_server1} + # - ${corp_dhcp_server2} + mandatory_dhcp: false + - vlan_id: 20 + name: "Voice" + subnet: ${vlan20_subnet} + appliance_ip: ${vlan20_appliance_ip} + ipv6: + enabled: false + dhcp_handling: "Run a DHCP server" + # dhcp_handling: "Relay DHCP to another server" + # dhcp_relay_server_ips: + # - ${corp_dhcp_server1} + # - ${corp_dhcp_server2} + mandatory_dhcp: false + - vlan_id: 30 + name: "Iot" + subnet: ${vlan30_subnet} + appliance_ip: ${vlan30_appliance_ip} + ipv6: + enabled: false + dhcp_handling: "Run a DHCP server" + # dhcp_handling: "Relay DHCP to another server" + # dhcp_relay_server_ips: + # - ${corp_dhcp_server1} + # - ${corp_dhcp_server2} + mandatory_dhcp: false + - vlan_id: 50 + name: "Guest" + subnet: ${vlan50_subnet} + appliance_ip: ${vlan50_appliance_ip} + ipv6: + enabled: false + dns_nameservers: opendns + dhcp_handling: "Run a DHCP server" + dhcp_lease_time: "1 day" + dhcp_boot_options: false + mandatory_dhcp: true + - vlan_id: 999 + name: "Infra" + subnet: ${vlan999_subnet} + appliance_ip: ${vlan999_appliance_ip} + ipv6: + enabled: false + dns_nameservers: opendns + dhcp_handling: "Run a DHCP server" + dhcp_lease_time: "1 day" + dhcp_boot_options: false + mandatory_dhcp: false + # fixed_ip_assignments: + # ip: 10.250.1.11 + # name: 6c:c3:b2:7e:ae:0a + # + # The below code does the following: + # + # Security appliance L3 & L7 firewall configuration template. + # + # This template hardcodes the following firewall rules on the + # security appliance. The rules are configured as examples only. + # Network administrators should configure firewall rule based on + # the security policy of their individual organizations. + # + # - Outbound Layer 3 firewall rules: + # - Deny UDP traffic from any source IP address with source port 1433 + # to any destination IP address with destination port 1433. + # - Deny TCP traffic from any source IP address with source port 22 + # to any destination IP address with destination port 22. + # (Note, this is technially not SSH traffic since SSH uses an ephemeral + # source TCP port.) + # + # - Services available / blocked from the outside interface of the security + # appliance + # - ICMP services blocked + # - Web services restricted to being reachable from IP addresses "2.2.2.2 and + # 3.3.3.3" only + # - SNMP services allowed + # + # - Outbound Layer 7 firewall rules: + # - Deny application category "meraki:layer7/category/27" + # (Note that application categories must be specified by ID currently. + # Work to translate the IDs into user-friendly names is ongoing.) + # - Deny application name "meraki:layer7/application/106" + # (Note that applications must be specified by ID currently. Work to + # translate the IDs into user-friengly names is ongoing.) + # - Deny traffic from host specified by name "abc.com" + # - Deny traffic from any host to port "161" + # - Deny traffic to remote IP address "192.168.0.1" + # - Deny traffic to remote IP address "192.168.0.2" port "80" + # + - name: app_fw + appliance: + firewall: + l3_firewall_rules: + rules: + - comment: "Block Bad Traffic" + policy: deny + protocol: udp + source_port: 1433 + source_cidr: Any + destination_port: 1433 + destination_cidr: Any + - comment: "Block SSH" + policy: deny + protocol: tcp + source_port: 22 + source_cidr: Any + destination_port: 22 + destination_cidr: Any + firewalled_services: + - service_name: "ICMP" + access: "blocked" + - service_name: "web" + access: "restricted" + allowed_ips: + - "2.2.2.2" + - "3.3.3.3" + - service_name: "SNMP" + access: "unrestricted" + l7_firewall_rules: + - policy: deny + type: applicationCategory + value: "meraki:layer7/category/27" + - policy: deny + type: application + value: "meraki:layer7/application/106" + - policy: deny + type: host + value: "abc.com" + - policy: deny + type: port + value: "161" + - policy: deny + type: ipRange + value: "192.168.0.1" + - policy: deny + type: ipRange + value: "192.168.0.2:80" + # + # + # The below code does the following: + # + # Security appliance content filtering configuration template. + # + # The following template enables content filtering on the security + # appliance. List entries under allowed_url_patterns, blocked_url_patterns, + # and blocked_url_categories are examples only. Network administrators + # should configure content filtering rules based on the security policy and + # requirements of their individual organizations. + + # - List entries under allowed_url_patterns are specific URLs excluded from + # content filtering and therefore allowed. + # - List entries under blocked_url_patterns are automatically blocked. + # - List entries under blocked_url_categories consist of categories of URLs + # automatically blocked. (Note that URL category must be specified by ID + # currently. Work to translate the IDs into user-friendly names is ongoing.) + # + - name: app_content + appliance: + content_filtering: + allowed_url_patterns: + - "www.cisco.com" + - "*.meraki.com" + blocked_url_patterns: + - www.porn.com + - www.socialmedia.net + - www.example.badsitehere.com + blocked_url_categories: + - "meraki:contentFiltering/category/C6" + - "meraki:contentFiltering/category/C69" + - "meraki:contentFiltering/category/C55" + - "meraki:contentFiltering/category/C47" + - "meraki:contentFiltering/category/C84" + - "meraki:contentFiltering/category/C22" + - "meraki:contentFiltering/category/T01" + - "meraki:contentFiltering/category/T03" + - "meraki:contentFiltering/category/T14" + - "meraki:contentFiltering/category/T05" + - "meraki:contentFiltering/category/T02" + - "meraki:contentFiltering/category/C36" + url_category_list_size: fullList + # + # The below code does the following: + # + # Security appliance intrusion prevention configuration template. + # + # The following template enables intrusion prevention on the security + # appliance and hardcodes a balanced ruleset, which is a compromise between + # performance and security. Note that no exclusion rules have been configured. + # + - name: app_intrusion + appliance: + security_intrusion: + mode: prevention + ids_rulesets: balanced + # + # The below code does the following: + # + # Security appliance advanced malware prevention configuration template. + # + # The following template enables advanced malware protection on the + # security appliance. The hardcoded allowed_urls list ("www.cisco.com + # and *.meraki.com") are excluded from malware scanning. The hardcoded + # allowed_files list contains files previously seen across the organization + # which were blocked. Currently these are specified as SHA-256 hash strings. + # Work to translate the hash strings into user-friendly names is ongoing. + # + - name: app_mal + appliance: + security_malware: + mode: enabled + allowed_urls: + - url: "www.cisco.com" + comment: "Cisco" + - url: "*.meraki.com" + comment: "Meraki" + allowed_files: + - sha256: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" + comment: "Test File 1" + - sha256: "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890" + comment: "Test File 2" + # + # The below code does the following: + # + # Security appliance static routing configuration template. + # + # Static routes are used to reach subnets that are behind a layer 3 switch + # or otherwise not directly connected to or configured on the WAN appliance. + # For this release it is assumed the switch attached to the secure router + # (security appliance) is a L2 switch. Hence there should be no static + # routes to be defined. This section is therefore purely for example. + # + # This template demonstrates how to configure two static routes in which + # the subnet/mask and gateway for each is defined as a variable. + # + - name: app_static_routes + appliance: + static_routes: + - name: Static Route 01 + subnet: ${static_route1_subnet} + gateway_ip: ${static_route1_gw} + - name: Static Route 02 + subnet: ${static_route2_subnet} + gateway_ip: ${static_route2_gw} diff --git a/data/templates-internet-policies.nac.yaml b/data/templates-internet-policies.nac.yaml new file mode 100644 index 0000000..e79d79e --- /dev/null +++ b/data/templates-internet-policies.nac.yaml @@ -0,0 +1,120 @@ +# =============================================================== +# SD-WAN INTERNET TRAFFIC POLICIES +# =============================================================== +# +# The below code does the following: +# +# Security appliance traffic steering configuration template. +# +# This template provides an example of how to configure SD-WAN policies for +# Internet traffic (SD-Internet). The SD-Internet function is to steer customer +# traffic to SaaS or public cloud-based applications (outside of any transport +# tunnel) over the best-performing WAN connection at the time the traffic is forwarded. +# The policies are configured as examples only. Network administrators should configure +# Internet traffic-steering policies based on the requirements the of their individual +# organizations. +# +# Below are example policies for managing internet traffic. +# Please customize these to fit your specific requirements. +# +# !!! NOTE !!! +# +# Don't use wan_traffic_uplink_preferences (see templates-wan-ts.nac.yaml) +# together with networks[].appliance.sdwan_internet_policies. +# +# The latter is a strictly better version of the former, though it requires a license. +# The 2 resources share the same set of data in the API, +# and preferences/policies with e.g. matching source get overridden by the resource created last. +# Also, deletion of any of the resources deletes the data from the other as well. +# Examples below. Adjust as needed. +# +# Network as Code Documentation: +# https://netascode.cisco.com/docs/data_models/meraki/networks_appliance/sdwan_internet_policies/ +# +meraki: + template: + networks: + - name: internet_policies + appliance: + sdwan_internet_policies: + # Policy 1 implements custom traffic classification by matching TCP protocol traffic + # originating from vlan10 subnet + - name: policy 1 + traffic_filters: + - type: custom + value: + protocol: "tcp" + source: + port: any + cidr: ${vlan10_subnet} + destination: + port: "any" + cidr: "any" + preferred_uplink: "wan1" + fail_over_criterion: "poorPerformance" + performance_class: + type: builtin + builtin_performance_class_name: VoIP + # Policy 1 implements custom traffic classification by matching TCP protocol traffic + # originating from vlan20 subnet + - name: policy 2 + traffic_filters: + - type: custom + value: + protocol: "tcp" + source: + port: any + cidr: ${vlan20_subnet} + destination: + port: "any" + cidr: "any" + preferred_uplink: "wan1" + fail_over_criterion: "poorPerformance" + performance_class: + type: builtin + builtin_performance_class_name: VoIP + # policy 3 leverages majorApplication filtering to identify and prioritize + # Office 365 Suite traffic using UDP protocol + - name: policy 3 + traffic_filters: + - type: majorApplication + value: + protocol: udp + source: + port: any + cidr: any + destination: + applications: + - id: "meraki:layer7/application/1" + name: "Office 365 Suite" + type: "major" + preferred_uplink: "wan1" + fail_over_criterion: "poorPerformance" + performance_class: + type: custom + custom_performance_class_name: Radius + # β€œpolicy 3” employs granular application-based filtering targeting specific email services + # (Rackspace Hosted Exchange and Hotmail) from the 192.168.20.0/24 subnet + # using NBAR (Network-Based Application Recognition) technology + # for precise application identification and traffic steering + # with builtin VoIP performance class treatment. + - name: policy 4 + traffic_filters: + - type: application + value: + protocol: "any" + source: + cidr: ${vlan10_subnet} + destination: + applications: + - id: "meraki:layer7/application/7" + name: "Rackspace Hosted Exchange" + type: "nbar" + - id: "meraki:layer7/application/39" + name: "Hotmail" + type: "nbar" + preferred_uplink: "wan1" + fail_over_criterion: "poorPerformance" + performance_class: + type: builtin + builtin_performance_class_name: VoIP diff --git a/data/templates-inventory.nac.yaml b/data/templates-inventory.nac.yaml new file mode 100644 index 0000000..cc9609b --- /dev/null +++ b/data/templates-inventory.nac.yaml @@ -0,0 +1,226 @@ +# The below code does the following: +# +# This YAML file defines the following inventory related template: +# +# - Small Branch Inventory (small_branch_inventory) +# - small_branch_inventory template defines 1 Secure Router +# (Security Appliance), 1 Switch Stack with 2 Switches, +# and 2 Access Points +# +# Each template defines network-level configuration which is +# applicable to the inventory - meaning the secure router, +# switch, and AP devices - within the site. +# +# Note that these templates are not related to templates +# configured within the Cisco (formerly Meraki) dashboard. +# +# The below code does the following: +# +# hub configuration template. +# +# The hub configuration template configures defines the +# device (security appliance) and configures parameters +# specific to those devices within the site / network to +# which the template is applied. +# +# For the current version of Unified Branch - Branch as Code, +# since only the hub name is require for branch configuration, +# the hub is imported. Hence the hub YAML configuration below +# has been commented out. +# +meraki: + template: + networks: + # - name: hub + # devices: + # - name: ${appliance_01_name} + # serial: ${appliance_01_serial} + # tags: + # - test + # lat: ${lat} + # lng: ${lng} + # address: ${address} + # notes: Small Branch Notes Appliance + # appliance: + # uplinks_settings: + # wan1: + # enabled: true + # svis: + # ipv4: + # assignment_mode: dynamic + # wan2: + # enabled: true + # svis: + # ipv4: + # assignment_mode: dynamic + # + # The below code does the following: + # + # small_branch_inventory configuration template. + # + # The small_branch_inventory configuration template configures defines the + # devices (security appliance, switch, and access points) + # and configures parameters specific to those devices + # within the site / network to which the template is applied. + # + # Note that this repository uses the words appliance, security appliance, + # and secure router to all refer to the MX security appliance. + # + - name: small_branch_inventory + devices: + # + # The below code does the following: + # + # Secure router (Appliance) configuration + # + # Defines the name, serial number, geolocation coordinates + # (latitude & longitude), and address variables for the + # security appliance within the site to which the template + # is applied. + # + - name: ${appliance_01_name} + serial: ${appliance_01_serial} + tags: + - test + lat: ${lat} + lng: ${lng} + address: ${address} + notes: Small Branch Notes Appliance + # + # The below code does the following: + # + # The switch configurations + # + # Defines the name, serial number, geolocation coordinates + # (latitude & longitude), and address variables for the + # first and second switches within the site to which the template + # is applied. + # + # Hardcodes the ports 1 - 13 of the switches to be trunk + # ports allowing specific VLANs. Rapid Spanning-Tree Protocol + # (RTSP) is enabled by default on the trunk ports. Link negotiation + # (speed and duplex) is set to auto negotiate by default. + # + # Hardcodes ports 14 - 24 to be access ports on VLAN 1 with + # Voice VLAN 30. RTSP is enabled by default with + # BPDU guard and storm control also enabled for access ports. + # Link negotiation (speed and duplex) is set to auto + # negotiate. + # + # Note, you may need to change the port_id_ranges depending + # upon which switch models you choose to deploy within your branch. + # + - name: ${access_switch_01_name} + serial: ${access_switch_01_serial} + tags: + - test + lat: ${lat} + lng: ${lng} + address: ${address} + notes: Small Branch Notes Switch + switch: + ports: + - port_id_ranges: + - from: 1 + to: 13 + name: Uplink Trunk Port + enabled: true + type: trunk + tags: + - uplink + - trunk + vlan: 1 + allowed_vlans: 1,10,20,30,50,999 + link_negotiation: Auto negotiate + udld: Alert only + storm_control: true + rstp: true + - port_id_ranges: + - from: 14 + to: 24 + name: Access Port + enabled: true + type: access + tags: + - access + vlan: 10 + voice_vlan: 20 + link_negotiation: Auto negotiate + storm_control: true + rstp: true + stp_guard: bpdu guard + - name: ${access_switch_02_name} + serial: ${access_switch_02_serial} + tags: + - test + lat: ${lat} + lng: ${lng} + address: ${address} + notes: Small Branch Notes Switch + switch: + ports: + - port_id_ranges: + - from: 1 + to: 13 + name: Uplink Trunk Port + enabled: true + type: trunk + tags: + - uplink + - trunk + vlan: 1 + allowed_vlans: 1,10,20,30,50,999 + link_negotiation: Auto negotiate + udld: Alert only + storm_control: true + rstp: true + - port_id_ranges: + - from: 14 + to: 24 + name: Access Port + enabled: true + type: access + tags: + - access + vlan: 10 + voice_vlan: 20 + link_negotiation: Auto negotiate + storm_control: true + rstp: true + stp_guard: bpdu guard + # + # The below code does the following: + # + # First access point configuration + # + # Defines the name, serial number, geolocation coordinates + # (latitude & longitude), and address variables for the + # first access point within the site to which the template + # is applied. + # + - name: ${ap_01_name} + serial: ${ap_01_serial} + tags: + - test + lat: ${lat} + lng: ${lng} + address: ${address} + notes: Small Branch Notes Access Point + # + # The below code does the following: + # + # Second access point configuration + # + # Defines the name, serial number, geolocation coordinates + # (latitude & longitude), and address variables for the + # second access point within the site to which the template + # is applied. + # + - name: ${ap_02_name} + serial: ${ap_02_serial} + tags: + - test + lat: ${lat} + lng: ${lng} + address: ${address} + notes: Small Branch Notes Appliance diff --git a/data/templates-network-related.nac.yaml b/data/templates-network-related.nac.yaml index 66a19b9..f44357d 100644 --- a/data/templates-network-related.nac.yaml +++ b/data/templates-network-related.nac.yaml @@ -1,103 +1,73 @@ -# The below code does the following: +# This template defines comprehensive network configuration templates for Meraki infrastructure. +# Templates are applied at the network/site level and configure device behaviors across the deployment. # -# This YAML file defines the following network related templates: -# -# - product_types -# - network_settings -# - snmp -# - syslog -# - nw_switch -# - wireless -# -# Each template defines services configuration which is -# applicable to devices within the network / site to which -# the template is applied. -# -# Note that these templates are not related to templates -# configured within the Cisco (formerly Meraki) dashboard. +# Note: These are NetasCode templates for infrastructure-as-code, not Meraki Dashboard templates. +# Variables use ${variable_name} syntax and sensitive data uses !env for environment variables. +# +#Last updated: 2025-10-20 # meraki: template: networks: + # Template: nw_setup + # Purpose: Defines fundamental network configuration including product types and elements + # for site creation, such as timezones and descriptions. # - # The below code does the following: + # This template establishes the base network configuration by: + # - Enabling specific Meraki product types (appliance, switch, wireless, cellularGateway) + # - Setting location-specific time zone for accurate logging and scheduling + # - Adding operational notes for site-specific requirements or constraints + # - Applying metadata tags for categorization, reporting, and search operations # - # product_types configuration template. # - # The product_types configuration template defines the - # devices (appliance, switch, wireless, camera, sensor, - # cellularGateway) within the network / site to which - # the template is applied. - # - - name: product_types + - name: nw_setup product_types: - appliance - switch - wireless - - camera - - sensor - cellularGateway - # + time_zone: ${time_zone} + notes: ${network_notes} + tags: + - small_branch + # # The below code does the following: + # + # Configures network-wide management plane settings for monitoring and access control # - # network_settings configuration template. + # This template establishes management configurations: + # - Local and remote status page access for troubleshooting the device directly + # - SNMPv3 with user-based authentication for secure monitoring of MIBs + # - Centralized syslog collection for compliance and troubleshooting + # - Named VLAN support for dynamic RADIUS-based VLAN assignment # - # The network_settings template enables both - # the local and remote status pages for devices within - # network / site to which the template is applied. - # Additionally, it sets the credentials for access - # to the local status page of the devices. Note: this - # configuration is for example only. As a general - # recommendation - DO NOT hardcode sensitive - # information such as credentials within any file which - # is checked into a version control system. - # - - name: network_settings + # Security Considerations: + # - Credentials use !env to reference environment variables (never hardcode) + # - SNMPv3 provides encryption and authentication vs SNMPv2 community strings + # - Local status page should use strong credentials and the password is a minimum 12 chars + # + # Integration Requirements: + # - Syslog server must be reachable from management VLAN + # - SNMP collector must support SNMPv3 with matching credentials, default encryption is DES + # - Named VLANs require coordination with RADIUS server configuration + # + - name: nw_management settings: local_status_page_enabled: true remote_status_page: true secure_port: false local_status_page_authentication: - username: ${local_status_page_username} - password: !env local_status_page_password - named_vlans: true - # - # The below code does the following: - # - # snmp configuration template. - # - # The snmp template configures SNMPv3 access (username - # and password) to devices within the site / netwwork - # to which the template is applied. This does not - # configure any firewall settings restricting SNMP access, - # which may be required based on the security policy of - # the organization. Note: this configuraiton is for example - # only. As a general recommendation - DO NOT hardcode - # sensitive information such as credentials within any file - # which is checked into a version control system. - # - - name: snmp + username: !env local_page_username + password: !env local_page_password + named_vlans: true snmp: access: users users: - - username: ${snmp_username} + - username: !env snmp_username passphrase: !env snmp_passphrase - # - # The below code does the following: - # - # syslog configuration template. - # - # The syslog template configures a single remote - # syslog server, defined as a variable. UDP port 514 - # is configured as port on which syslog traffic is - # sent. The configuration enables sending of all - # message categories / roles for all types of devices - # in the site / network to which the template is applied. - # - - name: syslog syslog_servers: - host: ${syslog_server} - port: 514 + port: ${syslog_port} roles: - Switch event log - Air Marshal events @@ -105,499 +75,42 @@ meraki: - URLs - Wireless event log - Appliance event log + # netflow: + # collector_ip: ${netflow_server} + # collector_port: ${netflow_port} + # reporting: true + # eta: false # # The below code does the following: # - # nw_switch configuration template. - # - # The nw_switch template configures the following - # for the switch within the network to which the - # template is applied: - # - # - Sets the management VLAN to VLAN 1. - # - # - Sets any secondary power supply to be redundant - # power for the switch only. - # - # - Enables sampling of clients and traffic on the - # detected uplink interface. - # - # - Sets the default MTU size of switch ports to - # 9100 bytes. - # - # - Sets the DHCP server policy of the switch to - # allow DHCP traffic. - # - # - Defines the DSCP to CoS queue mapping assuming - # a 12-class QoS model, using all 8 CoS queues. - # - # - Defines an example set of QoS classification - # and marking rules for different VLANs on the switch. - # - # - Restricts broadcast, multicast, and unknown unicast - # traffic to 30% of the available bandwidth of the - # switch ports (storm control). - # - # - Defines an esample port schedule named "Weekend Only - # Port Schedule". Configures ports to which the schedule - # is applied to be available at all hours for all days - # of the week. - # - - name: nw_switch - switch: - settings: - vlan: 1 - use_combined_power: false - uplink_client_sampling: true - mac_blocklist: false - mtu: - default_mtu_size: 9100 - dhcp_server_policy: - default_policy: allow - dscp_to_cos_mappings: - - cos: 0 - dscp: 8 - title: Scavenger CS1 - - cos: 0 - dscp: 10 - title: Bulk AF11 - - cos: 0 - dscp: 12 - title: Bulk AF12 - - cos: 0 - dscp: 14 - title: Bulk AF13 - - cos: 1 - dscp: 0 - title: Default CS0 - - cos: 2 - dscp: 16 - title: Network Mgmt CS2 - - cos: 2 - dscp: 18 - title: Transactional Data AF21 - - cos: 2 - dscp: 20 - title: Transactional Data AF22 - - cos: 2 - dscp: 22 - title: Transactional Data AF23 - - cos: 2 - dscp: 24 - title: Signaling CS3 - - cos: 3 - dscp: 26 - title: Multimedia Streaming AF31 - - cos: 3 - dscp: 28 - title: Multimedia Streaming AF32 - - cos: 3 - dscp: 30 - title: Multimedia Streaming AF33 - - cos: 3 - dscp: 40 - title: Broadcast Video CS5 - - cos: 4 - dscp: 32 - title: Realtime Interactive CS4 - - cos: 4 - dscp: 34 - title: Multimedia Conferencing AF41 - - cos: 4 - dscp: 36 - title: Multimedia Conferencing AF42 - - cos: 4 - dscp: 38 - title: Multimedia Conferencing AF43 - - cos: 5 - dscp: 44 - title: Admission-Controlled Voice EF - - cos: 5 - dscp: 46 - title: Voice EF - - cos: 5 - dscp: 48 - title: Internetwork Control CS6 - - cos: 5 - dscp: 56 - title: Network Control CS7 - qos_rules: - - vlan: 20 - protocol: ANY - dscp: -1 - qos_rule_name: Trust_DSCP_Voice_VLAN - - vlan: 30 - protocol: ANY - dscp: 0 - qos_rule_name: Remark_Guest_to_Default - - vlan: 10 - protocol: UDP - source_port_range: 16384-32767 - destination_port_range: 16385-32767 - dscp: 46 - qos_rule_name: Voice_to_EF_Data_VLAN - - vlan: 10 - protocol: ANY - dscp: 0 - qos_rule_name: Other_to_Default_Data_VLAN - storm_control: - broadcast_threshold: 30 - multicast_threshold: 30 - unknown_unicast_threshold: 30 - port_schedules: - - name: Weekend Only Port Schedule - port_schedule: - friday: - active: true - from: 00:00 - to: '24:00' - monday: - active: true - from: 00:00 - to: '24:00' - saturday: - active: true - from: 00:00 - to: '24:00' - sunday: - active: true - from: 00:00 - to: '24:00' - thursday: - active: true - from: 00:00 - to: '24:00' - tuesday: - active: true - from: 00:00 - to: '24:00' - wednesday: - active: true - from: 00:00 - to: '24:00' - # - # The below code does the following: - # - # wireless configuration template. - # - # The wireless template configures various parameters - # under three main categories - settings, rf_profiles, - # and ssids for the access points within the network to - # which the template is applied. Note that the parameters - # defined within this section are examples only. They are - # not intended to be used directly in production networks, - # and are not considered to be any form of best-practice - # configuration. - # - # settings: The settings sections configures various - # network-wide wireless device (AP) settings. - # - # rf-profiles: The rf_profiles section configures a - # single profile named "Corp wireless rf profile". - # - # - Clients are steered to the best available - # AP during association (client balancing). - # - # - Minimum bit rate supported is specified per - # RF band - 2.4, 5 GHz (6 GHz not enabled). - # - # - Selection of RF bands is configured on a - # per-SSID level, rather than across all SSIDs - # to which the RF profile is applied. - # - # - For the 2.4 GHz RF band: - # - Minimum transmit power configured for 10 dBm - # - Maximum transmit power configured for 30 dBm - # - Minimum supported bit rate is 11 Mbps - # - Auto channel selection is left at the default of - # channels 1, 3, & 11. - # - Keeps 802.11ax enabled - # - Enables and sets the Receiver Start of Packet - # (RX-SOP) to -80 dBm - # - # - For the 5 GHz RF band: - # - Minimum transmit power configured for 10 dBm - # - Maximum transmit power configured for 30 dBm - # - Minimum supported bit rate is 9 Mbps - # - Auto channel selection is configured to non-DFS - # channels 36, 40, 44 48, 157, and 161. - # - Channel width is set to 80 MHz - # - Keeps 802.11ax enabled - # - Enables and sets the Receiver Start of Packet - # (RX-SOP) to -80 dBm - # - # - Enables radio transmission. - # - # - Specific configuration for the "Guest" SSID for a minimum - # bit rate of 11 Mbps, operating in the 5 GHz band. - # - # - Sets the RF profile as the default indoor and outdoor - # profile. - # - # ssid: The SSIDs section hardcodes three SSIDs - Data (SSID 0), - # Voice (SSID 1), and Guest (SSID 3). - # - # - For the Data SSID: - # - Authentication mode is set to open (no encryption). - # - # - Per-client and per-SSID rate limits are set to unlimited - # (no rate-limiting). - # - # - The 4 default traffic shaping rules are disabled. Instead - # a per-application traffic shaping rule identifies and classifies - # 5 different applications, then sets the DSCP marking of the traffic - # to CS2 (DSCP 16) and defines custom per bandwidth limits of 1 Mbps - # upstream and downstream. (Note that applications must be specified - # by ID currently. Work to translate the IDs into user-friendly names - # is ongoing). A second traffic shaping rule identifies traffic based - # on host, IP subnet, and IP subnet with port, then sets the DSCP marking - # of the traffic to CS3 (DSCP 24) with rate limiting set to the network - # default (unlimited). - # - # - IP address assignment for wireless clients is via the DHCP server within - # the security appliance (briged_mode). - # - # - VLAN tagging is enabled with the assignment of the VLAN to which - # the Data SSID is assigned defined as a variable. - # - # - An example SSID availability schedule for the weekend is defined. - # - # - For the Voice SSID: - # - Authentication mode is set to open (no encryption). - # - # - Per-client and per-SSID rate limits are set to unlimited - # (no rate-limiting). - # - # - The 4 default traffic shaping rules are disabled. Instead - # a per-application traffic shaping rule identifies and classifies - # one voice application, then sets the DSCP marking of the traffic - # to EF (DSCP 46) & CoS to 7; and allows the application to ignore any - # bandwidth limits. (Note that applications must be specified by ID - # currently. Work to translate the IDs into user-friendly names is ongoing). - # - # - IP address assignment for wireless clients is via the DHCP server within - # the security appliance (briged_mode). - # - # - VLAN tagging is enabled with the assignment of the VLAN to which - # the Data SSID is assigned defined as a variable. - # - # - An example SSID availability schedule for the weekend is defined. - # - # - For the Guest SSID: - # - Authentication mode is set to open (no encryption). - # - # - Per-client rate limits are set to 10 Mbps upstream and downstream. - # - # - Per-SSID rate limits are set 100 Mbps upstream and downstream. - # - # - The 4 default traffic shaping rules are enabled. - # - # - IP address assignment for wireless clients is via the DHCP server within - # the security appliance (briged_mode). - # - # - VLAN tagging is enabled with the assignment of the VLAN to which - # the Data SSID is assigned defined as a variable. - # - # - A click-through splash-page is enabled for guest traffic. - # - # - An example SSID availability schedule for the weekend is defined. - # - - name: wireless - wireless: - settings: - meshing: false - ipv6_bridge: true - location_analytics: true - led_lights_on: true - upgrade_strategy: minimizeClientDowntime - named_vlans_pool_dhcp_monitoring: - enabled: false - duration: 5 - rf_profiles: - - name: Corp wireless rf profile - client_balancing: true - min_bitrate_type: band - band_selection_type: ssid - ap_band_settings: - two_four_ghz_settings: - max_power: 30 - min_power: 10 - min_bitrate: 11 - valid_auto_channels: - - 1 - - 6 - - 11 - ax: true - rxsop: -80 - five_ghz_settings: - max_power: 30 - min_power: 10 - min_bitrate: 9 - valid_auto_channels: - - 36 - - 40 - - 44 - - 48 - - 157 - - 161 - channel_width: "80" - rxsop: -80 - transmission: true - per_ssid_settings: - - ssid_name: "Guest" - min_bitrate: 11 - band_operation_mode: 5ghz - bands: - - "5" - band_steering: true - is_indoor_default: true - is_outdoor_default: true - ssids: - - name: Data - ssid_number: '0' - traffic_shaping_rules: - default_rules: false - traffic_shaping: true - rules: - - definitions: - - type: application - value: meraki:layer7/application/332 - - type: application - value: meraki:layer7/application/2249 - - type: application - value: meraki:layer7/application/351 - - type: application - value: meraki:layer7/application/2248 - - type: application - value: meraki:layer7/application/2542 - per_client_bandwidth_limits: - settings: custom - bandwidth_limits: - limit_up: 1000 - limit_down: 1000 - dscp_tag_value: 16 - - definitions: - - type: host - value: nms.example.com - - type: ipRange - value: 158.43.128.0/24 - - type: localNet - value: 192.168.0.0/16 - - type: port - value: "161" - per_client_bandwidth_limits: - settings: network default - dscp_tag_value: 24 - per_client_bandwidth_limit_down: 0 - per_client_bandwidth_limit_up: 0 - per_ssid_bandwidth_limit_down: 0 - per_ssid_bandwidth_limit_up: 0 - splash_page: None - enabled: true - ip_assignment_mode: Bridge mode - use_vlan_tagging: true - default_vlan_id: ${default-vlan-id-data} - ap_tags_and_vlan_ids: - - tags: - - ${ap-tag1} - vlan_id: ${ap-tag1-vlan-id} - - tags: - - ${ap-tag2} - vlan_id: ${ap-tag1-vlan-id} - schedules: - enabled: ${data_ssid_schedules_enabled} - ranges: - - start_day: Sunday - start_time: 00:00:00 - end_time: 06:00:00 - end_day: Sunday - - start_day: Saturday - start_time: 00:00:00 - end_time: 06:00:00 - end_day: Saturday - - name: Voice - ssid_number: '1' - traffic_shaping_rules: - default_rules: false - traffic_shaping: true - rules: - - definitions: - - type: applicationCategory - value: "meraki:layer7/category/16" - per_client_bandwidth_limits: - settings: ignore - dscp_tag_value: 46 - pcp_tag_value: 7 - per_client_bandwidth_limit_down: 0 - per_client_bandwidth_limit_up: 0 - per_ssid_bandwidth_limit_down: 0 - per_ssid_bandwidth_limit_up: 0 - splash_page: None - enabled: true - ip_assignment_mode: Bridge mode - use_vlan_tagging: true - default_vlan_id: ${default-vlan-id-data} - ap_tags_and_vlan_ids: - - tags: - - ${ap-tag1} - vlan_id: ${ap-tag1-vlan-id} - - tags: - - ${ap-tag2} - vlan_id: ${ap-tag1-vlan-id} - schedules: - enabled: ${voice_ssid_schedules_enabled} - ranges: - - start_day: Sunday - start_time: 00:00:00 - end_time: 06:00:00 - end_day: Sunday - - start_day: Saturday - start_time: 00:00:00 - end_time: 06:00:00 - end_day: Saturday - - name: Guest - ssid_number: '2' - traffic_shaping_rules: - default_rules: true - traffic_shaping: true - per_client_bandwidth_limit_down: 10000 - per_client_bandwidth_limit_up: 10000 - per_ssid_bandwidth_limit_down: 100000 - per_ssid_bandwidth_limit_up: 100000 - enabled: true - ip_assignment_mode: Bridge mode - use_vlan_tagging: true - default_vlan_id: ${default-vlan-id-data} - ap_tags_and_vlan_ids: - - tags: - - ${ap-tag1} - vlan_id: ${ap-tag1-vlan-id} - - tags: - - ${ap-tag2} - vlan_id: ${ap-tag1-vlan-id} - splash_page: Click-through splash page - splash_settings: - allow_simultaneous_logins: true - billing: - free_access: - duration_in_minutes: 20 - enabled: false - reply_to_email_address: ${splash_reply_to_email_address} - block_all_traffic_before_sign_on: true - controller_disconnection_behavior: default - guest_sponsorship: - guest_can_request_timeframe: false - splash_timeout: 1440 - use_redirect_url: false - use_splash_url: false - schedules: - enabled: ${guest_ssid_schedules_enabled} - ranges: - - start_day: Sunday - start_time: 00:00:00 - end_time: 06:00:00 - end_day: Sunday - - start_day: Saturday - start_time: 00:00:00 - end_time: 06:00:00 - end_day: Saturday + # group_policies template. + # + # The group_policies template configures the group policies + # that are returned by the Radius server through the Filter-Id + # attribute during 802.1x authentication for wired and wireless + # devices. Each group policy returns the VLAN ID override + # applicable to the VLAN to which the client is assigned. + # + # The YAML code below defines three group policies, with the + # policy group name and the VLAN assignment defined as + # variables. Since no other group policy parameters are + # configured, they do not appear within the YAML code. + # Please refer to the following URL for a full definition + # of available parameters within group policies: + # + # https://netascode.cisco.com/docs/data_models/meraki/networks/group_policies/ + # + # Additional group policies with their respective VLAN ID assignments + # can be added to the YAML code as needed for additional VLANs. + # + - name: group_policies + group_policies: + - name: ${data_vlan_group_policy} + vlan_tagging: + vlan_id: 10 + - name: ${voice_vlan_group_policy} + vlan_tagging: + vlan_id: 20 + - name: ${iot_vlan_group_policy} + vlan_tagging: + vlan_id: 30 diff --git a/data/templates-switch.nac.yaml b/data/templates-switch.nac.yaml new file mode 100644 index 0000000..95c9dde --- /dev/null +++ b/data/templates-switch.nac.yaml @@ -0,0 +1,188 @@ +# This template defines comprehensive network configuration templates for Meraki infrastructure. +# Templates are applied at the network/site level and configure device behaviors across the deployment. +# +# Note: These are NetasCode templates for infrastructure-as-code, not Meraki Dashboard templates. +# Variables use ${variable_name} syntax and sensitive data uses !env for environment variables. +# +# +meraki: + template: + networks: + # + # The below code does the following: + # + # Switch configuration including switch heirachy and setup, access control, QoS + # and network policies + # + # This template configures the complete switching infrastructure: + # + # Access Policies: - Configures a wired radius policy for authentication endpoints to the wire. + # + # - 802.1x hybrid authentication with RADIUS for wired network access control + # - RADIUS accounting for audit trails and session tracking + # - Change of Authorization (CoA) support for dynamic policy updates + # - Multi-host mode allowing multiple devices per port + # - Voice VLAN domain support for IP phones + # - Filter-Id attribute (11) maps to Meraki group policies for policy assignment + # + # Switch Settings: + # - Management VLAN 999 for out-of-band management (migrates from VLAN 1 after onboarding) + # - Uplink client sampling for traffic analytics + # - Jumbo frame support with MTU configuration configured at 9176 + # - IGMP snooping for multicast optimization + # + # Quality of Service: + # - 12-class QoS model mapped to 8 CoS queues + # - DSCP to CoS mappings following RFC 4594 recommendations + # - Per-VLAN QoS rules for traffic classification and marking + # - Voice traffic marked as EF (DSCP 46) for priority handling + # + # Network Protection: + # - Storm control limiting broadcast/multicast/unknown unicast to 30% + # - Rapid Spanning Tree Protocol (RSTP) with tuned priorities + # - Switch stack configuration for redundancy + # + # Variables: + # - ${radius_server1_host/port}: Primary RADIUS server details + # - !env radius_server1_secret: RADIUS shared secret (from environment) + # - ${radius_accounting_server1_host/port}: RADIUS accounting server + # - ${switch_mtu_size}: Maximum transmission unit size (default 9176) + # - ${access_stack_01_name}: Switch stack identifier + # - ${access_switch_01_name/02_name}: Individual switch serial numbers + # + # + - name: switch + switch: + access_policies: + - name: "Wired Access Policy" + radius_servers: + - host: ${radius_server1_host} + port: ${radius_server1_port} + secret: !env radius_server1_secret + radius_accounting_servers: + - host: ${radius_accounting_server1_host} + port: ${radius_accounting_server1_port} + secret: !env radius_accounting_server1_secret + radius_accounting: true + radius_coa_support: true + radius_testing: true + radius_group_attribute: "11" + host_mode: Multi-Host + voice_vlan_clients: true + access_policy_type: Hybrid authentication + radius: + re_authentication_interval: 86400 + dot1x_control_direction: both + url_redirect_walled_garden: false + settings: + vlan: 999 + use_combined_power: false + uplink_client_sampling: true + mac_blocklist: false + mtu: + default_mtu_size: ${switch_mtu_size} + routing_multicast: + default_settings: + igmp_snooping: true + flood_unknown_multicast_traffic: false + dscp_to_cos_mappings: + - cos: 0 + dscp: 8 + title: Scavenger CS1 + - cos: 0 + dscp: 10 + title: Bulk AF11 + - cos: 0 + dscp: 12 + title: Bulk AF12 + - cos: 0 + dscp: 14 + title: Bulk AF13 + - cos: 1 + dscp: 0 + title: Default CS0 + - cos: 2 + dscp: 16 + title: Network Mgmt CS2 + - cos: 2 + dscp: 18 + title: Transactional Data AF21 + - cos: 2 + dscp: 20 + title: Transactional Data AF22 + - cos: 2 + dscp: 22 + title: Transactional Data AF23 + - cos: 2 + dscp: 24 + title: Signaling CS3 + - cos: 3 + dscp: 26 + title: Multimedia Streaming AF31 + - cos: 3 + dscp: 28 + title: Multimedia Streaming AF32 + - cos: 3 + dscp: 30 + title: Multimedia Streaming AF33 + - cos: 3 + dscp: 40 + title: Broadcast Video CS5 + - cos: 4 + dscp: 32 + title: Realtime Interactive CS4 + - cos: 4 + dscp: 34 + title: Multimedia Conferencing AF41 + - cos: 4 + dscp: 36 + title: Multimedia Conferencing AF42 + - cos: 4 + dscp: 38 + title: Multimedia Conferencing AF43 + - cos: 5 + dscp: 44 + title: Admission-Controlled Voice EF + - cos: 5 + dscp: 46 + title: Voice EF + - cos: 5 + dscp: 48 + title: Internetwork Control CS6 + - cos: 5 + dscp: 56 + title: Network Control CS7 + qos_rules: + - vlan: 20 + protocol: ANY + dscp: -1 + qos_rule_name: Trust_DSCP_Voice_VLAN + - vlan: 30 + protocol: ANY + dscp: -1 + qos_rule_name: Remark_Guest_to_Default + - vlan: 10 + protocol: UDP + source_port_range: 16384-32767 + destination_port_range: 16385-32767 + dscp: 46 + qos_rule_name: Voice_to_EF_Data_VLAN + - vlan: 10 + protocol: ANY + dscp: -1 + qos_rule_name: Other_to_Default_Data_VLAN + storm_control: + broadcast_threshold: 30 + multicast_threshold: 30 + unknown_unicast_threshold: 30 + stp: + stp_bridge_priority: + - stp_priority: 8192 + stacks: + - ${access_stack_01_name} + rstp: true + switch_stacks: + - name: ${access_stack_01_name} + devices: + - ${access_switch_01_name} + - ${access_switch_02_name} diff --git a/data/templates-wan-connectivity.nac.yaml b/data/templates-wan-connectivity.nac.yaml new file mode 100644 index 0000000..8d6443c --- /dev/null +++ b/data/templates-wan-connectivity.nac.yaml @@ -0,0 +1,23 @@ +# The below code does the following: +# +# This YAML file defines templates which provide the following set of +# Unified Branch services applicable to the appliance: +# +# - Connectivivity monitoring configuration - defined in the app_connectivity_monitoring template +# +# Note that these templates are not related to templates +# configured within the Cisco (formerly Meraki) dashboard. +# +# NOTE: uncomment the below code to enable connectivity monitoring configuration +# and add appl_comonitoring template to your pods_variables.nac.yaml file to apply to desired network. +# =========================================================================== +# +# meraki: +# template: +# networks: +# - name: appl_comonitoring +# appliance: +# connectivity_monitoring_destinations: +# - ip: "1.1.1.1" +# description: Cloudflare DNS +# default: true diff --git a/data/templates-wan-ts.nac.yaml b/data/templates-wan-ts.nac.yaml new file mode 100644 index 0000000..4e4ddf4 --- /dev/null +++ b/data/templates-wan-ts.nac.yaml @@ -0,0 +1,204 @@ +# =============================================================== +# WAN TRAFFIC SHAPPING +# =============================================================== +# +# The below code does the following: +# +# Security appliance traffic shaping configuration template. +# +# This template applies to VPN (tunneled) traffic across the WAN +# interfaces of the security appliance. It consists of the following +# 4 sections: +# +# - global_bandwidth_limits +# - custom_performance_classes +# - rules +# - uplink_bandwidth_limits +# - uplink_selection +# +# The custom_performance_classes section defines an example custom +# (non-builtin) performance class named "Radius", and sets the max +# latency and max jitter tolerances at 30 milliseconds, and the +# max loss percentage at 5% in order for traffic to be within the +# SLA of the performance class. Note that performance classes defined +# here can apply to either VPN or non-VPN (Internet) traffic across +# WAN uplinks. +# +# The uplink_bandwidth_limits section sets the uplink and downlink +# bandwidth limits for all traffic from all clients on each WAN uplink. +# This is essentially equivalent to sub-line rate limiting to the +# speed of carrier, even though the physical connection may be 1 Gbps +# Ethernet. The example configuration sets the rate-limit to 400,000 Kbps +# (400 Mbps) upstream and downstream for WAN 1 uplinks and 500 Mbps for WAN 2. +# The limits are configured as variables so that they can be easily adjusted. +meraki: + template: + networks: + - name: app_ts + appliance: + traffic_shaping: + # + # ============================================================== + # Global bandwidth limits + # The global_bandwidth_limits section configures per-client + # rate-limiting both upstream and downstream. + # ============================================================== + # + global_bandwidth_limits: + limit_up: ${wan_limit_up} + limit_down: ${wan_limit_down} + custom_performance_classes: + - name: Radius + max_latency: 30 + max_jitter: 30 + max_loss_percentage: 5 + # + # ============================================================== + # Traffic shaping rules + # Traffic shaping rules can be applied per client and per application + # to optimize network performance and ensure critical applications + # receive the necessary bandwidth. + # + # Rule actions: + # Actions include setting bandwidth limits (upload/download), + # prioritizing traffic (High, Normal, Low), + # and applying DSCP tagging for QoS prioritization + # + # Update the rules as needed to fit your requirements. + # ============================================================== + # + rules: + rules: + - name: Rule 01 + definitions: + # Application categories and applications can be found by running /networks/{networkId}/appliance/firewall/l7FirewallRules/applicationCategories API call + - type: applicationCategory + value: "meraki:layer7/category/24" # "Databases & cloud services" + - type: application + value: meraki:layer7/application/332 # "Amazon RDS" + per_client_bandwidth_limits: + settings: custom + bandwidth_limits: + limit_up: 1000 + limit_down: 1000 + dscp_tag_value: 10 + priority: high + - name: Rule 02 + definitions: + - type: application + value: meraki:layer7/application/332 # "Amazon RDS" + per_client_bandwidth_limits: + settings: ignore + dscp_tag_value: 18 + priority: high + default_rules: false + # + # ============================================================== + # Uplink bandwidth limits + # Implements sub-line rate limiting to the speed of the carrier + # for each WAN uplink. + # ============================================================== + # + uplink_bandwidth_limits: + wan1: + limit_up: ${wan1_limit_up} + limit_down: ${wan1_limit_down} + wan2: + limit_up: ${wan2_limit_up} + limit_down: ${wan2_limit_down} + cellular: + limit_up: 0 + limit_down: 0 + # + # ============================================================== + # Uplink selection + # provide several configurable options for uplink selection + # as part of SD-WAN and traffic shaping capabilities. + # These options allow administrators to control how traffic + # is routed across multiple WAN uplinks to optimize performance, + # reliability, and application prioritization. + # ============================================================== + # + uplink_selection: + default_uplink: wan1 + active_active_auto_vpn: true + load_balancing: true + failover_and_failback_immediate: true + # + # ============================================================== + # Non-VPN (Internet) traffic uplink preferences + # + # See note below about using either wan_traffic_uplink_preferences + # or sdwan_internet_policies, but not both + # ============================================================== + # + # wan_traffic_uplink_preferences: + # - name: policy 1 + # preferred_uplink: "wan1" + # traffic_filters: + # - type: custom + # value: + # protocol: tcp + # source: + # port: "1-1024" + # cidr: any + # destination: + # cidr: any + # port: any + # - name: policy 2 + # preferred_uplink: "wan1" + # traffic_filters: + # - type: custom + # value: + # protocol: tcp + # source: + # port: any + # cidr: ${vlan10_subnet} + # destination: + # cidr: any + # port: "443" + # + # ============================================================== + # VPN traffic uplink preferences + # For VPN traffic uplink preferences on appliances + # ============================================================== + # + vpn_traffic_uplink_preferences: + - name: policy 1 + preferred_uplink: wan1 + traffic_filters: + - type: application + value: + id: meraki:layer7/application/375 + - type: "custom" + value: + protocol: any + source: + port: any + cidr: any + destination: + port: any + cidr: any + fail_over_criterion: poorPerformance + performance_class: + type: builtin + builtin_performance_class_name: VoIP + - name: policy 2 + preferred_uplink: wan1 + traffic_filters: + - type: application + value: + id: meraki:layer7/application/4 + - type: "custom" + value: + protocol: any + source: + port: any + cidr: any + destination: + port: any + cidr: any + fail_over_criterion: poorPerformance + performance_class: + type: builtin + builtin_performance_class_name: VoIP diff --git a/data/templates-wan-uplinks.nac.yaml b/data/templates-wan-uplinks.nac.yaml new file mode 100644 index 0000000..9dd772a --- /dev/null +++ b/data/templates-wan-uplinks.nac.yaml @@ -0,0 +1,759 @@ +# Comprehensive WAN Uplink Configuration Template +# This template provides complete coverage of all WAN uplink scenarios for Meraki MX appliances +# Aligns with schema.yaml and Meraki best practices +# +# Last updated: 2025-10-16 +# +meraki: + template: + networks: + # ===================================================================== + # WAN UPLINKS TEMPLATES + # ===================================================================== + # The below code does the following: + # + # These templates cover multiple possible WAN1 and WAN2 configuration scenarios + # Each template represents a specific use case + # ===================================================================== + # + # --------------------------------------------------------------------- + # TEMPLATE 1: WAN1 DHCP, WAN2 DHCP (Most Common - Auto-configuration) + # --------------------------------------------------------------------- + - name: wan_dhcp_dhcp + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + + # --------------------------------------------------------------------- + # TEMPLATE 2: WAN1 Static IPv4/IPv6, WAN2 DHCP + # --------------------------------------------------------------------- + - name: wan_static_dhcp + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "static" + address: ${wan1_ipv4_address} + gateway: ${wan1_ipv4_gateway} + nameservers: ${wan1_ipv4_dns} + ipv6: + assignment_mode: "static" + address: ${wan1_ipv6_address} + gateway: ${wan1_ipv6_gateway} + nameservers: ${wan1_ipv6_dns} + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + + # --------------------------------------------------------------------- + # TEMPLATE 3: WAN1 DHCP, WAN2 Static IPv4/IPv6 + # --------------------------------------------------------------------- + - name: wan_dhcp_static + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "static" + address: ${wan2_ipv4_address} + gateway: ${wan2_ipv4_gateway} + nameservers: ${wan2_ipv4_dns} + ipv6: + assignment_mode: "static" + address: ${wan2_ipv6_address} + gateway: ${wan2_ipv6_gateway} + nameservers: ${wan2_ipv6_dns} + + # --------------------------------------------------------------------- + # TEMPLATE 4: Both WAN Static (Full Manual Configuration) + # --------------------------------------------------------------------- + - name: wan_static_static + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "static" + address: ${wan1_ipv4_address} + gateway: ${wan1_ipv4_gateway} + nameservers: ${wan1_ipv4_dns} + ipv6: + assignment_mode: "static" + address: ${wan1_ipv6_address} + gateway: ${wan1_ipv6_gateway} + nameservers: ${wan1_ipv6_dns} + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "static" + address: ${wan2_ipv4_address} + gateway: ${wan2_ipv4_gateway} + nameservers: ${wan2_ipv4_dns} + ipv6: + assignment_mode: "static" + address: ${wan2_ipv6_address} + gateway: ${wan2_ipv6_gateway} + nameservers: ${wan2_ipv6_dns} + + # --------------------------------------------------------------------- + # TEMPLATE 5: PPPoE on WAN1, DHCP on WAN2 + # --------------------------------------------------------------------- + - name: wan_pppoe_dhcp + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: false + pppoe: + enabled: true + authentication: + enabled: true + username: ${wan1_pppoe_username} + password: ${wan1_pppoe_password} + svis: + ipv4: + assignment_mode: "dynamic" # PPPoE handles IP assignment + ipv6: + assignment_mode: "dynamic" + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + + # --------------------------------------------------------------------- + # TEMPLATE 6: DHCP on WAN1, PPPoE on WAN2 + # --------------------------------------------------------------------- + - name: wan_dhcp_pppoe + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + pppoe: + enabled: true + authentication: + enabled: true + username: ${wan2_pppoe_username} + password: ${wan2_pppoe_password} + svis: + ipv4: + assignment_mode: "dynamic" # PPPoE handles IP assignment + ipv6: + assignment_mode: "dynamic" + + # --------------------------------------------------------------------- + # TEMPLATE 7: Dual PPPoE Configuration + # --------------------------------------------------------------------- + - name: wan_pppoe_pppoe + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: false + pppoe: + enabled: true + authentication: + enabled: true + username: ${wan1_pppoe_username} + password: ${wan1_pppoe_password} + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + pppoe: + enabled: true + authentication: + enabled: true + username: ${wan2_pppoe_username} + password: ${wan2_pppoe_password} + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + + # --------------------------------------------------------------------- + # TEMPLATE 8: WAN1 VLAN Tagged DHCP, WAN2 VLAN Tagged DHCP + # --------------------------------------------------------------------- + - name: wan_vlan_vlan + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: true + vlan_id: ${wan1_vlan_id} + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: true + vlan_id: ${wan2_vlan_id} + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + + # --------------------------------------------------------------------- + # TEMPLATE 9: WAN1 Static VLAN Tagged, WAN2 DHCP + # --------------------------------------------------------------------- + - name: wan_vlan_static_dhcp + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: true + vlan_id: ${wan1_vlan_id} + svis: + ipv4: + assignment_mode: "static" + address: ${wan1_ipv4_address} + gateway: ${wan1_ipv4_gateway} + nameservers: ${wan1_ipv4_dns} + ipv6: + assignment_mode: "static" + address: ${wan1_ipv6_address} + gateway: ${wan1_ipv6_gateway} + nameservers: ${wan1_ipv6_dns} + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + + # --------------------------------------------------------------------- + # TEMPLATE 10: IPv4 Only - WAN1 DHCP, WAN2 DHCP (Legacy) + # --------------------------------------------------------------------- + - name: wan_ipv4_dhcp_dhcp + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + nameservers: ${wan1_ipv4_dns} + # IPv6 not configured for legacy networks + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + # IPv6 not configured for legacy networks + + # --------------------------------------------------------------------- + # TEMPLATE 11: IPv4 Only - WAN1 Static, WAN2 DHCP (Legacy) + # --------------------------------------------------------------------- + - name: wan_ipv4_static_dhcp + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "static" + address: ${wan1_ipv4_address} + gateway: ${wan1_ipv4_gateway} + nameservers: ${wan1_ipv4_dns} + # IPv6 not configured for legacy networks + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + # IPv6 not configured for legacy networks + + # --------------------------------------------------------------------- + # TEMPLATE 12: /31 Subnet Point-to-Point (Requires FW 14.24+) + # --------------------------------------------------------------------- + - name: wan_p2p_31 + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "static" + address: ${wan1_ipv4_address} # /31 subnet for P2P + gateway: ${wan1_ipv4_gateway} + nameservers: ${wan1_ipv4_dns} + ipv6: + assignment_mode: "static" + address: ${wan1_ipv6_address} # /127 for IPv6 P2P + gateway: ${wan1_ipv6_gateway} + nameservers: ${wan1_ipv6_dns} + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: false + svis: + ipv4: + assignment_mode: "dynamic" + ipv6: + assignment_mode: "dynamic" + + # --------------------------------------------------------------------- + # TEMPLATE 14: Enterprise with Custom Internal DNS and VLANs + # --------------------------------------------------------------------- + - name: wan_enterprise_vlan + devices: + - serial: ${appliance_01_serial} + name: ${appliance_01_name} + appliance: + uplinks_settings: + wan1: + enabled: ${wan1_enabled} + vlan_tagging: + enabled: true + vlan_id: ${wan1_vlan_id} # Enterprise WAN VLAN + svis: + ipv4: + assignment_mode: "static" + address: ${wan1_ipv4_address} + gateway: ${wan1_ipv4_gateway} + nameservers: ${wan1_ipv4_dns} # Internal DNS servers + ipv6: + assignment_mode: "static" + address: ${wan1_ipv6_address} + gateway: ${wan1_ipv6_gateway} + nameservers: ${wan1_ipv6_dns} # Internal IPv6 DNS + wan2: + enabled: ${wan2_enabled} + vlan_tagging: + enabled: true + vlan_id: ${wan2_vlan_id} # Backup WAN VLAN + svis: + ipv4: + assignment_mode: "static" + address: ${wan2_ipv4_address} + gateway: ${wan2_ipv4_gateway} + nameservers: ${wan2_ipv4_dns} + ipv6: + assignment_mode: "static" + address: ${wan2_ipv6_address} + gateway: ${wan2_ipv6_gateway} + nameservers: ${wan2_ipv6_dns} + +# ===================================================================== +# EXAMPLE CONFIGURATIONS USING VARIABLES +# ===================================================================== + +# --------------------------------------------------------------------- +# EXAMPLE 1: WAN1 DHCP, WAN2 DHCP (Most Common - Auto-configuration) +# Template: wan_dhcp_dhcp +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-XXXX-XXXX" +# appliance_01_name: "Branch-01-MX67" +# wan1_enabled: true +# wan2_enabled: true + +# --------------------------------------------------------------------- +# EXAMPLE 2: WAN1 Static IPv4/IPv6, WAN2 DHCP +# Template: wan_static_dhcp +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-YYYY-ZZZZ" +# appliance_01_name: "HQ-MX250" +# wan1_enabled: true +# wan1_ipv4_address: "203.0.113.10/29" +# wan1_ipv4_gateway: "203.0.113.9" +# wan1_ipv4_dns: +# - "8.8.8.8" +# - "8.8.4.4" +# wan1_ipv6_address: "2001:db8:1234::10/64" +# wan1_ipv6_gateway: "2001:db8:1234::1" +# wan1_ipv6_dns: +# - "2001:4860:4860::8888" +# - "2001:4860:4860::8844" +# wan2_enabled: true + +# --------------------------------------------------------------------- +# EXAMPLE 3: WAN1 DHCP, WAN2 Static IPv4/IPv6 +# Template: wan_dhcp_static +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-AAAA-BBBB" +# appliance_01_name: "Store-42-MX84" +# wan1_enabled: true +# wan2_enabled: true +# wan2_ipv4_address: "192.168.100.10/24" +# wan2_ipv4_gateway: "192.168.100.1" +# wan2_ipv4_dns: +# - "1.1.1.1" +# - "1.0.0.1" +# wan2_ipv6_address: "2001:db8:5678::10/64" +# wan2_ipv6_gateway: "2001:db8:5678::1" +# wan2_ipv6_dns: +# - "2606:4700:4700::1111" +# - "2606:4700:4700::1001" + +# --------------------------------------------------------------------- +# EXAMPLE 4: Both WAN Static (Full Manual Configuration) +# Template: wan_static_static +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-CCCC-DDDD" +# appliance_01_name: "DC-MX450" +# wan1_enabled: true +# wan1_ipv4_address: "198.51.100.10/30" +# wan1_ipv4_gateway: "198.51.100.9" +# wan1_ipv4_dns: +# - "8.8.8.8" +# - "8.8.4.4" +# wan1_ipv6_address: "2001:db8:dc01::10/64" +# wan1_ipv6_gateway: "2001:db8:dc01::1" +# wan1_ipv6_dns: +# - "2001:4860:4860::8888" +# - "2001:4860:4860::8844" +# wan2_enabled: true +# wan2_ipv4_address: "198.51.100.14/30" +# wan2_ipv4_gateway: "198.51.100.13" +# wan2_ipv4_dns: +# - "1.1.1.1" +# - "1.0.0.1" +# wan2_ipv6_address: "2001:db8:dc02::10/64" +# wan2_ipv6_gateway: "2001:db8:dc02::1" +# wan2_ipv6_dns: +# - "2606:4700:4700::1111" +# - "2606:4700:4700::1001" + +# --------------------------------------------------------------------- +# EXAMPLE 5: PPPoE on WAN1, DHCP on WAN2 +# Template: wan_pppoe_dhcp +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-EEEE-FFFF" +# appliance_01_name: "Main-MX67" +# wan1_enabled: true +# wan1_pppoe_username: "user123@isp.com" +# wan1_pppoe_password: "SecurePass2024!" +# wan2_enabled: true + +# --------------------------------------------------------------------- +# EXAMPLE 6: DHCP on WAN1, PPPoE on WAN2 +# Template: wan_dhcp_pppoe +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-GGGG-HHHH" +# appliance_01_name: "West-MX84" +# wan1_enabled: true +# wan2_enabled: true +# wan2_pppoe_username: "backup@isp2.net" +# wan2_pppoe_password: "BackupPass456!" + +# --------------------------------------------------------------------- +# EXAMPLE 7: Dual PPPoE Configuration +# Template: wan_pppoe_pppoe +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-IIII-JJJJ" +# appliance_01_name: "Remote-MX67C" +# wan1_enabled: true +# wan1_pppoe_username: "primary@isp1.com" +# wan1_pppoe_password: "PrimaryPass789!" +# wan2_enabled: true +# wan2_pppoe_username: "secondary@isp2.com" +# wan2_pppoe_password: "SecondaryPass012!" + +# --------------------------------------------------------------------- +# EXAMPLE 8: WAN1 VLAN Tagged DHCP, WAN2 VLAN Tagged DHCP +# Template: wan_vlan_vlan +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-MMMM-NNNN" +# appliance_01_name: "TenantA-MX84" +# wan1_enabled: true +# wan1_vlan_id: 500 +# wan2_enabled: true +# wan2_vlan_id: 501 + +# --------------------------------------------------------------------- +# EXAMPLE 9: VLAN Tagged WAN1 Static, WAN2 DHCP +# Template: wan_vlan_static_dhcp +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-KKKK-LLLL" +# appliance_01_name: "BuildingA-MX250" +# wan1_enabled: true +# wan1_vlan_id: 100 +# wan1_ipv4_address: "10.100.1.10/24" +# wan1_ipv4_gateway: "10.100.1.1" +# wan1_ipv4_dns: +# - "10.0.1.53" +# - "10.0.2.53" +# wan1_ipv6_address: "2001:db8:vlan100::10/64" +# wan1_ipv6_gateway: "2001:db8:vlan100::1" +# wan1_ipv6_dns: +# - "2001:db8:dns::53" +# wan2_enabled: true + +# --------------------------------------------------------------------- +# EXAMPLE 10: IPv4 Only - WAN1 DHCP, WAN2 DHCP (Legacy) +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-OOOO-PPPP" +# appliance_01_name: "Legacy-MX64" +# wan1_enabled: true +# wan1_ipv4_dns: +# - "10.0.1.53" # Internal DNS primary +# - "10.0.2.53" # Internal DNS secondary +# - "8.8.8.8" # External fallback +# - "8.8.4.4" # External fallback +# # No IPv6 configuration +# wan2_enabled: true +# # No IPv6 configuration + +# --------------------------------------------------------------------- +# EXAMPLE 11: IPv4 Only - WAN1 Static, WAN2 DHCP (Legacy) +# --------------------------------------------------------------------- +# Variables to set: +# appliance_01_serial: "Q2XX-OOOO-PPPP" +# appliance_01_name: "Legacy-MX64" +# wan1_enabled: true +# wan1_ipv4_address: "192.0.2.10/24" +# wan1_ipv4_gateway: "192.0.2.1" +# wan1_ipv4_dns: +# - "10.0.1.53" # Internal DNS primary +# - "10.0.2.53" # Internal DNS secondary +# - "8.8.8.8" # External fallback +# - "8.8.4.4" # External fallback +# # No IPv6 configuration +# wan2_enabled: true +# # No IPv6 configuration + +# ===================================================================== +# VARIABLE REFERENCE GUIDE +# ===================================================================== +# +# APPLIANCE: +# appliance_01_serial: String - Device serial number (format: QXXX-XXXX-XXXX) +# appliance_01_name: String - Descriptive device name +# +# WAN1 CONFIGURATION: +# wan1_enabled: Boolean - Enable/disable WAN1 (default: true) +# wan1_vlan_enabled: Boolean - Enable VLAN tagging (default: false) +# wan1_vlan_id: Integer - VLAN ID (1-4094) +# wan1_pppoe_enabled: Boolean - Enable PPPoE (default: false) +# wan1_pppoe_auth_enabled: Boolean - Enable PPPoE authentication (default: true) +# wan1_pppoe_username: String - PPPoE username +# wan1_pppoe_password: String - PPPoE password (5-64 characters) +# wan1_ipv4_mode: String - "dynamic" or "static" +# wan1_ipv4_address: String - IPv4 address with CIDR (e.g., "192.168.1.10/24") +# wan1_ipv4_gateway: String - IPv4 gateway address +# wan1_ipv4_dns: List - DNS servers (e.g., ["8.8.8.8", "8.8.4.4"]) +# wan1_ipv6_address: String - IPv6 address with prefix (e.g., "2001:db8::10/64") +# wan1_ipv6_gateway: String - IPv6 gateway address +# wan1_ipv6_dns: List - IPv6 DNS servers +# +# WAN2 CONFIGURATION: +# wan2_enabled: Boolean - Enable/disable WAN2 (default: true) +# wan2_vlan_enabled: Boolean - Enable VLAN tagging (default: false) +# wan2_vlan_id: Integer - VLAN ID (1-4094) +# wan2_pppoe_enabled: Boolean - Enable PPPoE (default: false) +# wan2_pppoe_auth_enabled: Boolean - Enable PPPoE authentication (default: true) +# wan2_pppoe_username: String - PPPoE username +# wan2_pppoe_password: String - PPPoE password (5-64 characters) +# wan2_ipv4_mode: String - "dynamic" or "static" +# wan2_ipv4_address: String - IPv4 address with CIDR +# wan2_ipv4_gateway: String - IPv4 gateway address +# wan2_ipv4_dns: List - DNS servers +# wan2_ipv6_address: String - IPv6 address with prefix +# wan2_ipv6_gateway: String - IPv6 gateway address +# wan2_ipv6_dns: List - IPv6 DNS servers +# +# ===================================================================== +# BEST PRACTICES AND RECOMMENDATIONS +# ===================================================================== +# +# 1. HIGH AVAILABILITY: +# - Configure WAN1 as primary (higher bandwidth/reliability) +# - Configure WAN2 as backup/failover +# - Use different ISPs for true redundancy +# - Test failover scenarios regularly +# +# 2. DNS CONFIGURATION: +# - Use geographically distributed DNS servers +# - Configure at least 2 DNS servers per WAN +# - Consider internal DNS for enterprise deployments +# - Popular public DNS options: +# * OpenDNS: 208.67.222.222, 208.67.220.220 +# * Google: 8.8.8.8, 8.8.4.4 +# * Cloudflare: 1.1.1.1, 1.0.0.1 +# * Quad9: 9.9.9.9, 149.112.112.112 +# +# 3. IP ADDRESSING: +# - Use RFC 1918 for internal networks +# - /30 or /31 subnets for point-to-point WAN links +# - Ensure no IP conflicts between WAN interfaces +# - Document all static IP assignments +# +# 4. PPPoE BEST PRACTICES: +# - Store credentials securely +# - Test authentication before production +# - Have ISP support contact readily available +# - Configure via local status page if needed +# +# 5. VLAN TAGGING: +# - Coordinate with upstream switch/router config +# - Document VLAN assignments +# - Use different VLANs for WAN separation +# - Test VLAN configuration with packet captures +# +# 6. IPv6 DEPLOYMENT: +# - Use /64 for standard subnets +# - Use /127 for point-to-point links +# - Ensure IPv6 DNS is configured +# - Test dual-stack functionality +# +# 7. MONITORING: +# - Enable uplink statistics +# - Configure alerts for failover events +# - Monitor latency and packet loss +# - Review uplink utilization regularly +# +# 8. SECURITY: +# - Change default credentials +# - Use strong PPPoE passwords +# - Implement firewall rules +# - Enable IDS/IPS on WAN interfaces +# +# 9. TESTING CHECKLIST: +# βœ“ Verify both WAN links connect +# βœ“ Test failover by disconnecting primary +# βœ“ Verify DNS resolution on both links +# βœ“ Test throughput on each link +# βœ“ Verify VLAN tags if configured +# βœ“ Test IPv6 connectivity if configured +# βœ“ Document configuration and test results +# +# 10. FIRMWARE REQUIREMENTS: +# - MX 14.24+ for /31 subnet support +# - Check compatibility for specific features +# - Keep firmware updated for security +# - Test updates in lab environment first +# +# ===================================================================== diff --git a/data/templates-wireless.nac.yaml b/data/templates-wireless.nac.yaml new file mode 100644 index 0000000..ace65bc --- /dev/null +++ b/data/templates-wireless.nac.yaml @@ -0,0 +1,307 @@ +# This template defines comprehensive network configuration templates for Meraki infrastructure. +# Templates are applied at the network/site level and configure device behaviors across the deployment. +# +# Note: These are NetasCode templates for infrastructure-as-code, not Meraki Dashboard templates. +# Variables use ${variable_name} syntax and sensitive data uses !env for environment variables. +# +# +meraki: + template: + networks: + # + # The below code does the following: + # + # wireless configuration template. + # + # The wireless template configures various parameters under three main + # categories - settings, rf_profiles, and ssids for the access points within + # the network to which the template is applied. The parameters defined + # within this section provide an example configuration based on best-practices + # consistent with Cisco Validated Designs. However, as with all network deployments, + # the specific configuration parameters should be modified and implemented based upon + # the business requirements of the organization to which they are applied. + # + # settings: The settings sections configures various network-wide wireless + # device (AP) settings. + # + # - There are two parameters specified under settings: First is the upgrade strategy which is + # hardcoded to minimize the time it takes to upgrade the APs. The second is to disable wireless + # meshing, which prevents the APs from meshing. All other parameters not specified are left at default values. + # + # Please refer to the following URL for a full definition of the parameters + # available under wireless settings: + # + # https://netascode.cisco.com/docs/data_models/meraki/networks_wireless/settings/ + # + # + # rf-profiles: The rf_profiles section configures a single profile named + # "Corp wireless rf profile". + # + # - Clients are steered to the best available AP during association (client balancing). + # This is the default setting and does not appear within the YAML configuration. + # + # - Minimum bit rate supported is specified per RF band - 2.4, 5, 6 GHz, Rather than + # per AP. Minimum bit rates are left at their default settings per band. + # + # - Selection of RF bands is configured on a per-SSID level, rather than across + # all SSIDs to which the RF profile is applied. + # + # - For the 2.4 GHz RF band the settings are left at their defaults which depend on + # the regulatory domain where the AP is operating. For example for the U.S. + # regulatory domain (-B) the following are the defaults. + # - Minimum transmit power configured for 5 dBm + # - Maximum transmit power configured for 30 dBm + # - Minimum supported bit rate is 11 Mbps + # - Auto channel selection is left at the default of channels 1, 3, & 11. + # - Keeps 802.11ax enabled + # - Receiver Start of Packet (RX-SOP) not defined (null) + # + # - For the 5 GHz RF band the settings are left at their defaults which depend on + # the regulatory domain where the AP is operating. For example for the U.S. + # regulatory domain (-B) the following are the defaults. + # - Minimum transmit power configured for 8 dBm + # - Maximum transmit power configured for 30 dBm + # - Minimum supported bit rate is 12 Mbps + # - Auto channel selection is configured to the following channels 36, 40, 44 48, + # 52, 56 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, + # 149, 153, 157, 161, and 165. + # - Channel width is set to auto + # - Receiver Start of Packet (RX-SOP) not defined (null) + # + # - For the 6 GHz RF band the settings are left at their defaults which depend on + # the regulatory domain where the AP is operating. For example for the U.S. + # regulatory domain (-B) the following are the defaults. + # - Minimum transmit power configured for 8 dBm + # - Maximum transmit power configured for 30 dBm + # - Minimum supported bit rate is 12 Mbps + # - Auto channel selection is configured to the following + # channels 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45 49, 53, 57 61, 65, 69, 73, + # 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, + # 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, + # 209, 213, 217, 221, 225, 229, 233 + # - Channel width is set to 0 (auto) + # - Receiver Start of Packet (RX-SOP) not defined (null) + # + # - Enables radio transmission. + # + # - Sets the RF profile as the default indoor profile. + # + # Please refer to the following URL and associated URLs for a full definition of the + # parameters available within an RF Profile: + # + # https://netascode.cisco.com/docs/data_models/meraki/networks_wireless/ssid_settings/ssid_base/ + # + # ssid: The SSIDs section hardcodes two SSIDs - Data (SSID 0) and Guest (SSID 1). + # + # - For the Data SSID: + # - The name of the SSID is defined as a variable (although it + # will be referred to as the Data SSID within this document). + # + # - All SSIDs are hardcoded to be enabled, advertised on all APs, + # and visible in beacons for the small branch design. + # + # - Authentication mode is set to 802.1x / WPA-EAP authentication + # via an external Radius server. Radius Accounting is enabled. + # The first Radius and Radius Accounting servers (host, port, + # and secret) are defined as variables. Additional servers can + # be added by modifying the YAML code. If multiple Radius and + # Radius Accounting servers are added, load-balancing is round-robin. + # If the Radius servers are unavailable access is denied. + # + # - Wi-Fi Protected Access (WPA) encryption mode is set for WPA + # Transition Mode. 802.11w Management Frame Protection (dot11w) + # is enabled but not mandatory, allowing for support for WPA3 + # with backward compatibility for WPA2. + # + # - VLAN tagging is enabled with the assignment of the VLAN to which + # the Data SSID is assigned hardcoded to VLAN 10. The Radius server + # overrides the default VLAN ID assigned to the Data SSID via group policy + # returned through the Filter-Id attribute. This is used to assign the + # VLAN to which wireless clients are assigned once authenticated. + # + # - 802.11r Fast Transition (dot11r) and Radius Change of Authorization (coa) + # are mutually exclusive for the version of wireless firmware which this + # document is currently based on. For the Data SSID, 802.11r Fast + # Transition has been enabled and Radius CoA disabled. Should CoA be + # desired, simply reverse the settings within the YAML code for the + # Data SSID. Future wireless firmware versions will support simultaneously + # enabling both parameters. + # + # - Per-client and per-SSID rate limits do not appear within the YAML + # configuration - meaning they are set to the default which is unlimited + # (no rate-limiting). + # + # - Traffic shaping is enabled on the Data SSID, using the 4 default traffic shaping + # rules. No Layer 7 firewall rules section appears within the YAML, since no + # no Layer 7 firewall rules have been defined for the small branch design. Should + # Layer 7 firewall rules be desired, the YAML code can be modified to add this + # section. + # + # - Wireless clients on the Data SSID are allowed to communicate with eachother and + # with wired clients on the LAN. + # + # - IP address assignment for wireless clients is via DHCP server (bridged mode), + # although not explicitely configure to be mandatory. + # + # - Enabling / disabling SSID availability via a schedule is configured as a variable. + # If enabled, the example schedule within the YAML code provides a basic example + # which can be modified to meet requirements. + # + # - For the Guest SSID: + # - The name of the SSID is defined as a variable (although it + # will be referred to as the Guest SSID within this document). + # + # - All SSIDs are hardcoded to be enabled, advertised on all APs, + # and visible in beacons for the small branch design. + # + # - Authentication mode is set to open (no encryption). + # + # - VLAN tagging is enabled with the assignment of the VLAN to which + # the Guest SSID is hardcoded to be VLAN 50. + # + # - Per-client and per-SSID rate limits are defined as variables + # within the YAML for the Guest SSID. + # + # - Traffic shaping is enabled on the Guest SSID, using the 4 default traffic shaping + # rules. No Layer 7 firewall rules section appears within the YAML, since no + # no Layer 7 firewall rules have been defined for the small branch design. Should + # Layer 7 firewall rules be desired, the YAML code can be modified to add this + # section. + # + # - Wireless clients on the Guest SSID are not allowed to communicate with eachother + # or with wired clients on the LAN. + # + # - IP address assignment for wireless clients is via DHCP server (bridged mode), + # and also explicitely configure to be mandatory. + # + # - Enabling / disabling SSID availability via a schedule is configured as a variable. + # If enabled, the example schedule within the YAML code provides a basic example + # which can be modified to meet requirements. + # + # - A click-through splash-page is enabled for guest traffic with a variable defined + # for the splash-page welcome message. + # + # - Enabling / disabling SSID availability via a schedule is configured as a variable. + # If enabled, the example schedule within the YAML code provides a basic example + # which can be modified to meet requirements. + # + # Please refer to the following URL and associated URLs for a full definition of the + # parameters available within an SSID: + # + # https://netascode.cisco.com/docs/data_models/meraki/networks_wireless/ssid_settings/ssid_base/ + # + - name: wireless + wireless: + settings: + upgrade_strategy: minimizeUpgradeTime + meshing: false + rf_profiles: + - name: Corp wireless rf profile + band_selection_type: ssid + is_indoor_default: true + min_bitrate_type: band + per_ssid_settings: + - ssid_name: ${guest_wireless_ssid_name} + band_operation_mode: dual + band_steering: true + bands: + - "2.4" + - "5" + - ssid_name: ${data_wireless_ssid_name} + band_operation_mode: dual + band_steering: true + bands: + - "2.4" + - "5" + - "6" + transmission: true + ssids: + - name: ${data_wireless_ssid_name} + auth_mode: 8021x-radius + available_on_all_aps: true + band_selection: Dual band operation with Band Steering + default_vlan_id: 10 + dot11r: + enabled: true + dot11w: + enabled: true + required: false + enabled: true + encryption_mode: wpa-eap + firewall_l3_firewall_rules: + allow_lan_access: true + ip_assignment_mode: Bridge mode + lan_isolation: false + radius: + accounting: true + accounting_servers: + - host: ${radius_accounting_server1_host} + port: 1813 + secret: !env radius_accounting_server1_secret + - host: ${radius_accounting_server2_host} + port: 1813 + secret: !env radius_accounting_server1_secret + attribute_for_group_policies: Filter-Id + coa: false + override: true + servers: + - host: ${radius_server1_host} + port: 1812 + secret: !env radius_server1_secret + - host: ${radius_server2_host} + port: 1812 + secret: !env radius_server1_secret + testing: true + unavailability_schedules: + enabled: ${data_ssid_schedules_enabled} + ranges: + - start_day: Sunday + start_time: 00:00:00 + end_time: 06:00:00 + end_day: Sunday + - start_day: Saturday + start_time: 00:00:00 + end_time: 06:00:00 + end_day: Saturday + ssid_number: '0' + traffic_shaping_rules: + traffic_shaping: true + default_rules: true + use_vlan_tagging: true + visible: true + wpa_encryption_mode: WPA3 Transition Mode + - name: ${guest_wireless_ssid_name} + auth_mode: open + available_on_all_aps: true + band_selection: Dual band operation + default_vlan_id: 50 + enabled: true + firewall_l3_firewall_rules: + allow_lan_access: false + ip_assignment_mode: Bridge mode + lan_isolation: true + mandatory_dhcp: true + per_client_bandwidth_limit_down: ${guest_wireless_client_bw_down} + per_client_bandwidth_limit_up: ${guest_wireless_client_bw_up} + per_ssid_bandwidth_limit_down: ${guest_wireless_ssid_bw_down} + per_ssid_bandwidth_limit_up: ${guest_wireless_ssid_bw_up} + unavailability_schedules: + enabled: ${guest_ssid_schedules_enabled} + ranges: + - start_day: Sunday + start_time: 00:00:00 + end_time: 06:00:00 + end_day: Sunday + - start_day: Saturday + start_time: 00:00:00 + end_time: 06:00:00 + end_day: Saturday + splash_page: Click-through splash page + splash_settings: + welcome_message: ${guest_ssid_welcome_message} + ssid_number: '1' + traffic_shaping_rules: + traffic_shaping: true + default_rules: true + use_vlan_tagging: true + visible: true diff --git a/docs/Device_Onboarding_Flow.md b/docs/Device_Onboarding_Flow.md new file mode 100644 index 0000000..0f8d71c --- /dev/null +++ b/docs/Device_Onboarding_Flow.md @@ -0,0 +1,349 @@ +# Dashboard Device Initial Onboarding Flow and Best Practices + +## Overview + +This document explains the Meraki device initial onboarding process and demonstrates best practice VLAN design, specifically covering the migration from VLAN 1 (onboard) to VLAN 999 (management) and the integration with Auto VPN for centralized DHCP services. This applies to all Meraki devices including switches (MS), access points (MR), cameras (MV), and sensors (MT). + +## Example VLAN Structure and Purpose + +| VLAN | Name | Purpose | DHCP Source | +|------|------|---------|-------------| +| 1 | Onboard | Initial device connectivity and dashboard registration | Local MX | +| 10 | Data | Corporate user traffic | Local MX or Central | +| 20 | Voice | Corporate Voice traffic | Local MX or Central | +| 30 | IOT | IoT device traffic | Local MX or Central | +| 50 | Guest | Guest network traffic | Local MX | +| 999 | MGMT | Management traffic after configuration pull | Local MX or Central DHCP via Auto VPN | + +## Initial Device Onboarding Process + +### Phase 1: Initial Connection (VLAN 1 - Onboard) + +1. **Power On and Default Behavior** + - New Meraki device powers on with factory defaults + - Device initially operates on VLAN 1 (native/untagged) + - Device attempts DHCP discovery on VLAN 1 + +2. **Dashboard Registration** + - Device obtains IP address from MX DHCP on VLAN 1 + - Establishes internet connectivity through MX VLAN 1 + - Contacts Meraki Dashboard for initial configuration via HTTPS Encrypted Connection + - Downloads network configuration and policies + +3. **Configuration Download** + - Device pulls its specific configuration from Dashboard assuming it has been claim and assigned to a network + - Device-specific configurations, VLAN assignments, and management settings downloaded + - Management VLAN setting retrieved (configured as VLAN 999) + +### Phase 2: Management VLAN Migration (VLAN 1 β†’ VLAN 999) + +1. **Management VLAN Activation** + - Device applies new configuration with management VLAN set to VLAN 999 + - Device initiates DHCP discovery on VLAN 999 + - VLAN 999 traffic routes through Auto VPN to central DHCP server + +2. **IP Address Assignment** + - Central DHCP server (in DC) assigns management IP to device + - DHCP reservation based on device MAC address + - Device maintains connectivity to Dashboard via VLAN 999. Note although DHCP address is obtained from central DHCP server, the route to dashboard can either be via the Auto-VPN or via local breakout of the MX internet interface. + +3. **Operational State** + - Device management now operates exclusively on VLAN 999 + - VLAN 1 DHCP services can be disabled if not required until new device onboarding + - All Dashboard communication occurs via VLAN 999 management interface + +## Device-Specific Management VLAN Configuration + +### Switches (MS Series) +**Dashboard Location**: `Switch > Configure > Switch Settings > Management VLAN` +- **Network-wide**: `Switch > Configure > Switch Settings > Management VLAN` +- **Per-device**: Individual switch configuration page +- **Template Support**: Full template support available +- **Best Practice**: Configure via switch template for consistency + +### Access Points (MR Series) +**Dashboard Location**: `Wireless > Configure > Access Points > [Select AP] > Management` +- **Network-wide**: `Wireless > Configure > Access Points > Management VLAN` +- **Per-device**: Individual AP configuration page +- **Template Support**: Limited template support +- **Best Practice**: Set network-wide default, override individually if needed + +### Cameras (MV Series) +**Dashboard Location**: `Cameras > Configure > Cameras > [Select Camera] > Settings` +- **Network-wide**: `Cameras > Configure > Video Settings > Management VLAN` +- **Per-device**: Individual camera configuration page +- **Template Support**: Basic template support +- **Best Practice**: Configure network-wide default for new deployments + +### Sensors (MT Series) +**Dashboard Location**: `Environmental > Configure > Sensors > [Select Sensor] > Settings` +- **Network-wide**: `Environmental > Configure > Settings > Management VLAN` +- **Per-device**: Individual sensor configuration page +- **Template Support**: Limited template support +- **Best Practice**: Set at network level for simplicity + +## Device Behavior by Platform Type + +### Switches (MS/Catalyst Series) + +#### Auora 1 +- **VLAN Snooping**: Requires VLAN 1 snooping to be explicitly enabled +- **Behavior**: Must have active VLANs configured before deployment +- **Limitation**: Cannot auto-discover VLANs, requires pre-configuration +- **Best Practice**: Configure management VLAN before deployment + +#### Auora 2 +- **VLAN Snooping**: Looks only for active VLANs first +- **Fallback Behavior**: If no active VLANs detected, starts snooping VLAN 1-1000 +- **Intelligence**: More adaptive than Auora 1, better auto-discovery +- **Best Practice**: Can be deployed with minimal pre-configuration + +#### Meraki Native +- **VLAN Snooping**: Will snoop all VLANs automatically +- **Behaviour**: Starts with VLAN 1-1000 by default +- **Intelligence**: Highest level of auto-discovery and adaptation +- **Best Practice**: Zero-touch deployment capable + +### Access Points (MR Series) +- **VLAN Discovery**: Automatic VLAN detection and adaptation +- **Fallback**: Always falls back to VLAN 1 if configured management VLAN unavailable +- **Bridge vs Router Mode**: Behavior consistent across both modes +- **Best Practice**: Zero-touch deployment supported + +### Cameras (MV Series) +- **VLAN Discovery**: Automatic detection with VLAN 1 fallback +- **Behavior**: Similar to access points, robust VLAN discovery +- **Power Considerations**: PoE+ requirements may affect initial connectivity +- **Best Practice**: Ensure adequate PoE budget for initial onboarding + +### Sensors (MT Series) +- **VLAN Discovery**: Basic VLAN detection capabilities +- **Behavior**: Simple onboarding process, inherits network settings +- **Power**: Low power requirements, typically PoE compatible +- **Best Practice**: Minimal configuration required + +## Auto VPN and Central DHCP Integration + +### Auto VPN Configuration + +1. **Spoke Configuration (Branch Sites)** + ``` + MX Spoke Configuration: + - Auto VPN enabled as Spoke + - VLAN 999 routing to Hub via VPN + - No local DHCP for VLAN 999 + - DHCP relay enabled for VLAN 999 to Central DHCP Server + - Route propagation enabled for VLAN 999 + - Either VLAN 999 uses Auto VPN or local breakout of the MX internet interface to reach the Central DHCP Server + ``` + +### DHCP Reservation Strategy + +1. **Central DHCP Server Setup** + - Windows DHCP or applicable IPAM solution in data center + - VLAN 999 scope (e.g., 10.2.0.0/24) + - Reservations based on device MAC addresses + - Optional dhcp assignment based on client identifier + - DHCP options for DNS, NTP, and management services + +2. **Reservation Examples** + ``` + # Switch Example + Switch Model: MS390-24P + MAC Address: 00:18:0a:12:34:56 + Reserved IP: 10.2.0.101 + Hostname: SW-BRANCH01-IDF01 + + # Access Point Example + AP Model: MR57 + MAC Address: 00:18:0a:78:9a:bc + Reserved IP: 10.2.0.201 + Hostname: AP-BRANCH01-FL02 + + # Camera Example + Camera Model: MV12W + MAC Address: 00:18:0a:de:f1:23 + Reserved IP: 10.2.0.301 + Hostname: CAM-BRANCH01-LOBBY + + # Sensor Example + Sensor Model: MT10 + MAC Address: 00:18:0a:45:67:89 + Reserved IP: 10.2.0.401 + Hostname: SENS-BRANCH01-SERVER + ``` + +## Best Practice Implementation Guide + +### Pre-Deployment Configuration + +1. **Dashboard Network Setup** + ``` + Network Settings: + - Create network + - Configure VLAN 999 as management VLAN for all device types + - Set device templates with VLAN 999 management (switches, APs) + - Configure network-wide management VLAN for cameras and sensors + - Configure Auto VPN settings + ``` + +2. **MX Base Configuration** + ``` + MX Security Appliance: + - VLAN 1: 192.168.128.0/24 ( default onboarding) + - VLAN 999: Routed via Auto VPN to DC + - DHCP enabled on VLAN 1 + - DHCP relay enabled for VLAN 999 to Central DHCP Server + - Auto VPN enabled as Spoke with Hub site pre-configured + - Route All VLAN 999 traffic via VPN tunnel or optionally only management services via VPN tunnel, with dashboard connectivity via local breakout of the MX internet interface + ``` + +3. **Central DHCP Server Configuration** + ``` + Central DHCP Server: + - VLAN 999 scope (e.g., 10.2.0.0/24) + - Reservations based on device MAC addresses + - Optional dhcp assignment based on client identifier + - DHCP options for DNS, NTP, and management services + ``` + +### Deployment Process + +1. **Physical Installation** + - Esnure MX is stable and online and has the MX Base Configuration applied. + - Connect device to the network (switch port or PoE+ for cameras) + - Ensure device can reach VLAN 1 for initial onboarding + - Power on device and wait for Dashboard connection and ensure that the light on the device is solid green. + - Verify device appears in Dashboard inventory + +2. **Configuration Application** + - Device automatically pulls configuration + - Monitor management IP assignment on VLAN 999 + - Verify Auto VPN tunnel connectivity + - Confirm central DHCP reservation + +3. **Validation** + + - Verify management connectivity for all device types either by pinging there address from the central NMS or by logging into the dashboard and pinging the management IP. + Navigate to: Inventory > [Select Device] > Management IP + + - Check Auto VPN status in Dashboard + Navigate to: Security & SD-WAN > Monitor > VPN status + + - Validate DHCP leases in central server + Check DHCP server for all active device leases + + - Device-specific validation + - Switches: Check port status and VLAN assignments + - APs: Verify wireless network broadcasting + - Cameras: Confirm video streaming functionality + - Sensors: Check environmental data reporting + This assumes that all additional configuration has been completed. + ``` + +## Troubleshooting Common Issues + +### Device Cannot Contact Dashboard + +1. **VLAN 1 Connectivity Issues** + - Verify MX DHCP is functioning on VLAN 1 + - Check internet connectivity from MX + - Ensure Dashboard access isn't blocked by an upstream firewall + +2. **Management VLAN Issues** + - Verify VLAN 999 is properly configured in Dashboard for specific device type + - Check Auto VPN tunnel status + - Validate central DHCP server accessibility + - Confirm device-specific management VLAN settings are applied + +### Auto VPN Connectivity Problems + +1. **Tunnel Establishment** + - Verify MX can reach Meraki cloud + - Check NAT/firewall rules for VPN traffic + - Validate MX licensing and organization membership + +2. **DHCP Relay Issues** + - Ensure VLAN 999 routes properly via VPN + - Check DHCP relay configuration on hub MX + - Validate DHCP server is responding to remote subnets + +## Security Considerations + +### Management VLAN Isolation +- VLAN 999 should be isolated from user traffic +- Implement access control lists limiting management access +- Use dedicated management subnet with controlled routing + +Please note that VRF is not currently supported on the MX and as such the management VLAN is not isolated from user traffic. + +### Network Segmentation +- Separate management traffic from production traffic +- Implement VLAN-based security policies or Adaptive Policy +- Monitor management traffic for anomalies + + +## Summary + +The Meraki device onboarding flow leveraging VLAN 1 for initial connectivity and VLAN 999 for management provides a robust, scalable approach to comprehensive network infrastructure management. This design pattern works consistently across all dashboard supporteddevice types - switches (MS/Catalyst), access points (MR/Catalyst), cameras (MV), and sensors (MT) - and combined with Auto VPN and central DHCP services, enables zero-touch deployment while maintaining centralized control and security. + +The key benefits of this approach include: +- **Unified Deployment**: All devices (switches, APs, cameras, sensors) follow the same onboarding pattern +- **Centralized Management**: Comprehensive device management from central DHCP and Dashboard +- **Scalability**: Consistent deployment process across all sites and device types +- **Security**: Management traffic isolated and controlled for entire infrastructure +- **Simplified Operations**: Single management VLAN strategy reduces complexity + +By following these best practices and understanding the device-specific behaviors, organizations can implement a robust, comprehensive Meraki infrastructure that includes switching, wireless, security cameras, and environmental monitoring - all managed through a unified approach that scales efficiently and maintains security standards. + +## References + +### Official Cisco Meraki Documentation + +#### Switch Documentation +1. **Switch Settings - Cisco Meraki Documentation** + *Management VLAN configuration and initial setup procedures* + https://documentation.meraki.com/MS/Other_Topics/Switch_Settings + +2. **General MS Best Practices - Cisco Meraki Documentation** + *Native VLAN and trunk configuration recommendations* + https://documentation.meraki.com/Architectures_and_Best_Practices/Cisco_Meraki_Best_Practice_Design/Best_Practice_Design_-_MS_Switching/General_MS_Best_Practices + +#### Access Point Documentation +3. **MR Access Point Settings - Cisco Meraki Documentation** + *Management VLAN configuration for wireless access points* + https://documentation.meraki.com/MR/Other_Topics/MR_Access_Point_Settings + +4. **Wireless LAN Best Practices - Cisco Meraki Documentation** + *Deployment and management VLAN recommendations for wireless* + https://documentation.meraki.com/Architectures_and_Best_Practices/Cisco_Meraki_Best_Practice_Design/Best_Practice_Design_-_MR_Wireless + +#### Camera Documentation +5. **MV Camera Settings - Cisco Meraki Documentation** + *Management VLAN and network configuration for security cameras* + https://documentation.meraki.com/MV/Other_Topics/MV_Camera_Settings + +6. **Video Best Practices - Cisco Meraki Documentation** + *Network requirements and VLAN considerations for video* + https://documentation.meraki.com/Architectures_and_Best_Practices/Cisco_Meraki_Best_Practice_Design/Best_Practice_Design_-_MV_Security_Cameras + +#### Sensor Documentation +7. **MT Sensor Settings - Cisco Meraki Documentation** + *Management configuration for environmental sensors* + https://documentation.meraki.com/MT/Other_Topics/MT_Sensor_Settings + +#### Cross-Platform Documentation +8. **VLAN Profiles - Cisco Meraki Documentation** + *Zero-touch provisioning and VLAN management across all device types* + https://documentation.meraki.com/General_Administration/Cross-Platform_Content/VLAN_Profiles + +9. **Configuring VLANs on the MX Security Appliance - Cisco Meraki Documentation** + *VLAN configuration and routing setup for MX devices* + https://documentation.meraki.com/MX/Networks_and_Routing/Configuring_VLANs_on_the_MX_Security_Appliance + + +--- + +*Document Version: 2.0* +*Last Updated: November 3, 2025* +*Author: Jon Humphries* diff --git a/docs/Readme.md b/docs/Readme.md index 7d30656..97f4fa2 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -1,106 +1,104 @@ -# Unified Branch - Branch as Code Design Guide: Release 1 - Early Availability # +# Cisco Unified Branch - Branch as Code Design Guide ## Overview ## -This initial release of Unified Branch - Branch as Code (referred to as Release 1, Early Availability), is intended to introduce the provisioning of branch network infrastructure (security appliances, switches, and Wi-Fi access points) wholistically using Network as Code (NAC) concepts, practices, and procedures. To ease the amount of learning involved in adopting Network as Code as a means of configuring branch network infrastructure, a very basic and highly prescriptive branch network design has been developed, tested, and documented for this initial release. +Please refer to the [Cisco Unified Branch CVD](https://www.cisco.com/c/en/us/td/docs/solutions/CVD/Campus/Cisco_Unified_Branch_Small_Branch.html) for an in-depth discussion of initial release of Cisco Unified Branch. Branch as Code and Workflows are both part of the overall automation toolkit for Cisco Unified Branch. This document focuses on the automation of Cisco Unified Branch through Branch as Code. -The intent of Release 1 - Early Availability is to allow Cisco customers and partners to utilize this repository to rapidly become familiar with the concepts, practices, and procedures necessary to adopt Network as Code - in a non-production test environment - and to provide feedback to Cisco. +Branch as Code is intended to introduce the provisioning of branch network infrastructure (secure routers, switches, and Wi-Fi access points) holistically using Network as Code (NAC) concepts, practices, and procedures. To ease the amount of learning involved in adopting Network as Code as a means of configuring branch network infrastructure, a standardized network design has been developed, tested, and documented. ## Network Design ## -Release 1 - Early Availability supports a single network design for small branch sites only. The small branch network design consists of the following components: +The initial release of Cisco Unified Branch - Branch as Code supports a standard network design for small branch sites. The small branch network design consists of the following components: -- 1 x MX-85 security appliance -- 1 x C9300L-24P-4X or C9300L-48P-4X switch -- 2 x CW-9176I Wi-Fi Access Points (APs) +- 1 x Secure Router - *MX67/MX68/MX85/MX95/MX105 secure router + +- 1 x switch or switch stack - C9300/X/L (-M versions), C9200/L (-M versions), or MS150/MS130 + +- N x Wi-Fi Access Points (APs) - CW9172 or CW9176 + +*Only base MX67/MX68 (non-W/CW versions) are supported. + +Please refer to the [Cisco Unified Branch CVD](https://www.cisco.com/c/en/us/td/docs/solutions/CVD/Campus/Cisco_Unified_Branch_Small_Branch.html) for specific software versions supported. The physical layout of the small branch design is shown below. **Figure 1. Small Branch Design** -![Small Branch](images/small-branch.png) +![Small Branch](images/unified_branch_architecture_small_branch.png) -### Small Branch Security Appliance ### -For Release 1 - Early Availability, the small branch network supports a single MX-85 security appliance for WAN connectivity. The physical connectivity of the MX-85 ports is shown in the following table. +### Small Branch Secure Router ### +The small branch network supports a single MX67, MX68, MX85, MX95, or MX105 secure router (also referred to as an appliance or secure appliance within the files and templates within this repository) for WAN connectivity. The physical connectivity of each of the ports for each model is shown in the following table. -**Table 1. MX-85 Security Appliance Physical Ports** +**Table 1. MX Secure Router Physical Ports** -![MX-85 Ports](images/mx-85-ports.png) +![MX Secure Router Ports](images/mx-secure-router-ports.png) #### WAN Connectivity #### -The physical ports which map to the logical WAN 1 and WAN 2 interfaces depend upon whether SFP modules are inserted into the appliance, as discussed in the [WAN Behavior on MX75/85/95/105](https://documentation.meraki.com/MX/MX_Overviews_and_Specifications/WAN_Behavior_on_MX75%2F%2F85%2F%2F95%2F%2F105) document. +For the MX85/95/105 platforms, the physical ports which map to the logical WAN 1 and WAN 2 interfaces depend upon whether SFP modules are inserted into the secure router, as discussed in the [WAN Behavior on MX75/85/95/105](https://documentation.meraki.com/MX/MX_Overviews_and_Specifications/WAN_Behavior_on_MX75%2F%2F85%2F%2F95%2F%2F105) document. When SFP modules are inserted into the MX85/95/105 secure router for WAN connectivity, the logical WAN 1 and WAN 2 interfaces correspond to physical ports 1 and 2, respectively. When SFP modules are not inserted into the appliance, the WAN 1 and WAN 2 interfaces correspond to physical ports 3 and 4, respectively. Hence for small branch deployments, network administrators must first determine whether they will be using SFP modules for WAN connectivity. Once that decision is made, physically connect port 1 (SFP) or port 3 (RJ45) to the first WAN service provider network (WAN 1) and either port 2 (SFP) or port 4 (RJ45) to the second WAN service provider network (WAN 2). -When SFP modules are inserted into the MX-85 security appliance for WAN connectivity, the logical WAN 1 and WAN 2 interfaces correspond to physical ports 1 and 2, respectively. When SFP modules are not inserted into the appliance, the WAN 1 and WAN 2 interfaces correspond to physical ports 3 and 4, respectively. Hence for small branch deployments, network administrators must first determine whether they will be using SFP modules for WAN connectivity. Once that decision is made, physically connect port 1 (SFP) or port 3 (RJ45) to the first WAN service provider network (WAN 1) and either port 2 (SFP) or port 4 (RJ45) to the second WAN service provider network (WAN 2). Note that the MX-85 supports only 1 Gbps Ethernet SFP or RJ45 WAN connections. - -For Release 1 - Early Availability, a single WAN uplink connected to port 3 of the MX-85 security appliance was configured and tested. The WAN 1 interface was configured for IPv4 only (no IPv6) with dynamic IP addressing (DHCP). +The MX67/68 platforms do not support SFP modules. The MX68 supports up to two Ethernet RJ45 WAN connections (Ports 1 & 2). The MX67 supports the conversion of Port 2 from a LAN to a WAN port, for up to two Ethernet RJ45 WAN connections (Ports 1 & 2). #### LAN Connectivity #### -The range of LAN ports on the MX-85 security appliance is from Port 5 - 14. Ports 5 - 12 support 1 Gbps Ethernet RJ45 connectivity, while Ports 13 & 14 support 1 Gbps Ethernet SFP (optical) connectivity. +The range of LAN ports available depends on the secure router model. For the MX85 the LAN port range is from Ports 5 - 14. Ports 5 - 12 support Ethernet RJ45 connectivity, while Ports 13 & 14 support SFP (optical) connectivity. For the MX95 and MX105 platforms, the LAN port range is from 5 - 10. Ports 5 - 8 support Ethernet RJ45 connectivity, while Ports 9 & 10 support SFP+ (optical) connectivity. For the MX67, assuming Port 2 is converted to a WAN interface for dual-WAN connectivity, the LAN port range is from Ports 3 -5 which support Ethernet RJ45 connectivity. Finally, for the MX68, the LAN port range is from Ports 3 - 12, which support Ethernet RJ45 connectivity. Note that Ports 11 & 12 support PoE+, which may be best utilized for connectivity to APs. -All devices downstream of an MX security appliance must be able to reach the Cisco Cloud (formerly known as the Meraki Cloud) to be onboarded to the network. To facilitate this, MX security appliances automatically configure VLAN 1 with an IPv4 subnet of 192.168.128.0/24. The VLAN 1 IP address of the MX security appliance is automatically configured to be 192.168.128.1/24. A DHCP pool is also automatically configured to hand out the remaining IPv4 addresses in the 192.168.128.2 - 254 range to downstream devices. All LAN ports of the MX security appliance are by default placed into VLAN 1, because the MX security appliance by default is configured for single VLAN (VLAN 1) operation. +All devices downstream of an MX secure router must be able to reach the Cisco Cloud (formerly known as the Meraki Cloud) to be onboarded to the network. To facilitate this, MX secure routers automatically configure VLAN 1 with an IPv4 subnet of 192.168.128.0/24. The VLAN 1 IP address of the MX secure router is automatically configured to be 192.168.128.1/24. A DHCP pool is also automatically configured to hand out the remaining IPv4 addresses in the 192.168.128.2 - 254 range to downstream devices. All LAN ports of the MX secure router are by default placed into VLAN 1, because the MX secure router by default is configured for single VLAN (VLAN 1) operation. -When a cloud enabled downstream switch is connected to the MX security appliance and is initially booted, all switch ports will, by default, be part of VLAN 1. The switch will initiate DHCP requests for an IP address on all connected interfaces. The switch will receive an IPv4 address in the 192.168.128.2 - 254 address range from the MX security appliance. Likewise, when a downstream cloud managed wireless AP is subsequently connected to the switch and is initially booted, the AP will initiate DHCP requests for an IP address on its uplink port. The AP will receive an IPv4 address in the 192.168.128.2 - 254 range from the MX security appliance. The MX security appliance firewall is, by default, configured to allow all outbound traffic to the Internet initiated internally on VLAN 1, and to NAT the traffic to the IP address of the WAN interface. This allows the downstream switch and APs to connect to the Cisco Cloud. +When a cloud enabled downstream switch is connected to the MX secure router and is initially booted, all switch ports will, by default, be part of VLAN 1. The switch will initiate DHCP requests for an IP address on all connected interfaces. The switch will receive an IPv4 address in the 192.168.128.2 - 254 address range from the MX secure router. Likewise, when a downstream cloud managed wireless AP is subsequently connected to the switch and is initially booted, the AP will initiate DHCP requests for an IP address on its uplink port. The AP will receive an IPv4 address in the 192.168.128.2 - 254 range from the MX secure router. The MX secure router firewall is, by default, configured to allow all outbound traffic to the Internet initiated internally on VLAN 1, and to NAT the traffic to the IP address of the WAN interface. This allows the downstream switch and APs to initially connect to the Cisco Cloud. -VLAN 1 on the MX security appliance can only be deleted if support for multiple VLANs is first enabled on the MX security appliance, and another VLAN with IP subnet is subsequently configured. However, the default 192.168.128.0/24 IPv4 subnet and corresponding DHCP pool address range for VLAN 1 can be changed without the requirement for enabling support for multiple VLANs on the MX security appliance. +VLAN 1 on the MX secure router can only be deleted if support for multiple VLANs is first enabled on the MX secure router, and another VLAN with IP subnet is subsequently configured. However, the default 192.168.128.0/24 IPv4 subnet and corresponding DHCP pool address range for VLAN 1 can be changed without the requirement for enabling support for multiple VLANs on the MX secure router. -Due to the need to smoothly onboard and maintain connectivity of downstream switches and APs to the Cisco Cloud, for Release 1 - Early Availability, the MX-85 security appliance uses the default configuration of VLAN 1 for handing out IPv4 addresses to the downstream C9300L-24P-4X or C9300L-48P-4X switch and CW9176I APs. VLAN 1 is used solely as an Infrastructure VLAN to allow the switch and APs downstream of the MX security appliance to receive IP addresses and connect to the Meraki Cloud, so these devices can be configured and managed. +Due to the need to smoothly onboard and maintain connectivity of downstream switches and APs to the Cisco Cloud, for Cisco Unified Branch - Branch as Code, the MX secure router uses the default configuration of VLAN 1 for initially handing out IPv4 addresses to the downstream switches and APs when they are unconfigured and initially connecting to the network. Once the devices have established connectivity to the Cisco Cloud, they will receive their configurations which change the management VLAN to the Infra VLAN (VLAN 999). This VLAN is carried across the Auto VPN to the hub site. This design allows for monitoring traffic, such as SNMP, Syslog, and NetFlow to be originated from the branch network infrastructure devices and sent to centralized servers at hub locations. VLAN 1 is used solely to onboard devices to the Cisco Cloud when unconfigured or reset to an unconfigured state. -Note that since VLAN 1 is automatically configured within the MX security appliance, it will not appear within the YAML configuration files within the *data* folder. Work is ongoing to import the VLAN 1 configuration for visibility in the YAML configuration files. +Note that since VLAN 1 is automatically configured within the MX secure router, it will not appear within the YAML configuration files within the */data* folder. Work is ongoing to import the VLAN 1 configuration for visibility in the YAML configuration files. -Also note that with this configuration, since all sites (networks) use the same default IPv4 subnet range of 192.168.128.0/24 for the Infrastructure VLAN, VLAN 1 cannot be distributed across the VPN fabric. Hence, the 192.168.128.0/24 IPv4 subnet range is local to each site / network only. +Also note that with this configuration, since all sites (networks) use the same default IPv4 subnet range of 192.168.128.0/24 for the Infrastructure VLAN, VLAN 1 cannot be distributed across the VPN fabric. Hence, the 192.168.128.0/24 IPv4 subnet range is local to each site / network only. However, the IPv4 subnet range of the Infra VLAN (VLAN 999) is unique for each branch and hence routeable to the hub sites. -The following are the constraints of the decision to maintain the default VLAN 1 configuration for Release 1 - Early Availability: +The following are the constraints of the decision to maintain the default VLAN 1 configuration: -- The small branch design requires the MX security appliance to be configured to support multiple VLANs. Since VLAN 1 is always used as an Infrastructure VLAN, any customer traffic will need to be part of another VLAN. -- The port connecting the MX security appliance to the downstream switch must be configured as a trunk port with the native VLAN being the default of VLAN 1. +- The small branch design requires the MX secure router to be configured to support multiple VLANs. Since VLAN 1 is always used as an Infrastructure VLAN, any customer traffic will need to be part of another VLAN. +- The port connecting the MX secure router to the downstream switch must be configured as a trunk port with the native VLAN being the default of VLAN 1. - The ports connecting the switch to downstream cloud managed APs must be configured as trunk ports with the native VLAN being the default of VLAN 1. -The Release 1 - Early Availability YAML configuration files (found within the /data directory of this repository) hardcode three additional VLANs – Data (VLAN 10), Voice (VLAN 20), and Guest (VLAN 30). - -As of the 19.1.x firmware release, MX security appliances do not support link aggregation (otherwise known as EtherChannel) of LAN ports for connectivity between an MX security appliance and a switch or switch stack. MX security appliances also do not support the concept of a logical Port Channel interface or spanning-tree protocol (STP). +The YAML configuration files (found within the /data directory of this repository) hardcode four additional VLANs – Data (VLAN 10), Voice (VLAN 20), IoT (VLAN 30), and Guest (VLAN 50). -For Release 1 - Early Availability, a single 1 Gbps Ethernet RJ45 connection configured as a trunk interface supporting VLANs 1, 10, 20, and 30 – corresponding to the Infrastructure, Data, Voice, and Guest VLANs – was provisioned between the MX-85 security appliance and the C9300L-24P-4X or C9300L-48P-4X switch. Port 5 of the MX-85 security appliance was connected to Port 1 of the switch. No redundancy of connectivity between the MX-85 security appliance and the switch was tested or validated. +As of the 19.1.x firmware release, MX secure routers do not support link aggregation (otherwise known as EtherChannel) of LAN ports for connectivity between an MX secure router and a switch or switch stack. MX secure routers also do not support the concept of a logical Port Channel interface or spanning-tree protocol (STP). -A single 1 Gigabit Ethernet RJ45 connection provides only 1 Gbps of bandwidth and no redundancy between the MX-85 security appliance and the switch. Depending upon the WAN transport speeds and the requirements for inter-VLAN routing within the branch, this may or may not be sufficient. For additional bandwidth, the following options may be possible. Note that these HAVE NOT BEEN VALIDATED for Release 1 - Early Availability. +The MX67 and MX68 platforms only support 1 Gbps Ethernet RJ45 connections between the MX secure router and switch or switch stack. The MX85 supports 1 Gbps Ethernet RJ45 or 1 Gbps SFP (optical) connections. However, the bandwidth per port is still limited to 1 Gbps. The MX95 and MX105 platforms support 1 Gbps Ethernet RJ45 connections as well, but also support 10 Gbps SFP+ (optical) connections. -- A single pair of redundant 1 Gbps Ethernet RJ45 or SFP connections configured as trunk ports supporting all VLANs. STP on the switch should put one of the connections into blocking mode, ensuring there are no loops between the switch or switch stack and the MX security appliance. This potential option addresses redundancy, but not additional bandwidth between the MX security appliance and the switch or switch stack. +When using an MX platform that only supports 1 Gbps RJ45 or SFP connections, a single connection, configured as a trunk port supporting all VLANs configured within the branch, provides only 1 Gbps of bandwidth and no redundancy between the MX secure router and the switch or switch stack. Depending upon the WAN transport speeds and the requirements for inter-VLAN routing within the branch, this may or may not be sufficient. For additional bandwidth, the following options may be possible. -- Multiple pairs of redundant 1 Gbps Ethernet RJ45 or SFP (optical) connections configured as trunk ports, each supporting a subset of the overall VLANs. STP on the switch will put one of the connections of each pair into blocking mode, ensuring there are no loops between the switch and the MX security appliance. This potential option addresses both redundancy and aggregate bandwidth across all VLANs (not per individual VLAN) between the MX security appliance and the switch or switch stack. +- A single pair of redundant 1 Gbps Ethernet RJ45 or SFP connections configured as trunk ports supporting all VLANs. STP on the switch should put one of the connections into blocking mode, ensuring there are no loops between the switch or switch stack and the MX secure router. This potential option addresses redundancy, but not additional bandwidth between the MX secure router and the switch or switch stack. -The use of SFP (optical) connectivity may also be needed in situations where the MX security appliance and the switch are physically separated from each other. Distances greater than 100 meters, or facilities where only fiber optic cabling exists between wiring closets may result in the use of the SFP ports. For Release 1 - Early Availability it is assumed that the MX-85 security appliance and switch are physically adjacent to each other, requiring only RJ45 wired connectivity. Hence, the physical port on the MX-85 security appliance is hard-coded in the YAML configuration files found within the *data* directory of this repository to port 1, rather than being assigned a variable which can be assigned by the end-user. +- Multiple pairs of redundant 1 Gbps Ethernet RJ45 or SFP (optical) connections configured as trunk ports, each supporting a subset of the overall VLANs. STP on the switch will put one of the connections of each pair into blocking mode, ensuring there are no loops between the switch and the MX secure router. This potential option addresses both redundancy and aggregate bandwidth across all VLANs (not per individual VLAN) between the MX secure router and the switch or switch stack. Note that this has not been validated or included as part of Unified Branch - Branch as Code for this release. -### Small Branch Switch ### -For Release 1 - Early Availability, a single C9300L-24P-4X or C9300L-48P-4X Layer 2 switch provides LAN connectivity to devices within the small branch. Physical port media and speeds, as well as Power over Ethernet (PoE) support for these models are shown in the table below. Both models support fixed 4 x 1/10Gbps SFP+ uplink ports. +The use of SFP (optical) connectivity may also be needed in situations where the MX secure router and the switch are physically separated from each other. Distances greater than 100 meters, or facilities where only fiber optic cabling exists between wiring closets may result in the use of the SFP ports. -**Table 2. C9300L-24P-4X and C9300L-48P-4X Physical Ports** +When using an MX platform which supports 10 Gbps SFP+ (optical) connections, you must ensure the switch model of the swith or switch stack you choose to deploy within the small branch also supports 10 Gbps SFP+ (optical) connections. -![C9300L Series Ports](images/c9300l-series-ports.png) +### Small Branch Switch / Switch Stack ### +For this release of Cisco Unified Branch - Branch as Code, a single switch or switch stack consisting of C9300/X/L (-M versions), C9200/L (-M versions), or MS150/MS130 switches provides LAN connectivity to devices within the small branch. All switches within a single stack should be the same model. -Support for PoE on switch ports may be needed when connecting wireless LAN (WLAN) APs, IP phones, surveillance cameras, and other devices to the switch. Both models support 802.3at / PoE+ (Type 2) which can supply up to 30W per port up to the total power budget for PoE devices of the switch. The total power budget for PoE devices depends on the number of power supplies installed within the switch, as well as the power rating of the individual power supplies (715 Watts AC vs. 1100 Watts AC), as shown in the table above. +Support for PoE on switch ports may be needed when connecting wireless LAN (WLAN) APs, IP phones, surveillance cameras, and other devices to switches. You must select switch models that support the necessary power per port for the devices you plan on using within the branch, as well as the overall power budget based on the number of such devices. The total power budget for PoE devices depends on the number of power supplies installed within the switch, as well as the power rating of the individual power supplies. -When a C9300L Series switch is managed by the Cisco Cloud (formerly known as the Meraki Cloud), the switch ports (or port_ids as they are referred to in the YAML configuration files within this repository) on the switch begin with port / port_id 1, and proceed up to the last port/port_id of the switch, including the uplinks which are typically the highest port / port_id numbers (25-29, 49-52, etc.). This is unlike switch configurations in traditional IOS-XE platforms, where the port numbering reflects the position of the switch in the switch stack, the module within the switch, and the port position on the switch. For instance, the first switch uplink port of a standalone IOS-XE switch would be referred to as port GigabitEthernet 1/1/1. +When C9300/X/L or C9200/L Series switches are managed by the Cisco Cloud (formerly known as the Meraki Cloud), the switch ports (or port_ids as they are referred to in the YAML configuration files within this repository) on the switch begin with port/port_id 1, and proceed up to the last port/port_id of the switch, including the uplinks which are typically the highest port/port_id numbers (25-29, 49-52, etc.). This is unlike switch configurations in traditional IOS-XE platforms, where the port numbering reflects the position of the switch in the switch stack, the module within the switch, and the port position on the switch. For instance, the first switch uplink port of a standalone IOS-XE switch would be referred to as port GigabitEthernet 1/1/1. -The link speed (10 Mbps, 100 Mbps, 1 Gbps, and/or 10 Gbps) and duplex (full or half) of the Ethernet ports on the MX security appliance and the C9300L Series switch must match for the uplink to come up active. A best practice is to leave the link speed for auto-negotiation of speed and duplex. +The link speed and duplex of the Ethernet ports on the MX secure router and the switches must match for the uplink to come up active. A best practice is to leave the link speed for auto-negotiation of speed and duplex. -802.1x authentication, MAC Authentication Bypass (MAB), or Meraki Secure Port are not currently supported on the uplink between the MX security appliance and the C9300L Series switch. Hence, a best practice is for the equipment to be in a secure area within the site, such as a wiring closet in which only authorized personnel are allowed to enter. +802.1x authentication, MAC Authentication Bypass (MAB), or Meraki Secure Port are not currently supported on the uplink between the MX secure router and the switch models supported for Unified Branch - Branch as Code. Hence, a best practice is for the equipment to be in a secure area within the site, such as a wiring closet in which only authorized personnel are allowed to enter. -To summarize, the uplink connectivity between the MX security appliance and the C9300L Series switch for Release 1 - Early Availability is as follows: +For Unified Branch - Branch as Code, uplink switch ports are configured as a trunk ports allowing VLANs 1, 10, 20, 30, 50, and 999 on the MX secure router with VLAN 1 being the native VLAN. This configuration allows switches to automatically acquire an IPv4 address in the 192.168.128.0/24 subnet from the MX secure router and connect to the Cisco (formerly Meraki) Cloud when initially deployed. Upon configuration, the management subnet of the switch is moved from VLAN 1 to VLAN 999. This allows monitoring flows such as SNMP, Syslog, and NetFlow to be initiated from the switches and sent over the Auto VPN tunnels to centralized servers. -- A single 1 Gbps RJ45 connection (Port 1) from the switch was connected to a 1 Gbps RJ45 connection (Port 5) of MX-85 security appliance. The SFP+ uplink ports of the C9300L Series switch were not utilized. -- Link speed and duplex of the uplink port were left to auto-negotiate. -- The switch port was configured as a trunk port allowing VLANs 1, 10, 20, and 30 on the MX security appliance and VLANs 1 - 100 on the switch - with VLAN 1 being the native VLAN. - -This configuration allowed the switch to automatically acquire an IPv4 address in the 192.168.128.0/24 subnet from the MX-85 security appliance and connect to the Cisco (formerly Meraki) Cloud. Note that the switch was initially manually configured via console connection to operate as a Cisco Cloud managed switch before being connected to the MX-85 security appliance. +Note that the switch may initially need to be manually configured via console connection to operate as a Cisco Cloud managed switch before being connected to the MX secure router. ### Small Branch WLAN Access Points ### -For Release 1 - Early Availability, two CW9176I cloud managed APs provided wireless LAN (WLAN) connectivity within the branch. The CW-9176I supports an omni-directional internal antenna. Physical port media and speeds, as well as PoE requirements for the CW-9176I are shown in the table below. +For Cisco Unified Branch - Branch as Code, cloud managed CW9172 or CW9176 APs provided wireless LAN (WLAN) connectivity within the branch. Physical port media and speeds, as well as PoE requirements for the AP models are shown in the table below. -**Table 3. CW9176I Physical Ports and PoE Requirements** +**Table 3. WLAN AP Physical Ports and PoE Requirements** -![CW9176I](images/cw9176i-ports.png) +![WLAN AP Ports](images/wlan-ap-ports.png) #### Uplink Connectivity to the Switch #### -The CW-9176I AP supports only a single uplink port for connectivity to the switch. As mentioned previously for Release 1 - Early Availability, VLAN 1 is used as an Infrastructure VLAN to ensure downstream switches and APs can connect to the Cisco Cloud to onboard. All VLANs with customer traffic (Data, Voice, and Guest) are configured as additional VLANs. This means that the connections between switches and APs must be configured as trunk ports. The native VLAN of the trunk ports should be configured for VLAN 1. +All WLAN AP models listed in the table above support only a single uplink port for connectivity to the switch. As mentioned previously, the default VLAN (VLAN 1) automatically configured on MX is used to initially ensure downstream unconfigured switches and APs can connect to the Cisco Cloud to onboard. All VLANs with customer traffic (Data, Voice, IoT, Infra, and Guest) are configured as additional VLANs. This means that the connections between switches and APs must be configured as trunk ports. The native VLAN of the trunk ports should be configured for VLAN 1. #### PoE Requirements for the Access Points #### When configuring the uplink between the switch and APs, the network administrator needs to consider how power is to be supplied to the APs. Power can be supplied via one of the following: @@ -111,52 +109,55 @@ When configuring the uplink between the switch and APs, the network administrato - External power supply which converts AC to DC connected directly to the AP. This is typically done via an AC outlet installed in proximity to the AP. -For Release 1 - Early Availability, the C9300L-24P-4X and C9300L-48P-4X switches support a maximum of 30W power per switch port. This is the method of providing power to the APs, since the power levels provided per switch port are sufficient for the CW-9176I AP when not using the USB port. +For Cisco Unified Branch - Branch as Code, the method which has been selected for providing power to the APs is via the switch ports. Therefore, you must select the model of switch such that there are sufficient switch ports, each with sufficient power (30W or 45W) to support all of the APs within your branch deployment. #### Throughput Requirements for the Access Points #### Aggregate 802.11 Wi-Fi throughput has exceeded 1 Gbps since 802.11ac came out years ago. However, this does not mean that the aggregate throughput requirements of each AP within a small branch site will exceed 1 Gbps. That depends on various factors such as the number of clients per AP, and each client’s particular application requirements. -If AP uplink speeds greater than 1 Gbps are required, then the network administrator must also consider whether the APs should be connected to switch ports which support Multi-Gigabit Ethernet (mGig) speeds of 2.5, 5, or 10 Gbps, or alternatively whether the APs support multiple uplink ports and/or link aggregation for higher throughput. Both depend upon the model of AP deployed. High speed optical connections (SFP+) to Wi-Fi APs are typically not an option because such connections do not address providing power to the APs. - -For Release 1 - Early Availability, the CW-9176I APs support mGig at speeds up to 10 Gbps. However, the C9300L-24P-4X and C9300-48P-4X switches only support access port speeds up to 1 Gbps. The uplink ports on the switch do support speeds up to 10 Gbps. However, those ports require optical SFP+ modules which do not support PoE. Hence, for Release 1 - Early Availability, the CW9176I Access Points were connected to access ports (ports 5 & 6) on the switches with a maximum speed of 1 Gbps. +If AP uplink speeds greater than 1 Gbps are required, then the network administrator must also consider whether the APs should be connected to switch ports which support Multi-Gigabit Ethernet (mGig) speeds of 2.5, 5, or 10 Gbps. This depends upon the model of AP deployed. Therefore, as with PoE requirements discussed above, you must select the model of switch and AP such that both the switch port and the AP supports port speeds greater than 1 Gbps if necessary. -As with the uplink between the MX-85 security appliance and the C9300L-24P-4X or C9300L-48P-4X switch port, link speed and duplex (full or half) of the Ethernet ports on the switch and the AP must match for the uplink to come up active. Again, a best practice is to typically leave the link speed for auto-negotiation of speed and duplex. +As with the uplinks between the MX secure router and the switch, link speed and duplex (full or half) of the Ethernet ports on the switch and the AP must match for the uplink to come up active. Again, a best practice is to typically leave the link speed for auto-negotiation of speed and duplex. #### Authentication of the AP to the Switch #### -For Release 1 - Early Availability, no authentication of the Access Point to the switch port was configured. The switch models for Release 1 - Early Availability do not support Meraki Secure Port. Likewise, the AP model does not support the 802.1x supplicant necessary for 802.1x authentication of the AP to the switch. Hence, the only alternatives are either no authentication or MAC Authentication Bypass (MAB). MAB is not ideal because the MAC address of the AP is normally printed on the AP, making it somewhat easy to circumvent. However, given the physical installations of the APs are typically 8-12 feet off the ground in the ceilings of sites, it is still preferable to no authentication, and would generally be recommended, although it HAS NOT BEEN VALIDATED for Release 1 - Early Availability. +For this release of Unified Branch - Branch as Code, no authentication of the AP to the switch port was configured. The switch models supported for Unified Branch - Branch as Code do not support Meraki Secure Port. Likewise, the AP models do not support the 802.1x supplicant necessary for 802.1x authentication of the AP to the switch. Hence, the only alternatives are either no authentication or MAC Authentication Bypass (MAB). MAB is not ideal because the MAC address of the AP is normally printed on the AP, making it somewhat easy to circumvent. However, given the physical installations of the APs are typically 8-12 feet off the ground in the ceilings of sites, it is still preferable to no authentication, and would generally be recommended. Note that use of MAB has not been validated between the AP and the switch for this release. #### WLAN SSIDs #### -For Release 1 - Early Availability, the following three SSIDs (Data - SSID 0, Voice - SSID 1, and Guest - SSDI 2) are hardcoded in the YAML configuration files for example purposes only. The SSIDs are all configured for open access (no authentication or encryption), with traffic mapped to the three VLANs (Data - VLAN 10, Voice - VLAN 20, and Guest - VLAN 30) defined as variables. +The following two SSIDs (Data - SSID 0 and Guest - SSID 1) are hardcoded in the YAML configuration files. The actual names of the SSIDs are specified as variables, however they will be referred to within this document as Data and Guest for clarity. -Again, this is shown as an example only, not intended to be implemented in a production network, and not representative of any best practices. In a production network best practice would recommend implementing secure SSIDs using methods such as enterprise WPA2 and/or WPA3 authentication. The exact method of securing SSIDs would depend on the security policy of the organization. +The Data SSID is configured according to best practices for corporate employees within an enterprise - with wpa-eap and 802.1x authentication via remote RADIUS server. Devices are assigned to the wired VLAN - VLAN 10 (Data), VLAN 20 (Voice) or VLAN 30 (IoT) based on the Group Policy to which the device belongs, which is returned in the Filter-ID attribute from the RADIUS server. + +The Guest SSID is configured for basic guest access, meaning an open SSID with click-through splash-page. Devices are automatically assigned to wired VLAN 50 (Guest), which is trunked to the MX secure router. You should configure a firewall policy on the MX secure router to restrict guests from accessing other VLANs within the branch. Since the subnet corresponding to VLAN 50 (Guest) is not transported across the Auto VPN tunnel, guests cannot access corporate resources at the hub site. However, for additional precaution you may wish to explicitly configure the MX secure router firewall policy to prevent guests from accessing corporate subnets at the head-end, should VLAN 50 (Guest) be accidently configured to be forwarded across the Auto VPN tunnel. ## Unified Branch Services ## -The following sections discuss the services enabled within the small branch for Release 1 - Early Availability. +The following sections discuss the services enabled within the small branch for Unified Branch - Branch as Code. ### WAN Services ### -WAN services for the small branch for Release 1 - Early Availability consist of the following: +WAN services for the small branch consist of the following: - WAN Connectivity - WAN Traffic Shaping & Traffic Steering #### WAN Connectivity #### -WAN connectivity services for the small branch are implemented by the MX security appliance. The *sb122* template within the *data/templates-inventory-related.nac.yaml* file provides an example of the configuration of WAN connectivity services via YAML. It specifies both WAN 1 and WAN 2 connectivity with IPv4 dynamic (DHCP) IP addressing. A general best practice for the small branch design would be to provision dual WAN uplink connectivity for resiliency purposes. - -> :information_source: -> Only 1 WAN uplink (WAN 1) was tested for Release 1 - Early Availability. +WAN connectivity services for the small branch are implemented by the MX secure router. The *data/templates-wan-uplinks.nac.yaml* file contains a series of templates which provide complete coverage of all WAN uplink scenarios for MX secure routers. To use the templates, simply add the desired wan-uplink template to the *templates* list under the *Unified Branch 2* network or any new network you define within the *pods_variables.nac.yaml* file. Be sure to define the necessary variables for the selected template within the *variables* list under the network. All of the templates within the *data/templates-wan-uplinks.nac.yaml* file contain dual WAN uplinks for resiliency purposes, consistent with general best practices for the small branch design. #### WAN Traffic Shaping & Traffic Steering #### -WAN traffic shaping & traffic steering services are implemented by the MX security appliance. The *app_ts* and *tfsteering* templates within the *data/appliance-related.nac.yaml* file provides examples of the configuration of the following: +WAN traffic shaping & traffic steering services are implemented by the MX secure router. The *app_ts* and template within the *data/templates-wan-ts.nac.yaml* file provides examples of the configuration in the following sections: + +- Global bandwidth limits - Configures per-client rate-limiting both upstream and downstream and definitions of performance classes which are then used within traffic steering policy to determine which WAN uplink to use for VPN and/or Internet traffic. -- Overall and per-client rate limiting of and each of the WAN uplinks -- Definition of performance classes which are then used within traffic steering policy to determine which WAN uplink to use for VPN and/or Internet traffic. -- Rule definitions for classifying traffic based on L3 characteristics (source and/or destination IP address and/or port) or L7 characteristics (application and/or application category) which is then matched to a performance class to determine the WAN uplink for the traffic. +- Traffic shaping rules - Configures traffic shaping rules that can be applied per client and per application to optimize network performance and ensure critical applications receive the necessary bandwidth. + +- Uplink bandwidth limits - Implements sub-line rate limiting to the speed of the carrier for each WAN uplink. + +- Uplink selection - Provides several configurable options for uplink selection as part of SD-WAN and traffic shaping capabilities. These options allow administrators to control how traffic is routed across multiple WAN uplinks to optimize performance, reliability, and application prioritization. + +Note that the *Non-VPN (Internet) traffic uplink preferences* section within the *app_ts* template is commented out. It is recommended to use the *internet_policies* template within the *templates-internet-policies.nac.yaml* file instead, which provides examples of L3 and L7 policies for non-VPN (Internet) traffic. > :information_source: > Applications and application categories must currently be specified via ID within YAML configuration files. Work is ongoing to translate these IDs into user-friendly names. @@ -165,65 +166,69 @@ The examples shown in the templates are meant to provide guidance for the networ ### LAN Services ### -LAN services for the small branch for Release 1 - Early Availability consist of the following: +LAN services for the small branch consist of the following: - LAN Connectivity - LAN QoS (Ingress Classification & Marking) +- Access Control Policies - Power over Ethernet (PoE) - Rapid Spanning-Tree Protocol (RSTP) - Multiple VLANs -- LAN Port Schedules #### LAN Connectivity #### -For Release 1 - Early Availability, LAN connectivity is implemented by a single C9300L-24P-4X or C9300L-48P-4X switch within the small branch. LAN connectivity consists of 1 Gbps RJ-45 wired LAN ports for connectivity as uplinks to the MX security appliance, uplinks to the CW9176I access points, and all wired LAN clients. The device *$(switch-01) section of the *sb122* template within the *data/templates-inventory-related.nac.yaml* file provides an example of the configuration of switch ports. Ports are set to auto-negotiate port speed and duplex via the *link_negotiation* setting. A general best practice is to allow switch ports to negotiate speed and duplex unless there is a specific reason otherwise. +LAN connectivity is implemented by a single switch or switch stack within the small branch. LAN connectivity consists of wired LAN ports for connectivity as uplinks to the MX secure router (trunk ports), uplinks to the access points (also trunk ports), and all wired LAN clients. + +The *access_switch_01_name* and *access_switch_02_name* sections of the *small_branch_inventory* template within the *data/templates-inventory.nac.yaml* file provides examples of the configuration of switch ports for small branch. Add or delete these sections based on the number of switches in the switch stack for the small branch to be deployed. Note that you may need to adjust the port ranges for *access* and *trunk* ports to reflect your needs as well as the number of ports on the model of switch which you deploy. Then, within the *switch* template within the *templates-switch.nac.yaml* file locate the *switch_stacks* section. Adjust the variables for the names of the switches to match those configured in the *small_branch_inventory* template. -#### QoS (Ingress Classification & Marking) #### +#### LAN QoS (Ingress Classification & Marking) #### -LAN QoS (ingress classification & marking) consists of DSCP to CoS queue mapping configuration as well as rules which classify and set the DSCP marking of traffic. The *nw_switch* template within the *data/templates-network-related.nac.yaml* file provides an example DSCP to CoS queue mapping assuming a 12 traffic-class QoS model, using all 8 CoS queues, as well as an example set of QoS classification & marking rules for different VLANs on the switch. Both are applied at the switch level, meaning the DSCP to CoS queue mapping and the QoS classification & marking rules apply to all ports of the switch to which the template is applied. +LAN QoS (ingress classification & marking) consists of DSCP to CoS queue mapping configuration as well as rules which classify and set the DSCP marking of traffic. The *switch* template within the *data/templates-switch.nac.yaml* file provides an example DSCP to CoS queue mapping assuming a 12 traffic-class QoS model, using all 8 CoS queues, as well as an example set of QoS classification & marking rules for different VLANs on the switch. Both are applied at the switch level, meaning the DSCP to CoS queue mapping and the QoS classification & marking rules apply to all ports of the switch to which the template is applied. The QoS classification & marking rules shown in the template are meant to provide guidance for the network administrator as to how to configure such services within the context of a YAML file. They are not meant to be deployed in a production network, nor do they represent any form of best practices. Such configuration would require knowledge of the specific applications and business requirements of the organization. +#### Access Control Policies #### + +Access control policies consists of hybrid authentication which supports both 802.1x and MAB for switch ports to which the policy is applied. This is configured within the *access_policies* section of the *switch* template in the *templates-switch.nac.yaml* file. External RADIUS and RADIUS accounting servers are specified via variables. + #### Power over Ethernet (PoE) #### -For Release 1 - Early Availability, the C9300L-24P-4X or C9300L-48P-4X switch within the small branch supplies up to 30 Watts 802.3at / PoE+ power per switch port (ports 1-24 for the C9300L-24P-4X or ports 1-48 for the C9300L-48P-4X). This is sufficient to power to the CW-9176I access points within the small branch design, without the use of the USB port. PoE is enabled by default on the switch ports. Therefore, the port level *PoE* setting (Boolean - true or false) does not appear within the *sb122* template within the *data/templates-inventory-related.nac.yaml* file. A general best practice is to leave PoE enabled on switch ports and allow the switch port to negotiate whether power is to be supplied to the device connected to the switch port. + PoE is enabled by default on switch ports which support PoE. Therefore, the port level *PoE* setting (Boolean - true or false) does not appear within the *small_branch_inventory* template within the *data/templates-inventory.nac.yaml* file. A general best practice is to leave PoE enabled on switch ports and allow the switch port to negotiate whether power is to be supplied to the device connected to the switch port. #### Rapid Spanning Tree Protocol (RSTP) #### -RSTP is enabled by default on the switch ports of the C9300L-24P-4X or C9300L-48P-4X small branch switch. Therefore, the port level *rstp* setting (Boolean - true or false) does not appear within the *sb122* template within the *data/templates-inventory-related.nac.yaml* file. In addition, BPDU guard (configured via the *stp_guard* setting) and storm control (configured via the Boolean *storm_control* setting) are hardcoded within the *sb122* template to be enabled for the access ports (ports not configured as trunk ports). +The port level *rstp* setting (Boolean - true or false) and is hardcoded to be true (enabled) for all access and trunk ports within the *small_branch_inventory* template within the *data/templates-inventory.nac.yaml* file. + +BPDU guard (configured via the *stp_guard* setting) is hardcoded within the *small_branch_inventory* template to be enabled for the access ports (ports not configured as trunk ports) only. + +Finally, storm control (configured via the Boolean *storm_control* setting) is hardcoded within the *small_branch_inventory* template to be enabled for both the access ports and trunk ports. -The storm control configuration itself is hardcoded within the *nw_switch* template within the *data/templates-network-related.nac.yaml* file to restrict broadcast, multicast, and unknown unicast traffic to 30% of the available bandwidth of the switch ports. These percentages are for example purposes only. Determining the appropriate levels for "normal" broadcast, multicast, and unknown unicast traffic may require monitoring the network first for a period, and then setting these parameters slightly above those levels, to protect the network. +The storm control configuration itself is hardcoded within the *switch* template within the *data/templates-switch.nac.yaml* file to restrict broadcast, multicast, and unknown unicast traffic to 30% of the available bandwidth of the switch ports. Tune these parameters if necessary. Determining the appropriate levels for "normal" broadcast, multicast, and unknown unicast traffic may require monitoring the network first for a period, and then setting these parameters slightly above those levels, to protect the network. -A general best practice is to leave RSTP protocol enabled on all switch ports within a small branch to minimize the chance of an outage or degradation of service resulting from an inadvertent loop in the network - unless there is a situation where you are absolutely sure this is not needed or will cause problems on given switch ports. Given the small branch design consists of only a single switch, the chance of a loop occurring is likely low. However, the benefits from enabling RSTP generally outweigh the minor time delay necessary for a switch port to move from a blocking to a forwarding state when first enabled. +A general best practice is to leave RSTP protocol enabled on all switch ports within a small branch to minimize the chance of an outage or degradation of service resulting from an inadvertent loop in the network - unless there is a situation where you are absolutely sure this is not needed or will cause problems on given switch ports. Given the small branch design consists of only a single switch or switch stack, the chance of a loop occurring may be low. However, the benefits from enabling RSTP generally outweigh the minor time delay necessary for a switch port to move from a blocking to a forwarding state when first enabled. #### Multiple VLANs #### -For Release 1 - Early Availability the small branch design YAML files are hardcoded to support four VLANs - Data (VLAN 10), Voice (VLAN 20), Guest (VLAN 30), and Infrastructure (VLAN 1). +For the small branch design, YAML files are hardcoded to support five VLANs - Data (VLAN 10), Voice (VLAN 20), IoT (VLAN 30), Guest (VLAN 50), and Infra (VLAN 999). In addition the MX secure router automatically configures the default VLAN (VLAN 1). > :information_source: > Configuration for VLAN 1 does not appear within the YAML configuration files since this is a default configuration. Work is ongoing to import VLAN 1 configuration to make it visible within the YAML configuration files to the network administrator. -Multiple VLAN support is enabled through *vlans_settings* within the *app_vlans* template of the *data/templates-appliance-related.nac.yaml* file. Layer 3 (SVI) interface definitions for the VLANs are configured on the MX-85 security appliance. These are defined within the same template. The template allows for the subnet of each VLAN as well as the IP address of the MX-85 Layer 3 (SVI) interface corresponding to the VLAN to be specified by the network administrator through variable definitions. +Multiple VLAN support is enabled via the Boolean *vlans_settings* setting within the *app_vlans* template of the *data/templates-appliance.nac.yaml* file. Layer 3 (SVI) interface definitions for the VLANs are configured on the MX secure router. These are defined within the same template. The template allows for the subnet of each VLAN as well as the IP address of the MX Layer 3 (SVI) interface corresponding to the VLAN to be specified by the network administrator through variable definitions. -VLAN trunking is supported on the links between the MX-85 security appliance and the C9300L-24P-4X or C9300L-48P-4X switch. On the MX-85 security appliance, this is configured within the *app_ports* template within the *data/templates-appliance-related.nac.yaml* file. On the switch (ports 1-2), this is configured within the *sb122* template within the *data/templates-inventory-related.nac.yaml* file. +VLAN trunking is supported on the links between the MX secure router and the switch or switch stack. On the secure router, this is configured within the *app_ports* template within the *data/templates-appliance.nac.yaml* file. On switches, this is configured within the *small_branch_inventory* template within the *data/templates-inventory.nac.yaml* file. -VLAN trunking is also supported on the links between the C9300L-24P-4X or C9300L-48P-4X switch and the CW-9176I access points. On the switch (ports 5-13), this is again configured within the *sb122* template within the *data/templates-inventory-related.nac.yaml* file. On the access points, Data, Voice, and Guest SSIDs are mapped to separate VLANs specified through variable definitions. This is configured within the *wireless* template within the *data/templates-network-related.nac.yaml* file. +VLAN trunking is also supported on the links between the switches and the access points. On the switch, this is again configured within the *small_branch_inventory* template within the *data/templates-inventory.nac.yaml* file. On the access points, Data and Guest SSIDs are mapped to separate VLANs. This is configured via the SSID level *default_vlan_id* setting within the *wireless* template of the *data/templates-wireless.nac.yaml* file. Note that for the Data SSID, the VLAN assignment can be overridden via the Filter-ID attribute corresponding to a Group Policy returned during 802.1x/MAB authentication. -Access ports (ports 5-24 on the C9300L-24P-4X or ports 5-48 on the C9300L-48P-4X) on the switch are hardcoded with a VLAN and voice VLAN configuration within the *app_ports* template within the *data/templates-appliance-related.nac.yaml* file. +Access ports on the switch are hardcoded with a VLAN and voice VLAN configuration within each switch definition within the *small_branch_inventory* template within the *data/templates-inventory.nac.yaml* file. Again, note that you may need to adjust the port ranges for trunks and access ports to match the ports on the switch models you deploy within the small branch. -In general, the network administrator should implement as many VLANs as needed based on the requirements of the organization. In other words, there are no best practices as to how many VLANs you should deploy. Cisco has long recommended a separate Voice VLAN for isolating IP phones from regular employee data traffic. The hardcoded YAML configuration files for Release 1 - Early Availability of the small branch design reflect that. However, note that the firewall configuration examples discussed in the sections below do not reflect restriction of traffic to/from the Voice VLAN. Simply putting VoIP telephone traffic onto a Voice VLAN and allowing unlimited access to the Voice VLAN does not provide any additional security for such devices. Hence the network administrator should configure the appropriate firewall policy restricting traffic to and from the Voice VLAN to only that required for the devices supported by the Voice VLAN. +In general, the network administrator should implement as many VLANs as needed based on the requirements of the organization. In other words, there are no best practices as to how many VLANs you should deploy. Cisco has long recommended a separate Voice VLAN for isolating IP phones from regular employee data traffic. The YAML configuration files of the small branch design reflect that. However, note that the MX secure appliance firewall configuration examples discussed in the sections below do not reflect restriction of traffic to/from the Voice VLAN. Simply putting IP phones onto a Voice VLAN and allowing unlimited access to the Voice VLAN does not provide any additional security for such devices. Hence the network administrator should configure the appropriate MX secure apliance firewall policy restricting traffic to and from the Voice VLAN to only that required for the devices supported by the Voice VLAN. Alternatively, if you do not have any dedicated IP Phones within the small branch, you may not wish to configure a Voice VLAN. In such scenarios, you will need to modify the YAML files appropriately. -Likewise, the network administrator should configure the appropriate firewall policy restricting Guest VLAN from reaching any VLANs which support the internal organization. For Release 1 - Early Availability of the small branch design, it is assumed the Guest VLAN traffic will only have direct Internet access only. Internet traffic may further be restricted based on content filtering policy. The firewall, content filtering, intrusion prevention, and AMP example policies currently within the YAML files currently do not reflect a complete guest access configuration - they are examples only, do not reflect best practices, and should not be deployed in a production network. The network administrator must configure the appropriate policies based on the requirements and security policy of the organization. - -#### LAN Port Schedules ##### - -LAN Port schedules allow network administrators to set up recurring time-based schedules in which LAN switch ports are enabled or disabled. The *nw_switch* template within the *data/templates-network-related.nac.yaml* file provides an example YAML configuration of a LAN port schedule in which all switch ports are enabled at all hours for all days of the week. This can be modified to suit the needs of the particular organization. The port schedule is applied to all switch ports of the C9300L-24P-4X or C9300L-48P-4X small branch switch via the *port_schedule_name* setting within the *sb122* template within the *data/templates-inventory-related.nac.yaml* file. - -The general use of port schedules depends on the needs of the specific organization. There are no best practices or recommendations. Examples of use may be for security or power savings purposes - for example disabling LAN switch ports during non-work hours when employees are not expected to be at the site. However, the network administrator must balance this against unforeseen situations where LAN port connectivity may occasionally be needed during those non-work hours. Additionally, should IP phone and/or IP surveillance camera connectivity within the small branch site be dependent upon the LAN switch ports being active, provisions for reaching emergency services and for surveillance monitoring may be required within the site, even during non-work hours. +Likewise, the network administrator should configure the appropriate firewall policy restricting Guest VLAN from reaching any VLANs which support the internal organization. For the small branch design, it is assumed the Guest VLAN traffic will only have direct Internet access only. Internet traffic may further be restricted based on content filtering policy. The firewall, content filtering, intrusion prevention, and AMP example policies currently within the YAML files currently do not reflect a complete guest access configuration - they are examples only, do not reflect best practices, and should not be deployed in a production network. The network administrator must configure the appropriate policies based on the requirements and security policy of the organization. ### Wireless LAN (WLAN) Services ### -WLAN services for the small branch for Release 1 - Early Availability consist of the following: +WLAN services for the small branch consist of the following: - WLAN Connectivity - Multiple SSIDs @@ -233,28 +238,32 @@ WLAN services for the small branch for Release 1 - Early Availability consist of #### WLAN Connectivity #### -For Release 1 - Early Availability, the small branch design supports Wi-Fi 7 / 802.11be compliant CW-9176I cloud managed access points for WLAN connectivity. CW-9176I access points feature WPA3 security and tri-band (2.4, 5, and 6 GHz) operation with a single multi-Gigabit Ethernet (mGig) uplink up to 10 Gbps. - -For many WLAN deployments, the pre-configured Basic Indoor and Basic Outdoor RF profiles provided by the Cisco (formerly Meraki) dashboard provide sufficient coverage when applied to access points which are properly placed within the network / site. Nevertheless, the *wireless* template within the *data/templates-network-related.nac.yaml* file provides an example configuration of a custom RF profile. Note that within the example RF profile, only the 2.4 and 5 GHz bands are enabled and parameters such as RX-SOP are modified. This is intended as an example of how to configure RF profile parameters via YAML configuration files only. It is not representative of best practices or meant to be deployed within a production environment. Work is ongoing to refine the wireless configurations throughout the YAML files within the repository to reflect best practices more accurately, and to also include Wi-Fi 7 / 802.11be components in future releases. +The small branch design supports Wi-Fi 7 / 802.11be compliant CW9176 or CW9172 cloud managed access points for WLAN connectivity. For many WLAN deployments, the pre-configured Basic Indoor and Basic Outdoor RF profiles provided by the Cisco (formerly Meraki) dashboard provide sufficient coverage when applied to access points which are properly placed within the network / site. Nevertheless, the *wireless* template within the *data/templates-wireless.nac.yaml* file provides an example configuration of a custom RF profile with minimal changes from default settings. Where possible, a best practice is to allow Meraki Auto RF to handle channel selection, channel width, power management, etc. #### Multiple SSIDs #### -For Release 1 - Early Availability, three SSIDs - Data, Voice, and Guest - are hardcoded within the *wireless* template within the *data/templates-network-related.nac.yaml* file for the small branch design. All three SSIDs are configured for open access and allow the mapping of SSID to VLAN to be specified via variables. +Two SSIDs - Data and Guest - are configured within the *wireless* template within the *data/templates-wireless.nac.yaml* file for the small branch design. Technically, the names of the SSIDs are defined as variables, but they will be referred to as the Data and Guest SSIDs for clarity in this document. -A general best practice for non-Guest SSIDs would be to utilize WPA3 enterprise security, WPA2 enterprise security, or potentially WPA3 transition mode - utilizing an external RADIUS server such as Cisco ISE, or the Meraki Cloud Authentication. Additionally, it is generally recommended to minimize the number of SSIDs advertised within a site. Potential methods to reduce the number of SSIDs include dynamic VLAN assignment of wireless clients such as IP Phones as they authenticate to the network on a common Corporate SSID, rather than provisioning a dedicated Voice SSID. Hence, work is ongoing to refine the wireless configurations as well as include identity services (discussed below) throughout the YAML files within the repository of the small branch design to reflect such best practices more accurately in future releases. +As mentioned previously, the Data SSID is configured according to best practices for corporate employees within an enterprise - with wpa-eap encryption mode and 802.1x authentication via remote RADIUS server. Devices are assigned to the wired VLAN - VLAN 10 (Data), VLAN 20 (Voice) or VLAN 30 (IoT) based on the Group Policy to which the device belongs, which returned in the Filter-ID attribute from the RADIUS server. + +The Guest SSID is configured for basic guest access, meaning an open SSID with click-through splash-page. Devices are automatically assigned to wired VLAN 50 (Guest), which is trunked to the MX secure router. + +A general best practice for non-Guest SSIDs would be to utilize WPA3 enterprise security, WPA2 enterprise security, or potentially WPA3 transition mode - utilizing an external RADIUS server such as Cisco ISE, or the Meraki Cloud Authentication. Additionally, it is generally recommended to minimize the number of SSIDs advertised within a site. Potential methods to reduce the number of SSIDs include dynamic VLAN assignment of wireless clients such as IP Phones as they authenticate to the network on a common SSID, rather than provisioning a dedicated Voice and/or IoT SSID. + +Note however, that in some scenarios, rather than implement MAB for devices on an SSID, it may be more desireable to configure a dedicated SSID with pre-shared key if such devices do not support digital certificates and have no end-user to enter credentials. This may alleviate the need to maintain MAC address tables for all the devices which authenticate via MAB to the SSID. To support such scenarios you may need to modify the YAML files directly. This has not been validated for support with the current release of Unified Branch - Branch as Code. #### Guest Services #### -Guest services for the small branch for Release 1 - Early Availability consist of a Guest SSID configured with open authentication and click-through splash page. The Guest SSID is terminated on a dedicated Guest VLAN (VLAN 30). Guest traffic is further rate limited on a per-user and per-SSID basis. The configuration of the Guest SSID is found in the *wireless* template within the *data/templates-network-related.nac.yaml* file. +Guest services for the small branch consist of a Guest SSID configured with open authentication and click-through splash page. The Guest SSID is terminated on a dedicated Guest VLAN (VLAN 50). Guest traffic can be further rate limited on a per-user and per-SSID basis. The configuration of the Guest SSID is found in the *wireless* template within the *data/templates-wireless.nac.yaml* file. -For Release 1 - Early Availability, Guest traffic is intended to be allowed Direct Internet Access (DIA) only via the MX security appliance firewall policy. The current firewall policy found within the *app_fw* template within the *data/templates-appliance-related.nac.yaml* file does not include rules restricting Guest traffic. Hence, the Guest services configuration is an incomplete example at this point and should not be taken as any form of best practice or implemented in a production network. Work is ongoing to refine the configurations within the repository to show a more complete policy allowing DIA access, potentially with content filtering rules for Guest traffic. +For the small branch design, guest traffic is intended to be allowed Direct Internet Access (DIA) only via the MX secure router firewall policy. The current firewall policy found within the *app_fw* template within the *data/templates-appliance.nac.yaml* file does not include rules restricting guest traffic. Hence, you will need to configure the appropriate MX secure router firewall policy to ensure guest traffic is only allowed DIA acces, and cannot access other VLANs within the branch. Note that by default VLAN 50 (Guest VLAN) is not transported across the Auto VPN tunnel in the small branch design. However as an extra precaution you may wish to also explicitly configure MX secure router firewall policy restricting this. > :information_source: -> Release 1 - Early Availability of the small branch design only considers wireless Guest services. No configurations have been considered for extending Guest services to wired guest traffic. +> The small branch design only considers wireless Guest services. No configurations have been considered for extending Guest services to wired guest traffic. #### Traffic & Bandwidth Shaping and QoS #### -Bandwidth shaping for cloud managed access points allows the network administrator to set per-SSID and per-device/user rate limits for upstream and downstream traffic, which are enforced on a per-AP basis. For Release 1 - Early Availability of the small branch design, the Data and Voice SSIDs have no bandwidth shaping limits. However, the Guest SSID has been hardcoded for an upstream and downstream per-SSID limits of 100 Mbps and per-device/user limits of 10 Mbps. This is configured within the *wireless* template within the *data/templates-network-related.nac.yaml* file. This is meant as an example only and should not be taken as any form of best practice or implemented in a production network. +Bandwidth shaping for cloud managed access points allows the network administrator to set per-SSID and per-device/user rate limits for upstream and downstream traffic, which are enforced on a per-AP basis. For the small branch design, the Data SSID has no bandwidth shaping limits. However, the Guest SSID has been configured with variables for upstream and downstream per-SSID limits and per-device/user limits. This is configured within the *wireless* template within the *data/templates-wireless.nac.yaml* file. Traffic shaping for cloud managed access points allows the network administrator to set per-device/user rate limits on a per-application basis. Traffic shaping configuration consists of rule definitions and rule actions. @@ -269,24 +278,22 @@ Rule actions can then specify one of the following for the matched traffic: - Obey the bandwidth shaping rate limits set for the SSID - Apply more restrictive limits than specified for the SSID -For Release 1 - Early Availability of the small branch design, the Data and Voice SSIDs provide examples of traffic shaping configurations. This is configured within the *wireless* template within the *data/templates-network-related.nac.yaml* file. This is meant as an example only and should not be taken as any form of best practice or implemented in a production network. +For the small branch design, the Data and Guest SSIDs simply implement the default traffic shaping rules that apply when configuring through the Cisco (formerly Meraki) Dashboard. This is configured within the *wireless* template within the *data/templates-wireless.nac.yaml* file. Cloud managed access points have a default downstream mapping of DSCP values to 802.11 Access Categories (ACs), as discussed in the [Wireless QoS and Fast Lane](https://documentation.meraki.com/MR/Wi-Fi_Basics_and_Best_Practices/Wireless_QoS_and_Fast_Lane) document. Upstream QoS sent by the wireless client is honored and the DSCP field within the traffic sent from the client is maintained on the Ethernet network. > :information_source: > The upstream switch port to which the access point is connected will need to be configured to trust DSCP markings or implement an ingress classification & marking policy if QoS from the wireless client is desired to be maintained. -Fast Lane is supported with the ability to install a wireless profile on Apple iOS devices via the Meraki EMM. The default configuration accepts all application markings. For Release 1 - Early Availability of the small branch design, Fast Lane was not considered. - #### WLAN SSID Schedules ##### -WLAN SSID schedules allow network administrators to set up recurring time-based schedules in which WLAN SSIDs are enabled or disabled. The *wireless* template within the *data/templates-network-related.nac.yaml* file provides example YAML configurations of a WLAN SSID schedules for each of the SSIDs. This can be modified to suit the needs of the particular organization. +WLAN SSID schedules allow network administrators to set up recurring time-based schedules in which WLAN SSIDs are enabled or disabled. The *wireless* template within the *data/templates-wireless.nac.yaml* file provides example YAML configurations of WLAN SSID unavailability schedules for each of the SSIDs. In order to use these examples, you must first enable the schedule via the variable *data_ssid_schedules_enabled* and/or *guest_ssid_schedules_enabled*, then modify the YAML configuration for start and end days and times, in order to meet the needs of the particular organization. The general use of SSID schedules depends on the needs of the specific organization. There are no best practices or recommendations. Examples of use may be for security or power savings purposes - for example disabling SSIDs during non-work hours when employees are not expected to be at the site. However, the network administrator must balance this against unforeseen situations where WLAN SSID connectivity may occasionally be needed during those non-work hours. Additionally, should WLAN connected IP phone and/or IP surveillance camera connectivity within the small branch site be dependent upon the SSID being active, provisions for reaching emergency services and for surveillance monitoring may be required within the site, even during non-work hours. ### Network Services ### -Network services for the small branch for Release 1 - Early Availability consist of the following: +Network services for the small branch consist of the following: - DHCP Services - SNMP Services @@ -297,67 +304,71 @@ Network services for the small branch for Release 1 - Early Availability consist #### DHCP Services #### -IP address assignment to devices within the small branch design can be static or dynamic. Dynamic IP address assignment is via the Dynamic Host Configuration Protocol (DHCP). IP addresses can also be IPv4 or IPv6. Release 1 - Early Availability of the small branch design only considers IPv4 addressing. Future releases may consider IPv6 as well. Both static and dynamic (DHCP) IP address assignments are used within the small branch design. +IP address assignment to devices within the small branch design can be static or dynamic. Dynamic IP address assignment is via the Dynamic Host Configuration Protocol (DHCP). IP addresses can also be IPv4 or IPv6. The current release of the small branch design only considers IPv4 addressing. Future releases may consider IPv6 as well. Both static and dynamic (DHCP) IP address assignments are used within the small branch design. -IP address assignments apply to wired and wireless devices within the small branch. Such devices can be network infrastructure devices such as the MX security appliance, C9300L-24P-4X or C9300L-48P-4X switch, and CW-9176I access points; or end-user devices such as laptops, IP phones, smart phones, tablets, etc. Within the small branch design, the MX security appliance can simultaneously function as a DHCP client, DHCP server, and/or DHCP relay agent. +IP address assignments apply to wired and wireless devices within the small branch. Such devices can be network infrastructure devices such as the MX secure router, switches, and access points; or end-user devices such as laptops, IP phones, smart phones, tablets, etc. Within the small branch design, the MX secure router can simultaneously function as a DHCP client, DHCP server, and/or DHCP relay agent. -A DHCP relay agent forwards DHCP requests to a centralized / remote DHCP server. Such designs are implemented typically to enforce centralized IP address assignment for administrative ease of deployment. With such designs, network redundancy (dual WAN circuits) becomes more critical, since a network failure could result in new clients not being able to receive an IP address when they connect to the wired or wireless network. +A DHCP relay agent forwards DHCP requests to a centralized / remote DHCP server. Such designs are implemented typically to enforce centralized IP address assignment for administrative ease of deployment. With such designs, network redundancy (dual WAN circuits and redundant hub sites) becomes more critical, since a network failure could result in new clients not being able to receive an IP address when they connect to the wired or wireless network. -Alternatively, running one or more DHCP server instances within the MX security appliance increases administrative overhead, particularly in deployments with hundreds or thousands of branches, since each DHCP server instance must be configured and maintained individually. However, the configuration of each DHCP instance within each IP subnet / VLAN of each branch MX security appliance can be rather simple compared to a centralized DHCP server deployment. Further, client devices can still get IP addresses in the event of a failure of connectivity to the site which houses the remote DHCP server. +Alternatively, running one or more DHCP server instances within the MX secure router increases administrative overhead, particularly in deployments with hundreds or thousands of branches, since each DHCP server instance must be configured and maintained individually. However, the configuration of each DHCP instance within each IP subnet / VLAN of each branch MX secure router can be rather simple compared to a centralized DHCP server deployment. Further, client devices can still get IP addresses in the event of a failure of connectivity to the site which houses the remote DHCP server. -Release 1 - Early Availability of the small branch design implements DHCP server instances for each of the three VLANs defined - Data (VLAN 10), Voice (VLAN 20), and Guest (VLAN 30). The DHCP server definitions for each of the VLANs are found within the *app_vlans* template within the *data/templates-appliance-related.nac.yaml* file. The DHCP server configuration specifies a lease time of 1 day, provides an example of how to configure DHCP options and reserved IP address ranges, and requires clients to get IP addresses from the DHCP server instance in order for the MX security appliance to forward traffic from those clients. The IP subnet range, IP address assignment of the SVI interface of the MX security appliance corresponding to the VLAN, and reserved IP address ranges are specified as variables for the network administrator to assign within the *Unified Branch 1* network configuration within the *pods_variables.nac.yaml* file within the repository. +The small branch design implements DHCP server instances for the following VLANs: + +- Default VLAN (VLAN 1) - This DHCP pool is used to initially onboard unconfigured switches and APs to the Cisco (formerly Meraki) Dashboard to recieve their configuration. Once the devices receive their configuration, their management VLAN is changed to the Infra VLAN (VLAN 999). The IPv4 subnet for the VLAN 1 is left at the default (192.168.128.0/24) value. Hence all branches have the same configuration. Note that since the VLAN 1 configuration is automatically configured on the MX secure router, it will not show up within the YAML configuration in the repository. Work is ongoing to import the VLAN 1 configuration so that it is visible in the repository. > :information_source: -> Note that the assignment of the IP address of the SVI interface of the MX security appliance corresponding to a given VLAN is a static definition. +> Note that the SVI interface of the MX secure router for VLAN 1 is automatically assigned the 192.168.128.1/24 IP address. Note also, that all 192.168.128.0/24 addresses are automatically NAT translated to the IP address of the WAN interface of the MX secure router as the devices attempt to reach the Cisco (formerly Meraki) Cloud. + +- Guest VLAN (VLAN 50) - This DHCP pool is used for wireless guest devices only. the IPv4 subnet for the Guest VLAN (VLAN 50) is specified as a variable within the *app_vlans* template within the *templates-appliance.nac.yaml* file. -Because VLAN trunking is enabled between the MX security appliance and the Layer 2 C9300L-24P-4X or C9300L-48P-4X switch, all wired end-user devices which connect to the switch are expected to received IP address from the DHCP server pools within the MX security appliance for the respective VLAN to which the device is connected. +- Infra VLAN (VLAN 999) - This DHCP pool is used for the management interfaces of switch and AP devices once they receive their configuration changing the management VLAN from the default VLAN 1 to the Infra VLAN (VLAN 999). The IPv4 subnet for the Infra VLAN (VLAN 999) is specified as a variable within the *app_vlans* template within the *templates-appliance.nac.yaml* file. In addition, since management IP addresses of network infrastructure should ideally not change - especially when monitoring flows such as NetFlow, SNMP, and Syslog are being generated by these devices - fixed IP address assignments should be configured for these devices, as is shown in the *app_vlans* template. -Likewise, because VLAN trunking is enabled between the Layer 2 C9300L-24P-4X or C9300L-48P-4X switch and the CW-9176I access points, and because the SSID definitions found within the *wireless* template within the *data/templates-networks specify bridged mode for IP address assignment, wireless clients are also expected to receive IP addresses from the DHCP server pools within the MX security appliance for the respective SSID (which is mapped to a specific VLAN) to which the device is connected. +The DHCP server configuration specifies a lease time of 1 day for these VLANs. -The MX security appliance by default also configures VLAN 1 along with a DHCP server instance for VLAN 1. For Release 1 - Early Availability of the small branch design, VLAN 1 is used as the Infrastructure VLAN. Cloud managed CW-9176I access points and C9300L-24P-4X or C9300L-48P-4X switches receive IP addresses from the default 192.168.128.0/24 subnet of the VLAN 1 server pool. These IP addresses are used as management IP addresses, allowing network devices downstream of the MX security appliance to connect to the Cisco (formerly Meraki) Cloud to be managed. +For the Data VLAN (VLAN 10), Voice VLAN (VLAN 20), and IoT VLAN (VLAN 30), the MX secure router is configured to relay the DHCP requests to centralized DHCP servers which are specified as variables within the *app_vlans* template within the *templates-appliance.nac.yaml* file. > :information_source: -> Note that the SVI interface of the MX security appliance for VLAN 1 is automatically assigned the 192.168.128.1/24 IP address. Note also, that all 192.168.128.0/24 addresses are automatically NAT translated to the IP address of the WAN interface of the MX security appliance as the devices attempt to reach the Cisco (formerly Meraki) Cloud. +> Note that the assignment of the IP address of the SVI interface of the MX secure router corresponding to a given VLAN is a static definition. -Finally, it should be noted that for Release 1 - Early Availability of the small branch design, the WAN interfaces of the MX security appliance are configured for dynamic IP address assignment. The configuration for IP address assignment of the WAN interfaces is found within the device *$(appliance-01)* section of the *sb122* template within the *data/templates-inventory-related.nac.yaml* file. Hence, the MX security appliance is simultaneously functioning as a DHCP client on the WAN interfaces, while also functioning as multiple DHCP server instances for each of the VLANs defined, and also has statically defined IP addresses for the Layer 3 SVI interfaces associated with each VLAN. +Because VLAN trunking is enabled between the MX secure router and the Layer 2 switch or switch stack, all wired end-user devices which connect to the switch are expected to received IP address either from the DHCP server pools within the MX secure router, or be relayed across the Auto VPN tunnel to centralized DHCP servers for the respective VLAN to which the device is connected. -#### SNMP Services #### +Likewise, because VLAN trunking is enabled between the Layer 2 switch or switch stack and the access points, and because the SSID definitions found within the *wireless* template within the *data/templates-wireless.nac.yaml* specify *bridged mode* for IP address assignment, wireless clients are also expected to receive IP addresses from the DHCP server pools within the MX secure router, or be relayed across the Auto VPN tunnel to centralized DHCP servers for the respective SSID (which is mapped to a specific VLAN) to which the device is connected. -SNMP polling can be used to query and gather information either from the Cisco (formerly Meraki) dashboard or directly from devices (security appliances, switches, and access points) within networks / sites. +#### SNMP Services #### -The SNMP configuration found within the *data/org_global.nac.yaml* file within this repository provides an example of allowing SNMPv2c and SNMPv3 access to the Cisco (formerly Meraki) dashboard. Note that for SNMPv2c access, the community string is not present as a configurable parameter. Likewise, for SNMPv3 access, although the authentication password is specified, the userid is not present as a configurable parameter. As discussed in the [SNMP Overview and Configuration](https://documentation.meraki.com/General_Administration/Monitoring_and_Reporting/SNMP_Overview_and_Configuration) document and shown in the example figure within the *Dashboard Polling* section of the document, these parameters along with hostname and port for sending the SNMP queries are visible through the dashboard. +SNMP polling can be used to query and gather information either from the Cisco (formerly Meraki) dashboard or directly from devices (secure routers, switches, and access points) within networks / sites. -It should be noted that the dashboard polling example shown in the configuration is only an example of how to configure dashboard polling via YAML configuration. It does not represent best practices, nor should it be used in a production network. SNMPv2c passes the community string in clear text within queries. Hence SNMPv2c is NOT RECOMMENDED to be used over unsecure networks - even though dashboard SNMP access provides just read only query capability. SNMPv3 is generally recommended since it includes provisions for privacy. Further, it is highly recommended to limit the source IP addresses which can issue dashboard SNMP queries, particularly when using SNMPv2C, but also when using SNMPv3. +The SNMP configuration found within the *data/org_global.nac.yaml* file within the repository provides an example of allowing SNMPv3 access to the Cisco (formerly Meraki) dashboard. For SNMPv3 access, although the authentication password is specified, the userid is not present as a configurable parameter. As discussed in the [SNMP Overview and Configuration](https://documentation.meraki.com/General_Administration/Monitoring_and_Reporting/SNMP_Overview_and_Configuration) document and shown in the example figure within the *Dashboard Polling* section of the document, these parameters along with hostname and port for sending the SNMP queries are visible through the dashboard. -The SNMP configuration found within the *snmp* template within the *data/templates-network-related.nac.yaml* file within this repository provides an example of how to configure local polling of devices using SNMPv3 via YAML configuration. Within the example configuration, the SNMP username is defined as a variable. This variable is then assigned a value within the *Unified Branch 1* network configuration within the *pods_variables.nac.yaml* file. The SNMP password is defined as an environmental variable. This is simply to demonstrate the best practice of never including passwords within any file which is subject to version control. +Note that SNMPv2c is NOT RECOMMENDED to be used over unsecure networks - even though dashboard SNMP access provides just read only query capability. SNMPv3 is generally recommended since it includes provisions for privacy. Further, it is highly recommended to limit the source IP addresses which can issue dashboard SNMP queries, also when using SNMPv3. -It should be noted that the configuration provides for SNMP polling from a management station which is local to the device being polled - meaning the management station must be on the same subnet as the management interface of the device being polled. The *app_fw* template within the *data/templates-appliance-related.nac.yaml* file contains configuration allowing SNMP through the security appliance for remote polling. Note however, that unrestricted SNMP access is not recommended. Hence this configuration is just an example only, does not represent best practices, and should not be deployed in a production network. Also, with the current Release 1 - Early Availability small branch design, the management interfaces of the MX security appliance, switch and access points are on VLAN 1. VLAN 1 is not transported across the VPN network, since the default IP address range of 192.168.128.0/24 is used currently. VLAN 1 IP addresses, including the management interfaces of the devices, are not reachable remotely across the VPN or externally. +The SNMP configuration found within the *nw_management* template within the *data/templates-network-related.nac.yaml* file within this repository provides an example of how to configure local polling of devices using SNMPv3 via YAML configuration. Within the example configuration, the SNMP username is defined as an environmental variable. This variable is then assigned a value within the *Unified Branch 2* network configuration within the *pods_variables.nac.yaml* file. The SNMP password is also defined as an environmental variable. This is to demonstrate the practice of never including passwords within any file which is subject to version control. -For Release 1 - Early Availability the YAML configuration files contain no configuration for enabling SNMP traps. Work is ongoing to refine the SNMP services configuration for remote SNMP querying of devices and generation of SNMP traps for future releases. +It should be noted that the configuration provides for SNMP polling from a management station which is local to the device being polled - meaning the management station must be on the same subnet as the management interface of the device being polled. The *app_fw* template within the *data/templates-appliance.nac.yaml* file contains configuration allowing SNMP through the secure router for remote polling. Note however, that unrestricted SNMP access is not recommended. Hence this configuration is just an example only, does not represent best practices, and should not be deployed in a production network. #### Syslog Services #### -Documentation of syslog services is currently under development and is expected to be included shortly. +Syslog configuration for Unified Branch - Branch as Code consists of the configuration of the remote host and port to which Syslog messages are to be sent, configured as variables defined in the *nw_management* template within the *data/templates-network-related.nac.yaml* file. Additionally the types of messages to be sent are defined as a list under the *roles* setting. For the small branch design, the management interface of branch network equipment is moved from the default of VLAN 1 to the Infra VLAN (VLAN 999). Since the Infra VLAN (VLAN 999) is advertised across the Auto VPN tunnels to the hub location, this supports centralized on-prem collection of Syslog messages. #### NTP Services #### -The Cisco (formerly Meraki) cloud handles all time synchronization for network devices. Specification of the time zone of a network / site is currently not included in the YAML configuration files within the repository. Future releases may add this capability. +The Cisco (formerly Meraki) cloud handles all time synchronization for network devices. Specification of the time zone of a network / site is defined as a variable within the *nw_setup* template within the *templates-network-related.nac.yaml* file. #### DNS Services #### -For Release 1 - Early Availability of the small branch design, DNS services consist of the following: +The small branch design, DNS services consist of the following: -- Dynamic DNS (DDNS) registration of the MX security appliance to update its DNS host record automatically each time its public IP address changes. This allows the network administrator to access the MX security appliance by its hostname instead of an IP address. Dynamic DNS configuration can be found within the *app_settings* template within the *data/templates-appliance-related.nac.yaml* file. All that is required is to enable DDNS and specify a prefix which is included in creating the FQDN for the MX security appliance. The FQDN can be found by accessing the Cisco (formerly Meraki) dashboard, as discussed in the [Dynamic DNS (DDNS)](https://documentation.meraki.com/MX/Other_Topics/Dynamic_DNS_(DDNS)) document. +- Dynamic DNS (DDNS) registration of the MX secure router to update its DNS host record automatically each time its public IP address changes. This allows the network administrator to access the MX secure router by its hostname instead of an IP address. Dynamic DNS configuration can be found within the *app_settings* template within the *data/templates-appliance.nac.yaml* file. All that is required is to enable DDNS and specify a prefix which is included in creating the FQDN for the MX secure router. The FQDN can be found by accessing the Cisco (formerly Meraki) dashboard, as discussed in the [Dynamic DNS (DDNS)](https://documentation.meraki.com/MX/Other_Topics/Dynamic_DNS_(DDNS)) document. -- Specification of the DNS server to be handed to clients that receive IP addresses via the individual DHCP server instances defined in the MX security appliance. This is configured via the *dns_nameservers* parameter within the *app_vlans* template within the *data/templates-appliance-related.nac.yaml* file for each of the DHCP server instances in each of the VLANs. +- Specification of the DNS server to be handed to clients that receive IP addresses via the individual DHCP server instances defined in the MX secure router. This is configured via the *dns_nameservers* parameter within the *app_vlans* template within the *data/templates-appliance.nac.yaml* file for each of the DHCP server instances in each of the VLANs. #### NetFlow Services #### -For Release 1 - Early Availability of the small branch design, NetFlow services are not included. Work is ongoing to include the configuration to support NetFlow services within the YAML files. +NetFlow services are currently not included within the repository for the small branch design. Work is ongoing to include the configuration to support NetFlow services within the YAML files. ### Security Services ### -Security services for the small branch for Release 1 - Early Availability consist of the following: +Security services for the small branch consist of the following: - Firewalling - Content Filtering @@ -367,41 +378,39 @@ Security services for the small branch for Release 1 - Early Availability consis #### Firewalling #### -Firewalling services for the small branch are implemented by the MX security appliance. Firewalling services consist of the following: -- L3 Firewalling: These are outbound rules which allow or deny traffic passing through the MX security appliance based on source and/or destination IP addresses and ports. -- WAN Appliance Services: These control SNMP, Web, and ICMP Ping access to the MX security appliance itself. +Firewalling services for the small branch are implemented by the MX secure router. Firewalling services consist of the following: +- L3 Firewalling: These are outbound rules which allow or deny traffic passing through the MX secure router based on source and/or destination IP addresses and ports. +- WAN Appliance Services: These control SNMP, Web, and ICMP Ping access to the MX secure router itself. - L7 firewalling: These are rules which allow or block traffic based on application or application category, relying on technologies such as deep packet inspection to identify and classify traffic. > :information_source: > Firewall applications and application categories must be specified by ID currently. Work to translate the IDs into user-friendly names is ongoing. -The *app_fw* template within the *data/templates-appliance-related.nac.yaml* file provides an example of the configuration of firewall services for Internet bound traffic via YAML. This is an example only, not intended to be deployed within a production network, and does not represent any form of best practices. The actual firewall configuration within any organization will depend upon the security policy of the organization. +The *app_fw* template within the *data/templates-appliance.nac.yaml* file provides an example of the configuration of firewall services for Internet bound traffic via YAML. This is an example only, not intended to be deployed within a production network, and does not represent any form of best practices. The actual firewall configuration within any organization will depend upon the security policy of the organization. The *vpn_firewall_rules* section under *appliance* within the *data/org_global.nac.yaml* file provides an example of the configuration of firewall services for traffic across the VPN via YAML. Again, this is an example only, not intended to be deployed within a production network, and does not represent any form of best practices. The actual firewall configuration within any organization will depend upon the security policy of the organization. Note that the rules defined here apply to all networks across the organization. #### Content Filtering #### -Content filtering services for the small branch are implemented by the MX security appliance. Content filtering rules allow or block Internet-bound web traffic based on specific URLs or URL categories. The *app_content* template within the *data/templates-appliance-related.nac.yaml* file provides an example of the configuration of content filtering services via YAML. This is an example only, not intended to be deployed within a production network, and does not represent any form of best practices. The actual content filtering configuration within any organization will depend upon the security policy of the organization. +Content filtering services for the small branch are implemented by the MX secure router. Content filtering rules allow or block Internet-bound web traffic based on specific URLs or URL categories. The *app_content* template within the *data/templates-appliance.nac.yaml* file provides an example of the configuration of content filtering services via YAML. This is an example only, not intended to be deployed within a production network, and does not represent any form of best practices. The actual content filtering configuration within any organization will depend upon the security policy of the organization. #### Intrusion Detection and Prevention #### -For Release 1 - Early Availability, intrusion detection and prevention services for the small branch are implemented by the MX security appliance. Intrusion detection and prevention applies to LAN traffic to and from the Internet, as well as between VLANs which passed through the security appliance. Intrusion detection and prevention can be configured to simply detect (detection mode) and/or prevent (prevention mode) malicious traffic based on a selectable ruleset geared toward security, connectivity, or a balance between security & connectivity. The *app_intrusion* template within the *data/templates-appliance-related.nac.yaml* file provides an example of the configuration of intrusion prevention services via YAML. This is an example only, not intended to be deployed within a production network, and does not represent any form of best practices. The actual intrusion detection or prevention configuration within any organization will depend upon the security policy of the organization. +Intrusion detection and prevention services for the small branch are implemented by the MX secure router. Intrusion detection and prevention applies to LAN traffic to and from the Internet, as well as between VLANs which passed through the secure router. Intrusion detection and prevention can be configured to simply detect (detection mode) and/or prevent (prevention mode) malicious traffic based on a selectable ruleset geared toward security, connectivity, or a balance between security & connectivity. The *app_intrusion* template within the *data/templates-appliance.nac.yaml* file provides an example of the configuration of intrusion prevention services via YAML. This is an example only, not intended to be deployed within a production network, and does not represent any form of best practices. The actual intrusion detection or prevention configuration within any organization will depend upon the security policy of the organization. > :information_source: -> Exclusions via allowed list rules are currently not supported within the YAML configuration for Release 1 - Early Availability. The network administrator will need to access the Cisco (formerly Meraki) dashboard to exclude specific IDS rules. +> Exclusions via allowed list rules are currently not supported within the YAML configuration. The network administrator will need to access the Cisco (formerly Meraki) dashboard to exclude specific IDS rules. #### Advanced Malware Protection (AMP) #### -AMP services for the small branch are implemented by the MX security appliance. AMP applies to non-encrypted (since AMP must first identify that content is being downloaded) LAN traffic to and from the Internet. Once enabled, specific URLs can be excluded from being scanned for malware. Likewise, previously identified files can be excluded by including the SHA-256 hash of the file to be excluded, in scenarios where a false positive has blocked the file. The *app_mal* template within the *data/templates-appliance-related.nac.yaml* file provides an example of the configuration of advanced malware protection via YAML. This is an example only, not intended to be deployed within a production network, and does not represent any form of best practices. The actual AMP configuration within any organization will depend upon the security policy of the organization. +AMP services for the small branch are implemented by the MX secure router. AMP applies to non-encrypted (since AMP must first identify that content is being downloaded) LAN traffic to and from the Internet. Once enabled, specific URLs can be excluded from being scanned for malware. Likewise, previously identified files can be excluded by including the SHA-256 hash of the file to be excluded, in scenarios where a false positive has blocked the file. The *app_mal* template within the *data/templates-appliance.nac.yaml* file provides an example of the configuration of advanced malware protection via YAML. This is an example only, not intended to be deployed within a production network, and does not represent any form of best practices. The actual AMP configuration within any organization will depend upon the security policy of the organization. #### Identity Services #### Identity Services provide per-user authentication and authorization of the wired and wireless LAN within the small branch design. These services include the following: -- 802.1x authentication of devices connected to wired switch ports with fallback to MAB for devices without 802.1x supplicant support, such as printers. -- Per-user access control via Group Policy assignment or VLAN assignment upon device authentication to a wired switch port. -- WPA2-Enterprise or WPA3-Enterprise with 802.1x authentication for non-Guest SSIDs. -- Per-user access control via Group Policy assignment or VLAN assignment upon device authentication to an access point. -- External ISE / Radius or Meraki Cloud authentication server. +- 802.1x authentication of devices connected to wired switch access ports or the wireless Data SSID, with fallback to MAB for devices without 802.1x supplicant support, such as printers. +- Per-user access control via Group Policy assignment or VLAN assignment upon device authentication. +- External RADIUS and RADIUS accounting servers. -For Release 1 - Early Availability, identity services have not been implemented and validated for the small branch design. Work is ongoing to add configurations for Identity services to the YAML files within the repository. \ No newline at end of file +Identity Services configurations for APs are found in the *wireless* template within the *templates-wireless.nac.yaml* file. Likewise Identity Services configurations for switches are found in the *switch* template within the *templates-switch.nac.yaml* file. Finally Group Policy definitions used for VLAN assignment upon authentication to the defined RADIUS servers is found within the *group_policies* template within the *templates-network-related.nac.yaml* file. \ No newline at end of file diff --git a/docs/as_code_defintions.md b/docs/as_code_defintions.md new file mode 100644 index 0000000..a781af3 --- /dev/null +++ b/docs/as_code_defintions.md @@ -0,0 +1,51 @@ + +# IaC to SaC β€” The Acronym Journey, Because Even Networks Deserve Version Control + + +## Infrastructure as Code (IaC) + +**Infrastructure as Code (IaC)** defines and manages infrastructure configurations through code, enabling **declarative**, **version-controlled**, and **automated** provisioning of network devices and services. +It integrates with CI/CD pipelines and commonly uses tools such as **Terraform** for orchestration and programmatic infrastructure management. + + +## Network as Code (NaC) + +[**Network as Code (NaC)**](https://netascode.cisco.com) extends Infrastructure as Code (IaC) principles to network configuration and policy management. NaC supports Cisco solutions such as ACI, SD-WAN, Meraki, Nexus Dashboard, and Catalyst Center, ensuring consistent, reliable, and auditable network operations. It provides a single source of truth for configurations, automated deployment pipelines, and integrated testing and observability to guarantee network reliability and compliance. +## Meraki as Code + +[**Meraki as Code**](https://netascode.cisco.com/docs/data_models/meraki/overview/) is a specialized implementation of Services as Code for Cisco Meraki’s cloud-managed platform. +It enables **programmatic management** and **automation** of network devices and configurations through the **Meraki API** and **Terraform**. +This approach supports **declarative infrastructure management** and enables seamless integration with CI/CD pipelines. + + +## Branch as Code (BaC) + +[**Branch as Code**](https://netascode.cisco.com/docs/guides/branch/00_overview/) automates and manages branch office network infrastructure as code. +It streamlines deployment and scaling of branch environments using **Terraform** and Cisco’s **validated Unified Branch designs**, ensuring consistency and agility across distributed sites. + +## Services as Code (SaC) + +[**Services as Code (SaC)**](https://www.cisco.com/site/us/en/services/professional/index.html) is a Cisco Lifecycle Services subscription that enables enterprises to define, manage, and operate their network infrastructure and services as software code. +It applies **DevSecOps** and **automation principles** to network operations, enabling: + +- Version control of configurations +- Automated provisioning, testing, and deployment +- Integration with CI/CD pipelines +- Continuous validation and lifecycle management + +By treating network services as code, SaC reduces manual errors, improves change success rates, and accelerates the adoption of new technologies. + +SaC includes: +- Readiness assessments +- Enablement of people, processes, and solutions +- Continuous integration setup +- Automated deployment and release management +- 24x7 operational support + +It supports Cisco technologies such as **ACI**, **SD-WAN**, **Nexus Dashboard**, **ISE**, **Catalyst Center**, **Meraki**, and **Unified Branch**. + +## Relationship Summary + +- **Network as Code (NaC)** is the **foundation**, applying Infrastructure as Code principles to networking. +- **ACI as Code**, **Meraki as Code**, **VXLAN as Code**, **ISE as Code**, and **Branch as Code** are **specialized implementations** of NaC for specific Cisco technologies. +- **Services as Code (SaC)** is the Cisco Services Subscription that unifies these implementations into a comprehensive automation and management methodologyβ€”enabling enterprises to manage their entire network and security services ecosystem as code. diff --git a/docs/images/mx-secure-router-ports.png b/docs/images/mx-secure-router-ports.png new file mode 100644 index 0000000..b05d12e Binary files /dev/null and b/docs/images/mx-secure-router-ports.png differ diff --git a/docs/images/steps.png b/docs/images/steps.png new file mode 100644 index 0000000..886269e Binary files /dev/null and b/docs/images/steps.png differ diff --git a/docs/images/unified_branch_architecture_small_branch.png b/docs/images/unified_branch_architecture_small_branch.png new file mode 100644 index 0000000..a1baa41 Binary files /dev/null and b/docs/images/unified_branch_architecture_small_branch.png differ diff --git a/docs/images/wlan-ap-ports.png b/docs/images/wlan-ap-ports.png new file mode 100644 index 0000000..ecbcbc5 Binary files /dev/null and b/docs/images/wlan-ap-ports.png differ diff --git a/main.tf b/main.tf index e660646..cd68cc0 100644 --- a/main.tf +++ b/main.tf @@ -1,13 +1,6 @@ -terraform { - required_providers { - meraki = { - source = "ciscodevnet/meraki" - version = "= 1.5.0" # Fixed to 1.5.0 untill Port IDs moved to range, PR #1677 - } - } -} + module "meraki" { - source = "github.com/netascode/terraform-meraki-nac-meraki?ref=v0.3.4" - yaml_directories = ["data/"] -} \ No newline at end of file + source = "github.com/netascode/terraform-meraki-nac-meraki?ref=v0.5.0" + yaml_directories = ["data"] +} diff --git a/rules/101_unique_keys.py b/rules/101_unique_keys.py new file mode 100644 index 0000000..4cb2aea --- /dev/null +++ b/rules/101_unique_keys.py @@ -0,0 +1,69 @@ +class Rule: + id = "101" + description = "Verify unique keys" + severity = "HIGH" + + paths = [ + "meraki.domains.name", + "meraki.domains.organizations.name", + "meraki.domains.organizations.networks.name", + "meraki.domains.organizations.administrators.name", + "meraki.domains.organizations.networks.switch_stacks.name", + "meraki.domains.organizations.action_batches.action_batch_name", + "meraki.domains.organizations.adaptive_policy_acls.name" + "meraki.domains.organizations.adaptive_policy_acls.rules.name", + "meraki.domains.organizations.networks.appliance.ports.port_id_ranges.from", + "meraki.domains.organizations.networks.appliance.ports.port_id_ranges.to", + ] + + @classmethod + def match_path(cls, inventory, full_path, search_path): + results = [] + path_elements = search_path.split(".") + inv_element = inventory + for idx, path_element in enumerate(path_elements[:-1]): + if isinstance(inv_element, dict): + inv_element = inv_element.get(path_element) + elif isinstance(inv_element, list): + for i in inv_element: + r = cls.match_path(i, full_path, ".".join(path_elements[idx:])) + results.extend(r) + return results + if inv_element is None: + return results + values = [] + if isinstance(inv_element, list): + for i in inv_element: + if not isinstance(i, dict): + continue + value = i.get(path_elements[-1]) + if isinstance(value, list): + values = [] + for v in value: + if v not in values: + values.append(v) + else: + results.append(full_path + " - " + str(v)) + elif value: + if value not in values: + values.append(value) + else: + results.append(full_path + " - " + str(value)) + elif isinstance(inv_element, dict): + list_element = inv_element.get(path_elements[-1]) + if isinstance(list_element, list): + for value in list_element: + if value: + if value not in values: + values.append(value) + else: + results.append(full_path + " - " + str(value)) + return results + + @classmethod + def match(cls, inventory): + results = [] + for path in cls.paths: + r = cls.match_path(inventory, path, path) + results.extend(r) + return results diff --git a/tests/templates/config/__init__.robot b/tests/templates/config/__init__.robot new file mode 100644 index 0000000..6d9a898 --- /dev/null +++ b/tests/templates/config/__init__.robot @@ -0,0 +1,4 @@ +*** Settings *** +Library pabot.PabotLib +Library ../myutils.py +Suite Setup Run Setup Only Once Clear Meraki API Cache diff --git a/tests/templates/config/networks_appliance_traffic_shaping_rules.robot b/tests/templates/config/networks_appliance_traffic_shaping_rules.robot new file mode 100644 index 0000000..32a9082 --- /dev/null +++ b/tests/templates/config/networks_appliance_traffic_shaping_rules.robot @@ -0,0 +1,33 @@ + +*** Settings *** +Library String +Library ../myutils.py + +*** Test Cases *** +{% for domain in meraki.domains | default([], true) %} +{% for organization in domain.organizations | default([], true) %} +{% for network in organization.networks | default([], true) %} + +{% set appliance_traffic_shaping_rules = network.appliance.traffic_shaping.rules | default({}, true) %} +Verify {{ organization.name }}/networks/{{ network.name }}/appliance_traffic_shaping_rules/default_rules{% if appliance_traffic_shaping_rules.default_rules is defined %} + [Setup] Get Meraki Data /networks/{networkId}/appliance/trafficShaping/rules ['{{ organization.name }}', '{{ network.name }}'] appliance_traffic_shaping_rules + Should Be Equal As Strings ${appliance_traffic_shaping_rules}[defaultRulesEnabled] {{ appliance_traffic_shaping_rules.default_rules }} + +{% else %} + Skip appliance_traffic_shaping_rules.default_rules is not defined +{% endif %} +Verify {{ organization.name }}/networks/{{ network.name }}/appliance_traffic_shaping_rules/rules{% if appliance_traffic_shaping_rules.rules is defined %} + [Setup] Get Meraki Data /networks/{networkId}/appliance/trafficShaping/rules ['{{ organization.name }}', '{{ network.name }}'] appliance_traffic_shaping_rules + ${evaluated}= Evaluate {{ appliance_traffic_shaping_rules.rules }} + ${evaluated}= Map Application IDs To API ${evaluated} path=definitions + ${validated}= Validate Subset ${appliance_traffic_shaping_rules}[rules] ${evaluated} ['definitions.type', 'definitions.value', 'per_client_bandwidth_limits.settings', 'per_client_bandwidth_limits.bandwidth_limits.limit_up', 'per_client_bandwidth_limits.bandwidth_limits.limit_down', 'dscp_tag_value', 'priority'] + Should Be True ${validated} + +{% else %} + Skip appliance_traffic_shaping_rules.rules is not defined +{% endif %} + + +{% endfor %} +{% endfor %} +{% endfor %} diff --git a/tests/templates/config/networks_list.robot b/tests/templates/config/networks_list.robot new file mode 100644 index 0000000..eff5ca2 --- /dev/null +++ b/tests/templates/config/networks_list.robot @@ -0,0 +1,74 @@ + +*** Settings *** +Library String +Library ../myutils.py + +*** Test Cases *** +{% for domain in meraki.domains | default([], true) %} +{% for organization in domain.organizations | default([], true) %} +{% for network in organization.networks | default([], true) %} + +# Note: id is not checked, as it is only included in the response, +# but not in the OpenAPI request, hence not in the .nac.yaml schema. +# Note: organizationId is not checked, as it is only included in the response, +# but not in the OpenAPI request, hence not in the .nac.yaml schema. +Verify {{ organization.name }}/networks/{{ network.name }}//name{% if network.name is defined %} + [Setup] Get Meraki Data /networks/{networkId} ['{{ organization.name }}', '{{ network.name }}'] network + Should Be Equal As Strings ${network}[name] {{ network.name }} + +{% else %} + Skip network.name is not defined +{% endif %} +Verify {{ organization.name }}/networks/{{ network.name }}//product_types{% if network.product_types is defined %} + [Setup] Get Meraki Data /networks/{networkId} ['{{ organization.name }}', '{{ network.name }}'] network + ${evaluated}= Evaluate {{ network.product_types }} + ${validated}= Validate Subset ${network}[productTypes] ${evaluated} + Should Be True ${validated} + +{% else %} + Skip network.product_types is not defined +{% endif %} +Verify {{ organization.name }}/networks/{{ network.name }}//time_zone{% if network.time_zone is defined %} + [Setup] Get Meraki Data /networks/{networkId} ['{{ organization.name }}', '{{ network.name }}'] network + Should Be Equal As Strings ${network}[timeZone] {{ network.time_zone }} + +{% else %} + Skip network.time_zone is not defined +{% endif %} +Verify {{ organization.name }}/networks/{{ network.name }}//tags{% if network.tags is defined %} + [Setup] Get Meraki Data /networks/{networkId} ['{{ organization.name }}', '{{ network.name }}'] network + ${evaluated}= Evaluate {{ network.tags }} + ${validated}= Validate Subset ${network}[tags] ${evaluated} + Should Be True ${validated} + +{% else %} + Skip network.tags is not defined +{% endif %} +Verify {{ organization.name }}/networks/{{ network.name }}//enrollment_string{% if network.enrollment_string is defined %} + [Setup] Get Meraki Data /networks/{networkId} ['{{ organization.name }}', '{{ network.name }}'] network + Should Be Equal As Strings ${network}[enrollmentString] {{ network.enrollment_string }} + +{% else %} + Skip network.enrollment_string is not defined +{% endif %} +# Note: url is not checked, as it is only included in the response, +# but not in the OpenAPI request, hence not in the .nac.yaml schema. +Verify {{ organization.name }}/networks/{{ network.name }}//notes{% if network.notes is defined %} + [Setup] Get Meraki Data /networks/{networkId} ['{{ organization.name }}', '{{ network.name }}'] network + Should Be Equal As Strings ${network}[notes] {{ network.notes }} + +{% else %} + Skip network.notes is not defined +{% endif %} +Verify {{ organization.name }}/networks/{{ network.name }}//is_bound_to_config_template{% if network.is_bound_to_config_template is defined %} + [Setup] Get Meraki Data /networks/{networkId} ['{{ organization.name }}', '{{ network.name }}'] network + Should Be Equal As Strings ${network}[isBoundToConfigTemplate] {{ network.is_bound_to_config_template }} + +{% else %} + Skip network.is_bound_to_config_template is not defined +{% endif %} + +{% endfor %} + +{% endfor %} +{% endfor %} diff --git a/tests/templates/meraki_request.py b/tests/templates/meraki_request.py new file mode 100644 index 0000000..9ad5d3e --- /dev/null +++ b/tests/templates/meraki_request.py @@ -0,0 +1,209 @@ +# meraki_request.py +import requests +import os +import urllib.parse +from robot.api import logger +import time, random, json + +# Code ported from https://github.com/meraki/dashboard-api-python/releases/tag/2.0.2 +# Python SDK release 2.0.2 + +# Local constants +API_BASE = "https://api.meraki.com/api/v1" +MAXIMUM_RETRIES = 2 +API_KEY_ENVIRONMENT_VARIABLE = 'MERAKI_API_KEY' +NGINX_429_RETRY_WAIT_TIME = 10 +ACTION_BATCH_RETRY_WAIT_TIME = 10 +NETWORK_DELETE_RETRY_WAIT_TIME = 240 +RETRY_4XX_ERROR = False +RETRY_4XX_ERROR_WAIT_TIME = 1 + +# To catch exceptions while making API calls (ported from Meraki Python SDK) +class APIError(Exception): + def __init__(self, response): + self.response = response + self.status = ( + self.response.status_code + if self.response is not None and self.response.status_code + else None + ) + self.reason = ( + self.response.reason + if self.response is not None and self.response.reason + else None + ) + try: + self.message = ( + self.response.json() + if self.response is not None and self.response.json() + else None + ) + except ValueError: + self.message = self.response.content[:100].decode("UTF-8").strip() + if ( + type(self.message) == str + and self.status == 404 + and self.reason == "Not Found" + ): + self.message += ( + "please wait a minute if the key or org was just newly created." + ) + super(APIError, self).__init__( + f"{self.status} {self.reason}, {self.message}" + ) + + def __repr__(self): + return f"{self.status} {self.reason}, {self.message}" + +# API key error (ported from Meraki Python SDK) +class APIKeyError(Exception): + def __init__(self): + self.message = "Meraki API key needs to be defined" + super(APIKeyError, self).__init__(self.message) + + def __repr__(self): + return self.message + +# Setup request session for reuse throughout the run +def request_session(api_key=None): + # Check API key + api_key = api_key or os.environ.get(API_KEY_ENVIRONMENT_VARIABLE) + if not api_key: + raise APIKeyError() + session = requests.session() + session.encoding = 'utf-8' + session.headers = { + 'Authorization': 'Bearer ' + api_key, + 'Content-Type': 'application/json', + 'User-Agent': f'nac-robot/{requests.__version__}', + } + return session + +# Request with API error handling (ported from Meraki Python SDK) +def request(req_session, method, url, **kwargs): + base_url = API_BASE + + # Ensure proper base URL + allowed_domains = ['meraki.com', 'meraki.ca', 'meraki.cn', 'meraki.in', 'gov-meraki.com'] + parsed_url = urllib.parse.urlparse(url) + + if any(domain in parsed_url.netloc for domain in allowed_domains): + abs_url = url + else: + abs_url = base_url + url + + # Set maximum number of retries + retries = MAXIMUM_RETRIES + + response = None + while retries > 0: + # Make the HTTP request to the API endpoint + try: + if response: + response.close() + logger.info(f'{method} {abs_url}') + response = req_session.request(method, abs_url, allow_redirects=False, + **kwargs) + reason = response.reason if response.reason else '' + status = response.status_code + except requests.exceptions.RequestException as e: + logger.info(f'{method}, {abs_url} - {e}, retrying in 1 second') + time.sleep(1) + retries -= 1 + if retries == 0: + if e.response: + raise APIError(e.response) + else: + raise Exception(f'Request failed for {method} {abs_url} - {e}') + else: + continue + + # Handle 3XX redirects automatically + if str(status)[0] == '3': + abs_url = response.headers['Location'] + substring = 'meraki.com/api/v' + if substring not in abs_url: + substring = 'meraki.cn/api/v' + base_url = abs_url[:abs_url.find(substring) + len(substring) + 1] + + # 2XX success + elif response.ok: + logger.info(f'{method}, {abs_url} - {status} {reason}') + # For non-empty response to GET, ensure valid JSON + try: + if method == 'GET' and response.content.strip(): + response.json() + return response + except json.decoder.JSONDecodeError as e: + logger.info(f'{method}, {abs_url} - {e}, retrying in 1 second') + time.sleep(1) + retries -= 1 + if retries == 0: + raise APIError(response) + else: + continue + + # Rate limit 429 errors + elif status == 429: + if 'Retry-After' in response.headers: + wait = int(response.headers['Retry-After']) + else: + wait = random.randint(1, NGINX_429_RETRY_WAIT_TIME) + logger.info(f'{method}, {abs_url} - {status} {reason}, retrying in {wait} seconds') + time.sleep(wait) + retries -= 1 + if retries == 0: + raise APIError(response) + + # 5XX errors + elif status >= 500: + logger.info(f'{method}, {abs_url} - {status} {reason}, retrying in 1 second') + time.sleep(1) + retries -= 1 + if retries == 0: + raise APIError(response) + + # 4XX errors + else: + try: + message = response.json() + message_is_dict = True + except ValueError: + message = response.content[:100] + message_is_dict = False + + # Check for specific concurrency errors + network_delete_concurrency_error_text = 'This may be due to concurrent requests to delete networks.' + action_batch_concurrency_error = {'errors': [ + 'Too many concurrently executing batches. Maximum is 5 confirmed but not yet executed batches.'] + } + # Check specifically for network delete concurrency error + if message_is_dict and 'errors' in message.keys() \ + and network_delete_concurrency_error_text in message['errors'][0]: + wait = random.randint(30, NETWORK_DELETE_RETRY_WAIT_TIME) + logger.info(f'{method}, {abs_url} - {status} {reason}, retrying in {wait} seconds') + time.sleep(wait) + retries -= 1 + if retries == 0: + raise APIError(response) + # Check specifically for action batch concurrency error + elif message == action_batch_concurrency_error: + wait = ACTION_BATCH_RETRY_WAIT_TIME + logger.info(f'{method}, {abs_url} - {status} {reason}, retrying in {wait} seconds') + time.sleep(wait) + retries -= 1 + if retries == 0: + raise APIError(response) + elif RETRY_4XX_ERROR: + wait = random.randint(1, RETRY_4XX_ERROR_WAIT_TIME) + logger.info(f'{method}, {abs_url} - {status} {reason}, retrying in {wait} seconds') + time.sleep(wait) + retries -= 1 + if retries == 0: + raise APIError(response) + + # All other client-side errors + else: + logger.info(f'{method}, {abs_url} - {status} {reason}, {message}') + raise APIError(response) + diff --git a/tests/templates/myutils.py b/tests/templates/myutils.py new file mode 100644 index 0000000..96892a0 --- /dev/null +++ b/tests/templates/myutils.py @@ -0,0 +1,534 @@ +# utils.py +import re, time, requests, json +from robot.api import logger +import urllib.parse +from robot.libraries.BuiltIn import BuiltIn +import fcntl +import os +import random +from meraki_request import ( + request_session, request, APIError, APIKeyError, +) + +# Constants +API_PATH_ID_REGEX = r'{[a-zA-Z]*}' +API_BASE = "https://api.meraki.com/api/v1" +CACHE_FILE = "cache.json" +LOCK_FILE = "cache.json.lock" +THROTTLE_LOCK_FILE = "meraki_api_throttle.lock" +THROTTLE_SLEEP_SECONDS = 0.1 # Meraki limit = 10 req/sec + +def throttle_request(): + lock = FileLock(THROTTLE_LOCK_FILE) + lock.acquire() + try: + time.sleep(THROTTLE_SLEEP_SECONDS) + finally: + lock.release() + +def to_snake_case(text): + text = re.sub(r'(? 0: + subset = filter_by_whitelist(subset, whitelist) + return _validate_subset(superset, subset) + +def unflatten_dicts(data, add_key): + """ + Make a single-item dict with add_key as the key and data as the value. + If data is a list, make each item a single-item dict. + + >>> unflatten_dicts(["a", "b"], "name") + [{"name": "a"}, {"name": "b"}] + + The usecase is adjusting YAML data + that is flattened in the .nac.yaml schema compared to Meraki API + back to a Meraki-API-like format for comparison with the API's response. + """ + + if isinstance(data, list): + return [{add_key: i} for i in data] + + return {add_key: data} + +def unflatten_dicts_in_property(data, prop, add_key): + """ + Return data with its prop key's value replaced + with a single-item dict with add_key as the key. + If data is a list, transform each item's prop key. + If the prop key's value is a list, + replace each item with a single-item dict. + + >>> unflatten_dicts_in_property([ + {"acls": ["a", "b"], "organization_name": "Dev"}, + {"acls": ["c", "d"]}, + ], "acls", "name") + [ + {"acls": [{"name": "a"}, {"name": "b"}], "organization_name": "Dev"}, + {"acls": [{"name: c"}, {"name": "d"}]}, + ] + + The usecase is adjusting YAML data + in a list of resources that has to be compared to the API response as a whole + as opposed to comparing the individual resources + (which is not possible due to lack of names in the API + to correlate individual resources with the YAML counterparts). + """ + + # TODO Allow property to be a path like prop1.prop2 when that becomes needed. + + if isinstance(data, list): + return [unflatten_dicts_in_property(i, prop, add_key) for i in data] + + return { + k: unflatten_dicts(v, add_key) if k == prop else v + for k, v in data.items() + } + +def get_list_item_by_key(l, key, value): + """ + Return the first element of l that has the given key with the given value. + + >>> get_list_item_by_key([ + {"networkName": "a", "data": "a_data"}, + {"networkName": "b", "data": "b_data"}, + ], "networkName", "a") + {"networkName": "a", "data": "a_data"} + + The usecase is e.g. extracting data for a particular network + from the response of an organization-level endpoint. + """ + + try: + return next((item for item in l if item.get(key) == value)) + except (StopIteration, AttributeError): + raise Exception(f"Dict with {key} == {value} is not found in list {l}") + +def _get_switch_stack_id(stacks, name): + for s in stacks: + if s["id"] == name: + return s["name"] + raise Exception("switch stack "+name+" not found") + +def _fix_switch_stacks(stp, stacks): + logger.info(stp) + logger.info(stacks) + return [ + { + "stacks": [_get_switch_stack_id(stacks, j) for j in i.get("stacks", [])] if i.get("stacks", None) is not None else None, + "switches": i.get("switches", None), + "stpPriority": i["stpPriority"], + "switchProfiles": i.get("switchProfiles", None) + } for i in stp + ] + +class FileLock: + """Implements a file-based lock using flock(2). + The lock file is saved in directory dir with name lock_name. + dir is the current directory by default. + """ + + def __init__(self, lock_name, dir="."): + self.lock_file = open(os.path.join(dir, lock_name), "w") + + def acquire(self, blocking=True): + """Acquire the lock. + If the lock is not already acquired, return None. If the lock is + acquired and blocking is True, block until the lock is released. If + the lock is acquired and blocking is False, raise an IOError. + """ + ops = fcntl.LOCK_EX + if not blocking: + ops |= fcntl.LOCK_NB + fcntl.flock(self.lock_file, ops) + + def release(self): + """Release the lock. Return None even if lock not currently acquired""" + fcntl.flock(self.lock_file, fcntl.LOCK_UN) + +def _delete_cache(): + # Note: this doesn't handle locking, + # but that's fine since this should only be used + # with Pabot's "Run Setup Only Once" in the top-level Robot suite setup. + if os.path.exists(CACHE_FILE): + os.remove(CACHE_FILE) + if os.path.exists(LOCK_FILE): + os.remove(LOCK_FILE) + logger.info("Cleared Meraki API response cache") + +def _get_request_caching(session, url): + if os.path.exists(CACHE_FILE): + lock = FileLock(LOCK_FILE) + lock.acquire() + with open(CACHE_FILE, "r") as f: + contents = f.read() + cache = json.loads(contents) + if url in cache: + lock.release() + logger.info(f"Returning url {url} result from cache: {cache[url]}") + return cache[url] + lock.release() + throttle_request() + r = request(session, "GET", url) + lock = FileLock(LOCK_FILE) + lock.acquire() + if os.path.exists(CACHE_FILE): + with open(CACHE_FILE, "r") as f: + contents = f.read() + cache = json.loads(contents) + else: + cache = {} + rjson = r.json() + cache[url] = rjson + with open(CACHE_FILE, "w") as f: + f.write(json.dumps(cache)) + lock.release() + logger.info(f"Returning url {url} result from a fresh request: {rjson}") + return rjson + +def _get_resource_id(resource, possible_id_props): + for id_prop in possible_id_props: + if id_prop in resource: + return str(resource[id_prop]) + raise Exception("could not find id by possible ids:" + json.dumps(resource) +" "+json.dumps(possible_id_props)) + +special_res_names = { + "switch/routing/multicast/rendezvousPoints": "interfaceIp", + "earlyAccess/features/optIns": "shortName", +} + +def _get_child_data(session, api_path, url_acc, resource_names, id_props): + url_acc += "/"+api_path[0] + resources = _get_request_caching(session, url_acc.strip("/")) + if len(api_path) == 1: + return resources + logger.info(f"getting child data {api_path[0]}") + res_id = special_res_names.get(api_path[0], "name") + for r in resources: + print(r) + if r[res_id] == resource_names[0]: + return _get_child_data(session, api_path[1:], url_acc+"/"+_get_resource_id(r, id_props), resource_names[1:], id_props) + raise Exception("could not find resource by name") + +def _set_suite_var(var, data): + try: + BuiltIn().set_suite_variable(f"${{{var}}}", data) + except: + pass + +def _fix_devices_serials(session, obj, org_id): + logger.info(f"obj {obj} org_id {org_id}") + devices_map = {d["serial"]: d["name"] for d in _get_request_caching(session, f"{API_BASE}/organizations/{org_id}/devices")} + obj["device"] = devices_map[obj["serial"]] + return obj + +def get_meraki_data(url, resource_names, suite_variable): + resource_names = eval(resource_names) + data = _get_meraki_data(url, resource_names) + _set_suite_var(suite_variable, data) + return data + +def _get_meraki_data(url, resource_names): + session = request_session() + possible_ids = _possible_id_props_from_url(url) + api_path = [p.strip("/") for p in re.split(API_PATH_ID_REGEX, url)] + org_resource = False + if api_path[0] == "organizations": + api_path = api_path[1:] + org_resource = True + orgs = _get_request_caching(session, API_BASE+"/organizations") + org_id = None + for org in orgs: + if org["name"] == resource_names[0]: + org_id = org["id"] + if org_id is None: + raise Exception(f"Could not find organization named {resource_names[0]} in {orgs}") + if org_resource: + print(api_path, resource_names) + return _get_child_data(session, api_path, f"{API_BASE}/organizations/{org_id}", resource_names[1:], possible_ids) + top_resource_id_name = "id" + if api_path[0] == "devices": + top_resource_id_name = "serial" + top_resources = _get_request_caching(session, f"{API_BASE}/organizations/{org_id}/{api_path[0]}") + top_resource_id = None + for t in top_resources: + if t["name"] == resource_names[1]: + top_resource_id = t[top_resource_id_name] + url_acc = f"{API_BASE}/{api_path[0]}/{top_resource_id}" + child_data = _get_child_data(session, api_path[1:], url_acc, resource_names[2:], possible_ids) + logger.info(f"get {url}") + if url == "/networks/{networkId}/switch/stp": + stacks = _get_request_caching(session, f"https://api.meraki.com/api/v1/networks/{top_resource_id}/switch/stacks") + new_stp_bridge_priority = _fix_switch_stacks(child_data["stpBridgePriority"], stacks) + child_data["stpBridgePriority"] = new_stp_bridge_priority + if url == "/networks/{networkId}/wireless/alternateManagementInterface": + child_data["accessPoints"] = [_fix_devices_serials(session, x, org_id) for x in child_data["accessPoints"]] + if url == "/networks/{networkId}/switch/linkAggregations": + for agg in child_data: + for p in agg['switchPorts']: + _fix_devices_serials(session, p, org_id) + if url == "/networks/{networkId}/appliance/ports": + for p in child_data: + p["port_id"] = p["number"] + return child_data + +def _possible_id_props_from_url(url): + return [x.strip("{}") for x in re.findall(API_PATH_ID_REGEX, url)+["id", "groupId"]][1:] + +def validate_per_ssid_settings(all_ssids, my_ssid): + ssids_map = {d["name"].lower() : d for _, d in all_ssids.items()} + return validate_subset(ssids_map[my_ssid["ssid_name"].lower()], {k : v for k, v in my_ssid.items() if k != "ssid_name"}) + +def validate_appliance_per_ssid_settings(api_data, my_data, ssids): + ssids_numbers = {s["name"].lower() : s["number"] for s in ssids} + logger.info("ssids_numbers") + logger.info(ssids_numbers) + per_ssid_settings = {str(ssids_numbers[s["ssid_name"]]) : {k : v for k, v in s.items() if k != "ssid_name"} for s in my_data} + logger.info("per_ssid_settings") + logger.info(per_ssid_settings) + return validate_subset(api_data, per_ssid_settings) + +def _map_application_id_to_api(type_value_dict): + new_type_value_dict = type_value_dict.copy() + if type_value_dict.get("type") in ("application", "applicationCategory"): + new_type_value_dict["value"] = {"id": type_value_dict["value"]} + return new_type_value_dict + +def _map_country_id_to_api(type_value_dict): + new_type_value_dict = type_value_dict.copy() + if type_value_dict.get("type") in ("blockedCountries", "allowedCountries"): + new_type_value_dict["value"] = type_value_dict["value_countries"] + del new_type_value_dict["value_countries"] + return new_type_value_dict + +def _map_at_path(data, path, func): + if isinstance(data, list): + return [_map_at_path(item, path, func) for item in data] + + if path == "": + return func(data) + + if not isinstance(data, dict): + # Nothing at path, so nothing to change - return data as is. + return data + + steps = path.split(".") + next_step, further_steps = steps[0], steps[1:] + further_path = ".".join(further_steps) + + new_data = data.copy() + if next_step in data: + new_data[next_step] = _map_at_path(new_data[next_step], further_path, func) + return new_data + +def map_application_ids_to_api(data, path=""): + """ + Adjust the data from YAML to match the API format like the provider does: + https://github.com/CiscoDevNet/terraform-provider-meraki/blob/5e28e94fb9feaddb7e0e20cceaf848cc565b6ab2/internal/provider/model_meraki_appliance_l7_firewall_rules.go#L74-L81 + """ + + return _map_at_path(data, path, _map_application_id_to_api) + +def map_country_ids_to_api(data, path=""): + """ + Adjust the data from YAML to match the API format like the provider does: + https://github.com/CiscoDevNet/terraform-provider-meraki/blob/5e28e94fb9feaddb7e0e20cceaf848cc565b6ab2/internal/provider/model_meraki_appliance_l7_firewall_rules.go#L82-L86 + """ + + return _map_at_path(data, path, _map_country_id_to_api) + +def map_names_to_ids(data, url, parent_names, path="", name_prop="", id_prop=""): + """ + Convert names to IDs at path + by fetching url (like "Get Meraki Data "). + If name_prop is not "", take names from .. + If id_prop is not "", put names at ., replacing . if any. + + >>> map_names_to_ids(["netascode-network-01"], "/networks/{networkId}", "['Dev-WB']") + ['L_4005951868546057359'] + + >>> map_names_to_ids( + [ + { + "performance_class": { + "custom_performance_class_name": "Radius", + "type": "custom", + }, + }, + ], + "/networks/{networkId}/appliance/trafficShaping/customPerformanceClasses/{customPerformanceClassId}", + "['Dev-WB', 'netascode-network-01']", + path="performance_class", + name_prop="custom_performance_class_name", + id_prop="custom_performance_class_id") + [ + { + "performance_class": { + "custom_performance_class_id": "4005951868546056226", + "type": "custom", + }, + }, + ] + + """ + + parent_names = eval(parent_names) + return _map_at_path(data, path, lambda data: _map_name_to_id(data, url, parent_names, name_prop, id_prop)) + +def _map_name_to_id(data, url, parent_names, name_prop, id_prop): + if name_prop != "": + name = data.get(name_prop) + if name is None: + return data + else: + name = data + + resource = _get_meraki_data(url, parent_names + [name]) + resource_id_props = _possible_id_props_from_url(url) + id = _get_resource_id(resource, resource_id_props) + + if id_prop != "": + if not isinstance(data, dict): + data = {} + new_data = data.copy() + if name_prop != "": + new_data.pop(name_prop, None) + new_data[id_prop] = id + return new_data + else: + return id + +def rename_property(data, old_name, new_name, path=""): + """ + If data[old_name] exists at path, rename it to data[new_name]. + + >>> rename_property( + [ + {'ipv4_address': '1.2.3.4', 'trusted_server_name': 's1'}, + {'ipv4_address': '1.2.3.4', 'trusted_server_name': 's2'}, + ], + "ipv4_address", + "ipv4") + [ + {'ipv4': '1.2.3.4', 'trusted_server_name': 's1'}, + {'ipv4': '1.2.3.4', 'trusted_server_name': 's2'}, + ] + """ + + return _map_at_path(data, path, lambda data: _rename_property(data, old_name, new_name)) + +def _rename_property(data, old_name, new_name): + new_data = data.copy() + if old_name in new_data: + new_data[new_name] = new_data[old_name] + del new_data[old_name] + + return new_data + +def clear_meraki_api_cache(): + _delete_cache() diff --git a/workspaces/.terraform/providers/registry.terraform.io/hashicorp/local/2.5.3/darwin_arm64/LICENSE.txt b/workspaces/.terraform/providers/registry.terraform.io/hashicorp/local/2.5.3/darwin_arm64/LICENSE.txt deleted file mode 100644 index b9ac071..0000000 --- a/workspaces/.terraform/providers/registry.terraform.io/hashicorp/local/2.5.3/darwin_arm64/LICENSE.txt +++ /dev/null @@ -1,375 +0,0 @@ -Copyright (c) 2017 HashiCorp, Inc. - -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/workspaces/main.tf b/workspaces/main.tf index 819057c..a7047cf 100644 --- a/workspaces/main.tf +++ b/workspaces/main.tf @@ -1,7 +1,5 @@ module "model" { - source = "github.com/netascode/terraform-meraki-nac-meraki/modules/model" - yaml_directories = ["../data"] - write_model_file = "merged_configuration.nac.yaml" - } - - \ No newline at end of file + source = "github.com/netascode/terraform-meraki-nac-meraki/modules/model" + yaml_directories = ["../data"] + write_model_file = "merged_configuration.nac.yaml" +} \ No newline at end of file