【AWS】用語を整理しながら学ぶAWS - part5 Cloud Formation - 5

# はじめに

この記事では AWS Cloud Tech を通して Cloud Formation を学習して実践していく記事です。
主な内容としては実践したときのメモを中心に書きます。（忘れやすいことなど）
誤りなどがあれば書き直していく予定です。

https://aws-cloud-tech.com/

## 前回までのおさらい

前回は Part5-3 で作成したネットワークに対して EC2 を建てるところまで作成しました。

[【AWS】用語を整理しながら学ぶ AWS - part5 Cloud Formation - 4](https://qiita.com/ymd65536/items/bddd66ce258a8a9328fc)

## 今回やること

- WEB サーバに踏み台 SSH ができるかどうか
- WEB サーバを経由して PrivateNetwork の EC2 サーバに SSH ログインできるか

何回か Cloud Formation のコードを載せていますが
書いたコードが想定とは違う動作をした為に
問題が発生して問題を解決していくうちに前回と違う内容になりましたので再度、掲載

| ファイル名         | 用途                               |
| :----------------- | :--------------------------------- |
| vpc_network.yml    | VPC の構成を管理                   |
| public_subnet.yml  | パブリックサブネットの構成を管理   |
| private_subnet.yml | プライベートサブネットの構成を管理 |
| public_ec2.yml     | パブリックサブネット内の EC2       |
| private_ec2.yml    | プライベートサブネット内の EC2     |

## どんな問題に激突したか

WEB サーバに踏み台 SSH 後
プライベートサブネットにある EC2 に SSH ログインしようとすると
SSH の応答が返って来ない。

## どう気づいたか

CloudFormation テンプレートで作成した EC2 とコンソールでポチポチ作った EC2 を比較した。

## 原因はなんだったか

プライベートサブネットにある EC2 のセキュリティグループが
なぜかデフォルトのセキュリティグループで守られていた。
また、プライベートサブネットのルートテーブルが関連付けされていなかった。

## どう解決したか

private_subnet.yml にサブネットの関連付けを実施
また、private_ec2.yml の NetworkInterfaces にある GroupSet にセキュリティグループを明示的に追加

## 実際のコード

```yml:vpc_network.yml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  MainVpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/21
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: MainVpcfromCF
  IGW:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: igw
          Value: igw-cf
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MainVpc
      InternetGatewayId: !Ref IGW

Outputs:
  MainVpc:
    Value: !Ref MainVpc
    Export:
      Name: MainVpcId
  MainIgw:
    Value: !Ref IGW
    Export:
      Name: MainIGWId

```

パブリックサブネットを定義する。

```yml:public_subnet.yml
AWSTemplateFormatVersion: 2010-09-09

Parameters:
  AZ:
    Description: AvailabilityZone
    Type: String
    Default: "ap-northeast-1a"
  PublicSubnetCidrBlock:
    Description: PublicSubnetCidrBlock
    Type: String
    Default: 10.0.2.0/24

Resources:
  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AZ
      VpcId: !ImportValue MainVpcId
      CidrBlock: !Ref PublicSubnetCidrBlock
      Tags:
        - Key: Name
          Value: PublicSubnet
  PubRT:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !ImportValue MainVpcId
      Tags:
        - Key: PublicRoute
          Value: PublicRouteCf
  PubToInternet:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PubRT
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !ImportValue MainIGWId
  PubRTAssociate:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PubRT
  secGroupName:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: PublicSecGrp
      GroupDescription: PublicSecGrp
      VpcId: !ImportValue MainVpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: PublicSecGrp

Outputs:
  PublicSubnet:
    Value: !Ref PublicSubnet
    Export:
      Name: PublicSubnet
  PublicSecGrp:
    Value: !GetAtt secGroupName.GroupId
    Export:
      Name: PublicSecGrp

```

> ※もしかすると、パブリック向けのルーティング書いてないっぽいので踏み台 SSH つながらないかも・・・

前回の予想が当たりましたね。
ただ、ルーティングだけではなくセキュリティグループとサブネットの関連付けも原因でした。

今回、残念ながら検証で誤っているとわかったコード
ルートテーブルとその関連付けを追加して対応

```yml:private_subnet.yml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      VpcId: !ImportValue MainVpcId
      CidrBlock: 10.0.1.0/24
      Tags:
        - Key: Name
          Value: PrivateSubnet
  VpcRT:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !ImportValue MainVpcId
      Tags:
        - Key: VpcNetwork
          Value: vpcnet
  VpcRTAssociate:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref VpcRT
  PrivateSec:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: PrivateSecGrp
      GroupDescription: PrivateSecGrp
      VpcId: !ImportValue MainVpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 10.0.2.0/24
      Tags:
        - Key: Name
          Value: PrivateSecGrp

Outputs:
  PrivateSubnet:
    Value: !Ref PrivateSubnet
    Export:
      Name: PrivateSubnet
  PrivateSecGrp:
    Value: !Ref PrivateSec
    Export:
      Name: PrivateSecGrp


```

パブリックサブネットに EC2 を配置する。

```yml:public_ec2.yml

AWSTemplateFormatVersion: 2010-09-09
Resources:
  myEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: PublicEc2Key
      ImageId: ami-0992fc94ca0f1415a
      InstanceType: t2.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
          GroupSet:
            - !ImportValue PublicSecGrp
          PrivateIpAddress: "10.0.2.10"
          SubnetId: !ImportValue PublicSubnet
      Tags:
        - Key: Name
          Value: PublicEC2


```

今回、残念ながら検証で誤っているとわかったコード
セキュリティグループを Interfaces に追加して対応

誤

```yml:private_ec2.yml

AWSTemplateFormatVersion: 2010-09-09
Resources:
  myEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: PrivateEc2Key
      ImageId: ami-0992fc94ca0f1415a
      InstanceType: t2.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: false
          DeviceIndex: "0"
          PrivateIpAddress: "10.0.1.15"
          SubnetId: !ImportValue PrivateSubnet
      Tags:
        - Key: Name
          Value: PrivateEC2

```

正

```yml:private_ec2.yml

AWSTemplateFormatVersion: 2010-09-09
Resources:
  myEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: PrivateEc2Key
      ImageId: ami-0992fc94ca0f1415a
      InstanceType: t2.micro
      Monitoring: false
      NetworkInterfaces:
        - AssociatePublicIpAddress: false
          DeviceIndex: "0"
          GroupSet:
            - !ImportValue PrivateSecGrp
          PrivateIpAddress: "10.0.1.15"
          SubnetId: !ImportValue PrivateSubnet
      Tags:
        - Key: Name
          Value: PrivateEC2

```

## 動作確認

まずはパブリックサブネットの EC2 にログインする為に
パブリック IP を確認する。

![cfn_public_ec2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/2778d700-a7bd-9d20-b3ab-a2c98ef7d322.jpeg)


今回は TeraTerm を利用。

ID とパスワードを聞かれるので ID は「 ec2-user 」
パスワードではなくキーペア「 PublicEc2Key 」を利用

![cfn_login.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/b767413f-0088-510f-02a6-02db01aae64e.jpeg)

踏み台にログインできたので
プライベートサブネットにある EC2 のキーペアをパブリック EC2 に送信

scp を使ってやる方法もありますが、せっかくなので TeraTerm の便利な機能を利用します。
「SSH SCP...」を選択

![cfn_Teraterm.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/b26eaf94-d232-57c1-6a92-dbee9e90d361.jpeg)

無事にキーペアを送信できたらさっそく SSH をしてみよう。(おおきな間違い)

```sh
[ec2-user@ip-10-0-2-10 ~]$ ssh -i PrivateEc2Key.pem ec2-user@10.0.1.15
The authenticity of host '10.0.1.15 (10.0.1.15)' can't be established.
ECDSA key fingerprint is SHA256:/dxsREuZ7a0y5mCe99lvEvXq3pcW2KdBpchRip4A3fU.
ECDSA key fingerprint is MD5:4d:5b:db:05:fb:61:2a:15:3c:0c:b7:d8:04:70:99:ab.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.1.15' (ECDSA) to the list of known hosts.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'PrivateEc2Key.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "PrivateEc2Key.pem": bad permissions
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

```

はい、権限エラーですね。
キーペアの権限を確認しましょう。

キーペアの権限を確認するには ls -l

```sh

[ec2-user@ip-10-0-2-10 ~]$ ls -l
total 4
-rw-r--r-- 1 ec2-user ec2-user 1674 Apr  5 11:57 PrivateEc2Key.pem
[ec2-user@ip-10-0-2-10 ~]$

```

それでは最低限、SSH で利用できるようにキーペアの権限を変更してあげましょう。

キーペアの権限を変更するには chmod を使います。
ちなみに権限を変更するときに利用する番号は 3bit で表現できます。

| 10 進数 | ビット表現 | パーミッション |
| :------ | :--------- | :------------- |
| 1       | 001        | --x            |
| 2       | 010        | -w-            |
| 3       | 011        | -wx            |
| 4       | 100        | r--            |
| 5       | 101        | r-x            |
| 6       | 110        | rw-            |
| 7       | 111        | rwx            |

```sh
[ec2-user@ip-10-0-2-10 ~]$ chmod 400 PrivateEc2Key.pem
[ec2-user@ip-10-0-2-10 ~]$
[ec2-user@ip-10-0-2-10 ~]$
[ec2-user@ip-10-0-2-10 ~]$
[ec2-user@ip-10-0-2-10 ~]$ ls -l
total 4
-r-------- 1 ec2-user ec2-user 1674 Apr  5 11:57 PrivateEc2Key.pem
[ec2-user@ip-10-0-2-10 ~]$

```

気を取り直してもう一度 SSH

```sh

[ec2-user@ip-10-0-2-10 ~]$ ssh -i PrivateEc2Key.pem ec2-user@10.0.1.15

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

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-0-1-15 ~]$

```

無事に SSH ログインできましたね。88888

## 次回の準備

次回は **CloudFormation を利用して**Wordpress をインストールし、
ブログを閲覧できるようにします。

### 必要だと思われるコマンド

[参考 - Amazon Web Services 基礎からのネットワーク&サーバー構築 改訂版 単行本 –](https://www.amazon.co.jp/dp/4822237443/ref=cm_sw_r_tw_dp_9QCCSGEGY3F4WHC3QF23)

まず、チョットした整理
WEB サーバには
データベースクライアントと Worpress、PHP が必要

プライベートサブネットの EC2(以下、DB サーバ)には
データベースとその設定

```sh:db_server.sh

sudo yum -y install mariadb-server
sudo systemctl start mariadb
sudo systemctl enable mariadb

```

MariaDB の設定

```txt:mysql.txt

$ mysqladmin -u root password
パスワードの設定を行う

テーブルを作成する
$ mysql -u root -p
MariaDB[none] > CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

データベースに対してすべてのアクセス権を与える。
MariaDB[none] > grant all on wordpress.* to wordpress@"%" identified by 'wordpresspasswd';

権限を反映させる。
MariaDB[none] > flush privileges;

MariaDB[none] > select user, host from mysql.user;
MariaDB[none] > exit


```

データベース側の設定が完了したら WEB サーバを設定する。

```sh:web_server.sh
sudo amazon-linux-extras install php7.3
sudo yum -y install php php-mbstring
sudo yum -y install mariadb-server

```

DB 接続確認用コマンド

```sh
mysql -h 10.0.1.15 -u wordpress -p
```

wordpress インストールコマンド

```sh:wordpress.sh

cd ~
wget https://ja.wordpress.org/latest-ja.tar.gz
tar xzvf latest-ja.tar.gz
cd wordpress
sudo cp -r * /var/www/html/
sudo chown apache:apache /var/www/html -R
sudo systemctl start httpd

```

### 遭遇しそうなエラー

よく見かけるエラーとしては

- テーブルが存在しないことにより発生するエラー
- DB のアクセス権限がないことにより発生するエラー
- パスワードが違うことにより発生するエラー
- テーブルへのアクセス権限がないことにより発生するエラー
- IP アドレスを間違えたことによる UnKnown Host エラー
- PHP がインストールされていないことにより発生するエラー

ざっくり上げるとこんな感じ

## まとめ

前回の環境を検証して
無事に WEB サーバを経由してプライベートサブネットに
SSH ログインすることができました。

次回は構築したネットワークに NAT を追加したのちに WordPress をインストールする
CloudFormation に書き換えます。

## おわり