diff --git a/roles/azure_controllers/README.md b/roles/azure_controllers/README.md
index 5a9cc4d..5c94f46 100644
--- a/roles/azure_controllers/README.md
+++ b/roles/azure_controllers/README.md
@@ -47,6 +47,7 @@ The `azure_controllers` role automates the deployment of Cisco SD-WAN controller
- `az_vmanage_vm_size`, `az_vbond_vm_size`, `az_vsmart_vm_size`: Azure VM sizes for vManage, vBond, and vSmart instances.
- `site_id_vmanage`, `site_id_vbond`, `site_id_vsmart`: Default site IDs for vManage, vBond, and vSmart instances.
- `vmanage_instances`, `vbond_instances`, `vsmart_instances`: Lists for instance configurations.
+- `ipv6_strict_control`: Control if ipv6-strict-control is enabled.
### Vars (`vars/main.yml`)
diff --git a/roles/azure_controllers/defaults/main.yml b/roles/azure_controllers/defaults/main.yml
index 24de968..bc9d93f 100644
--- a/roles/azure_controllers/defaults/main.yml
+++ b/roles/azure_controllers/defaults/main.yml
@@ -24,22 +24,30 @@ az_vn_address_prefixes_cidr: 10.0.0.0/16
az_subnets: |
{% filter from_yaml %}
- name: "{{ az_resources_prefix }}-mgmt-subnet-512"
- cidr: "10.0.1.0/24"
+ cidr:
+ - "10.0.1.0/24"
+ - "fd00:0:0:1::/64"
VPN: 512
type: mgmt
- name: "{{ az_resources_prefix }}-transport-subnet-0"
- cidr: "10.0.2.0/24"
+ cidr:
+ - "10.0.2.0/24"
+ - "fd00:0:0:2::/64"
VPN: 0
type: transport
{% if vmanage_instances is defined and vmanage_instances | length > 2 %}
- name: "{{ az_resources_prefix }}-cluster-subnet-0"
- cidr: "10.0.3.0/24"
+ cidr:
+ - "10.0.3.0/24"
+ - "fd00:0:0:3::/64"
VPN: 0
type: cluster
{% endif %}
{% if ux20_deployment is defined and ux20_deployment == true %}
- name: "{{ az_resources_prefix }}-service-subnet-10"
- cidr: "10.0.4.0/24" # default ips from official Cisco guides
+ cidr:
+ - "10.0.4.0/24" # default ips from official Cisco guides
+ - "fd00:0:0:4::/64"
VPN: 10
type: service
{% endif %}
@@ -49,6 +57,11 @@ az_subnets: |
az_network_security_group: "{{ az_resources_prefix }}-nsg"
+# Private DNS zone
+az_private_dns_zone: "{{ az_resources_prefix }}.internal"
+az_vbond_address: "vbond.{{ az_private_dns_zone }}"
+
+
# VPN subnets from which we can connect to Azure EIPs (Network Security Group config)
az_allowed_subnets: null
@@ -63,6 +76,7 @@ admin_password: null # pragma: allowlist secret
admin_ssh_keys: []
vbond_port: 12346
default_vbond_ip: 192.168.1.199
+ipv6_strict_control: true
# vpn0_interface_color: default
diff --git a/roles/azure_controllers/tasks/azure_vbond_vm.yml b/roles/azure_controllers/tasks/azure_vbond_vm.yml
index 6411ca0..f1e4b9a 100644
--- a/roles/azure_controllers/tasks/azure_vbond_vm.yml
+++ b/roles/azure_controllers/tasks/azure_vbond_vm.yml
@@ -19,6 +19,7 @@
Machine: "{{ hostname }}"
VPN: "{{ subnet_item.VPN }}"
Subnet: "{{ subnet_item.name }}"
+ sku: standard
loop:
- "{{ mgmt_subnet }}"
- "{{ transport_subnet }}"
@@ -26,6 +27,26 @@
loop_var: subnet_item
register: public_ip_addresses
+- name: "Create public IPv6 addresses for machine: {{ hostname }}"
+ azure.azcollection.azure_rm_publicipaddress:
+ resource_group: "{{ az_resource_group }}"
+ allocation_method: static
+ name: "public-ipv6-{{ hostname }}-vpn-{{ subnet_item.VPN }}"
+ tags:
+ Name: "public-ipv6-{{ hostname }}"
+ Creator: "{{ az_tag_creator }}"
+ Machine: "{{ hostname }}"
+ VPN: "{{ subnet_item.VPN }}"
+ Subnet: "{{ subnet_item.name }}"
+ version: ipv6
+ sku: standard
+ loop:
+ - "{{ mgmt_subnet }}"
+ - "{{ transport_subnet }}"
+ loop_control:
+ loop_var: subnet_item
+ register: public_ipv6_addresses
+
- name: "Get info about NSG: {{ az_network_security_group }}"
azure.azcollection.azure_rm_securitygroup_info:
resource_group: "{{ az_resource_group }}"
@@ -49,7 +70,7 @@
Name: "{{ az_network_security_group }}"
Creator: "{{ az_tag_creator }}"
Organization: "{{ organization_name }}"
- loop: "{{ public_ip_addresses.results }}"
+ loop: "{{ public_ip_addresses.results + public_ipv6_addresses.results }}"
loop_control:
loop_var: public_ip_state
index_var: my_idx
@@ -67,6 +88,10 @@
- name: "ipconfig-vpn-{{ public_ip_state.state.tags.VPN }}"
public_ip_address_name: "{{ public_ip_state.state.name }}"
private_ip_allocation_method: "Dynamic"
+ - name: "ipconfig-vpn-{{ public_ip_state.state.tags.VPN }}-ipv6"
+ public_ip_address_name: "{{ public_ipv6_addresses.results | json_query(_public_ip_query) | first }}"
+ private_ip_allocation_method: "Dynamic"
+ private_ip_address_version: IPv6
tags:
Name: "nic-{{ hostname }}-vpn-{{ public_ip_state.state.tags.VPN }}"
Creator: "{{ az_tag_creator }}"
@@ -78,30 +103,41 @@
index_var: my_idx
label: public_ip_state.state.name
register: vbond_nics
+ vars:
+ _public_ip_query: "[?to_number(state.tags.VPN)==`{{ public_ip_state.state.tags.VPN }}`].state.name"
- name: Set az_network_interfaces_vbond fact with a list of interfaces for vBond
ansible.builtin.set_fact:
az_network_interfaces_vbond: "{{ vbond_nics.results | map(attribute='state') | list }}"
- az_public_ip_addresses_vbond: "{{ public_ip_addresses.results | map(attribute='state') | list }}"
+ az_public_ip_addresses_vbond: "{{ (public_ip_addresses.results + public_ipv6_addresses.results) | map(attribute='state') | list }}"
- name: Filter az_network_interfaces_vbond for instance creation. Set az_mgmt_nic and az_transport_nic facts
ansible.builtin.set_fact:
az_mgmt_nic: "{{ az_network_interfaces_vbond | selectattr('tags.VPN', 'equalto', '512') | list | first }}"
az_transport_nic: "{{ az_network_interfaces_vbond | selectattr('tags.VPN', 'equalto', '0') | list | first }}"
- az_mgmt_public_ip: "{{ az_public_ip_addresses_vbond | selectattr('tags.VPN', 'equalto', '512') | list | first }}"
- az_transport_public_ip: "{{ az_public_ip_addresses_vbond | selectattr('tags.VPN', 'equalto', '0') | list | first }}"
+ az_mgmt_public_ip: "{{ _mgmt_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv4') | list | first }}"
+ az_transport_public_ip: "{{ _transport_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv4') | list | first }}"
+ az_mgmt_public_ipv6: "{{ _mgmt_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv6') | list | first }}"
+ az_transport_public_ipv6: "{{ _transport_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv6') | list | first }}"
+ vars:
+ _mgmt_public_ips: "{{ az_public_ip_addresses_vbond | selectattr('tags.VPN', 'equalto', '512') }}"
+ _transport_public_ips: "{{ az_public_ip_addresses_vbond | selectattr('tags.VPN', 'equalto', '0') }}"
# vbond_mgmt_private_ip
- name: "Set ip addresses vbond facts"
ansible.builtin.set_fact:
- vbond_mgmt_private_ip: "{{ az_mgmt_nic.ip_configuration.private_ip_address }}"
- vbond_transport_private_ip: "{{ az_transport_nic.ip_configuration.private_ip_address }}"
+ vbond_mgmt_private_ip: "{{ (az_mgmt_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv4`]') | first).private_ip_address }}"
+ vbond_mgmt_private_ipv6: "{{ (az_mgmt_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv6`]') | first).private_ip_address }}"
+ vbond_transport_private_ip: "{{ (az_transport_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv4`]') | first).private_ip_address }}"
+ vbond_transport_private_ipv6: "{{ (az_transport_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv6`]') | first).private_ip_address }}"
vbond_mgmt_public_ip: "{{ az_mgmt_public_ip.ip_address }}"
vbond_transport_public_ip: "{{ az_transport_public_ip.ip_address }}"
+ vbond_mgmt_public_ipv6: "{{ az_mgmt_public_ipv6.ip_address }}"
+ vbond_transport_public_ipv6: "{{ az_transport_public_ipv6.ip_address }}"
- name: "Set vpn0_default_gateway fact from VPN 0 subnet value"
ansible.builtin.set_fact:
- vpn0_default_gateway: "{{ subnet_item.cidr | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}"
+ vpn0_default_gateway: "{{ subnet_item.cidr[0] | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}"
loop:
- "{{ mgmt_subnet }}"
- "{{ transport_subnet }}"
@@ -178,9 +214,26 @@
admin_password: "{{ admin_password }}"
mgmt_public_ip: "{{ vbond_mgmt_public_ip }}"
transport_public_ip: "{{ vbond_transport_public_ip }}"
+ mgmt_public_ipv6: "{{ vbond_mgmt_public_ipv6 }}"
+ transport_public_ipv6: "{{ vbond_transport_public_ipv6 }}"
changed_when: true
notify: Show deployment_facts
+- name: DNS records
+ azure.azcollection.azure_rm_privatednsrecordset:
+ resource_group: "{{ az_resource_group }}"
+ zone_name: "{{ az_private_dns_zone }}"
+ relative_name: "vbond"
+ record_type: "{{ item.type }}"
+ records: "{{ item.records }}"
+ loop:
+ - type: 'A'
+ records:
+ - entry: "{{ vbond_transport_public_ip }}"
+ - type: 'AAAA'
+ records:
+ - entry: "{{ vbond_transport_public_ipv6 }}"
+
- name: Update deployment facts - vBond - that will be consumed by vManage-client in Ansible
ansible.builtin.set_fact:
deployment_facts:
diff --git a/roles/azure_controllers/tasks/azure_vmanage_vm.yml b/roles/azure_controllers/tasks/azure_vmanage_vm.yml
index e6d4a1e..f8c7c53 100644
--- a/roles/azure_controllers/tasks/azure_vmanage_vm.yml
+++ b/roles/azure_controllers/tasks/azure_vmanage_vm.yml
@@ -21,6 +21,7 @@
VPN: "{{ subnet_item.VPN }}"
Subnet: "{{ subnet_item.name }}"
type: "{{ subnet_item.type }}"
+ sku: standard
loop:
- "{{ mgmt_subnet }}"
- "{{ transport_subnet }}"
@@ -28,6 +29,27 @@
loop_var: subnet_item
register: public_ip_addresses
+- name: "Create public IPv6 addresses for machine: {{ hostname }}"
+ azure.azcollection.azure_rm_publicipaddress:
+ resource_group: "{{ az_resource_group }}"
+ allocation_method: static
+ name: "public-ipv6-{{ hostname }}-vpn-{{ subnet_item.VPN }}"
+ tags:
+ Name: "public-ipv6-{{ hostname }}"
+ Creator: "{{ az_tag_creator }}"
+ Machine: "{{ hostname }}"
+ VPN: "{{ subnet_item.VPN }}"
+ Subnet: "{{ subnet_item.name }}"
+ type: "{{ subnet_item.type }}"
+ version: ipv6
+ sku: standard
+ loop:
+ - "{{ mgmt_subnet }}"
+ - "{{ transport_subnet }}"
+ loop_control:
+ loop_var: subnet_item
+ register: public_ipv6_addresses
+
- name: "Get info about NSG: {{ az_network_security_group }}"
azure.azcollection.azure_rm_securitygroup_info:
resource_group: "{{ az_resource_group }}"
@@ -51,7 +73,7 @@
Name: "{{ az_network_security_group }}"
Creator: "{{ az_tag_creator }}"
Organization: "{{ organization_name }}"
- loop: "{{ public_ip_addresses.results }}"
+ loop: "{{ public_ip_addresses.results + public_ipv6_addresses.results }}"
loop_control:
loop_var: public_ip_state
index_var: my_idx
@@ -71,6 +93,10 @@
- name: "ipconfig-vpn-{{ public_ip_state.state.tags.VPN }}"
public_ip_address_name: "{{ public_ip_state.state.name }}"
private_ip_allocation_method: "Dynamic"
+ - name: "ipconfig-vpn-{{ public_ip_state.state.tags.VPN }}-ipv6"
+ public_ip_address_name: "{{ public_ipv6_addresses.results | json_query(_public_ip_query) | first }}"
+ private_ip_allocation_method: "Dynamic"
+ private_ip_address_version: IPv6
tags:
Name: "nic-{{ hostname }}-{{ public_ip_state.state.tags.type }}-vpn-{{ public_ip_state.state.tags.VPN }}"
Creator: "{{ az_tag_creator }}"
@@ -85,6 +111,8 @@
register: vmanage_nics
when:
- public_ip_state.state is defined
+ vars:
+ _public_ip_query: "[?to_number(state.tags.VPN)==`{{ public_ip_state.state.tags.VPN }}`].state.name"
- name: "Create virtual network interface card if cluster deployment"
azure.azcollection.azure_rm_networkinterface:
@@ -140,15 +168,22 @@
- name: Set az_network_interfaces_vmanage fact with a list of interfaces for vmanage
ansible.builtin.set_fact:
az_network_interfaces_vmanage: "{{ (vmanage_nics.results + [cluster_vmanage_nic]) | selectattr('state', 'defined') | map(attribute='state') | list }}"
- az_public_ip_addresses_vmanage: "{{ public_ip_addresses.results | selectattr('state', 'defined') | map(attribute='state') | list }}"
+ az_public_ip_addresses_vmanage: "{{ _public_ip_addresses | selectattr('state', 'defined') | map(attribute='state') | list }}"
+ vars:
+ _public_ip_addresses: "{{ public_ip_addresses.results + public_ipv6_addresses.results }}"
- name: Filter az_network_interfaces_vmanage for instance creation. Set az_mgmt_nic and az_transport_nic facts
ansible.builtin.set_fact:
az_mgmt_nic: "{{ az_network_interfaces_vmanage | selectattr('tags.type', 'equalto', 'mgmt') | list | first }}"
az_transport_nic: "{{ az_network_interfaces_vmanage | selectattr('tags.type', 'equalto', 'transport') | list | first }}"
az_cluster_nic: "{{ az_network_interfaces_vmanage | selectattr('tags.type', 'equalto', 'cluster') | list | first | default(omit) }}"
- az_mgmt_public_ip: "{{ az_public_ip_addresses_vmanage | selectattr('tags.type', 'equalto', 'mgmt') | list | first }}"
- az_transport_public_ip: "{{ az_public_ip_addresses_vmanage | selectattr('tags.type', 'equalto', 'transport') | list | first }}"
+ az_mgmt_public_ip: "{{ _mgmt_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv4') | list | first }}"
+ az_transport_public_ip: "{{ _transport_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv4') | list | first }}"
+ az_mgmt_public_ipv6: "{{ _mgmt_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv6') | list | first }}"
+ az_transport_public_ipv6: "{{ _transport_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv6') | list | first }}"
+ vars:
+ _mgmt_public_ips: "{{ az_public_ip_addresses_vmanage | selectattr('tags.VPN', 'equalto', '512') }}"
+ _transport_public_ips: "{{ az_public_ip_addresses_vmanage | selectattr('tags.VPN', 'equalto', '0') }}"
- name: Prepare nics_ids_list variable for VM creation
ansible.builtin.set_fact:
@@ -169,11 +204,18 @@
- name: "Set vmanage facts"
ansible.builtin.set_fact:
- vmanage_mgmt_private_ip: "{{ az_mgmt_nic.ip_configuration.private_ip_address }}"
- vmanage_transport_private_ip: "{{ az_transport_nic.ip_configuration.private_ip_address }}"
+ vmanage_mgmt_private_ip: "{{ (az_mgmt_nic.ip_configurations | json_query(_ipv4_query) | first).private_ip_address }}"
+ vmanage_mgmt_private_ipv6: "{{ (az_mgmt_nic.ip_configurations | json_query(_ipv6_query) | first).private_ip_address }}"
+ vmanage_transport_private_ip: "{{ (az_transport_nic.ip_configurations | json_query(_ipv4_query) | first).private_ip_address }}"
+ vmanage_transport_private_ipv6: "{{ (az_transport_nic.ip_configurations | json_query(_ipv6_query) | first).private_ip_address }}"
vmanage_mgmt_public_ip: "{{ az_mgmt_public_ip.ip_address }}"
vmanage_transport_public_ip: "{{ az_transport_public_ip.ip_address }}"
+ vmanage_mgmt_public_ipv6: "{{ az_mgmt_public_ipv6.ip_address }}"
+ vmanage_transport_public_ipv6: "{{ az_transport_public_ipv6.ip_address }}"
vmanage_persona: "{{ persona | default(vmanage_default_persona) }}"
+ vars:
+ _ipv4_query: "[?private_ip_address_version==`IPv4`]"
+ _ipv6_query: "[?private_ip_address_version==`IPv6`]"
- name: "Set vmanage cluster related facts"
ansible.builtin.set_fact:
@@ -185,7 +227,7 @@
- name: "Set vpn0_default_gateway fact from VPN 0 subnet value"
ansible.builtin.set_fact:
- vpn0_default_gateway: "{{ subnet.cidr | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}"
+ vpn0_default_gateway: "{{ subnet.cidr[0] | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}"
loop: "{{ az_subnets }}"
loop_control:
loop_var: subnet
@@ -254,6 +296,8 @@
admin_password: "{{ admin_password }}"
mgmt_public_ip: "{{ vmanage_mgmt_public_ip }}"
transport_public_ip: "{{ vmanage_transport_public_ip }}"
+ mgmt_public_ipv6: "{{ vmanage_mgmt_public_ipv6 }}"
+ transport_public_ipv6: "{{ vmanage_transport_public_ipv6 }}"
cluster_private_ip: "{{ vmanage_cluster_private_ip | default(omit) }}"
persona: "{{ vmanage_persona }}"
changed_when: true
diff --git a/roles/azure_controllers/tasks/azure_vsmart_vm.yml b/roles/azure_controllers/tasks/azure_vsmart_vm.yml
index ba7d587..ff6312f 100644
--- a/roles/azure_controllers/tasks/azure_vsmart_vm.yml
+++ b/roles/azure_controllers/tasks/azure_vsmart_vm.yml
@@ -19,6 +19,7 @@
Machine: "{{ hostname }}"
VPN: "{{ subnet_item.VPN }}"
Subnet: "{{ subnet_item.name }}"
+ sku: standard
loop:
- "{{ mgmt_subnet }}"
- "{{ transport_subnet }}"
@@ -26,6 +27,26 @@
loop_var: subnet_item
register: public_ip_addresses
+- name: "Create public IPv6 addresses for machine: {{ hostname }}"
+ azure.azcollection.azure_rm_publicipaddress:
+ resource_group: "{{ az_resource_group }}"
+ allocation_method: static
+ name: "public-ipv6-{{ hostname }}-vpn-{{ subnet_item.VPN }}"
+ tags:
+ Name: "public-ipv6-{{ hostname }}"
+ Creator: "{{ az_tag_creator }}"
+ Machine: "{{ hostname }}"
+ VPN: "{{ subnet_item.VPN }}"
+ Subnet: "{{ subnet_item.name }}"
+ version: ipv6
+ sku: standard
+ loop:
+ - "{{ mgmt_subnet }}"
+ - "{{ transport_subnet }}"
+ loop_control:
+ loop_var: subnet_item
+ register: public_ipv6_addresses
+
- name: "Get info about NSG: {{ az_network_security_group }}"
azure.azcollection.azure_rm_securitygroup_info:
resource_group: "{{ az_resource_group }}"
@@ -49,7 +70,7 @@
Name: "{{ az_network_security_group }}"
Creator: "{{ az_tag_creator }}"
Organization: "{{ organization_name }}"
- loop: "{{ public_ip_addresses.results }}"
+ loop: "{{ public_ip_addresses.results + public_ipv6_addresses.results }}"
loop_control:
loop_var: public_ip_state
index_var: my_idx
@@ -67,6 +88,10 @@
- name: "ipconfig-vpn-{{ public_ip_state.state.tags.VPN }}"
public_ip_address_name: "{{ public_ip_state.state.name }}"
private_ip_allocation_method: "Dynamic"
+ - name: "ipconfig-vpn-{{ public_ip_state.state.tags.VPN }}-ipv6"
+ public_ip_address_name: "{{ public_ipv6_addresses.results | json_query(_public_ip_query) | first }}"
+ private_ip_allocation_method: "Dynamic"
+ private_ip_address_version: IPv6
tags:
Name: "nic-{{ hostname }}-vpn-{{ public_ip_state.state.tags.VPN }}"
Creator: "{{ az_tag_creator }}"
@@ -78,29 +103,40 @@
index_var: my_idx
label: public_ip_state.state.name
register: vsmart_nics
+ vars:
+ _public_ip_query: "[?to_number(state.tags.VPN)==`{{ public_ip_state.state.tags.VPN }}`].state.name"
- name: "Set az_network_interfaces_vsmart fact with a list of interfaces for vSmart"
ansible.builtin.set_fact:
az_network_interfaces_vsmart: "{{ vsmart_nics.results | map(attribute='state') | list }}"
- az_public_ip_addresses_vsmart: "{{ public_ip_addresses.results | map(attribute='state') | list }}"
+ az_public_ip_addresses_vsmart: "{{ (public_ip_addresses.results + public_ipv6_addresses.results) | map(attribute='state') | list }}"
- name: "Filter az_network_interfaces_vsmart for instance creation. Set az_mgmt_nic and az_transport_nic facts"
ansible.builtin.set_fact:
az_mgmt_nic: "{{ az_network_interfaces_vsmart | selectattr('tags.VPN', 'equalto', '512') | list | first }}"
az_transport_nic: "{{ az_network_interfaces_vsmart | selectattr('tags.VPN', 'equalto', '0') | list | first }}"
- az_mgmt_public_ip: "{{ az_public_ip_addresses_vsmart | selectattr('tags.VPN', 'equalto', '512') | list | first }}"
- az_transport_public_ip: "{{ az_public_ip_addresses_vsmart | selectattr('tags.VPN', 'equalto', '0') | list | first }}"
+ az_mgmt_public_ip: "{{ _mgmt_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv4') | list | first }}"
+ az_transport_public_ip: "{{ _transport_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv4') | list | first }}"
+ az_mgmt_public_ipv6: "{{ _mgmt_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv6') | list | first }}"
+ az_transport_public_ipv6: "{{ _transport_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv6') | list | first }}"
+ vars:
+ _mgmt_public_ips: "{{ az_public_ip_addresses_vsmart | selectattr('tags.VPN', 'equalto', '512') }}"
+ _transport_public_ips: "{{ az_public_ip_addresses_vsmart | selectattr('tags.VPN', 'equalto', '0') }}"
- name: "Set vsmart facts"
ansible.builtin.set_fact:
- vsmart_mgmt_private_ip: "{{ az_mgmt_nic.ip_configuration.private_ip_address }}"
- vsmart_transport_private_ip: "{{ az_transport_nic.ip_configuration.private_ip_address }}"
+ vsmart_mgmt_private_ip: "{{ (az_mgmt_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv4`]') | first).private_ip_address }}"
+ vsmart_mgmt_private_ipv6: "{{ (az_mgmt_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv6`]') | first).private_ip_address }}"
+ vsmart_transport_private_ip: "{{ (az_transport_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv4`]') | first).private_ip_address }}"
+ vsmart_transport_private_ipv6: "{{ (az_transport_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv6`]') | first).private_ip_address }}"
vsmart_mgmt_public_ip: "{{ az_mgmt_public_ip.ip_address }}"
vsmart_transport_public_ip: "{{ az_transport_public_ip.ip_address }}"
+ vsmart_mgmt_public_ipv6: "{{ az_mgmt_public_ipv6.ip_address }}"
+ vsmart_transport_public_ipv6: "{{ az_transport_public_ipv6.ip_address }}"
- name: "Set vpn0_default_gateway fact from VPN 0 subnet value"
ansible.builtin.set_fact:
- vpn0_default_gateway: "{{ subnet_item.cidr | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}"
+ vpn0_default_gateway: "{{ subnet_item.cidr[0] | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}"
loop:
- "{{ mgmt_subnet }}"
- "{{ transport_subnet }}"
@@ -165,6 +201,8 @@
admin_password: "{{ admin_password }}"
mgmt_public_ip: "{{ vsmart_mgmt_public_ip }}"
transport_public_ip: "{{ vsmart_transport_public_ip }}"
+ mgmt_public_ipv6: "{{ vsmart_mgmt_public_ipv6 }}"
+ transport_public_ipv6: "{{ vsmart_transport_public_ipv6 }}"
changed_when: true
notify: Show deployment_facts
diff --git a/roles/azure_controllers/templates/userdata_vbond.j2 b/roles/azure_controllers/templates/userdata_vbond.j2
index c75e9ba..7c18a74 100644
--- a/roles/azure_controllers/templates/userdata_vbond.j2
+++ b/roles/azure_controllers/templates/userdata_vbond.j2
@@ -31,6 +31,7 @@ write_files:
+ true
{{ admin_username }}
@@ -46,6 +47,9 @@ write_files:
true
+
+ true
+
ipsec
@@ -76,6 +80,9 @@ write_files:
true
+
+ true
+
false
diff --git a/roles/azure_controllers/templates/userdata_vmanage.j2 b/roles/azure_controllers/templates/userdata_vmanage.j2
index 523b8d4..dafc755 100644
--- a/roles/azure_controllers/templates/userdata_vmanage.j2
+++ b/roles/azure_controllers/templates/userdata_vmanage.j2
@@ -45,7 +45,7 @@ write_files:
{{ organization_name }}
{{ site_id }}
- {{ vbond_transport_public_ip | default(default_vbond_ip) }}
+ {{ az_vbond_address }}
local
@@ -57,6 +57,8 @@ write_files:
netadmin
+ {{ ipv6_strict_control | lower }}
+ true
@@ -66,6 +68,9 @@ write_files:
true
+
+ true
+
true
@@ -95,6 +100,9 @@ write_files:
true
+
+ true
+
false
diff --git a/roles/azure_controllers/templates/userdata_vsmart.j2 b/roles/azure_controllers/templates/userdata_vsmart.j2
index 7c198f8..8356173 100644
--- a/roles/azure_controllers/templates/userdata_vsmart.j2
+++ b/roles/azure_controllers/templates/userdata_vsmart.j2
@@ -27,7 +27,7 @@ write_files:
{{ organization_name }}
{{ site_id }}
- {{ vbond_transport_public_ip | default(default_vbond_ip) }}
+ {{ az_vbond_address }}
@@ -35,6 +35,8 @@ write_files:
{{ admin_password }}
+ {{ ipv6_strict_control | lower }}
+ true
@@ -44,6 +46,9 @@ write_files:
true
+
+ true
+
ipsec
@@ -74,6 +79,9 @@ write_files:
true
+
+ true
+
false
diff --git a/roles/azure_edges/README.md b/roles/azure_edges/README.md
index 718fc2d..4229103 100644
--- a/roles/azure_edges/README.md
+++ b/roles/azure_edges/README.md
@@ -46,6 +46,7 @@ Variables with default values that can be overridden by the user:
- `vbond_port`, `default_vbond_ip`: Default configurations for vBond.
- `az_cedge_vm_size`: Default Azure VM size for cEdge instances.
- `edge_instances`: List of cEdge instance configurations. If not provided, instances will be created based on PnP Portal information.
+- `ipv6_strict_control`: Control if ipv6-strict-control is enabled.
### Vars (`vars/main.yml`)
diff --git a/roles/azure_edges/defaults/main.yml b/roles/azure_edges/defaults/main.yml
index 7224173..61265dd 100644
--- a/roles/azure_edges/defaults/main.yml
+++ b/roles/azure_edges/defaults/main.yml
@@ -63,6 +63,7 @@ admin_password: example_password # pragma: allowlist secret
admin_ssh_keys: []
vbond_port: 12346
default_vbond_ip: 192.168.1.199
+ipv6_strict_control: true
# vpn0_interface_color: default
################################
diff --git a/roles/azure_edges/tasks/azure_cedge_vm.yml b/roles/azure_edges/tasks/azure_cedge_vm.yml
index ed24b9c..f7f4ebe 100644
--- a/roles/azure_edges/tasks/azure_cedge_vm.yml
+++ b/roles/azure_edges/tasks/azure_cedge_vm.yml
@@ -20,6 +20,7 @@
VPN: "{{ subnet_item.VPN }}"
Subnet: "{{ subnet_item.name }}"
type: "{{ subnet_item.type }}"
+ sku: standard
loop:
- "{{ mgmt_subnet }}"
- "{{ transport_subnet }}"
@@ -27,6 +28,27 @@
loop_var: subnet_item
register: public_ip_addresses
+- name: "Create public IPv6 addresses for machine: {{ hostname }}"
+ azure.azcollection.azure_rm_publicipaddress:
+ resource_group: "{{ az_resource_group }}"
+ allocation_method: static
+ name: "public-ipv6-{{ hostname }}-vpn-{{ subnet_item.VPN }}"
+ tags:
+ Name: "public-ipv6-{{ hostname }}"
+ Creator: "{{ az_tag_creator }}"
+ Machine: "{{ hostname }}"
+ VPN: "{{ subnet_item.VPN }}"
+ Subnet: "{{ subnet_item.name }}"
+ type: "{{ subnet_item.type }}"
+ version: ipv6
+ sku: standard
+ loop:
+ - "{{ mgmt_subnet }}"
+ - "{{ transport_subnet }}"
+ loop_control:
+ loop_var: subnet_item
+ register: public_ipv6_addresses
+
- name: "Get info about NSG: {{ az_network_security_group }}"
azure.azcollection.azure_rm_securitygroup_info:
resource_group: "{{ az_default_resource_group }}"
@@ -50,7 +72,7 @@
Name: "{{ az_network_security_group }}"
Creator: "{{ az_tag_creator }}"
Organization: "{{ organization_name }}"
- loop: "{{ public_ip_addresses.results }}"
+ loop: "{{ public_ip_addresses.results + public_ipv6_addresses.results }}"
loop_control:
loop_var: public_ip_state
index_var: my_idx
@@ -68,6 +90,10 @@
- name: "ipconfig-vpn-{{ public_ip_state.state.tags.VPN }}"
public_ip_address_name: "{{ public_ip_state.state.name }}"
private_ip_allocation_method: "Dynamic"
+ - name: "ipconfig-vpn-{{ public_ip_state.state.tags.VPN }}-ipv6"
+ public_ip_address_name: "{{ public_ipv6_addresses.results | json_query(_public_ip_query) | first }}"
+ private_ip_allocation_method: "Dynamic"
+ private_ip_address_version: IPv6
tags:
Name: "nic-{{ hostname }}-vpn-{{ public_ip_state.state.tags.VPN }}"
Creator: "{{ az_tag_creator }}"
@@ -80,6 +106,8 @@
index_var: my_idx
label: public_ip_state.state.name
register: cedge_nics
+ vars:
+ _public_ip_query: "[?to_number(state.tags.VPN)==`{{ public_ip_state.state.tags.VPN }}`].state.name"
- name: "Create private virtual network interface cards"
azure.azcollection.azure_rm_networkinterface:
@@ -109,7 +137,7 @@
ansible.builtin.set_fact:
az_network_interfaces_cedge: "{{ cedge_nics.results | map(attribute='state') | list }}"
az_private_network_interfaces_cedge: "{{ cedge_private_nics.results | selectattr('state', 'defined') | map(attribute='state') | list | default([]) }}"
- az_public_ip_addresses_cedge: "{{ public_ip_addresses.results | map(attribute='state') | list }}"
+ az_public_ip_addresses_cedge: "{{ (public_ip_addresses.results + public_ipv6_addresses.results) | map(attribute='state') | list }}"
- name: Append to az_network_interfaces_cedge
ansible.builtin.set_fact:
@@ -120,16 +148,25 @@
az_mgmt_nic: "{{ az_network_interfaces_cedge | selectattr('tags.type', 'equalto', 'mgmt') | list | first }}"
az_transport_nic: "{{ az_network_interfaces_cedge | selectattr('tags.type', 'equalto', 'transport') | list | first }}"
az_service_nics: "{{ az_network_interfaces_cedge | selectattr('tags.type', 'equalto', 'service') | list | default(omit) }}"
- az_mgmt_public_ip: "{{ az_public_ip_addresses_cedge | selectattr('tags.type', 'equalto', 'mgmt') | list | first }}"
- az_transport_public_ip: "{{ az_public_ip_addresses_cedge | selectattr('tags.type', 'equalto', 'transport') | list | first }}"
+ az_mgmt_public_ip: "{{ _mgmt_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv4') | list | first }}"
+ az_transport_public_ip: "{{ _transport_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv4') | list | first }}"
+ az_mgmt_public_ipv6: "{{ _mgmt_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv6') | list | first }}"
+ az_transport_public_ipv6: "{{ _transport_public_ips | selectattr('public_ip_address_version', 'equalto', 'ipv6') | list | first }}"
+ vars:
+ _mgmt_public_ips: "{{ az_public_ip_addresses_cedge | selectattr('tags.VPN', 'equalto', '512') }}"
+ _transport_public_ips: "{{ az_public_ip_addresses_cedge | selectattr('tags.VPN', 'equalto', '0') }}"
# cedge_mgmt_private_ip
- name: "Set ip addresses cedge facts"
ansible.builtin.set_fact:
- cedge_mgmt_private_ip: "{{ az_mgmt_nic.ip_configuration.private_ip_address }}"
- cedge_transport_private_ip: "{{ az_transport_nic.ip_configuration.private_ip_address }}"
+ cedge_mgmt_private_ip: "{{ (az_mgmt_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv4`]') | first).private_ip_address }}"
+ cedge_mgmt_private_ipv6: "{{ (az_mgmt_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv6`]') | first).private_ip_address }}"
+ cedge_transport_private_ip: "{{ (az_transport_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv4`]') | first).private_ip_address }}"
+ cedge_transport_private_ipv6: "{{ (az_transport_nic.ip_configurations | json_query('[?private_ip_address_version==`IPv6`]') | first).private_ip_address }}"
cedge_mgmt_public_ip: "{{ az_mgmt_public_ip.ip_address }}"
cedge_transport_public_ip: "{{ az_transport_public_ip.ip_address }}"
+ cedge_mgmt_public_ipv6: "{{ az_mgmt_public_ipv6.ip_address }}"
+ cedge_transport_public_ipv6: "{{ az_transport_public_ipv6.ip_address }}"
- name: "Set vpn0_default_gateway fact from VPN 0 subnet value"
ansible.builtin.set_fact:
@@ -219,6 +256,8 @@
admin_password: "{{ admin_password }}"
mgmt_public_ip: "{{ cedge_mgmt_public_ip }}"
transport_public_ip: "{{ cedge_transport_public_ip }}"
+ mgmt_public_ipv6: "{{ cedge_mgmt_public_ipv6 }}"
+ transport_public_ipv6: "{{ cedge_transport_public_ipv6 }}"
service_interfaces: "{{ service_interfaces | default(omit) }}"
uuid: "{{ uuid }}"
site_id: "{{ site_id }}"
diff --git a/roles/azure_edges/templates/userdata_cedge.j2 b/roles/azure_edges/templates/userdata_cedge.j2
index bfaf4df..76928f4 100644
--- a/roles/azure_edges/templates/userdata_cedge.j2
+++ b/roles/azure_edges/templates/userdata_cedge.j2
@@ -52,7 +52,8 @@ Content-Disposition: attachment; filename="config-{{ uuid }}.txt"
config-template-name Default_Azure_vWAN_C8000V_Template_V01
no on-demand enable
on-demand idle-timeout 10
- vbond {{ vbond }} port {{ vbond_port }}
+ vbond {{ vbond_transport_hostname }} port {{ vbond_port }}
+ ipv6-strict-control {{ ipv6_strict_control | lower }}
!
bfd color lte
hello-interval 1000
@@ -186,6 +187,10 @@ Content-Disposition: attachment; filename="config-{{ uuid }}.txt"
no shutdown
arp timeout 1200
ip address dhcp client-id GigabitEthernet1
+ ipv6 address dhcp
+ ipv6 enable
+ ipv6 nd autoconfig prefix
+ ipv6 nd autoconfig default-route
no ip redirects
ip dhcp client default-router distance 1
ip mtu 1500
@@ -197,6 +202,10 @@ Content-Disposition: attachment; filename="config-{{ uuid }}.txt"
no shutdown
arp timeout 1200
ip address dhcp client-id GigabitEthernet2
+ ipv6 address dhcp
+ ipv6 enable
+ ipv6 nd autoconfig prefix
+ ipv6 nd autoconfig default-route
no ip redirects
ip dhcp client default-router distance 1
ip mtu 1500
@@ -210,6 +219,7 @@ Content-Disposition: attachment; filename="config-{{ uuid }}.txt"
no shutdown
ip unnumbered GigabitEthernet1
no ip redirects
+ ipv6 enable
ipv6 unnumbered GigabitEthernet1
no ipv6 redirects
tunnel source GigabitEthernet1
diff --git a/roles/azure_network_infrastructure/defaults/main.yml b/roles/azure_network_infrastructure/defaults/main.yml
index 2fb157e..30d5016 100644
--- a/roles/azure_network_infrastructure/defaults/main.yml
+++ b/roles/azure_network_infrastructure/defaults/main.yml
@@ -19,28 +19,38 @@ az_resource_group: "{{ az_resources_prefix }}-rg"
# Virtual Network
az_virtual_network: "{{ az_resources_prefix }}-vn"
-az_vn_address_prefixes_cidr: 10.0.0.0/16
+az_vn_address_prefixes_cidr:
+ - 10.0.0.0/16
+ - "fd00::/48"
# Subnets
az_subnets: |
{% filter from_yaml %}
- name: "{{ az_resources_prefix }}-mgmt-subnet-512"
- cidr: "10.0.1.0/24"
+ cidr:
+ - "10.0.1.0/24"
+ - "fd00:0:0:1::/64"
VPN: 512
type: mgmt
- name: "{{ az_resources_prefix }}-transport-subnet-0"
- cidr: "10.0.2.0/24"
+ cidr:
+ - "10.0.2.0/24"
+ - "fd00:0:0:2::/64"
VPN: 0
type: transport
{% if vmanage_instances is defined and vmanage_instances | length > 2 %}
- name: "{{ az_resources_prefix }}-cluster-subnet-0"
- cidr: "10.0.3.0/24"
+ cidr:
+ - "10.0.3.0/24"
+ - "fd00:0:0:3::/64"
VPN: 0
type: cluster
{% endif %}
{% if ux20_deployment is defined and ux20_deployment == true %}
- name: "{{ az_resources_prefix }}-service-subnet-10"
- cidr: "10.0.4.0/24" # default ips from official Cisco guides
+ cidr:
+ - "10.0.4.0/24" # default ips from official Cisco guides
+ - "fd00:0:0:4::/64"
VPN: 10
type: service
{% endif %}
@@ -50,5 +60,10 @@ az_subnets: |
az_network_security_group: "{{ az_resources_prefix }}-nsg"
+# Private DNS zone
+az_private_dns_zone: "{{ az_resources_prefix }}.internal"
+az_private_network_link: "{{ az_resources_prefix }}-pnl"
+
+
# VPN subnets from which we can connect to Azure EIPs (Network Security Group config)
az_allowed_subnets: null
diff --git a/roles/azure_network_infrastructure/tasks/azure_network_infrastructure.yml b/roles/azure_network_infrastructure/tasks/azure_network_infrastructure.yml
index 768868f..b704fdc 100644
--- a/roles/azure_network_infrastructure/tasks/azure_network_infrastructure.yml
+++ b/roles/azure_network_infrastructure/tasks/azure_network_infrastructure.yml
@@ -79,3 +79,20 @@
Name: "{{ az_network_security_group }}"
Creator: "{{ az_tag_creator }}"
Organization: "{{ organization_name }}"
+
+- name: Create a private DNS zone
+ azure.azcollection.azure_rm_privatednszone:
+ resource_group: "{{ az_resource_group }}"
+ name: "{{ az_private_dns_zone }}"
+ tags:
+ Name: "{{ az_virtual_network }}"
+ Creator: "{{ az_tag_creator }}"
+ Organization: "{{ organization_name }}"
+
+- name: Create a virtual network link
+ azure.azcollection.azure_rm_privatednszonelink:
+ resource_group: "{{ az_resource_group }}"
+ name: "{{ az_private_network_link }}"
+ zone_name: "{{ az_private_dns_zone }}"
+ virtual_network: "{{ az_virtual_network }}"
+ state: present