ちょっと話題の記事

PCI DSS対応 AWS 上の踏み台サーバーでの操作ログ取得、MFA、アイドルタイムアウトを実現

PCI DSS に対応すべく Linux サーバーの操作履歴を S3 へ保存する、ログイン時に MFA を使用する、アイドルタイムアウトを実装する方法を紹介します。
2020.10.30

こんにちは。
ご機嫌いかがでしょうか。
"No human labor is no human error" が大好きな ネクストモード株式会社 の吉井です。

AWS 上の踏み台サーバー (ここでは Amazon Linux 2 を想定しています) での操作履歴を S3 へ保存する、ログイン時に MFA を使用する、アイドルタイムアウトを実装する方法を紹介します。

PCI DSS の関連して以下のような要件があり、これを実現するために考えた方法です。

  • ssh ログインは Google Authenticator を利用した二要素認証にしたい
  • ssh ログイン後の操作ログ(コマンドログ)を保管したい
  • 踏み台サーバーから更に業務サーバーへ ssh する。その操作ログもほしい
  • 無操作が15分続いたら強制切断する

構成図

構成は以下図になっています。

青線

保守 PC から踏み台サーバーへはセッションマネージャーを使います。
セッションマネージャーの利点は、踏み台サーバーのセキュリティグループで ssh (TCP 22) を開放しなくてよいところです。
執筆日時点では在宅勤務をされているエンジニアの方が多くいると思います。
自宅の IP アドレスを登録したり、VPN 経由で踏み台サーバーへ接続することが不要になるのがメリットです。

保守 PC にインストールした AWS CLI から踏み台サーバーへ接続します。
まず IAM ユーザーで認証します。(二要素)

その後、セッションマネージャー権限も持った IAM ロールへスイッチします。
これは必須ではありませんが、MFA を強制したかったので IAM ロールを使っています。
(IAM ロールがなくても MFA 強制可能ですが、ポリシーのシンプルさを求めてました)

緑線

踏み台サーバーでのコマンド履歴、出力はテキストファイルで S3 へ保管されます。
この S3 バケットにはアクセス制限をかけて、監査担当者のみ閲覧可能にします。
バケットへの書き込みは踏み台サーバーに関連付けたインスタンスプロファイルのみに限定します。

オレンジ線

踏み台サーバーから各アプリケーションサーバーへ ssh 接続し、メンテナンスを行います。
アプリケーションサーバー上のコマンド履歴も S3 へ保管されます。

環境設定手順

踏み台サーバーの作成

踏み台サーバーを Amazon Linux 2 で作成します。
インスタンスタイプやディスクサイズは任意で大丈夫です。

踏み台サーバーはパブリックサブネット (Internet Gateway へのルート有り) で起動し
セキュリティグループは以下にしました。

  • インバウンドルール → 任意
  • アウトバウンドルール → 全てのトラフィック、0.0.0.0/0 許可

IAM ユーザー用ポリシー作成

保守 PC から作業を行う担当者用の IAM ユーザー用ポリシーを作成します。

マネジメントコンソールから IAM ポリシー を開きます。

ポリシーの作成 をクリックします。

