Skip to content

Commit 087ac06

Browse files
Merge remote-tracking branch 'intive/main' into fix/idempotent-lifecycle-ops
2 parents 94850ce + 76d2775 commit 087ac06

72 files changed

Lines changed: 2408 additions & 714 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
go-version-file: "go.mod"
2828
cache: true
2929
- name: Import GPG key
30-
uses: crazy-max/ghaction-import-gpg@v6
30+
uses: crazy-max/ghaction-import-gpg@v7
3131
id: import_gpg
3232
with:
3333
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}

docs/data-sources/network.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ data "stackit_network" "example" {
4747
- `ipv6_prefixes` (List of String) The IPv6 prefixes of the network.
4848
- `labels` (Map of String) Labels are key-value string pairs which can be attached to a resource container
4949
- `name` (String) The name of the network.
50-
- `nameservers` (List of String, Deprecated) The nameservers of the network. This field is deprecated and will be removed soon, use `ipv4_nameservers` to configure the nameservers for IPv4.
51-
- `prefixes` (List of String, Deprecated) The prefixes of the network. This field is deprecated and will be removed soon, use `ipv4_prefixes` to read the prefixes of the IPv4 networks.
5250
- `public_ip` (String) The public IP of the network.
5351
- `routed` (Boolean) Shows if the network is routed and therefore accessible from other networks.
5452
- `routing_table_id` (String) The ID of the routing table associated with the network.

docs/data-sources/ske_cluster.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,17 @@ Read-Only:
117117

118118
Read-Only:
119119

120+
- `control_plane` (Attributes) Control plane for the cluster. (see [below for nested schema](#nestedatt--network--control_plane))
120121
- `id` (String) ID of the STACKIT Network Area (SNA) network into which the cluster will be deployed.
121122

123+
<a id="nestedatt--network--control_plane"></a>
124+
### Nested Schema for `network.control_plane`
125+
126+
Read-Only:
127+
128+
- `access_scope` (String) Access scope of the control plane. It defines if the Kubernetes control plane is public or only available inside a STACKIT Network Area.Possible values are: `PUBLIC`, `SNA`. The field is immutable!
129+
130+
122131

123132
<a id="nestedatt--node_pools"></a>
124133
### Nested Schema for `node_pools`
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
---
2+
page_title: "Setting up Encrypted Volumes for STACKIT Kubernetes Engine (SKE)"
3+
---
4+
5+
# Setting up Encrypted Volumes for STACKIT Kubernetes Engine (SKE)
6+
7+
~> This guide assumes that your project or organization has been enabled for a preview version of the STACKIT CSI Driver. If you wish to use encrypted volumes, please contact your account manager.
8+
9+
## Overview
10+
11+
This guide demonstrates how to roll out an encrypted storage class for SKE using the STACKIT Key Management Service (KMS). To achieve this, we use a **Service Account Impersonation** (Act-As) pattern. This allows the internal SKE service account to perform encryption and decryption tasks on behalf of a user-managed service account that has been granted access to your KMS keys.
12+
13+
## Steps
14+
15+
### 1. Configure the SKE Cluster
16+
17+
Create a standard SKE cluster. We also generate a kubeconfig dynamically to allow the `kubernetes` provider to interact with the cluster within the same Terraform execution.
18+
19+
```hcl
20+
resource "stackit_ske_cluster" "default" {
21+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
22+
name = "ske-enc-vol"
23+
kubernetes_version_min = "1.33"
24+
25+
node_pools = [{
26+
name = "standard"
27+
machine_type = "c2i.4"
28+
minimum = 1
29+
maximum = 3
30+
availability_zones = ["eu01-1"]
31+
os_name = "flatcar"
32+
volume_size = 32
33+
}]
34+
}
35+
36+
resource "stackit_ske_kubeconfig" "default" {
37+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
38+
cluster_name = stackit_ske_cluster.default.name
39+
refresh = true
40+
}
41+
```
42+
43+
44+
### 2. Identify the Internal SKE Service Account
45+
46+
Each STACKIT project with a SKE Cluster deployed has a dedicated, internal service account used by SKE. We need to look this up to grant it permissions in a later step.
47+
48+
```hcl
49+
data "stackit_service_accounts" "ske_internal" {
50+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
51+
email_suffix = "@ske.sa.stackit.cloud"
52+
53+
depends_on = [stackit_ske_cluster.default]
54+
}
55+
```
56+
57+
### 3. Setup KMS Infrastructure
58+
59+
Define the Keyring and the specific Key that will be used to encrypt the block storage volumes.
60+
61+
```hcl
62+
resource "stackit_kms_keyring" "encryption" {
63+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
64+
display_name = "ske-volume-keyring"
65+
}
66+
67+
resource "stackit_kms_key" "volume_key" {
68+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
69+
keyring_id = stackit_kms_keyring.encryption.keyring_id
70+
display_name = "volume-encryption-key"
71+
protection = "software"
72+
algorithm = "aes_256_gcm"
73+
purpose = "symmetric_encrypt_decrypt"
74+
}
75+
```
76+
77+
### 4. Configure Identity and Permissions (Act-As)
78+
79+
This is the most critical part of the setup. We create a **manager** service account that holds the KMS permissions, and then authorize the SKE internal service account to **Act-As** (impersonate) that manager.
80+
81+
```hcl
82+
# Create the service account that 'owns' the KMS access
83+
resource "stackit_service_account" "kms_manager" {
84+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
85+
name = "volume-encryptor"
86+
}
87+
88+
# Grant the 'kms.admin' role to the manager service-account
89+
resource "stackit_authorization_project_role_assignment" "kms_user" {
90+
// in this case the STACKIT project_id
91+
resource_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
92+
role = "kms.admin"
93+
subject = stackit_service_account.kms_manager.email
94+
}
95+
96+
# Authorize the internal SKE account to impersonate the kms manager service-account (Act-As)
97+
resource "stackit_authorization_service_account_role_assignment" "ske_impersonation" {
98+
resource_id = stackit_service_account.kms_manager.service_account_id
99+
role = "user"
100+
subject = data.stackit_service_accounts.ske_internal.items[0].email
101+
}
102+
```
103+
104+
### 5. Create the Encrypted Storage Class in Kubernetes
105+
106+
Define the `kubernetes_storage_class`. We pass the IDs of the KMS resources and the email of our manager service account into the parameters.
107+
108+
```hcl
109+
resource "kubernetes_storage_class_v1" "encrypted_premium" {
110+
metadata {
111+
name = "stackit-encrypted-premium"
112+
}
113+
114+
storage_provisioner = "block-storage.csi.stackit.cloud"
115+
reclaim_policy = "Delete"
116+
allow_volume_expansion = true
117+
volume_binding_mode = "WaitForFirstConsumer"
118+
119+
parameters = {
120+
type = "storage_premium_perf6"
121+
encrypted = "true"
122+
kmsKeyID = stackit_kms_key.volume_key.key_id
123+
kmsKeyringID = stackit_kms_keyring.encryption.keyring_id
124+
kmsProjectID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
125+
kmsKeyVersion = "1"
126+
kmsServiceAccount = stackit_service_account.kms_manager.email
127+
}
128+
129+
depends_on = [
130+
stackit_authorization_service_account_role_assignment.ske_impersonation,
131+
stackit_authorization_project_role_assignment.kms_user
132+
]
133+
}
134+
```
135+
136+
### 6. Verify with a Persistent Volume Claim (PVC)
137+
138+
You can now create a PVC using the new storage class. When a pod claims this volume, the STACKIT CSI driver will automatically use the KMS key to provide an encrypted volume.
139+
140+
```hcl
141+
resource "kubernetes_persistent_volume_claim_v1" "test_pvc" {
142+
metadata {
143+
name = "test-encryption-pvc"
144+
}
145+
146+
spec {
147+
access_modes = ["ReadWriteOnce"]
148+
149+
resources {
150+
requests = {
151+
storage = "10Gi"
152+
}
153+
}
154+
155+
storage_class_name = kubernetes_storage_class_v1.encrypted_premium.metadata[0].name
156+
}
157+
}
158+
```
159+
160+
### 7. Create a Pod to Consume the Volume
161+
162+
```hcl
163+
resource "kubernetes_pod_v1" "test_app" {
164+
metadata {
165+
name = "encrypted-volume-test"
166+
}
167+
168+
spec {
169+
container {
170+
image = "nginx:latest"
171+
name = "web-server"
172+
173+
volume_mount {
174+
mount_path = "/usr/share/nginx/html"
175+
name = "data-volume"
176+
}
177+
}
178+
179+
volume {
180+
name = "data-volume"
181+
persistent_volume_claim {
182+
claim_name = "test-encryption-pvc"
183+
}
184+
}
185+
}
186+
}
187+
```

docs/resources/authorization_folder_role_assignment.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ import {
4141

4242
### Required
4343

44-
- `resource_id` (String) folder Resource to assign the role to.
44+
- `resource_id` (String) Folder Resource to assign the role to.
4545
- `role` (String) Role to be assigned. Available roles can be queried using stackit-cli: `stackit curl https://authorization.api.stackit.cloud/v2/permissions`
46-
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients
46+
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients. All letters must be lowercased.
4747

4848
### Read-Only
4949

docs/resources/authorization_organization_role_assignment.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ import {
3434

3535
### Required
3636

37-
- `resource_id` (String) organization Resource to assign the role to.
37+
- `resource_id` (String) Organization Resource to assign the role to.
3838
- `role` (String) Role to be assigned. Available roles can be queried using stackit-cli: `stackit curl https://authorization.api.stackit.cloud/v2/permissions`
39-
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients
39+
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients. All letters must be lowercased.
4040

4141
### Read-Only
4242

docs/resources/authorization_project_role_assignment.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ import {
4141

4242
### Required
4343

44-
- `resource_id` (String) project Resource to assign the role to.
44+
- `resource_id` (String) Project Resource to assign the role to.
4545
- `role` (String) Role to be assigned. Available roles can be queried using stackit-cli: `stackit curl https://authorization.api.stackit.cloud/v2/permissions`
46-
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients
46+
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients. All letters must be lowercased.
4747

4848
### Read-Only
4949

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "stackit_authorization_service_account_role_assignment Resource - stackit"
4+
subcategory: ""
5+
description: |-
6+
Service-account Role Assignment resource schema.
7+
~> Important: Use this resource to grant 'Act-As' permissions. This allows a service-account (the subject) to impersonate the target Service Account. A common example is authorizing the SKE Service Account to act as a project-specific Service Account to access APIs.
8+
~> This resource is part of the iam experiment and is likely going to undergo significant changes or be removed in the future. Use it at your own discretion.
9+
---
10+
11+
# stackit_authorization_service_account_role_assignment (Resource)
12+
13+
Service-account Role Assignment resource schema.
14+
15+
~> **Important:** Use this resource to grant 'Act-As' permissions. This allows a service-account (the `subject`) to impersonate the target Service Account. A common example is authorizing the SKE Service Account to act as a project-specific Service Account to access APIs.
16+
17+
~> This resource is part of the iam experiment and is likely going to undergo significant changes or be removed in the future. Use it at your own discretion.
18+
19+
## Example Usage
20+
21+
```terraform
22+
data "stackit_service_accounts" "ske_sa_suffix" {
23+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
24+
email_suffix = "@ske.sa.stackit.cloud"
25+
}
26+
27+
resource "stackit_service_account" "iam" {
28+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
29+
name = "kms"
30+
}
31+
32+
resource "stackit_authorization_project_role_assignment" "pr_sa" {
33+
resource_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
34+
role = "kms.admin"
35+
subject = stackit_service_account.iam.email
36+
}
37+
38+
// Assign the Act-As permissions to the previously created ServiceAccount.
39+
// The SKE ServiceAccount is now authorized to access KMS upon the behalf of stackit_service_account.iam
40+
resource "stackit_authorization_service_account_role_assignment" "sa" {
41+
resource_id = stackit_service_account.iam.service_account_id
42+
role = "user"
43+
subject = data.stackit_service_accounts.ske_sa_suffix.items.0.email
44+
}
45+
46+
# Only use the import statement, if you want to import an existing service account assignment
47+
import {
48+
to = stackit_authorization_service_account_assignment.sa
49+
id = "${var.resource_id},${var.service_account_assignment_role},${var.service_account_assignment_subject}"
50+
}
51+
```
52+
53+
<!-- schema generated by tfplugindocs -->
54+
## Schema
55+
56+
### Required
57+
58+
- `resource_id` (String) Service-account Resource to assign the role to.
59+
- `role` (String) Role to be assigned. Available roles can be queried using stackit-cli: `stackit curl https://authorization.api.stackit.cloud/v2/permissions`
60+
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients. All letters must be lowercased.
61+
62+
### Read-Only
63+
64+
- `id` (String) Terraform's internal resource identifier. It is structured as "`resource_id`,`role`,`subject`".

docs/resources/network.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ page_title: "stackit_network Resource - stackit"
44
subcategory: ""
55
description: |-
66
Network resource schema. Must have a region specified in the provider configuration.
7-
~> Behavior of not configured ipv4_nameservers will change from January 2026. When ipv4_nameservers is not set, it will be set to the network area's default_nameservers.
7+
~> Behavior of not configured ipv4_nameservers has changed. When ipv4_nameservers is not set, it will be set to the network area's default_nameservers.
88
To prevent any nameserver configuration, the ipv4_nameservers attribute should be explicitly set to an empty list [].
99
In cases where ipv4_nameservers are defined within the resource, the existing behavior will remain unchanged.
1010
---
1111

1212
# stackit_network (Resource)
1313

1414
Network resource schema. Must have a `region` specified in the provider configuration.
15-
~> Behavior of not configured `ipv4_nameservers` will change from January 2026. When `ipv4_nameservers` is not set, it will be set to the network area's `default_nameservers`.
15+
~> Behavior of not configured `ipv4_nameservers` has changed. When `ipv4_nameservers` is not set, it will be set to the network area's `default_nameservers`.
1616
To prevent any nameserver configuration, the `ipv4_nameservers` attribute should be explicitly set to an empty list `[]`.
1717
In cases where `ipv4_nameservers` are defined within the resource, the existing behavior will remain unchanged.
1818

@@ -66,15 +66,14 @@ import {
6666

6767
- `dhcp` (Boolean) If the network has DHCP enabled. Default value is `true`.
6868
- `ipv4_gateway` (String) The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway.
69-
- `ipv4_nameservers` (List of String) The IPv4 nameservers of the network.
69+
- `ipv4_nameservers` (List of String) The IPv4 nameservers of the network. If not specified on creation, it will be set with the default nameservers from the network area. If not specified on update, it will remain unchanged.
7070
- `ipv4_prefix` (String) The IPv4 prefix of the network (CIDR).
7171
- `ipv4_prefix_length` (Number) The IPv4 prefix length of the network.
7272
- `ipv6_gateway` (String) The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway.
7373
- `ipv6_nameservers` (List of String) The IPv6 nameservers of the network.
7474
- `ipv6_prefix` (String) The IPv6 prefix of the network (CIDR).
7575
- `ipv6_prefix_length` (Number) The IPv6 prefix length of the network.
7676
- `labels` (Map of String) Labels are key-value string pairs which can be attached to a resource container
77-
- `nameservers` (List of String, Deprecated) The nameservers of the network. This field is deprecated and will be removed in January 2026, use `ipv4_nameservers` to configure the nameservers for IPv4.
7877
- `no_ipv4_gateway` (Boolean) If set to `true`, the network doesn't have a gateway.
7978
- `no_ipv6_gateway` (Boolean) If set to `true`, the network doesn't have a gateway.
8079
- `region` (String) The resource region. If not defined, the provider region is used.
@@ -87,5 +86,4 @@ import {
8786
- `ipv4_prefixes` (List of String) The IPv4 prefixes of the network.
8887
- `ipv6_prefixes` (List of String) The IPv6 prefixes of the network.
8988
- `network_id` (String) The network ID.
90-
- `prefixes` (List of String, Deprecated) The prefixes of the network. This field is deprecated and will be removed in January 2026, use `ipv4_prefixes` to read the prefixes of the IPv4 networks.
9189
- `public_ip` (String) The public IP of the network.

docs/resources/ske_cluster.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ resource "stackit_ske_cluster" "example" {
3939
start = "01:00:00Z"
4040
end = "02:00:00Z"
4141
}
42+
network = {
43+
control_plane = {
44+
access_scope = "PUBLIC"
45+
}
46+
}
4247
}
4348
4449
# Only use the import statement, if you want to import an existing ske cluster
@@ -204,4 +209,12 @@ Optional:
204209

205210
Optional:
206211

212+
- `control_plane` (Attributes) Control plane for the cluster. (see [below for nested schema](#nestedatt--network--control_plane))
207213
- `id` (String) ID of the STACKIT Network Area (SNA) network into which the cluster will be deployed.
214+
215+
<a id="nestedatt--network--control_plane"></a>
216+
### Nested Schema for `network.control_plane`
217+
218+
Optional:
219+
220+
- `access_scope` (String) Access scope of the control plane. It defines if the Kubernetes control plane is public or only available inside a STACKIT Network Area.Possible values are: `PUBLIC`, `SNA`. The field is immutable!

0 commit comments

Comments
 (0)