Module not including on plan/apply

Hi! I have some experience with terraform, although pretty new with modules. I have the issue, that my module is not invoking on run. It doesn’t throw any errors, tf is simply ignoring it. I guess, I do have a logical mistake anywhere.

The code/project is about to setup sftp-transfer server and use for_each to reduce the amount of code and improve maintainability of users.

# terraform.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "4.39.0"
    }
  }
}

provider "aws" {
  region     = var.region
}
# sftp-transfer.tf
resource "aws_transfer_server" "sftp" {
  domain                 = "S3"
  protocols              = ["SFTP"]
  identity_provider_type = "SERVICE_MANAGED"
  endpoint_type          = "VPC"

  endpoint_details {
    subnet_ids = [aws_subnet.subnet_public_az_a.id]
    vpc_id     = aws_vpc.sftp_vpc.id
  }
}

# Create bucket for SFTP users
resource "aws_s3_bucket" "sftp" {
  bucket = "sftp-homedirs"
}
# users.tf
variable "user_map" {
  type = map(string)
  default = {
    user1    = "ssh-rsa AAAAB3NzaC1yc2EAA..."
    user2    = "ssh-rsa AAAAB3NzaC1zc2EAB..."
  }
}
# modules/aws-sftp-user/aws-sftp-user.tf

module "aws-sftp-user" {
  for_each = var.user_map
  source   = "./modules/aws-sftp-user"

  username       = each.key
  sshkey         = each.value
  s3_bucket_arn  = aws_s3_bucket.sftp.arn
  s3_bucket_name = aws_s3_bucket.sftp.id
  sftp_server_id = aws_transfer_server.sftp.id
}

# Create sftp transfer users
resource "aws_transfer_user" "user" {
  server_id      = var.sftp_server_id
  user_name      = var.username
  role           = aws_iam_role.sftp.arn
  home_directory = "/${var.s3_bucket_name}/${var.username}"
}

# Create transfer ssh keys for users
resource "aws_transfer_ssh_key" "user" {
  server_id = aws_transfer_server.sftp.id
  user_name = aws_transfer_user.user.user_name
  body      = var.sshkey
}

# Create IAM role for SFTP users
resource "aws_iam_role" "sftp" {
  name = "sftp-${var.username}-user-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Sid    = ""
        Principal = {
          Service = "transfer.amazonaws.com"
        }
      },
    ]
  })
}

# Create IAM role policy for SFTP users
resource "aws_iam_role_policy" "sftp" {
  name = "sftp-${var.username}-user-policy"
  role = aws_iam_role.sftp.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "s3:ListBucket",
          "s3:GetBucketLocation"
        ]
        Effect   = "Allow"
        Sid      = "AllowListingFolder"
        Resource = "${var.s3_bucket_arn}"
        Condition = {
          StringLike = {
            "s3:prefix" = [
              "${var.username}/*",
              "${var.username}"
            ],
          }
        }
      },
      {
        Action = [
          "s3:PutObject",
          "s3:GetObject",
          "s3:DeleteObjectVersion",
          "s3:DeleteObject",
          "s3:GetObjectVersion"
        ],
        Effect   = "Allow"
        Sid      = "AllowReadWriteToObject"
        Resource = "${var.s3_bucket_arn}/${var.username}*"
      },
    ]
  })
}

(leaving out the VCP code, as not relevant to the question)

Thanks for any hints in advance!

You seem to have placed the module block intended to call your module … inside that same module, instead of in your root directory of configuration!

Hey @maxb,

yeah, logically it makes totally sense. That’s also what I’ve tried first. But if I place the module code block anywhere outside of the module - then I simply get error messages for any referenced variable.

tf-sftp % terraform plan
╷
│ Error: Unsupported argument
│
│   on terraform.tf line 21, in module "aws-sftp-user":
│   21:   username       = each.key
│
│ An argument named "username" is not expected here.
╵
╷
│ Error: Unsupported argument
│
│   on terraform.tf line 22, in module "aws-sftp-user":
│   22:   sshkey         = each.value
│
│ An argument named "sshkey" is not expected here.
╵
╷
│ Error: Unsupported argument
│
│   on terraform.tf line 23, in module "aws-sftp-user":
│   23:   s3_bucket_arn  = aws_s3_bucket.sftp.arn
│ An argument named "s3_bucket_arn" is not expected here.

What is the best way or how is it possible to go through for_each key/value in a module, which isn’t defined in the same file where the module code block is written?

That is because when you move the block into the module, you’re completely unlinking it from the configuration your’re passing to Terraform - practically deleting it entirely.

The errors you are getting are because you are passing variables in your module block:

yet you have not declared any of these 5 variables inside the module.

You need a variable block within your module directory for each of these 5.