JSON タブを選択し、以下をコピー&ペーストします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowListActions",
            "Effect": "Allow",
            "Action": [
                "iam:ListUsers",
                "iam:ListVirtualMFADevices"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowIndividualUserToListOnlyTheirOwnMFA",
            "Effect": "Allow",
            "Action": [
                "iam:ListMFADevices"
            ],
            "Resource": [
                "arn:aws:iam::*:mfa/*",
                "arn:aws:iam::*:user/${aws:username}"
            ]
        },
        {
            "Sid": "AllowIndividualUserToManageTheirOwnMFA",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice",
                "iam:DeleteVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:ResyncMFADevice"
            ],
            "Resource": [
                "arn:aws:iam::*:mfa/${aws:username}",
                "arn:aws:iam::*:user/${aws:username}"
            ]
        },
        {
            "Sid": "AllowIndividualUserToDeactivateOnlyTheirOwnMFAOnlyWhenUsingMFA",
            "Effect": "Allow",
            "Action": [
                "iam:DeactivateMFADevice"
            ],
            "Resource": [
                "arn:aws:iam::*:mfa/${aws:username}",
                "arn:aws:iam::*:user/${aws:username}"
            ],
            "Condition": {
                "Bool": {
                    "aws:MultiFactorAuthPresent": "true"
                }
            }
        },
        {
            "Sid": "BlockMostAccessUnlessSignedInWithMFA",
            "Effect": "Deny",
            "NotAction": [
                "iam:CreateVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:ListMFADevices",
                "iam:ListUsers",
                "iam:ListVirtualMFADevices",
                "iam:ResyncMFADevice"
            ],
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

任意の名前を付けてポリシーを作成します。

IAM ユーザーの作成

IAM ユーザーとアクセスキーを作成します。
IAM ユーザー作成手順は割愛します。
公式ドキュメント Creating an IAM user in your AWS account を参照ください。
IAM ユーザー作成途中でポリシーをアタッチする画面が表示されると思います。前の手順で作成したポリシーをアタッチしてください。

アクセスキー作成手順は割愛します。
公式ドキュメント Managing access keys for IAM users を参照ください。

スイッチロール用ポリシー作成

スイッチするためのロール用ポリシーを作成します。

マネジメントコンソールから IAM ポリシー を開きます。

ポリシーの作成 をクリックします。

JSON タブを選択し、以下をコピー&ペーストします。
「instance-id」は踏み台サーバーのインスタンス ID に置き換えてください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:StartSession"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:instance/instance-id"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:DescribeSessions",
                "ssm:GetConnectionStatus",
                "ssm:DescribeInstanceProperties",
                "ec2:DescribeInstances"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:TerminateSession"
            ],
            "Resource": [
                "arn:aws:ssm:*:*:session/${aws:username}-*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kms:GenerateDataKey"
            ],
            "Resource": "*"
        }
    ]
}

任意の名前を付けてポリシーを作成します。

スイッチロール用 IAM ロール作成

マネジメントコンソールで IAM ロール を開きます。

ロールの作成 をクリックします。

別のアカウント タグを開きます。
アカウント ID にご自身の AWS アカウントを入力します。
MFA が必要 にチェックを入れます。
次のステップ をクリックします。

「Attach アクセス権限ポリシー」画面が表示されます。前で作成したスイッチロール用ポリシーを選択し、次のステップ をクリックします。

任意の名前を付けてロールを作成します。

マネジメントコンソールから作成したばかりのロールを表示します。

ロール ARN は後ほど使うのでメモしておきます。

信頼関係 タブを開き、信頼関係の編集 をクリックします。
以下の通りに書き換えます。
「account_id」をご自身の AWS アカウントに、「user_name」は前の手順で作成した IAM ユーザー名に置き換えてください。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::account_id:user/user_name"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

ログ保管 S3 バケット作成

コマンド履歴保管用の S3 バケットを作成します。

バケット作成手順は割愛します。
公式ドキュメント How do I create an S3 Bucket? を参照ください。

踏み台サーバー用インスタンスプロファイルの作成

ポリシー作成

マネジメントコンソールから IAM ポリシー を開きます。

ポリシーの作成 をクリックします。

JSON タブを選択し、以下をコピー&ペーストします。
「your-bucket」 は前の手順で作成したバケットに置き換えてください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssmmessages:CreateControlChannel",
                "ssmmessages:CreateDataChannel",
                "ssmmessages:OpenControlChannel",
                "ssmmessages:OpenDataChannel",
                "ssm:UpdateInstanceInformation"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:DescribeLogGroups",
                "logs:DescribeLogStreams"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::your-bucket/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetEncryptionConfiguration"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "kms:GenerateDataKey",
            "Resource": "*"
        }
    ]
}

任意の名前を付けてポリシーを作成します。

ロール作成

マネジメントコンソールで IAM ロール を開きます。

