mirror of
https://github.com/outbackdingo/homelab-v.git
synced 2026-08-25 14:53:19 +00:00
feat: create GCS bucket to store remote state
feat: Add gcloud tofu code to automatically create gcs buckets to use as remote backend. Also setup workload identity federation, and store it to infisical, to use it in github actions. Signed-off-by: Karteek <[email protected]> feat(tofu): modularise gcs-state Create a Google Cloud Storage (GCS) bucket and store the state for doing it in the bucket itself Signed-off-by: Vegard Hagen <[email protected]> feat(wif): enable workload identify federation Signed-off-by: Vegard Hagen <[email protected]>
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# Google Cloud Storage
|
||||
|
||||
Example configuration for creating [Google Cloud Storage](https://cloud.google.com/storage) bucket for storing an
|
||||
encrypted Tofu state in.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Google Cloud Platform project with an active Billing Account.
|
||||
|
||||
## Getting started
|
||||
|
||||
1. Install `gcloud` — Instructions: https://cloud.google.com/sdk/docs/install-sdk
|
||||
2. Run `gcloud init`
|
||||
3. Authenticate using `gcloud auth application-default login`
|
||||
|
||||
Before initialising, disable the GCS backend in `providers.tofu` (by e.g. commenting it out) since we can't store the
|
||||
state in something that doesn't exist yet.
|
||||
|
||||
After the initial `tofy apply` to create the bucket, the state can be migrated by adding
|
||||
|
||||
```terraform
|
||||
backend "gcs" {
|
||||
bucket = var.bucket_name
|
||||
prefix = var.state_prefix
|
||||
}
|
||||
```
|
||||
|
||||
back in and running
|
||||
|
||||
```shell
|
||||
tofu init -migrate-state
|
||||
```
|
||||
|
||||
to migrate the state to the remote GCS bucket.
|
||||
@@ -0,0 +1,44 @@
|
||||
resource "google_service_account" "tofu_dev_sa" {
|
||||
account_id = "tofu-dev-sa"
|
||||
display_name = "Tofu Dev Service Account"
|
||||
description = "Service account for development tasks using Tofu"
|
||||
}
|
||||
|
||||
# Bucket names must be globally unique.
|
||||
resource "google_storage_bucket" "tofu_remote_state" {
|
||||
name = var.bucket_name
|
||||
location = var.gcp.region
|
||||
storage_class = "STANDARD"
|
||||
|
||||
uniform_bucket_level_access = true
|
||||
public_access_prevention = "enforced"
|
||||
|
||||
versioning {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
# `force_destroy = true` must be applied before removing bucket
|
||||
force_destroy = true
|
||||
|
||||
# Add a lifecycle rule to delete noncurrent versions after 90 days
|
||||
lifecycle_rule {
|
||||
action {
|
||||
type = "Delete"
|
||||
}
|
||||
condition {
|
||||
# Delete noncurrent versions older than 90 days
|
||||
age = 30
|
||||
# Keep up to 100 newer versions
|
||||
num_newer_versions = 100
|
||||
# Apply this rule to noncurrent versions
|
||||
with_state = "ARCHIVED"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# This grants the tofu-dev_sa service account administrative permissions over objects in the bucket.
|
||||
resource "google_storage_bucket_iam_member" "tofu_remote_state_object_admin" {
|
||||
bucket = google_storage_bucket.tofu_remote_state.name
|
||||
role = "roles/storage.objectAdmin"
|
||||
member = "serviceAccount:${google_service_account.tofu_dev_sa.email}"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
output "tofu_service_account" {
|
||||
value = {
|
||||
id = google_service_account.tofu_dev_sa.id
|
||||
name = google_service_account.tofu_dev_sa.name
|
||||
email = google_service_account.tofu_dev_sa.email
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
google = {
|
||||
source = "hashicorp/google"
|
||||
version = "~> 6.44.0"
|
||||
}
|
||||
}
|
||||
encryption {
|
||||
key_provider "pbkdf2" "my_passphrase" {
|
||||
passphrase = var.tofu_encryption_passphrase
|
||||
}
|
||||
method "aes_gcm" "my_method" {
|
||||
keys = key_provider.pbkdf2.my_passphrase
|
||||
}
|
||||
state {
|
||||
method = method.aes_gcm.my_method
|
||||
enforced = true
|
||||
}
|
||||
plan {
|
||||
method = method.aes_gcm.my_method
|
||||
enforced = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
variable "bucket_name" {
|
||||
description = "Globally unique name for the GCS bucket"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "gcp" {
|
||||
description = "Google Cloud project ID and region to deploy resources into"
|
||||
type = object({
|
||||
project_id = string,
|
||||
region = string
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
module "gcs" {
|
||||
source = "./gcs"
|
||||
|
||||
gcp = var.gcp
|
||||
bucket_name = var.bucket_name
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
output "tofu_dev_service_account_email" {
|
||||
description = "The email of the service account that GitHub Actions will impersonate. Use this for the GCP_SERVICE_ACCOUNT_EMAIL GitHub secret."
|
||||
value = module.gcs.tofu_service_account.email
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
google = {
|
||||
source = "hashicorp/google"
|
||||
version = "~> 6.44.0"
|
||||
}
|
||||
}
|
||||
encryption {
|
||||
key_provider "pbkdf2" "encryption_passphrase" {
|
||||
passphrase = var.encryption_passphrase
|
||||
}
|
||||
method "aes_gcm" "encryption_method" {
|
||||
keys = key_provider.pbkdf2.encryption_passphrase
|
||||
}
|
||||
state {
|
||||
method = method.aes_gcm.encryption_method
|
||||
enforced = true
|
||||
}
|
||||
plan {
|
||||
method = method.aes_gcm.encryption_method
|
||||
enforced = true
|
||||
}
|
||||
}
|
||||
backend "gcs" {
|
||||
bucket = var.bucket_name
|
||||
prefix = var.state_prefix
|
||||
}
|
||||
}
|
||||
|
||||
provider "google" {
|
||||
project = var.gcp.project_id
|
||||
region = var.gcp.region
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
gcp = {
|
||||
project_id = "homelab-359819",
|
||||
region = "europe-west1"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
variable "encryption_passphrase" {
|
||||
description = "Encryption passphrase for Tofu state encryption"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "gcp" {
|
||||
description = "Google Cloud project ID and region to deploy resources into"
|
||||
type = object({
|
||||
project_id = string,
|
||||
region = string
|
||||
})
|
||||
}
|
||||
|
||||
variable "bucket_name" {
|
||||
description = "Globally unique name for GCS bucket"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "state_prefix" {
|
||||
description = "State prefix in GCS bucket"
|
||||
type = string
|
||||
default = "tofu/gcs-state"
|
||||
}
|
||||
Reference in New Issue
Block a user