[アップデート] Transfer Family サーバー用の Terraform I-A モジュールがリリースされました

[アップデート] Transfer Family サーバー用の Terraform I-A モジュールがリリースされました

Clock Icon2025.04.23

こんにちは!クラウド事業本部コンサルティング部のたかくに(@takakuni_)です。

今朝、Transfer Family サーバーデプロイ用の Terraform モジュールが登場したとアナウンスがありました。今後、What's New には Terraform モジュールのアップデートも出てくるのでしょうか。興味深いです。

https://aws.amazon.com/jp/about-aws/whats-new/2025/04/aws-transfer-family-terraform-module-sftp-endpoints/

アップデート内容

アップデート前をおさらいします。AWS I-A モジュールおよび、Terraform AWS modules では Transfer Family モジュールがない状態のため、自前で実装する必要がありました。

今回のアップデートは AWS I-A モジュール側で Transfer Family のモジュールの提供を開始しました。というものです。

https://github.com/aws-ia/terraform-aws-transfer-family

構成

構成を確認してみます。シークレットマネージャーに SSH キーを保管し SFTP するようなアーキテクチャであると伺えます。必要に応じてカスタムドメイン設定可能なポイントも良さそうです。

image.png
terraform-aws-transfer-family より画像引用

ベストプラクティスも挙げられていました。利用の際は一読しておきましょう。

  • 監査とモニタリングのために CloudWatch のロギングを有効にすること
    • enable_logging 変数で設定可能
  • 最新のセキュリティポリシーを使用すること
    • TransferSecurityPolicy-2024-01
  • カスタムホスト名を使用する場合、適切な DNS 設定を行うこと
  • DNS プロバイダとカスタムホスト名の設定に組み込みの検証チェックを利用すること
  • リソースに適切なタグ付けを行うこと
    • tags 変数で対応

https://github.com/aws-ia/terraform-aws-transfer-family?tab=readme-ov-file#best-practices

Module 構成

Module は Core Transfer Server ModuleTransfer Users Module の 2 つに分かれています。基本的には Core Transfer Server Module を使ってから、Transfer Users Module を使う流れになると思います。Users Module の CSV 管理も運用楽そうに思えました。

Core Transfer Server Module (main module)

  • SFTP protocol support
  • Public endpoint configuration
  • CloudWatch logging setup
  • Service-managed authentication
  • Custom hostname support (optional)

Transfer Users Module

  • CSV-based user configuration support
  • Optional test user creation
  • IAM role and policy management
  • Integration with S3 bucket permissions
  • KMS encryption key access management

Module

やってみる

それでは今回の Terraform Module を利用してみます。

Transfer Server Module

まずは SFTP サーバーを立ち上げてみたいと思います。オプショナルですが custom_hostname も設定してみました。

main.tf
module "transfer_sftp" {
  source = "aws-ia/transfer-family/aws//modules/transfer-server"

  identity_provider        = "SERVICE_MANAGED"
  protocols                = ["SFTP"]
  domain                   = "S3"
  dns_provider             = "route53"
  custom_hostname          = "sftp.hoge.blog"
  route53_hosted_zone_name = "hoge.blog"

  tags = {
    Environment = "Dev"
    Project     = "File Transfer"
  }
}

レコードを作りながら、Transfer Family サーバーを作っている様子がわかります。

transferfamily-module % terraform apply
module.transfer_sftp.data.aws_route53_zone.selected[0]: Reading...
module.transfer_sftp.data.aws_route53_zone.selected[0]: Read complete after 2s [id=XXXXXXXXXXXXXXXXXXXXX]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.transfer_sftp.aws_route53_record.sftp[0] will be created
  + resource "aws_route53_record" "sftp" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "sftp.hoge.blog"
      + records         = (known after apply)
      + ttl             = 300
      + type            = "CNAME"
      + zone_id         = "XXXXXXXXXXXXXXXXXXXXX"
    }

  # module.transfer_sftp.aws_transfer_server.transfer_server will be created
  + resource "aws_transfer_server" "transfer_server" {
      + arn                         = (known after apply)
      + domain                      = "S3"
      + endpoint                    = (known after apply)
      + endpoint_type               = "PUBLIC"
      + force_destroy               = false
      + host_key_fingerprint        = (known after apply)
      + id                          = (known after apply)
      + identity_provider_type      = "SERVICE_MANAGED"
      + protocols                   = [
          + "SFTP",
        ]
      + security_policy_name        = "TransferSecurityPolicy-2024-01"
      + sftp_authentication_methods = (known after apply)
      + tags                        = {
          + "Environment" = "Dev"
          + "Name"        = "transfer-server"
          + "Project"     = "File Transfer"
        }
      + tags_all                    = {
          + "Environment" = "Dev"
          + "Name"        = "transfer-server"
          + "Project"     = "File Transfer"
        }

      + protocol_details (known after apply)

      + s3_storage_options (known after apply)
    }

  # module.transfer_sftp.aws_transfer_tag.with_custom_domain_name[0] will be created
  + resource "aws_transfer_tag" "with_custom_domain_name" {
      + id           = (known after apply)
      + key          = "aws:transfer:customHostname"
      + resource_arn = (known after apply)
      + value        = "sftp.hoge.blog"
    }

  # module.transfer_sftp.aws_transfer_tag.with_custom_domain_route53_zone_id[0] will be created
  + resource "aws_transfer_tag" "with_custom_domain_route53_zone_id" {
      + id           = (known after apply)
      + key          = "aws:transfer:route53HostedZoneId"
      + resource_arn = (known after apply)
      + value        = "/hostedzone/XXXXXXXXXXXXXXXXXXXXX"
    }

Plan: 4 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.transfer_sftp.aws_transfer_server.transfer_server: Creating...
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [10s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [20s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [30s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [40s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [50s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [1m0s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [1m10s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [1m20s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [1m30s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [1m40s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [1m50s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [2m0s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [2m10s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [2m20s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [2m30s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [2m40s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Still creating... [2m50s elapsed]
module.transfer_sftp.aws_transfer_server.transfer_server: Creation complete after 2m56s [id=s-485b0a02d1f344188]
module.transfer_sftp.aws_transfer_tag.with_custom_domain_name[0]: Creating...
module.transfer_sftp.aws_transfer_tag.with_custom_domain_route53_zone_id[0]: Creating...
module.transfer_sftp.aws_route53_record.sftp[0]: Creating...
module.transfer_sftp.aws_transfer_tag.with_custom_domain_name[0]: Creation complete after 0s [id=arn:aws:transfer:ap-northeast-1:123456789012:server/s-485b0a02d1f344188,aws:transfer:customHostname]
module.transfer_sftp.aws_transfer_tag.with_custom_domain_route53_zone_id[0]: Creation complete after 0s [id=arn:aws:transfer:ap-northeast-1:123456789012:server/s-485b0a02d1f344188,aws:transfer:route53HostedZoneId]
module.transfer_sftp.aws_route53_record.sftp[0]: Still creating... [10s elapsed]
module.transfer_sftp.aws_route53_record.sftp[0]: Still creating... [20s elapsed]
module.transfer_sftp.aws_route53_record.sftp[0]: Still creating... [30s elapsed]
module.transfer_sftp.aws_route53_record.sftp[0]: Creation complete after 34s [id=XXXXXXXXXXXXXXXXXXXXX_sftp.hoge.blog_CNAME]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

マネジメントコンソールを見ると test-user が作成されていました。(秘密鍵は Secrets Manager に保管されています)

今回は利用しませんが、こちらのユーザーを利用すれば疎通確認ができそうです。

2025-04-23 at 22.53.11-サーバー詳細  AWS Transfer Family  ap-northeast-1.png

Transfer User Module

続いて User Module 側です。 users は list(object) の形式または CSV での指定でした。今回は list(object) に従いました。

resource "random_pet" "name" {
  prefix = "aws-ia"
  length = 1
}

module "s3_bucket" {
  source                   = "git::https://github.com/terraform-aws-modules/terraform-aws-s3-bucket.git?ref=fc09cc6fb779b262ce1bee5334e85808a107d8a3"
  bucket                   = lower("${random_pet.name.id}-${module.transfer_sftp.server_id}-s3-sftp")
  control_object_ownership = true
  object_ownership         = "BucketOwnerEnforced"
  block_public_acls        = true
  block_public_policy      = true
  ignore_public_acls       = true
  restrict_public_buckets  = true
  versioning = {
    enabled = false
  }
}

resource "tls_private_key" "main" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

output "pem" {
  value     = tls_private_key.main.private_key_pem
  sensitive = true
}

resource "aws_kms_key" "transfer_family_key" {
  description             = "KMS key for encrypting S3 bucket and cloudwatch log group"
  deletion_window_in_days = 7
  enable_key_rotation     = true

  tags = {
    Purpose = "Transfer Family Encryption"
  }
}

module "sftp_users" {
  source = "aws-ia/transfer-family/aws//modules/transfer-users"
  users = [
    {
      username   = "takakuni"
      home_dir   = "/${module.s3_bucket.s3_bucket_id}"
      public_key = tls_private_key.main.public_key_openssh
    }
  ]
  create_test_user = true

  server_id      = module.transfer_sftp.server_id
  kms_key_id     = aws_kms_key.transfer_family_key.arn
  s3_bucket_name = module.s3_bucket.s3_bucket_id
  s3_bucket_arn  = module.s3_bucket.s3_bucket_arn
}

接続確認

custom_hostname で設定したドメインから SFTP 接続を試みます。

terraform output pem > ./ssh.pem
chmod 600 ./ssh.pem
transferfamily-module % sftp -i ./ssh.pem takakuni@sftp.hoge.blog
Connected to sftp.hoge.blog.
sftp> ls
sftp> pwd
Remote working directory: /
sftp> 

うまくつながっているところまで確認できました。

まとめ

以上、「[アップデート] Transfer Family サーバー用の Terraform I-A モジュールがリリースされました」でした。

今後、 I-A モジュールがリリースされた時は What's New に乗るのでしょうか。乞うご期待ですね。

クラウド事業本部コンサルティング部のたかくに(@takakuni_)でした!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.