ロールの作成 をクリックします。

一般的なユースケース の下にある EC2 を選択し、次のステップ をクリックします。

「Attach アクセス権限ポリシー」画面が表示されます。前で作成したポリシーを選択し、次のステップ をクリックします。

任意の名前を付けてロールを作成します。

踏み台サーバーへインスタンスプロファイルをアタッチ

マネジメントコンソールで EC2 を開きます。

踏み台サーバーにチェックを入れます。

アクションセキュリティIAM ロールを変更 をクリックします。

前の手順で作成した IAM ロールを選択して、保存します。

セッションマネージャー設定

セッションマネージャーで S3 ロギング設定を行います。

セッションマネージャー を開きます。

設定 タブ → 編集 をクリックします。

以下図のように Enable にチェックを入れ、リストから S3 バケットを指定します。

Linux shell profile というテキストボックスに以下を入力します。
上4行はあってもなくても大丈夫です。
セッションマネージャーで EC2 へ接続すると .bash_profile 等を読み込んでくれないのでこのようにしています。
「TMOUT=900」は 900秒でアイドルタイムアウトする という意味です。

cd ~/
source /etc/profile
source ~/.bash_profile
source ~/.bashrc
TMOUT=900

保存 をクリックします。

接続方法

長かった準備が完了しました。
ここからは保守 PC での作業です。

AWS CLI インストール

本エントリでは「保守 PC = Windows 10」を想定して書いています。ご了承ください。

AWS CLI Version 2 をダウンロードしてインストールします。
https://awscli.amazonaws.com/AWSCLIV2.msi

インストールの確認です。PowerShell でコマンドを実行しバージョンが表示されれば OK です。

aws --version

Session Manager plugin インストール

続いて AWS CLI からセッションマネージャーを使うためのプラグインをダウンロード&インストールします。

https://s3.amazonaws.com/session-manager-downloads/plugin/latest/windows/SessionManagerPluginSetup.exe

インストールの確認です。 PowerShell からコマンドを実行し「The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.」が表示されれば OK です。

session-manager-plugin

AWS CLI の設定

IAM ユーザー作成時にダウンロードしたアクセスキー (csv ファイル) を手元に用意します。
保守 PC で PowerShell を管理者で開き、コマンドを実行します。

aws configure

AWS Access Key ID [None]: アクスキーを入力
AWS Secret Access Key [None]: シークレットアクスキーを入力
Default region name [None]: ap-northeast-1
Default output format [None]:

MFA ソフトウェアデバイスの設定

AWS CLI の設定が終わったら以下のコマンドを実行し MFA 用の QR コードを生成します。
「IAMUserName」は作成した IAM ユーザー名に
「C:/QRCode.png」は任意のパスに置き換えてください。

aws iam create-virtual-mfa-device --virtual-mfa-device-name IAMUserName --outfile C:/QRCode.png --bootstrap-method QRCodePNG

標準出力に SerialNumber という項目で ARN が表示されているはずです。それをメモします。

コマンド実行後「C:/QRCode.png」に QR コードが出力されます。
これを Google Authenticator などのソフトウェアデバイスで読み取ります。

つづいて MFA 認証を2回行い、IAM ユーザーの MFA を有効にします。
「ユーザー名」は作成した IAM ユーザーを入力します。
「上のコマンドの出力」は直前に実行したコマンドの標準出力でメモした値を入力します。
「6桁コード1回目」「6桁コード2回目」は Google Authenticator 等で表示される6桁コードを2回入力します。(同じコードではなく30秒待って異なるコードを入力)

aws iam enable-mfa-device --user-name ユーザー名 --serial-number 上のコマンドの出力 --authentication-code1 6桁コード1回目 --authentication-code2 6桁コード2回目

aws/config 編集

C:\Users\ユーザー名\.aws に config というファイルがあります。
これをテキストエディタで開きます。
おそらく defaul が記述されているはずです。
以下の3行目以降を追記します。

[default]
region = ap-northeast-1

