この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
先日、CloudFormation で Transfer for SFTP を作成できるようになりましたが、今回は Terraform で作成してみました。
ちなみに Terraform AWS プロバイダの CHANGELOG を参照すると、2018年12月13日リリースの 1.52.0
で aws_transfer_server
が追加されていました。Transfer for SFTP がリリースされたのは2018年11月26日ですので、3週間弱で使えるようになってたってことですね。早いですねー。すごいですねー。
という Terraform 好きの白々しいポジトークをしつつ、さっそく試していきます。
今回の環境
今回はパブリックエンドポイントではなく、VPC エンドポイントの Transfer for SFTP を作成します。検証した際の、バージョンは下記のとおりです。(まだ v0.12 あげてません。。)
$ terraform -v
Terraform v0.11.11
+ provider.aws v2.12.0
今回は VPC エンドポイントタイプになりますので、provider.aws v2.6.0 以上が必要となります。
tf ファイル
作成した tf ファイルは以下のとおりです。VPC やサブネット、S3 など割愛してている Terraform リソースは xxxx
にしていますので、ご自身の環境に読み替えてください。
security-group.tf
VPC エンドポイントに割り当てるセキュリティグループを作成します。今回は VPC の CIDR 内から 22 番を許可しました。
security-group.tf
resource "aws_security_group" "sftp-vpce-sg" {
name = "sftp-vpce-sg"
description = "Security Group for SFTP VPC Endpoint"
vpc_id = "${aws_vpc.xxxx.id}"
# VPC 内からの接続を許可
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [
"${aws_vpc.xxxx.cidr_block}",
]
}
}
VPC エンドポイントの作成
Transfer for SFTP と VPC をつなぐ VPC エンドポイントを作成します。service_name
は com.amazonaws.ap-northeast-1.transfer.server
を指定します。
vpc-endpoint.tf
#--------------------------------------
# VPC Endpoint
#--------------------------------------
resource "aws_vpc_endpoint" "sftp-vpce" {
vpc_id = "${aws_vpc.xxxx.id}"
service_name = "com.amazonaws.ap-northeast-1.transfer.server"
vpc_endpoint_type = "Interface"
# 先ほど作成した VPC エンドポイント用の SG を指定
security_group_ids = [
"${aws_security_group.sftp-vpce-sg.id}",
]
# VPC エンドポイントを作成するサブネットを指定
subnet_ids = [
"${aws_subnet.xxxx.id}",
"${aws_subnet.xxxx.id}",
]
private_dns_enabled = true
}
IAM ロールおよびポリシーの作成
作成するロールは以下の2つです。
- ログ出力用
- SFTP ユーザ 用
まずはポリシードキュメントを用意しておきます。
iam-policy-document.tf
#--------------------------------------
# IAM Policy Document
#--------------------------------------
# Transfer for SFTP の assume policy
data "aws_iam_policy_document" "assume-sftp" {
statement {
sid = "AssumeTransferforSFTP"
actions = [
"sts:AssumeRole",
]
principals {
type = "Service"
identifiers = [
"transfer.amazonaws.com",
]
}
}
}
# ログ出力用のポリシー
data "aws_iam_policy_document" "cwl-full" {
statement {
sid = "AllowFullAccesstoCloudWatchLogs"
actions = [
"logs:*",
]
resources = [
"*",
]
}
}
# SFTP ユーザ用のポリシー
data "aws_iam_policy_document" "sftpuser" {
statement {
sid = "AllowBucket"
effect = "Allow"
actions = [
"s3:GetBucketLocation",
"s3:ListBucket",
]
# ホームディレクトリの S3 バケット
resources = [
"${aws_s3_bucket.xxxx.arn}",
]
}
statement {
sid = "AllowObject"
effect = "Allow"
actions = [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetObjectVersion",
]
# ホームディレクトリの S3 バケット
resources = [
"${aws_s3_bucket.xxxx.arn}/*",
]
}
}
先ほどのポリシードキュメントを使って、IAM ポリシーを定義します。SFTP ユーザ用のポリシーは、今回はインラインポリシーにしたいので、ここではポリシー定義していません。(利用頻度が高いのであれば、定義すると良いかと思います)
iam-policy.tf
#--------------------------------------
# IAM Policy
#--------------------------------------
resource "aws_iam_policy" "cwl-full" {
name = "cloudwatch-logs-full-policy"
policy = "${data.aws_iam_policy_document.cwl-full.json}"
}
そして IAM ロールを作成およびポリシーをアタッチします。
iam-role.tf
#--------------------------------------
# IAM Role
#--------------------------------------
# ログ出力用 IAM ロール
resource "aws_iam_role" "sftp-log-role" {
name = "sftp-log-role"
assume_role_policy = "${data.aws_iam_policy_document.assume-sftp.json}"
}
# SFTP ユーザ用 IAM ロール
resource "aws_iam_role" "sftpuser-role" {
name = "sftpuser-role"
assume_role_policy = "${data.aws_iam_policy_document.assume-sftp.json}"
}
#--------------------------------------
# IAM Policy Attachment
#--------------------------------------
# ログ出力用 IAM ロールにポリシーをアタッチ
resource "aws_iam_policy_attachment" "sftp-log-role" {
name = "sftp-log-role"
roles = [
"${aws_iam_role.sftp-log-role.id}",
]
policy_arn = "${aws_iam_policy.cwl-full.arn}"
}
#--------------------------------------
# IAM Role Policy
#--------------------------------------
# SFTP ユーザ用 インラインポリシーをアタッチ
resource "aws_iam_role_policy" "sftpuser-role" {
name = "sftpuser-role-policy"
role = "${aws_iam_role.sftpuser-role.id}"
policy = "${data.aws_iam_policy_document.sftpuser.json}"
}
そして Transfer for SFTP
前置きがながくなりましたが、ようやく Transfer for SFTP のリソース定義です。
transfer-sftp.tf
#--------------------------------------
# Transfer Server
#--------------------------------------
resource "aws_transfer_server" "sftp-server" {
identity_provider_type = "SERVICE_MANAGED"
# ログ出力用の IAM ロール
logging_role = "${aws_iam_role.sftp-log-role.arn}"
endpoint_details {
vpc_endpoint_id = "${aws_vpc_endpoint.sftp-vpce.id}"
}
# VPC エンドポイントタイプを指定
endpoint_type = "VPC_ENDPOINT"
}
#--------------------------------------
# Transfer user
#--------------------------------------
resource "aws_transfer_user" "sftp-user" {
server_id = "${aws_transfer_server.sftp-server.id}"
user_name = "sftpuser"
# ホームディレクトリに使用する S3 バケット名を指定
home_directory = "/${aws_s3_bucket.xxxx.id}"
# SFTP ユーザ用の IAM ロールを指定
role = "${aws_iam_role.sftpuser-role.arn}"
}
#--------------------------------------
# Transfer ssh key
#--------------------------------------
resource "aws_transfer_ssh_key" "sftp-ssh-key" {
server_id = "${aws_transfer_server.sftp-server.id}"
user_name = "${aws_transfer_user.sftp-ssnb.user_name}"
# SSH 公開鍵を指定
body = "ssh-rsa AAAABBBBBBCCCCCCC・・・・・"
}
接続に使用する SSH 公開鍵 を body
に指定します。以下のコマンドでキーペアファイルを利用することも可能です。
$ chmod 400 key-pair.pem
$ ssh-keygen -y -f key-pair.pem
ssh-rsa AAAABBBBBBCCCCCCC・・・・(省略)
tf ファイルが作成できましたら、terraform plan
して terraform apply
で構築しましょう!
接続してみる
今回、VPC エンドポイントタイプとして作成しましたので、sftp クライアントからの接続先は VPC エンドポイントの FQDN になります。先ほどの SSH キーの秘密鍵を使って接続します。
$ sftp -i key-pair.pem sftpuser@vpce-05xxxxxxxxx-xxxxxxxx.server.transfer.ap-northeast-1.vpce.amazonaws.com
sftp>
ログインできたので put
や get
が正しくできるか確認します。
# PUT
sftp> put test.txt
Uploading test.txt to /<home_directory>/test.txt
text.txt 100% 5 0.7KB/s 00:00
# GET
sftp> get test.txt
Fetching /<home_directory>/test.txt to test.txt
/<home_directory>/test.txt 100% 5 0.1KB/s 00:00
問題なく SFTP できることが確認できました!
さいごに
今回は1ユーザでの利用想定でしたが、次は複数ユーザを想定したスコープダウンポリシーも Terraform で作成してみたいと思います。
以上!大阪オフィスの丸毛(@marumo1981)でした!