Skip to content

Commit 26b4ec1

Browse files
authored
Add Launchpad (#2)
Signed-off-by: Roman Schwarz <rs@cloudeteer.de>
1 parent 8f92a62 commit 26b4ec1

File tree

3 files changed

+254
-0
lines changed

3 files changed

+254
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: prod-stackit-terraform-10-launchpad
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
terraform-force-unlock:
7+
default: false
8+
description: Terraform force unlock
9+
required: false
10+
type: boolean
11+
terraform-force-unlock-id:
12+
description: Terraform LOCK_ID
13+
required: false
14+
type: string
15+
pull_request:
16+
paths:
17+
- prod-stackit/terraform/10_launchpad/**
18+
- .github/workflows/prod-stackit-terraform-10-launchpad.yaml
19+
20+
permissions:
21+
contents: read
22+
id-token: write
23+
24+
jobs:
25+
terraform:
26+
name: Terraform
27+
uses: cloudeteer/iac-deployment-framework/.github/workflows/terraform-deploy-stackit.yaml@wip/stackit
28+
with:
29+
directory: prod-stackit/terraform/10_launchpad
30+
terraform-force-unlock-id: ${{ github.event_name == 'workflow_dispatch' && inputs.terraform-force-unlock == true && inputs.terraform-force-unlock-id }}
31+
terraform-force-unlock: ${{ github.event_name == 'workflow_dispatch' && inputs.terraform-force-unlock == true && inputs.terraform-force-unlock }}
32+
secrets:
33+
stackit_service_account_key: ${{ secrets.CDT_LAUNCHPAD_STACKIT_SERVICE_ACCOUNT_KEY }}
34+
backend_s3_secret_key: ${{ secrets.CDT_LAUNCHPAD_STACKIT_BACKEND_SECRET_ACCESS_KEY }}
35+
backend_s3_access_key: ${{ secrets.CDT_LAUNCHPAD_STACKIT_BACKEND_ACCESS_KEY }}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Launchpad
2+
3+
This document details the initial setup process for the Launchpad on StackIT Cloud.
4+
5+
## 1. Launchpad Service Account
6+
7+
### Authentication
8+
9+
We first logged in with a personal user account that had **Organization Owner** rights.
10+
11+
```console
12+
$ stackit auth login
13+
Successfully logged into STACKIT CLI.
14+
```
15+
16+
We set the organization ID statically because, unfortunately, the CLI wasn't feeling cooperative.
17+
18+
```console
19+
$ STACKIT_ORGANIZATION_ID=6f0a04e7-8d5f-42a5-b1b3-89b8532126db
20+
```
21+
22+
To avoid missing crucial details in CLI output, we switched to json format:
23+
24+
```console
25+
$ stackit config set --output-format json
26+
```
27+
28+
### Creating the StackIT Project
29+
30+
The launchpad project was created under our organization:
31+
32+
```console
33+
$ stackit project create --name launchpad --parent-id "$STACKIT_ORGANIZATION_ID"
34+
Are you sure you want to create a project under the parent with ID "6f0a04e7-8d5f-42a5-b1b3-89b8532126db"? [y/N] y
35+
{
36+
"containerId": "launchpad-MyKfrt1",
37+
"creationTime": "2025-03-05T19:45:07.325899101Z",
38+
"labels": {},
39+
"lifecycleState": "CREATING",
40+
"name": "launchpad",
41+
"parent": {
42+
"containerId": "cloudeteer-gmb-h-iKVDWA1",
43+
"id": "6f0a04e7-8d5f-42a5-b1b3-89b8532126db",
44+
"type": "ORGANIZATION"
45+
},
46+
"projectId": "6b590d5d-f2ab-4584-9556-5ed8bbabb796",
47+
"updateTime": "2025-03-05T19:45:07.325899101Z"
48+
}
49+
```
50+
51+
For convenience, we set the project ID as a configuration parameter:
52+
53+
```console
54+
$ stackit config set --project-id 6b590d5d-f2ab-4584-9556-5ed8bbabb796
55+
```
56+
57+
### Creating and Configuring the Service Account
58+
59+
A Service Account with **Organization Owner** permissions was created:
60+
61+
```console
62+
$ stackit service-account create --name launchpad
63+
Are you sure you want to create a service account for project "launchpad"? [y/N] y
64+
{
65+
"email": "launchpad-z3sy221@sa.stackit.cloud",
66+
"id": "3e57ce0e-d7f6-48b8-865a-1336e547dde4",
67+
"internal": false,
68+
"projectId": "6b590d5d-f2ab-4584-9556-5ed8bbabb796"
69+
}
70+
```
71+
72+
The generated email was saved for later:
73+
74+
```console
75+
$ STACKIT_SERVICE_ACCOUNT_EMAIL=launchpad-z3sy221@sa.stackit.cloud
76+
```
77+
78+
We then granted Organization Owner privileges to the Service Account:
79+
80+
```console
81+
$ stackit organization member add "$STACKIT_SERVICE_ACCOUNT_EMAIL" \
82+
--organization-id "$STACKIT_ORGANIZATION_ID" \
83+
--role organization.owner
84+
Are you sure you want to add the organization.owner role to launchpad-z3sy221@sa.stackit.cloud on organization with ID "6f0a04e7-8d5f-42a5-b1b3-89b8532126db"? [y/N] y
85+
Member added
86+
```
87+
88+
### Generating a Service Account Key
89+
90+
A key was generated and securely stored as a GitHub secret:
91+
92+
```console
93+
$ stackit service-account key create --email "$STACKIT_SERVICE_ACCOUNT_EMAIL" |
94+
gh secret set CDT_LAUNCHPAD_STACKIT_SERVICE_ACCOUNT_KEY
95+
Are you sure you want to create a key for service account launchpad-z3sy221@sa.stackit.cloud? The key will be valid until deleted [y/N] y
96+
Created key for service account launchpad-z3sy221@sa.stackit.cloud with ID "a93c1c11-7710-49bf-b235-4d6b3aa1d708"
97+
✓ Set Actions secret CDT_LAUNCHPAD_STACKIT_SERVICE_ACCOUNT_KEY for cloudeteer/playground-stackit
98+
```
99+
100+
## 2. Terraform Remote State Backend
101+
102+
### Enabling Object Storage
103+
104+
To store Terraform remote state, we needed an S3-compatible Object Store. Initially, we attempted to create a storage bucket:
105+
106+
```console
107+
$ stackit object-storage bucket create launchpad
108+
Are you sure you want to create bucket "launchpad"? (This cannot be undone) [y/N] y
109+
Error: This service isn't enabled for the current project.
110+
111+
To enable it, run:
112+
$ stackit object-storage enable
113+
```
114+
115+
So, we enabled the Object Storage service:
116+
117+
```console
118+
$ stackit object-storage enable
119+
Are you sure you want to enable Object Storage for project "launchpad"? [y/N] y
120+
Enabled Object Storage for project "launchpad"
121+
```
122+
123+
Once enabled, we successfully created the bucket:
124+
125+
```console
126+
$ stackit object-storage bucket create launchpad
127+
Are you sure you want to create bucket "launchpad"? (This cannot be undone) [y/N] y
128+
Creating bucket ✓
129+
{
130+
"bucket": "launchpad",
131+
"project": "6b590d5d-f2ab-4584-9556-5ed8bbabb796"
132+
}
133+
```
134+
135+
### Creating Object Storage Credentials
136+
137+
Since Organization Owner rights were not enough for accessing Object Storage, we had to create an additional access key:
138+
139+
```console
140+
$ stackit object-storage credentials-group create --name launchpad
141+
Are you sure you want to create a credentials group with name "launchpad"? [y/N] y
142+
{
143+
"credentialsGroup": {
144+
"credentialsGroupId": "76555949-9eee-442d-82ad-a3c3481b6f6a",
145+
"displayName": "launchpad",
146+
"urn": "urn:sgws:identity::79244107857127418979:group/credentials-group-49bb71"
147+
},
148+
"project": "6b590d5d-f2ab-4584-9556-5ed8bbabb796"
149+
}
150+
```
151+
152+
Then, we generated credentials and stored them securely as GitHub secrets:
153+
154+
```console
155+
$ temp=$(stackit object-storage credentials create --credentials-group-id 76555949-9eee-442d-82ad-a3c3481b6f6a)
156+
157+
$ echo $temp | jq -r .accessKey | gh secret set CDT_LAUNCHPAD_STACKIT_BACKEND_ACCESS_KEY
158+
✓ Set Actions secret CDT_LAUNCHPAD_STACKIT_BACKEND_ACCESS_KEY for cloudeteer/playground-stackit
159+
160+
$ echo $temp | jq -r .secretAccessKey | gh secret set CDT_LAUNCHPAD_STACKIT_BACKEND_SECRET_ACCESS_KEY
161+
✓ Set Actions secret CDT_LAUNCHPAD_STACKIT_BACKEND_SECRET_ACCESS_KEY for cloudeteer/playground-stackit
162+
163+
$ unset temp
164+
```
165+
166+
## Summary
167+
168+
- Service Account with Organization Owner permissions created.
169+
- Object Storage provisioned for Terraform Remote State.
170+
- Credentials securely stored as GitHub secrets.
171+
172+
Currently, a Launchpad Virtual Machine for a GitHub private runner is missing, but with StackIT, we may explore this possibility in the coming weeks. 🚀
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
terraform {
2+
required_providers {
3+
stackit = {
4+
source = "stackitcloud/stackit"
5+
version = "0.43.3"
6+
}
7+
}
8+
9+
# Terraform Remote State Backend Configuration
10+
# https://developer.hashicorp.com/terraform/language/backend/s3#configuration
11+
backend "s3" {
12+
bucket = "launchpad"
13+
region = "eu01"
14+
key = "prod-stackid/terraform/10_launchpad/terraform.tfstate"
15+
16+
endpoints = {
17+
s3 = "https://object.storage.eu01.onstackit.cloud"
18+
}
19+
20+
# AWS specific checks must be skipped as they do not work on STACKIT
21+
skip_credentials_validation = true
22+
skip_region_validation = true
23+
skip_requesting_account_id = true
24+
skip_s3_checksum = true
25+
26+
# Credentials supplied by environment variables
27+
# access_key = null # AWS_ACCESS_KEY_ID
28+
# secret_key = null # AWS_SECRET_ACCESS_KEY
29+
}
30+
}
31+
32+
provider "stackit" {
33+
34+
# Region will be used as the default location for regional services.
35+
# Not all services require a region, some are global
36+
region = "eu01"
37+
38+
# NOTE: There are no environment variables available for the parameters service_account_key and private_key.
39+
# Alternatively, we use TF_VAR_service_account_key and TF_VAR_private_key.
40+
41+
# Service account key used for authentication
42+
service_account_key = var.service_account_key
43+
44+
# Private RSA key used for authentication, relevant for the key flow.
45+
# It takes precedence over the private key that is included in the service account key.
46+
private_key = var.private_key
47+
}

0 commit comments

Comments
 (0)