mirror of
https://github.com/netbirdio/ansible-netbird.git
synced 2026-05-22 18:43:36 -07:00
@@ -632,8 +632,9 @@ For inventory-based workflows (e.g., AAP), use the roles directly in your own pl
|
||||
|
||||
- **Preview mode** (default) — shows a read-only diff of what would change before applying
|
||||
- **Strict mode** — enforces full IaC by removing resources not defined in YAML
|
||||
- **Setup key management** — create/rotate enrollment keys with auto_groups name resolution; key values registered for downstream Vault storage
|
||||
- **Name-based config** — use plain names ("developers") instead of API IDs; resolved automatically
|
||||
- **Dependency ordering** — resources applied in correct order (settings → posture checks → groups → DNS → networks → policies)
|
||||
- **Dependency ordering** — resources applied in correct order (settings → posture checks → groups → setup keys → DNS → networks → policies)
|
||||
- **Export utility** — captures current API state as clean, ready-to-use YAML config files
|
||||
- **Roles** — use `community.ansible_netbird.configure` and `community.ansible_netbird.export` directly in your own playbooks for full control
|
||||
|
||||
@@ -643,6 +644,7 @@ For inventory-based workflows (e.g., AAP), use the roles directly in your own pl
|
||||
my_netbird_config/
|
||||
├── settings.yml # Account-wide settings
|
||||
├── networks.yml # Networks with routers and resources
|
||||
├── setup_keys.yml # Peer enrollment keys (optional)
|
||||
├── access_control/
|
||||
│ ├── groups.yml # Groups
|
||||
│ ├── posture_checks.yml # Posture checks
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
# NetBird Setup Keys
|
||||
#
|
||||
# Keys are used for peer enrollment. Key values are returned only at creation
|
||||
# time and cannot be retrieved later — store them securely.
|
||||
#
|
||||
# auto_groups use plain names (resolved to IDs automatically).
|
||||
# See docs/guide_netbird_config_as_code.md for details.
|
||||
|
||||
netbird_setup_keys: []
|
||||
# - name: "server-enrollment"
|
||||
# key_type: "reusable" # one-off or reusable
|
||||
# expires_in: 604800 # 7 days in seconds
|
||||
# auto_groups:
|
||||
# - servers # resolved to ID automatically
|
||||
# usage_limit: 0 # 0 = unlimited (reusable only)
|
||||
# ephemeral: false
|
||||
# state: present
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
Manage your NetBird logical configuration (groups, policies, networks, DNS, posture checks, account settings) as YAML files stored in Git. Changes are reviewed via pull requests and applied via the `configure_netbird` playbook.
|
||||
Manage your NetBird logical configuration (groups, policies, networks, DNS, posture checks, setup keys, account settings) as YAML files stored in Git. Changes are reviewed via pull requests and applied via the `configure_netbird` playbook.
|
||||
|
||||
```
|
||||
Edit YAML → PR → Review → Merge → Apply
|
||||
@@ -69,6 +69,7 @@ ansible-playbook community.ansible_netbird.configure_netbird \
|
||||
my_netbird_config/
|
||||
├── settings.yml → netbird_settings
|
||||
├── networks.yml → netbird_networks
|
||||
├── setup_keys.yml → netbird_setup_keys (optional)
|
||||
├── access_control/
|
||||
│ ├── groups.yml → netbird_groups
|
||||
│ ├── posture_checks.yml → netbird_posture_checks
|
||||
@@ -84,6 +85,7 @@ The directory layout mirrors the NetBird UI navigation:
|
||||
- `access_control/` — Groups, posture checks, policies (UI: Access Control)
|
||||
- `dns/` — Nameservers, zones, DNS settings (UI: DNS)
|
||||
- `networks.yml` — Networks with routers and resources (UI: Networks)
|
||||
- `setup_keys.yml` — Peer enrollment keys (optional, UI: Setup Keys)
|
||||
|
||||
## Resource Dependencies
|
||||
|
||||
@@ -92,9 +94,10 @@ Resources are applied in dependency order (handled automatically):
|
||||
1. **Account settings** — no dependencies
|
||||
2. **Posture checks** — no dependencies (referenced by policies)
|
||||
3. **Groups** — no dependencies (referenced by everything else)
|
||||
4. **DNS** — depends on groups
|
||||
5. **Networks** — depends on groups
|
||||
6. **Policies** — depends on groups + posture checks
|
||||
4. **Setup keys** — depends on groups (for auto_groups)
|
||||
5. **DNS** — depends on groups
|
||||
6. **Networks** — depends on groups
|
||||
7. **Policies** — depends on groups + posture checks
|
||||
|
||||
## Adding/Modifying Resources
|
||||
|
||||
@@ -211,6 +214,58 @@ netbird_networks:
|
||||
state: present
|
||||
```
|
||||
|
||||
### Setup Keys
|
||||
|
||||
```yaml
|
||||
# setup_keys.yml
|
||||
netbird_setup_keys:
|
||||
- name: "server-enrollment"
|
||||
key_type: "reusable" # one-off or reusable
|
||||
expires_in: 604800 # 7 days in seconds
|
||||
auto_groups:
|
||||
- servers # resolved to ID automatically
|
||||
usage_limit: 0 # 0 = unlimited (reusable only)
|
||||
ephemeral: false
|
||||
state: present
|
||||
```
|
||||
|
||||
> **Important:** Setup key values are returned by the NetBird API **only at creation time**. On subsequent runs, the key exists and `changed=false` is reported — the key value is not retrievable. Store key values securely when they are first created.
|
||||
|
||||
The role registers results as `netbird_setup_key_results`, making key values available to `post_tasks:` in wrapper playbooks for downstream storage (e.g., HashiCorp Vault, AWS Secrets Manager).
|
||||
|
||||
### Setup Key Rotation
|
||||
|
||||
The NetBird API does not support regenerating a setup key — the Update endpoint can only change `revoked` and `auto_groups`. Rotation requires a two-phase approach:
|
||||
|
||||
**Phase 1 — Create new key alongside old (both active):**
|
||||
|
||||
```yaml
|
||||
# setup_keys.yml
|
||||
netbird_setup_keys:
|
||||
- name: "server-enrollment" # existing key, still active
|
||||
key_type: "reusable"
|
||||
auto_groups: [servers]
|
||||
- name: "server-enrollment-rotated" # new key
|
||||
key_type: "reusable"
|
||||
auto_groups: [servers]
|
||||
```
|
||||
|
||||
Apply with `commit=true`. The new key is created and its value is displayed (or stored via `post_tasks:`). Deploy the new key to clients while the old key still works.
|
||||
|
||||
**Phase 2 — Revoke old key after clients migrated:**
|
||||
|
||||
```yaml
|
||||
# setup_keys.yml
|
||||
netbird_setup_keys:
|
||||
- name: "server-enrollment"
|
||||
revoked: true # revoked, no longer usable
|
||||
- name: "server-enrollment-rotated"
|
||||
key_type: "reusable"
|
||||
auto_groups: [servers]
|
||||
```
|
||||
|
||||
The old key is revoked. You can later change it to `state: absent` to delete it entirely.
|
||||
|
||||
## Name-Based ID Resolution
|
||||
|
||||
Config files use **plain names** for groups and posture checks — no IDs, no Jinja2 syntax. The playbook resolves names to API IDs automatically at runtime.
|
||||
@@ -233,7 +288,6 @@ source_posture_checks:
|
||||
> **Note:** Router `peer` values in networks remain as peer IDs because peers are dynamic (they register via setup keys). The export playbook annotates peer IDs with hostnames in comments for reference.
|
||||
|
||||
**Not managed by IaC (intentional):**
|
||||
- **Setup keys** — key values are one-time secrets returned only at creation. The export playbook captures setup key metadata as a read-only reference.
|
||||
- **Peers** — dynamic, register via setup keys
|
||||
- **Users** — managed via IdP/LDAP sync
|
||||
|
||||
@@ -326,6 +380,36 @@ Then run with just a limit: `ansible-playbook configure_netbird.yml -i inventory
|
||||
|
||||
Using roles directly gives you full control over `hosts`, `gather_facts`, and variable resolution — and avoids `import_playbook` path resolution issues in AAP.
|
||||
|
||||
## Remote / Public API Endpoint
|
||||
|
||||
If your NetBird management plane runs on OpenShift or a cloud platform without SSH access, you can run the playbooks against the public API endpoint directly from `localhost`:
|
||||
|
||||
```yaml
|
||||
# configure_netbird.yml (remote API)
|
||||
- name: Configure NetBird via Public API
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
roles:
|
||||
- role: community.ansible_netbird.configure
|
||||
run_once: true
|
||||
vars:
|
||||
netbird_api_url: "https://netbird.example.com"
|
||||
netbird_api_token: "{{ vault_netbird_token }}"
|
||||
config_dir: "{{ playbook_dir }}/../netbird_config/{{ netbird_env }}"
|
||||
```
|
||||
|
||||
Or use the collection playbook directly:
|
||||
|
||||
```bash
|
||||
ansible-playbook community.ansible_netbird.configure_netbird \
|
||||
-e "config_dir=$(pwd)/netbird_config/prod" \
|
||||
-e "netbird_api_url=https://netbird.example.com" \
|
||||
-e "netbird_api_token=your-token" \
|
||||
-e "commit=true"
|
||||
```
|
||||
|
||||
Both patterns work identically — the only difference is whether Ansible SSHes to a control node (and queries `localhost:33073`) or runs locally against a remote HTTPS endpoint.
|
||||
|
||||
## Multi-Environment Setup
|
||||
|
||||
For managing multiple environments (e.g., production and staging), create separate config directories:
|
||||
@@ -334,11 +418,13 @@ For managing multiple environments (e.g., production and staging), create separa
|
||||
netbird_config/
|
||||
├── prod/
|
||||
│ ├── settings.yml
|
||||
│ ├── setup_keys.yml
|
||||
│ ├── access_control/
|
||||
│ ├── dns/
|
||||
│ └── networks.yml
|
||||
└── staging/
|
||||
├── settings.yml
|
||||
├── setup_keys.yml
|
||||
├── access_control/
|
||||
├── dns/
|
||||
└── networks.yml
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
# 1. Account settings (no dependencies)
|
||||
# 2. Posture checks (no dependencies, needed by policies)
|
||||
# 3. Groups (no dependencies, needed by everything else)
|
||||
# 4. DNS (depend on groups)
|
||||
# 5. Networks (depend on groups)
|
||||
# 6. Policies (depend on groups + posture checks)
|
||||
# 4. Setup keys (depend on groups for auto_groups)
|
||||
# 5. DNS (depend on groups)
|
||||
# 6. Networks (depend on groups)
|
||||
# 7. Policies (depend on groups + posture checks)
|
||||
#
|
||||
# Required variables:
|
||||
# - config_dir: Path to your config directory
|
||||
@@ -86,6 +87,17 @@
|
||||
ansible.builtin.include_vars:
|
||||
file: "{{ config_dir }}/networks.yml"
|
||||
|
||||
- name: Check if setup keys config exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ config_dir }}/setup_keys.yml"
|
||||
register: _setup_keys_file
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Load setup keys
|
||||
ansible.builtin.include_vars:
|
||||
file: "{{ config_dir }}/setup_keys.yml"
|
||||
when: _setup_keys_file.stat.exists
|
||||
|
||||
- name: Display configuration summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
@@ -94,6 +106,7 @@
|
||||
- " Groups: {{ netbird_groups | default([]) | length }}"
|
||||
- " Posture checks: {{ netbird_posture_checks | default([]) | length }}"
|
||||
- " Policies: {{ netbird_policies | default([]) | length }}"
|
||||
- " Setup keys: {{ netbird_setup_keys | default([]) | length }}"
|
||||
- " DNS nameservers: {{ netbird_dns_nameserver_groups | default([]) | length }}"
|
||||
- " DNS zones: {{ netbird_dns_zones | default([]) | length }}"
|
||||
- " Networks: {{ netbird_networks | default([]) | length }}"
|
||||
@@ -207,6 +220,20 @@
|
||||
# =====================================================================
|
||||
# Resolve group/posture-check names to IDs in config variables
|
||||
# =====================================================================
|
||||
- name: Resolve auto_groups in setup keys
|
||||
ansible.builtin.set_fact:
|
||||
_resolved_setup_keys: >-
|
||||
{% set result = [] -%}
|
||||
{% for sk in netbird_setup_keys | default([]) -%}
|
||||
{% set _ = result.append(sk | combine({
|
||||
'auto_groups': sk.auto_groups | default([]) | map('extract', group_ids) | list
|
||||
})) -%}
|
||||
{% endfor -%}
|
||||
{{ result | to_json }}
|
||||
when:
|
||||
- commit | bool
|
||||
- netbird_setup_keys | default([]) | length > 0
|
||||
|
||||
- name: Resolve group names in policies and networks
|
||||
ansible.builtin.set_fact:
|
||||
_resolved_policies: >-
|
||||
@@ -252,9 +279,50 @@
|
||||
{{ result | to_json }}
|
||||
when: commit | bool
|
||||
|
||||
# --- 4. Setup Keys (depend on groups for auto_groups) ---
|
||||
- name: Manage setup keys
|
||||
community.ansible_netbird.netbird_setup_key:
|
||||
name: "{{ item.name }}"
|
||||
key_type: "{{ item.key_type | default('one-off') }}"
|
||||
expires_in: "{{ item.expires_in | default(86400) }}"
|
||||
revoked: "{{ item.revoked | default(false) }}"
|
||||
auto_groups: "{{ item.auto_groups | default([]) }}"
|
||||
usage_limit: "{{ item.usage_limit | default(0) }}"
|
||||
ephemeral: "{{ item.ephemeral | default(false) }}"
|
||||
allow_extra_dns_labels: "{{ item.allow_extra_dns_labels | default(false) }}"
|
||||
state: "{{ item.state | default('present') }}"
|
||||
loop: "{{ _resolved_setup_keys | default(netbird_setup_keys | default([])) }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
register: netbird_setup_key_results
|
||||
when:
|
||||
- commit | bool
|
||||
- netbird_setup_keys | default([]) | length > 0
|
||||
|
||||
- name: Display created setup key values
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
NOTICE: Setup key "{{ item.item.name }}" created.
|
||||
Key value: {{ item.setup_key.key }}
|
||||
This value is shown ONCE and cannot be retrieved later.
|
||||
Store it securely (e.g., HashiCorp Vault).
|
||||
loop: "{{ netbird_setup_key_results.results | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item.item.name }}"
|
||||
when:
|
||||
- netbird_setup_key_results is not skipped
|
||||
- item.changed | default(false)
|
||||
- item.setup_key.key is defined
|
||||
|
||||
# =====================================================================
|
||||
# PHASE 3: Fetch remaining API state (preview or strict mode)
|
||||
# =====================================================================
|
||||
- name: Fetch current setup keys
|
||||
community.ansible_netbird.netbird_info:
|
||||
resource: setup_keys
|
||||
register: api_setup_keys
|
||||
when: not commit | bool or strict | bool
|
||||
|
||||
- name: Fetch current DNS nameserver groups
|
||||
community.ansible_netbird.netbird_info:
|
||||
resource: dns_nameservers
|
||||
@@ -293,7 +361,7 @@
|
||||
# PHASE 4: Apply dependent resources (commit mode only)
|
||||
# =====================================================================
|
||||
|
||||
# --- 4. DNS (depend on groups) ---
|
||||
# --- 5. DNS (depend on groups) ---
|
||||
- name: Manage DNS nameserver groups
|
||||
community.ansible_netbird.netbird_dns:
|
||||
resource_type: nameserver_group
|
||||
@@ -322,7 +390,7 @@
|
||||
- commit | bool
|
||||
- netbird_dns_disabled_management_groups is defined
|
||||
|
||||
# --- 5. DNS Zones (depend on groups) ---
|
||||
# --- 6. DNS Zones (depend on groups) ---
|
||||
- name: Manage DNS zones
|
||||
community.ansible_netbird.netbird_dns_zone:
|
||||
name: "{{ item.name }}"
|
||||
@@ -339,7 +407,7 @@
|
||||
- commit | bool
|
||||
- netbird_dns_zones | default([]) | length > 0
|
||||
|
||||
# --- 6. Networks (depend on groups) ---
|
||||
# --- 7. Networks (depend on groups) ---
|
||||
- name: Manage networks
|
||||
community.ansible_netbird.netbird_network:
|
||||
name: "{{ item.name }}"
|
||||
@@ -354,7 +422,7 @@
|
||||
- commit | bool
|
||||
- netbird_networks | default([]) | length > 0
|
||||
|
||||
# --- 7. Policies (depend on groups + posture checks) ---
|
||||
# --- 8. Policies (depend on groups + posture checks) ---
|
||||
- name: Manage policies
|
||||
community.ansible_netbird.netbird_policy:
|
||||
name: "{{ item.name }}"
|
||||
@@ -378,6 +446,7 @@
|
||||
_protected_groups: "{{ api_groups.data | selectattr('issued', 'defined') | selectattr('issued', 'equalto', 'jwt') | map(attribute='name') | list + ['All'] }}"
|
||||
_yaml_group_names: "{{ netbird_groups | default([]) | map(attribute='name') | list }}"
|
||||
_yaml_pc_names: "{{ netbird_posture_checks | default([]) | map(attribute='name') | list }}"
|
||||
_yaml_sk_names: "{{ netbird_setup_keys | default([]) | map(attribute='name') | list }}"
|
||||
_yaml_dns_names: "{{ netbird_dns_nameserver_groups | default([]) | map(attribute='name') | list }}"
|
||||
_yaml_dns_zone_names: "{{ netbird_dns_zones | default([]) | map(attribute='name') | list }}"
|
||||
_yaml_net_names: "{{ netbird_networks | default([]) | map(attribute='name') | list }}"
|
||||
@@ -390,6 +459,7 @@
|
||||
_orphaned_networks: "{{ api_networks.data | map(attribute='name') | list | difference(_yaml_net_names) }}"
|
||||
_orphaned_dns: "{{ api_dns_nameservers.data | map(attribute='name') | list | difference(_yaml_dns_names) }}"
|
||||
_orphaned_dns_zones: "{{ api_dns_zones.data | map(attribute='name') | list | difference(_yaml_dns_zone_names) }}"
|
||||
_orphaned_setup_keys: "{{ api_setup_keys.data | map(attribute='name') | list | difference(_yaml_sk_names) }}"
|
||||
_orphaned_posture_checks: "{{ api_posture_checks.data | map(attribute='name') | list | difference(_yaml_pc_names) }}"
|
||||
_orphaned_groups: "{{ api_groups.data | map(attribute='name') | list | difference(_yaml_group_names) | difference(_protected_groups) }}"
|
||||
when: commit | bool and strict | bool
|
||||
@@ -402,6 +472,7 @@
|
||||
- " Networks: {{ _orphaned_networks | length }} ({{ _orphaned_networks | join(', ') }})"
|
||||
- " DNS nameservers: {{ _orphaned_dns | length }} ({{ _orphaned_dns | join(', ') }})"
|
||||
- " DNS zones: {{ _orphaned_dns_zones | length }} ({{ _orphaned_dns_zones | join(', ') }})"
|
||||
- " Setup keys: {{ _orphaned_setup_keys | length }} ({{ _orphaned_setup_keys | join(', ') }})"
|
||||
- " Posture checks: {{ _orphaned_posture_checks | length }} ({{ _orphaned_posture_checks | join(', ') }})"
|
||||
- " Groups: {{ _orphaned_groups | length }} ({{ _orphaned_groups | join(', ') }})"
|
||||
when: commit | bool and strict | bool
|
||||
@@ -443,6 +514,15 @@
|
||||
label: "{{ item }}"
|
||||
when: commit | bool and strict | bool and _orphaned_dns_zones | length > 0
|
||||
|
||||
- name: "Strict: Remove unmanaged setup keys"
|
||||
community.ansible_netbird.netbird_setup_key:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
loop: "{{ _orphaned_setup_keys }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
when: commit | bool and strict | bool and _orphaned_setup_keys | length > 0
|
||||
|
||||
- name: "Strict: Remove unmanaged posture checks"
|
||||
community.ansible_netbird.netbird_posture_check:
|
||||
name: "{{ item }}"
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
# Shows which resources will be added, removed, or re-applied.
|
||||
#
|
||||
# Expects these variables to be set by the parent role:
|
||||
# - api_groups, api_posture_checks, api_dns_nameservers, api_dns_zones,
|
||||
# api_networks, api_policies, api_accounts (registered from netbird_info)
|
||||
# - netbird_groups, netbird_posture_checks, netbird_dns_nameserver_groups,
|
||||
# netbird_dns_zones, netbird_networks, netbird_policies,
|
||||
# netbird_settings (desired config from include_vars)
|
||||
# - api_groups, api_posture_checks, api_setup_keys, api_dns_nameservers,
|
||||
# api_dns_zones, api_networks, api_policies, api_accounts
|
||||
# (registered from netbird_info)
|
||||
# - netbird_groups, netbird_posture_checks, netbird_setup_keys,
|
||||
# netbird_dns_nameserver_groups, netbird_dns_zones, netbird_networks,
|
||||
# netbird_policies, netbird_settings (desired config from include_vars)
|
||||
# - netbird_api_url, config_dir
|
||||
|
||||
- name: Display preview header
|
||||
@@ -29,6 +30,7 @@
|
||||
ansible.builtin.set_fact:
|
||||
current_groups_map: "{{ dict(api_groups.data | map(attribute='name') | zip(api_groups.data)) }}"
|
||||
current_posture_checks_map: "{{ dict(api_posture_checks.data | map(attribute='name') | zip(api_posture_checks.data)) }}"
|
||||
current_setup_keys_map: "{{ dict(api_setup_keys.data | map(attribute='name') | zip(api_setup_keys.data)) }}"
|
||||
current_dns_map: "{{ dict(api_dns_nameservers.data | map(attribute='name') | zip(api_dns_nameservers.data)) }}"
|
||||
current_dns_zones_map: "{{ dict(api_dns_zones.data | map(attribute='name') | zip(api_dns_zones.data)) }}"
|
||||
current_networks_map: "{{ dict(api_networks.data | map(attribute='name') | zip(api_networks.data)) }}"
|
||||
@@ -66,6 +68,20 @@
|
||||
{{ netbird_posture_checks | default([]) | selectattr('state', 'defined') | selectattr('state', 'eq', 'absent') | map(attribute='name') | list
|
||||
| intersect(current_posture_checks_map.keys() | list) }}
|
||||
|
||||
- name: Classify setup keys
|
||||
ansible.builtin.set_fact:
|
||||
sk_new: >-
|
||||
{{ (netbird_setup_keys | default([]) | rejectattr('state', 'defined') | map(attribute='name') | list
|
||||
+ netbird_setup_keys | default([]) | selectattr('state', 'defined') | selectattr('state', 'eq', 'present') | map(attribute='name') | list)
|
||||
| difference(current_setup_keys_map.keys() | list) }}
|
||||
sk_existing: >-
|
||||
{{ (netbird_setup_keys | default([]) | rejectattr('state', 'defined') | map(attribute='name') | list
|
||||
+ netbird_setup_keys | default([]) | selectattr('state', 'defined') | selectattr('state', 'eq', 'present') | map(attribute='name') | list)
|
||||
| intersect(current_setup_keys_map.keys() | list) }}
|
||||
sk_remove: >-
|
||||
{{ netbird_setup_keys | default([]) | selectattr('state', 'defined') | selectattr('state', 'eq', 'absent') | map(attribute='name') | list
|
||||
| intersect(current_setup_keys_map.keys() | list) }}
|
||||
|
||||
- name: Classify DNS nameserver groups
|
||||
ansible.builtin.set_fact:
|
||||
dns_new: >-
|
||||
@@ -133,6 +149,7 @@
|
||||
ansible.builtin.set_fact:
|
||||
groups_orphaned: "{{ current_groups_map.keys() | list | difference(netbird_groups | default([]) | map(attribute='name') | list) | difference(_protected_groups) }}"
|
||||
pc_orphaned: "{{ current_posture_checks_map.keys() | list | difference(netbird_posture_checks | default([]) | map(attribute='name') | list) }}"
|
||||
sk_orphaned: "{{ current_setup_keys_map.keys() | list | difference(netbird_setup_keys | default([]) | map(attribute='name') | list) }}"
|
||||
dns_orphaned: "{{ current_dns_map.keys() | list | difference(netbird_dns_nameserver_groups | default([]) | map(attribute='name') | list) }}"
|
||||
dz_orphaned: "{{ current_dns_zones_map.keys() | list | difference(netbird_dns_zones | default([]) | map(attribute='name') | list) }}"
|
||||
net_orphaned: "{{ current_networks_map.keys() | list | difference(netbird_networks | default([]) | map(attribute='name') | list) }}"
|
||||
@@ -146,6 +163,7 @@
|
||||
diff_account: "{{ ['── Account Settings ──────────────────────────────────────────'] + ([' (not configured — skipped)'] if netbird_settings | default({}) | length == 0 else [' ~ EXISTS: account settings (will be re-applied)']) }}"
|
||||
diff_posture_checks: "{{ ['── Posture Checks ────────────────────────────────────────────'] + ([' (not configured — skipped)'] if netbird_posture_checks | default([]) | length == 0 and pc_remove | length == 0 and pc_orphaned | length == 0 else [' (no changes)'] if pc_new | length == 0 and pc_remove | length == 0 and pc_existing | length == 0 and pc_orphaned | length == 0 else pc_new | map('regex_replace', '^(.*)$', ' + ADD: \"\\1\"') | list + pc_remove | map('regex_replace', '^(.*)$', ' - REMOVE: \"\\1\"') | list + pc_orphaned | map('regex_replace', '^(.*)$', ' - ORPHAN: \"\\1\" (not in config)') | list + pc_existing | map('regex_replace', '^(.*)$', ' ~ EXISTS: \"\\1\" (will be re-applied)') | list) }}"
|
||||
diff_groups: "{{ ['── Groups ────────────────────────────────────────────────────'] + ([' (not configured — skipped)'] if netbird_groups | default([]) | length == 0 and groups_remove | length == 0 and groups_orphaned | length == 0 else [' (no changes)'] if groups_new | length == 0 and groups_remove | length == 0 and groups_existing | length == 0 and groups_orphaned | length == 0 else groups_new | map('regex_replace', '^(.*)$', ' + ADD: \"\\1\"') | list + groups_remove | map('regex_replace', '^(.*)$', ' - REMOVE: \"\\1\"') | list + groups_orphaned | map('regex_replace', '^(.*)$', ' - ORPHAN: \"\\1\" (not in config)') | list + groups_existing | map('regex_replace', '^(.*)$', ' ~ EXISTS: \"\\1\" (will be re-applied)') | list) }}"
|
||||
diff_setup_keys: "{{ ['── Setup Keys ────────────────────────────────────────────────'] + ([' (not configured — skipped)'] if netbird_setup_keys | default([]) | length == 0 and sk_remove | length == 0 and sk_orphaned | length == 0 else [' (no changes)'] if sk_new | length == 0 and sk_remove | length == 0 and sk_existing | length == 0 and sk_orphaned | length == 0 else sk_new | map('regex_replace', '^(.*)$', ' + ADD: \"\\1\"') | list + sk_remove | map('regex_replace', '^(.*)$', ' - REMOVE: \"\\1\"') | list + sk_orphaned | map('regex_replace', '^(.*)$', ' - ORPHAN: \"\\1\" (not in config)') | list + sk_existing | map('regex_replace', '^(.*)$', ' ~ EXISTS: \"\\1\" (will be re-applied)') | list) }}"
|
||||
diff_dns: "{{ ['── DNS Nameserver Groups ─────────────────────────────────────'] + ([' (not configured — skipped)'] if netbird_dns_nameserver_groups | default([]) | length == 0 and dns_remove | length == 0 and dns_orphaned | length == 0 else [' (no changes)'] if dns_new | length == 0 and dns_remove | length == 0 and dns_existing | length == 0 and dns_orphaned | length == 0 else dns_new | map('regex_replace', '^(.*)$', ' + ADD: \"\\1\"') | list + dns_remove | map('regex_replace', '^(.*)$', ' - REMOVE: \"\\1\"') | list + dns_orphaned | map('regex_replace', '^(.*)$', ' - ORPHAN: \"\\1\" (not in config)') | list + dns_existing | map('regex_replace', '^(.*)$', ' ~ EXISTS: \"\\1\" (will be re-applied)') | list) }}"
|
||||
diff_dns_zones: "{{ ['── DNS Zones ─────────────────────────────────────────────────'] + ([' (not configured — skipped)'] if netbird_dns_zones | default([]) | length == 0 and dz_remove | length == 0 and dz_orphaned | length == 0 else [' (no changes)'] if dz_new | length == 0 and dz_remove | length == 0 and dz_existing | length == 0 and dz_orphaned | length == 0 else dz_new | map('regex_replace', '^(.*)$', ' + ADD: \"\\1\"') | list + dz_remove | map('regex_replace', '^(.*)$', ' - REMOVE: \"\\1\"') | list + dz_orphaned | map('regex_replace', '^(.*)$', ' - ORPHAN: \"\\1\" (not in config)') | list + dz_existing | map('regex_replace', '^(.*)$', ' ~ EXISTS: \"\\1\" (will be re-applied)') | list) }}"
|
||||
diff_networks: "{{ ['── Networks ──────────────────────────────────────────────────'] + ([' (not configured — skipped)'] if netbird_networks | default([]) | length == 0 and net_remove | length == 0 and net_orphaned | length == 0 else [' (no changes)'] if net_new | length == 0 and net_remove | length == 0 and net_existing | length == 0 and net_orphaned | length == 0 else net_new | map('regex_replace', '^(.*)$', ' + ADD: \"\\1\"') | list + net_remove | map('regex_replace', '^(.*)$', ' - REMOVE: \"\\1\"') | list + net_orphaned | map('regex_replace', '^(.*)$', ' - ORPHAN: \"\\1\" (not in config)') | list + net_existing | map('regex_replace', '^(.*)$', ' ~ EXISTS: \"\\1\" (will be re-applied)') | list) }}"
|
||||
@@ -156,17 +174,17 @@
|
||||
# =========================================================================
|
||||
- name: Display diff report
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ diff_account + [''] + diff_posture_checks + [''] + diff_groups + [''] + diff_dns + [''] + diff_dns_zones + [''] + diff_networks + [''] + diff_policies }}"
|
||||
msg: "{{ diff_account + [''] + diff_posture_checks + [''] + diff_groups + [''] + diff_setup_keys + [''] + diff_dns + [''] + diff_dns_zones + [''] + diff_networks + [''] + diff_policies }}"
|
||||
|
||||
# =========================================================================
|
||||
# Summary
|
||||
# =========================================================================
|
||||
- name: Compute totals
|
||||
ansible.builtin.set_fact:
|
||||
total_add: "{{ (groups_new | length) + (pc_new | length) + (dns_new | length) + (dz_new | length) + (net_new | length) + (pol_new | length) }}"
|
||||
total_exists: "{{ (groups_existing | length) + (pc_existing | length) + (dns_existing | length) + (dz_existing | length) + (net_existing | length) + (pol_existing | length) }}"
|
||||
total_remove: "{{ (groups_remove | length) + (pc_remove | length) + (dns_remove | length) + (dz_remove | length) + (net_remove | length) + (pol_remove | length) }}"
|
||||
total_orphan: "{{ (groups_orphaned | length) + (pc_orphaned | length) + (dns_orphaned | length) + (dz_orphaned | length) + (net_orphaned | length) + (pol_orphaned | length) }}"
|
||||
total_add: "{{ (groups_new | length) + (pc_new | length) + (sk_new | length) + (dns_new | length) + (dz_new | length) + (net_new | length) + (pol_new | length) }}"
|
||||
total_exists: "{{ (groups_existing | length) + (pc_existing | length) + (sk_existing | length) + (dns_existing | length) + (dz_existing | length) + (net_existing | length) + (pol_existing | length) }}"
|
||||
total_remove: "{{ (groups_remove | length) + (pc_remove | length) + (sk_remove | length) + (dns_remove | length) + (dz_remove | length) + (net_remove | length) + (pol_remove | length) }}"
|
||||
total_orphan: "{{ (groups_orphaned | length) + (pc_orphaned | length) + (sk_orphaned | length) + (dns_orphaned | length) + (dz_orphaned | length) + (net_orphaned | length) + (pol_orphaned | length) }}"
|
||||
|
||||
- name: Display summary
|
||||
ansible.builtin.debug:
|
||||
|
||||
Reference in New Issue
Block a user