AL@のTech Blog

個人用備忘録

【Vuls】Linuxサーバの脆弱性を検知してみた part2 (vulsrepoへのアクセスをSSL化)

前回、Vulsサーバの構築を行い、クライアントからパッケージ情報を送信し、ブラウザ上で脆弱性の検知結果を確認しました。
今回は、vulsrepoへのアクセスをSSL化していこうと思います。

残念なことにvulsrepoは現状SSL化の設定がないようなので、nginxでSSL化させてvulsrepoに接続させていきたいと思います。
 

目次

 1. 前提
 2. nginxインストール&confの設定変更
 3. 接続確認


1. 前提

サーバ名:vuls-server
EC2インスタンスタイプ:t2.medium
EBSボリューム:16GB
OS:Amazon Linux 2

2. nginxインストール&confの設定変更

まずはnginxをインストールします。

amazon-linux-extras install nginx1

 
nginxを起動させます。

systemctl status nginx
systemctl start nginx
systemctl status nginx
systemctl enable nginx

  
鍵の作成とディレクトリ等のパーミッションを変更します。

mkdir /etc/nginx/ssl
openssl req -new -x509 -sha256 -newkey rsa:2048 -days 365 -nodes -out /etc/nginx/ssl/nginx.pem -keyout /etc/nginx/ssl/nginx.key

