Mountpoint for Amazon S3でS3バケットをマウントしたEC2インスタンスをSFTPサーバーとして動作させてみた

Mountpoint for Amazon S3でS3バケットをマウントしたEC2インスタンスをSFTPサーバーとして動作させてみた

Clock Icon2024.08.12

S3バケットにSFTPで接続したい

こんにちは、のんピ(@non____97)です。

皆さんはS3バケットにSFTPで接続したいなと思ったことはありますか? 私はあります。

S3バケットにSFTPで接続したい場合は大きく2パターンあります。

  1. S3バケットに対応したSFTPクライアントで接続する
  2. ドメインがS3のAWS Transfer Familyを用意し、SFTPクライアントで接続する

最初に選択するのは前者だと考えます。SFTPクライアントとIAMユーザーを用意するだけです。コストも転送料金とS3バケットのストレージ料金程度でしょう。

WinSCPの場合は以下記事を参考に実装できます。

https://dev.classmethod.jp/articles/connected-to-s3-with-winscp/

また、Cyberduckの様にMFAに対応したものであれば、よりセキュアに使用できます。

https://dev.classmethod.jp/articles/cyberduck-mfa-assumerole-windows-10/

ただし、利用者数が非常に多かったり、利用者が自組織外だったりする場合は、IAMユーザーやIAM Identity Centerの発行が大変だったりします。IAMユーザーの場合は初期認証情報を渡すプロセスも煩雑になりがちです。

そんな時にはAWS Transfer Familyが候補になります。AWS Transfer Familyはパスワードだけでなく、鍵、ドメイン認証などが使用できます。

しかし、AWS Transfer Familyのネックとなるのはコストです。以下記事で紹介されている様に、何も通信が発生しなくとも216 USD/monthほどのコストがかかります。

https://dev.classmethod.jp/articles/202210-aws-transfer-family-sftp/

上述以外の候補に「Mountpoint for Amazon S3でS3バケットをマウントしたEC2インスタンスをSFTPサーバーとして動作させる」方法もあると思います。

Mountpoint for Amazon S3の詳細は以下記事をご覧ください。

https://dev.classmethod.jp/articles/amazon-s3-mountpoint-ga-update/

この方式であれば、パターン1の方法にEC2インスタンスの料金が追加する程度です。利用者間でSFTPを使ってファイルを単純に授受するレベルであればインスタンスタイプも安価なもので良いでしょう。

ユーザー追加も利用者側に鍵を作成してもらい、受け取った公開鍵をEC2インスタンスに登録する程度です。

以下の懸念点を十分理解し、許容できるのであれば十分選択肢に入るような気がしています。

  • EC2インスタンスのコストがかかる
  • EC2インスタンス上のOSユーザーの管理コストがかかる
  • EC2インスタンスのセキュリティアップデートなどのメンテナンスが必要
  • EC2インスタンス1台構成の場合、EC2インスタンスが停止している間、SFTPで接続できない
  • 完全な POSIX セマンティクスをサポートしていない

セマンティクスの詳細はMountpoint for Amazon S3のREADMEをご覧ください。

https://github.com/awslabs/mountpoint-s3/blob/main/doc/SEMANTICS.md

実際に試してみて、SFTPサーバーとして動作できるのか確認してみました。

やってみた

検証環境

検証環境は以下のとおりです。

Mountpoint for Amazon S3でS3バケットをマウントしたEC2インスタンスをSFTPサーバーとして動作させてみた検証環境構成図.png

Mountpoint for Amazon S3でEC2インスタンスからS3バケットをマウントしています。

自端末からインターネット越しにSFTPで接続し、ファイルのGETやPUT、DELETEなどを行います。

Mountpoint for Amazon S3インストールおよび設定スクリプト

Mountpoint for Amazon S3を使ったマウントはユーザーデータのシェルスクリプトで行っています。

