ファイルをsftp経由でEC2にアップロード→lsyncdでS3へのアップロード連携を行う

2015.09.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS環境に於いてデータをs3にアップロードする際、通常であればAWS CLIやSDK等を使ってダイレクトにs3にアップロードする方法が一般的ではありますが、オンプレ側・アップロードする側の状況によってはその手法が使えない場合もあるかと思います。

今回ご紹介する内容は『sftpなら使える』と言うようなケースを想定しており、『lsyncd』を導入したEC2にsftp経由でファイルをアップロード→sftpがアップロードを検知してs3へのファイルアップロードを実施、という流れについての環境構築及び確認手順のご紹介となります。

目次

処理フローイメージ

今回実現する処理フローのイメージは以下の様な形になります。起点となるEC2サーバを用意し、EC2サーバに『lsyncd』というソフトウェアをインストールしておきます。設定を行なったlsyncdが稼働しているEC2の任意のフォルダにファイルがsftp経由でアップロードされると、稼働しているlsyncdがそのファイルを検知、行われた操作方法に応じた処理を行う...という流れです。最後の『行われた操作方法に応じた処理』の部分でAWS CLIによるS3へのファイルアップロード処理を記載しておく事で、ユーザーのEC2へのファイルアップロードからS3へのファイルアップロードが連携して行われる、というわけです。

ec2-s3-lsyncd_04

sftpアップロード用のEC2環境を用意

では、ここから必要な環境を整えて行きたいと思います。EC2環境に際してはAmazon Linuxの最新バージョンを用いてベースとなる環境を用意しました。今回は検証用なのであまり深く考えずに進めていますが、実運用でこういった環境を用いる場合は以下の様なポイントが考慮すべき点に挙がってくる事と思います。

  • ストレージ容量:アップロードするファイルの容量・総量・アップロード及び削除サイクルに応じたストレージ容量を確保する必要がある。
  • アクセス専用ユーザの作成:今回の手順ではec2-user経由でアクセス専用ユーザー(sftpuser)を作成し、以後は作成したユーザーでアクセスさせる形を想定。
  • セキュリティグループ:SFTPを用いるため、ポート番号は22のみ許可。併せて、アクセス先IP等の制御を行う必要がある。
  • 各種アクセス制限:IAM Roleの権限、S3のバケットに関するアクセス権限等。

sftp接続専用ユーザーの作成

EC2では特に意識しなければデフォルトで用意されているec2-userでアクセスする事になるかと思いますが、今回はEC2にsftp経由でアクセスするための専用ユーザーを用意し、そのユーザーでファイルのアップロードを行なってもらう形にしようと思います。

以下のエントリを参考に、sftpuserというSFTP接続専用のユーザーを作成します。

まずは従来通り、ec2-userでSSHログイン。

$ ssh -i xxxxxxxxxxx.pem ec2-user@xxx.xx.xx.xx
$ sudo yum -y update

接続用ユーザー: sftpuserを作成します。今回はパスワードも併せて設定しました。

$ sudo useradd sftpuser
$ sudo passwd sftpuser
ユーザー sftpuser のパスワードを変更。
新しいパスワード: *****************
新しいパスワードを再入力してください: *****************
passwd: 全ての認証トークンが正しく更新できました。
$

sftpユーザーの権限に関する設定を追記。

$ sudo visudo
----
## The COMMANDS section may have other options added to it.
##
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
sftpuser    ALL=(ALL)       ALL

sftpuserにsuして秘密鍵・公開鍵を作成します。

$ sudo su sftpuser

$ cd /home/sftpuser/
$ mkdir .ssh
$ cd .ssh/
$ ssh-keygen -t rsa

Generating public/private rsa key pair.
Enter file in which to save the key (/home/sftpuser/.ssh/id_rsa):     
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/sftpuser/.ssh/id_rsa.
Your public key has been saved in /home/sftpuser/.ssh/id_rsa.pub.
The key fingerprint is:
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX sftpuser@ip-xx-xx-xx-xxx
The key's randomart image is:
+--[ RSA 2048]----+
|            |
|            |
|            |
|            |
|            |
|            |
|            |
|            |
|            |
+-----------------+

出来ました。今回は作成されたファイルを以下の様にリネームしています。authorized_keysについては環境的にこの名前にする必要があるようです。

$ ls
id_rsa  id_rsa.pub
$ mv id_rsa.pub authorized_keys
$ mv id_rsa sftp-server.pem
$ ls
authorized_keys  sftp-server.pem
$ chmod 600 authorized_keys
$ cd ../
$ chmod 700 .ssh