chown nginx:nginx -R /etc/nginx/ssl/
chmod 600 /etc/nginx/ssl/*
chmod 700 /etc/nginx/ssl

 
nginx.confの設定ファイルを追加します。

vim /etc/nginx/nginx.conf
server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;
        server_name  _;
        root         /usr/share/nginx/html;
        ssl_certificate /etc/nginx/ssl/nginx.pem;
        ssl_certificate_key /etc/nginx/ssl/nginx.key;
            location / {
            root   html;
            index  index.html index.htm;
            proxy_pass http://localhost:5111/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            }
        }

 
nginxを再起動させます。

systemctl restart nginx
systemctl status nginx

 
 

3. 接続確認

最後にHTTPSでアクセスしてみます。

ちなみにhttps:[パブリックIP]でアクセスできるようになりましたが、このままだとhttp://[パブリックIP]:5111でもアクセスできてしまいます。
なのでセキュリティグループのport:5111は忘れず削除しておきましょう。

【Vuls】Linuxサーバの脆弱性を検知してみた part1 (Vulsの構築)

管理していたLinuxサーバが知らぬ間に脆弱性の危機に・・・
何てことがないように脆弱性を検知してくれる仕組みがあると便利ですよね。
ってことでVulsを構築してみました。


リモートのクライアントサーバを検知させる場合、パッケージ情報を送信する方法としてSSHを使ったリモートスキャンモードがあります。
ただ、今回はSSHを使わないサーバモードにします。
こちらだと鍵自体が不要かつ、指定した任意のportさえ通信を許可すればパッケージ情報を送信できるので非常にシンプルでよいですね。

目次

 1. 前提
 2. Vulsサーバ側の事前準備
 3. Goインストール
 4. go-cve-dictionaryのインストール
 5. goval-dictionaryのインストール
 6. Vulsのインストール
 7. vulsrepoのインストール
 8. Vuls,vulsrepoをsystemd化する
 9. 脆弱性検知&確認

1. 前提

【Vulsサーバ側】
サーバ名:vuls-server
EC2インスタンスタイプ:t2.medium
EBSボリューム:16GB
OS:Amazon Linux 2
DB:Sqlite3
Go:ver1.21.1
※後ほどの手順にも記載しますが、インストール途中でプロセスがkillされてしまう、またデフォルトのEBSボリュームだと足りなかったため、Vulsサーバ側だけ少しスペック上げてます。


【Vulsクライアント側】
サーバ名:vuls-client
OS:Amazon Linux 2
EC2インスタンスタイプ:t2.micro
EBSボリューム:8GB

また、Vuls関連のインストール手順は公式ドキュメントを参考に進めていきます。
vuls.io



2. Vulsサーバ側の事前準備

基本設定や必要パッケージをインストールしていきます。
ちなみにVulsクライアント側は脆弱性検知をさせたいので敢えてアップデートせずにそのままにしておきます。

getenforce
>Disabled

timedatectl set-timezone Asia/Tokyo

yum -y update
yum -y install git gcc make wget vim

 
 

3. Goインストール

vulsはgoで作られているみたいなので、Goをインストールします。
最新版のGoをインストールする場合は、公式サイトで都度確認してください。
go.dev

cd /opt
wget https://go.dev/dl/go1.21.1.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.21.1.linux-amd64.tar.gz
rm -rf go1.21.1.linux-amd64.tar.gz

 

環境変数の設定をします。

vim /etc/profile.d/goenv.sh

export GOROOT=/usr/local/go
export GOPATH=/opt/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

source /etc/profile.d/goenv.sh

 
 

4. go-cve-dictionaryのインストール

脆弱性データベースのインストール作業となります。
インストールする脆弱性データべースは、アメリカのNISTが管理しているNVD(National Vulnerability Database)と日本のJPCERT/CCIPAが共同で管理しているJVN(Japan Vulnerability Notes)となります。

mkdir /var/log/vuls
chmod 700 /var/log/vuls
mkdir -p $GOPATH/src/github.com/vulsio
cd $GOPATH/src/github.com/vulsio

git clone https://github.com/vulsio/go-cve-dictionary.git
cd go-cve-dictionary
make install
mkdir /opt/vuls
cd /opt/vuls
go-cve-dictionary fetch jvn
go-cve-dictionary fetch nvd

前提にも記載しましたが、t2.microのEC2インスタンス上でgo-cve-dictionary fetch nvdを実行すると急にkillされてしまいましたので、個人的にはt2.micro以上のスペックで実行することをオススメします。
 
 

5. goval-dictionaryのインストール

OVAL(Open Vulnerability and Assessment Language)情報を取得するためのツールです。詳細は下記サイト参考にいただければ。
www.ipa.go.jp
 
 

mkdir -p $GOPATH/src/github.com/vulsio
cd $GOPATH/src/github.com/vulsio
git clone https://github.com/vulsio/goval-dictionary.git
cd goval-dictionary
make install
ln -s $GOPATH/src/github.com/vulsio/goval-dictionary/oval.sqlite3 /opt/vuls/oval.sqlite3

 
今回は検知対象のサーバがAmaozon Linux 2ですが、念のためすべて入れておきました。
GitHub - vulsio/goval-dictionary: Build a local copy of OVAL. Server mode for easy querying.github.com

goval-dictionary fetch amazon 1 2 2022 2023

 
 

6. Vulsのインストール

ようやくVulsのインストールとなります。

mkdir -p $GOPATH/src/github.com/future-architect
cd $GOPATH/src/github.com/future-architect
git clone https://github.com/future-architect/vuls.git
cd vuls
make install
cd /opt/vuls
vim config.toml

[servers]

[servers.localhost]
host = "localhost"
port = "local"


vuls configtestで成功していればOKです。

[root@vuls-server vuls]# vuls configtest
[Sep 23 16:54:11]  INFO [localhost] vuls-v0.23.4-build-20230922_223515_70fd968
[Sep 23 16:54:11]  INFO [localhost] Validating config...
[Sep 23 16:54:11]  INFO [localhost] Detecting Server/Container OS...
[Sep 23 16:54:11]  INFO [localhost] Detecting OS of servers...
[Sep 23 16:54:11]  INFO [localhost] (1/1) Detected: localhost: amazon 2
[Sep 23 16:54:11]  INFO [localhost] Detecting OS of containers...
[Sep 23 16:54:11]  INFO [localhost] Checking Scan Modes...
[Sep 23 16:54:11]  INFO [localhost] Checking dependencies...
[Sep 23 16:54:11]  INFO [localhost] Dependencies ... Pass
[Sep 23 16:54:11]  INFO [localhost] Checking sudo settings...
[Sep 23 16:54:11]  INFO [localhost] Sudo... Pass
[Sep 23 16:54:11]  INFO [localhost] It can be scanned with fast scan mode even if warn or err messages are displayed due to lack of dependent packages or sudo settings in fast-root or deep scan mode
[Sep 23 16:54:11]  INFO [localhost] Scannable servers are below...
localhost

 
 

7. vulsrepoのインストール

VulsはCUI上でも検知&検知結果の表示ができますが、やはりWEB上で表示できたほうが見やすいのでvulsrepoをインストールします。

mkdir /opt/vuls/results
cd /opt
git clone https://github.com/ishiDACo/vulsrepo.git
cd /opt/vulsrepo/server
cp vulsrepo-config.toml.sample vulsrepo-config.toml

vim vulsrepo-config.toml

[Server]
rootPath = "/opt/vulsrepo"
resultsPath  = "/opt/vuls/results"
serverPort  = "5111"

 
 

8. Vuls,vulsrepoをsystemd化する

こちらの記事を参考にVulsとvulsrepoをsystemctl化させます。
qiita.com

vim /etc/systemd/system/vulsrepo.service

[Unit]
Description=vulsrepo daemon
Documentation=https://github.com/usiusi360/vulsrepo

[Service]
ExecStart = /opt/vuls/vulsrepo/server/vulsrepo-server
ExecRestart = /bin/kill -WINCH ${MAINPID} ; /opt/vulsrepo/server/vulsrepo-server
ExecStop = /bin/kill -WINCH ${MAINPID}
Restart = no
Type = simple
User = root
Group = root

[Install]
WantedBy = multi-user.target
vim /etc/systemd/system/vuls.service

[Unit]
Description=vuls daemon
Documentation=https://github.com/usiusi360/vulsrepo

[Service]
WorkingDirectory=/opt/vuls
ExecStart = /opt/go/bin/vuls server -listen [プライベートIP]:5515 -to-localfile
ExecRestart = /bin/kill -WINCH ${MAINPID} ; /opt/go/bin/vuls server -listen [プライベートIP]:5515 -to-localfile
ExecStop = /bin/kill -WINCH ${MAINPID}
Restart = no
Type = simple
User = root
Group = root

[Install]
WantedBy = multi-user.target
systemctl daemon-reload

systemctl start vulsrepo vuls
systemctl enable vulsrepo vuls
systemctl status vulsrepo vuls

以上でVulsサーバ側の構築は完了です。


それではブラウザからアクセスしてみます。

 
 

9. 脆弱性検知&確認

最後にvulsクライアントを検知してみましょう。

クライアント側にパッケージ情報を送信する方法はcurlコマンドでPOSTするだけなのですが、検知対象のサーバのOSによってリクエストヘッダが異なります。

vuls.io


せっかくなのでシェルにしておきます。

[root@vuls-client bin]# cat vuls-send.sh
#!/bin/bash

VULS_SERVER='[プライベートIP]'
AMAZON_LINUX_RELEASE=$(awk '{if ($0 ~ /Amazon\ Linux\ release\ 2023/) for (i=4; i<=NF; i++) printf("%s ", $i); else if ($0 ~ /Amazon\ Linux\ 2023/) for (i=3; i<=NF; i++) printf("%s ", $i); else if ($0 ~ /Amazon\ Linux\ release\ 2022/) for (i=4; i<=NF; i++) printf("%s ", $i); else if ($0 ~ /Amazon\ Linux\ 2022/) for (i=3; i<=NF; i++) printf("%s ", $i); else if ($0 ~ /Amazon\ Linux\ release\ 2/) printf("%s %s",$4, $5); else if ($0 ~ /Amazon\ Linux\ 2/) for (i=3; i<=NF; i++) printf("%s ", $i); else if (NF==5) print $5}' /etc/system-release)

curl -X POST -H "Content-Type: text/plain" -H "X-Vuls-OS-Family: `awk '{print tolower($1)}' /etc/system-release`" -H "X-Vuls-OS-Release: $AMAZON_LINUX_RELEASE" -H "X-Vuls-Kernel-Release: `uname -r`" -H "X-Vuls-Server-Name: `hostname`" --data-binary "`repoquery --all --pkgnarrow=installed --qf="%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH} %{UI_FROM_REPO}"`" http://${VULS_SERVER}:5515/vuls > /dev/null

if [ $? -ne 0 ]; then
  logger 'vuls scan is error.'
fi


スクリプトを実行します。

[root@vuls-client bin]# bash vuls-send.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  113k    0 94355  100 21805  20722   4788  0:00:04  0:00:04 --:--:-- 25512


先ほど送信されたパッケージ情報に対して検知した脆弱性がserverity別に表示されました。


もっと詳細に見ていくと、どのパッケージが検知されたのか、推奨されるパッケージのバージョンも表示されるのはよいですね。


 
 

【rbash】SCP転送したいがSSH接続時はコマンドの実行を制限したい場合

タイトル通りですが、SCP転送させたいがSSH接続は制限するというちょっとワガママなことを実現させる方法になります。

目次

・要件
・ユーザーの作成
・鍵作成&設定
・rbashの設定
環境変数 $PATHの設定

要件

・SCP転送でファイルを送りたい
SSH接続(*1)されても、ある程度制限かけたい(*2)
・SCP転送用のユーザーを用意する
  SCP転送先&ホームディレクトリ:/opt/test-file

(*1)
SSH接続先でのコマンド実行方法としては以下の2パターンが考えられるので、どちらも制限したいと思います。

SSH接続後にSSH接続先のサーバでコマンドの実行
例)

[root@src-server ~]# ssh test-user@aaa.aaa.aaa.aaa
[test-user@dest-server ~]# ls

 
SSHコマンドと同時にSSH接続先でコマンドを実行する
例)

[root@src-server ~]# ssh test-user@aaa.aaa.aaa.aaa ls


(*2)
ある程度の制限とは、SSH接続先であるサーバ内のディレクトリやファイルを参照または変更できないことを言います。
例えば、ls,mv,rm,rmdirコマンドの実行禁止。

前提

・転送元サーバ、転送先
OS:CentOS7.9
Shell:bash
 

ユーザーの作成

SCP転送用のユーザー、グループを作成します。

ユーザー名:test-user
グループ名:test-group

[test-user@dest-server ~]# groupadd test-group
[test-user@dest-server ~]# grep test-group /etc/group
test-group:x:1002:

[test-user@dest-server ~]# useradd test-user -g 1002 -d /opt/test-file
[test-user@dest-server ~]# grep test-user /etc/passwd
test-user:x:2001:1002::/opt/test-file:/bin/bash

 
 

鍵作成&設定

test-user用の公開鍵と秘密鍵を作成します。

[test-user@dest-server ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/opt/test-file/.ssh/id_rsa):
Created directory '/opt/test-file/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /opt/test-file/.ssh/id_rsa.
Your public key has been saved in /opt/test-file/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:cqxkgcm6HyA8/fmD663EM+XyTXEy7hHxmmjSL7L0ujc test-user@dest-server
The key's randomart image is:
+---[RSA 2048]----+
|                 |
|   . o           |
|    + .  .       |
|. ..   o  o      |
|.oo.  +.S= o     |
| ..ooo=+o O      |
|  . .@o= *       |
|   .o+@E= .      |
|    oBO=++       |
+----[SHA256]-----+

 
  
公開鍵の名前は変更させ、パーミッションは600に変更してください。

[test-user@dest-server ~]# mv /opt/test-file/.ssh/id_rsa.pub /opt/test-file/.ssh/authorized_keys
[test-user@dest-server ~]# chmod 600 /opt/test-file/.ssh/authorized_keys

 
秘密鍵は転送元サーバの~/.ssh配下に格納してください。
 

rbashの設定

rbashを作成します。
rbashとは、制限機能付きシェルのことで、cdコマンドの実行等を制限してくれます。

rbashが制限できる機能の詳細は、以下のマニュアルにあります。
Man page of RBASH


 

[test-user@dest-server ~]# ln -s /bin/bash /bin/rbash
[test-user@dest-server ~]# ll /bin/ | grep bash
lrwxrwxrwx. 1 root root          9 Jan 28 14:36 rbash -> /bin/bash

 

test-userが実行するシェルをrbashに変更します。

[test-user@dest-server ~]# usermod -s /bin/rbash test-user
[test-user@dest-server ~]# grep test-user /etc/passwd
test-user:x:2001:1002::/opt/test-file:/bin/rbash

 
 

環境変数 $PATHの設定

現状の設定だとtest-userの実行シェルはrbashを指定していますが、test-userの./bash_profileで設定されている$PATHはデフォルトのままです。

仮にSSH接続した場合、rbashのシェルとして実行されるのでcdコマンドの実行は制限できます。
ただし$PATHの中身は変わっていないので、binディレクトリ配下などにあるコマンドが実行できてしまい、結果としてcdコマンド以外のコマンドは通常通り実行できてしまいます。
 
そのため、$PATHはscpコマンドしか実行できないよう、scpコマンドのシンボリックリンクが配置されているディレクトリを指定する必要があります。
 

[test-user@dest-server ~]# vim /opt/test-file/.bash_profile
PATH=$PATH:$HOME/.local/bin:$HOME/bin
↓
PATH=/opt/test-file

 
では、実際にSSH接続してコマンドの実行は制限できているか確認してみます。
  
 
まずはパターン①を実施します。
SSH接続後にSSH接続先のサーバでコマンドの実行

[root@src-server ~]# ls
-rbash: ls: command not found
[root@src-server ~]# cd
-rbash: cd: restricted

lsコマンドはコマンドの参照先(今回の場合では/opt/test-file配下)にlsコマンドの実行に必要なファイルが存在しないので、参照エラーとなっています。
cdコマンドはrbashで実行を制限しているので、「restriced」と表示されています。



次にパターン②を実施します。
SSHコマンドと同時にSSH接続先でコマンドを実行する

[root@src-server ~]# ssh test-user@192.168.2.32 ls -ls
total 0
0 -rw-r--r--. 1 root root 0 Jan 28 14:53 hoge

残念ながらrbashと$PATHを変更したにも関わらず、「ls -ls」コマンドが実行されてしまいました。。。


調べてみるとどうやら以下の仕様が原因のようです。
 
ssh(1) manページ

コマンド が指定されている場合は コマンド はログインシェルの代わりにリモートホスト上で実行されます。

 
Man page of BASH

bash は、リモートシェルデーモン rshd やセキュアシェルデーモン sshd によって実行された場合など、標準入力がネットワーク接続に接続された 状態で実行されたかどうかを調べます。 この方法によって実行されていると bash が判断した場合、 ~/.bashrc が存在し、かつ読み込み可能であれば、 bash はコマンドをこのファイルから読み込んで実行します。

 
 
先ほどパターン②で実行したSSHコマンドの「ls -ls」コマンドが実行できてしまうのは、
SSH接続時だが.pash_profileではなく、.bashrcファイルを実行しているため「/opt/test-file」ではないデフォルトの$PATHで実行されてしまうからのようです。
 
従ってパターン②のリモートコマンドの実行を制限するために、.bashrcファイルで$PATHを定義するように設定を変更します。また今回.bashrcで$PATHを定義するので、.bash_profileの$PATHはコメントアウトします。

[root@src-server ~]# vim /opt/test-file/.bash_profile
PATH=/opt/test-file
↓
#PATH=/opt/test-file
:wq
[root@src-server ~]# vim /opt/test-file/.bashrc
PATH=/opt/test-file
:wq

 
再度、パターン②を実行します。 
SSHコマンドと同時にSSH接続先でコマンドを実行する

[root@src-server ~]# ssh test-user@x ls -ls
rbash: ls: command not found

 
今度はちゃんと制限できましたね。
 
 
最後にSCP転送を試すと

[root@src-server ~]# scp ./source-file test-user@192.168.2.32:~
rbash: scp: command not found
lost connection

SCP転送が失敗しましたね。
先ほどscp転送先サーバであるtest-userのシェルはrbashで実行するように変更したせいか、scpコマンドはNGのようです。
 
 
なのでscpコマンドが実行できるようにscpファイルのシンボリックリンクを作成します。

[test-user@dest-server ~]# ln -s /bin/scp /opt/test-file/scp
[test-user@dest-server ~]# ls -l /opt/test-file/
lrwxrwxrwx. 1 root root 8 Jan 28 15:40 scp -> /bin/scp

再度SCP転送を試してみます。

[root@src-server ~]# scp -i id_rsa ./source-file  test-user@192.168.2.32:~
source-file                                                                        100%    0     0.0KB/s   00:00
 
[test-user@dest-server ~]# ls -l
-rw-r--r--. 1 test-user test-group 0 Jan 28 15:52 source-file

無事、SCP転送できました。
これで上記の要件はすべて満たせますね。
 
 
最後にこのままだと転送先サーバ上でSCPコマンドが実行できてしまうので、iptablesもしくはセキュリティグループでアウトバウンド側のSSH(デフォルトport22)は通信できないよう設定すれば問題ないかと思います。

【Amazon Linux2】Proxy経由でDockerfileをビルドする方法

Dockerfileをビルドする際にコンテナのベースイメージの箇所で躓いたのですが、思いのほかハマってしまったので備忘になります。
ビルドに限らず、Dockerイメージをプル等、プロキシ経由でDockerイメージを自身のサーバへ引っ張ってくるときに参考になるかと思います。

前提

OS:Amazon Linux2
パッケージ:docker-20.10.17-1.amzn2.0.1.x86_64

本題

やることは至って簡単で、プロキシ用の設定を追加するだけです。

mkdir /etc/systemd/system/docker.service.d
vi /etc/systemd/system/docker.service.d/http-proxy.conf

[Service]
Environment = 'http_proxy=http://[IPアドレス]:[port]'
Environment = 'https_proxy=http://[IPアドレス]:[port]'

IPアドレスとポート番号は任意のものを入力してください。



最後にデーモンのリロードとdockerを再起動します。

systemctl daemon-reload
systemctl restart docker

参考サイト

aws.amazon.com

【Django 入門】CentOS + MariaDBを使ってEC2インスタンス上にDjangoを構築してみた

DjangoデフォルトのデータベースはSQLite3ですが、使い慣れたMariaDBを使いたかったので、MariaDBDjangoの環境構築を行いました。

 

目次

・事前準備
Pythonインストール
MariaDBインストール
Djangoのインストール
・nginxインストール
・Gunicornインストール&環境構築
マイグレーション&起動
・動作確認

 

前提条件

publicサブネット上にあるEC2インスタンスに構築しました。

OS:CentOS 7.9.2009
Python:3.6.8
Django:3.2.13
MariaDB:5.5.68
nginx:1.20.2
gunicorn:20.1.0

 

事前準備

selinuxを無効化させます。

timedatectl set-timezone Asia/Tokyo
vi /etc/selinux/config

SELINUX=enforcing
↓
SELINUX=disabled
:wq

yum -y update
reboot

 

Pythonインストール

CentOS7ではデフォルトでpython2がインストールされていますが、python3をインストールします。

python3 -V
yum -y install python3
python3 -V

 

MariaDBインストール

mariadbをインストールさせます。

yum -y install mariadb-server python3-devel mysql-devel gcc

 

mariadbを起動させます。

systemctl start mariadb
systemctl status mariadb
systemctl enable mariadb

 

rootユーザーでログインします。

mysql -u root
create database mysite;
create user mysite@localhost identified by 'PassWord';
grant all privileges on mysite.* to 'mysite'@'localhost';
flush privileges;
exit

データベース「mysite」を作成し、mysiteユーザーへすべての権限を与えます。

また、パスワードは任意で設定してください。

 

 

作成したmysiteユーザーでログインして、データベース「mysite」が表示されることを確認します。

mysql -u mysite -p
show databases;
exit


Djangoのインストール

Djangoをインストールします。

pip3 install mysqlclient django

今回MariaDBを使うので、DjangoMariaDBを利用できるようにmysqlclientをインストールします。

 

プロジェクトを作成します。ここでは「mysite」というプロジェクトを作成します。

cd /opt/
django-admin startproject mysite

 

Djangoの設定ファイルを変更します。

vi ./mysite/settings.py

ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['*']


DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mysite', 'USER': 'mysite', 'PASSWORD': 'PassWord', 'HOST': 'localhost', 'PORT': '3306', 'OPTIONS': { 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", }, } }

LANGUAGE_CODE = 'en-us'

LANGUAGE_CODE = 'ja'


TIME_ZONE = 'UTC'

TIME_ZONE = 'Asia/Tokyo'

STATIC_ROOT = '/opt/mysite/static/'

今回はDBはMariaDBを使用しますので、DATABASESの中身をSQLite3からMariaDBへ変更します。
この時、MariaDBで作成したユーザー名、パスワードを指定してください。


また、静的ファイルの処理はnginx側で行うように設定したいと思いますので、STATIC_ROOTはプロジェクトで使用する静的ファイルの格納先を指定するよう追加します。

 

新規でstaticディレクトリを作成します。

cd /opt/mysite
mkdir /opt/mysite/static
chown appserver:appserver /opt/mysite/static
ls -l

 

nginxインストール

nginxをインストールさせます。

vi /etc/yum.repos.d/nginx.repo

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
:wq
yum -y install nginx

 

nginxを起動させます。

systemctl start nginx
systemctl status nginx
systemctl enable nginx

 

nginxの設定ファイルを新規作成します。

vi /etc/nginx/conf.d/mysite.conf

server {
    listen  80;
    server_name xxx.xxx.xxx.xxx;

    location /static/ {
        alias /opt/mysite/static/;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
    }
}

server_nameではパブリックIPを設定してください。

 

作成したmysite.confにエラーが出力されないことを確認して、nginxを再起動します。

nginx -t
systemctl restart nginx
systemctl status nginx

 

Gunicornインストール

gunicornを起動させるユーザーを作成します。

useradd -M appserver

 

gunicornをインストールさせます。

pip3 install gunicorn
gunicorn -v

 

gunicorn.serviceを作成します。

cd /etc/systemd/system
touch gunicorn.service
chmod 644 ./gunicorn.service

vi gunicorn.service [Unit] Description=gunicorn daemon After=network.target [Service] Type=notify PIDFile=/run/gunicorn/pid User=appserver Group=appserver RuntimeDirectory=gunicorn WorkingDirectory=/opt/mysite ExecStart=/usr/local/bin/gunicorn \ --access-logfile - \ --workers 3 \ --bind=localhost:8000 \ mysite.wsgi ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s TERM $MAINPID KillMode=mixed TimeoutStopSec=5 PrivateTmp=true Restart=always [Install] WantedBy=multi-user.target

UserとGroupは先ほど作成したユーザー名を指定してください。
WorkingDirectoryは作成したプロジェクトのディレクトリ先を指定してください。


先ほどgunicorn.serverで設定したPIDファイルの格納先を作成します。

mkdir /run/gunicorn
chown appserver:appserver /run/gunicorn
ll /run | grep gunicorn

 

gunicorn.serviceを作成したので、一度リロードします。

systemctl daemon-reload

 

gunicorn.serviceを起動させます。

systemctl start gunicorn
systemctl status gunicorn
systemctl enable gunicorn

 

Djangoの起動

静的ファイルを先ほど設定した/opt/mysite/staticへ配置させます。

python3 manage.py collectstatic

 

プロジェクト「mysite」で利用するデータベース「mysite」のテーブル情報を自動的に作成します。

python3 manage.py migrate

setting.pyの設定内容が誤っている、あるいはmysqlclientのインストールがない等があるとエラーが返ってきますので注意してください。

 

Djangoのスーパーユーザーを作成します。名前は任意で構わないです。
メールアドレスの設定を求められますが、空白でも特に問題ないです。

python3 manage.py createsuperuser

 

プロジェクト「mysite」を起動させます。

python3 manage.py runserver


動作確認

ブラウザでパブリックIPでアクセスすると以下の画面が表示されます。

 

 

次に「パブリックIP/admin」でアクセスするとログイン画面が表示されます。

 

作成したアカウントでログインすると以下の画面が表示されます。

シェルスクリプトでNATGatewayを自動で作成or削除してみた

privateサブネットにあるEC2インスタンスをインターネット接続するためにNatGatewayを利用するかと思いますが、作成したままですとお金がかかり(※1)、かといって必要なときだけ作成、削除するのは面倒なので、シェルスクリプトを作成しました。

 

※1 NatGatewayの利用料金について
東京リージョンでNatGatewayを作成して、特に利用せず30日間保持した場合は$32.4かかります。
なお、利用料金は別になります。詳細は下記のサイトを参考にしてみてください。

https://aws.amazon.com/jp/vpc/pricing/

 

目次

・環境
・前提条件
シェルスクリプトの解説
・実行結果

 

環境

OS:CentOS7
aws cli:2.4.23
シェル:bash

 

前提条件

前提として、以下の事前準備が必要となります。
 - privateサブネットとprivateサブネットへ追加するルートテーブル
 - aws cliのインストール&IAMユーザーの認証情報

 

シェルスクリプトの解説

実行する際は、引数に"enable"もしくは"disable"を指定して実行してください。

 - enable:EIP,NatGateway作成&ルートテーブルへ追加

 - disable:EIP,NatGateway&ルートテーブルから削除

#!/bin/bash

case "$1" in
  "enable")
        ############# Create NATGateway ##############
        ALLOCATION=$(aws ec2 allocate-address | grep AllocationId | awk '{print$2}' | sed 's/^.*"\(.*\)".*$/\1/')
        aws ec2 create-nat-gateway --subnet-id {サブネットID} --allocation-id $ALLOCATION --tag-specifications ResourceType=natgateway,Tags=[{"Key=Name,Value={Natgateway名}"}]
        sleep 210
        NETWORK_INTERFACE=$(aws ec2 describe-addresses | grep NetworkInterfaceId | awk '{print$2}' | sed 's/^.*"\(.*\)".*$/\1/')
        aws ec2 create-route --route-table-id {ルートテーブルID} --destination-cidr-block 0.0.0.0/0 --network-interface-id $NETWORK_INTERFACE
        ;;
        ##############################################

   "disable")
        ############# Delete NATGateway ##############
        aws ec2 delete-route --route-table-id {ルートテーブルID} --destination-cidr-block 0.0.0.0/0
        ALLOCATION=$(aws ec2 describe-nat-gateways --filter Name=state,Values=available | grep AllocationId | awk '{print$2}' | sed 's/^.*"\(.*\)".*$/\1/')
        NATGATEWAY=$(aws ec2 describe-nat-gateways --filter Name=state,Values=available | grep NatGatewayId | awk '{print$2}' | sed 's/^.*"\(.*\)".*$/\1/')
        aws ec2 delete-nat-gateway --nat-gateway-id $NATGATEWAY
        sleep 210
        aws ec2 release-address --allocation-id $ALLOCATION
        ;;
        ##############################################

    *)
        echo "Please enter enable or disable.";;
    esac

 

 

・Natgateway作成&ルートテーブルへ追加

ALLOCATION=$(aws ec2 allocate-address | grep AllocationId | awk '{print$2}' | sed 's/^.*"\(.*\)".*$/\1/')

NatGatewayを作成する前にまずEIPを作成します。
NatGatewayを作成する際に、作成したEIPの割り当てIDを指定する必要がありますので、変数に代入しています。

 

aws ec2 create-nat-gateway --subnet-id {サブネットID} --allocation-id $ALLOCATION --tag-specifications ResourceType=natgateway,Tags=[{"Key=Name,Value={NatGateway名}"}]

NatGatewayを作成しています。
事前に作成されているprivateサブネットのサブネットIDを指定します。
NatGateway名は任意の名前を付けてください。

 

sleep 210

NatGatewayの作成に少々時間がかかりますので、ルートテーブルへの追加までsleepコマンドで一時停止します。

 

NETWORK_INTERFACE=$(aws ec2 describe-addresses | grep NetworkInterfaceId | awk '{print$2}' | sed 's/^.*"\(.*\)".*$/\1/')

先ほど作成したNatgatewayのネットワークインターフェースIDを取得します。

 

aws ec2 create-route --route-table-id {ルートテーブルID} --destination-cidr-block 0.0.0.0/0 --network-interface-id $NETWORK_INTERFACE

事前に作成したprivateサブネットのルートテーブルへNatGatewayを追加します。

 

 

・Natgateway削除&ルートテーブルから削除

aws ec2 delete-route --route-table-id {ルートテーブルID} --destination-cidr-block 0.0.0.0/0

privateサブネットのルートテーブルからNatGatewayを削除します。

 

ALLOCATION=$(aws ec2 describe-nat-gateways --filter Name=state,Values=available | grep AllocationId | awk '{print$2}' | sed 's/^.*"\(.*\)".*$/\1/')
NATGATEWAY=$(aws ec2 describe-nat-gateways --filter Name=state,Values=available | grep NatGatewayId | awk '{print$2}' | sed 's/^.*"\(.*\)".*$/\1/')

作成したNatGatewayを削除するためにEIPの割り当てIDとNATGatewayのIDをそれぞれ変数に代入しています。

 

aws ec2 delete-nat-gateway --nat-gateway-id $NATGATEWAY

NatGatewayを削除します。

 

sleep 210

ここも時間がかかりますので、一時停止します。

 

aws ec2 release-address --allocation-id $ALLOCATION

最後にEIPを開放します。

【AWS SAA-C02合格】AWSソリューションアソシエイトを1ヶ月半で2回受けて合格しました。

1回目は泣きの不合格。。。再トライの2回目で合格できましたので、それまでにやってきたこと、受けてみた感想的なことを書いていきます。

本来はAWSの知識を身に着け、実践で環境構築、問題解決できる状態になることが大切ですが、まずは資格取得を第一優先としています。

 

目次

・私のスペック、業務経験

・使った参考書、教材、公式ドキュメント等その他

・勉強方法

・1度目の受験(在宅)

・2度目の受験(テストセンター)

・まとめ

 

私のスペック、業務経験

スペック

LPIC Level2 取得

これ持っているからと言ってAWSの資格とは何も関係ありませんが念のため。

 

業務経験

AWS + オンプレ環境のサーバ構築案件 対応中(ちょうど1年ぐらい)

私はペーペーエンジニアということもあって、業務中にAWSのマネージドサービスを使う機会はほぼなく、EC2インスタンス起動、停止ぐらい。休みの日には、ALB + AutoScalingとかLambdaで少し遊んでいた程度。

↓以前書いたALB + AutoScalingの記事

 

使った参考書、教材、公式ドキュメント(BlackBelt)

参考書

合格対策 AWS認定ソリューションアーキテクト - アソシエイト (日本語) 単行本(ソフトカバー) 

色んなQuiitaの記事や個人ブログで取り上げられていたので、とりあえずアマゾンでポチりました。

私の場合はそもそもどんなマネージドサービスがあるかも知らなかったので、初めてAWSの勉強をするだとか、あるいはまずはマネージドサービスの概要を知りたい人にはオススメ。ただし、あくまで概要レベルなので、この本だけでは正直物足りなかったです。私は勉強を始めた最初の1週間に2周読んでそれ以降は使ってないです。

 

  

AWS認定資格試験テキスト AWS認定 ソリューションアーキテクト-アソシエイト

今の案件に携わる前にAWSに興味を持っていた時にたまたま本屋で買ったものを使いました。

各マネージドサービスの概要や機能についてある程度は記載されています。ちょっと機能の確認をしたいときとかに重宝してました。本格的にアソシエイトの受験を考えている人は買ってみるといいかもです。

ちなみに参考書の末あたりに模擬試験がありますが、私は一度も使いませんでした。

 

 

 Web教材

AWS WEB問題集

これは必須ですね。利用するには有料の会員登録が必要ですが、正直これさえ完璧にすれば大幅に合格に近づくと思います。(ゴールドプランの場合、3880円/2ヶ月)

 

サイト内にある「合格記」で過去合格された方が実際の試験で出題されたマネージドサービス等有益な情報が記載されてますので、ぜひ活用しましょう!

 

これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座(SAA-C02試験対応版)

こちらは主要のマネージドサービスのハンズオン + 模擬試験3回分になります。定価だと12000円相当するみたいですが、購入するときはセール時に買ったほうが得です。ちなみに私は1820円で購入しました。ハンズオンはほぼ見ませんでした。(well-architectedぐらい)

 

 

※私は試験勉強を始める前によく確認せずに上記のほうを購入してしまいましたが、資格取得を第一優先するのであれば模擬試験だけ受けられるこちらのほうがいいと思います。

【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集(6回分390問)

 

 

 

公式ドキュメント等その他

公式ドキュメント、BlackBelt

参考書やWEB問題集だけではわからないところが多々でてくると思いますが、そのときは都度ググってました。公式ドキュメントの「よくある質問」やBlackBeltあたりは参考になるかと思います。量は膨大なので、まずは合格したいといことであれば必要あれば調べるぐらいでいいと思います。

 

またAWS公式ではありませんが、以下のサイトも大変参考になりました。

※記事は各サイトの中で一番印象に残っている&実際の試験で重要そうな内容をピックアップしてます。

 

 

勉強方法

1.参考書を2周読み、マネージドサービスの概要をさらっと理解する

2.AWS WEB問題集(#100~141)をひたすら解く

 間違えた問題はExcelやテキスト等にメモする。

※ただ正解を選ぶだけでなく、なぜほかの選択肢は間違いなのか理解しながら解くといいです。わからないところは参考書を読んだり、公式ドキュメント(BlackBelt)や色んなサイトを見る。

3.Udemyの模擬試験

※実力確認として受験

 

あとは2と3をひたすら繰り返してました。私は1ヶ月半で4回ほど繰り返して合格できましたが、業務でAWSを触っている方や効率よく資格勉強できる方などはもっと短い期間で取得できるかと思います。

 

ちなみに、AWS公式の模擬試験は受けてません。

 

 

1度目の受験(在宅)

実は2020年11月末に勉強を始めて2020年以内、つまり1ヶ月以内でアソシエイトを取得することを目標としていたのですが、本当はテストセンター受験の予定のところを翌日の在宅受験しか予約できなかったため、仕方なく在宅受験を予約しました。前日予約できなかったのはコロナの影響のせい?

 

※完全に個人的な考えですが、試験環境がきちんと整った場所でテストを受けたい派です。移動時間は気持ちを整えるのによいので。

 

f:id:d-dragon53:20210110174140p:plain

 

という言い訳をして、結果不合格。

予想ですが、あと2,3問正解していれば合格してたかも。 

 

 

ちなみに在宅で試験を受ける場合は、事前にPCに受験用のソフトをインストールする必要があります。

私はインカメラ付きのノートPCで受験したのですが、受験直前には試験に不正がないよう試験官に以下の写真とカメラに映す必要があります。

 

【写真の送付が必要なもの】

・身分証等自身を証明できるもの2点

・部屋の周辺(四方向)

 

【カメラに映すよう指示されたこと】

・PC、デスクの周辺

・腕時計の有無

・眼鏡を外して回転させて見せる

・外部ディスプレイの電源が入らないこと (ケーブルが抜けていることも含め)

※私のデスク上に外部ディスクプレイが2つあるため

 

これらの確認で大体30分ぐらいかかってしまい、試験開始時間を若干過ぎてしまいましたが、試験時間は問題なく140分で受験できました。

 

在宅受験だとPC以外の筆記用具等も利用禁止ですので、テスト中に何かメモする方はテストセンターで受験されることをオススメします。(テストセンター受験の場合は、テストセンターでメモができる紙のようなもの?を借りることができます。)

 

また試験中ですが、PC画面以外を見ていると試験官にチャットで注意されました。私のように問題の難しさに現実逃避しようと画面外を見ていると怒られますので、在宅で受けられる方は頑張ってPCの画面を見続けてください笑

※あくまで感覚ですが、画面外を見ていたのは5秒ほどでした。

 

こんなご時世でもありますので在宅で受験できるメリットはありますが、事前準備や制約がありますので、どちらで受けたほうがよいかは自宅環境やその人次第かと思います。

 

 

2度目の受験(テストセンター)

前回の在宅受験の経て、試験時に問題以外のことで気にかけたくなかったため、今回(2021年1月)はテストセンターで受験しました。

 

f:id:d-dragon53:20210110173857p:plain

 

ギリギリですが合格しました!!2回目なのに1回目とそれほど点数差ありませんが、合格したのでよしとしましょう笑

 

まとめ

個人的な目標は達成できませんでしたが、なんとかアソシエイト合格できました。

色んな方のQuiitaや個人ブログ等と比べると勉強期間が1か月半と若干長いので、私より要領よくやられている方がたくさんいらっしゃると思いますので、情報の一つとして参考にしていただければ幸いです。

次はSOADVA取得を目指します。