行っている処理は以下のとおりです。

  • 変数宣言
    • バケット名
    • マウントポイント
    • Mountpoint for Amazon S3のログ出力先のディレクトリパス
    • SFTPユーザー兼Mountpoint for Amazon S3のサービスユーザーの名前
    • SFTPユーザーのグループ名
    • CPUアーキテクチャ
      • Mountpoint for Amazon S3をインストールする際に使用
  • SFTPユーザー兼Mountpoint for Amazon S3のサービスユーザーの作成
  • Mountpoint for Amazon S3のインストール
  • マウントポイントとログ出力先ディレクトリの作成
  • ountpoint for Amazon S3のサービスユーザー以外もマウントポイント上の操作をできるように/etc/fuse.confを変更
  • Mountpoint for Amazon S3のsystemdサービスの作成
  • Mountpoint for Amazon S3のsystemdサービスの自動起動の有効化および起動
  • SFTPユーザーが鍵認証できるように設定
  • 指定したグループのchrootの設定およびSFTPのみできるように設定

systemdのサービスを作成したのはEC2インスタンス起動時に自動でマウントするためです。以下記事を参考にしました。

https://dev.classmethod.jp/articles/how-to-auto-mount-mountpoint-for-amazon-s3-using-systemd/

ユーザーデータのシェルスクリプトは以下のとおりです。

lib/ec2/user-data/install_mountpoint_s3.sh
#!/usr/bin/env bash

# -x to display the command to be executed
set -xeu

# Redirect /var/log/user-data.log and /dev/console
exec > >(tee /var/log/user-data.log | logger -t user-data -s 2>/dev/console) 2>&1

# Declare
readonly bucket_name="_bucket_name_"
readonly mount_dir="/mnt/s3/${bucket_name}"
readonly log_dir="/var/log/amazon/mountpoint-s3"
readonly user_name="sftp-s3"
readonly group_name="${user_name}"
readonly architecture="arm64"

# Add SFTP user
useradd "${user_name}" -U

# Install Mountpoint for Amazon S3
wget https://s3.amazonaws.com/mountpoint-s3-release/latest/${architecture}/mount-s3.rpm
dnf install -y ./mount-s3.rpm

mkdir -p "${mount_dir}"
mkdir -p "${log_dir}"
chown "${user_name}":"${group_name}" "${mount_dir}"
chown "${user_name}":"${group_name}" "${log_dir}"

# Allow other users to access mount
# Needed if --allow-root or --allow-other option is set
if ! grep -q "^user_allow_other" /etc/fuse.conf; then
    echo "user_allow_other" | tee -a /etc/fuse.conf
fi

# Unit file of Mountpoint for Amazon S3
tee /etc/systemd/system/mountpoint-s3-${bucket_name}.service << EOF
[Unit]
ConditionPathExists=/usr/bin/mount-s3
Wants=network-online.target 
After=network-online.target 

[Service]
User=${user_name}
Group=${group_name}
Type=oneshot
RemainAfterExit=yes

ExecStart=/usr/bin/mount-s3 ${bucket_name} ${mount_dir} --allow-delete --allow-overwrite --allow-other -l ${log_dir} --dir-mode 0775 --file-mode 0664
ExecStop=/usr/bin/umount ${mount_dir}

[Install]
WantedBy=multi-user.target
EOF

# Start Mountpoint for Amazon S3 service
systemctl daemon-reload
systemctl list-unit-files --type=service | grep mountpoint
systemctl enable mountpoint-s3-${bucket_name}.service --now

# Set SFTP user
mkdir /home/${user_name}/.ssh
chmod 700 /home/${user_name}/.ssh
touch /home/${user_name}/.ssh/authorized_keys
chmod 600 /home/${user_name}/.ssh/authorized_keys
chown -R ${user_name}:${group_name} /home/${user_name}/.ssh

# Set chroot for SFTP user
tee -a /etc/ssh/sshd_config << EOF
Match Group ${group_name}
        ChrootDirectory /mnt/s3/
        ForceCommand internal-sftp
EOF

systemctl restart sshd

参考までにMountpoint for Amazon S3のヘルプを以下に記載します。オプションで指定すれば削除や上書きもできるようになっています。

$ mount-s3 --version
mount-s3 1.8.0

$ mount-s3 --help
Mountpoint for Amazon S3

