概要
やること
今回は検証目的なので、必要最小限で以下の要件とする。
- Nginx+Gunicorn+Djangoの構成(同一サーバー上)
- Djangoアプリケーションは、私が公式のDjangoチュートリアルをやった際のリポジトリを使用する。
- ブラウザにDjangoの任意の画面が表示されればOK
- DBはSQLite(RDSは使わない)
- 静的コンテンツは同一サーバー上に配置する。(S3は使わない)
- Python3とNginxはAmazonのリポジトリからパッケージインストールする。
- ログは以下を
/var/log
配下に出力する。 - NginxとGunicornの通信にはUnixドメインソケットを使用する。
参考文献
- 『Pythonプロフェッショナルプログラミング 第3版』の「Chapter 11 環境構築とデプロイの自動化」
- 『現場で使える Django の教科書《実践編》』の「第7章 デプロイ」
その1:ユーザー作成
概要
EC2上に必要なユーザーを作成する。
作成するユーザー
以下のユーザーを作成する。
No | ユーザー名 | sudo権限 | 目的 |
---|---|---|---|
1 | admin | ○ | サーバー構築・sudo権限が必要なオペレーションの実行 |
2 | release | × | ソースコードの取得・管理 |
3 | webserver | × | Nginxの起動 |
4 | appserver | × | Gunicornの起動 |
方針
rootユーザーは使わない
rootユーザーで作業することは、以下の記事に書かれているように、セキュリティ的に問題があるため、rootユーザーは使用せず、sudo権限のある管理者ユーザーを作成する。
アプリケーションを起動するユーザーの権限を最小限にする
『体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践』の「OSコマンド・インジェクション」の項には以下のように書かれている。
OSコマンド・インジェクション脆弱性を攻撃された場合、コマンドの実行権限はWebアプリケーションの持つ権限となるため、Webアプリケーションの権限を必要最低限に制限しておくと、攻撃の被害を最小限にとどめることができます。(中略)
このユーザ権限を最小限にするという保険的対策は、ディレクトリ・トラバーサル脆弱性などに対しても有効です。
p307
極端な例を挙げると、OSコマンド・インジェクション脆弱性が存在して、rm -rf /
を実行されたとしても、ユーザーの権限を正しく設計していれば、削除されるのは「Webアプリケーションを起動しているユーザー」が書き込み権限を持っているディレクトリ・ファイルに限定される。
もし、rootでWebアプリケーションを起動していると、理論上は全てのディレクトリ・ファイルが削除されてしまう。
(やったことないので実際どうなるのかは知らない。実際にやってみた方の記事があった。)
qiita.com
従って、Nginxを起動するユーザー・Gunicornを起動するユーザーには、それぞれ権限の小さい専用のユーザーを作成する。
手順
0.事前準備(重要)
何も考えずに流れに沿ってEC2インスタンスを作成すると、以下のセキュリティグループが割り当てられているため、(鍵があれば)全世界からssh可能な状態になっており、EC2インスタンスは立ち上がった直後から、sshログインのリスト型攻撃を受け続けている。
インバウンドルール
タイプ | プロトコル | ポート範囲 | ソース | 説明 - オプション |
---|---|---|---|---|
SSH | TCP | 22 | 0.0.0.0/0 | - |
この状態で誤って以下の①〜③の条件を満たすようなユーザーを作成してしまうと、簡単にアカウントを乗っ取られてしまう。
①パスワードによるsshログイン可
②パスワードが脆弱(admin/adminなど)
→ 検証用の環境だからと脆弱なパスワードを設定しがち
③sudo権限がある。
※ パスワードによるsshログインはデフォルトでは許可されていない。
$ grep 'PasswordAuthentication ' /etc/ssh/sshd_config #PasswordAuthentication yes PasswordAuthentication no $
従って、割り当てるセキュリティグループを変更して、自宅のIPアドレス以外からはssh接続できないようにする。
①以下のセキュリティグループの割り当てを解除する。
インバウンドルール
タイプ | プロトコル | ポート範囲 | ソース | 説明 - オプション |
---|---|---|---|---|
SSH | TCP | 22 | 0.0.0.0/0 | - |
②以下のセキュリティグループを作成して割り当てる。
インバウンドルール
タイプ | プロトコル | ポート範囲 | ソース | 説明 - オプション |
---|---|---|---|---|
SSH | TCP | 22 | ${自宅のIPアドレス}/32 | - |
マネージメントコンソール上での操作は以下
アクション > ネットワーキング > セキュリティグループの変更
※ 固定IPではない場合は、PCをシャットダウンしたりするとIPアドレスが変わるので注意。
1.「admin」ユーザーを作成する
・「admin」ユーザーを作成する。
$ sudo useradd -m admin
※-m
はユーザー作成時にユーザーのホームディレクトリを作成する。
・パスワードを設定する。
$ sudo passwd admin
・adminにログインしてみる。
$ sudo su - admin $ whoami admin
・現状ではsudo権限がないことを確認する。
$ sudo pwd We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. [sudo] password for admin: admin is not in the sudoers file. This incident will be reported. $
・ec2-userに戻ってadminにsudo権限を追加して保存する。
$ exit
$ whoami
ec2-user
$ sudo visudo
→ ファイルの最後に以下の1行を追加して保存する。
admin ALL=(ALL) ALL
・adminでログインしてsudoができるようになっていることを確認する。
$ sudo su - admin $ sudo pwd [sudo] password for admin: /home/admin $
・クライアント側(Mac)で秘密鍵と公開鍵を作成する。(質問は全部Enter)
※ ssh-keygenで鍵を生成する時のオプションについては、いつもコピペで済ましてしまっているので、いつかちゃんと理解したい。
$ ssh-keygen -b 2048
以下の記事にあるように、クライアント側(ログインする側)で公開鍵と秘密鍵を作成して、公開鍵のみをサーバー側に送信するというのがあるべき形なので、その方針で作業していく。
dev.classmethod.jp
・公開鍵をEC2インスタンスに転送する。
$ scp -i mysecretkey.pem ~/.ssh/id_rsa.pub ec2-user@xxx.xxx.xxx.xxx:~/ id_rsa.pub 100% 424 3.1KB/s 00:00 $
・adminユーザーのhomeディレクトリ配下に.ssh
ディレクトリを作成する。
$ sudo mkdir /home/admin/.ssh $ sudo chown admin:admin /home/admin/.ssh $ sudo chmod 700 /home/admin/.ssh $ sudo ls -ld /home/admin/.ssh drwx------ 2 admin admin 6 5月 24 16:11 /home/admin/.ssh $
・.ssh
ディレクトリ配下にauthorized_keys
を作成し、公開鍵を登録する。
$ sudo touch /home/admin/.ssh/authorized_keys $ cat id_rsa.pub | sudo tee /home/admin/.ssh/authorized_keys > /dev/null $ sudo chown admin:admin /home/admin/.ssh/authorized_keys $ sudo chmod 400 /home/admin/.ssh/authorized_keys $ sudo ls -l /home/admin/.ssh/authorized_keys -r-------- 1 admin admin 424 5月 24 16:24 /home/admin/.ssh/authorized_keys $ rm -i id_rsa.pub
※ id_rsa.pub
の内容をauthorized_keys
にリダイレクトするところ、最初は
$ sudo cat id_rsa.pub >> /home/admin/.ssh/authorized_keys
-bash: /home/admin/.ssh/authorized_keys: Permission denied
としたがPermission denied
が出てしまい、以下の記事を参照させて頂いた。
tetsuyai.hatenablog.com
・クライアントPC(Mac)からadminユーザーでsshログインできるようになったことを確認する。
$ ssh admin@xxx.xxx.xxx.xxx Last login: Sun May 24 15:34:00 2020 __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ 1 package(s) needed for security, out of 16 available Run "sudo yum update" to apply all updates. $ whoami admin $
以上でadminユーザーの作成は完了。
2.ec2-userを削除する。
sudo権限のある「admin」ユーザーを作成したことで、「ec2-user」は不要になったので削除する。
$ whoami
admin
$ sudo userdel -r ec2-user
※-r
はホームディレクトリとメールスプールも削除する。
3.「release」、「webserver」、「appserver」ユーザーをそれぞれ作成する。
「release」、「webserver」、「appserver」ユーザーの要件は以下の通り。
- sudo権限なし。
- homeディレクトリは作成しない。
- パスワードは設定しない。
作成していく。
$ whoami admin $ sudo useradd -M release $ sudo useradd -M webserver $ sudo useradd -M appserver
※-M
は作成時にユーザーのホームディレクトリを作成しない。
・ユーザーが作成されていることを確認する。
$ sudo su release $ whoami release $ exit $ sudo su webserver $ whoami webserver $ exit $ sudo su appserver $ whoami appserver
以上で「その1:ユーザー作成」は完了。
その2に続く。