diff --git a/.gitignore b/.gitignore index f07b67855..b18e44f03 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,23 @@ vendor/bundle /yarn-error.log yarn-debug.log* .yarn-integrity + +# Terraform state files +*.tfstate +*.tfstate.backup + +# Terraform variable files (actual, not examples) +*.tfvars +*.auto.tfvars + +# .terraform directory +.terraform/ + +# Sensitive credentials +*.pem +*.key +*.secret +*.env + +# Plan files +*.tfplan diff --git a/infra/.terraform.lock.hcl b/infra/.terraform.lock.hcl new file mode 100644 index 000000000..00f630cdb --- /dev/null +++ b/infra/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.100.0" + constraints = "~> 5.92" + hashes = [ + "h1:Ijt7pOlB7Tr7maGQIqtsLFbl7pSMIj06TVdkoSBcYOw=", + "zh:054b8dd49f0549c9a7cc27d159e45327b7b65cf404da5e5a20da154b90b8a644", + "zh:0b97bf8d5e03d15d83cc40b0530a1f84b459354939ba6f135a0086c20ebbe6b2", + "zh:1589a2266af699cbd5d80737a0fe02e54ec9cf2ca54e7e00ac51c7359056f274", + "zh:6330766f1d85f01ae6ea90d1b214b8b74cc8c1badc4696b165b36ddd4cc15f7b", + "zh:7c8c2e30d8e55291b86fcb64bdf6c25489d538688545eb48fd74ad622e5d3862", + "zh:99b1003bd9bd32ee323544da897148f46a527f622dc3971af63ea3e251596342", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9f8b909d3ec50ade83c8062290378b1ec553edef6a447c56dadc01a99f4eaa93", + "zh:aaef921ff9aabaf8b1869a86d692ebd24fbd4e12c21205034bb679b9caf883a2", + "zh:ac882313207aba00dd5a76dbd572a0ddc818bb9cbf5c9d61b28fe30efaec951e", + "zh:bb64e8aff37becab373a1a0cc1080990785304141af42ed6aa3dd4913b000421", + "zh:dfe495f6621df5540d9c92ad40b8067376350b005c637ea6efac5dc15028add4", + "zh:f0ddf0eaf052766cfe09dea8200a946519f653c384ab4336e2a4a64fdd6310e9", + "zh:f1b7e684f4c7ae1eed272b6de7d2049bb87a0275cb04dbb7cda6636f600699c9", + "zh:ff461571e3f233699bf690db319dfe46aec75e58726636a0d97dd9ac6e32fb70", + ] +} diff --git a/infra/main.tf b/infra/main.tf new file mode 100644 index 000000000..7ef92ceda --- /dev/null +++ b/infra/main.tf @@ -0,0 +1,118 @@ +provider "aws" { + region = "eu-north-1" +} + +# Create the IAM user who will assume the basic role +resource "aws_iam_user" "basic_user" { + name = "basic-user" +} + +# Basic Role - trust the specific IAM user to assume this role +resource "aws_iam_role" "basic_role" { + name = "terraform-basic-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Principal = { + AWS = aws_iam_user.basic_user.arn # <--- Trust this IAM user + }, + Action = "sts:AssumeRole" + } + ] + }) +} + +# Policy allowing the basic role to assume the admin role +resource "aws_iam_policy" "assume_admin_policy" { + name = "AssumeTerraformAdminRole" + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Action = "sts:AssumeRole", + Resource = aws_iam_role.admin_role.arn + } + ] + }) +} + +# Attach the assume admin role policy to the basic role +resource "aws_iam_role_policy_attachment" "basic_assume_admin_attach" { + role = aws_iam_role.basic_role.name + policy_arn = aws_iam_policy.assume_admin_policy.arn +} + +# Admin role (trusts the basic role) +resource "aws_iam_role" "admin_role" { + name = "terraform-admin-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Principal = { + AWS = aws_iam_role.basic_role.arn + }, + Action = "sts:AssumeRole" + } + ] + }) +} + +resource "aws_iam_role_policy_attachment" "admin_attach" { + role = aws_iam_role.admin_role.name + policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess" +} + +# 1. S3 Bucket (private by default) +resource "aws_s3_bucket" "auth_bucket" { + bucket = "codebar-planner-auth-bucket" +} + +# 2. IAM User for Heroku app +resource "aws_iam_user" "heroku_role" { + name = "heroku-s3-access" +} + +# 3. IAM Policy: Read-only access to just this bucket +resource "aws_iam_policy" "read_write_policy" { + name = "HerokuS3ReadWrite" + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Action = [ + "s3:ListBucket", # List files in bucket + "s3:GetObject", # Read/download files + "s3:PutObject", # Upload files + "s3:DeleteObject", # Optional: allow deleting files + "s3:ListAllMyBuckets" # enable user to list all buckets + ], + Resource = [ + aws_s3_bucket.auth_bucket.arn, + "${aws_s3_bucket.auth_bucket.arn}/*" + ] + } + ] + }) +} + + +# 4. Attach the policy to the user +resource "aws_iam_user_policy_attachment" "attach_policy" { + user = aws_iam_user.heroku_role.name + policy_arn = aws_iam_policy.read_write_policy.arn +} + +# 5. Create access keys for the user +resource "aws_iam_access_key" "heroku_user_keys" { + user = aws_iam_user.heroku_role.name +} diff --git a/infra/terraform.tf b/infra/terraform.tf new file mode 100644 index 000000000..65c7ec2c5 --- /dev/null +++ b/infra/terraform.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.92" + } + } + + required_version = ">= 1.2" +}