Usage: mount-s3 [OPTIONS] <BUCKET_NAME> <DIRECTORY>

Arguments:
  <BUCKET_NAME>  Name of bucket to mount
  <DIRECTORY>    Directory to mount the bucket at

Options:
  -f, --foreground  Run as foreground process
  -h, --help        Print help
  -V, --version     Print version

Bucket options:
      --prefix <PREFIX>
          Prefix inside the bucket to mount, ending in '/' [default: mount the entire bucket]
      --region <REGION>
          AWS region of the bucket [default: auto-detect region]
      --endpoint-url <ENDPOINT_URL>
          S3 endpoint URL [default: auto-detect endpoint]
      --force-path-style
          Force path-style addressing
      --transfer-acceleration
          Use S3 Transfer Acceleration when accessing S3. This must be enabled on the bucket.
      --dual-stack
          Use dual-stack endpoints when accessing S3
      --requester-pays
          Set the 'x-amz-request-payer' to 'requester' on S3 requests
      --bucket-type <BUCKET_TYPE>
          Type of S3 bucket to use [default: inferred from bucket name] [possible values: general-purpose, directory]
      --storage-class <STORAGE_CLASS>
          Set the storage class for new objects
      --expected-bucket-owner <AWS_ACCOUNT_ID>
          Account ID of the expected bucket owner. If the bucket is owned by a different account, S3 requests fail with an access denied error.
      --sse <SSE>
          Server-side encryption algorithm to use when uploading new objects [possible values: aws:kms, aws:kms:dsse, AES256]
      --sse-kms-key-id <AWS_KMS_KEY_ARN>
          AWS Key Management Service (KMS) key ARN to use with KMS server-side encryption when uploading new objects. Key ID, Alias and Alias ARN are all not supported.
      --upload-checksums <ALGORITHM>
          Checksum algorithm to use for S3 uploads [default: crc32c] [possible values: crc32c, off]

AWS credentials options:
      --no-sign-request    Do not sign requests. Credentials will not be loaded if this argument is provided.
      --profile <PROFILE>  Use a specific profile from your credential file.

