diff --git a/.github/workflows/terraform-scaleway-iac-apply.yml b/.github/workflows/terraform-scaleway-iac-apply.yml new file mode 100644 index 0000000..7478825 --- /dev/null +++ b/.github/workflows/terraform-scaleway-iac-apply.yml @@ -0,0 +1,35 @@ +name: Terraform Scaleway IAC Apply + +on: + schedule: + - cron: "0 1 * * 0" + push: + branches: + - main + paths: + - "terraform/scaleway-iac/**" +jobs: + opentofu-apply: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup environment + uses: ./.github/actions/setup-env + + - name: Setup OpenTofu environment + uses: ./.github/actions/setup-opentofu-env + + - name: OpenTofu Init and Apply + env: + BW_PROJECT_ID: ${{ secrets.BW_PROJECT_ID }} + BW_ORGANIZATION_ID: ${{ secrets.BW_ORGANIZATION_ID }} + BW_ACCESS_TOKEN: ${{ secrets.BW_ACCESS_TOKEN }} + run: | + cd terraform/scaleway-iac + sectool -f ../../sectool.json exec tofu init + sectool -f ../../sectool.json exec tofu apply --auto-approve diff --git a/.github/workflows/terraform-scaleway-iac-validate-on-pr.yml b/.github/workflows/terraform-scaleway-iac-validate-on-pr.yml new file mode 100644 index 0000000..b4f30bc --- /dev/null +++ b/.github/workflows/terraform-scaleway-iac-validate-on-pr.yml @@ -0,0 +1,39 @@ +name: Terraform Scaleway IAC Validate on Pull Request + +on: + pull_request: + branches: + - main + paths: + - "terraform/scaleway-iac/**" + types: + - opened + - synchronize + - reopened +jobs: + terraform-validate: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup environment + uses: ./.github/actions/setup-env + + - name: Setup OpenTofu environment + uses: ./.github/actions/setup-opentofu-env + + - name: OpenTofu Init and Validate + env: + BW_PROJECT_ID: ${{ secrets.BW_PROJECT_ID }} + BW_ORGANIZATION_ID: ${{ secrets.BW_ORGANIZATION_ID }} + BW_ACCESS_TOKEN: ${{ secrets.BW_ACCESS_TOKEN }} + run: | + cd terraform/scaleway-iac + sectool -f ../../sectool.json exec tofu init + sectool -f ../../sectool.json exec tofu validate + sectool -f ../../sectool.json exec tofu fmt -check + sectool -f ../../sectool.json exec tofu plan diff --git a/terraform/scaleway-iac/backend.tf b/terraform/scaleway-iac/backend.tf new file mode 100644 index 0000000..844bb6a --- /dev/null +++ b/terraform/scaleway-iac/backend.tf @@ -0,0 +1,7 @@ +terraform { + backend "s3" { + bucket = "a13labs.infra.eu" + key = "scaleway.core.infra.tfstate" + region = "eu-west-1" + } +} diff --git a/terraform/scaleway-iac/buckets.tf b/terraform/scaleway-iac/buckets.tf new file mode 100644 index 0000000..82b6475 --- /dev/null +++ b/terraform/scaleway-iac/buckets.tf @@ -0,0 +1,45 @@ +resource "scaleway_object_bucket" "infra_assets" { + name = "a13labs-infra-${var.bucket_suffix}" + project_id = var.scaleway_project_id + region = "fr-par" +} + +resource "scaleway_object_bucket_policy" "policy" { + bucket = scaleway_object_bucket.infra_assets.name + policy = jsonencode({ + Version = "2023-04-17", + Id = "AllowMachineDownload", + Statement = [ + { + Effect = "Allow" + Action = [ + "s3:ListBucket", + "s3:GetObject", + ] + Principal = "*" + Resource = [ + scaleway_object_bucket.infra_assets.name, + "${scaleway_object_bucket.infra_assets.name}/*", + ] + Condition = { + IpAddress = { + "aws:SourceIp" = local.instance_ips + } + }, + }, + { + Effect = "Allow" + Action = [ + "s3:*", + ] + Principal = { + SCW = "user_id:${var.scaleway_user_id}" + } + Resource = [ + scaleway_object_bucket.infra_assets.name, + "${scaleway_object_bucket.infra_assets.name}/*", + ] + }, + ] + }) +} diff --git a/terraform/scaleway-iac/config.tf b/terraform/scaleway-iac/config.tf new file mode 100644 index 0000000..5fe00ad --- /dev/null +++ b/terraform/scaleway-iac/config.tf @@ -0,0 +1,21 @@ +locals { + instance_ips = [ + "${local.vps_1.ip}/32", + ] + + vps_1 = { + id = data.terraform_remote_state.contabo.outputs.instances[0].id + name = data.terraform_remote_state.contabo.outputs.instances[0].name + ip = data.terraform_remote_state.contabo.outputs.instances[0].ip_config[0].v4[0].ip + } +} + +data "terraform_remote_state" "contabo" { + backend = "s3" + config = { + bucket = "a13labs.infra.eu" + key = "contabo.core.infra.tfstate" + region = "eu-west-1" + } +} + diff --git a/terraform/scaleway-iac/encryption.tf b/terraform/scaleway-iac/encryption.tf new file mode 100644 index 0000000..3cb0342 --- /dev/null +++ b/terraform/scaleway-iac/encryption.tf @@ -0,0 +1,6 @@ +resource "scaleway_object" "system_id_encryption_key" { + bucket = scaleway_object_bucket.infra_assets.id + key = "keys/${var.system_id}" + + content_base64 = base64encode(var.encryption_key) +} diff --git a/terraform/scaleway-iac/import.tf b/terraform/scaleway-iac/import.tf new file mode 100644 index 0000000..01bac4e --- /dev/null +++ b/terraform/scaleway-iac/import.tf @@ -0,0 +1,20 @@ +import { + to = scaleway_object.system_id_encryption_key + id = "fr-par/a13labs-infra-${nonsensitive(var.bucket_suffix)}/keys/${nonsensitive(var.system_id)}" +} + +import { + to = scaleway_registry_namespace.a13labs + id = "fr-par/ea39fede-ad83-4616-aa53-529cf5d01b16" +} + +import { + to = scaleway_object_bucket.infra_assets + id = "fr-par/a13labs-infra-${nonsensitive(var.bucket_suffix)}" +} + +import { + to = scaleway_object_bucket_policy.policy + id = "fr-par/a13labs-infra-${nonsensitive(var.bucket_suffix)}" +} + diff --git a/terraform/scaleway-iac/provider.tf b/terraform/scaleway-iac/provider.tf new file mode 100644 index 0000000..4b62d78 --- /dev/null +++ b/terraform/scaleway-iac/provider.tf @@ -0,0 +1,19 @@ + +terraform { + required_version = "~>1.8" + required_providers { + scaleway = { + source = "scaleway/scaleway" + version = "~>2.13" + } + } +} + +provider "scaleway" { + zone = "fr-par-2" + region = "fr-par" + access_key = var.scaleway_access_key + secret_key = var.scaleway_secret_key + organization_id = var.scaleway_organization_id +} + diff --git a/terraform/scaleway-iac/registry.tf b/terraform/scaleway-iac/registry.tf new file mode 100644 index 0000000..292205a --- /dev/null +++ b/terraform/scaleway-iac/registry.tf @@ -0,0 +1,5 @@ +resource "scaleway_registry_namespace" "a13labs" { + name = "a13labs" + description = "A13Labs container registry" + is_public = false +} diff --git a/terraform/scaleway-iac/sectool.env b/terraform/scaleway-iac/sectool.env new file mode 100644 index 0000000..0703d1d --- /dev/null +++ b/terraform/scaleway-iac/sectool.env @@ -0,0 +1,9 @@ +AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY +AWS_SECRET_ACCESS_KEY=$AWS_SECRET_KEY +TF_VAR_scaleway_access_key=$SCALEWAY_ACCESS_KEY +TF_VAR_scaleway_secret_key=$SCALEWAY_SECRET_KEY +TF_VAR_scaleway_project_id=$SCALEWAY_PROJECT_ID +TF_VAR_scaleway_organization_id=$SCALEWAY_ORGANIZATION_ID +TF_VAR_scaleway_user_id=$SCALEWAY_USER_ID +TF_VAR_bucket_suffix=$BUCKET_SUFFIX +TF_VAR_encryption_key=$ENCRYPT_KEY diff --git a/terraform/scaleway-iac/variables.tf b/terraform/scaleway-iac/variables.tf new file mode 100644 index 0000000..bfc94c0 --- /dev/null +++ b/terraform/scaleway-iac/variables.tf @@ -0,0 +1,47 @@ +variable "scaleway_access_key" { + description = "Scaleway Access key" + type = string + sensitive = true +} + +variable "scaleway_secret_key" { + description = "Scaleway Secret key" + type = string + sensitive = true +} + +variable "scaleway_project_id" { + description = "Scaleway Project Id" + type = string + sensitive = true +} + +variable "scaleway_organization_id" { + description = "Scaleway Organization Id" + type = string + sensitive = true +} + +variable "scaleway_user_id" { + description = "Scaleway User Id" + type = string + sensitive = true +} + +variable "encryption_key" { + description = "Encryption key for sensitive data" + type = string + sensitive = true +} + +variable "bucket_suffix" { + description = "Suffix for bucket names" + type = string + sensitive = true +} + +variable "system_id" { + description = "System ID" + type = string + sensitive = true +}