mirror of
https://github.com/immich-app/yucca.git
synced 2026-09-30 13:33:00 +08:00
chore(netbird): move to kebab naming (#242)
* chore(netbird): move to kebab naming Render NetBird object names (groups, setup keys, policies, networks, network-resources) as lowercase-kebab instead of UPPER_SNAKE, e.g. YUCCA_PROD_HTZ_FSN1_MGMT → yucca-prod-htz-fsn1-mgmt. The 1Password setup-key item titles stay UPPER_SNAKE (decoupled) so CI/ansible/talos op:// consumers keep resolving. Pin the futo-org/netbird provider to 1.0.2, which fixes the group resources TF→API decode so a resource-tag group (htz-fsn1 `resources`) can be renamed in place — no name pin needed. * update locks
This commit is contained in:
@@ -78,3 +78,4 @@ ansible/mgmt/inventories/*/group_vars/all/users.generated.yml
|
||||
tf/render/*/.terraform/
|
||||
tf/render/*/.terraform.lock.hcl
|
||||
tf/render/*/terraform.tfstate*
|
||||
.DS_Store
|
||||
|
||||
@@ -84,6 +84,22 @@ mise mgmt:render-inventory / mgmt:ansible # render + converge management
|
||||
|
||||
`tf:*` wrap terragrunt in `tf/op-run.sh` (injects the 1P superuser token from `tf/.env`).
|
||||
|
||||
> **CI owns terraform applies.** Do **not** run `mise tf:apply` (or `infra:apply`) by
|
||||
> hand — `terraform`/`terragrunt` applies are run by CI (`.github/workflows/infra.yml`)
|
||||
> on merge to main. Locally you may `tf:plan` to preview, but never apply. (Also: the
|
||||
> `tf:*` tasks inherit a stray `AWS_CA_BUNDLE=~/.config/homelab/root-ca.crt` from the
|
||||
> shell that breaks the OVH S3 state backend — unset it if you plan locally.)
|
||||
>
|
||||
> **NetBird futo-org provider — `netbird_group` resources bug (fixed in 1.0.2):**
|
||||
> `registry.terraform.io/futo-org/netbird` **≤ 1.0.1** could not UPDATE/DELETE a
|
||||
> `netbird_group` that had network resources tagged into it — the TF→API path decoded
|
||||
> the `resources` list of `{id,type}` objects into `[]map[string]string` ("cannot
|
||||
> reflect tftypes.Object … into a map"), so a resource-tag group (e.g. htz-fsn1
|
||||
> `resources`) couldn't be renamed in place. **Fixed in 1.0.2** — we own the provider
|
||||
> (`../terraform-provider-netbird`); stacks pin `version = "1.0.2"`. Renaming a setup
|
||||
> key still **forces replacement** (the NetBird API can't rename keys), regenerating
|
||||
> its value.
|
||||
|
||||
## Application architecture
|
||||
|
||||
**Backend services are NestJS 11 + TypeScript**, sharing patterns: controllers → services →
|
||||
|
||||
+14
-12
@@ -70,7 +70,7 @@ tf/
|
||||
│ ├── region.hcl ← role + FQDN parts; site_id=40
|
||||
│ ├── mgmt-hosts.yaml ← mgmt-host roster (region root; fabric + render read it)
|
||||
│ ├── fabric/ ← Junos switch fabric + NetBox + mgmt reprovision
|
||||
│ └── netbird/ ← htz-fsn1 site NetBird layer (routed HTZ-FSN1 network)
|
||||
│ └── netbird/ ← htz-fsn1 site NetBird layer (routed htz-fsn1 network)
|
||||
└── global/
|
||||
├── region.hcl
|
||||
├── terragrunt.hcl ← account-wide prod NetBird (two-segment region-root stack)
|
||||
@@ -397,10 +397,10 @@ Per env (and per prod site), the baseline groups are:
|
||||
|
||||
| group | who | rendered (staging / prod htz-fsn1) |
|
||||
|---|---|---|
|
||||
| `ci` | ephemeral CI runners | `YUCCA_STAGING_CI` / `YUCCA_PROD_HTZ_FSN1_CI` |
|
||||
| `mgmt` | management nodes (configured via Ansible; also the route peers) | `YUCCA_STAGING_MGMT` / … |
|
||||
| `talos` | Talos cluster nodes | `YUCCA_STAGING_TALOS` / … |
|
||||
| `k8s_operator` | in-cluster kubernetes operator | `YUCCA_STAGING_K8S_OPERATOR` / … |
|
||||
| `ci` | ephemeral CI runners | `yucca-staging-ci` / `yucca-prod-htz-fsn1-ci` |
|
||||
| `mgmt` | management nodes (configured via Ansible; also the route peers) | `yucca-staging-mgmt` / … |
|
||||
| `talos` | Talos cluster nodes | `yucca-staging-talos` / … |
|
||||
| `k8s_operator` | in-cluster kubernetes operator | `yucca-staging-k8s-operator` / … |
|
||||
|
||||
Logical keys (the tfvars map keys, e.g. `ci`) stay lowercase; **rendered NetBird
|
||||
names are UPPER_SNAKE** (uppercased, hyphens → underscores). CI is **per-env**
|
||||
@@ -420,7 +420,7 @@ Staging is single-layer. **Prod is layered**: a `global` layer (reserved for
|
||||
account-wide / cross-region groups + policies) above per-region layers. The
|
||||
global layer is empty today — each region owns its own resource group and the
|
||||
`yucca → resources` policy is module-generated per layer (see below). Region
|
||||
groups are region-scoped (`YUCCA_PROD_<REGION>_<ROLE>`) so a network router's
|
||||
groups are region-scoped (`yucca-prod-<region>-<role>`) so a network router's
|
||||
peers are unambiguously *that region's* mgmt nodes. A region layer can still
|
||||
consume a global group via a terragrunt `dependency` on `prod/global` → the
|
||||
module's `external_groups` input, but none do today. The root terragrunt derives `stack` from the full sub-path,
|
||||
@@ -434,19 +434,21 @@ rename (`YUCCA_STAGING_*`, `NETBIRD_YUCCA_PROD_HTZ_FSN1_*`): the `env`→`partit
|
||||
|
||||
### The `yucca` → yucca-tags access model
|
||||
|
||||
`yucca` members reach everything tagged as a **yucca tag** (rendered names in caps):
|
||||
`yucca` members reach everything tagged as a **yucca tag** (NetBird object names are
|
||||
lowercase-kebab — e.g. `yucca-prod-htz-fsn1-mgmt`; the 1Password setup-key item
|
||||
titles stay UPPER_SNAKE, since CI/ansible/talos read them by `op://` string):
|
||||
|
||||
- **`yucca`** — the existing **users** group (people). External (looked up by its
|
||||
actual name `yucca`); never managed here.
|
||||
- **yucca tags** — any group flagged **`resource = true`** in a layer's `groups`.
|
||||
This marks the group **yucca-reachable**; it applies to **peer/node groups**
|
||||
(so a yucca member can SSH `YUCCA_PROD_HTZ_FSN1_MGMT`, the mgmt nodes) as well
|
||||
as routed-subnet tags (`YUCCA_PROD_HTZ_FSN1_RESOURCES`, which the site's
|
||||
(so a yucca member can SSH `yucca-prod-htz-fsn1-mgmt`, the mgmt nodes) as well
|
||||
as routed-subnet tags (`yucca-prod-htz-fsn1-resources`, which the site's
|
||||
`netbird_network_resource`s are tagged into). Today every group a layer owns is
|
||||
flagged.
|
||||
|
||||
For each layer that owns ≥1 yucca tag, the `netbird-env` module **auto-generates**
|
||||
a `<PREFIX>_YUCCA_TO_RESOURCES` policy (`bidirectional = false`) whose
|
||||
a `<prefix>-yucca-to-resources` policy (`bidirectional = false`) whose
|
||||
destinations are *all* of that layer's flagged groups — so flagging a group grants
|
||||
`yucca` users access to it (its peers and any tagged resources) with no policy to
|
||||
edit. The source is `var.yucca_users_group` (default `yucca`, looked up by name;
|
||||
@@ -498,13 +500,13 @@ policy is *not* declared here: the module generates it from every group flagged
|
||||
|
||||
### Networks (prod htz-fsn1) — CIDRs propagated, not hardcoded
|
||||
|
||||
The htz-fsn1 site layer exposes a NetBird **Network** named `HTZ-FSN1`: the
|
||||
The htz-fsn1 site layer exposes a NetBird **Network** named `htz-fsn1`: the
|
||||
`mgmt` group are the routing peers, and each routed subnet is a
|
||||
`netbird_network_resource`. The **CIDRs are derived from the same
|
||||
`fabric-addressing` module the fabric stack uses** (re-instantiated in the
|
||||
layer's `addressing.tf` — a pure, stateless module, so no duplication and no
|
||||
cross-stack coupling). Every resource is tagged into the site's own `resources`
|
||||
group, so access is the module-generated `YUCCA_PROD_HTZ_FSN1_YUCCA_TO_RESOURCES`
|
||||
group, so access is the module-generated `yucca-prod-htz-fsn1-yucca-to-resources`
|
||||
policy. The only per-site input is the site id (the CIDRs flow from it):
|
||||
|
||||
```hcl
|
||||
|
||||
+19
-19
@@ -25,26 +25,26 @@ provider "registry.opentofu.org/1password/onepassword" {
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/futo-org/netbird" {
|
||||
version = "1.0.1"
|
||||
constraints = "~> 1.0"
|
||||
version = "1.0.2"
|
||||
constraints = "1.0.2"
|
||||
hashes = [
|
||||
"h1:/7jw47nsJ3huM4DjtEwAd486NDpOg+YEkfBfLh1ZPGU=",
|
||||
"h1:FGhKWXOOHG+3K5i2LIFh3vjoeAV+AngSwwTPSHwMskQ=",
|
||||
"h1:GAirg4Iu5grhEXBFrN8BGCuDN0jy1TyIjL6uBIHT9Rs=",
|
||||
"h1:o6ixZi6QxtL7o3SkChsiINUXHkHiaJEYII2dnM81f08=",
|
||||
"zh:10c5908178a89532eb0c8213f9b4e614accd95bdd863ecaada181bd3dcfb2fc4",
|
||||
"zh:142301b60f38044d341474cddc7a3fe4b21896103783d80d17b9d3ae8bbaf358",
|
||||
"zh:1703d7e0829af459927237ce7154fd9c161aed062bf3a5cc4f43676727be3222",
|
||||
"zh:1b90a5a14b48e0905f3877114b8c9225459a6a851d572da511d1432f451837be",
|
||||
"zh:40fb5e32e53e492625dd2421d550c53edc8d241e2f48886c8b20ffbe1e4e14f8",
|
||||
"zh:40ff60d0c259a0af774081700ecab581964d0594500d02970f66a3fc6db4a0ad",
|
||||
"zh:69fb842ad58908d3ae794c8d0aa2fbdfbae0b50f428a9ca009f1be2e59fb545c",
|
||||
"zh:6ca76c6ed6fbcd159c3f9f80a2ae99592bc5f2c155873fdfda18727f8467849d",
|
||||
"h1:++sZUO9jm4pezIuPdEKS4Fr/FeDCRGI55ZvL0fqRkCg=",
|
||||
"h1:0kZr39vIeWl9WnprCdfSRfUYOe4di5PZLTWKj+BPbqg=",
|
||||
"h1:CE91Uvc3FhpgpwgjVR96ueerThTZSCTcKF8Rp2+lzQw=",
|
||||
"h1:Oo+Ck3+1EwXBiYM3S2YFpOiwllXw58zzLLFa2Ps+XVE=",
|
||||
"zh:1a1b727dd3971eb0f4c923c19fa95100e5b91b163ae0607f72a37d656f9d71a6",
|
||||
"zh:5169993e54c6b184cdb359fb310477d85eeb99d1d91db14d367a29bf3119dc55",
|
||||
"zh:573279b9532f916ee4bfb4e12faacf26e8e27df626ac37e1a5c42d5eab2350a4",
|
||||
"zh:5cafd8cb073fc6774d959080c06b6faf821c3a7caaf3d876a40be8b8945a70fd",
|
||||
"zh:66d40bbde6d756160a94e8c908582cb7806acccbebe0e9060b82cb4993f5adad",
|
||||
"zh:6eb6493922345ec4306d8f0e95e799a6045ff3b25fd05973828e960757df5b97",
|
||||
"zh:88c638c29d7dad339f1c4e90e54d0996be85a95574d5d9c5f125cb0bbb5b8902",
|
||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||
"zh:8f68847b66e7e5e71b80c83aec81cdd68790acb9de17e42ca299c396c2c9fc18",
|
||||
"zh:9112042e68282e9c1698f3192bbd818d8f09f09932534590ce444f2aeee43d42",
|
||||
"zh:9bbc34da2991c7504ea75d114ad168f9babe33d61b25dc614bc8a3432bd3b152",
|
||||
"zh:df00d3aa18251282c471ff56390d530b58b7ae5547ee1e11a3da81e5c47975ca",
|
||||
"zh:e0668eb65d8b6921e8ae2479cfab2c901198a18eb039c1fa20324301c8303f48",
|
||||
"zh:89cca24eeb5305cfcac51092bd0c330336af6613648f14a4c70f23a56fe4e93d",
|
||||
"zh:91186b07d2ee1494bcd7e2c132ca1c61b62b2a1f2d325d2bbc4bfe6572ce327d",
|
||||
"zh:aa6cbe8f5c8121d96861e293d3773cc210723fa410acf45512a337703d55d911",
|
||||
"zh:d38dce0bcc61ca2482ee3b9f457ebf45929c7ebc8717487d9f1270aa3dcd3cfa",
|
||||
"zh:dba9742f0a0cb5e190a10265ec00d20a4d266f8a6dd517cb4c1d8486335ed636",
|
||||
"zh:e8eaabc072208c10ab554b4c89dbe32831a7d0125ab628af4a6530a02ea5a993",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ terraform {
|
||||
required_providers {
|
||||
netbird = {
|
||||
source = "registry.terraform.io/futo-org/netbird"
|
||||
version = "~> 1.0"
|
||||
version = "1.0.2"
|
||||
}
|
||||
onepassword = {
|
||||
source = "1Password/onepassword"
|
||||
|
||||
+19
-16
@@ -25,23 +25,26 @@ provider "registry.opentofu.org/1password/onepassword" {
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/futo-org/netbird" {
|
||||
version = "1.0.1"
|
||||
constraints = "~> 1.0"
|
||||
version = "1.0.2"
|
||||
constraints = "1.0.2"
|
||||
hashes = [
|
||||
"h1:/7jw47nsJ3huM4DjtEwAd486NDpOg+YEkfBfLh1ZPGU=",
|
||||
"zh:10c5908178a89532eb0c8213f9b4e614accd95bdd863ecaada181bd3dcfb2fc4",
|
||||
"zh:142301b60f38044d341474cddc7a3fe4b21896103783d80d17b9d3ae8bbaf358",
|
||||
"zh:1703d7e0829af459927237ce7154fd9c161aed062bf3a5cc4f43676727be3222",
|
||||
"zh:1b90a5a14b48e0905f3877114b8c9225459a6a851d572da511d1432f451837be",
|
||||
"zh:40fb5e32e53e492625dd2421d550c53edc8d241e2f48886c8b20ffbe1e4e14f8",
|
||||
"zh:40ff60d0c259a0af774081700ecab581964d0594500d02970f66a3fc6db4a0ad",
|
||||
"zh:69fb842ad58908d3ae794c8d0aa2fbdfbae0b50f428a9ca009f1be2e59fb545c",
|
||||
"zh:6ca76c6ed6fbcd159c3f9f80a2ae99592bc5f2c155873fdfda18727f8467849d",
|
||||
"h1:++sZUO9jm4pezIuPdEKS4Fr/FeDCRGI55ZvL0fqRkCg=",
|
||||
"h1:0kZr39vIeWl9WnprCdfSRfUYOe4di5PZLTWKj+BPbqg=",
|
||||
"h1:CE91Uvc3FhpgpwgjVR96ueerThTZSCTcKF8Rp2+lzQw=",
|
||||
"h1:Oo+Ck3+1EwXBiYM3S2YFpOiwllXw58zzLLFa2Ps+XVE=",
|
||||
"zh:1a1b727dd3971eb0f4c923c19fa95100e5b91b163ae0607f72a37d656f9d71a6",
|
||||
"zh:5169993e54c6b184cdb359fb310477d85eeb99d1d91db14d367a29bf3119dc55",
|
||||
"zh:573279b9532f916ee4bfb4e12faacf26e8e27df626ac37e1a5c42d5eab2350a4",
|
||||
"zh:5cafd8cb073fc6774d959080c06b6faf821c3a7caaf3d876a40be8b8945a70fd",
|
||||
"zh:66d40bbde6d756160a94e8c908582cb7806acccbebe0e9060b82cb4993f5adad",
|
||||
"zh:6eb6493922345ec4306d8f0e95e799a6045ff3b25fd05973828e960757df5b97",
|
||||
"zh:88c638c29d7dad339f1c4e90e54d0996be85a95574d5d9c5f125cb0bbb5b8902",
|
||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||
"zh:8f68847b66e7e5e71b80c83aec81cdd68790acb9de17e42ca299c396c2c9fc18",
|
||||
"zh:9112042e68282e9c1698f3192bbd818d8f09f09932534590ce444f2aeee43d42",
|
||||
"zh:9bbc34da2991c7504ea75d114ad168f9babe33d61b25dc614bc8a3432bd3b152",
|
||||
"zh:df00d3aa18251282c471ff56390d530b58b7ae5547ee1e11a3da81e5c47975ca",
|
||||
"zh:e0668eb65d8b6921e8ae2479cfab2c901198a18eb039c1fa20324301c8303f48",
|
||||
"zh:89cca24eeb5305cfcac51092bd0c330336af6613648f14a4c70f23a56fe4e93d",
|
||||
"zh:91186b07d2ee1494bcd7e2c132ca1c61b62b2a1f2d325d2bbc4bfe6572ce327d",
|
||||
"zh:aa6cbe8f5c8121d96861e293d3773cc210723fa410acf45512a337703d55d911",
|
||||
"zh:d38dce0bcc61ca2482ee3b9f457ebf45929c7ebc8717487d9f1270aa3dcd3cfa",
|
||||
"zh:dba9742f0a0cb5e190a10265ec00d20a4d266f8a6dd517cb4c1d8486335ed636",
|
||||
"zh:e8eaabc072208c10ab554b4c89dbe32831a7d0125ab628af4a6530a02ea5a993",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
# routed-subnet tag the site Network resources (netbird.tf) are tagged into;
|
||||
# it replaced the retired shared "yucca_resource" tag.
|
||||
groups = {
|
||||
ci = { resource = true } # ephemeral CI runners → YUCCA_PROD_HTZ_FSN1_CI
|
||||
ci = { resource = true } # ephemeral CI runners → yucca-prod-htz-fsn1-ci
|
||||
mgmt = { resource = true } # management nodes (ansible); also the route peers
|
||||
talos = { resource = true } # Talos cluster nodes → YUCCA_PROD_HTZ_FSN1_TALOS
|
||||
talos = { resource = true } # Talos cluster nodes → yucca-prod-htz-fsn1-talos
|
||||
k8s_operator = { resource = true } # in-cluster kubernetes operator
|
||||
resources = { resource = true } # routed-subnet tag → YUCCA_PROD_HTZ_FSN1_RESOURCES
|
||||
resources = { resource = true } # routed-subnet tag → yucca-prod-htz-fsn1-resources (Network resources tag in)
|
||||
}
|
||||
|
||||
setup_keys = {
|
||||
|
||||
@@ -3,7 +3,7 @@ terraform {
|
||||
required_providers {
|
||||
netbird = {
|
||||
source = "registry.terraform.io/futo-org/netbird"
|
||||
version = "~> 1.0"
|
||||
version = "1.0.2"
|
||||
}
|
||||
onepassword = {
|
||||
source = "1Password/onepassword"
|
||||
|
||||
+19
-19
@@ -25,26 +25,26 @@ provider "registry.opentofu.org/1password/onepassword" {
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/futo-org/netbird" {
|
||||
version = "1.0.1"
|
||||
constraints = "~> 1.0"
|
||||
version = "1.0.2"
|
||||
constraints = "1.0.2"
|
||||
hashes = [
|
||||
"h1:/7jw47nsJ3huM4DjtEwAd486NDpOg+YEkfBfLh1ZPGU=",
|
||||
"h1:FGhKWXOOHG+3K5i2LIFh3vjoeAV+AngSwwTPSHwMskQ=",
|
||||
"h1:GAirg4Iu5grhEXBFrN8BGCuDN0jy1TyIjL6uBIHT9Rs=",
|
||||
"h1:o6ixZi6QxtL7o3SkChsiINUXHkHiaJEYII2dnM81f08=",
|
||||
"zh:10c5908178a89532eb0c8213f9b4e614accd95bdd863ecaada181bd3dcfb2fc4",
|
||||
"zh:142301b60f38044d341474cddc7a3fe4b21896103783d80d17b9d3ae8bbaf358",
|
||||
"zh:1703d7e0829af459927237ce7154fd9c161aed062bf3a5cc4f43676727be3222",
|
||||
"zh:1b90a5a14b48e0905f3877114b8c9225459a6a851d572da511d1432f451837be",
|
||||
"zh:40fb5e32e53e492625dd2421d550c53edc8d241e2f48886c8b20ffbe1e4e14f8",
|
||||
"zh:40ff60d0c259a0af774081700ecab581964d0594500d02970f66a3fc6db4a0ad",
|
||||
"zh:69fb842ad58908d3ae794c8d0aa2fbdfbae0b50f428a9ca009f1be2e59fb545c",
|
||||
"zh:6ca76c6ed6fbcd159c3f9f80a2ae99592bc5f2c155873fdfda18727f8467849d",
|
||||
"h1:++sZUO9jm4pezIuPdEKS4Fr/FeDCRGI55ZvL0fqRkCg=",
|
||||
"h1:0kZr39vIeWl9WnprCdfSRfUYOe4di5PZLTWKj+BPbqg=",
|
||||
"h1:CE91Uvc3FhpgpwgjVR96ueerThTZSCTcKF8Rp2+lzQw=",
|
||||
"h1:Oo+Ck3+1EwXBiYM3S2YFpOiwllXw58zzLLFa2Ps+XVE=",
|
||||
"zh:1a1b727dd3971eb0f4c923c19fa95100e5b91b163ae0607f72a37d656f9d71a6",
|
||||
"zh:5169993e54c6b184cdb359fb310477d85eeb99d1d91db14d367a29bf3119dc55",
|
||||
"zh:573279b9532f916ee4bfb4e12faacf26e8e27df626ac37e1a5c42d5eab2350a4",
|
||||
"zh:5cafd8cb073fc6774d959080c06b6faf821c3a7caaf3d876a40be8b8945a70fd",
|
||||
"zh:66d40bbde6d756160a94e8c908582cb7806acccbebe0e9060b82cb4993f5adad",
|
||||
"zh:6eb6493922345ec4306d8f0e95e799a6045ff3b25fd05973828e960757df5b97",
|
||||
"zh:88c638c29d7dad339f1c4e90e54d0996be85a95574d5d9c5f125cb0bbb5b8902",
|
||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||
"zh:8f68847b66e7e5e71b80c83aec81cdd68790acb9de17e42ca299c396c2c9fc18",
|
||||
"zh:9112042e68282e9c1698f3192bbd818d8f09f09932534590ce444f2aeee43d42",
|
||||
"zh:9bbc34da2991c7504ea75d114ad168f9babe33d61b25dc614bc8a3432bd3b152",
|
||||
"zh:df00d3aa18251282c471ff56390d530b58b7ae5547ee1e11a3da81e5c47975ca",
|
||||
"zh:e0668eb65d8b6921e8ae2479cfab2c901198a18eb039c1fa20324301c8303f48",
|
||||
"zh:89cca24eeb5305cfcac51092bd0c330336af6613648f14a4c70f23a56fe4e93d",
|
||||
"zh:91186b07d2ee1494bcd7e2c132ca1c61b62b2a1f2d325d2bbc4bfe6572ce327d",
|
||||
"zh:aa6cbe8f5c8121d96861e293d3773cc210723fa410acf45512a337703d55d911",
|
||||
"zh:d38dce0bcc61ca2482ee3b9f457ebf45929c7ebc8717487d9f1270aa3dcd3cfa",
|
||||
"zh:dba9742f0a0cb5e190a10265ec00d20a4d266f8a6dd517cb4c1d8486335ed636",
|
||||
"zh:e8eaabc072208c10ab554b4c89dbe32831a7d0125ab628af4a6530a02ea5a993",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ terraform {
|
||||
required_providers {
|
||||
netbird = {
|
||||
source = "registry.terraform.io/futo-org/netbird"
|
||||
version = "~> 1.0"
|
||||
version = "1.0.2"
|
||||
}
|
||||
onepassword = {
|
||||
source = "1Password/onepassword"
|
||||
|
||||
@@ -7,13 +7,23 @@
|
||||
# module only declares the dependency in versions.tf).
|
||||
|
||||
locals {
|
||||
# DERIVED names are normalized to UPPER_SNAKE: uppercased, hyphens → underscores.
|
||||
# e.g. name_prefix "yucca_prod_htz-fsn1" + key "mgmt" → "YUCCA_PROD_HTZ_FSN1_MGMT".
|
||||
# An explicit `name` override is taken VERBATIM (not uppercased), for groups that
|
||||
# must keep an exact pre-existing name (e.g. one created outside this module).
|
||||
# Network display names are likewise verbatim.
|
||||
# DERIVED NetBird object names are normalized to lowercase-kebab: lowercased,
|
||||
# underscores → hyphens. e.g. name_prefix "yucca_prod_htz-fsn1" + key "mgmt" →
|
||||
# "yucca-prod-htz-fsn1-mgmt"; key "k8s_operator" → "yucca-prod-htz-fsn1-k8s-operator".
|
||||
# An explicit `name` override is taken VERBATIM, for objects that must keep an
|
||||
# exact pre-existing name (e.g. one created outside this module).
|
||||
# NB: the 1Password setup-key item TITLES are deliberately NOT kebab — they stay
|
||||
# UPPER_SNAKE (see setup_key_op_titles below) because CI / ansible / the talos
|
||||
# stack read them by string via op:// refs.
|
||||
group_names = {
|
||||
for k, g in var.groups : k => coalesce(g.name, upper(replace("${var.name_prefix}_${k}", "-", "_")))
|
||||
for k, g in var.groups : k => coalesce(g.name, lower(replace("${var.name_prefix}_${k}", "_", "-")))
|
||||
}
|
||||
|
||||
# UPPER_SNAKE 1Password item titles for the minted setup keys, kept stable
|
||||
# (decoupled from the now-kebab NetBird object name) so external op:// consumers
|
||||
# keep resolving. e.g. key "mgmt" → "NETBIRD_YUCCA_PROD_HTZ_FSN1_MGMT_SETUP_KEY".
|
||||
setup_key_op_titles = {
|
||||
for k, s in var.setup_keys : k => "NETBIRD_${upper(replace("${var.name_prefix}_${k}", "-", "_"))}_SETUP_KEY"
|
||||
}
|
||||
|
||||
# Logical key → NetBird group ID, covering both the groups this layer owns and
|
||||
@@ -33,7 +43,7 @@ locals {
|
||||
description = r.description
|
||||
groups = r.groups
|
||||
enabled = r.enabled
|
||||
name = upper(replace(coalesce(r.name, "${nk}_${rk}"), "-", "_"))
|
||||
name = lower(replace(coalesce(r.name, "${nk}_${rk}"), "_", "-"))
|
||||
}
|
||||
}
|
||||
]...)
|
||||
@@ -59,7 +69,7 @@ resource "netbird_group" "this" {
|
||||
resource "netbird_setup_key" "this" {
|
||||
for_each = var.setup_keys
|
||||
|
||||
name = upper(replace("${var.name_prefix}_${each.key}", "-", "_"))
|
||||
name = lower(replace("${var.name_prefix}_${each.key}", "_", "-"))
|
||||
type = each.value.type
|
||||
expiry_seconds = each.value.expiry_seconds
|
||||
usage_limit = each.value.usage_limit
|
||||
@@ -72,14 +82,14 @@ resource "netbird_setup_key" "this" {
|
||||
resource "netbird_policy" "this" {
|
||||
for_each = var.policies
|
||||
|
||||
name = upper(replace("${var.name_prefix}_${each.key}", "-", "_"))
|
||||
name = lower(replace("${var.name_prefix}_${each.key}", "_", "-"))
|
||||
description = each.value.description
|
||||
enabled = each.value.enabled
|
||||
|
||||
dynamic "rule" {
|
||||
for_each = each.value.rules
|
||||
content {
|
||||
name = upper(replace(rule.value.name, "-", "_"))
|
||||
name = lower(replace(rule.value.name, "_", "-"))
|
||||
action = rule.value.action
|
||||
protocol = rule.value.protocol
|
||||
bidirectional = rule.value.bidirectional
|
||||
@@ -108,7 +118,7 @@ data "netbird_group" "yucca_users" {
|
||||
resource "netbird_policy" "yucca_to_resources" {
|
||||
count = local.manage_resource_policy ? 1 : 0
|
||||
|
||||
name = upper(replace("${var.name_prefix}_yucca_to_resources", "-", "_"))
|
||||
name = lower(replace("${var.name_prefix}_yucca_to_resources", "_", "-"))
|
||||
description = "${var.yucca_users_group} users → every yucca-tagged (resource=true) group in this layer: peers + tagged resources (auto-derived)."
|
||||
enabled = true
|
||||
|
||||
@@ -127,11 +137,11 @@ resource "netbird_policy" "yucca_to_resources" {
|
||||
# A Network groups one or more resources (subnets/hosts) reachable through a set
|
||||
# of routing peers (router.peer_groups — e.g. a site's mgmt nodes). resources[*]
|
||||
# .groups controls which peers may reach that subnet. The Network's display name
|
||||
# is the map key (or `name` override), uppercased but NOT underscore-normalized —
|
||||
# so human labels like "HTZ-FSN1" survive (hyphen kept).
|
||||
# is the lowercase-kebab map key (or `name` override) — e.g. key "HTZ-FSN1" →
|
||||
# "htz-fsn1". The map key itself is unchanged (resources address by network_id).
|
||||
resource "netbird_network" "this" {
|
||||
for_each = var.networks
|
||||
name = coalesce(each.value.name, each.key)
|
||||
name = coalesce(each.value.name, lower(replace(each.key, "_", "-")))
|
||||
description = each.value.description
|
||||
}
|
||||
|
||||
@@ -167,10 +177,11 @@ resource "onepassword_item" "setup_key" {
|
||||
for_each = var.setup_keys
|
||||
|
||||
vault = data.onepassword_vault.env.uuid
|
||||
# Title derived from the (already UPPER_SNAKE) setup-key name so multiple sites
|
||||
# writing to the SAME vault (prod: global + every site → yucca_tf_prod) never
|
||||
# collide, e.g. "YUCCA_PROD_HTZ_FSN1_MGMT" → NETBIRD_YUCCA_PROD_HTZ_FSN1_MGMT_SETUP_KEY.
|
||||
title = "NETBIRD_${netbird_setup_key.this[each.key].name}_SETUP_KEY"
|
||||
# Title stays UPPER_SNAKE (decoupled from the now-kebab NetBird setup-key name)
|
||||
# so external op:// consumers (CI, ansible, talos) keep resolving, and so multiple
|
||||
# sites writing to the SAME vault (prod: global + every site → yucca_tf_prod)
|
||||
# never collide. e.g. key "mgmt" → NETBIRD_YUCCA_PROD_HTZ_FSN1_MGMT_SETUP_KEY.
|
||||
title = local.setup_key_op_titles[each.key]
|
||||
category = "password"
|
||||
password = netbird_setup_key.this[each.key].key
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ terraform {
|
||||
# Only published to the Terraform registry, so the source is fully
|
||||
# qualified — OpenTofu would otherwise look it up on registry.opentofu.org.
|
||||
source = "registry.terraform.io/futo-org/netbird"
|
||||
version = "~> 1.0"
|
||||
version = "1.0.2" # pinned: 1.0.2 fixes the group resources TF→API decode (rename of groups with tagged resources)
|
||||
}
|
||||
# Writes minted setup keys into the per-env yucca_tf_<env> vault as the
|
||||
# source-of-truth record. Auth via OP_SERVICE_ACCOUNT_TOKEN (op run).
|
||||
|
||||
Reference in New Issue
Block a user