Mount options:
      --read-only              Mount file system in read-only mode
      --allow-delete           Allow delete operations on file system
      --allow-overwrite        Allow overwrite operations on file system
      --auto-unmount           Automatically unmount on exit
      --allow-root             Allow root user to access file system
      --allow-other            Allow other users, including root, to access file system
      --uid <UID>              Owner UID [default: current user's UID]
      --gid <GID>              Owner GID [default: current user's GID]
      --dir-mode <DIR_MODE>    Directory permissions [default: 0755]
      --file-mode <FILE_MODE>  File permissions [default: 0644]

Client options:
      --maximum-throughput-gbps <N>  Maximum throughput in Gbps [default: auto-detected on EC2 instances, 10 Gbps elsewhere]
      --max-threads <N>              Maximum number of FUSE daemon threads [default: 16]
      --part-size <SIZE>             Part size for multi-part GET and PUT in bytes [default: 8388608]
      --read-part-size <SIZE>        Part size for GET in bytes [default: 8388608]
      --write-part-size <SIZE>       Part size for multi-part PUT in bytes [default: 8388608]

Logging options:
  -l, --log-directory <DIRECTORY>  Write log files to a directory [default: logs written to syslog]
      --log-metrics                Enable logging of summarized performance metrics
  -d, --debug                      Enable debug logging for Mountpoint
      --debug-crt                  Enable debug logging for AWS Common Runtime
      --no-log                     Disable all logging. You will still see stdout messages.

Caching options:
      --cache <DIRECTORY>
          Enable caching of object content to the given directory and set metadata TTL to 60 seconds
      --metadata-ttl <SECONDS|indefinite|minimal>
          Time-to-live (TTL) for cached metadata in seconds [default: minimal, or 60 seconds if --cache is set]
      --max-cache-size <MiB>
          Maximum size of the cache directory in MiB [default: preserve 5% of available space]

Advanced options:
      --user-agent-prefix <PREFIX>  Configure a string to be prepended to the 'User-Agent' HTTP request header for all S3 requests

Mountpoint for Amazon S3でS3バケットをマウントしているかを確認

Mountpoint for Amazon S3でS3バケットをマウントしているかを確認します。

検証環境はAWS CDKでデプロイしました。使用したコードは以下リポジトリに保存しています。

https://github.com/non-97/mountpoint-s3-sftp

起動完了後、EC2インスタンスにSSMセッションマネージャーで接続し、サービスやマウントの状態を確認します。

$ systemctl status mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
● mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service
     Loaded: loaded (/etc/systemd/system/mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service; enabled; preset: disabled)
     Active: active (exited) since Mon 2024-08-12 05:23:59 UTC; 2min 4s ago
   Main PID: 3324 (code=exited, status=0/SUCCESS)
      Tasks: 9 (limit: 1004)
     Memory: 5.6M
        CPU: 120ms
     CGroup: /system.slice/mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service
             └─3365 /usr/bin/mount-s3 mountpoints3sftpstack-bucket83908e77-pqysme6vaopb /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb --allow-delete --allow-overwrite --allow-other -l /var/log/amazon/mountpoint-s3 --dir-mode 0775 --file-mode 0664

Aug 12 05:23:59 ip-10-10-10-5.ec2.internal systemd[1]: Starting mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service...
Aug 12 05:23:59 ip-10-10-10-5.ec2.internal mount-s3[3324]: bucket mountpoints3sftpstack-bucket83908e77-pqysme6vaopb is mounted at /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
Aug 12 05:23:59 ip-10-10-10-5.ec2.internal systemd[1]: Finished mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service.

$ mount | grep s3
mountpoint-s3 on /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb type fuse (rw,nosuid,nodev,noatime,user_id=1001,group_id=1001,default_permissions,allow_other)

マウントできていそうですね。

マウントポイントをlsで確認します。現時点ではS3バケット上に何も置いていないので空です。

$ ls -ld /mnt/s3
drwxr-xr-x. 3 root root 63 Aug 12 05:23 /mnt/s3

$ ls -l /mnt/s3
total 0
drwxrwxr-x. 2 sftp-s3 sftp-s3 0 Aug 12 05:23 mountpoints3sftpstack-bucket83908e77-pqysme6vaopb

$ ls -l /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/
total 0

SFTPでファイルのPUT

SFTPでファイルのPUTをします。

下準備としてセキュリティグループで自端末のIPアドレスを許可します。

1.セキュリティグループの変更.png

続いて、SFTPユーザー用の鍵を作成します。

> ssh-keygen -t ed25519 -C "sftp-s3" -f ./sftp-s3
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./sftp-s3
Your public key has been saved in ./sftp-s3.pub
The key fingerprint is:
SHA256:5Ea1F37EnoArTXqP5cPN23vcI7mdX+FVTZu/haOj6I4 sftp-s3
The key's randomart image is:
+--[ED25519 256]--+
|          ..... .|
|         .oo.o..+|
|        o+..oo.+o|
|       +o +...o.o|
|        So * oo.+|
|       .  . =.+.=|
|            o..*o|
|       . . . +o.B|
|      Eo+ .  .o+*|
+----[SHA256]-----+

> cat sftp-s3.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC/kWz4C1jBXHjTA1uF6/RO9uauvXARmDVFPF1O7dS48 sftp-s3

作成した公開鍵をEC2インスタンスに登録します。

$ sudo vi /home/sftp-s3/.ssh/authorized_keys

$ sudo ls -l /home/sftp-s3/.ssh/authorized_keys
-rw-------. 1 sftp-s3 sftp-s3 89 Aug 12 05:29 /home/sftp-s3/.ssh/authorized_keys

PUT用に手元の端末で適当なファイルを作成します。

> echo test > test.txt

SFTPで接続します。

>  sftp -i ./sftp-s3 sftp-s3@ec2-54-198-70-121.compute-1.amazonaws.com
Connected to ec2-54-198-70-121.compute-1.amazonaws.com.
sftp> pwd
Remote working directory: /
sftp> ls -l
drwxrwxr-x    2 1001     1001            0 Aug 12 05:23 mountpoints3sftpstack-bucket83908e77-pqysme6vaopb

接続できましたね。chrootで/mnt/s3をルートにしているのも正常に動作していそうです。

/mnt/s3はrootユーザーでしか書き込めないようにしているので、ここでは書き込めません。

sftp> put test.txt
Uploading test.txt to /test.txt
dest open "/test.txt": Permission denied

マウントポイントである/mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopbに書き込めるか確認します。

sftp> cd mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
sftp> put test.txt
Uploading test.txt to /mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/test.txt
test.txt                                                                                                                                                                                                             100%    5     0.0KB/s   00:00
sftp> ls -l
-rw-rw-r--    1 1001     1001            5 Aug 12 05:35 test.txt

書き込めました。

PUTされたファイルがEC2インスタンス上でも表示できることを確認します。

$ ls -l /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/
total 1
-rw-rw-r--. 1 sftp-s3 sftp-s3 5 Aug 12 05:35 test.txt

$ cat /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/test.txt
test

表示できましたね。

SFTPでファイルの上書き

SFTPでファイルの上書きができるか確認します。

手元の端末でファイルに追記します。

> echo test2 >> test.txt

追記したファイルをPUTします。

sftp> put test.txt
Uploading test.txt to /mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/test.txt
test.txt                                                                                                                                                                                                             100%   11     0.1KB/s   00:00
sftp> ls -l
-rw-rw-r--    1 1001     1001           11 Aug 12 05:38 test.txt

EC2インスタンス上で上書きされたかどうか確認します。

$ cat /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/test.txt
test
test2

上書きされていますね。

SFTPでファイルのGET

SFTPでファイルのGETができるかも確認します。

EC2インスタンス上で適当にファイルを作成します。

$ echo get-test | sudo tee /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/get-test.txt > /dev/null
$ ls -l /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/
total 1
-rw-rw-r--. 1 sftp-s3 sftp-s3  9 Aug 12 05:40 get-test.txt
-rw-rw-r--. 1 sftp-s3 sftp-s3 11 Aug 12 05:38 test.txt

SFTPでファイルをGETします。

sftp> ls -l
-rw-rw-r--    1 1001     1001            9 Aug 12 05:40 get-test.txt
-rw-rw-r--    1 1001     1001           11 Aug 12 05:38 test.txt

sftp> get get-test.txt
Fetching /mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/get-test.txt to get-test.txt
get-test.txt

GETできていそうです。

catします。

> cat get-test.txt
get-test

正常に表示できましたね。問題なさそうです。

SFTPでファイルのDELETE

SFTPでファイルのDELETEができるか確認します。

sftp> rm test.txt
Removing /mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/test.txt

sftp> ls -l
-rw-rw-r--    1 1001     1001            9 Aug 12 05:40 get-test.txt

はい、問題なくできました。

SFTPユーザーでSSHできないことを確認

SFTPユーザーでSSHできないことを確認します。

/etc/ssh/sshd_configでSFTP用のグループはinternal-sftpでSFTPでしか接続できないようにしています。

$ sudo tail /etc/ssh/sshd_config
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server

AuthorizedKeysCommand /opt/aws/bin/eic_run_authorized_keys %u %f
AuthorizedKeysCommandUser ec2-instance-connect
Match Group sftp-s3
        ChrootDirectory /mnt/s3/
        ForceCommand internal-sftp

実際に動作するか確認します。

> ssh -i ./sftp-s3 sftp-s3@ec2-54-198-70-121.compute-1.amazonaws.com
This service allows sftp connections only.
Connection to ec2-54-198-70-121.compute-1.amazonaws.com closed.

はい、This service allows sftp connections only.と拒否されましたね。

ちなみにjournalには以下のように記録されています。

$ journalctl -u sshd | tail
Aug 12 05:33:44 ip-10-10-10-5.ec2.internal sshd[25629]: Accepted publickey for sftp-s3 from <接続元IPアドレス> port 59384 ssh2: ED25519 SHA256:5Ea1F37EnoArTXqP5cPN23vcI7mdX+FVTZu/haOj6I4
Aug 12 05:33:44 ip-10-10-10-5.ec2.internal sshd[25629]: pam_unix(sshd:session): session opened for user sftp-s3(uid=1001) by (uid=0)
Aug 12 05:43:11 ip-10-10-10-5.ec2.internal sshd[25996]: Accepted publickey for sftp-s3 from <接続元IPアドレス> port 59709 ssh2: ED25519 SHA256:5Ea1F37EnoArTXqP5cPN23vcI7mdX+FVTZu/haOj6I4
Aug 12 05:43:11 ip-10-10-10-5.ec2.internal sshd[25996]: pam_unix(sshd:session): session opened for user sftp-s3(uid=1001) by (uid=0)
Aug 12 05:43:11 ip-10-10-10-5.ec2.internal sshd[25996]: error: /dev/pts/1: No such file or directory [postauth]
Aug 12 05:43:11 ip-10-10-10-5.ec2.internal sshd[25996]: error: open /dev/tty failed - could not set controlling tty: No such file or directory [postauth]
Aug 12 05:43:11 ip-10-10-10-5.ec2.internal sshd[25996]: error: Connection from user sftp-s3 <接続元IPアドレス> port 59709: refusing non-sftp session [postauth]
Aug 12 05:43:11 ip-10-10-10-5.ec2.internal sshd[25996]: Received disconnect from <接続元IPアドレス> port 59709:11: disconnected by user [postauth]
Aug 12 05:43:11 ip-10-10-10-5.ec2.internal sshd[25996]: Disconnected from user sftp-s3 <接続元IPアドレス> port 59709 [postauth]
Aug 12 05:43:11 ip-10-10-10-5.ec2.internal sshd[25996]: pam_unix(sshd:session): session closed for user sftp-s3

SFTPサーバーとして動作させ、利用者にはSFTP経由でS3バケット上のオブジェクトの操作しかさせたくないのであれば、このような制限をしてあげると良いでしょう。

SFTPユーザーの追加

SFTPユーザーを追加したい場合は大きく以下の3ステップです。

  1. SFTPユーザーの追加
  2. SFTPユーザー用の鍵の作成
  3. SFTPユーザーの公開鍵の登録です。

まず、SFTPユーザーの追加をします。追加は以下スクリプトで可能です。

readonly user_name=sftp-user_1  # 任意の名前
readonly group_name=sftp-s3     # サービス起動時に指定したグループ

sudo useradd "${user_name}" -g "${group_name}"

sudo mkdir /home/${user_name}/.ssh
sudo chmod 700 /home/${user_name}/.ssh
sudo touch /home/${user_name}/.ssh/authorized_keys
sudo chmod 600 /home/${user_name}/.ssh/authorized_keys
sudo chown -R ${user_name}:${group_name} /home/${user_name}/.ssh

SFTPユーザー用の鍵の作成は先ほど実施したものと同様です。

> ssh-keygen -t ed25519 -C "sftp-user_1" -f ./sftp-user_1
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./sftp-user_1
Your public key has been saved in ./sftp-user_1.pub
The key fingerprint is:
SHA256:mLy+1LGixO2RjzmzWtq65X8jFn4DBZi7Ws0W7XAgYWk sftp-user_1
The key's randomart image is:
+--[ED25519 256]--+
|      o=         |
|     .E o        |
|     . o +       |
|     ..oo +      |
|      ++S*       |
|   . .o+*o.      |
|    ooXooo       |
|   ..@o*+ =      |
|    *+XBo+ o     |
+----[SHA256]-----+

> cat sftp-user_1.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINobmNDj4i31T3OOOG6vq/xvGjdH+ojxEM3RehXkaK7j sftp-user_1

SFTPユーザーの鍵の作成が完了したら、生成された公開鍵を共有してもらい、EC2インスタンスに登録します。

sudo vi /home/${user_name}/.ssh/authorized_keys

以上で追加したユーザーでSFTPを使って接続できるようになります。

> sftp -i ./sftp-user_1 sftp-user_1@ec2-54-198-70-121.compute-1.amazonaws.com
Connected to ec2-54-198-70-121.compute-1.amazonaws.com.
sftp> ls -l
drwxrwxr-x    2 1001     1001            0 Aug 12 05:23 mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
sftp> cd mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
sftp> ls -l
-rw-rw-r--    1 1001     1001            9 Aug 12 05:40 get-test.txt

sftp> put test.txt
Uploading test.txt to /mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/test.txt
test.txt                                                                                                                                                                                                             100%   11     0.1KB/s   00:00

sftp> ls -l
-rw-rw-r--    1 1001     1001            9 Aug 12 05:40 get-test.txt
-rw-rw-r--    1 1001     1001           11 Aug 12 05:47 test.txt

sftp> get get-test.txt
Fetching /mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/get-test.txt to get-test.txt
get-test.txt                                                                                                                                                                                                         100%    9     0.0KB/s   00:00

サービスの停止でマウントが外れることを確認

サービスの停止でマウントが外れることを確認します。

$ sudo systemctl stop mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb

$ systemctl status mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
○ mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service
     Loaded: loaded (/etc/systemd/system/mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service; enabled; preset: disabled)
     Active: inactive (dead) since Mon 2024-08-12 05:51:29 UTC; 7s ago
   Duration: 27min 30.155s
    Process: 26385 ExecStop=/usr/bin/umount /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb (code=exited, status=0/SUCCESS)
   Main PID: 3324 (code=exited, status=0/SUCCESS)
        CPU: 871ms

Aug 12 05:23:59 ip-10-10-10-5.ec2.internal systemd[1]: Starting mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service...
Aug 12 05:23:59 ip-10-10-10-5.ec2.internal mount-s3[3324]: bucket mountpoints3sftpstack-bucket83908e77-pqysme6vaopb is mounted at /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
Aug 12 05:23:59 ip-10-10-10-5.ec2.internal systemd[1]: Finished mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service.
Aug 12 05:51:29 ip-10-10-10-5.ec2.internal systemd[1]: Stopping mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service...
Aug 12 05:51:29 ip-10-10-10-5.ec2.internal systemd[1]: mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service: Killing process 26390 (EvntLoopCleanup) with signal SIGKILL.
Aug 12 05:51:29 ip-10-10-10-5.ec2.internal systemd[1]: mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service: Deactivated successfully.
Aug 12 05:51:29 ip-10-10-10-5.ec2.internal systemd[1]: Stopped mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service.

$ ls -l /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/
total 0

マウントが外れ、マウントポイントにアクセスしてもファイルが見当たりません。意図したとおりです。

SFTPでも同様にファイルを確認できないようになりました。

sftp> pwd
Remote working directory: /mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
sftp> ls -l
sftp>

サービスの起動を行います。

$ sudo systemctl start mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb

$ systemctl status mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
● mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service
     Loaded: loaded (/etc/systemd/system/mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service; enabled; preset: disabled)
     Active: active (exited) since Mon 2024-08-12 05:52:35 UTC; 3s ago
    Process: 26468 ExecStart=/usr/bin/mount-s3 mountpoints3sftpstack-bucket83908e77-pqysme6vaopb /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb --allow-delete --allow-overwrite --allow-other -l /var/log/amazon/mountpoint-s3 --dir-mode 0775>
   Main PID: 26468 (code=exited, status=0/SUCCESS)
      Tasks: 10 (limit: 1004)
     Memory: 5.3M
        CPU: 66ms
     CGroup: /system.slice/mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service
             └─26469 /usr/bin/mount-s3 mountpoints3sftpstack-bucket83908e77-pqysme6vaopb /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb --allow-delete --allow-overwrite --allow-other -l /var/log/amazon/mountpoint-s3 --dir-mode 0775 --file->

Aug 12 05:52:35 ip-10-10-10-5.ec2.internal systemd[1]: Starting mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service...
Aug 12 05:52:35 ip-10-10-10-5.ec2.internal mount-s3[26468]: bucket mountpoints3sftpstack-bucket83908e77-pqysme6vaopb is mounted at /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
Aug 12 05:52:35 ip-10-10-10-5.ec2.internal systemd[1]: Finished mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service.

$ ls -l /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/
total 1
-rw-rw-r--. 1 sftp-s3 sftp-s3  9 Aug 12 05:40 get-test.txt
-rw-rw-r--. 1 sftp-s3 sftp-s3 11 Aug 12 05:47 test.txt

サービスの起動をするとファイルを確認できるようになりました。

EC2インスタンス起動時にサービスが自動起動することを確認

EC2インスタンス起動時にサービスが自動起動することを確認をします。

EC2インスタンスを再起動します。

再起動後、サービスの状態を確認します。

$ systemctl status mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
● mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service
     Loaded: loaded (/etc/systemd/system/mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service; enabled; preset: disabled)
     Active: active (exited) since Mon 2024-08-12 05:53:41 UTC; 42s ago
    Process: 1588 ExecStart=/usr/bin/mount-s3 mountpoints3sftpstack-bucket83908e77-pqysme6vaopb /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb --allow-delete --allow-overwrite --allow-other -l /var/log/amazon/mountpoint-s3 --dir-mode 0775 ->
   Main PID: 1588 (code=exited, status=0/SUCCESS)
      Tasks: 9 (limit: 1004)
     Memory: 14.9M
        CPU: 92ms
     CGroup: /system.slice/mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service
             └─1609 /usr/bin/mount-s3 mountpoints3sftpstack-bucket83908e77-pqysme6vaopb /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb --allow-delete --allow-overwrite --allow-other -l /var/log/amazon/mountpoint-s3 --dir-mode 0775 --file-mo>

Aug 12 05:53:41 ip-10-10-10-5.ec2.internal systemd[1]: Starting mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service...
Aug 12 05:53:41 ip-10-10-10-5.ec2.internal mount-s3[1588]: bucket mountpoints3sftpstack-bucket83908e77-pqysme6vaopb is mounted at /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
Aug 12 05:53:41 ip-10-10-10-5.ec2.internal systemd[1]: Finished mountpoint-s3-mountpoints3sftpstack-bucket83908e77-pqysme6vaopb.service.

$ ls -l /mnt/s3/mountpoints3sftpstack-bucket83908e77-pqysme6vaopb/
total 1
-rw-rw-r--. 1 sftp-s3 sftp-s3  9 Aug 12 05:40 get-test.txt
-rw-rw-r--. 1 sftp-s3 sftp-s3 11 Aug 12 05:47 test.txt

サービスが起動し、マウントできていることが分かります。

AWS CLIで表示されているオブジェクト一覧とも一致しています。

$ aws s3 ls s3://mountpoints3sftpstack-bucket83908e77-pqysme6vaopb
2024-08-12 14:40:22          9 get-test.txt
2024-08-12 14:47:26         11 test.txt

コスト試算

コスト試算をしてみます。

条件は以下です。

項目 条件
リージョン 東京リージョン
インスタンスタイプ t4g.micro
支払いオプション オンデマンド
EBSボリュームタイプ gp3
ボリュームサイズ 10GB
スナップショットの頻度 毎日
スナップショットごとの変更量 100MB
アウトバウンド送信データ転送量 100GB
パブリックIPv4アドレス あり

この場合の料金は22.06 USD/monthです。

項目ごとの料金は以下のとおりです。

項目 金額
インスタンス料金 7.8840 USD
EBSボリューム料金 0.96 USD
EBSスナップショット料金 1.53 USD
データ転送料金 9.00 USD
パブリックIPv4アドレス料金 3.65 USD (月730時間で計算)

アウトバウンドのデータ転送量が少ないのであれば、15 USD/monthほどで使用できそうです。

S3バケットをデータストアにしたセルフマネージドなSFTPサーバーが欲しい場合に

Mountpoint for Amazon S3でS3バケットをマウントしたEC2インスタンスをSFTPサーバーとして動作させてみました。

S3バケットをデータストアにしたセルフマネージドなSFTPサーバーが欲しい場合には十分使えそうな気がしています。

利用する際は冒頭挙げた注意点を理解した上で使用しましょう。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.