Page MenuHomeDevCentral

D4191.id10994.diff
No OneTemporary

D4191.id10994.diff

diff --git a/roles/core/init.sls b/roles/core/init.sls
--- a/roles/core/init.sls
+++ b/roles/core/init.sls
@@ -32,3 +32,6 @@
# Depends on software (git)
- .src
+
+ # Depends on software (?)
+ - .backups
diff --git a/terraform/ovh-ops-backups/object_storage.tf b/terraform/ovh-ops-backups/object_storage.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/object_storage.tf
@@ -0,0 +1,42 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Public cloud :: ops-backups :: Storage
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Description: Create object storage bucket for backups.
+# Provider: OVH
+# Target: OVH Public Cloud > Nasqueron :: Operations :: Backups
+# -------------------------------------------------------------
+
+resource "ovh_cloud_project_storage" "storage_backups" {
+ service_name = ovh_cloud_project.nasqueron-ops-backups.id
+ name = var.bucket
+ region_name = "eu-west-par"
+
+ # S3 Object Lock requires versioning to be enabled.
+ versioning = {
+ status = "enabled"
+ }
+
+ object_lock {
+ status = "enabled"
+ rule {
+ # Governance mode protects against malicious deletion.
+ # To prune old backups, a separate admin credential with
+ # s3:BypassGovernanceRetention permission must be used.
+ mode = "governance"
+ period = "P90D" # 90 days default retention
+ }
+ }
+
+ tags = {
+ group = "operations"
+ role = "backup"
+ encryption = "client-side"
+ privacy_level = "sensible"
+ }
+
+ lifecycle {
+ prevent_destroy = true
+ }
+}
diff --git a/terraform/ovh-ops-backups/project.tf b/terraform/ovh-ops-backups/project.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/project.tf
@@ -0,0 +1,45 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Public cloud :: ops-backups
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Provider: OVH
+# Target: OVH public cloud
+# -------------------------------------------------------------
+
+# -------------------------------------------------------------
+# Order and create a new public cloud project
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+data "ovh_me" "account" {}
+
+data "ovh_order_cart" "cart" {
+ ovh_subsidiary = data.ovh_me.account.ovh_subsidiary
+}
+
+data "ovh_order_cart_product_plan" "cart_product_plan" {
+ cart_id = data.ovh_order_cart.cart.id
+ price_capacity = "renew"
+ product = "cloud"
+ plan_code = "project.2018"
+}
+
+resource "ovh_cloud_project" "nasqueron-ops-backups" {
+ description = "Nasqueron :: Operations :: Backups"
+ ovh_subsidiary = data.ovh_me.account.ovh_subsidiary
+
+ plan {
+ duration = data.ovh_order_cart_product_plan.cart_product_plan.selected_price.0.duration
+ plan_code = data.ovh_order_cart_product_plan.cart_product_plan.plan_code
+ pricing_mode = data.ovh_order_cart_product_plan.cart_product_plan.selected_price.0.pricing_mode
+
+ configuration {
+ label = "vrack"
+ value = "pn-1250"
+ }
+ }
+
+ lifecycle {
+ prevent_destroy = true
+ }
+}
diff --git a/terraform/ovh-ops-backups/providers.tf b/terraform/ovh-ops-backups/providers.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/providers.tf
@@ -0,0 +1,36 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Providers
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Provider: OVH / Vault / OpenBao
+# Target: complector.nasqueron.drake
+# -------------------------------------------------------------
+
+terraform {
+ required_version = ">= 1.6.0"
+
+ required_providers {
+ ovh = {
+ source = "ovh/ovh"
+ version = ">= 2.19.0"
+ }
+
+ vault = {
+ source = "hashicorp/vault"
+ version = ">= 5.11.0"
+ }
+ }
+}
+
+# -------------------------------------------------------------
+# Providers configuration
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+provider "ovh" {
+ endpoint = "ovh-eu"
+}
+
+provider "vault" {
+ address = "https://172.27.27.7:8200"
+}
diff --git a/terraform/ovh-ops-backups/terraform.tfvars.example b/terraform/ovh-ops-backups/terraform.tfvars.example
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/terraform.tfvars.example
@@ -0,0 +1,11 @@
+backup_clients = {
+ docker-002 = {
+ description = "Restic backup client for docker-002"
+ prefixes = ["docker-002"]
+ }
+
+ db-a-001 = {
+ description = "Restic backup client for db-a-001"
+ prefixes = ["db-a-001"]
+ }
+}
diff --git a/terraform/ovh-ops-backups/users.tf b/terraform/ovh-ops-backups/users.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/users.tf
@@ -0,0 +1,92 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: S3 Users and Policies
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Provider: OVH / Vault / OpenBao
+# Target: complector.nasqueron.drake
+# -------------------------------------------------------------
+
+/*
+locals {
+ region = "EU-WEST-PAR"
+ bucket = "nasqueron-backups-a"
+ endpoint = "s3.${lower(local.region)}.cloud.ovh.net"
+}
+
+resource "ovh_cloud_project_user" "backup_clients" {
+ for_each = var.backup_clients
+
+ service_name = ovh_cloud_project.ops-backups.id
+ description = each.value.description
+ role_name = "objectstore_operator"
+}
+
+resource "ovh_cloud_project_user_s3_credential" "backup_clients" {
+ for_each = var.backup_clients
+
+ service_name = ovh_cloud_project.ops-backups.id
+ user_id = ovh_cloud_project_user.backup_clients[each.key].id
+}
+
+resource "ovh_cloud_project_user_s3_policy" "backup_clients" {
+ for_each = var.backup_clients
+
+ service_name = ovh_cloud_project.ops-backups.id
+ user_id = ovh_cloud_project_user.backup_clients[each.key].id
+
+ policy = jsonencode({
+ Version = "2012-10-17"
+
+ Statement = [
+ {
+ Sid = "ListOwnPrefixOnly"
+ Effect = "Allow"
+
+ Action = [
+ "s3:ListBucket",
+ "s3:GetBucketLocation",
+ "s3:ListBucketMultipartUploads"
+ ]
+
+ Resource = [
+ "arn:aws:s3:::${local.bucket}"
+ ]
+
+ Condition = {
+ StringLike = {
+ "s3:prefix" = distinct(flatten([
+ for p in each.value.prefixes : [
+ p,
+ "${p}/",
+ "${p}/*"
+ ]
+ ]))
+ }
+ }
+ },
+
+ {
+ Sid = "ReadWriteOwnPrefixOnly"
+ Effect = "Allow"
+
+ Action = [
+ "s3:GetObject",
+ "s3:PutObject",
+ "s3:DeleteObject",
+ "s3:AbortMultipartUpload",
+ "s3:ListMultipartUploadParts"
+ ]
+
+ Resource = distinct(flatten([
+ for p in each.value.prefixes : "arn:aws:s3:::${local.bucket}/${p}/*"
+ ]))
+ }
+ ]
+ })
+
+ depends_on = [
+ ovh_cloud_project.ops-backups
+ ]
+}
+*/
diff --git a/terraform/ovh-ops-backups/variables.tf b/terraform/ovh-ops-backups/variables.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/variables.tf
@@ -0,0 +1,24 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Variables
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Provider: OVH / Vault / OpenBao
+# Target: complector.nasqueron.drake
+# -------------------------------------------------------------
+
+variable bucket {
+ description = "The name of the bucket."
+ type = string
+ default = "nasqueron-backups-amaris"
+}
+
+/*
+variable "backup_clients" {
+ description = "Backup clients configuration."
+ type = map(object({
+ description = string
+ prefixes = list(string)
+ }))
+}
+*/
diff --git a/terraform/ovh-ops-backups/vault.tf b/terraform/ovh-ops-backups/vault.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/vault.tf
@@ -0,0 +1,36 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Store S3 Credentials in OpenBao/Vault
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Provider: OVH / Vault / OpenBao
+# Target: complector.nasqueron.drake
+# -------------------------------------------------------------
+
+/*
+resource "vault_kv_secret_v2" "ovh_s3_credentials" {
+ for_each = var.backup_clients
+
+ mount = "ops"
+ name = "secrets/backups/${each.key}/s3"
+ delete_all_versions = true
+
+ data_json = jsonencode({
+ access_key = ovh_cloud_project_user_s3_credential.backup_clients[each.key].access_key_id
+ secret_key = ovh_cloud_project_user_s3_credential.backup_clients[each.key].secret_access_key
+ repository = "s3:${local.endpoint}/${var.bucket_name}/${each.key}"
+ })
+
+ # We use lifecycle to prevent Terraform from trying to update the secret
+ # if it is manually rotated or changed in Vault after initial creation.
+ # Note: The generated secret_access_key from OVH will still be present in
+ # the Terraform state file of the `ovh_cloud_project_user_s3_credential`
+ # resource, as Terraform must store managed resource attributes in state.
+ # Ensure your Terraform state backend is strictly encrypted and access-controlled.
+ lifecycle {
+ ignore_changes = [
+ data_json,
+ ]
+ }
+}
+*/

File Metadata

Mime Type
text/plain
Expires
Tue, Aug 25, 04:33 (22 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4033692
Default Alt Text
D4191.id10994.diff (9 KB)

Event Timeline