From dca339bcff2f907472d46ed2355381ab8b4b7d85 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Fri, 24 Jul 2026 16:26:17 +0200 Subject: [PATCH 1/6] feat: unify to a single stackit landing zone architecture with optional networking --- .../stackit-hub-spoke/README.md | 107 ------ .../stackit-hub-spoke/buildingblock/README.md | 77 ---- .../buildingblock/SUMMARY.md.tftpl | 14 - .../stackit-hub-spoke/buildingblock/main.tf | 104 ------ .../buildingblock/outputs.tf | 26 -- .../buildingblock/variables.tf | 141 ------- .../meshstack_integration.tf | 348 ------------------ .../stackit-landingzone/README.md | 156 ++++++++ .../buildingblock/README.md | 83 +++++ .../buildingblock/SUMMARY.md.tftpl | 21 ++ .../buildingblock/logo.png | Bin .../stackit-landingzone/buildingblock/main.tf | 151 ++++++++ .../buildingblock/outputs.tf | 27 ++ .../buildingblock/provider.tf | 0 .../buildingblock/variables.tf | 37 +- .../buildingblock/versions.tf | 0 .../logo.png | Bin .../meshstack_integration.tf | 117 ++++-- .../stackit-sandbox-landingzone/README.md | 54 --- .../buildingblock/README.md | 68 ---- .../buildingblock/logo.png | Bin 2285 -> 0 bytes .../buildingblock/main.tf | 48 --- .../buildingblock/outputs.tf | 14 - .../buildingblock/provider.tf | 4 - .../buildingblock/versions.tf | 14 - .../stackit-sandbox-landingzone/logo.png | Bin 5579 -> 0 bytes 26 files changed, 547 insertions(+), 1064 deletions(-) delete mode 100644 reference-architectures/stackit-hub-spoke/README.md delete mode 100644 reference-architectures/stackit-hub-spoke/buildingblock/README.md delete mode 100644 reference-architectures/stackit-hub-spoke/buildingblock/SUMMARY.md.tftpl delete mode 100644 reference-architectures/stackit-hub-spoke/buildingblock/main.tf delete mode 100644 reference-architectures/stackit-hub-spoke/buildingblock/outputs.tf delete mode 100644 reference-architectures/stackit-hub-spoke/buildingblock/variables.tf delete mode 100644 reference-architectures/stackit-hub-spoke/meshstack_integration.tf create mode 100644 reference-architectures/stackit-landingzone/README.md create mode 100644 reference-architectures/stackit-landingzone/buildingblock/README.md create mode 100644 reference-architectures/stackit-landingzone/buildingblock/SUMMARY.md.tftpl rename reference-architectures/{stackit-hub-spoke => stackit-landingzone}/buildingblock/logo.png (100%) create mode 100644 reference-architectures/stackit-landingzone/buildingblock/main.tf create mode 100644 reference-architectures/stackit-landingzone/buildingblock/outputs.tf rename reference-architectures/{stackit-hub-spoke => stackit-landingzone}/buildingblock/provider.tf (100%) rename reference-architectures/{stackit-sandbox-landingzone => stackit-landingzone}/buildingblock/variables.tf (52%) rename reference-architectures/{stackit-hub-spoke => stackit-landingzone}/buildingblock/versions.tf (100%) rename reference-architectures/{stackit-hub-spoke => stackit-landingzone}/logo.png (100%) rename reference-architectures/{stackit-sandbox-landingzone => stackit-landingzone}/meshstack_integration.tf (64%) delete mode 100644 reference-architectures/stackit-sandbox-landingzone/README.md delete mode 100644 reference-architectures/stackit-sandbox-landingzone/buildingblock/README.md delete mode 100644 reference-architectures/stackit-sandbox-landingzone/buildingblock/logo.png delete mode 100644 reference-architectures/stackit-sandbox-landingzone/buildingblock/main.tf delete mode 100644 reference-architectures/stackit-sandbox-landingzone/buildingblock/outputs.tf delete mode 100644 reference-architectures/stackit-sandbox-landingzone/buildingblock/provider.tf delete mode 100644 reference-architectures/stackit-sandbox-landingzone/buildingblock/versions.tf delete mode 100644 reference-architectures/stackit-sandbox-landingzone/logo.png diff --git a/reference-architectures/stackit-hub-spoke/README.md b/reference-architectures/stackit-hub-spoke/README.md deleted file mode 100644 index 311cc25c..00000000 --- a/reference-architectures/stackit-hub-spoke/README.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -name: STACKIT Hub-and-Spoke Network -description: > - Bootstraps a STACKIT sandbox platform together with a hub-and-spoke network topology: - a shared network-area address plan (hub) and a self-service routed-network building - block (spoke) for application teams. -cloudProviders: - - stackit -buildingBlocks: - - path: stackit/project - role: Provisions a STACKIT Project with role assignments. - - path: stackit/network-area - role: Provisions the hub network area with the shared IPv4 address plan. - - path: stackit/network - role: Lets application teams self-service order routed spoke networks inside their projects. ---- - -# STACKIT Hub-and-Spoke Network - -## Overview - -The **STACKIT Hub-and-Spoke Network** reference architecture turns a bare STACKIT organization -into a self-service-ready meshStack platform with IPAM built in: a shared network-area address -plan (the hub) that all tenant projects draw from, and a self-service routed-network building -block (the spoke) application teams can order inside their own projects. It builds on the -[STACKIT Sandbox Landing Zone](../stackit-sandbox-landingzone/README.md) foundation. - -**Target audience:** - -- **Platform engineers** bootstrapping a new STACKIT organization who want network segmentation - from day one, without hand-wiring a network area and its address plan separately. -- **Application teams** who need a dedicated IPv4 subnet inside their STACKIT project without - manually coordinating CIDR ranges with the platform team. - -## Architecture Diagram - -```mermaid -flowchart LR - subgraph Bootstrap["Platform Bootstrap"] - PLAT[STACKIT Project Platform] - PLAT --> DEFLZ[Default Landing Zone] - PLAT --> NETLZ[Networked Landing Zone] - end - - NETLZ -->|new projects land in| HUB - - subgraph HUB["Hub"] - NA["Network Area
shared IPv4 address plan"] - end - - HUB --> TP1[Tenant Project A] - HUB --> TP2[Tenant Project B] - - subgraph SPOKES["Spokes (self-service)"] - TP1 -->|orders stackit/network| NET1[Routed Network] - TP2 -->|orders stackit/network| NET2[Routed Network] - end - - NET1 -.draws CIDR from.-> NA - NET2 -.draws CIDR from.-> NA -``` - -Application teams order a routed network into their own project via the self-service -`stackit/network` building block; each order draws its subnet from the hub's address plan, -so no two spokes can accidentally collide on CIDR ranges. - -## How It Works - -Running this reference architecture: - -1. Sources the [STACKIT Sandbox Landing Zone](../stackit-sandbox-landingzone/README.md) to - create the landing-zone folder, backplane project, and the **STACKIT Project** platform with - its default landing zone. -2. Registers the [`stackit/network-area`](../../modules/stackit/network-area) building block - definition and immediately orders **one instance** of it in the platform team's own - workspace — this is the hub's IPv4 address plan. -3. Registers the [`stackit/network`](../../modules/stackit/network) building block definition - (`TENANT_LEVEL`) so application teams can self-service order routed networks (spokes) inside - their STACKIT projects, drawing from the hub's address plan. -4. Provisions an additional **networked landing zone**, tagged with the hub's network area ID, - so new STACKIT projects created against it are placed in the hub's network area. - -## Getting Started - -### Prerequisites - -| Requirement | Description | -|-----------------------|------------------------------------------------------------------------------------| -| STACKIT organization | With a service account key that has `resource-manager.admin` on the organization. | -| CIDR plan | A non-overlapping IPv4 address plan chosen up front for the hub network ranges and transfer network. | - -### Deployment Order - -Order the **STACKIT Hub and Spoke Network** building block once per workspace. It creates the -platform, the hub network area instance, and registers the spoke `stackit/network` building -block in a single apply. Application teams can then order `stackit/network` inside their own -STACKIT projects once those projects exist. - -## Shared Responsibilities - -| Responsibility | Platform Team | Application Team | -|---------------------------------------------------------------------------|:---:|:---:| -| Provision the STACKIT platform and landing zones | ✅ | ❌ | -| Provision the hub network area and choose its address plan | ✅ | ❌ | -| Register the spoke `stackit/network` building block for self-service | ✅ | ❌ | -| Order spoke networks inside their STACKIT projects | ❌ | ✅ | -| Use the assigned subnet for their workloads | ❌ | ✅ | diff --git a/reference-architectures/stackit-hub-spoke/buildingblock/README.md b/reference-architectures/stackit-hub-spoke/buildingblock/README.md deleted file mode 100644 index c7e3803e..00000000 --- a/reference-architectures/stackit-hub-spoke/buildingblock/README.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -name: STACKIT Hub and Spoke Network -supportedPlatforms: - - stackit -description: Bootstraps a STACKIT sandbox platform together with a hub-and-spoke network topology, provisioning the hub network area and registering the self-service spoke network building block. ---- - -This building block composes three Hub modules into a single orderable offering: it sources -[`stackit-sandbox-landingzone`](../../stackit-sandbox-landingzone/buildingblock) to bootstrap the -STACKIT platform, registers [`modules/stackit/network-area`](../../../modules/stackit/network-area) -and immediately orders one instance of it as the hub address plan, and registers -[`modules/stackit/network`](../../../modules/stackit/network) so application teams can self-service -order routed spoke networks inside their STACKIT projects. New STACKIT projects are placed in the -hub's network area via an additional `networked` landing zone tagged with the hub's network area ID. - -The user-facing readme is maintained inline in the `readme` field of the -`meshstack_building_block_definition` in -[`../meshstack_integration.tf`](../meshstack_integration.tf). - - -## Requirements - -| Name | Version | -| ---- | ------- | -| [terraform](#requirement\_terraform) | >= 1.12.0 | -| [meshstack](#requirement\_meshstack) | >= 0.24.0 | -| [stackit](#requirement\_stackit) | >= 0.99.0 | - -## Modules - -| Name | Source | Version | -| ---- | ------ | ------- | -| [foundation](#module\_foundation) | github.com/meshcloud/meshstack-hub//reference-architectures/stackit-sandbox-landingzone/buildingblock | main | -| [network\_area\_integration](#module\_network\_area\_integration) | github.com/meshcloud/meshstack-hub//modules/stackit/network-area | main | -| [network\_integration](#module\_network\_integration) | github.com/meshcloud/meshstack-hub//modules/stackit/network | main | - -## Resources - -| Name | Type | -| ---- | ---- | -| [meshstack_building_block.network_area_hub](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block) | resource | -| [meshstack_landingzone.networked](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/landingzone) | resource | -| [meshstack_landingzone.foundation_default](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/data-sources/landingzone) | data source | - -## Inputs - -| Name | Description | Type | Default | Required | -| ---- | ----------- | ---- | ------- | :------: | -| [hub](#input\_hub) | `git_ref`: meshstack-hub reference used to source the nested foundation, network-area, and network integration modules. `const` so it can be interpolated into the module source at init time.

