professional-service/scripts/README.md
Michael Sodan db959fcb05
All checks were successful
Default CI / Check for Open TODOs (pull_request) Successful in 52s
Default CI / Secret Scanner (TruffleHog) (pull_request) Successful in 59s
Default CI / Pre-Commit Hooks (pull_request) Successful in 2m22s
example(scripts): S3 object storage SSE-C automation script
2026-05-20 11:33:53 +00:00

14 KiB

Scripts

Helper scripts for working with STACKIT services.

Warning: These scripts can perform destructive or wide-reaching operations against your STACKIT account (e.g. deleting volumes, overwriting kubeconfigs, writing secrets). Review each script and understand what it does before running it.

Overview

Script Purpose Required tools
s3-ssec.sh Upload and Download Files to a STACKIT S3 Bucket (Object Storage) and enable Server Side Encryption with Custom Keys. awscli, python3-awscrt
check-stackit-ip.sh Check whether a given IP address belongs to STACKIT's public IP ranges. stackit, jq, grepcidr
create-kubeconfig-multiple-projects.sh Generate kubeconfig entries for every SKE cluster across one or more STACKIT projects. stackit, yq
delete-unused-volumes.sh Delete all STACKIT volumes whose status is AVAILABLE (i.e. not attached). stackit, yq
list-project-resources.sh Render a Markdown inventory of resources (DNS, SKE, databases, storage, …) for one or more STACKIT projects. stackit, jq
ske-show-versions.sh Print overview of SKE cluster Kubernetes versions and nodepool image versions, marking deprecated versions. stackit (>= 0.59.0), jq, awk
smctl.sh Unified CLI wrapper around HashiCorp Vault for the STACKIT Secret Manager (KV v2), think kubectl for secrets vault, jq
vault-migrate.sh Migrate secrets between two Vault instances using the KV v2 API (supports userpass and LDAP for source). vault, jq

s3-ssec.sh

STACKIT S3 Object Storage SSE-C Automation Script

This script automates secure Server-Side Encryption with Customer-Provided Keys (SSE-C) using the native aws-cli tool against STACKIT Object Storage.

Why This Script Exists

Standard S3 tools (s3cmd, rclone) often fail during SSE-C operations on Linux due to a Binary-to-Text Encoding Mismatch when passing keys via the command line. Furthermore, third-party tools frequently throw false alarms regarding data corruption because the server-side encrypted file's MD5 hash (ETag) no longer matches the local unencrypted file's hash.

