diff --git a/terraform/modules/buckets/.gitignore b/terraform/modules/buckets/.gitignore new file mode 100644 index 0000000..df50a6a --- /dev/null +++ b/terraform/modules/buckets/.gitignore @@ -0,0 +1,7 @@ +*.swp +.terraform* +main.tfvars +terraform.tfstate* +plan.tfplan +errored.tfstate +!.terraform-docs.yml diff --git a/terraform/modules/buckets/.terraform-docs.yml b/terraform/modules/buckets/.terraform-docs.yml new file mode 100644 index 0000000..73058d1 --- /dev/null +++ b/terraform/modules/buckets/.terraform-docs.yml @@ -0,0 +1,47 @@ +formatter: "md table" # this is required + +version: "" + +header-from: docs/header.md +footer-from: "" + +recursive: + enabled: false + path: modules + +sections: + hide: [] + show: [] + +content: "" + +output: + file: "" + mode: inject + template: |- + + {{ .Content }} + + +output-values: + enabled: false + from: "" + +sort: + enabled: true + by: name + +settings: + anchor: true + color: true + default: true + description: false + escape: true + hide-empty: false + html: true + indent: 2 + lockfile: true + read-comments: true + required: true + sensitive: true + type: true diff --git a/terraform/modules/buckets/README.md b/terraform/modules/buckets/README.md new file mode 100644 index 0000000..227202a --- /dev/null +++ b/terraform/modules/buckets/README.md @@ -0,0 +1,91 @@ + +## Description du module + +Ce module a pour but de gérer les applications et leur ressources associées dans le cloud public Scaleway. + +## Fonctionnement du module + +- Ce module prend en charge la gestion des ressources suivantes : + - Les applications, groupes et policies de l'IAM Scaleway. + - Les buckets S3 et de leur policy associée. + - Les file d'attente de type SQS et leurs identifiants associés. + +### Fonctionnement bucket S3 + +#### Pré-requis + +- Une liste de bucket est déclarée au sein de l'application. +- Pour déclarer des règles de cycle de vie (lifecycle\_rules), au moins expiration\_days ou le couple transition\_days et transition\_sc doivent être déclarés. + +#### Fonctionnement + +- Pour chaque bucket de la liste buckets\_list, une resource va être déclarée. Dans cette ressource, une lifecycle\_rule va être déclarée pour chaque membre de la liste de lifecycle\_rule. +- Pour chaque bucket de la liste buckets\_list, une policy est attachée et contient 3 sections : + - Une section pour autoriser l'application principale à accéder au bucket. + - Une section pour donner accès aux user\_id et application\_id des administrateurs. + - Une section pour donner accès à d'autres user\_id pour une application tierce. + +### Fonctionnement SQS + +#### Pré-requis + +- Avoir activé le module SQS dans l'interface Scaleway -> Messaging. +- Une liste de queue est déclarée au sein de l'application. + +#### Informations + +- On utilise une resource de type scaleway\_mnq\_sqs\_credentials.admin\_creds par projet. En effet, en lui donnant uniquement le droit "can\_manage", elle peut créer, supprimer et modifier des queues mais pas accéder à leur contenu. +- En parallèle, on créé un jeu d'identifiant par application et par queue qui ne disposent que des droits de publication/réception. + +## Requirements + +| Name | Version | +|------|---------| +| [scaleway](#requirement\_scaleway) | >= 2.35.0 | + +## Providers + +| Name | Version | +|------|---------| +| [scaleway](#provider\_scaleway) | >= 2.35.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [scaleway_iam_api_key.keys](https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/resources/iam_api_key) | resource | +| [scaleway_iam_application.apps](https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/resources/iam_application) | resource | +| [scaleway_iam_group.groups](https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/resources/iam_group) | resource | +| [scaleway_iam_policy.group_policies](https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/resources/iam_policy) | resource | +| [scaleway_object_bucket.s3_buckets](https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/resources/object_bucket) | resource | +| [scaleway_object_bucket_policy.s3_policies](https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/resources/object_bucket_policy) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [admins\_user\_id](#input\_admins\_user\_id) | List of s3 admin user's ID | `list(string)` | `[]` | no | +| [app\_desc](#input\_app\_desc) | Application's description | `string` | `""` | no | +| [app\_name](#input\_app\_name) | Name of the application | `string` | `"changeme"` | no | +| [app\_tags](#input\_app\_tags) | Application's tags | `map(string)` | `{}` | no | +| [buckets\_list](#input\_buckets\_list) | List of the application's buckets |
list(object({
bucket_name = string
bucket_region = optional(string)
bucket_versioning = optional(bool)
bucket_tags = optional(map(string))
bucket_policy_actions = optional(list(string))
bucket_lifecycle_rules = optional(list(object({
id = string
enabled = bool
prefix = optional(string)
expiration_days = optional(number)
transition_days = optional(number)
transition_sc = optional(string)
tags = optional(map(string))
})))
other_app_access = optional(list(string))
other_app_policy_actions= optional(list(string))
})) | n/a | yes |
+| [env](#input\_env) | App's environment (dev/stg/prd/inf) | `string` | `"dev"` | no |
+| [policy\_permissions](#input\_policy\_permissions) | Policy permissions for app | `list(string)` | `[]` | no |
+| [project\_id](#input\_project\_id) | App's project ID | `string` | `"changeme"` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [api\_access\_key](#output\_api\_access\_key) | App access key |
+| [api\_secret\_key](#output\_api\_secret\_key) | App secret key |
+| [app\_desc](#output\_app\_desc) | Description of the application |
+| [app\_id](#output\_app\_id) | ID of the application |
+| [app\_name](#output\_app\_name) | Name of the application |
+| [bucket\_ID](#output\_bucket\_ID) | ID of the bucket |
+| [bucket\_endpoint](#output\_bucket\_endpoint) | Bucket's endpoint |
+
\ No newline at end of file
diff --git a/terraform/modules/buckets/buckets.tf b/terraform/modules/buckets/buckets.tf
new file mode 100644
index 0000000..6d85ce6
--- /dev/null
+++ b/terraform/modules/buckets/buckets.tf
@@ -0,0 +1,86 @@
+resource "scaleway_object_bucket" "s3_buckets" {
+ for_each = (var.buckets_list == null) ? {} : { for b in var.buckets_list : b.bucket_name => b }
+
+ name = each.value.bucket_name
+ tags = each.value.bucket_tags
+ region = each.value.bucket_region
+ project_id = var.project_id
+ versioning {
+ enabled = each.value.bucket_versioning
+ }
+
+ /* Dans cette section, on ajoute un bloc lifecycle_rule pour chaque
+ élément présent dans la liste lifecycle_rules de l'objet buckets.
+ */
+ dynamic "lifecycle_rule" {
+ for_each = each.value.bucket_lifecycle_rules
+ content {
+ id = lifecycle_rule.value["id"]
+ prefix = lifecycle_rule.value["prefix"]
+ enabled = lifecycle_rule.value["enabled"]
+ tags = lifecycle_rule.value["tags"]
+ /* On ajoute les blocs expiration ou transition en fonction
+ de la présence ou non des variables expiration_days,
+ transition_days et transition_sc. Au moins l'un de ces blocs
+ est obligatoire pour que la règle soit valide.
+ */
+ dynamic "expiration" {
+ for_each = lifecycle_rule.value["expiration_days"] == null ? [] : [1]
+ content {
+ days = lifecycle_rule.value["expiration_days"]
+ }
+ }
+ dynamic "transition" {
+ for_each = (lifecycle_rule.value["transition_days"] == null) && (lifecycle_rule.value["transition_sc"] == null) ? [] : [1]
+ content {
+ days = lifecycle_rule.value["transition_days"]
+ storage_class = lifecycle_rule.value["transition_sc"]
+ }
+ }
+ }
+ }
+
+ depends_on = [
+ scaleway_iam_api_key.keys
+ ]
+}
+
+resource "scaleway_object_bucket_policy" "s3_policies" {
+ for_each = (var.buckets_list == null) ? {} : { for b in var.buckets_list : b.bucket_name => b }
+
+ bucket = each.value.bucket_name
+ policy = jsonencode({
+ Version = "2023-04-17",
+ Id = "${each.value.bucket_name}",
+ Statement = [
+ {
+ Sid = "RW-${each.value.bucket_name}",
+ Effect = "Allow",
+ Principal = {
+ SCW = "application_id:${scaleway_iam_application.apps.id}"
+ },
+ Action = "${each.value.bucket_policy_actions}",
+ Resource = [
+ "${each.value.bucket_name}",
+ "${each.value.bucket_name}/*"
+ ],
+ },
+ {
+ Sid = "Admin-${each.value.bucket_name}",
+ Effect = "Allow",
+ Principal = {
+ SCW = var.admins_user_id
+ },
+ Action = "s3:*",
+ Resource = [
+ "${each.value.bucket_name}",
+ "${each.value.bucket_name}/*"
+ ],
+ }
+ ]
+ })
+
+ depends_on = [
+ scaleway_object_bucket.s3_buckets
+ ]
+}
diff --git a/terraform/modules/buckets/docs/header.md b/terraform/modules/buckets/docs/header.md
new file mode 100644
index 0000000..a95a97e
--- /dev/null
+++ b/terraform/modules/buckets/docs/header.md
@@ -0,0 +1,37 @@
+## Description du module
+
+Ce module a pour but de gérer les applications et leur ressources associées dans le cloud public Scaleway.
+
+## Fonctionnement du module
+
+- Ce module prend en charge la gestion des ressources suivantes :
+ - Les applications, groupes et policies de l'IAM Scaleway.
+ - Les buckets S3 et de leur policy associée.
+ - Les file d'attente de type SQS et leurs identifiants associés.
+
+### Fonctionnement bucket S3
+
+#### Pré-requis
+
+- Une liste de bucket est déclarée au sein de l'application.
+- Pour déclarer des règles de cycle de vie (lifecycle_rules), au moins expiration_days ou le couple transition_days et transition_sc doivent être déclarés.
+
+#### Fonctionnement
+
+- Pour chaque bucket de la liste buckets_list, une resource va être déclarée. Dans cette ressource, une lifecycle_rule va être déclarée pour chaque membre de la liste de lifecycle_rule.
+- Pour chaque bucket de la liste buckets_list, une policy est attachée et contient 3 sections :
+ - Une section pour autoriser l'application principale à accéder au bucket.
+ - Une section pour donner accès aux user_id et application_id des administrateurs.
+ - Une section pour donner accès à d'autres user_id pour une application tierce.
+
+### Fonctionnement SQS
+
+#### Pré-requis
+
+- Avoir activé le module SQS dans l'interface Scaleway -> Messaging.
+- Une liste de queue est déclarée au sein de l'application.
+
+#### Informations
+
+- On utilise une resource de type scaleway_mnq_sqs_credentials.admin_creds par projet. En effet, en lui donnant uniquement le droit "can_manage", elle peut créer, supprimer et modifier des queues mais pas accéder à leur contenu.
+- En parallèle, on créé un jeu d'identifiant par application et par queue qui ne disposent que des droits de publication/réception.
diff --git a/terraform/modules/buckets/iam.tf b/terraform/modules/buckets/iam.tf
new file mode 100644
index 0000000..55076b0
--- /dev/null
+++ b/terraform/modules/buckets/iam.tf
@@ -0,0 +1,41 @@
+resource "scaleway_iam_application" "apps" {
+ name = "${var.app_name}-${var.env}"
+ description = "${var.app_desc} env : ${var.env}"
+}
+
+resource "scaleway_iam_api_key" "keys" {
+ application_id = scaleway_iam_application.apps.id
+ description = "${var.app_name}-${var.env} api key"
+ default_project_id = var.project_id
+
+ depends_on = [
+ scaleway_iam_application.apps
+ ]
+}
+
+resource "scaleway_iam_group" "groups" {
+ name = "group-${var.app_name}-${var.env}"
+ description = "${var.app_name} IAM group for env ${var.env}"
+
+ application_ids = [
+ scaleway_iam_application.apps.id
+ ]
+
+ depends_on = [
+ scaleway_iam_application.apps
+ ]
+}
+
+resource scaleway_iam_policy "group_policies" {
+ name = "policy-${var.app_name}-${var.env}"
+ description = "${var.app_name} policy for group ${scaleway_iam_group.groups.name} in env ${var.env}"
+ group_id = scaleway_iam_group.groups.id
+ rule {
+ project_ids = [var.project_id]
+ permission_set_names = var.policy_permissions
+ }
+
+ depends_on = [
+ scaleway_iam_group.groups
+ ]
+}
diff --git a/terraform/modules/buckets/main.tf b/terraform/modules/buckets/main.tf
new file mode 100644
index 0000000..2d43ee1
--- /dev/null
+++ b/terraform/modules/buckets/main.tf
@@ -0,0 +1,8 @@
+terraform {
+ required_providers {
+ scaleway = {
+ source = "scaleway/scaleway"
+ version = ">= 2.35.0"
+ }
+ }
+}
diff --git a/terraform/modules/buckets/outputs.tf b/terraform/modules/buckets/outputs.tf
new file mode 100644
index 0000000..ffe3b46
--- /dev/null
+++ b/terraform/modules/buckets/outputs.tf
@@ -0,0 +1,43 @@
+#############
+# APP OUTPUT
+#############
+
+
+output "app_name" {
+ description = "Name of the application"
+ value = scaleway_iam_application.apps.name
+}
+
+output "app_id" {
+ description = "ID of the application"
+ value = scaleway_iam_application.apps.id
+}
+
+output "app_desc" {
+ description = "Description of the application"
+ value = scaleway_iam_application.apps.description
+}
+
+output "api_access_key" {
+ description = "App access key"
+ value = scaleway_iam_api_key.keys.access_key
+}
+
+output "api_secret_key" {
+ description = "App secret key"
+ value = scaleway_iam_api_key.keys.secret_key
+}
+
+##############
+# BUCKET OUTPUT
+##############
+
+output "bucket_ID" {
+ description = "ID of the bucket"
+ value = [ for b in scaleway_object_bucket.s3_buckets: b.id ]
+}
+
+output "bucket_endpoint" {
+ description = "Bucket's endpoint"
+ value = [ for b in scaleway_object_bucket.s3_buckets: b.endpoint ]
+}
diff --git a/terraform/modules/buckets/variables.tf b/terraform/modules/buckets/variables.tf
new file mode 100644
index 0000000..bd8cb9b
--- /dev/null
+++ b/terraform/modules/buckets/variables.tf
@@ -0,0 +1,77 @@
+###################
+# GLOBAL VARIABLES
+###################
+
+variable "project_id" {
+ description = "App's project ID"
+ type = string
+ default = "changeme"
+}
+###################
+# APP VARIABLES
+###################
+
+variable "app_name" {
+ description = "Name of the application"
+ type = string
+ default = "changeme"
+}
+
+variable "app_desc" {
+ description = "Application's description"
+ type = string
+ default = ""
+}
+
+variable "app_tags" {
+ description = "Application's tags"
+ type = map(string)
+ default = {}
+}
+
+variable "env" {
+ description = "App's environment (dev/stg/prd/inf)"
+ type = string
+ default = "dev"
+}
+
+variable "policy_permissions" {
+ description = "Policy permissions for app"
+ type = list(string)
+ default = []
+}
+
+###################
+# BUCKETS VARIABLE
+###################
+
+variable "buckets_list" {
+ description = "List of the application's buckets"
+ type = list(object({
+ bucket_name = string
+ bucket_region = optional(string)
+ bucket_versioning = optional(bool)
+ bucket_tags = optional(map(string))
+ bucket_policy_actions = optional(list(string))
+ bucket_lifecycle_rules = optional(list(object({
+ id = string
+ enabled = bool
+ prefix = optional(string)
+ expiration_days = optional(number)
+ transition_days = optional(number)
+ transition_sc = optional(string)
+ tags = optional(map(string))
+ })))
+ other_app_access = optional(list(string))
+ other_app_policy_actions= optional(list(string))
+ }))
+}
+
+
+# 09/01/2024 - Pas possible de mettre des group_id comme principal
+# cf https://feature-request.scaleway.com/posts/714/bucket-policy-with-group_id
+variable "admins_user_id" {
+ description = "List of s3 admin user's ID"
+ type = list(string)
+ default = []
+}