Skip to content

Commit 805616f

Browse files
h3adexcgoetz-inovexFyusel
authored
feat(iam): add resource for service_account role assginment (#1265)
* feat(iam): resource for service_account role assignment Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> * review changes Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> * review changes Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> * fixed docs Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> --------- Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> Co-authored-by: cgoetz-inovex <carlo.goetz@inovex.de> Co-authored-by: Alexander Dahmen <alexander.dahmen@inovex.de>
1 parent cc99cdd commit 805616f

13 files changed

+791
-97
lines changed
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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ 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`
4646
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients. All letters must be lowercased.
4747

docs/resources/authorization_organization_role_assignment.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ 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`
3939
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients. All letters must be lowercased.
4040

docs/resources/authorization_project_role_assignment.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ 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`
4646
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients. All letters must be lowercased.
4747

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`".
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
data "stackit_service_accounts" "ske_sa_suffix" {
2+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
3+
email_suffix = "@ske.sa.stackit.cloud"
4+
}
5+
6+
resource "stackit_service_account" "iam" {
7+
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
8+
name = "kms"
9+
}
10+
11+
resource "stackit_authorization_project_role_assignment" "pr_sa" {
12+
resource_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
13+
role = "kms.admin"
14+
subject = stackit_service_account.iam.email
15+
}
16+
17+
// Assign the Act-As permissions to the previously created ServiceAccount.
18+
// The SKE ServiceAccount is now authorized to access KMS upon the behalf of stackit_service_account.iam
19+
resource "stackit_authorization_service_account_role_assignment" "sa" {
20+
resource_id = stackit_service_account.iam.service_account_id
21+
role = "user"
22+
subject = data.stackit_service_accounts.ske_sa_suffix.items.0.email
23+
}
24+
25+
# Only use the import statement, if you want to import an existing service account assignment
26+
import {
27+
to = stackit_authorization_service_account_assignment.sa
28+
id = "${var.resource_id},${var.service_account_assignment_role},${var.service_account_assignment_subject}"
29+
}

0 commit comments

Comments
 (0)