秘密鍵の情報をツールアクセス用に控えておきます。(ローカルでファイルを作成しておいてください)

$ cat .ssh/sftp-server.pem

SSHの設定を行います。ファイルの内容を確認し、AuthorizedKeysFileの行が設定されている事を確認してください。無ければ下記内容で追記します。

$ sudo vi /etc/ssh/sshd_config
====
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
====

設定ファイルを使ってアクセス出来るか試してみます。Mac上で(上記ファイル内容を使って)作成したpemファイルを使い、アクセスを試みて見ます。

$ chmod 400 sftp-server.pem
$ ssh -i sftp-server.pem sftpuser@xxx.xx.xx.xxx

パスワード入力を求められます(上記でパスワード設定を行っているとこうなる)ので、入力を行い[OK]押下。

sftp-server-ssh-login

無事ログイン出来ました!

$ ssh -i sftp-server.pem sftpuser@xxx.xx.xx.xxx
Identity added: sftp-server.pem (sftp-server.pem)
Last login: Tue Sep  8 17:23:19 2015

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2015.03-release-notes/
$
$ whoami
sftpuser

ツールからSFTP経由でEC2に接続する(WinSCPの場合)

次は、SFTPツールを使ったログインを確認したいと思います。ツールはWinSCPを使いました。Windows8及びWinSCPを使った確認を今回行いましたが、環境やツールについては適宜対応するOSやツールで内容を読み替えて頂ければと思います。

ツール起動後、接続情報を入力するのと併せて、[PuTTYgenを実行]を選択。

sftp-server-ssh-login_01

[Load private key]を選択。

sftp-server-ssh-login_02

先程ローカルで作成したpemファイルを指定します。

sftp-server-ssh-login_03

ここでパスワード入力を求められますので、対応する内容を入力して[OK]押下。

sftp-server-ssh-login_04

認証が成功すると以下の様なダイアログが出ます。[OK]押下。

sftp-server-ssh-login_05

[Save private key]を押下し、ファイル保存へ進みます。

sftp-server-ssh-login_06

任意の名前で*.ppkファイルを作成します。今回は拡張子のみppkに変更した形でファイル保存(新規作成)を行いました。

sftp-server-ssh-login_07

次いで、[設定]を選択。

sftp-server-ssh-login_08

秘密鍵に、上記で生成したppkファイルを選択します。

sftp-server-ssh-login_09

[はい]を押下し、先へ進めます。

sftp-server-ssh-login_10

パスフレーズ入力を求められますのでパスワードを入力し、[OK]押下。

sftp-server-ssh-login_11

sftp経由で無事EC2環境への接続が行えました!

sftp-server-ssh-login_12

AWS CLI設定

EC2上でAWS CLIコマンドによるs3アップロードを行いたいため、一度AWS CLIの導入確認を行なっておきます。Amazon LinuxであればEC2起動時点でAWS CLIが利用出来るようにっています。

$ ssh -i sftp-server.pem sftpuser@xxx.xx.xx.xxx
Last login: Tue Sep  8 17:35:00 2015 from XXX.XXX.XXX.XXX.XXX

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2015.03-release-notes/
$ aws --version
aws-cli/1.7.45 Python/2.7.9 Linux/3.14.48-33.39.amzn1.x86_64
$

認証情報については、EC2に紐付けたIAM Roleの権限を利用する形を取ろうと思います。ですので、紐付けたIAM Roleの権限は必要な権限を有するようなものにしておいてください。

EC2-S3連携: lsyncdの導入

EC2とS3の同期については『lsyncd』という仕組みを利用します。lsyncdの詳細については以下の情報をご参照ください。

インストールはシンプルにyumで実行可能です。EPELリポジトリを指定した上で実行してください。

$ sudo yum -y install --enablerepo=epel lsyncd

次いで、EC2側にファイルをアップロードするディレクトリを準備。/home/sftpuser/csv-upload というフォルダを用意し、その中にファイルをアップロードしてもらう形を取ろうと思います。

$ mkdir csv-upload
$ cd csv-upload/
$ pwd
/home/sftpuser/csv-upload

対応するS3バケットも併せて用意します。こちらも、s3://cm-sftp-test/csv-upload/というバケット・ディレクトリを作成しました。

ec2-s3-lsyncd_01

