Terraform + EC2でFTPサーバーを構築
概要
EC2で検証用にFTPサーバーを構築する機会があり、Terraformでの構築記事が無かったのでメモを残しておきます。
Terraformで構築を行いますが、後述するように全自動では構築が出来なかったので、半自動で構築を行います。
なお今回はVPCは作成されているものとして、作成されているVPCの値を利用します。
環境
- Mac OS X 12.6
- Terraform 1.2.1
以下のようなディレクトリ構成で進めていきますので、あらかじめ作成しておいてください
sample
- key_pair/
- main.tf
- local.tf
- parameter_store.tf
- security_group.tf
- ec2.tf
手順
- キーペアの作成
- main.tfの作成
- local.tf
- parameter_store.tfの作成
- security_group.tfの作成
- ec2.tfの作成
- terraform apply
- vsftpd.confを修正し、vsftpdを再起動
- 接続確認
1. キーペアの作成
FTPサーバーにログインするためのキーペアを作成します
$ cd /path/to/sample
# 4096ビットでキーペアを作成
$ ssh-keygen -t rsa -b 4096 -f ./key_pair/id_rsa
2. main.tfの作成
本来はS3 or Terraform Cloudでstateファイルを管理しますが、今回はサンプルなので、ローカルでstateファイルを管理します。
terraform {
required_version = "~> 1.2.1"
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.22.0"
}
}
}
3. local.tfの作成
ローカル変数の値を管理します
locals {
vpc_id = ""
public_subnet_id = ""
allow_ips = ["", ""] # FTP接続を許可するIPの配列を設定
}
4. parameter_store.tfの作成
FTPプロトコルでログインをする際に利用するパスワードをterraformで生成します。
resource "random_password" "this" {
length = 16
special = false
}
resource "aws_ssm_parameter" "this" {
name = "/ftp/user-password"
type = "SecureString"
value = random_password.this.result
}
5. security_group.tfの作成
security_group.tf
では以下のことを許可するように構築
- 許可したIPからのFTP接続を許可
- 許可したIPからのSSHでの接続を許可
resource "aws_security_group" "this" {
name = "ftp-sg"
vpc_id = local.vpc_id
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_security_group_rule" "range" {
security_group_id = aws_security_group.this.id
from_port = 60001
to_port = 60010
protocol = "tcp"
type = "ingress"
cidr_blocks = local.allow_ips
}
resource "aws_security_group_rule" "ssh" {
security_group_id = aws_security_group.this.id
from_port = 22
to_port = 22
protocol = "tcp"
type = "ingress"
cidr_blocks = local.allow_ips
}
resource "aws_security_group_rule" "ftp" {
security_group_id = aws_security_group.this.id
from_port = 21
to_port = 21
protocol = "tcp"
type = "ingress"
cidr_blocks = local.allow_ips
}
6. ec2.tfの作成
FTPサーバーの構築を行います。
ここでのポイントは、user_dataにスクリプトを投げてある程度のことは自動化しているのと、後の作業でElastic IPの値を利用するため、outputでElastic IPを出力出来るようにしています
resource "aws_key_pair" "this" {
key_name = "ftp-rsa"
public_key = file("${path.module}/key_pair/id_rsa.pub")
}
data "aws_ssm_parameter" "amzn2_ami" {
name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}
resource "aws_instance" "this" {
depends_on = [random_password.this, aws_ssm_parameter.this]
ami = data.aws_ssm_parameter.amzn2_ami.value
instance_type = "t2.small"
monitoring = true
key_name = aws_key_pair.this.id
vpc_security_group_ids = [aws_security_group.this.id]
associate_public_ip_address = true
subnet_id = local.public_subnet_id
user_data = <<EOF
#!/bin/bash
sudo yum update -y
sudo yum install vsftpd -y
sudo systemctl start vsftpd
sudo systemctl enable vsftpd
sudo adduser --home /home/ftp-user ftp-user
echo ${random_password.this.result} | sudo passwd --stdin ftp-user
sudo chown ftp-user:ftp-user -R /home/ftp-user/
sudo mv /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.bk
sudo touch /etc/vsftpd/vsftpd.conf
sudo sh -c "cat << EOF >> /etc/vsftpd/vsftpd.conf
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=NO
xferlog_enable=YES
connect_from_port_20=NO
xferlog_file=/var/log/vsftpd.log
xferlog_std_format=NO
ascii_upload_enable=YES
ascii_download_enable=YES
ls_recurse_enable=YES
listen=NO
listen_ipv6=YES
pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES
pasv_enable=YES
pasv_addr_resolve=YES
# pasv_address=Elastic Terraform Apply後、固定IPに変更をする
pasv_min_port=60001
pasv_max_port=60010
use_localtime=YES
force_dot_files=YES
seccomp_sandbox=NO
allow_writeable_chroot=YES
EOF"
sudo systemctl restart vsftpd
EOF
tags = {
Name = "ftp-server"
}
}
resource "aws_eip" "this" {
vpc = true
instance = aws_instance.this.id
}
output "eip" {
value = aws_eip.this.public_ip
}
7. terraform apply
以下を実行して、問題ないことを確認していきましょう
$ terraform init
$ terraform fmt
$ terraform validate
# ここで出力されるリソースを問題ないか確認する
$ terraform plan
# planで問題なければ、apply
$ terraform apply
8. vsftpd.confを修正し、vsftpdを再起動
一部EC2内で手動で作業をする必要があり、以下のように変更します。
- # pasv_address=Elastic Terraform Apply後、固定IPに変更をする
+ pasv_address=ElasticIPのIPを設定
なぜこの部分だけ手動で作業をするかというと、Terraformのec2.tfのコードでelastic ipはec2 instanceを以下のように参照しています
resource "aws_eip" "this" {
vpc = true
instance = aws_instance.this.id
}
そして、aws_instanceのスコープで以下のようにしてしまうと、双方で参照となり、循環参照となってしまいエラーとなってしまうため、vsftpd.conf
は手動で書き換える必要があります。
pasv_address=aws_eip.this.public_ip
$ /path/to/sample
# 固定IPを確認
$ terraform output
$ ssh -i ./key_pair/id_rsa ec2-user@上で確認した固定IP
上記でFTPサーバーにSSH接続をしたら、vsftpd.conf
を編集します
$ sudo vi /etc/vsftpd/vsftpd.conf
pasv_addressをコメントインして、値に固定IPを設定します
- # pasv_address=Elastic Terraform Apply後、固定IPに変更をする
+ pasv_address=ElasticIPのIPを設定
設定したら、保存して、vsftpdを再起動します
$ sudo systemctl restart vsftpd
上記でFTPサーバーの構築作業は完了です。
9. 接続確認
Macでftpコマンドで接続確認を行っていきます
ftpコマンドが使えない場合は、brewでインストールしてください
$ brew install tnftp
ftpへのログインパスワードは、AWS Web Console > System Manager > Parameter Storeで/ftp/user-password
と検索をして、パラメータを確認が出来ます
# 以下でエンターしたらパスワードを聞かれるので、上記で取得したパスワードでログインを行う
$ ftp ftp-user@固定IP
これで接続が出来たかと思います
Discussion