Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 187 additions & 0 deletions docs/guides/setting_up_encrypted_volumes_for_ske.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
---
page_title: "Setting up Encrypted Volumes for STACKIT Kubernetes Engine (SKE)"
---

# Setting up Encrypted Volumes for STACKIT Kubernetes Engine (SKE)

~> 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.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminder^


## Overview

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.

## Steps

### 1. Configure the SKE Cluster

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.

```hcl
resource "stackit_ske_cluster" "default" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "ske-enc-vol"
kubernetes_version_min = "1.33"

node_pools = [{
name = "standard"
machine_type = "c2i.4"
minimum = 1
maximum = 3
availability_zones = ["eu01-1"]
os_name = "flatcar"
volume_size = 32
}]
}

resource "stackit_ske_kubeconfig" "default" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
cluster_name = stackit_ske_cluster.default.name
refresh = true
}
```


### 2. Identify the Internal SKE Service Account

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.

```hcl
data "stackit_service_accounts" "ske_internal" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_suffix = "@ske.sa.stackit.cloud"

depends_on = [stackit_ske_cluster.default]
}
```

### 3. Setup KMS Infrastructure

Define the Keyring and the specific Key that will be used to encrypt the block storage volumes.

```hcl
resource "stackit_kms_keyring" "encryption" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
display_name = "ske-volume-keyring"
}

resource "stackit_kms_key" "volume_key" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
keyring_id = stackit_kms_keyring.encryption.keyring_id
display_name = "volume-encryption-key"
protection = "software"
algorithm = "aes_256_gcm"
purpose = "symmetric_encrypt_decrypt"
}
```

### 4. Configure Identity and Permissions (Act-As)

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.

```hcl
# Create the service account that 'owns' the KMS access
resource "stackit_service_account" "kms_manager" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "volume-encryptor"
}

# Grant the 'kms.admin' role to the manager service-account
resource "stackit_authorization_project_role_assignment" "kms_user" {
// in this case the STACKIT project_id
resource_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
role = "kms.admin"
subject = stackit_service_account.kms_manager.email
}

# Authorize the internal SKE account to impersonate the kms manager service-account (Act-As)
resource "stackit_authorization_service_account_role_assignment" "ske_impersonation" {
resource_id = stackit_service_account.kms_manager.service_account_id
role = "user"
subject = data.stackit_service_accounts.ske_internal.items[0].email
}
```

### 5. Create the Encrypted Storage Class in Kubernetes

Define the `kubernetes_storage_class`. We pass the IDs of the KMS resources and the email of our manager service account into the parameters.

```hcl
resource "kubernetes_storage_class_v1" "encrypted_premium" {
metadata {
name = "stackit-encrypted-premium"
}

storage_provisioner = "block-storage.csi.stackit.cloud"
reclaim_policy = "Delete"
allow_volume_expansion = true
volume_binding_mode = "WaitForFirstConsumer"

parameters = {
type = "storage_premium_perf6"
encrypted = "true"
kmsKeyID = stackit_kms_key.volume_key.key_id
kmsKeyringID = stackit_kms_keyring.encryption.keyring_id
kmsProjectID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
kmsKeyVersion = "1"
kmsServiceAccount = stackit_service_account.kms_manager.email
}

depends_on = [
stackit_authorization_service_account_role_assignment.ske_impersonation,
stackit_authorization_project_role_assignment.kms_user
]
}
```

### 6. Verify with a Persistent Volume Claim (PVC)

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.

```hcl
resource "kubernetes_persistent_volume_claim_v1" "test_pvc" {
metadata {
name = "test-encryption-pvc"
}

spec {
access_modes = ["ReadWriteOnce"]

resources {
requests = {
storage = "10Gi"
}
}

storage_class_name = kubernetes_storage_class_v1.encrypted_premium.metadata[0].name
}
}
```

### 7. Create a Pod to Consume the Volume

```hcl
resource "kubernetes_pod_v1" "test_app" {
metadata {
name = "encrypted-volume-test"
}

spec {
container {
image = "nginx:latest"
name = "web-server"

volume_mount {
mount_path = "/usr/share/nginx/html"
name = "data-volume"
}
}

volume {
name = "data-volume"
persistent_volume_claim {
claim_name = "test-encryption-pvc"
}
}
}
}
```
2 changes: 1 addition & 1 deletion docs/resources/authorization_folder_role_assignment.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {

### Required

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {

### Required

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

Expand Down
2 changes: 1 addition & 1 deletion docs/resources/authorization_project_role_assignment.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {

### Required

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

Expand Down
64 changes: 64 additions & 0 deletions docs/resources/authorization_service_account_role_assignment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "stackit_authorization_service_account_role_assignment Resource - stackit"
subcategory: ""
description: |-
Service-account Role Assignment resource schema.
~> 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.
~> 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.
---

# stackit_authorization_service_account_role_assignment (Resource)

Service-account Role Assignment resource schema.

~> **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.

~> 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.

## Example Usage

```terraform
data "stackit_service_accounts" "ske_sa_suffix" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_suffix = "@ske.sa.stackit.cloud"
}

resource "stackit_service_account" "iam" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "kms"
}

resource "stackit_authorization_project_role_assignment" "pr_sa" {
resource_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
role = "kms.admin"
subject = stackit_service_account.iam.email
}

// Assign the Act-As permissions to the previously created ServiceAccount.
// The SKE ServiceAccount is now authorized to access KMS upon the behalf of stackit_service_account.iam
resource "stackit_authorization_service_account_role_assignment" "sa" {
resource_id = stackit_service_account.iam.service_account_id
role = "user"
subject = data.stackit_service_accounts.ske_sa_suffix.items.0.email
}

# Only use the import statement, if you want to import an existing service account assignment
import {
to = stackit_authorization_service_account_assignment.sa
id = "${var.resource_id},${var.service_account_assignment_role},${var.service_account_assignment_subject}"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `resource_id` (String) Service-account Resource to assign the role to.
- `role` (String) Role to be assigned. Available roles can be queried using stackit-cli: `stackit curl https://authorization.api.stackit.cloud/v2/permissions`
- `subject` (String) Identifier of user, service account or client. Usually email address or name in case of clients

### Read-Only

- `id` (String) Terraform's internal resource identifier. It is structured as "`resource_id`,`role`,`subject`".
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
data "stackit_service_accounts" "ske_sa_suffix" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
email_suffix = "@ske.sa.stackit.cloud"
}

resource "stackit_service_account" "iam" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "kms"
}

resource "stackit_authorization_project_role_assignment" "pr_sa" {
resource_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
role = "kms.admin"
subject = stackit_service_account.iam.email
}

// Assign the Act-As permissions to the previously created ServiceAccount.
// The SKE ServiceAccount is now authorized to access KMS upon the behalf of stackit_service_account.iam
resource "stackit_authorization_service_account_role_assignment" "sa" {
resource_id = stackit_service_account.iam.service_account_id
role = "user"
subject = data.stackit_service_accounts.ske_sa_suffix.items.0.email
}

# Only use the import statement, if you want to import an existing service account assignment
import {
to = stackit_authorization_service_account_assignment.sa
id = "${var.resource_id},${var.service_account_assignment_role},${var.service_account_assignment_subject}"
}
Loading
Loading