`bbd_draft`: Forwarded as-is to those nested integrations' own `hub.bbd_draft`, so their building block definition draft state tracks this building block's own release state. |
object({
git_ref = optional(string, "main")
bbd_draft = optional(bool, true)
})
|
{
"bbd_draft": true,
"git_ref": "main"
}
| no | -| [hub\_default\_nameservers](#input\_hub\_default\_nameservers) | Default IPv4 nameservers assigned to networks created within the hub network area. | `list(string)` | `[]` | no | -| [hub\_default\_prefix\_length](#input\_hub\_default\_prefix\_length) | Default prefix length used for networks created within the hub network area when none is specified. | `number` | `28` | no | -| [hub\_max\_prefix\_length](#input\_hub\_max\_prefix\_length) | Maximum prefix length allowed for networks created within the hub network area. | `number` | `28` | no | -| [hub\_min\_prefix\_length](#input\_hub\_min\_prefix\_length) | Minimum prefix length allowed for networks created within the hub network area. | `number` | `24` | no | -| [hub\_network\_area\_name](#input\_hub\_network\_area\_name) | Name of the hub STACKIT network area instance. | `string` | `"hub"` | no | -| [hub\_network\_ranges](#input\_hub\_network\_ranges) | List of IPv4 CIDR ranges available to projects within the hub network area. | `list(string)` |
[
"10.0.0.0/16"
]
| no | -| [hub\_transfer\_network](#input\_hub\_transfer\_network) | IPv4 CIDR range used as the transfer network between the hub network area and connected networks. | `string` | `"10.1.255.0/24"` | no | -| [network\_area\_tag\_name](#input\_network\_area\_tag\_name) | Name of the meshStack landing zone tag whose value is the hub network area's ID. Forwarded to the foundation's nested STACKIT Project integration (so it knows which tag to read) and set on the `networked` landing zone created here (with the hub's network area ID as its value). | `string` | `"StackitNetworkArea"` | no | -| [platform\_identifier](#input\_platform\_identifier) | Identifier for the STACKIT sandbox platform created in meshStack (letters, digits and dashes only). | `string` | n/a | yes | -| [role\_mapping](#input\_role\_mapping) | Default mapping from meshStack roles to STACKIT project roles for the nested STACKIT Project integration. Values can be built-in STACKIT roles or custom STACKIT role names. | `map(list(string))` |
{
"admin": [
"owner"
],
"reader": [
"reader"
],
"user": [
"editor"
]
}
| no | -| [stackit\_org](#input\_stackit\_org) | STACKIT organization UUID under which the landing-zone folder, backplane project and tenant projects are created. | `string` | n/a | yes | -| [stackit\_organization\_onboarding\_enabled](#input\_stackit\_organization\_onboarding\_enabled) | Whether the nested STACKIT Project integration adds meshStack project users to the STACKIT organization before applying project-level role assignments. Disable if organization membership is managed outside this landing zone. | `bool` | `true` | no | -| [stackit\_owner\_email](#input\_stackit\_owner\_email) | Owner email assigned to the STACKIT resourcemanager folder and backplane project. | `string` | n/a | yes | -| [stackit\_service\_account\_key](#input\_stackit\_service\_account\_key) | STACKIT service account key JSON with `resource-manager.admin` on the organization. Used to create the landing-zone folder and backplane project. | `string` | n/a | yes | -| [tags](#input\_tags) | Tags forwarded to the nested foundation, network-area, and network integrations. `landingzone` tags are applied to the created landing zones; `building_block` tags are applied to the nested building block definitions. |
object({
landingzone = map(list(string))
building_block = map(list(string))
})
|
{
"building_block": {},
"landingzone": {}
}
| no | -| [tenant\_network\_max\_prefix\_length](#input\_tenant\_network\_max\_prefix\_length) | Maximum allowed IPv4 prefix length for the spoke network BBD's prefix length input, offered to application teams ordering spoke networks. | `number` | `28` | no | -| [tenant\_network\_min\_prefix\_length](#input\_tenant\_network\_min\_prefix\_length) | Minimum allowed IPv4 prefix length for the spoke network BBD's prefix length input, offered to application teams ordering spoke networks. | `number` | `24` | no | -| [use\_global\_location](#input\_use\_global\_location) | Use the global location instead of creating a dedicated location for this platform. | `bool` | `false` | no | -| [workspace](#input\_workspace) | Identifier of the meshStack workspace that will own the created platform, location, landing zones, and the hub network-area instance. | `string` | n/a | yes | - -## Outputs - -| Name | Description | -| ---- | ----------- | -| [backplane\_project\_id](#output\_backplane\_project\_id) | Project ID of the STACKIT backplane project that hosts the service account used for tenant project creation. | -| [backplane\_project\_url](#output\_backplane\_project\_url) | Deep link to the backplane project in the STACKIT portal. | -| [lz\_folder\_container\_id](#output\_lz\_folder\_container\_id) | Container ID of the STACKIT resourcemanager folder created for the landing zone. Tenant projects are created inside this folder. | - diff --git a/reference-architectures/stackit-hub-spoke/buildingblock/SUMMARY.md.tftpl b/reference-architectures/stackit-hub-spoke/buildingblock/SUMMARY.md.tftpl deleted file mode 100644 index fbfd8db6..00000000 --- a/reference-architectures/stackit-hub-spoke/buildingblock/SUMMARY.md.tftpl +++ /dev/null @@ -1,14 +0,0 @@ -# STACKIT Hub and Spoke Network: **${platform_identifier}** - -## Details - -| Property | Value | -|----------|-------| -| **Backplane Project** | [Open in STACKIT Portal](${backplane_project_url}) (`${backplane_project_id}`) | -| **Landing Zone Folder** | `${lz_folder_container_id}` | -| **Networked Landing Zone** | `${networked_landingzone_name}` | -| **Hub Network Area** | @buildingblock[${network_area_hub_uuid}] | - -Application teams can now order the **STACKIT Network** building block inside their own projects in -the `${networked_landingzone_name}` landing zone to get a routed spoke network drawn from the hub's -address plan. diff --git a/reference-architectures/stackit-hub-spoke/buildingblock/main.tf b/reference-architectures/stackit-hub-spoke/buildingblock/main.tf deleted file mode 100644 index 8e9de323..00000000 --- a/reference-architectures/stackit-hub-spoke/buildingblock/main.tf +++ /dev/null @@ -1,104 +0,0 @@ -module "foundation" { - source = "github.com/meshcloud/meshstack-hub//reference-architectures/stackit-sandbox-landingzone/buildingblock?ref=${var.hub.git_ref}" - - workspace = var.workspace - use_global_location = var.use_global_location - stackit_org = var.stackit_org - stackit_owner_email = var.stackit_owner_email - stackit_service_account_key = var.stackit_service_account_key - platform_identifier = var.platform_identifier - tags = var.tags - role_mapping = var.role_mapping - stackit_organization_onboarding_enabled = var.stackit_organization_onboarding_enabled - network_area_tag_name = var.network_area_tag_name - hub = var.hub -} - -module "network_area_integration" { - source = "github.com/meshcloud/meshstack-hub//modules/stackit/network-area?ref=${var.hub.git_ref}" - - stackit_organization_id = var.stackit_org - stackit_project_id = module.foundation.backplane_project_id - - meshstack = { owning_workspace_identifier = var.workspace, tags = var.tags.building_block } - hub = var.hub -} - -module "network_integration" { - source = "github.com/meshcloud/meshstack-hub//modules/stackit/network?ref=${var.hub.git_ref}" - - stackit_organization_id = var.stackit_org - stackit_project_id = module.foundation.backplane_project_id - stackit_network_min_prefix_length = var.tenant_network_min_prefix_length - stackit_network_max_prefix_length = var.tenant_network_max_prefix_length - - meshstack = { owning_workspace_identifier = var.workspace, tags = var.tags.building_block } - hub = var.hub -} - -resource "meshstack_building_block" "network_area_hub" { - wait_for_completion = true - depends_on = [module.network_area_integration] - - spec = { - building_block_definition_version_ref = { - uuid = module.network_area_integration.building_block_definition.version_ref.uuid - } - display_name = "Hub Network Area" - target_ref = { kind = "meshWorkspace", name = var.workspace } - - inputs = { - network_area_name = { - value = jsonencode(var.hub_network_area_name) - } - network_ranges = { - value = jsonencode(jsonencode(var.hub_network_ranges)) - } - transfer_network = { - value = jsonencode(var.hub_transfer_network) - } - min_prefix_length = { - value = jsonencode(var.hub_min_prefix_length) - } - max_prefix_length = { - value = jsonencode(var.hub_max_prefix_length) - } - default_prefix_length = { - value = jsonencode(var.hub_default_prefix_length) - } - default_nameservers = { - value = jsonencode(jsonencode(var.hub_default_nameservers)) - } - } - } -} - -# Looks up the default landing zone that `module.foundation` already registered (via the nested -# `modules/stackit` platform integration), without needing new outputs threaded through -# sandbox-landingzone. Used below only as an input into the independent `networked` landing zone — -# never fed back into `module.foundation` itself, which would create a dependency cycle. -data "meshstack_landingzone" "foundation_default" { - metadata = { name = "${var.platform_identifier}-default" } - depends_on = [module.foundation] -} - -resource "meshstack_landingzone" "networked" { - metadata = { - name = "${var.platform_identifier}-networked" - owned_by_workspace = var.workspace - tags = merge(var.tags.landingzone, { - (var.network_area_tag_name) = [jsondecode(meshstack_building_block.network_area_hub.status.outputs["network_area_id"].value)] - }) - } - - spec = { - display_name = "STACKIT Networked" - description = "STACKIT landing zone whose projects are placed in the hub network area." - automate_deletion_approval = true - automate_deletion_replication = true - - platform_ref = data.meshstack_landingzone.foundation_default.spec.platform_ref - platform_properties = { custom = {} } - mandatory_building_block_refs = data.meshstack_landingzone.foundation_default.spec.mandatory_building_block_refs - } -} diff --git a/reference-architectures/stackit-hub-spoke/buildingblock/outputs.tf b/reference-architectures/stackit-hub-spoke/buildingblock/outputs.tf deleted file mode 100644 index 84aac60d..00000000 --- a/reference-architectures/stackit-hub-spoke/buildingblock/outputs.tf +++ /dev/null @@ -1,26 +0,0 @@ -output "lz_folder_container_id" { - value = module.foundation.lz_folder_container_id - description = "Container ID of the STACKIT resourcemanager folder created for the landing zone. Tenant projects are created inside this folder." -} - -output "backplane_project_id" { - value = module.foundation.backplane_project_id - description = "Project ID of the STACKIT backplane project that hosts the service account used for tenant project creation." -} - -output "backplane_project_url" { - value = module.foundation.backplane_project_url - description = "Deep link to the backplane project in the STACKIT portal." -} - -output "summary" { - description = "Summary of the meshStack resources created by this reference architecture." - value = templatefile("${path.module}/SUMMARY.md.tftpl", { - platform_identifier = var.platform_identifier - backplane_project_id = module.foundation.backplane_project_id - backplane_project_url = module.foundation.backplane_project_url - lz_folder_container_id = module.foundation.lz_folder_container_id - networked_landingzone_name = meshstack_landingzone.networked.metadata.name - network_area_hub_uuid = meshstack_building_block.network_area_hub.metadata.uuid - }) -} diff --git a/reference-architectures/stackit-hub-spoke/buildingblock/variables.tf b/reference-architectures/stackit-hub-spoke/buildingblock/variables.tf deleted file mode 100644 index 28562f6e..00000000 --- a/reference-architectures/stackit-hub-spoke/buildingblock/variables.tf +++ /dev/null @@ -1,141 +0,0 @@ -variable "workspace" { - type = string - nullable = false - description = "Identifier of the meshStack workspace that will own the created platform, location, landing zones, and the hub network-area instance." -} - -variable "use_global_location" { - type = bool - nullable = false - description = "Use the global location instead of creating a dedicated location for this platform." -} - -variable "stackit_org" { - type = string - nullable = false - description = "STACKIT organization UUID under which the landing-zone folder, backplane project and tenant projects are created." - - validation { - condition = can(regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", var.stackit_org)) - error_message = "stackit_org must be a valid UUID." - } -} - -variable "stackit_owner_email" { - type = string - nullable = false - description = "Owner email assigned to the STACKIT resourcemanager folder and backplane project." -} - -variable "stackit_service_account_key" { - type = string - sensitive = true - nullable = false - description = "STACKIT service account key JSON with `resource-manager.admin` on the organization. Used to create the landing-zone folder and backplane project." -} - -variable "platform_identifier" { - type = string - nullable = false - description = "Identifier for the STACKIT sandbox platform created in meshStack (letters, digits and dashes only)." - - validation { - condition = can(regex("^[a-zA-Z0-9-]+$", var.platform_identifier)) - error_message = "platform_identifier must only contain letters, digits, and dashes." - } -} - -variable "tags" { - type = object({ - landingzone = map(list(string)) - building_block = map(list(string)) - }) - nullable = false - description = "Tags forwarded to the nested foundation, network-area, and network integrations. `landingzone` tags are applied to the created landing zones; `building_block` tags are applied to the nested building block definitions." -} - -variable "role_mapping" { - type = map(list(string)) - nullable = false - description = "Default mapping from meshStack roles to STACKIT project roles for the nested STACKIT Project integration. Values can be built-in STACKIT roles or custom STACKIT role names." -} - -variable "stackit_organization_onboarding_enabled" { - type = bool - nullable = false - description = "Whether the nested STACKIT Project integration adds meshStack project users to the STACKIT organization before applying project-level role assignments. Disable if organization membership is managed outside this landing zone." -} - -variable "network_area_tag_name" { - type = string - nullable = false - description = "Name of the meshStack landing zone tag whose value is the hub network area's ID. Forwarded to the foundation's nested STACKIT Project integration (so it knows which tag to read) and set on the `networked` landing zone created here (with the hub's network area ID as its value)." -} - -variable "hub_network_area_name" { - type = string - nullable = false - description = "Name of the hub STACKIT network area instance." -} - -variable "hub_network_ranges" { - type = list(string) - nullable = false - description = "List of IPv4 CIDR ranges available to projects within the hub network area." -} - -variable "hub_transfer_network" { - type = string - nullable = false - description = "IPv4 CIDR range used as the transfer network between the hub network area and connected networks. Must not overlap with `hub_network_ranges`." -} - -variable "hub_min_prefix_length" { - type = number - nullable = false - description = "Minimum prefix length allowed for networks created within the hub network area." -} - -variable "hub_max_prefix_length" { - type = number - nullable = false - description = "Maximum prefix length allowed for networks created within the hub network area." -} - -variable "hub_default_prefix_length" { - type = number - nullable = false - description = "Default prefix length used for networks created within the hub network area when none is specified." -} - -variable "hub_default_nameservers" { - type = list(string) - nullable = false - description = "Default IPv4 nameservers assigned to networks created within the hub network area." -} - -variable "tenant_network_min_prefix_length" { - type = number - nullable = false - description = "Minimum allowed IPv4 prefix length for the spoke network BBD's prefix length input, offered to application teams ordering spoke networks." -} - -variable "tenant_network_max_prefix_length" { - type = number - nullable = false - description = "Maximum allowed IPv4 prefix length for the spoke network BBD's prefix length input, offered to application teams ordering spoke networks." -} - -variable "hub" { - type = object({ - git_ref = optional(string, "main") - bbd_draft = optional(bool, true) - }) - const = true - default = { git_ref = "main", bbd_draft = true } - - description = <<-EOT - `git_ref`: meshstack-hub reference used to source the nested foundation, network-area, and network integration modules. `const` so it can be interpolated into the module source at init time. - `bbd_draft`: Forwarded as-is to those nested integrations' own `hub.bbd_draft`, so their building block definition draft state tracks this building block's own release state. - EOT -} diff --git a/reference-architectures/stackit-hub-spoke/meshstack_integration.tf b/reference-architectures/stackit-hub-spoke/meshstack_integration.tf deleted file mode 100644 index 86a36999..00000000 --- a/reference-architectures/stackit-hub-spoke/meshstack_integration.tf +++ /dev/null @@ -1,348 +0,0 @@ -variable "meshstack" { - type = object({ - owning_workspace_identifier = string - tags = optional(map(list(string)), {}) - }) - description = "Shared meshStack context. Tags are optional and propagated to building block definition metadata." -} - -variable "hub" { - type = object({ - git_ref = optional(string, "main") - bbd_draft = optional(bool, true) - }) - const = true - - default = { - git_ref = "main" - bbd_draft = true - } - - description = <<-EOT - `git_ref`: Hub release reference. Set to a tag (e.g. 'v1.2.3') or branch or commit sha of the meshstack-hub repo. - `bbd_draft`: If true, the building block definition version is kept in draft mode. - EOT -} - -output "building_block_definition" { - description = "BBD is consumed in building block compositions." - value = { - uuid = meshstack_building_block_definition.this.metadata.uuid - version_ref = var.hub.bbd_draft ? meshstack_building_block_definition.this.version_latest : meshstack_building_block_definition.this.version_latest_release - } -} - -resource "meshstack_building_block_definition" "this" { - metadata = { - owned_by_workspace = var.meshstack.owning_workspace_identifier - tags = var.meshstack.tags - } - - spec = { - display_name = "STACKIT Hub and Spoke Network" - symbol = "https://raw.githubusercontent.com/meshcloud/meshstack-hub/${var.hub.git_ref}/reference-architectures/stackit-hub-spoke/buildingblock/logo.png" - description = "Bootstraps a STACKIT sandbox platform together with a hub-and-spoke network topology: a shared network-area address plan and a self-service routed-network building block for application teams." - support_url = "https://portal.stackit.cloud" - target_type = "WORKSPACE_LEVEL" - run_transparency = true - - readme = chomp(<<-EOT - Bootstraps a STACKIT sandbox platform together with a hub-and-spoke network topology: it - provisions a shared network-area address plan (the hub) and registers a self-service - routed-network building block (the spoke) that application teams can order inside their - own STACKIT projects. - - ## 🎯 When to use it - - Use this building block when you: - - want a STACKIT platform where all tenant projects draw from a single, non-overlapping - IPv4 address plan instead of STACKIT's default flat networking. - - need application teams to self-service order routed subnets inside their projects - without manually coordinating CIDR ranges with the platform team. - - are bootstrapping a new STACKIT organization and want the network foundation (hub) - provisioned in the same step as the platform itself. - - ## 💡 Usage examples - - **Example 1: Bootstrap a new STACKIT sandbox with hub-and-spoke networking** - A platform engineer orders this building block once for a workspace. It creates the STACKIT - platform, provisions the hub network area with a chosen CIDR plan, and registers the - **STACKIT Network** building block so application teams can request spokes. - - **Example 2: Order a spoke network** - Once the platform is bootstrapped, an application team orders the **STACKIT Network** - building block inside their own STACKIT project to get a routed subnet drawn from the hub's - address plan — no manual IPAM coordination needed. - - ## 📊 Shared Responsibility - - | Responsibility | Platform Team | Application Team | - |---|:---:|:---:| - | Provision the STACKIT platform, hub network area, and its address plan | ✅ | ❌ | - | Choose non-overlapping CIDR ranges for the hub | ✅ | ❌ | - | Register the spoke `STACKIT Network` building block for self-service | ✅ | ❌ | - | Order spoke networks inside their STACKIT projects | ❌ | ✅ | - | Use the assigned subnet for their workloads | ❌ | ✅ | - EOT - ) - } - - version_spec = { - draft = var.hub.bbd_draft - deletion_mode = "DELETE" - - # Ephemeral API key permissions for meshStack resources created by this building block and its - # nested foundation/network-area/network integrations (all part of the same Terraform run). - permissions = [ - "INTEGRATION_LIST", - "BUILDINGBLOCKDEFINITION_LIST", - "BUILDINGBLOCKDEFINITION_SAVE", - "BUILDINGBLOCKDEFINITION_DELETE", - "BUILDINGBLOCK_LIST", - "BUILDINGBLOCK_SAVE", - "BUILDINGBLOCK_DELETE", - "LANDINGZONE_LIST", - "LANDINGZONE_SAVE", - "LANDINGZONE_DELETE", - "PLATFORMINSTANCE_LIST", - "PLATFORMINSTANCE_SAVE", - "PLATFORMINSTANCE_DELETE" - ] - - implementation = { - terraform = { - terraform_version = "1.12.0" - repository_url = "https://github.com/meshcloud/meshstack-hub.git" - repository_path = "reference-architectures/stackit-hub-spoke/buildingblock" - ref_name = var.hub.git_ref - async = false - use_mesh_http_backend_fallback = true - } - } - - inputs = { - # ── STACKIT authentication (service account key supplied by the operator) ── - - stackit_service_account_key = { - display_name = "STACKIT Service Account Key" - description = "STACKIT service account key JSON with `resource-manager.admin` on the organization. Paste the full JSON as a secret input." - type = "CODE" - assignment_type = "USER_INPUT" - updateable_by_consumer = true - sensitive = {} - } - - hub = { - display_name = "Hub" - description = "JSON object with `git_ref` (meshstack-hub reference used to source the nested foundation, network-area, and network integration modules) and `bbd_draft` (forwarded to those nested integrations' own building block definition draft state)." - type = "CODE" - assignment_type = "STATIC" - argument = jsonencode(jsonencode(var.hub)) - } - - # ── Platform configuration (set by the platform team) ── - - stackit_org = { - display_name = "STACKIT Organization UUID" - description = "STACKIT organization UUID under which the landing-zone folder, backplane project and tenant projects are created." - type = "STRING" - assignment_type = "USER_INPUT" - value_validation_regex = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" - validation_regex_error_message = "STACKIT Organization UUID must be a valid UUID." - } - - stackit_owner_email = { - display_name = "STACKIT Owner Email" - description = "Owner email assigned to the STACKIT resourcemanager folder and backplane project." - type = "STRING" - assignment_type = "USER_INPUT" - } - - tags = { - display_name = "Tags" - description = "JSON object with `landingzone` and `building_block` tag maps forwarded to the nested foundation, network-area, and network integrations." - type = "CODE" - assignment_type = "USER_INPUT" - updateable_by_consumer = true - - default_value = jsonencode(jsonencode({ - landingzone = {} - building_block = {} - })) - } - - role_mapping = { - display_name = "STACKIT Project Role Mapping" - description = "JSON object mapping meshStack roles from project users to STACKIT project roles. Values can be built-in STACKIT roles or custom STACKIT role names." - type = "CODE" - assignment_type = "USER_INPUT" - updateable_by_consumer = true - - default_value = jsonencode(jsonencode({ - admin = ["owner"] - user = ["editor"] - reader = ["reader"] - })) - } - - stackit_organization_onboarding_enabled = { - display_name = "STACKIT Organization Onboarding Enabled" - description = "If true, the nested STACKIT Project integration adds meshStack project users to the STACKIT organization before applying project-level role assignments." - type = "BOOLEAN" - assignment_type = "USER_INPUT" - updateable_by_consumer = true - default_value = jsonencode(true) - } - - network_area_tag_name = { - display_name = "Network Area Tag Name" - description = "Name of the meshStack landing zone tag whose value is the hub network area's ID. Forwarded to the foundation's nested STACKIT Project integration and set on the `networked` landing zone created by this building block." - type = "STRING" - assignment_type = "USER_INPUT" - updateable_by_consumer = true - default_value = jsonencode("StackitNetworkArea") - } - - # ── Hub network area configuration ── - - hub_network_area_name = { - display_name = "Hub Network Area Name" - description = "Name of the hub STACKIT network area instance." - type = "STRING" - assignment_type = "USER_INPUT" - default_value = jsonencode("hub") - } - - hub_network_ranges = { - display_name = "Hub Network Ranges" - description = "JSON list of IPv4 CIDR ranges available to projects within the hub network area, e.g. [\"10.0.0.0/16\"]." - type = "CODE" - assignment_type = "USER_INPUT" - default_value = jsonencode(jsonencode(["10.0.0.0/16"])) - } - - hub_transfer_network = { - display_name = "Hub Transfer Network" - description = "IPv4 CIDR range used as the transfer network between the hub network area and connected networks. Must not overlap with the Hub Network Ranges." - type = "STRING" - assignment_type = "USER_INPUT" - default_value = jsonencode("10.1.255.0/24") - value_validation_regex = "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$" - validation_regex_error_message = "Transfer network must be a valid IPv4 CIDR range, e.g. '10.1.255.0/24'." - } - - hub_min_prefix_length = { - display_name = "Hub Minimum Prefix Length" - description = "Minimum prefix length allowed for networks created within the hub network area." - type = "INTEGER" - assignment_type = "USER_INPUT" - default_value = jsonencode(24) - } - - hub_max_prefix_length = { - display_name = "Hub Maximum Prefix Length" - description = "Maximum prefix length allowed for networks created within the hub network area." - type = "INTEGER" - assignment_type = "USER_INPUT" - default_value = jsonencode(28) - } - - hub_default_prefix_length = { - display_name = "Hub Default Prefix Length" - description = "Default prefix length used for networks created within the hub network area when none is specified." - type = "INTEGER" - assignment_type = "USER_INPUT" - default_value = jsonencode(28) - } - - hub_default_nameservers = { - display_name = "Hub Default Nameservers" - description = "JSON list of default IPv4 nameservers assigned to networks created within the hub network area." - type = "CODE" - assignment_type = "USER_INPUT" - default_value = jsonencode(jsonencode([])) - } - - # ── Spoke network configuration (bounds offered to application teams) ── - - tenant_network_min_prefix_length = { - display_name = "Tenant Network Minimum Prefix Length" - description = "Minimum allowed IPv4 prefix length for the spoke network BBD's prefix length input, offered to application teams ordering spoke networks." - type = "INTEGER" - assignment_type = "USER_INPUT" - default_value = jsonencode(24) - } - - tenant_network_max_prefix_length = { - display_name = "Tenant Network Maximum Prefix Length" - description = "Maximum allowed IPv4 prefix length for the spoke network BBD's prefix length input, offered to application teams ordering spoke networks." - type = "INTEGER" - assignment_type = "USER_INPUT" - default_value = jsonencode(28) - } - - # ── meshStack context ── - - workspace = { - display_name = "Workspace Identifier" - description = "Workspace that will own the created platform, location, landing zones, and the hub network-area instance." - type = "STRING" - assignment_type = "WORKSPACE_IDENTIFIER" - } - - platform_identifier = { - display_name = "Platform Identifier" - description = "Identifier for the STACKIT sandbox platform created in meshStack (letters, digits and dashes only)." - type = "STRING" - assignment_type = "USER_INPUT" - value_validation_regex = "^[a-zA-Z0-9-]+$" - validation_regex_error_message = "platform_identifier must only contain letters, digits, and dashes." - } - - use_global_location = { - display_name = "Use Global Location" - description = "If true, use the existing global meshStack location instead of creating a dedicated location for this platform." - type = "BOOLEAN" - assignment_type = "USER_INPUT" - default_value = jsonencode(false) - } - } - - outputs = { - lz_folder_container_id = { - display_name = "LZ Folder Container ID" - type = "STRING" - assignment_type = "NONE" - } - - backplane_project_id = { - display_name = "Backplane Project ID" - type = "STRING" - assignment_type = "NONE" - } - - backplane_project_url = { - display_name = "Open Backplane Project" - type = "STRING" - assignment_type = "RESOURCE_URL" - } - - summary = { - display_name = "Summary" - type = "STRING" - assignment_type = "SUMMARY" - } - } - } -} - -terraform { - required_version = ">= 1.12.0" - - required_providers { - meshstack = { - source = "meshcloud/meshstack" - version = ">= 0.24.0" - } - } -} diff --git a/reference-architectures/stackit-landingzone/README.md b/reference-architectures/stackit-landingzone/README.md new file mode 100644 index 00000000..47156ce9 --- /dev/null +++ b/reference-architectures/stackit-landingzone/README.md @@ -0,0 +1,156 @@ +--- +name: STACKIT Landing Zone +description: > + Bootstraps a self-service-ready STACKIT platform: a dedicated STACKIT resourcemanager folder, + a foundation project with a service account, and the STACKIT Project platform with a default + landing zone. Optionally layers on a hub-and-spoke network topology — a shared network-area + address plan (hub) and a self-service routed-network building block (spoke) — when a network + configuration is provided. +cloudProviders: + - stackit +buildingBlocks: + - path: stackit/project + role: Provisions a STACKIT Project with role assignments. + - path: stackit/network-area + role: (Optional) Provisions the hub network area with the shared IPv4 address plan. + - path: stackit/network + role: (Optional) Lets application teams self-service order routed spoke networks inside their projects. +--- + +# STACKIT Landing Zone + +## Overview + +The **STACKIT Landing Zone** reference architecture turns a bare STACKIT organization into a +self-service-ready meshStack platform in one step using its own Terraform code. + +The **always-on** foundation is a sandbox landing zone: a dedicated STACKIT resourcemanager +folder, a foundation project hosting the project-creation service account, and the **STACKIT +Project** platform with its default landing zone. Application teams can immediately request +STACKIT projects against it. + +Optionally, by providing a **network** configuration, the same building block layers on a +hub-and-spoke network topology with IPAM built in: a shared network-area address plan (the hub) +that all tenant projects draw from, and a self-service routed-network building block (the spoke) +application teams can order inside their own projects. Leaving the network configuration unset +deploys only the sandbox foundation. + +**Target audience:** + +- **Platform engineers** onboarding a new STACKIT organization into meshStack who want a sandbox + environment application teams can request projects from immediately — optionally with network + segmentation from day one, without hand-wiring a network area and its address plan separately. +- **Application teams** who need a dedicated IPv4 subnet inside their STACKIT project without + manually coordinating CIDR ranges with the platform team (when networking is enabled). + +## Architecture Diagram + +The diagram separates the **platform artifacts** provisioned once by the platform team — the +STACKIT cloud objects (folder, foundation project), the meshStack platform, landing zones, and the +building block **definitions** (BBDs) registered in meshStack — from the **application landing zone +objects** that application teams instantiate `N` times in self-service. Building block definitions +(blue) are registered once; building block **instances** (green) are ordered against them — the hub +network area is a single instance the platform team orders, while STACKIT projects and spoke +networks are ordered `N` times by application teams. + +```mermaid +flowchart TB + subgraph platform["🏗️ Platform Team — provisioned once by this reference architecture"] + direction TB + FOLDER["📁 Resourcemanager Folder
STACKIT"] + FOUND["🔑 Foundation Project
STACKIT · project-creation service account"] + PLAT["🛰️ STACKIT Project Platform
meshStack"] + PRJBBD["📦 STACKIT Project BBD
meshStack definition"] + DEFLZ["🛬 Default Landing Zone
meshStack"] + + PLAT --> PRJBBD + PLAT --> DEFLZ + FOUND -. hosts SA, creates projects in .-> FOLDER + + subgraph net["Optional — enabled by the network configuration"] + direction TB + NABBD["📦 Network Area BBD
meshStack definition"] + SPOKEBBD["📦 STACKIT Network BBD
meshStack definition · spoke"] + HUBNA["🌐 Hub Network Area
1 building block instance"] + NETLZ["🛬 Networked Landing Zone
meshStack"] + + NABBD -->|platform team orders 1| HUBNA + NETLZ -. tagged with area id .-> HUBNA + end + PLAT --> NETLZ + end + + subgraph apps["👥 Application Teams — self-service · N instances"] + direction TB + PRJ["🗂️ STACKIT Project ×N
building block instance"] + SPOKE["🔌 Spoke Network ×N
building block instance"] + PRJ -->|orders stackit/network| SPOKE + end + + DEFLZ ==>|request project| PRJ + NETLZ ==>|request networked project| PRJ + PRJBBD -. defines .-> PRJ + SPOKEBBD -. defines .-> SPOKE + SPOKE -. draws CIDR from .-> HUBNA + + classDef bbd fill:#e8ecff,stroke:#5566dd,stroke-width:1px,color:#111; + classDef inst fill:#e6f6e6,stroke:#4a9a4a,stroke-width:1px,color:#111; + class PRJBBD,NABBD,SPOKEBBD bbd; + class HUBNA,PRJ,SPOKE inst; +``` + +When networking is enabled, application teams order a routed network into their own project via the +self-service `stackit/network` building block; each order draws its subnet from the hub's address +plan, so no two spokes can accidentally collide on CIDR ranges. + +## How It Works + +Running this reference architecture always: + +1. Creates a **STACKIT resourcemanager folder** under the given organization — new STACKIT + projects are created inside this folder. +2. Creates a **STACKIT foundation project** directly under the organization to host the + project-creation service account and other landing-zone core assets. +3. Sources the [`modules/stackit`](../../modules/stackit) platform integration to register the + **STACKIT Project** platform and its default landing zone in meshStack, wired to the foundation + service account. + +When a **network** configuration is provided, it additionally: + +4. Registers the [`stackit/network-area`](../../modules/stackit/network-area) building block + definition and immediately orders **one instance** of it in the platform team's own workspace — + this is the hub's IPv4 address plan. +5. Registers the [`stackit/network`](../../modules/stackit/network) building block definition + (`TENANT_LEVEL`) so application teams can self-service order routed networks (spokes) inside + their STACKIT projects, drawing from the hub's address plan. +6. Provisions an additional **networked landing zone**, tagged with the hub's network area ID, so + new STACKIT projects created against it are placed in the hub's network area. + +## Getting Started + +### Prerequisites + +| Requirement | Description | +|----------------------|-----------------------------------------------------------------------------------| +| STACKIT organization | With a service account key that has `resource-manager.admin` on the organization. | +| CIDR plan | *(Only when enabling networking)* A non-overlapping IPv4 address plan chosen up front for the hub network ranges and transfer network. | + +### Deployment Order + +Order the **STACKIT Landing Zone** building block once per workspace. Without a network +configuration it creates the platform and default landing zone. With a network configuration it +additionally creates the hub network area instance, the networked landing zone, and registers the +spoke `stackit/network` building block in the same apply. Application teams can then request +projects and — when networking is enabled — order `stackit/network` inside their own STACKIT +projects once those projects exist. + +## Shared Responsibilities + +| Responsibility | Platform Team | Application Team | +|-------------------------------------------------------------------------------|:---:|:---:| +| Provision the STACKIT platform and default landing zone | ✅ | ❌ | +| *(Optional)* Provision the hub network area and choose its address plan | ✅ | ❌ | +| *(Optional)* Register the spoke `stackit/network` building block | ✅ | ❌ | +| Request STACKIT projects through the landing zone | ❌ | ✅ | +| *(Optional)* Order spoke networks inside their STACKIT projects | ❌ | ✅ | +| Use the assigned subnet and manage workloads inside their projects | ❌ | ✅ | diff --git a/reference-architectures/stackit-landingzone/buildingblock/README.md b/reference-architectures/stackit-landingzone/buildingblock/README.md new file mode 100644 index 00000000..e7fc4157 --- /dev/null +++ b/reference-architectures/stackit-landingzone/buildingblock/README.md @@ -0,0 +1,83 @@ +--- +name: STACKIT Landing Zone +supportedPlatforms: + - stackit +description: Onboards a STACKIT sandbox platform into meshStack (location, resourcemanager folder and STACKIT Project platform with its default landing zone), and optionally layers on a hub-and-spoke network topology. +--- + +This building block bootstraps a complete STACKIT sandbox platform integration inside a meshStack +workspace. It creates a meshStack location, a dedicated STACKIT resourcemanager folder and a +foundation project hosting the landing-zone core assets, then sources the +[`modules/stackit`](../../../modules/stackit) project integration to provision the STACKIT Project +platform together with its default landing zone. + +When a `network` object is supplied, it additionally composes two more Hub modules into the same +offering: it registers [`modules/stackit/network-area`](../../../modules/stackit/network-area) and +immediately orders one instance of it as the hub address plan, and registers +[`modules/stackit/network`](../../../modules/stackit/network) so application teams can self-service +order routed spoke networks inside their STACKIT projects. New STACKIT projects are then placed in +the hub's network area via an additional `networked` landing zone tagged with the hub's network +area ID. Leaving `network` unset (`null`) deploys only the sandbox landing zone. + +It authenticates to STACKIT with a service account key you paste as a secret input. You also +provide the STACKIT organization UUID, owner email, nested integration tags and default role mapping +as user inputs. The service account needs `resource-manager.admin` on the organization. The nested +integrations are pinned to the same `git_ref` as this building block's implementation. + +The user-facing readme is maintained inline in the `readme` field of the +`meshstack_building_block_definition` in +[`../meshstack_integration.tf`](../meshstack_integration.tf). + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.12.0 | +| [meshstack](#requirement\_meshstack) | >= 0.24.0 | +| [stackit](#requirement\_stackit) | >= 0.99.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [network\_area\_integration](#module\_network\_area\_integration) | github.com/meshcloud/meshstack-hub//modules/stackit/network-area | main | +| [network\_integration](#module\_network\_integration) | github.com/meshcloud/meshstack-hub//modules/stackit/network | main | +| [stackit\_integration](#module\_stackit\_integration) | github.com/meshcloud/meshstack-hub//modules/stackit | main | + +## Resources + +| Name | Type | +|------|------| +| [meshstack_building_block.network_area_hub](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block) | resource | +| [meshstack_landingzone.networked](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/landingzone) | resource | +| [meshstack_location.this](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/location) | resource | +| [stackit_resourcemanager_folder.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_folder) | resource | +| [stackit_resourcemanager_project.foundation](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_project) | resource | +| [meshstack_landingzone.foundation_default](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/data-sources/landingzone) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [hub](#input\_hub) | `git_ref`: meshstack-hub reference used to source the nested foundation, network-area, and network integration modules. `const` so it can be interpolated into the module source at init time.
`bbd_draft`: Forwarded as-is to those nested integrations' own `hub.bbd_draft`, so their building block definition draft state tracks this building block's own release state. |
object({
git_ref = optional(string, "main")
bbd_draft = optional(bool, true)
})
|
{
"bbd_draft": true,
"git_ref": "main"
}
| no | +| [network](#input\_network) | Optional hub-and-spoke network topology. Leave unset (null) to deploy only the sandbox landing zone. When set, additionally provisions a shared hub network area with the given address plan (`hub_*` fields), registers the self-service spoke `STACKIT Network` building block (`tenant_network_*` prefix bounds), and creates a `networked` landing zone (tagged via `network_area_tag_name`) whose projects are placed in the hub network area. |
object({
network_area_tag_name = optional(string, "StackitNetworkArea")
hub_network_area_name = optional(string, "hub")
hub_network_ranges = optional(list(string), ["10.0.0.0/16"])
hub_transfer_network = optional(string, "10.1.255.0/24")
hub_min_prefix_length = optional(number, 24)
hub_max_prefix_length = optional(number, 28)
hub_default_prefix_length = optional(number, 28)
hub_default_nameservers = optional(list(string), [])
tenant_network_min_prefix_length = optional(number, 24)
tenant_network_max_prefix_length = optional(number, 28)
})
| `null` | no | +| [platform\_identifier](#input\_platform\_identifier) | Identifier for the STACKIT sandbox platform created in meshStack (letters, digits and dashes only). | `string` | n/a | yes | +| [role\_mapping](#input\_role\_mapping) | Default mapping from meshStack roles to STACKIT project roles for the nested STACKIT Project integration. Values can be built-in STACKIT roles or custom STACKIT role names. | `map(list(string))` | n/a | yes | +| [stackit\_org](#input\_stackit\_org) | STACKIT organization UUID under which the landing-zone folder, foundation project and tenant projects are created. | `string` | n/a | yes | +| [stackit\_organization\_onboarding\_enabled](#input\_stackit\_organization\_onboarding\_enabled) | Whether the nested STACKIT Project integration adds meshStack project users to the STACKIT organization before applying project-level role assignments. Disable if organization membership is managed outside this landing zone. | `bool` | n/a | yes | +| [stackit\_owner\_email](#input\_stackit\_owner\_email) | Owner email assigned to the STACKIT resourcemanager folder and foundation project. | `string` | n/a | yes | +| [stackit\_service\_account\_key](#input\_stackit\_service\_account\_key) | STACKIT service account key JSON with `resource-manager.admin` on the organization. Used to create the landing-zone folder and foundation project. | `string` | n/a | yes | +| [tags](#input\_tags) | Tags forwarded to the nested STACKIT integrations. `landingzone` tags are applied to the created landing zones; `building_block` tags are applied to the nested building block definitions. |
object({
landingzone = map(list(string))
building_block = map(list(string))
})
| n/a | yes | +| [use\_global\_location](#input\_use\_global\_location) | Use the global location instead of creating a dedicated location for this platform. | `bool` | n/a | yes | +| [workspace](#input\_workspace) | Identifier of the meshStack workspace that will own the created platform, location, landing zones, and (when networking is enabled) the hub network-area instance. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [foundation\_project\_id](#output\_foundation\_project\_id) | Project ID of the STACKIT foundation project that hosts the landing-zone core assets (the service account used for tenant project creation). | +| [foundation\_project\_url](#output\_foundation\_project\_url) | Deep link to the foundation project in the STACKIT portal. | +| [lz\_folder\_container\_id](#output\_lz\_folder\_container\_id) | Container ID of the STACKIT resourcemanager folder created for the landing zone. Tenant projects are created inside this folder. | +| [summary](#output\_summary) | Summary of the meshStack resources created by this reference architecture. | + diff --git a/reference-architectures/stackit-landingzone/buildingblock/SUMMARY.md.tftpl b/reference-architectures/stackit-landingzone/buildingblock/SUMMARY.md.tftpl new file mode 100644 index 00000000..a8d028ef --- /dev/null +++ b/reference-architectures/stackit-landingzone/buildingblock/SUMMARY.md.tftpl @@ -0,0 +1,21 @@ +# STACKIT Landing Zone: **${platform_identifier}** + +## Details + +| Property | Value | +|----------|-------| +| **Foundation Project** | [Open in STACKIT Portal](${foundation_project_url}) (`${foundation_project_id}`) | +| **Landing Zone Folder** | `${lz_folder_container_id}` | +%{ if network_enabled ~} +| **Networked Landing Zone** | `${networked_landingzone_name}` | +| **Hub Network Area** | @buildingblock[${network_area_hub_uuid}] | +%{ endif ~} + +%{ if network_enabled ~} +Hub-and-spoke networking is enabled. Application teams can order the **STACKIT Network** building +block inside their own projects in the `${networked_landingzone_name}` landing zone to get a routed +spoke network drawn from the hub's address plan. +%{ else ~} +Application teams can now request STACKIT projects against the `${platform_identifier}-default` +landing zone. Provide a `network` object to additionally enable hub-and-spoke networking. +%{ endif ~} diff --git a/reference-architectures/stackit-hub-spoke/buildingblock/logo.png b/reference-architectures/stackit-landingzone/buildingblock/logo.png similarity index 100% rename from reference-architectures/stackit-hub-spoke/buildingblock/logo.png rename to reference-architectures/stackit-landingzone/buildingblock/logo.png diff --git a/reference-architectures/stackit-landingzone/buildingblock/main.tf b/reference-architectures/stackit-landingzone/buildingblock/main.tf new file mode 100644 index 00000000..734156e5 --- /dev/null +++ b/reference-architectures/stackit-landingzone/buildingblock/main.tf @@ -0,0 +1,151 @@ +locals { + # Hub-and-spoke networking is deployed only when the operator supplies a `network` object. + network_enabled = var.network != null +} + +# ── Sandbox landing zone foundation (always deployed) ── + +resource "meshstack_location" "this" { + count = var.use_global_location ? 0 : 1 + + metadata = { + name = var.platform_identifier + owned_by_workspace = var.workspace + } + + spec = { + display_name = var.platform_identifier + description = "STACKIT sandbox location created by the STACKIT Landing Zone." + } +} + +resource "stackit_resourcemanager_folder" "this" { + name = var.platform_identifier + owner_email = var.stackit_owner_email + parent_container_id = var.stackit_org +} + +# Foundation project hosting the landing-zone core assets (the project-creation service account). +# Created directly under the organization (not the landing-zone folder). +resource "stackit_resourcemanager_project" "foundation" { + name = "${var.platform_identifier}-foundation" + owner_email = var.stackit_owner_email + parent_container_id = var.stackit_org +} + +module "stackit_integration" { + source = "github.com/meshcloud/meshstack-hub//modules/stackit?ref=${var.hub.git_ref}" + + stackit_organization_id = var.stackit_org + stackit_parent_container_id = stackit_resourcemanager_folder.this.container_id + stackit_project_id = stackit_resourcemanager_project.foundation.project_id + stackit_service_account_name = substr(var.platform_identifier, 0, 20) + role_mapping = var.role_mapping + stackit_organization_onboarding_enabled = var.stackit_organization_onboarding_enabled + stackit_network_area_tag_name = local.network_enabled ? var.network.network_area_tag_name : null + + hub = var.hub + + meshstack = { + owning_workspace_identifier = var.workspace + location_name = var.use_global_location ? "global" : meshstack_location.this[0].metadata.name + platform_identifier = var.platform_identifier + tags = var.tags + } +} + +# ── Hub-and-spoke network topology (optional — deployed only when var.network is set) ── + +module "network_area_integration" { + count = local.network_enabled ? 1 : 0 + source = "github.com/meshcloud/meshstack-hub//modules/stackit/network-area?ref=${var.hub.git_ref}" + + stackit_organization_id = var.stackit_org + stackit_project_id = stackit_resourcemanager_project.foundation.project_id + + meshstack = { owning_workspace_identifier = var.workspace, tags = var.tags.building_block } + hub = var.hub +} + +module "network_integration" { + count = local.network_enabled ? 1 : 0 + source = "github.com/meshcloud/meshstack-hub//modules/stackit/network?ref=${var.hub.git_ref}" + + stackit_organization_id = var.stackit_org + stackit_project_id = stackit_resourcemanager_project.foundation.project_id + stackit_network_min_prefix_length = var.network.tenant_network_min_prefix_length + stackit_network_max_prefix_length = var.network.tenant_network_max_prefix_length + + meshstack = { owning_workspace_identifier = var.workspace, tags = var.tags.building_block } + hub = var.hub +} + +resource "meshstack_building_block" "network_area_hub" { + count = local.network_enabled ? 1 : 0 + wait_for_completion = true + depends_on = [module.network_area_integration] + + spec = { + building_block_definition_version_ref = { + uuid = module.network_area_integration[0].building_block_definition.version_ref.uuid + } + display_name = "Hub Network Area" + target_ref = { kind = "meshWorkspace", name = var.workspace } + + inputs = { + network_area_name = { + value = jsonencode(var.network.hub_network_area_name) + } + network_ranges = { + value = jsonencode(jsonencode(var.network.hub_network_ranges)) + } + transfer_network = { + value = jsonencode(var.network.hub_transfer_network) + } + min_prefix_length = { + value = jsonencode(var.network.hub_min_prefix_length) + } + max_prefix_length = { + value = jsonencode(var.network.hub_max_prefix_length) + } + default_prefix_length = { + value = jsonencode(var.network.hub_default_prefix_length) + } + default_nameservers = { + value = jsonencode(jsonencode(var.network.hub_default_nameservers)) + } + } + } +} + +# Looks up the default landing zone that `module.stackit_integration` already registered, without +# needing new outputs threaded through it. Used below only as an input into the independent +# `networked` landing zone — never fed back into the integration itself, which would create a cycle. +data "meshstack_landingzone" "foundation_default" { + count = local.network_enabled ? 1 : 0 + metadata = { name = "${var.platform_identifier}-default" } + depends_on = [module.stackit_integration] +} + +resource "meshstack_landingzone" "networked" { + count = local.network_enabled ? 1 : 0 + + metadata = { + name = "${var.platform_identifier}-networked" + owned_by_workspace = var.workspace + tags = merge(var.tags.landingzone, { + (var.network.network_area_tag_name) = [jsondecode(meshstack_building_block.network_area_hub[0].status.outputs["network_area_id"].value)] + }) + } + + spec = { + display_name = "STACKIT Networked" + description = "STACKIT landing zone whose projects are placed in the hub network area." + automate_deletion_approval = true + automate_deletion_replication = true + + platform_ref = data.meshstack_landingzone.foundation_default[0].spec.platform_ref + platform_properties = { custom = {} } + mandatory_building_block_refs = data.meshstack_landingzone.foundation_default[0].spec.mandatory_building_block_refs + } +} diff --git a/reference-architectures/stackit-landingzone/buildingblock/outputs.tf b/reference-architectures/stackit-landingzone/buildingblock/outputs.tf new file mode 100644 index 00000000..db9506a6 --- /dev/null +++ b/reference-architectures/stackit-landingzone/buildingblock/outputs.tf @@ -0,0 +1,27 @@ +output "lz_folder_container_id" { + value = stackit_resourcemanager_folder.this.container_id + description = "Container ID of the STACKIT resourcemanager folder created for the landing zone. Tenant projects are created inside this folder." +} + +output "foundation_project_id" { + value = stackit_resourcemanager_project.foundation.project_id + description = "Project ID of the STACKIT foundation project that hosts the landing-zone core assets (the service account used for tenant project creation)." +} + +output "foundation_project_url" { + value = "https://portal.stackit.cloud/projects/${stackit_resourcemanager_project.foundation.project_id}" + description = "Deep link to the foundation project in the STACKIT portal." +} + +output "summary" { + description = "Summary of the meshStack resources created by this reference architecture." + value = templatefile("${path.module}/SUMMARY.md.tftpl", { + platform_identifier = var.platform_identifier + foundation_project_id = stackit_resourcemanager_project.foundation.project_id + foundation_project_url = "https://portal.stackit.cloud/projects/${stackit_resourcemanager_project.foundation.project_id}" + lz_folder_container_id = stackit_resourcemanager_folder.this.container_id + network_enabled = local.network_enabled + networked_landingzone_name = local.network_enabled ? meshstack_landingzone.networked[0].metadata.name : "" + network_area_hub_uuid = local.network_enabled ? meshstack_building_block.network_area_hub[0].metadata.uuid : "" + }) +} diff --git a/reference-architectures/stackit-hub-spoke/buildingblock/provider.tf b/reference-architectures/stackit-landingzone/buildingblock/provider.tf similarity index 100% rename from reference-architectures/stackit-hub-spoke/buildingblock/provider.tf rename to reference-architectures/stackit-landingzone/buildingblock/provider.tf diff --git a/reference-architectures/stackit-sandbox-landingzone/buildingblock/variables.tf b/reference-architectures/stackit-landingzone/buildingblock/variables.tf similarity index 52% rename from reference-architectures/stackit-sandbox-landingzone/buildingblock/variables.tf rename to reference-architectures/stackit-landingzone/buildingblock/variables.tf index 4269bcf2..35074ec9 100644 --- a/reference-architectures/stackit-sandbox-landingzone/buildingblock/variables.tf +++ b/reference-architectures/stackit-landingzone/buildingblock/variables.tf @@ -1,6 +1,7 @@ variable "workspace" { type = string - description = "Identifier of the meshStack workspace that will own the created location, platform and landing zone." + nullable = false + description = "Identifier of the meshStack workspace that will own the created platform, location, landing zones, and (when networking is enabled) the hub network-area instance." } variable "use_global_location" { @@ -11,8 +12,8 @@ variable "use_global_location" { variable "stackit_org" { type = string - description = "STACKIT organization UUID under which the landing-zone folder, backplane project and tenant projects are created." nullable = false + description = "STACKIT organization UUID under which the landing-zone folder, foundation project and tenant projects are created." validation { condition = can(regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", var.stackit_org)) @@ -22,15 +23,15 @@ variable "stackit_org" { variable "stackit_owner_email" { type = string - description = "Owner email assigned to the STACKIT resourcemanager folder and backplane project." nullable = false + description = "Owner email assigned to the STACKIT resourcemanager folder and foundation project." } variable "stackit_service_account_key" { type = string sensitive = true nullable = false - description = "STACKIT service account key JSON with `resource-manager.admin` on the organization. Used to create the landing-zone folder and backplane project." + description = "STACKIT service account key JSON with `resource-manager.admin` on the organization. Used to create the landing-zone folder and foundation project." } variable "platform_identifier" { @@ -50,7 +51,7 @@ variable "tags" { building_block = map(list(string)) }) nullable = false - description = "Tags forwarded to the nested STACKIT Project integration. `landingzone` tags are applied to the default landing zone; `building_block` tags are applied to the nested building block definition." + description = "Tags forwarded to the nested STACKIT integrations. `landingzone` tags are applied to the created landing zones; `building_block` tags are applied to the nested building block definitions." } variable "role_mapping" { @@ -65,10 +66,21 @@ variable "stackit_organization_onboarding_enabled" { description = "Whether the nested STACKIT Project integration adds meshStack project users to the STACKIT organization before applying project-level role assignments. Disable if organization membership is managed outside this landing zone." } -variable "network_area_tag_name" { - type = string +variable "network" { + type = object({ + network_area_tag_name = optional(string, "StackitNetworkArea") + hub_network_area_name = optional(string, "hub") + hub_network_ranges = optional(list(string), ["10.0.0.0/16"]) + hub_transfer_network = optional(string, "10.1.255.0/24") + hub_min_prefix_length = optional(number, 24) + hub_max_prefix_length = optional(number, 28) + hub_default_prefix_length = optional(number, 28) + hub_default_nameservers = optional(list(string), []) + tenant_network_min_prefix_length = optional(number, 24) + tenant_network_max_prefix_length = optional(number, 28) + }) default = null - description = "Name of the meshStack landing zone tag whose value is used as the STACKIT project's `networkArea` label, forwarded to the nested STACKIT Project integration. Set to null (default) to skip network area assignment." + description = "Optional hub-and-spoke network topology. Leave unset (null) to deploy only the sandbox landing zone. When set, additionally provisions a shared hub network area with the given address plan (`hub_*` fields), registers the self-service spoke `STACKIT Network` building block (`tenant_network_*` prefix bounds), and creates a `networked` landing zone (tagged via `network_area_tag_name`) whose projects are placed in the hub network area." } variable "hub" { @@ -76,12 +88,11 @@ variable "hub" { git_ref = optional(string, "main") bbd_draft = optional(bool, true) }) - const = true - nullable = false + const = true + default = { git_ref = "main", bbd_draft = true } description = <<-EOT - `git_ref`: meshstack-hub reference used to source the nested STACKIT project integration module. `const` so it can be interpolated into the module source at init time. - `bbd_draft`: Forwarded as-is to the nested STACKIT project integration's own `hub.bbd_draft`, so its building block definition draft state tracks this building block's own release state. + `git_ref`: meshstack-hub reference used to source the nested foundation, network-area, and network integration modules. `const` so it can be interpolated into the module source at init time. + `bbd_draft`: Forwarded as-is to those nested integrations' own `hub.bbd_draft`, so their building block definition draft state tracks this building block's own release state. EOT } - diff --git a/reference-architectures/stackit-hub-spoke/buildingblock/versions.tf b/reference-architectures/stackit-landingzone/buildingblock/versions.tf similarity index 100% rename from reference-architectures/stackit-hub-spoke/buildingblock/versions.tf rename to reference-architectures/stackit-landingzone/buildingblock/versions.tf diff --git a/reference-architectures/stackit-hub-spoke/logo.png b/reference-architectures/stackit-landingzone/logo.png similarity index 100% rename from reference-architectures/stackit-hub-spoke/logo.png rename to reference-architectures/stackit-landingzone/logo.png diff --git a/reference-architectures/stackit-sandbox-landingzone/meshstack_integration.tf b/reference-architectures/stackit-landingzone/meshstack_integration.tf similarity index 64% rename from reference-architectures/stackit-sandbox-landingzone/meshstack_integration.tf rename to reference-architectures/stackit-landingzone/meshstack_integration.tf index 66241f63..cd74d42a 100644 --- a/reference-architectures/stackit-sandbox-landingzone/meshstack_integration.tf +++ b/reference-architectures/stackit-landingzone/meshstack_integration.tf @@ -24,12 +24,6 @@ variable "hub" { EOT } -variable "stackit_organization_onboarding_enabled" { - type = bool - default = true - description = "Whether the project building block adds meshStack project users to the STACKIT organization. Disable if organization membership is managed externally." -} - output "building_block_definition" { description = "BBD is consumed in building block compositions." value = { @@ -45,24 +39,33 @@ resource "meshstack_building_block_definition" "this" { } spec = { - display_name = "STACKIT Sandbox Landing Zone" - symbol = "https://raw.githubusercontent.com/meshcloud/meshstack-hub/${var.hub.git_ref}/reference-architectures/stackit-sandbox-landingzone/buildingblock/logo.png" - description = "Onboards a STACKIT sandbox platform into meshStack: creates a location, a STACKIT resourcemanager folder and the STACKIT Project platform with its default landing zone." + display_name = "STACKIT Landing Zone" + symbol = "https://raw.githubusercontent.com/meshcloud/meshstack-hub/${var.hub.git_ref}/reference-architectures/stackit-landingzone/buildingblock/logo.png" + description = "Onboards a STACKIT sandbox platform into meshStack: a location, resourcemanager folder and the STACKIT Project platform with its default landing zone. Optionally layers on a hub-and-spoke network topology when a network config is provided." support_url = "https://portal.stackit.cloud" target_type = "WORKSPACE_LEVEL" run_transparency = true readme = chomp(<<-EOT - The **STACKIT Sandbox Landing Zone** building block bootstraps a complete STACKIT sandbox platform integration inside a - meshStack workspace. Running it once turns a STACKIT organization into a sandbox-ready self-service platform: it - registers a meshStack location, carves out a dedicated STACKIT resourcemanager folder for the workspace and - wires up the **STACKIT Project** platform together with its default landing zone. + The **STACKIT Landing Zone** building block bootstraps a complete STACKIT sandbox platform + integration inside a meshStack workspace. Running it once turns a STACKIT organization into a + sandbox-ready self-service platform: it registers a meshStack location, carves out a dedicated + STACKIT resourcemanager folder for the workspace and wires up the **STACKIT Project** platform + together with its default landing zone. + + Optionally, when you provide a **network** configuration, it additionally layers on a + hub-and-spoke network topology: a shared network-area address plan (the hub) and a self-service + routed-network building block (the spoke) that application teams can order inside their own + STACKIT projects. ## 🎯 When to use it Use this building block when you: - want to onboard STACKIT in meshStack without manually creating locations, folders and project platform wiring. - need a reusable setup for sandbox environments where application teams can request STACKIT projects self-service. + - (optionally) want all tenant projects to draw from a single, non-overlapping IPv4 address plan + and let application teams self-service order routed subnets — enable this by providing the + **network** configuration. ## 💡 Usage examples @@ -70,18 +73,24 @@ resource "meshstack_building_block_definition" "this" { A platform engineer runs this building block once for a workspace to bootstrap the STACKIT location, landing-zone folder and default `STACKIT Project` platform so teams can start requesting projects immediately. - **Example 2: Prepare an isolated training environment** - For workshops or onboarding waves, the platform team creates a dedicated platform identifier and folder boundary so - participant projects are provisioned in a controlled area with clear ownership. + **Example 2: Bootstrap with hub-and-spoke networking** + A platform engineer provides a **network** configuration (CIDR plan, prefix bounds). In addition + to the sandbox platform, the building block provisions the hub network area with the chosen + address plan, registers the **STACKIT Network** building block, and creates a `networked` landing + zone. Application teams can then self-service order routed spoke networks inside their projects. ## 📦 Resources created - **meshStack location** – named after the chosen platform identifier. - **STACKIT resourcemanager folder** – created under the configured organization and owned by the given owner email. New tenant projects are created inside this folder. - - **STACKIT backplane project** – created directly under the organization to host the project-creation service account. + - **STACKIT foundation project** – created directly under the organization to host the + project-creation service account and other landing-zone core assets. - **STACKIT Project platform** – the `STACKIT Project` building block definition, platform and default landing zone, - including the project-creation service account provisioned in the backplane project. + including the project-creation service account provisioned in the foundation project. + - **Hub network area + spoke network building block + networked landing zone** *(only when a + network configuration is provided)* – the shared hub address plan, the self-service + `STACKIT Network` building block, and a landing zone that places projects into the hub. ## 🔑 Authentication @@ -94,7 +103,10 @@ resource "meshstack_building_block_definition" "this" { |---|:---:|:---:| | Provide the STACKIT service account key, organization details, tags and role mapping | ✅ | ❌ | | Provision the location, folder and STACKIT Project platform | ✅ | ❌ | + | (Optional) Provide the network CIDR plan and provision the hub network area | ✅ | ❌ | + | (Optional) Register the spoke `STACKIT Network` building block for self-service | ✅ | ❌ | | Request STACKIT projects through the landing zone | ❌ | ✅ | + | (Optional) Order spoke networks inside their STACKIT projects | ❌ | ✅ | | Manage workloads inside the provisioned STACKIT projects | ❌ | ✅ | EOT ) @@ -104,12 +116,16 @@ resource "meshstack_building_block_definition" "this" { draft = var.hub.bbd_draft deletion_mode = "DELETE" - # Ephemeral API key permissions for meshStack resources created by this building block and STACKIT integration. + # Ephemeral API key permissions for meshStack resources created by this building block and its + # nested foundation/network-area/network integrations (all part of the same Terraform run). permissions = [ "INTEGRATION_LIST", "BUILDINGBLOCKDEFINITION_LIST", "BUILDINGBLOCKDEFINITION_SAVE", "BUILDINGBLOCKDEFINITION_DELETE", + "BUILDINGBLOCK_LIST", + "BUILDINGBLOCK_SAVE", + "BUILDINGBLOCK_DELETE", "LANDINGZONE_LIST", "LANDINGZONE_SAVE", "LANDINGZONE_DELETE", @@ -122,7 +138,7 @@ resource "meshstack_building_block_definition" "this" { terraform = { terraform_version = "1.12.0" repository_url = "https://github.com/meshcloud/meshstack-hub.git" - repository_path = "reference-architectures/stackit-sandbox-landingzone/buildingblock" + repository_path = "reference-architectures/stackit-landingzone/buildingblock" ref_name = var.hub.git_ref async = false use_mesh_http_backend_fallback = true @@ -132,7 +148,7 @@ resource "meshstack_building_block_definition" "this" { inputs = { # ── STACKIT authentication (service account key supplied by the operator) ── - "stackit_service_account_key" = { + stackit_service_account_key = { display_name = "STACKIT Service Account Key" description = "STACKIT service account key JSON with `resource-manager.admin` on the organization. Paste the full JSON as a secret input." type = "CODE" @@ -143,7 +159,7 @@ resource "meshstack_building_block_definition" "this" { hub = { display_name = "Hub" - description = "JSON object with `git_ref` (meshstack-hub reference used to source the nested STACKIT project integration module) and `bbd_draft` (forwarded to the nested integration's own building block definition draft state)." + description = "JSON object with `git_ref` (meshstack-hub reference used to source the nested STACKIT integration modules) and `bbd_draft` (forwarded to those nested integrations' own building block definition draft state)." type = "CODE" assignment_type = "STATIC" argument = jsonencode(jsonencode(var.hub)) @@ -153,7 +169,7 @@ resource "meshstack_building_block_definition" "this" { stackit_org = { display_name = "STACKIT Organization UUID" - description = "STACKIT organization UUID under which the landing-zone folder, backplane project and tenant projects are created." + description = "STACKIT organization UUID under which the landing-zone folder, foundation project and tenant projects are created." type = "STRING" assignment_type = "USER_INPUT" value_validation_regex = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" @@ -162,14 +178,14 @@ resource "meshstack_building_block_definition" "this" { stackit_owner_email = { display_name = "STACKIT Owner Email" - description = "Owner email assigned to the STACKIT resourcemanager folder and backplane project." + description = "Owner email assigned to the STACKIT resourcemanager folder and foundation project." type = "STRING" assignment_type = "USER_INPUT" } tags = { display_name = "Tags" - description = "JSON object with `landingzone` and `building_block` tag maps forwarded to the STACKIT Project integration module." + description = "JSON object with `landingzone` and `building_block` tag maps forwarded to the nested STACKIT integrations." type = "CODE" assignment_type = "USER_INPUT" updateable_by_consumer = true @@ -200,15 +216,46 @@ resource "meshstack_building_block_definition" "this" { type = "BOOLEAN" assignment_type = "USER_INPUT" updateable_by_consumer = true + default_value = jsonencode(true) + } - default_value = jsonencode(var.stackit_organization_onboarding_enabled) + # ── Optional hub-and-spoke networking ── + # Leave `network` as null to deploy only the sandbox landing zone. Provide a JSON object to + # additionally provision the hub network area, register the spoke network building block, and + # create a networked landing zone. + + network = { + display_name = "Network (Hub-and-Spoke)" + description = <<-DESC + Optional JSON object enabling hub-and-spoke networking. Leave as `null` to deploy only the + sandbox landing zone. When set, all fields are optional (sensible defaults shown): + + ```json + { + "network_area_tag_name": "StackitNetworkArea", + "hub_network_area_name": "hub", + "hub_network_ranges": ["10.0.0.0/16"], + "hub_transfer_network": "10.1.255.0/24", + "hub_min_prefix_length": 24, + "hub_max_prefix_length": 28, + "hub_default_prefix_length": 28, + "hub_default_nameservers": [], + "tenant_network_min_prefix_length": 24, + "tenant_network_max_prefix_length": 28 + } + ``` + DESC + type = "CODE" + assignment_type = "USER_INPUT" + updateable_by_consumer = true + default_value = jsonencode(jsonencode(null)) } # ── meshStack context ── workspace = { display_name = "Workspace Identifier" - description = "Workspace that will own the created platform, location and landing zone." + description = "Workspace that will own the created platform, location and landing zones." type = "STRING" assignment_type = "WORKSPACE_IDENTIFIER" } @@ -238,17 +285,23 @@ resource "meshstack_building_block_definition" "this" { assignment_type = "NONE" } - backplane_project_id = { - display_name = "Backplane Project ID" + foundation_project_id = { + display_name = "Foundation Project ID" type = "STRING" assignment_type = "NONE" } - backplane_project_url = { - display_name = "Open Backplane Project" + foundation_project_url = { + display_name = "Open Foundation Project" type = "STRING" assignment_type = "RESOURCE_URL" } + + summary = { + display_name = "Summary" + type = "STRING" + assignment_type = "SUMMARY" + } } } } @@ -259,7 +312,7 @@ terraform { required_providers { meshstack = { source = "meshcloud/meshstack" - version = ">= 0.22.0" + version = ">= 0.24.0" } } } diff --git a/reference-architectures/stackit-sandbox-landingzone/README.md b/reference-architectures/stackit-sandbox-landingzone/README.md deleted file mode 100644 index 32cd9c1d..00000000 --- a/reference-architectures/stackit-sandbox-landingzone/README.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -name: STACKIT Sandbox Landing Zone -description: > - Bootstraps a self-service-ready STACKIT platform: a dedicated STACKIT resourcemanager folder, a service account, and the STACKIT Project platform with a default landing zone. -cloudProviders: - - stackit -buildingBlocks: - - path: stackit/project - role: Provisions a STACKIT Project with role assignments. ---- - -# STACKIT Sandbox Landing Zone - -## Overview - -The **STACKIT Sandbox Landing Zone** reference architecture turns a bare STACKIT organization -into a self-service-ready meshStack platform in one step using its own Terraform code. - -**Target audience:** - -- **Platform engineers** onboarding a new STACKIT organization into meshStack who want a - sandbox environment application teams can request projects from immediately. - -## Architecture Diagram - -```mermaid -flowchart TD - A[STACKIT Organization] -->|folder| B[Landing-Zone Folder] - A -->|backplane project| C[Backplane Project] - C -->|hosts| D[Project-Creation Service Account] - F[STACKIT Project Platform] --> G[Default Landing Zone] - G -->|scoped to| B - D -->|creates tenant projects in| B -``` - -## How It Works - -Running this reference architecture: - -1. Creates a **STACKIT resourcemanager folder** under the given organization — new STACKIT - projects are created inside this folder. -2. Creates a **STACKIT backplane project** directly under the organization to host the - project-creation service account. -3. Sources the [`modules/stackit`](../../modules/stackit) platform integration to register the - **STACKIT Project** platform and its default landing zone in meshStack, wired to the - backplane service account. - -## Getting Started - -### Prerequisites - -| Requirement | Description | -|----------------------|-----------------------------------------------------------------------------------| -| STACKIT organization | With a service account key that has `resource-manager.admin` on the organization. | diff --git a/reference-architectures/stackit-sandbox-landingzone/buildingblock/README.md b/reference-architectures/stackit-sandbox-landingzone/buildingblock/README.md deleted file mode 100644 index 9023fbf9..00000000 --- a/reference-architectures/stackit-sandbox-landingzone/buildingblock/README.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -name: STACKIT Sandbox Landing Zone -supportedPlatforms: - - stackit -description: Onboards a STACKIT sandbox platform into meshStack by creating a location, a STACKIT resourcemanager folder and the STACKIT Project platform with its default landing zone. ---- - -This building block bootstraps a complete STACKIT sandbox platform integration inside a meshStack -workspace. It creates a meshStack location, a dedicated STACKIT resourcemanager folder and -sources the [`modules/stackit`](../../../modules/stackit) project integration to provision the -STACKIT Project platform together with its default landing zone. - -It authenticates to STACKIT with a service account key you paste as a secret input. You also -provide the STACKIT organization UUID, owner email, nested integration tags and default role mapping -as user inputs. The service account needs `resource-manager.admin` on the organization. The nested project integration is -pinned to the same `git_ref` as this building block's implementation. - -The user-facing readme is maintained inline in the `readme` field of the -`meshstack_building_block_definition` in -[`../meshstack_integration.tf`](../meshstack_integration.tf). - - -## Requirements - -| Name | Version | -| ---- | ------- | -| [terraform](#requirement\_terraform) | >= 1.12.0 | -| [meshstack](#requirement\_meshstack) | >= 0.22.0 | -| [stackit](#requirement\_stackit) | >= 0.99.0 | - -## Modules - -| Name | Source | Version | -| ---- | ------ | ------- | -| [stackit\_integration](#module\_stackit\_integration) | github.com/meshcloud/meshstack-hub//modules/stackit | main | - -## Resources - -| Name | Type | -| ---- | ---- | -| [meshstack_location.this](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/location) | resource | -| [stackit_resourcemanager_folder.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_folder) | resource | -| [stackit_resourcemanager_project.backplane](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_project) | resource | - -## Inputs - -| Name | Description | Type | Default | Required | -| ---- | ----------- | ---- | ------- | :------: | -| [hub](#input\_hub) | `git_ref`: meshstack-hub reference used to source the nested STACKIT project integration module. `const` so it can be interpolated into the module source at init time.

`bbd_draft`: Forwarded as-is to the nested integration's own `hub.bbd_draft`, so its building block definition draft state tracks this building block's own release state. |
object({
git_ref = optional(string, "main")
bbd_draft = optional(bool, true)
})
|
{
"bbd_draft": true,
"git_ref": "main"
}
| no | -| [network\_area\_tag\_name](#input\_network\_area\_tag\_name) | Name of the meshStack landing zone tag whose value is used as the STACKIT project's `networkArea` label, forwarded to the nested STACKIT Project integration. Set to null (default) to skip network area assignment. | `string` | `null` | no | -| [platform\_identifier](#input\_platform\_identifier) | Identifier for the STACKIT sandbox platform created in meshStack (letters, digits and dashes only). | `string` | n/a | yes | -| [role\_mapping](#input\_role\_mapping) | Default mapping from meshStack roles to STACKIT project roles for the nested STACKIT Project integration. Values can be built-in STACKIT roles or custom STACKIT role names. | `map(list(string))` |
{
"admin": [
"owner"
],
"reader": [
"reader"
],
"user": [
"editor"
]
}
| no | -| [stackit\_org](#input\_stackit\_org) | STACKIT organization UUID under which the landing-zone folder, backplane project and tenant projects are created. | `string` | n/a | yes | -| [stackit\_organization\_onboarding\_enabled](#input\_stackit\_organization\_onboarding\_enabled) | Whether the nested STACKIT Project integration adds meshStack project users to the STACKIT organization before applying project-level role assignments. Disable if organization membership is managed outside this landing zone. | `bool` | `true` | no | -| [stackit\_owner\_email](#input\_stackit\_owner\_email) | Owner email assigned to the STACKIT resourcemanager folder and backplane project. | `string` | n/a | yes | -| [stackit\_service\_account\_key](#input\_stackit\_service\_account\_key) | STACKIT service account key JSON with `resource-manager.admin` on the organization. Used to create the landing-zone folder and backplane project. | `string` | n/a | yes | -| [tags](#input\_tags) | Tags forwarded to the nested STACKIT Project integration. `landingzone` tags are applied to the default landing zone; `building_block` tags are applied to the nested building block definition. |
object({
landingzone = map(list(string))
building_block = map(list(string))
})
|
{
"building_block": {},
"landingzone": {}
}
| no | -| [use\_global\_location](#input\_use\_global\_location) | Use the global location instead of creating a dedicated location for this platform. | `bool` | `false` | no | -| [workspace](#input\_workspace) | Identifier of the meshStack workspace that will own the created location, platform and landing zone. | `string` | n/a | yes | - -## Outputs - -| Name | Description | -| ---- | ----------- | -| [backplane\_project\_id](#output\_backplane\_project\_id) | Project ID of the STACKIT backplane project that hosts the service account used for tenant project creation. | -| [backplane\_project\_url](#output\_backplane\_project\_url) | Deep link to the backplane project in the STACKIT portal. | -| [lz\_folder\_container\_id](#output\_lz\_folder\_container\_id) | Container ID of the STACKIT resourcemanager folder created for the landing zone. Tenant projects are created inside this folder. | - diff --git a/reference-architectures/stackit-sandbox-landingzone/buildingblock/logo.png b/reference-architectures/stackit-sandbox-landingzone/buildingblock/logo.png deleted file mode 100644 index f346453fa5d520821a765f278e3ad5c014e04a20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2285 zcmZ8i30PBC7Ji6;Y|=8+!9q0+P(~pMV$~)jDPUMqAPb5~STZCCAwpg-c@Uh4VjZ#6 zy0r?T0$Tm5MLs1UOHf27Fx5s`3REybTp9rf1cgE|R_DGKz_#x@@8;Zd&-wrVoSS?p z!b(am4Uc6|fRBbrcpR33WYF;Z7!Gc|T#<@fOAH_e;OP!H9FD5k zoJNUdgwK|P9Sxt3AXyX=Nu^Q|RjY||g@m+g)|G1%3&OeD-z4I5gHzk63ssrorpB;EfcJqZ3{F=LQhDmhykQ|Y*0!?qZGD6 znhKaveEKRXmiedHEDx20lK(-BrBf^lTBSQsN%Lc)J1iAGv;&j0&x#Z%A*kd>^tF0? z_$(d-t(375q0q%P&tb4xC<%!PfgsI6$5$d72wFhlL~jg>$cl#8@epgyqT(T7U<)3W z0E&r+V!$eZ($Y|$#fLcYP+T0E0D{565Gw(7SmN0<;Db|O0Fy0%mw0qjgB6b_)~m1Cnow?I5#v^W-juAM){LGTY; zZ#%_q1m&7D(59tX&;_^@5Vu^!>`Z_*^e(c4qfOvT(uBmaHb9JLaTWM?Ut3MSdNOP? z_5NDh-+o`XE!3Iw=>`|;h#iZ~X9_y67q&gRv|!{iU;1#Q<6+--M;dp3|5bnY z-Rb6@G2=^p@A$qi_Wbus=^^jv&+7Bfj|P^H{=DuR@atI2WQ1(Yy*Fy)@iv6G**w7c zScUHY+@X{Ig>CBs{yUC~&gU;$vXIddN}9T_9&4JuuO4ik$t;^HStHSOjx5i5lAyX1 zCh0HT`Uzue+~nh%(B4lb)R8a3;PRVd`C$X^>y983@i| z_IGW(6bvs97f*X!t#FJSIjVS>>08*ufTydkRz&`jc)4E8K4fVBrXyl$=Ja##DM!V>5~+o>2)Mkhy5H{BsK9&j7+#zAVPW3CZ(N`p zXxYJKu_q4o4&EFU`Cod<)#efHX^qXsYXvRzpB}{R_t8jh4)5_dLtCD2y?*(` z(B(^ON7S7?6}v=19d##_<<92VZlSf)#J9S#gqaE9KBCIg-L~EY_nl(%cM;e9?HJh9 z^;Q*sdqI0xnw9YED`)l6#(1v)Cs^NTWH(|L9P;1`E85qO;5XqM+{u`djmOd+_&g|4G)!R@8A0V&1pihPBNyG zX~hi$9z!ywmua0^>k^d>@T>DQ9=x}CrSykW1YT6=x^(@+e;z%O(oy7>+81csoa>jO z@wjX{&L6RrY3;m`-F1mU`V^2=Tixq?Pm$!G10r_z{a$ZcJzmE#$u6dYrBBjYZMEpy zr3ljB`I3`B{D=QKKcJ*}y|PAJ`%2SgtmJ#u*BC2%l^j^26}-DeZ?ngg7FK_f1rp8} zp8@J^f2loHWvu)yl66ii(6C^1O@znNG=ut408MAPc1ht)+ete|n)!9NeYLcGtve#& xH+RGXD^Qwa(s7T5BLN4zDWUd0M|OU^6KZ(w;@;qCa7X_LnPDu(#n9x>{|}IngG~Sc diff --git a/reference-architectures/stackit-sandbox-landingzone/buildingblock/main.tf b/reference-architectures/stackit-sandbox-landingzone/buildingblock/main.tf deleted file mode 100644 index 2be36647..00000000 --- a/reference-architectures/stackit-sandbox-landingzone/buildingblock/main.tf +++ /dev/null @@ -1,48 +0,0 @@ -resource "meshstack_location" "this" { - count = var.use_global_location ? 0 : 1 - - metadata = { - name = var.platform_identifier - owned_by_workspace = var.workspace - } - - spec = { - display_name = var.platform_identifier - description = "STACKIT sandbox location created by the STACKIT Sandbox Landing Zone." - } -} - -resource "stackit_resourcemanager_folder" "this" { - name = var.platform_identifier - owner_email = var.stackit_owner_email - parent_container_id = var.stackit_org -} - -# Project hosting the backplane service account that creates tenant projects. -# Created directly under the organization (not the landing-zone folder). -resource "stackit_resourcemanager_project" "backplane" { - name = "${var.platform_identifier}-backplane" - owner_email = var.stackit_owner_email - parent_container_id = var.stackit_org -} - -module "stackit_integration" { - source = "github.com/meshcloud/meshstack-hub//modules/stackit?ref=${var.hub.git_ref}" - - stackit_organization_id = var.stackit_org - stackit_parent_container_id = stackit_resourcemanager_folder.this.container_id - stackit_project_id = stackit_resourcemanager_project.backplane.project_id - stackit_service_account_name = substr(var.platform_identifier, 0, 20) - role_mapping = var.role_mapping - stackit_organization_onboarding_enabled = var.stackit_organization_onboarding_enabled - stackit_network_area_tag_name = var.network_area_tag_name - - hub = var.hub - - meshstack = { - owning_workspace_identifier = var.workspace - location_name = var.use_global_location ? "global" : meshstack_location.this[0].metadata.name - platform_identifier = var.platform_identifier - tags = var.tags - } -} diff --git a/reference-architectures/stackit-sandbox-landingzone/buildingblock/outputs.tf b/reference-architectures/stackit-sandbox-landingzone/buildingblock/outputs.tf deleted file mode 100644 index 6c2f12de..00000000 --- a/reference-architectures/stackit-sandbox-landingzone/buildingblock/outputs.tf +++ /dev/null @@ -1,14 +0,0 @@ -output "lz_folder_container_id" { - value = stackit_resourcemanager_folder.this.container_id - description = "Container ID of the STACKIT resourcemanager folder created for the landing zone. Tenant projects are created inside this folder." -} - -output "backplane_project_id" { - value = stackit_resourcemanager_project.backplane.project_id - description = "Project ID of the STACKIT backplane project that hosts the service account used for tenant project creation." -} - -output "backplane_project_url" { - value = "https://portal.stackit.cloud/projects/${stackit_resourcemanager_project.backplane.project_id}" - description = "Deep link to the backplane project in the STACKIT portal." -} diff --git a/reference-architectures/stackit-sandbox-landingzone/buildingblock/provider.tf b/reference-architectures/stackit-sandbox-landingzone/buildingblock/provider.tf deleted file mode 100644 index 91d6ee43..00000000 --- a/reference-architectures/stackit-sandbox-landingzone/buildingblock/provider.tf +++ /dev/null @@ -1,4 +0,0 @@ -provider "stackit" { - experiments = ["iam"] # Required for authorization resources - service_account_key = var.stackit_service_account_key -} diff --git a/reference-architectures/stackit-sandbox-landingzone/buildingblock/versions.tf b/reference-architectures/stackit-sandbox-landingzone/buildingblock/versions.tf deleted file mode 100644 index 70fa5d68..00000000 --- a/reference-architectures/stackit-sandbox-landingzone/buildingblock/versions.tf +++ /dev/null @@ -1,14 +0,0 @@ -terraform { - required_version = ">= 1.12.0" # const variables require OpenTofu >= 1.12 / Terraform >= 1.15 - - required_providers { - meshstack = { - source = "meshcloud/meshstack" - version = ">= 0.22.0" - } - stackit = { - source = "stackitcloud/stackit" - version = ">= 0.99.0" - } - } -} diff --git a/reference-architectures/stackit-sandbox-landingzone/logo.png b/reference-architectures/stackit-sandbox-landingzone/logo.png deleted file mode 100644 index 0ef884fbf0fef303b0bf55d4b29920442a71d7a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5579 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 E2S}~H(*OVf From 9bb3bd13dad5207eb6b37d93d8ab6b59c644ab99 Mon Sep 17 00:00:00 2001 From: Jo Schwandke Date: Wed, 29 Jul 2026 07:17:23 +0200 Subject: [PATCH 2/6] chore: shorten description of network input for stackit LZ reference architecture (for now, was too long) --- .../meshstack_integration.tf | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/reference-architectures/stackit-landingzone/meshstack_integration.tf b/reference-architectures/stackit-landingzone/meshstack_integration.tf index cd74d42a..17892445 100644 --- a/reference-architectures/stackit-landingzone/meshstack_integration.tf +++ b/reference-architectures/stackit-landingzone/meshstack_integration.tf @@ -228,22 +228,7 @@ resource "meshstack_building_block_definition" "this" { display_name = "Network (Hub-and-Spoke)" description = <<-DESC Optional JSON object enabling hub-and-spoke networking. Leave as `null` to deploy only the - sandbox landing zone. When set, all fields are optional (sensible defaults shown): - - ```json - { - "network_area_tag_name": "StackitNetworkArea", - "hub_network_area_name": "hub", - "hub_network_ranges": ["10.0.0.0/16"], - "hub_transfer_network": "10.1.255.0/24", - "hub_min_prefix_length": 24, - "hub_max_prefix_length": 28, - "hub_default_prefix_length": 28, - "hub_default_nameservers": [], - "tenant_network_min_prefix_length": 24, - "tenant_network_max_prefix_length": 28 - } - ``` + sandbox landing zone. When set, all fields are optional DESC type = "CODE" assignment_type = "USER_INPUT" From 5899e5cb7c5db56e5b0cf09ebc95a64ded2b031e Mon Sep 17 00:00:00 2001 From: Jo Schwandke Date: Wed, 29 Jul 2026 07:36:28 +0200 Subject: [PATCH 3/6] chore: add description of network input for stackit LZ reference to definition readme --- .../meshstack_integration.tf | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/reference-architectures/stackit-landingzone/meshstack_integration.tf b/reference-architectures/stackit-landingzone/meshstack_integration.tf index 17892445..c80eeef0 100644 --- a/reference-architectures/stackit-landingzone/meshstack_integration.tf +++ b/reference-architectures/stackit-landingzone/meshstack_integration.tf @@ -79,6 +79,24 @@ resource "meshstack_building_block_definition" "this" { address plan, registers the **STACKIT Network** building block, and creates a `networked` landing zone. Application teams can then self-service order routed spoke networks inside their projects. + A **network** configuration looks like this (sensible example values shown — adapt them to your + own address plan): + + ```json + { + "network_area_tag_name": "StackitNetworkArea", + "hub_network_area_name": "hub", + "hub_network_ranges": ["10.0.0.0/16"], + "hub_transfer_network": "10.1.255.0/24", + "hub_min_prefix_length": 24, + "hub_max_prefix_length": 28, + "hub_default_prefix_length": 28, + "hub_default_nameservers": [], + "tenant_network_min_prefix_length": 24, + "tenant_network_max_prefix_length": 28 + } + ``` + ## 📦 Resources created - **meshStack location** – named after the chosen platform identifier. From 12a5e5fb682841f6db6cdd18b31f1a3f1e27052e Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 30 Jul 2026 16:44:20 +0200 Subject: [PATCH 4/6] docs: nice new LZ logo --- .../buildingblock/logo.png | Bin 2285 -> 5579 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/reference-architectures/stackit-landingzone/buildingblock/logo.png b/reference-architectures/stackit-landingzone/buildingblock/logo.png index f346453fa5d520821a765f278e3ad5c014e04a20..0ef884fbf0fef303b0bf55d4b29920442a71d7a6 100644 GIT binary patch literal 5579 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 E2S}~H(*OVf literal 2285 zcmZ8i30PBC7Ji6;Y|=8+!9q0+P(~pMV$~)jDPUMqAPb5~STZCCAwpg-c@Uh4VjZ#6 zy0r?T0$Tm5MLs1UOHf27Fx5s`3REybTp9rf1cgE|R_DGKz_#x@@8;Zd&-wrVoSS?p z!b(am4Uc6|fRBbrcpR33WYF;Z7!Gc|T#<@fOAH_e;OP!H9FD5k zoJNUdgwK|P9Sxt3AXyX=Nu^Q|RjY||g@m+g)|G1%3&OeD-z4I5gHzk63ssrorpB;EfcJqZ3{F=LQhDmhykQ|Y*0!?qZGD6 znhKaveEKRXmiedHEDx20lK(-BrBf^lTBSQsN%Lc)J1iAGv;&j0&x#Z%A*kd>^tF0? z_$(d-t(375q0q%P&tb4xC<%!PfgsI6$5$d72wFhlL~jg>$cl#8@epgyqT(T7U<)3W z0E&r+V!$eZ($Y|$#fLcYP+T0E0D{565Gw(7SmN0<;Db|O0Fy0%mw0qjgB6b_)~m1Cnow?I5#v^W-juAM){LGTY; zZ#%_q1m&7D(59tX&;_^@5Vu^!>`Z_*^e(c4qfOvT(uBmaHb9JLaTWM?Ut3MSdNOP? z_5NDh-+o`XE!3Iw=>`|;h#iZ~X9_y67q&gRv|!{iU;1#Q<6+--M;dp3|5bnY z-Rb6@G2=^p@A$qi_Wbus=^^jv&+7Bfj|P^H{=DuR@atI2WQ1(Yy*Fy)@iv6G**w7c zScUHY+@X{Ig>CBs{yUC~&gU;$vXIddN}9T_9&4JuuO4ik$t;^HStHSOjx5i5lAyX1 zCh0HT`Uzue+~nh%(B4lb)R8a3;PRVd`C$X^>y983@i| z_IGW(6bvs97f*X!t#FJSIjVS>>08*ufTydkRz&`jc)4E8K4fVBrXyl$=Ja##DM!V>5~+o>2)Mkhy5H{BsK9&j7+#zAVPW3CZ(N`p zXxYJKu_q4o4&EFU`Cod<)#efHX^qXsYXvRzpB}{R_t8jh4)5_dLtCD2y?*(` z(B(^ON7S7?6}v=19d##_<<92VZlSf)#J9S#gqaE9KBCIg-L~EY_nl(%cM;e9?HJh9 z^;Q*sdqI0xnw9YED`)l6#(1v)Cs^NTWH(|L9P;1`E85qO;5XqM+{u`djmOd+_&g|4G)!R@8A0V&1pihPBNyG zX~hi$9z!ywmua0^>k^d>@T>DQ9=x}CrSykW1YT6=x^(@+e;z%O(oy7>+81csoa>jO z@wjX{&L6RrY3;m`-F1mU`V^2=Tixq?Pm$!G10r_z{a$ZcJzmE#$u6dYrBBjYZMEpy zr3ljB`I3`B{D=QKKcJ*}y|PAJ`%2SgtmJ#u*BC2%l^j^26}-DeZ?ngg7FK_f1rp8} zp8@J^f2loHWvu)yl66ii(6C^1O@znNG=ut408MAPc1ht)+ete|n)!9NeYLcGtve#& xH+RGXD^Qwa(s7T5BLN4zDWUd0M|OU^6KZ(w;@;qCa7X_LnPDu(#n9x>{|}IngG~Sc From ba344943127322d7fad7e2a3eed7c371ca3aa23d Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 3 Aug 2026 09:52:25 +0200 Subject: [PATCH 5/6] docs: add STACKIT landing zone architecture diagram Replace the mermaid diagram with a Graphviz DOT source and its rendered SVG, following the repo diagram conventions: STACKIT resource hierarchy and meshStack constructs as separate top-level clusters, with the mapping between them drawn as dotted cross-cluster edges. Co-Authored-By: Claude Opus 5 (1M context) --- .../stackit-landingzone/README.md | 63 +----- .../stackit-landingzone.dot | 69 ++++++ .../stackit-landingzone.svg | 204 ++++++++++++++++++ 3 files changed, 283 insertions(+), 53 deletions(-) create mode 100644 reference-architectures/stackit-landingzone/stackit-landingzone.dot create mode 100644 reference-architectures/stackit-landingzone/stackit-landingzone.svg diff --git a/reference-architectures/stackit-landingzone/README.md b/reference-architectures/stackit-landingzone/README.md index 47156ce9..225160fa 100644 --- a/reference-architectures/stackit-landingzone/README.md +++ b/reference-architectures/stackit-landingzone/README.md @@ -45,59 +45,16 @@ deploys only the sandbox foundation. ## Architecture Diagram -The diagram separates the **platform artifacts** provisioned once by the platform team — the -STACKIT cloud objects (folder, foundation project), the meshStack platform, landing zones, and the -building block **definitions** (BBDs) registered in meshStack — from the **application landing zone -objects** that application teams instantiate `N` times in self-service. Building block definitions -(blue) are registered once; building block **instances** (green) are ordered against them — the hub -network area is a single instance the platform team orders, while STACKIT projects and spoke -networks are ordered `N` times by application teams. - -```mermaid -flowchart TB - subgraph platform["🏗️ Platform Team — provisioned once by this reference architecture"] - direction TB - FOLDER["📁 Resourcemanager Folder
STACKIT"] - FOUND["🔑 Foundation Project
STACKIT · project-creation service account"] - PLAT["🛰️ STACKIT Project Platform
meshStack"] - PRJBBD["📦 STACKIT Project BBD
meshStack definition"] - DEFLZ["🛬 Default Landing Zone
meshStack"] - - PLAT --> PRJBBD - PLAT --> DEFLZ - FOUND -. hosts SA, creates projects in .-> FOLDER - - subgraph net["Optional — enabled by the network configuration"] - direction TB - NABBD["📦 Network Area BBD
meshStack definition"] - SPOKEBBD["📦 STACKIT Network BBD
meshStack definition · spoke"] - HUBNA["🌐 Hub Network Area
1 building block instance"] - NETLZ["🛬 Networked Landing Zone
meshStack"] - - NABBD -->|platform team orders 1| HUBNA - NETLZ -. tagged with area id .-> HUBNA - end - PLAT --> NETLZ - end - - subgraph apps["👥 Application Teams — self-service · N instances"] - direction TB - PRJ["🗂️ STACKIT Project ×N
building block instance"] - SPOKE["🔌 Spoke Network ×N
building block instance"] - PRJ -->|orders stackit/network| SPOKE - end - - DEFLZ ==>|request project| PRJ - NETLZ ==>|request networked project| PRJ - PRJBBD -. defines .-> PRJ - SPOKEBBD -. defines .-> SPOKE - SPOKE -. draws CIDR from .-> HUBNA - - classDef bbd fill:#e8ecff,stroke:#5566dd,stroke-width:1px,color:#111; - classDef inst fill:#e6f6e6,stroke:#4a9a4a,stroke-width:1px,color:#111; - class PRJBBD,NABBD,SPOKEBBD bbd; - class HUBNA,PRJ,SPOKE inst; -``` +The left half of the diagram is the **STACKIT resource hierarchy** — the organization, the +resourcemanager folder tenant projects land in, the foundation project holding the project-creation +service account, and the org-level network area. The right half is **meshStack**: the platform, its +landing zones and the building block **definitions** (BBDs). Dotted edges across the boundary show +how each meshStack construct maps onto a STACKIT one. Definitions (blue) are registered once; +**instances** (green) are ordered against them — the hub network area is a single instance the +platform team orders, while STACKIT projects and spoke networks are ordered `N` times by application +teams. Everything marked *optional* only appears when a network configuration is provided. + +![STACKIT Landing Zone reference architecture](stackit-landingzone.svg) When networking is enabled, application teams order a routed network into their own project via the self-service `stackit/network` building block; each order draws its subnet from the hub's address diff --git a/reference-architectures/stackit-landingzone/stackit-landingzone.dot b/reference-architectures/stackit-landingzone/stackit-landingzone.dot new file mode 100644 index 00000000..7f708b2f --- /dev/null +++ b/reference-architectures/stackit-landingzone/stackit-landingzone.dot @@ -0,0 +1,69 @@ +/* + * STACKIT Landing Zone reference architecture. + * Conventions: .agents/references/diagrams.md — render with: task diagrams + */ +digraph stackit_landingzone { + rankdir=TB + splines=ortho + forcelabels=true + bgcolor="white" + nodesep=0.55 + ranksep=0.85 + + node [shape=box style="rounded,filled" fontname="Helvetica" fontsize=11 + fillcolor="#ffffff" color="#a2abb8" penwidth=1.1 margin="0.20,0.11"] + edge [fontname="Helvetica" fontsize=9 fontcolor="#697180" color="#8b95a3" arrowsize=0.7] + + subgraph cluster_stackit { + label=" STACKIT" + labeljust=l + fontname="Helvetica" fontsize=12 fontcolor="#697180" + style="rounded" color="#d5dae0" + margin=18 + + ORG [label="🏢 STACKIT Organization" fillcolor="#ffffff" color="#a2abb8"] + FOUND [label="🔑 Foundation Project\nhosts the project-creation service account" fillcolor="#ffffff" color="#a2abb8"] + FOLDER [label="📁 Resourcemanager Folder\ntenant projects are created here" fillcolor="#ffffff" color="#a2abb8"] + NA [label="🌐 Network Area ×1\nshared IPv4 address plan · hub" fillcolor="#e5f2ea" color="#85bfa0"] + PRJ [label="🗂️ STACKIT Project ×N" fillcolor="#e5f2ea" color="#85bfa0"] + SPOKE [label="🔌 Routed Network ×N\nspoke subnet" fillcolor="#e5f2ea" color="#85bfa0"] + + { rank=same; FOUND -> FOLDER -> NA [style=invis] } + + ORG -> FOUND + ORG -> FOLDER + ORG -> NA + FOLDER -> PRJ [xlabel="holds"] + PRJ -> SPOKE [xlabel="contains"] + NA -> SPOKE [xlabel="assigns CIDR to" style=dashed constraint=false] + } + + subgraph cluster_mesh { + label=" meshStack" + labeljust=l + fontname="Helvetica" fontsize=12 fontcolor="#697180" + style="rounded" color="#d5dae0" + margin=18 + + PLAT [label="🛰️ STACKIT Project Platform" fillcolor="#ecedfb" color="#9aa2e6"] + DEFLZ [label="🛬 Default Landing Zone" fillcolor="#ecedfb" color="#9aa2e6"] + NETLZ [label="🛬 Networked Landing Zone\noptional · with network config" fillcolor="#ecedfb" color="#9aa2e6"] + PRJBBD [label="📦 stackit/project BBD" fillcolor="#ecedfb" color="#9aa2e6"] + NABBD [label="📦 stackit/network-area BBD\noptional · platform team orders it once" fillcolor="#ecedfb" color="#9aa2e6"] + SPOKEBBD [label="📦 stackit/network BBD\noptional · tenant-level self-service" fillcolor="#ecedfb" color="#9aa2e6"] + + { rank=same; DEFLZ -> NETLZ [style=invis] } + { rank=same; PRJBBD -> SPOKEBBD -> NABBD [style=invis] } + + PLAT -> DEFLZ + PLAT -> NETLZ + DEFLZ -> PRJBBD [xlabel="requests"] + NETLZ -> SPOKEBBD [xlabel="offers to tenants"] + } + + FOUND -> PLAT [xlabel="authenticates" style=dotted constraint=false] + PRJBBD -> PRJ [xlabel="provisions" style=dotted constraint=false] + NABBD -> NA [xlabel="provisions" style=dotted constraint=false] + SPOKEBBD -> SPOKE [xlabel="provisions" style=dotted constraint=false] + NETLZ -> NA [xlabel="tagged with area id" style=dotted constraint=false] +} diff --git a/reference-architectures/stackit-landingzone/stackit-landingzone.svg b/reference-architectures/stackit-landingzone/stackit-landingzone.svg new file mode 100644 index 00000000..4033f724 --- /dev/null +++ b/reference-architectures/stackit-landingzone/stackit-landingzone.svg @@ -0,0 +1,204 @@ + + + + +stackit_landingzone + + +cluster_stackit + +  STACKIT + + +cluster_mesh + +  meshStack + + + +ORG + +🏢 STACKIT Organization + + + +FOUND + +🔑 Foundation Project +hosts the project-creation service account + + + +ORG->FOUND + + + + + +FOLDER + +📁 Resourcemanager Folder +tenant projects are created here + + + +ORG->FOLDER + + + + + +NA + +🌐 Network Area ×1 +shared IPv4 address plan · hub + + + +ORG->NA + + + + + + +PLAT + +🛰️ STACKIT Project Platform + + + +FOUND->PLAT + + +authenticates + + + + +PRJ + +🗂️ STACKIT Project ×N + + + +FOLDER->PRJ + + +holds + + + +SPOKE + +🔌 Routed Network ×N +spoke subnet + + + +NA->SPOKE + + +assigns CIDR to + + + +PRJ->SPOKE + + +contains + + + +DEFLZ + +🛬 Default Landing Zone + + + +PLAT->DEFLZ + + + + + +NETLZ + +🛬 Networked Landing Zone +optional · with network config + + + +PLAT->NETLZ + + + + + + +PRJBBD + +📦 stackit/project BBD + + + +DEFLZ->PRJBBD + + +requests + + + +NETLZ->NA + + +tagged with area id + + + +SPOKEBBD + +📦 stackit/network BBD +optional · tenant-level self-service + + + +NETLZ->SPOKEBBD + + +offers to tenants + + + +PRJBBD->PRJ + + +provisions + + + + +NABBD + +📦 stackit/network-area BBD +optional · platform team orders it once + + + +NABBD->NA + + +provisions + + + +SPOKEBBD->SPOKE + + +provisions + + + + From 38308e2a8d08b2b8a4a13b429e56f76a024094b2 Mon Sep 17 00:00:00 2001 From: Jo Schwandke Date: Mon, 3 Aug 2026 11:22:15 +0200 Subject: [PATCH 6/6] chore: add deep links to STACKIT for network(-area)s --- modules/stackit/network-area/buildingblock/README.md | 1 + modules/stackit/network-area/buildingblock/SUMMARY.md.tftpl | 1 + modules/stackit/network-area/buildingblock/outputs.tf | 6 ++++++ modules/stackit/network-area/meshstack_integration.tf | 6 ++++++ modules/stackit/network/buildingblock/README.md | 1 + modules/stackit/network/buildingblock/SUMMARY.md.tftpl | 1 + modules/stackit/network/buildingblock/outputs.tf | 6 ++++++ modules/stackit/network/meshstack_integration.tf | 6 ++++++ 8 files changed, 28 insertions(+) diff --git a/modules/stackit/network-area/buildingblock/README.md b/modules/stackit/network-area/buildingblock/README.md index 42a2a629..b1da154f 100644 --- a/modules/stackit/network-area/buildingblock/README.md +++ b/modules/stackit/network-area/buildingblock/README.md @@ -51,6 +51,7 @@ No modules. |------|-------------| | [network\_area\_id](#output\_network\_area\_id) | The UUID of the created STACKIT network area. | | [network\_area\_name](#output\_network\_area\_name) | The name of the created STACKIT network area. | +| [network\_area\_url](#output\_network\_area\_url) | The deep link URL to access the network area in the STACKIT portal. | | [network\_ranges](#output\_network\_ranges) | IPv4 CIDR ranges available to projects within the network area. | | [summary](#output\_summary) | Summary of the created network area. | | [transfer\_network](#output\_transfer\_network) | IPv4 CIDR range used as the transfer network between the network area and connected networks. | diff --git a/modules/stackit/network-area/buildingblock/SUMMARY.md.tftpl b/modules/stackit/network-area/buildingblock/SUMMARY.md.tftpl index 83cf71da..e698dbbc 100644 --- a/modules/stackit/network-area/buildingblock/SUMMARY.md.tftpl +++ b/modules/stackit/network-area/buildingblock/SUMMARY.md.tftpl @@ -7,3 +7,4 @@ | **Network Area ID** | `${network_area_id}` | | **Network Ranges** | ${join(", ", network_ranges)} | | **Transfer Network** | `${transfer_network}` | +| **Portal** | [Open in STACKIT Portal](${network_area_url}) | diff --git a/modules/stackit/network-area/buildingblock/outputs.tf b/modules/stackit/network-area/buildingblock/outputs.tf index f2fa83f0..94bda18b 100644 --- a/modules/stackit/network-area/buildingblock/outputs.tf +++ b/modules/stackit/network-area/buildingblock/outputs.tf @@ -18,11 +18,17 @@ output "transfer_network" { description = "IPv4 CIDR range used as the transfer network between the network area and connected networks." } +output "network_area_url" { + value = "https://portal.stackit.cloud/network-area/network-areas/${stackit_network_area.this.network_area_id}/overview?organization=${var.organization_id}" + description = "The deep link URL to access the network area in the STACKIT portal." +} + output "summary" { description = "Summary of the created network area." value = templatefile("${path.module}/SUMMARY.md.tftpl", { network_area_id = stackit_network_area.this.network_area_id network_area_name = stackit_network_area.this.name + network_area_url = "https://portal.stackit.cloud/network-area/network-areas/${stackit_network_area.this.network_area_id}/overview?organization=${var.organization_id}" network_ranges = var.network_ranges transfer_network = var.transfer_network }) diff --git a/modules/stackit/network-area/meshstack_integration.tf b/modules/stackit/network-area/meshstack_integration.tf index 49064e80..f0e59748 100644 --- a/modules/stackit/network-area/meshstack_integration.tf +++ b/modules/stackit/network-area/meshstack_integration.tf @@ -227,6 +227,12 @@ resource "meshstack_building_block_definition" "this" { } outputs = { + network_area_url = { + display_name = "Network Area URL" + type = "STRING" + assignment_type = "RESOURCE_URL" + } + network_area_id = { display_name = "Network Area ID" type = "STRING" diff --git a/modules/stackit/network/buildingblock/README.md b/modules/stackit/network/buildingblock/README.md index 5fcddffa..6fbda6f3 100644 --- a/modules/stackit/network/buildingblock/README.md +++ b/modules/stackit/network/buildingblock/README.md @@ -46,5 +46,6 @@ No modules. |------|-------------| | [network\_cidr](#output\_network\_cidr) | Allocated IPv4 CIDR block of the network. | | [network\_id](#output\_network\_id) | The UUID of the created STACKIT network. | +| [network\_url](#output\_network\_url) | The deep link URL to access the network in the STACKIT portal. | | [summary](#output\_summary) | Summary of the created network. | \ No newline at end of file diff --git a/modules/stackit/network/buildingblock/SUMMARY.md.tftpl b/modules/stackit/network/buildingblock/SUMMARY.md.tftpl index be7d9a34..c10dc2c0 100644 --- a/modules/stackit/network/buildingblock/SUMMARY.md.tftpl +++ b/modules/stackit/network/buildingblock/SUMMARY.md.tftpl @@ -6,3 +6,4 @@ |----------|-------| | **Network ID** | `${network_id}` | | **Network CIDR** | `${network_cidr}` | +| **Portal** | [Open in STACKIT Portal](${network_url}) | diff --git a/modules/stackit/network/buildingblock/outputs.tf b/modules/stackit/network/buildingblock/outputs.tf index ec06ed9f..540ba65a 100644 --- a/modules/stackit/network/buildingblock/outputs.tf +++ b/modules/stackit/network/buildingblock/outputs.tf @@ -8,11 +8,17 @@ output "network_cidr" { description = "Allocated IPv4 CIDR block of the network." } +output "network_url" { + value = "https://portal.stackit.cloud/network/networks/${stackit_network.this.network_id}/overview?project=${var.project_id}" + description = "The deep link URL to access the network in the STACKIT portal." +} + output "summary" { description = "Summary of the created network." value = templatefile("${path.module}/SUMMARY.md.tftpl", { network_name = stackit_network.this.name network_id = stackit_network.this.network_id network_cidr = stackit_network.this.ipv4_prefix + network_url = "https://portal.stackit.cloud/network/networks/${stackit_network.this.network_id}/overview?project=${var.project_id}" }) } diff --git a/modules/stackit/network/meshstack_integration.tf b/modules/stackit/network/meshstack_integration.tf index 1825a332..1e2201bc 100644 --- a/modules/stackit/network/meshstack_integration.tf +++ b/modules/stackit/network/meshstack_integration.tf @@ -203,6 +203,12 @@ resource "meshstack_building_block_definition" "this" { } outputs = { + network_url = { + display_name = "Network URL" + type = "STRING" + assignment_type = "RESOURCE_URL" + } + network_id = { display_name = "Network ID" type = "STRING"