挙動に関する部分はlsyncdの設定ファイルで指定します。/etc/lsyncd.confというファイルが空の内容で作成されていますので、必要事項を追記します。追記に際しては以下のエントリ等を参考にしました。

/etc/lsyncd.conf

----
-- User configuration file for lsyncd.
--
-- Simple example for default rsync, but executing moves through on the target.
--
-- For more examples, see /usr/share/doc/lsyncd*/examples/
--
-- sync{default.rsyncssh, source="/var/www/html", host="localhost", targetdir="/tmp/htmlcopy/"}

settings{
    logfile    = "/var/log/lsyncd.log",
    statusFile = "/var/log/lsyncd.status",
    nodaemon = false,
    statusInterval = 1,
    delay = 15,
}

s3sync = {
    maxProcesses = 1,
    onCreate = "[ -f ^source^pathname ] && aws s3 cp ^source^pathname ^target^pathname || true",
    onModify = "[ -f ^source^pathname ] && aws s3 cp ^source^pathname ^target^pathname || true",
    onDelete = "[ -f ^source^pathname ] && aws s3 rm ^target^pathname || true",
--  onMove = "aws s3 mv ^target^o.pathname ^target^d.pathname",
}

sync{
    s3sync,
    source = "/home/sftpuser/csv-upload",
    target = "s3://cm-sftp-test/csv-upload/",
}

設定の保存が完了したらlsyncdを再起動します。これで環境が準備出来ました。

$ sudo /etc/init.d/lsyncd restart
[sudo] password for sftpuser: 
lsyncd を停止中:                                           [  OK  ]
lsyncd を起動中:                                           [  OK  ]
$

動作確認

ここまでの作業でひと通りの環境が揃ったので、実際に連動してアップロードされるかどうか試してみます。CSVファイルを用意して所定のEC2フォルダにsftp経由でアップロードを行います。

ec2-s3-lsyncd_02

アップロードと併せて、ログファイル(上記設定内容の場合だと/var/log/lsyncd.log)を確認してみます。アップロード完了から程なくしてログが吐き出されてきました。

/var/log/lsyncd.log

Thu Sep 10 15:07:47 2015 Normal: Event Create spawns shell "[ -f /home/sftpuser/csv-upload//sftp-upload-test.csv ] && aws s3 cp /home/sftpuser/csv-upload//sftp-upload-test.csv s3://cm-sftp-test/csv-upload/sftp-upload-test.csv || true"
upload: home/sftpuser/csv-upload/sftp-upload-test.csv to s3://cm-sftp-test/csv-upload/sftp-upload-test.csv
Thu Sep 10 15:07:47 2015 Normal: Retrying Create on /home/sftpuser/csv-upload//sftp-upload-test.csv = 0
Thu Sep 10 15:07:48 2015 Normal: Event Create spawns shell "[ -f /home/sftpuser/csv-upload//sftp-upload-test2.csv ] && aws s3 cp /home/sftpuser/csv-upload//sftp-upload-test2.csv s3://cm-sftp-test/csv-upload/sftp-upload-test2.csv || true"
upload: home/sftpuser/csv-upload/sftp-upload-test2.csv to s3://cm-sftp-test/csv-upload/sftp-upload-test2.csv
Thu Sep 10 15:07:48 2015 Normal: Retrying Create on /home/sftpuser/csv-upload//sftp-upload-test2.csv = 0
Thu Sep 10 15:07:49 2015 Normal: Event Create spawns shell "[ -f /home/sftpuser/csv-upload//sftp-upload-test3.csv ] && aws s3 cp /home/sftpuser/csv-upload//sftp-upload-test3.csv s3://cm-sftp-test/csv-upload/sftp-upload-test3.csv || true"
upload: home/sftpuser/csv-upload/sftp-upload-test3.csv to s3://cm-sftp-test/csv-upload/sftp-upload-test3.csv
Thu Sep 10 15:07:49 2015 Normal: Retrying Create on /home/sftpuser/csv-upload//sftp-upload-test3.csv = 0

S3の内容を確認してみます。こちらにもちゃんとファイルがアップロードされている事を確認出来ました!

ec2-s3-lsyncd_03

まとめ

以上、lsyncdを使ったsftp経由でのEC2ファイルアップロード、からのS3アップロード連携に関する手順のご紹介でした。参考にした情報の中には『lsyncdは時々調子悪くなるので再起動した方が良い』『monitで監視させておく事が望ましい』という記述も見られましたので、より万全を期する場合はその辺りの対処も併せて行うべきかと思われます。こちらからは以上です。

その他参考情報: