Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F48388480
D4206.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
16 KB
Referenced Files
None
Subscribers
None
D4206.diff
View Options
diff --git a/terraform/ovh-ops-backups/locals.tf b/terraform/ovh-ops-backups/locals.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/locals.tf
@@ -0,0 +1,130 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Public cloud :: ops-backups :: Storage
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Description: Create object storage bucket for backups.
+# Provider: OVH + Vault / OpenBao
+# Target: OVH Public Cloud > Nasqueron :: Operations :: Backups
+# complector.nasqueron.drake (Vault)
+# -------------------------------------------------------------
+
+locals {
+ default_tags = {
+ group = "operations"
+ role = "backup"
+ encryption = "client-side"
+ privacy_level = "sensible"
+ }
+
+ backup_containers = {
+ amaris = {
+ container_name = "nasqueron-backups-amaris"
+ purpose = "Main backup container"
+
+ tags = local.default_tags
+
+ # Each server should get access
+ # For databases servers, prefixes are by cluster.
+ clients = {
+ windriver = {
+ prefixes = [
+ "windriver",
+ ]
+ }
+
+ db-a-001 = {
+ prefixes = [
+ "db-a",
+ ]
+ }
+
+ db-b-001 = {
+ prefixes = [
+ "db-b",
+ ]
+ }
+
+ dns-001 = {
+ prefixes = [
+ "dns-001",
+ ]
+ }
+
+ docker-002 = {
+ prefixes = [
+ "docker-002",
+ ]
+ }
+
+ dwellers = {
+ prefixes = [
+ "dwellers",
+ ]
+ }
+
+ hervil = {
+ prefixes = [
+ "hervil",
+ ]
+ }
+
+ router-001 = {
+ prefixes = [
+ "router-intranought",
+ ]
+ }
+
+ router-002 = {
+ prefixes = [
+ "router-intranought",
+ ]
+ }
+
+ router-003 = {
+ prefixes = [
+ "router-intranought",
+ ]
+ }
+
+ web-001 = {
+ prefixes = [
+ "web-001",
+ ]
+ }
+ }
+ }
+
+ darak = {
+ container_name = "nasqueron-backups-darak"
+ purpose = "Dereckson backups"
+
+ tags = merge(local.default_tags, {
+ group = "user-dereckson"
+ })
+
+ clients = {
+ windriver = {
+ prefixes = [
+ "windriver-home",
+ ]
+ }
+ }
+ }
+
+ vakor = {
+ container_name = "nasqueron-backups-vakor"
+ purpose = "Vault backups"
+
+ tags = local.default_tags
+
+ clients = {
+ complector = {
+ prefixes = [
+ "complector",
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/terraform/ovh-ops-backups/modules/object_storage_project_user/main.tf b/terraform/ovh-ops-backups/modules/object_storage_project_user/main.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/modules/object_storage_project_user/main.tf
@@ -0,0 +1,115 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Public cloud :: ops-backups :: Project user
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Description: Create user with access to object storage container
+# for backups in specified prefix.
+# Provider: OVH
+# -------------------------------------------------------------
+
+# -------------------------------------------------------------
+# Project user
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+resource "ovh_cloud_project_user" "user" {
+ service_name = var.service_name
+ description = var.description
+}
+
+resource "ovh_cloud_project_user_s3_credential" "s3_credentials" {
+ service_name = var.service_name
+ user_id = ovh_cloud_project_user.user.id
+}
+
+# -------------------------------------------------------------
+# Policy for the user
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+locals {
+ # Normalize prefixes: remove leading/trailing slashes, ignore empty values.
+ normalized_prefixes = distinct([
+ for p in var.prefixes : trim(p, "/")
+ if trim(p, "/") != ""
+ ])
+
+ # Values accepted by the s3:prefix condition.
+ #
+ # We allow:
+ # prefix
+ # prefix/
+ # prefix/*
+ #
+ # This is useful because S3 clients may list with different prefix forms.
+ list_prefixes = distinct(flatten([
+ for p in local.normalized_prefixes : [
+ p,
+ "${p}/",
+ "${p}/*"
+ ]
+ ]))
+
+ # Object-level resources.
+ #
+ # Allow both:
+ # arn:aws:s3:::container/prefix
+ # arn:aws:s3:::container/prefix/*
+ #
+ # The first one is not always required, but it makes the policy more robust
+ # if a client ever writes an object exactly named after the prefix.
+ object_resources = distinct(flatten([
+ for p in local.normalized_prefixes : [
+ "arn:aws:s3:::${var.container_name}/${p}",
+ "arn:aws:s3:::${var.container_name}/${p}/*"
+ ]
+ ]))
+
+ policy = jsonencode({
+ Version = "2012-10-17"
+
+ Statement = [
+ {
+ Sid = "ListOwnPrefixOnly"
+ Effect = "Allow"
+
+ Action = [
+ "s3:ListBucket",
+ "s3:GetBucketLocation",
+ "s3:ListBucketMultipartUploads"
+ ]
+
+ Resource = [
+ "arn:aws:s3:::${var.container_name}"
+ ]
+
+ Condition = {
+ StringLike = {
+ "s3:prefix" = local.list_prefixes
+ }
+ }
+ },
+
+ {
+ Sid = "ReadWriteOwnPrefixOnly"
+ Effect = "Allow"
+
+ Action = [
+ "s3:GetObject",
+ "s3:PutObject",
+ "s3:DeleteObject",
+ "s3:AbortMultipartUpload",
+ "s3:ListMultipartUploadParts"
+ ]
+
+ Resource = local.object_resources
+ }
+ ]
+ })
+}
+
+resource "ovh_cloud_project_user_s3_policy" "policy" {
+ service_name = var.service_name
+ user_id = ovh_cloud_project_user.user.id
+
+ policy = local.policy
+}
diff --git a/terraform/ovh-ops-backups/modules/object_storage_project_user/outputs.tf b/terraform/ovh-ops-backups/modules/object_storage_project_user/outputs.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/modules/object_storage_project_user/outputs.tf
@@ -0,0 +1,56 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Public cloud :: ops-backups :: Project user
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Description: Create user with access to object storage container
+# for backups in specified prefix.
+# Provider: OVH
+# -------------------------------------------------------------
+
+# -------------------------------------------------------------
+# Variables to describe the user in other systems (e.g. Vault)
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+output "account_name" {
+ description = "Logical account name."
+ value = var.account_name
+}
+
+output "container_name" {
+ description = "S3 container name."
+ value = var.container_name
+}
+
+output "prefixes" {
+ description = "Allowed S3 prefixes."
+ value = local.normalized_prefixes
+}
+
+# -------------------------------------------------------------
+# Variables for the module resources
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+output "user" {
+ description = "OVH user"
+ value = {
+ id = ovh_cloud_project_user.user.id
+ openstack_rc = ovh_cloud_project_user.user.openstack_rc
+ username = ovh_cloud_project_user.user.username
+ }
+}
+
+output "user_password" {
+ description = "OVH user password"
+ sensitive = true
+ value = ovh_cloud_project_user.user.password
+}
+
+output "s3_credentials" {
+ description = "S3 credentials"
+ sensitive = true
+ value = {
+ access_key = ovh_cloud_project_user_s3_credential.s3_credentials.access_key_id
+ secret_key = ovh_cloud_project_user_s3_credential.s3_credentials.secret_access_key
+ }
+}
diff --git a/terraform/ovh-ops-backups/modules/object_storage_project_user/providers.tf b/terraform/ovh-ops-backups/modules/object_storage_project_user/providers.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/modules/object_storage_project_user/providers.tf
@@ -0,0 +1,23 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Public cloud :: ops-backups :: Project user
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Description: Create user with access to object storage container
+# for backups in specified prefix.
+# Provider: OVH
+# -------------------------------------------------------------
+
+terraform {
+ // Per `for` expression
+ required_version = ">= 0.12.0"
+
+ required_providers {
+ ovh = {
+ source = "ovh/ovh"
+
+ # For object lock support
+ version = ">= 2.11.0"
+ }
+ }
+}
diff --git a/terraform/ovh-ops-backups/modules/object_storage_project_user/variables.tf b/terraform/ovh-ops-backups/modules/object_storage_project_user/variables.tf
new file mode 100644
--- /dev/null
+++ b/terraform/ovh-ops-backups/modules/object_storage_project_user/variables.tf
@@ -0,0 +1,39 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Public cloud :: ops-backups :: Project user
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Description: Create user with access to object storage container
+# for backups in specified prefix.
+# Provider: OVH
+# -------------------------------------------------------------
+
+variable "service_name" {
+ description = "OVH Cloud Project service name."
+ type = string
+}
+
+variable "account_name" {
+ description = "Logical account name, for example user-bak-amaris-windriver."
+ type = string
+}
+
+variable "description" {
+ description = "Description of the OVH user."
+ type = string
+}
+
+variable "container_name" {
+ description = "Object storage container (S3 bucket) name."
+ type = string
+}
+
+variable "prefixes" {
+ description = "S3 key prefixes this account may access."
+ type = list(string)
+
+ validation {
+ condition = length(var.prefixes) > 0
+ error_message = "At least one S3 prefix is required."
+ }
+}
diff --git a/terraform/ovh-ops-backups/object_storage.tf b/terraform/ovh-ops-backups/object_storage.tf
--- a/terraform/ovh-ops-backups/object_storage.tf
+++ b/terraform/ovh-ops-backups/object_storage.tf
@@ -8,40 +8,6 @@
# Target: OVH Public Cloud > Nasqueron :: Operations :: Backups
# -------------------------------------------------------------
-locals {
- default_tags = {
- group = "operations"
- role = "backup"
- encryption = "client-side"
- privacy_level = "sensible"
- }
-
- backup_containers = {
- amaris = {
- container_name = "nasqueron-backups-amaris"
- purpose = "Main backup container"
-
- tags = local.default_tags
- }
-
- darak = {
- container_name = "nasqueron-backups-darak"
- purpose = "Dereckson backups"
-
- tags = merge(local.default_tags, {
- group = "user-dereckson"
- })
- }
-
- vakor = {
- container_name = "nasqueron-backups-vakor"
- purpose = "Vault backups"
-
- tags = local.default_tags
- }
- }
-}
-
module "backup" {
source = "./modules/object_storage_container"
for_each = local.backup_containers
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,52 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: S3 Users and Policies
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Provider: OVH + Vault / OpenBao
+# Target: OVH Public Cloud > Nasqueron :: Operations :: Backups
+# complector.nasqueron.drake
+# -------------------------------------------------------------
+
+# -------------------------------------------------------------
+# Flattened backup containers and clients into client accounts
+#
+# Allow to create S3 users like user-bak-<container>-<client>
+# e.g. "user-bak-amaris-windriver"
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+locals {
+ backup_client_accounts = {
+ for account in flatten([
+ for container_key, container in local.backup_containers : [
+ for client_key, client in container.clients : {
+ key = "${container_key}-${client_key}"
+
+ container_key = container_key
+ container_name = container.container_name
+
+ client_key = client_key
+ prefixes = client.prefixes
+
+ account_name = "user-bak-${container_key}-${client_key}"
+ description = "Service account for ${client_key} on ${container.container_name}"
+ }
+ ]
+ ]) : account.key => account
+ }
+}
+
+# -------------------------------------------------------------
+# Create user accounts and apply prefixes policies
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+module "backup_client_accounts" {
+ source = "./modules/object_storage_project_user"
+ for_each = local.backup_client_accounts
+
+ service_name = ovh_cloud_project.nasqueron-ops-backups.id
+ account_name = each.value.account_name
+ description = each.value.description
+ container_name = each.value.container_name
+ prefixes = each.value.prefixes
+}
diff --git a/terraform/ovh-ops-backups/variables.tf b/terraform/ovh-ops-backups/variables.tf
deleted file mode 100644
--- a/terraform/ovh-ops-backups/variables.tf
+++ /dev/null
@@ -1,13 +0,0 @@
-# -------------------------------------------------------------
-# Terraform :: OVH :: Variables
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# Project: Nasqueron
-# License: BSD-2-Clause
-# Provider: OVH / Vault
-# -------------------------------------------------------------
-
-variable "bucket" {
- description = "The name of the bucket."
- type = string
- default = "nasqueron-backups-amaris"
-}
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,44 @@
+# -------------------------------------------------------------
+# Terraform :: OVH :: Store S3 Credentials in OpenBao/Vault
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# Provider: OVH / Vault / OpenBao
+# Target: complector.nasqueron.drake
+# -------------------------------------------------------------
+
+locals {
+ s3_endpoint = "https://s3.eu-west-par.io.cloud.ovh.net"
+}
+
+resource "vault_kv_secret_v2" "ovh_s3_credentials" {
+ for_each = local.backup_client_accounts
+
+ mount = "ops"
+ name = "secrets/backups/ovh/s3/${each.key}"
+
+ data_json = jsonencode({
+ access_key = module.backup_client_accounts[each.key].s3_credentials.access_key
+ secret_key = module.backup_client_accounts[each.key].s3_credentials.secret_key
+ })
+
+ custom_metadata {
+ data = {
+ container_name = each.value.container_name
+ endpoint = "s3:${local.s3_endpoint}/${each.value.container_name}/"
+ prefixes = join(", ", each.value.prefixes)
+ }
+ }
+
+ # 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
Details
Attached
Mime Type
text/plain
Expires
Mon, Sep 7, 02:05 (22 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4067792
Default Alt Text
D4206.diff (16 KB)
Attached To
Mode
D4206: Create restic users and generate S3 credentials
Attached
Detach File
Event Timeline
Log In to Comment