[profile bastion]
role_arn=スイッチロール用 IAM ロール作成でメモしたロール ARN
source_profile=default
region=ap-northeast-1
mfa_serial=MFA ソフトウェアデバイスの設定でメモした SerialNumber ARN

セッションの開始

踏み台サーバーへ接続します。
「インスタンスID」は踏み台サーバーのものへ置き換えてください。

aws --profile bastion ssm start-session --target インスタンスID

Google Authenticator 等で表示される6桁コードを入力します。

Enter MFA code for arn:aws:iam::123456789012:mfa/iam-user-name:

接続が成功すると以下のような出力になります。

Starting session with SessionId: botocore-session-xxxx
cd ~/
source /etc/profile
source ~/.bash_profile
source ~/.bashrc
TMOUT=90

踏み台サーバーから別のサーバーへ ssh してみます。

ssh -i ~/.ssh/yoshii_personal.pem ec2-user@10.0.101.190

ログインできました。プロンプトが変わって 10.0.101.190 へ接続できていることが確認できます。

Last login: Thu Oct 29 11:09:34 2020 from ip-10-0-2-182.ap-northeast-1.compute.internal

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

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

S3 の確認

S3 バケットをマネジメントコンソールから確認してみます。

ログをダウンロードして中身を確認します。
少々見にくくなってしまっていますが、しっかり記録が残っています。

Script started on 2020-10-30 08:35:23+0000
cd ~/

source /etc/profile

source ~/.bash_profile

source ~/.bashrc

TMOUT=90

[?1034hsh-4.2$ cd ~/

sh-4.2$ source /etc/profile

sh-4.2$ source ~/.bash_profile

]0;ssm-user@ip-10-0-2-182:~[ssm-user@ip-10-0-2-182 ~]$ source ~/.bashrc

]0;ssm-user@ip-10-0-2-182:~[ssm-user@ip-10-0-2-182 ~]$ TMOUT=90

]0;ssm-user@ip-10-0-2-182:~[ssm-user@ip-10-0-2-182 ~]$ 

]0;ssm-user@ip-10-0-2-182:~[ssm-user@ip-10-0-2-182 ~]$ sudo su - ec2-user

]0;ec2-user@ip-10-0-2-182:~[ec2-user@ip-10-0-2-182 ~]$ ssh -i ~/.ssh/yoshii_personal.pem ec2-user@10.0.101.190

Last login: Thu Oct 29 11:09:34 2020 from ip-10-0-2-182.ap-northeast-1.compute.internal




       __|  __|_  )

       _|  (     /   Amazon Linux 2 AMI

      ___|\___|___|



https://aws.amazon.com/amazon-linux-2/

]0;ec2-user@ip-10-0-101-190:~[?1034h[ec2-user@ip-10-0-101-190 ~]$ 

]0;ec2-user@ip-10-0-101-190:~[ec2-user@ip-10-0-101-190 ~]$ exit

logout

Connection to 10.0.101.190 closed.


]0;ec2-user@ip-10-0-2-182:~[ec2-user@ip-10-0-2-182 ~]$ exit

logout

]0;ssm-user@ip-10-0-2-182:~[ssm-user@ip-10-0-2-182 ~]$ exit

exit


Script done on 2020-10-30 08:35:23+0000

まとめ

セッションマネージャーを使うことで操作ログを取得可能になります。
操作ログは S3 へ保管されるので改ざんの危険性が低くなります。
かつ、ssh ポートを開放しなくて済むのでよりセキュアです。

script コマンド、screen コマンド、psacct コマンド、snoopy logger など様様な方法がありますが
その選択肢の一つとして今回の方式も検討して頂ければ幸いです。

セッションマネージャーは ssm-user というユーザーで接続されますが
個別のユーザーへ変更したい場合は runas を使ってみてください。
[ついに来た!?] AWS Systems Manager セッションマネージャーを OS ユーザー指定で使えるようになりました

参考

AWS Systems Manager Session Manager

以上、吉井 亮 がお届けしました。