はじめに
記事を見ていただいて、ありがとうございます!
Webエンジニアをしているsannoと申します。
皆さん、AWSのEC2でサーバーを立てていますか?
私はこのblogをAWSのEC2上に構築しています。
EC2を立てる上で気になるのが、EC2へのアクセス方法ではないでしょうか?
EC2へのアクセス方法で、よく紹介されている方法はSSH用ポートの穴を開けて、キーペアを作成してSSHで接続という方法ではないでしょうか。
個人的に気になるのが、SSH用ポートの穴を開けることで少なからず不正にアクセスされるリスクがあることと、プライベートキーの管理が発生してしまうことです。
そんな私と同じ悩みを感じている方に紹介したいのが、AWS Systems Manager Session Managerです!
このサービスを使えば、なんとSSH用ポートの穴を開けないで、キーペアも作成せずともEC2インスタンスにアクセスできるようになります。
ただ一点補足で、EC2インスタンスにSCPなどでファイル転送したいといった要望がある場合は、キーペアの作成と管理の必要性は残ってしまいます。
この記事で紹介するEC2とS3の構成をとれば、SCPを使わずともS3に必要なファイルをアップロードしてEC2からS3のファイルをダウンロードしてくるということも可能になります。
そこまでするならばSCPを使うわ!! というツッコミがあるかもしれませんが…
また、この記事だけではいまいち、AWS Systems Manager Session Managerのイメージやメリットがわからないなという方もいると思います。
そんな方は以下の解説なんかも参照していただくと良いかもしれません。
安定のクラスメソッドさんの良記事です。
それではAWS Systems Manager Session Managerの具体的な設定や操作をしてゆきましょう!
もし、この記事で解説している内容に誤りがございましたら、コメント等でご指摘いただけると幸いです。
構築するAWS構成
構築時点の環境
# ==============================
# リモート接続するPCで実行
# ==============================
$ ssh -V
OpenSSH_8.1p1, LibreSSL 2.7.3
$ aws --version
aws-cli/2.0.48 Python/3.8.5 Darwin/20.3.0 source/x86_64
$ session-manager-plugin --version
1.2.245.0
# ==============================
# 構築したEC2で実行
# ==============================
$ aws --version
aws-cli/1.18.147 Python/2.7.18 Linux/4.14.232-177.418.amzn2.x86_64 botocore/1.18.6
$ amazon-ssm-agent --version
SSM Agent version: 3.0.1124.0
AWS Systems Manager Session Managerの設定手順
準備
まずは下準備をしてゆきましょう。
AWS Systems Manager Session Managerの設定をしてゆくためにEC2のインスタンスを立ち上げる必要があるのですが、そのためにはVPC等のネットワークやIAM Role, あるいは操作logの記録にCloudWatch Logsが必要になります。
また、AWS Systems Manager Session Managerの本質的な解説とは関係ないのですが、今回はS3も使いたいので、それも準備します。
上記についてはCloudFormationを使ってサクッと準備してしまいましょう。
CloudFormationの使い方に関しては以下の記事で紹介しているので、良かったらそちらも参照してみてください。
CloudFormationで使うymlテンプレートは以下になります。
AWSTemplateFormatVersion: "2010-09-09"
Description: "Configure environment to use SSM"
Resources:
EC2VPC:
Type: "AWS::EC2::VPC"
Properties:
CidrBlock: "10.0.0.0/16"
EnableDnsSupport: true
EnableDnsHostnames: false
InstanceTenancy: "default"
Tags:
-
Key: "Name"
Value: "test-vpc-01"
EC2InternetGateway:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
-
Key: "Name"
Value: "test-ssm-igw"
EC2VPCGatewayAttachment:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
InternetGatewayId: !Ref EC2InternetGateway
VpcId: !Ref EC2VPC
EC2Subnet:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: !Sub "${AWS::Region}a"
CidrBlock: "10.0.10.0/24"
VpcId: !Ref EC2VPC
MapPublicIpOnLaunch: false
Tags:
-
Key: "Name"
Value: "test-ssm-public-subnet-1a"
EC2RouteTable:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref EC2VPC
Tags:
-
Key: "Name"
Value: "test-ssm-public-route"
EC2Route:
Type: "AWS::EC2::Route"
Properties:
RouteTableId: !Ref EC2RouteTable
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref EC2InternetGateway
EC2SubnetRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref EC2Subnet
RouteTableId: !Ref EC2RouteTable
EC2SecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "Security group for attaching ec2"
GroupName: "test-ssm-sg-attach-ec2"
VpcId: !Ref EC2VPC
IAMRole:
Type: "AWS::IAM::Role"
Properties:
Path: "/"
RoleName: "test-ec2-AccessSSMAndS3"
AssumeRolePolicyDocument: "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
MaxSessionDuration: 3600
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
- "arn:aws:iam::aws:policy/AmazonS3FullAccess"
Description: "Allows EC2 instances to call AWS services on your behalf."
InstanceProfile:
Type: "AWS::IAM::InstanceProfile"
Properties:
InstanceProfileName: "test-ec2-AccessSSMAndS3-profile"
Path: /
Roles:
- !Ref IAMRole
S3Bucket:
Type: "AWS::S3::Bucket"
DeletionPolicy: Delete
Properties:
BucketName: "test-ssm-bucket"
AccessControl: Private
PublicAccessBlockConfiguration:
BlockPublicAcls: True
BlockPublicPolicy: True
IgnorePublicAcls: True
RestrictPublicBuckets: True
LogsLogGroup:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: "test-ssm-log-group"
RetentionInDays: 365
AWS Systems Manager Session Managerの実行環境を構築する上で、気をつけるポイントは以下の記事で解説していてくれている点かなと思います。
またまた登場のクラスメソッドさんの良記事です。
私もCloudFormationにて環境を構築する上で、とても参考になりました。
CloudFormationのテンプレートで、分かりづらい点として”InstanceProfile”があるかなと思います。
これは何かといいますと、EC2にIAM Roleを設定するときに必要なものになります。
詳細な説明は以下の方の記事がとても参考になりました。
EC2の設定
準備が完了しましたら、EC2のインスタンスを立ててゆきましょう。
AWS consoleで”ec2″と検索
“インスタンスを起動”を選択
“Amazon Linux 2 AMI”
“t3.nano”(検証用なので一番安価なインスタンスタイプを選択)
CloudFormationで作成したリソースを設定
検証用なので”クレジット仕様”のチェックは外す(状況に合わせて設定してください)
ストレージはデフォルトの設定
タグの設定は任意
CloudFormationで作成したセキュリティグループを設定
ポートが開いていないと警告が出るかもしれませんがそのまま”次へ”
確認で問題なければ”起動”を選択
最後にキーペアの作成をするかどうかですが。
この記事にて解説するS3経由でEC2にファイルを送る構成で問題ないようでしたら、特に作成する必要はありません。
もし、S3を使わずにSCPで直接ファイル転送を行う必要があるようでしたら、キーペアを作成する必要があります。
私は後の解説のためにキーペアを作成しておきます。
最後に”インスタンスの作成”を選択してEC2の作成は完了です。
ちなみにキーペアを作成しないと以下のような同意を求められますが、チェックを入れてもらって”インスタンスの作成”で大丈夫です。
最後に補足ですが、保存したシークレットキー(今回だとtest-ssm-key.pem)は、ssh接続時にそのまま使おうとすると以下のエラーが発生するかもしれません。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/***/test-ssm-key.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 "/***/test-ssm-key.pem": bad permissions
これはファイルのパーミッションが広すぎることが原因で発生するエラーです。
ですので、以下のコマンドでファイルのパーミッションを制限しておきましょう。
$ chmod 600 /***/test-ssm-key.pem
以下のように設定できていればOKです。
$ ls -l /***/test-ssm-key.pem
-rw-------@ 1 owner group 1704 7 16 08:00 /***/test-ssm-key.pem
AWS Systems Manager Session ManagerからEC2にアクセスする
無事、EC2インスタンスが立てられたら、以下の画面でAWS Systems Manager Session ManagerからEC2にアクセスできると思います。
AWS consoleで”system manager”と検索
“セッションマネージャー”を選択
“セッションを開始する”を選択
先ほど立てたEC2のインスタンスが表示されていると思うので、それをチェックして”セッションを開始する”を選択
ターミナル画面が開けばAWS Systems Manager Session Manager経由でEC2にアクセスできています
AWS Systems Manager Session Manager経由で無事にEC2にアクセスできたら、あとは好きなだけEC2を遊び倒してください。
ここまでで、AWS Systems Manager Session Managerの重要な部分については解説できたかなと思います。
ここから先は個人的に、こういう設定もしておいた方が良いかなということを解説してゆきます。
また、私が実際にAWS Systems Manager Session Managerを使っていて、EC2にファイルを送りたいのだけれどどうするのだろうと、課題に直面した時に調べた内容とこんな方法があるよということも解説してゆきます。
AWS Systems Manager Session Managerの操作logを記録する
どのように操作logを記録するか
個人でEC2等のサーバーを使っている分には気にならないかもしれませんが、業務でそれらを使っていると往々にして考慮しなければいけないのがアクセス履歴の記録ですよね。
誰がいつサーバーにアクセスしてどんな操作をしたのか、それらのアクセス履歴を取得しておくことは重要な要件であることが多いのではないでしょうか。
ですので、ここではAWS Systems Manager Session ManagerからEC2にアクセスした場合にCloudWatch Logsに記録しておく方法を紹介します。
CloudWatch Logsについては以下の公式など説明を見ていただく良いかなと思います。
ここで紹介した方法を設定してもらうと、以下のような操作logをCloudWatch Logsに記録しておくことができます。
それでは、CloudWatch Logsの設定をしてゆきましょう!
CloudWatch Logsの設定手順
EC2インスタンスとCloudWatch Logs groupの関連付け
CloudWatch Logsの設定手順は以下の公式の説明にある通りの設定を行ってゆきます。
AWS Systems Manager Session ManagerでEC2にアクセスする
テンプレートファイルをコピーする
$ sudo cp /etc/amazon/ssm/seelog.xml.template /etc/amazon/ssm/seelog.xml
“seelog.xml”ファイルを編集する
$ sudo vi /etc/amazon/ssm/seelog.xml
“seelog.xml”に以下の記述を追加
<seelog type="adaptive" mininterval="2000000" maxinterval="100000000" critmsgcount="500" minlevel="info">
<exceptions>
<exception filepattern="test*" minlevel="error"/>
</exceptions>
<outputs formatid="fmtinfo">
<console formatid="fmtinfo"/>
<rollingfile type="size" filename="/var/log/amazon/ssm/amazon-ssm-agent.log" maxsize="30000000" maxrolls="5"/>
<filter levels="error,critical" formatid="fmterror">
<rollingfile type="size" filename="/var/log/amazon/ssm/errors.log" maxsize="10000000" maxrolls="5"/>
</filter>
<!-- ここの記述を追加 -->
<custom name="cloudwatch_receiver" formatid="fmtdebug" data-log-group="test-ssm-log-group"/>
<!-- ここまで -->
</outputs>
<formats>
<format id="fmterror" format="%Date %Time %LEVEL [%FuncShort @ %File.%Line] %Msg%n"/>
<format id="fmtdebug" format="%Date %Time %LEVEL [%FuncShort @ %File.%Line] %Msg%n"/>
<format id="fmtinfo" format="%Date %Time %LEVEL %Msg%n"/>
</formats>
</seelog>
“SSM Agent”の再起動
$ sudo service amazon-ssm-agent restart
“SSM Agent”のステータス確認
$ sudo systemctl status amazon-ssm-agent
以下のような表示がされていれば更新OK
AWS consoleで”systems manager”と検索
“セッションマネージャー”を選択
“設定”を選択
“編集”を選択
“Cloud Watch logging”の項目を以下のように設定
“保存”を選択
“Enabled”のステータスになっていればOK
操作logの確認
AWS consoleで”cloudwatch”と検索
“ロググループ”を選択
“test-ssm-log-group”を選択する
以下のようにログストリームが表示される
アクセスしたIAM名の方を表示すると操作したlogの一覧が表示される
SSM Agentのバージョンの自動更新設定
SSM Agentのバージョンの自動更新設定は必須ではないのですが、公式でもおすすめしているので、設定しておきます。
AWS consoleで”systems manager”と検索
“フリートマネージャー”を選択
“設定”を選択
“SSM エージェントの自動更新”を選択
“成功”のステータスになればOK
EC2インスタンスへファイル転送する
EC2を運用していると、しばしば、ファイルをEC2に転送したいってことがあると思います。
何か設定用のファイルを転送したいだとか、何かやらかした時に別の場所に保存してあるバックアップファイルを転送して、それを適用したいだとか。
AWS Systems Manager Session ManagerでEC2にアクセスする方法だと、ファイル転送をしたいという場合にどうすれば良いのか私も戸惑ったので、その方法についても解説したいと思います。
方法1. キーペアを利用してSCPで転送する
AWS Systems Manager Session Managerでファイル転送をする1つ目の方法として、キーペアを利用する方法があります。
これは、最初にAWS Systems Manager Session Managerを利用するメリットの一つとしてキーペアの管理をしなくてすむということを挙げましたが、そのメリットを手放すこととトレードオフにはなってしまいます。
ですが、AWS Systems Manager Session Managerを使うもう一つのメリットとして、SSH用のポートを開かなくてすむというメリットは活きるので、キーペアの管理にそこまで煩わしさを感じない方はこの方法1で良いかもしれません。
では、実際にキーペアを利用したファイル転送の手順を見てゆきましょう!
Session Managerプラグインのインストールをする
AWS Systems Manager Session ManagerでEC2にアクセスするためには、Session Managerプラグインが必要です。
Session Managerプラグインをインストールしましょう。
インストール方法はご自身の環境に合わせて、以下の公式の情報を参考に行ってみてください。
ここではmacOSのインストール方法を記載しておきます。
自身のマシーンのターミナルで以下のコマンドを実行してファイルをダウンロード
$ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip"
ダウンロードしたファイルを解凍
$ unzip ./sessionmanager-bundle.zip
解凍したインストーラーからインストールを実行
$ sudo ./sessionmanager-bundle/install -i /usr/local/sessionmanagerplugin -b /usr/local/bin/session-manager-plugin
正常にインストールされると以下のようなメッセージが表示される
Creating install directories: /usr/local/sessionmanagerplugin/bin
Creating Symlink from /usr/local/sessionmanagerplugin/bin/session-manager-plugin to /usr/local/bin/session-manager-plugin
Installation successful!
また、session-manager-pluginのコマンドを実行して以下のようなメッセージが表示されていればOK
$ session-manager-plugin
The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.
使用したインストーラーを削除(必要に応じて)
$ rm -f ./sessionmanager-bundle.zip
$ rm -rf ./sessionmanager-bundle
SSHのconfigファイルの設定をする
公式でSSHのconfig設定追加について言及していますので、設定を追加しましょう。
SSHのconfigファイルに以下の設定を追加
# SSH over Session Manager
host i-* mi-*
ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
設定の内容については、以下の引用させていただいた記事にて解説してくれています。
i-*
はインスタンスIDを指定したとき、mi-*
はオンプレのサーバをSSMで管理している場合に使うIDです。つまり、インスタンスIDに対してSSHアクセスしたときには、ssmでトンネル張って、その中をSSH接続するということですね。
Session ManagerでSCPとかSSH Portforwardもできる!
SSH接続をする
SSH接続をしてみましょう。
sshコマンドで接続
# ssh -i [キーペアのシークレットキー] ec2-user@[EC2インスタンスのインスタンスID]
$ ssh -i ~/***/test-ssm-key.pem ec2-user@i-***
EC2インスタンスのインスタンスIDはEC2コンソール画面の以下から確認できます。
また、補足としてAWS CLIを初めて使う場合は以下のようなエラーが出るかもしれません。
$ ssh -i ~/***/test-ssm-key.pem ec2-user@i-***
You must specify a region. You can also configure your region by running "aws configure".
kex_exchange_identification: Connection closed by remote host
その場合は”aws configure”を実行しましょう。
$ aws configure
AWS Access Key ID [None]: [自身のIAMのAccess Key ID]
AWS Secret Access Key [None]: [自身のIAMのSecret Access Key]
Default region name [None]: [自身のEC2を設置しているregion]
Default output format [None]: [任意のDefault output format]
特にわかりにくい設定値として、”Default output format”かなと思います。
“Default output format”は各種AWS CLIを実行したときの出力形式を指定します。
特にこだわりがなければ、一旦は何も設定しなくて良いかもしれません。
より詳細な説明は、以下の公式の説明を参照していただくと良いと思います。
SCPでファイル転送をする
やっと目的のSCPでファイル転送までたどり着きましたね。
SSH接続までできていれば、SCPでファイル転送も問題なく実行できるはずです。
SCPでファイル転送
# scp -i [キーペアのシークレットキー] [転送元ファイル] ec2-user@[EC2インスタンスのインスタンスID]:[転送先ファイル]
$ scp -i ~/***/test-ssm-key.pem ./sample.txt ec2-user@i-***:~/sample.txt
SSHで接続してファイル確認
以下のようにファイルが存在していればOK
$ ssh -i ~/***/test-ssm-key.pem ec2-user@i-***
[user@ip ~]$ ls -l
合計 0
-rw-r--r-- 1 owner group 0 9月 19 03:22 sample.txt
SSH用のポートを開かなくてもSCPでファイル転送できることを確認できました!
ここまでが、”方法1. キーペアを利用してSCPで転送する”手順でした。
方法2. S3を介してファイル転送する
AWS Systems Manager Session Managerでファイル転送をする2つ目の方法として、S3を利用する方法があります。
EC2とS3を連携する構成はよくあるパターンかなと思います。
ですので、方法2としてはクライアントからインターネット経由でS3に転送したいファイルをアップロードして、AWS Systems Manager Session Manager接続のEC2から、そのファイルをダウンロードするという方法の手順になります。
では、実際にS3を介したファイル転送の手順を見てゆきましょう!
S3にファイルをアップロードする
転送したいファイルをS3のtest-ssm-bucketにアップロードします。
コンソール画面から操作をしても良いですが、ここではAWS CLIを使ってアップロードしてみたいと思います。
S3にファイルのアップロード
# aws s3 cp [ローカルのパス] [S3のパス]
$ aws s3 cp ./sample.txt s3://test-ssm-bucket
ファイルがアップロードできたか確認してみましょう。
以下のコマンドでbucket内のファイルを表示
アップロードしたファイルが表示されればOK
$ aws s3 ls s3://test-ssm-bucket
2021-09-19 15:20:10 0 sample.txt
AWS Systems Manager Session Manager接続のEC2からS3のファイルをダウンロードする
S3にアップロードしたファイルをEC2にダウンロードしましょう。
以下のコマンドの実行はAWS Systems Manager Session Manager接続のEC2から行います。
AWS Systems Manager Session Manager接続なので、ここではAWS CLI操作のみになります。
S3からEC2にファイルのダウンロード
# aws s3 cp [S3のパス] [ローカルのパス]
$ sudo aws s3 cp s3://test-ssm-bucket/sample.txt ./sample.txt
ダウンロードしたファイルが表示されればOK
$ ls -l
total 0
-rw-r--r-- 1 root root 0 Sep 19 06:20 sample.txt
“方法2. S3を介してファイル転送する”の手順は以上になります。
S3とEC2が連携されていれば使える手法なので、一つの手段として良いのかなと思います。
おわりに
AWS Systems Manager Session Managerの良さが、少しは伝わりましたでしょうか?
セキュアにEC2を管理する手段として、ぜひAWS Systems Manager Session Managerを使ってみてください。
最後まで記事を読んでいただいて、ありがとうございました!!
コメント