The Solution: This script utilizes the official aws-cli along with a binary key file reference (fileb://). This approach bypasses shell encoding issues entirely. The AWS CLI natively understands SSE-C protocols, managing hash verifications and setting all necessary headers automatically.

Prerequisites

AWS CLI installed:

sudo apt install awscli -y  # Debian/Ubuntu
sudo dnf install aws-cli -y # RHEL/CentOS

Permissions: Root access (or appropriate sudo permissions) to store the encryption key safely under /root/ssec.key.

Setup & Configuration

Open the script and fill in your STACKIT credentials and bucket name under the configuration block:

export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY"
BUCKET="s3://your-bucket-name"

Note: On its very first run, the script will automatically generate a cryptographically secure 32-byte binary AES key using openssl and lock down its file permissions (chmod 400).

Usage

Make the script executable:

chmod +x s3-ssec.sh
  1. Uploading a File (Encrypted) To upload and encrypt a local file, pass upload followed by the file path:
./s3-ssec.sh upload /path/to/local/file.txt

The file will be encrypted on the fly by the STACKIT storage backend using your generated key.

  1. Downloading a File (Decrypted) To download and decrypt an object from the bucket, pass download followed by the remote object name:
./s3-ssec.sh download file.txt

The script will fetch the file, provide the required key headers, and save the decrypted file locally as ./file.txt_downloaded.

Security Warning ⚠️ Backup your Key: If you lose the /root/ssec.key file, any data encrypted with it in the bucket cannot be recovered.

Credential Rotation: Never commit the script to public repositories while it contains live AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY strings. Use environment variables or secret managers in production environments.


check-stackit-ip.sh

Looks up the STACKIT public IP ranges (via stackit curl https://iaas.api.eu01.stackit.cloud/v1/networks/public-ip-ranges) and tells you whether a given IP falls inside any of them. Useful to verify whether a public-facing address actually originates from STACKIT.

Exits 0 if the IP is found, 1 otherwise.

Example

# Check a single IP
./check-stackit-ip.sh 45.129.40.1

Sample output:

Fetching STACKIT IP ranges...
Found: 45.129.40.1 is in the range 45.129.40.0/22

create-kubeconfig-multiple-projects.sh

Logs in to STACKIT, iterates over a hard-coded list of project IDs, lists all SKE clusters in each project and writes a 60-day kubeconfig for every cluster into a single kubeconfig file.

Edit the projects=( ... ) array near the bottom of the script before running.

Flags

  • -f, --filepath <path> — destination kubeconfig path (default: $HOME/.kube/config).
  • -h, --help — show usage.

Examples

# Write to default ~/.kube/config (will prompt before overwriting)
./create-kubeconfig-multiple-projects.sh

# Write to a custom location
./create-kubeconfig-multiple-projects.sh -f ~/.kube/stackit-config

delete-unused-volumes.sh

Lists all STACKIT volumes in the currently configured project and deletes those with status AVAILABLE.

Set DRY_RUN=1 at the top of the script to preview the deletions without executing them.

Examples

# Make sure the right project is selected
stackit config set --project-id <project-id>

# Preview what would be deleted (edit DRY_RUN=1 in the script first)
./delete-unused-volumes.sh

# Actually delete unused volumes
./delete-unused-volumes.sh

ske-show-versions.sh

Prints a tabular overview of SKE clusters across the project IDs configured in the projectid variable. For each nodepool it shows the Kubernetes version and the Flatcar machine image version, annotated with supported or the expirationDate for deprecated versions. Rows containing any deprecated version are highlighted in red.

The script enforces a minimum STACKIT CLI version (0.59.0).

Edit the projectid="..." variable (space-separated list) before running.

Example

./ske-show-versions.sh

Sample output:

CLUSTER NAME         SKE VERSION                    NODEPOOL             FLATCAR VERSION                MACHINE TYPE    PROJECT ID
------------         -----------                    --------             ---------------                ------------    ----------
prod-cluster         1.30.4 (supported)             default              4081.2.0 (supported)           c1.4            xxxxxxxx-...
legacy-cluster       1.27.9 (exp. 2026-05-01)       default              3815.2.5 (exp. 2026-03-15)     c1.2            yyyyyyyy-...

Summary:
Total clusters: 2

smctl.sh

Wrapper around the vault CLI to works with secrets in STACKIT Secrets Manager, think about it as kubectl but for secrets.

Required environment variables

Variable Description
SM_USERNAME STACKIT Secret Manager username
SM_PASSWORD STACKIT Secret Manager password
SM_ID KV secrets engine mount path (your secret manager instance ID)

Commands

Command Description
get <vault_path> <key> Print the value of a single key.
get <vault_path> all Print all keys as key: value.
get <vault_path> all-export Print all keys as export key=value (suitable for eval/source).
put <vault_path> <key> [value] Write/update a key. Reads from stdin if no value is given. Existing keys at the path are preserved.
list List all secret paths under the mount.
list <vault_path> List all keys at a specific path.
help Show usage.

Examples

export SM_USERNAME='my-user'
export SM_PASSWORD='my-pass'
export SM_ID='sm-xxxxxxxx'

# List all paths
./smctl.sh list

# List keys at a path
./smctl.sh list postgresql

# Read a single value
./smctl.sh get postgresql db_password

# Dump everything at a path
./smctl.sh get postgresql all

# Load all secrets at a path into the current shell
eval "$(./smctl.sh get postgresql all-export)"

# Write a value directly
./smctl.sh put postgresql db_password 'super-secret'

# Write a value from a file (e.g. a full .env)
./smctl.sh put terraform secret-env < .env

list-project-resources.sh

Iterates over the listable STACKIT services (DNS, Git, Load Balancers, SKE etc.) and prints a Markdown report containing one section per project with a table per resource type. Intended to be redirected into a .md file.

Project IDs are passed as arguments — at least one is required.

Example

# Single project
./list-project-resources.sh xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx > project-inventory.md

# Multiple projects in one report
./list-project-resources.sh \
  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
  yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy \
  > inventory.md

Sample output (excerpt):

## Project: my-prod-project (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)

**SKE Clusters:**
|name|status|...|
|---|---|---|
|prod-cluster|HEALTHY|...|

**Public IPs:**
N/A

last update: Thu, 16-Apr-2026 14:42:11 CEST

vault-migrate.sh

Migrates secrets between two KV v2-compatible secret backends, typically from a HashiCorp Vault instance into STACKIT Secrets Manager, or from one STACKIT Secrets Manager instance to another (both expose the Vault KV v2 API). Source authentication can be userpass or ldap (LDAP triggers an interactive password prompt); the target always uses userpass. Recursively walks all paths under the source mount unless MIGRATE_PATHS is set.

Flags

  • -d, --dry-run — show what would be migrated without writing.
  • -v, --verbose — verbose progress output.
  • -s, --skip-existing — skip secrets that already exist in the target.
  • --debug — debug output (implies --verbose).
  • -h, --help — show usage.

Required environment variables

Variable Description
SOURCE_VAULT_ADDR Source Vault address (e.g. https://vault.example.com).
SOURCE_SM_ID Source KV mount path.
SOURCE_AUTH_METHOD userpass (default) or ldap.
SOURCE_SM_USERNAME Source username — required when SOURCE_AUTH_METHOD=userpass.
SOURCE_SM_PASSWORD Source password — required when SOURCE_AUTH_METHOD=userpass.
SOURCE_LDAP_USERNAME LDAP username — required when SOURCE_AUTH_METHOD=ldap.
TARGET_VAULT_ADDR Target Vault address.
TARGET_SM_USERNAME Target Vault username (always userpass).
TARGET_SM_PASSWORD Target Vault password.
TARGET_SM_ID Target KV mount path.
MIGRATE_PATHS Optional space-separated list of paths to migrate (default: all).

Examples

# Common target setup
export TARGET_VAULT_ADDR="https://prod.sm.eu01.stackit.cloud"
export TARGET_SM_USERNAME="target-user"
export TARGET_SM_PASSWORD='<your-target-password>'
export TARGET_SM_ID="sm-target-xxxx"

# 1) Dry run — migrate everything from a userpass source
export SOURCE_VAULT_ADDR="https://old.vault.example.com"
export SOURCE_SM_ID="sm-source-xxxx"
export SOURCE_AUTH_METHOD="userpass"
export SOURCE_SM_USERNAME="source-user"
export SOURCE_SM_PASSWORD='<your-source-password>'
./vault-migrate.sh --dry-run --verbose

# 2) Migrate from an LDAP source (will prompt for password)
export SOURCE_AUTH_METHOD="ldap"
export SOURCE_LDAP_USERNAME="myuser"
./vault-migrate.sh

# 3) Migrate only selected paths, skipping ones that already exist
export MIGRATE_PATHS="postgresql redis terraform"
./vault-migrate.sh --skip-existing --verbose