AWS System Managerセッションマネージャーにポートフォワーディング機能が追加されました。
AWS System Manager Sessions Manager を使用した新しい機能 – Port Forwarding
この機能を利用すれば、インバウンドポート(SSH/RDP)を許可せずに対象インスタンスへログインすることが出来ます。
実際に本機能を利用してみましょう。
※クライアント機はWindowsを想定しています。
サーバー側(EC2インスタンス)の準備
IAMロール
ログインするEC2インスタンスにIAMロールをアタッチします。
IAMポリシーは AmazonSSMManagedInstanceCore (AWS管理ポリシー) を利用します。
SSMエージェントのインストール
以下を参照ください。Amazon Linux等には既定でインストールされています。
Amazon EC2 Linux インスタンスに SSM エージェント を手動でインストールする
SSMエージェントのアップデート
以下を参照ください。
Run Command を使用して SSM エージェント を更新する
yum update等を利用した場合は最新バージョンに更新されない場合もあるので、Run Command での更新をお勧めします。
クライアント側の準備
AWS CLIのインストール
以下を参照ください。既にインストールされている場合も最新版のインストールをお勧めします。
セッションマネージャープラグインのインストール
以下を参照ください。既にインストールされている場合も最新版のインストールをお勧めします。
Windows に Session Manager Plugin をインストールする
クライアントで利用するアクセスキーの準備
クライアントにインストールしたAWS CLIを利用する為に、IAMのアクセスキーを準備します。
CloudFormationのテンプレートを用意したのでご利用ください。
AWSTemplateFormatVersion: "2010-09-09" Description: Sample CloudFormation Template for Use of SSM Session Manager. Metadata: "AWS::CloudFormation::Interface": ParameterGroups: - Label: default: "EC2 Instance" Parameters: - EC2InstanceId - Label: default: "IAM Group" Parameters: - NameOfIamGroup - NameOfIamPolicyForSsmSession - NameOfIamPolicyForRotatingAccessKey - Label: default: "IAM User 01" Parameters: - NameOfIamUser01 - Label: default: "IAM User 02" Parameters: - CreateIamUser02 - NameOfIamUser02 - Label: default: "IAM User 03" Parameters: - CreateIamUser03 - NameOfIamUser03 - Label: default: "IAM User 04" Parameters: - CreateIamUser04 - NameOfIamUser04 - Label: default: "IAM User 05" Parameters: - CreateIamUser05 - NameOfIamUser05 ParameterLabels: EC2InstanceId: default: "EC2 Instance ID" NameOfIamGroup: default: "Name of IAM Group" NameOfIamPolicyForSsmSession: default: "Name of IAM Policy For Executiong SSM Session Manager" NameOfIamPolicyForRotatingAccessKey: default: "Name of IAM Policy For Rotating Access Key" NameOfIamUser01: default: "User Name" CreateIamUser02: default: "User Create" NameOfIamUser02: default: "User Name" CreateIamUser03: default: "User Create" NameOfIamUser03: default: "User Name" CreateIamUser04: default: "User Create" NameOfIamUser04: default: "User Name" CreateIamUser05: default: "User Create" NameOfIamUser05: default: "User Name" # ------------------------------------------------------------# # Input Parameters # ------------------------------------------------------------# Parameters: EC2InstanceId: Type: AWS::EC2::Instance::Id NameOfIamGroup: Type: String Default: "SSM-Session-Manager_Executors" NameOfIamPolicyForSsmSession: Type: String Default: "Execute_SSM-Session-Manager_to_Specific-Instance" NameOfIamPolicyForRotatingAccessKey: Type: String Default: "Rotate_Self-AccessKey" NameOfIamUser01: Type: String Default: "IAM-User01" CreateIamUser02: Type: String Default: false AllowedValues: - true - false NameOfIamUser02: Type: String Default: "IAM-User02" CreateIamUser03: Type: String Default: false AllowedValues: - true - false NameOfIamUser03: Type: String Default: "IAM-User03" CreateIamUser04: Type: String Default: false AllowedValues: - true - false NameOfIamUser04: Type: String Default: "IAM-User04" CreateIamUser05: Type: String Default: false AllowedValues: - true - false NameOfIamUser05: Type: String Default: "IAM-User05" # ------------------------------------------------------------# # Conditions # ------------------------------------------------------------# Conditions: # Create or Not: IAM Users CreateIamUser02True: !Equals [ !Ref CreateIamUser02, true ] CreateIamUser03True: !Equals [ !Ref CreateIamUser03, true ] CreateIamUser04True: !Equals [ !Ref CreateIamUser04, true ] CreateIamUser05True: !Equals [ !Ref CreateIamUser05, true ] Resources: # ------------------------------------------------------------# # IAM Group # ------------------------------------------------------------# # IAM Group IamGroup: Type: AWS::IAM::Group Properties: GroupName: !Ref NameOfIamGroup # IAM Policy For Executing SSM Session Manager IamPolicyForSsmSession: Type: AWS::IAM::Policy Properties: PolicyName: !Ref NameOfIamPolicyForSsmSession PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - ssm:StartSession Resource: - !Sub "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:instance/${EC2InstanceId}" - !Sub "arn:aws:ssm:${AWS::Region}::document/AWS-StartPortForwardingSession" - Effect: Allow Action: - ssm:TerminateSession Resource: arn:aws:ssm:*:*:session/${aws:username}-* Groups: - !Ref IamGroup # IAM Policy For Rotating Access Key IamPolicyForRotatingAccessKey: Type: AWS::IAM::Policy Properties: PolicyName: !Ref NameOfIamPolicyForRotatingAccessKey PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - iam:CreateAccessKey - iam:DeleteAccessKey Resource: !Join - '' - - !Sub "arn:aws:iam::${AWS::AccountId}:user/" - ${aws:username} Groups: - !Ref IamGroup # ------------------------------------------------------------# # IAM Users # ------------------------------------------------------------# # IAM User 01 IamUser01: Type: AWS::IAM::User Properties: UserName: !Ref NameOfIamUser01 Groups: - !Ref IamGroup # Access Key 01 AccessKey01: Type: AWS::IAM::AccessKey Properties: Status: Active UserName: !Ref IamUser01 # IAM User 02 IamUser02: Type: AWS::IAM::User Condition: CreateIamUser02True Properties: UserName: !Ref NameOfIamUser02 Groups: - !Ref IamGroup # Access Key 02 AccessKey02: Type: AWS::IAM::AccessKey Condition: CreateIamUser02True Properties: Status: Active UserName: !Ref IamUser02 # IAM User 03 IamUser03: Type: AWS::IAM::User Condition: CreateIamUser03True Properties: UserName: !Ref NameOfIamUser03 Groups: - !Ref IamGroup # Access Key 03 AccessKey03: Type: AWS::IAM::AccessKey Condition: CreateIamUser03True Properties: Status: Active UserName: !Ref IamUser03 # IAM User 04 IamUser04: Type: AWS::IAM::User Condition: CreateIamUser04True Properties: UserName: !Ref NameOfIamUser04 Groups: - !Ref IamGroup # Access Key 04 AccessKey04: Type: AWS::IAM::AccessKey Condition: CreateIamUser04True Properties: Status: Active UserName: !Ref IamUser04 # IAM User 05 IamUser05: Type: AWS::IAM::User Condition: CreateIamUser05True Properties: UserName: !Ref NameOfIamUser05 Groups: - !Ref IamGroup # Access Key 05 AccessKey05: Type: AWS::IAM::AccessKey Condition: CreateIamUser05True Properties: Status: Active UserName: !Ref IamUser05 # ------------------------------------------------------------# # OUTPUTS # ------------------------------------------------------------# Outputs: 01AccessKey: Description: Access Key of IAM User 01 Value: !Ref AccessKey01 01SecretAccessKey: Description: Secret Access Key of IAM User 01 Value: !GetAtt AccessKey01.SecretAccessKey 02AccessKey: Description: Access Key of IAM User 02 Value: !Ref AccessKey02 Condition: CreateIamUser02True 02SecretAccessKey: Description: Secret Access Key of IAM User 02 Value: !GetAtt AccessKey02.SecretAccessKey Condition: CreateIamUser02True 03AccessKey: Description: Access Key of IAM User 03 Value: !Ref AccessKey03 Condition: CreateIamUser03True 03SecretAccessKey: Description: Secret Access Key of IAM User 03 Value: !GetAtt AccessKey03.SecretAccessKey Condition: CreateIamUser03True 04AccessKey: Description: Access Key of IAM User 04 Value: !Ref AccessKey04 Condition: CreateIamUser04True 04SecretAccessKey: Description: Secret Access Key of IAM User 04 Value: !GetAtt AccessKey04.SecretAccessKey Condition: CreateIamUser04True 05AccessKey: Description: Access Key of IAM User 05 Value: !Ref AccessKey05 Condition: CreateIamUser05True 05SecretAccessKey: Description: Secret Access Key of IAM User 05 Value: !GetAtt AccessKey05.SecretAccessKey Condition: CreateIamUser05True
CloudFormationの出力に表示されたアクセスキーとシークレットアクセスキーを控えておいてください。

ポートフォワーディング機能を利用してログインしてみる
コマンドプロンプトで、AWS CLI用のアクセスキーを設定します。
C:\>set AWS_ACCESS_KEY_ID=AKIAxxxxxxxxxxxxxxxx C:\>set AWS_SECRET_ACCESS_KEY=+Xd0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
必要に応じてデフォルトリージョンと出力形式も設定します。
C:\>set AWS_DEFAULT_REGION=ap-northeast-1 C:\>set AWS_DEFAULT_OUTPUT=table
インスタンスIDとポート番号(今回はEC2インスタンスがLinuxなのでSSH=22)を指定してポートフォワーディング機能を呼び出します。
C:\>aws ssm start-session --target i-xxxxxxxxxxxxxxxxx ^ --document-name AWS-StartPortForwardingSession ^ --parameters "{\"portNumber\":[\"22\"]}"
start-session コマンド実行後、ランダムに割り当てられたローカル側のポート番号が出力されます。
Starting session with SessionId: IAM-User01-xxxxxxxxxxxxxxxxx
Port 55394 opened for sessionId IAM-User01-xxxxxxxxxxxxxxxxx.
Connection accepted for session IAM-User01-xxxxxxxxxxxxxxxxx.
各クライアントで 127.0.0.1:[出力されたポート番号] を接続先に指定し、ログインします。

ログイン出来ました。

ちなみに、ローカルのポート番号を指定したい場合は以下のようにします。
C:\>aws ssm start-session --target i-xxxxxxxxxxxxxxxxx ^
--document-name AWS-StartPortForwardingSession ^
--parameters "{\"portNumber\":[\"22\"],\"localPortNumber\":[\"9999\"]}"
RDPの場合
C:\>aws ssm start-session --target i-xxxxxxxxxxxxxxxxx ^ --document-name AWS-StartPortForwardingSession ^ --parameters "{\"portNumber\":[\"3389\"]}"
アクセスキーのローテーション
話がそれますが、CloudFormationで作成したIAMユーザには自身のアクセスキーを作成・削除できる権限があります。
適宜アクセスキーをローテートしましょう。
# 現在利用しているアクセスキーを確認 C:\>echo %AWS_ACCESS_KEY_ID% AKIAxxxxxxxxxxxxxxxx # 新しいアクセスキーを作成 C:\>aws iam create-access-key ------------------------------------------------------------------- | CreateAccessKey | +-----------------------------------------------------------------+ || AccessKey || |+------------------+--------------------------------------------+| || AccessKeyId | AKIAxxxxxxxxxxxxxxxx || || CreateDate | 2019-10-02T07:24:17Z || || SecretAccessKey | iOTbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx || || Status | Active || || UserName | IAM-User01 || |+------------------+--------------------------------------------+| # 新しいアクセスキーをCLIにセット C:\>set AWS_ACCESS_KEY_ID=AKIAxxxxxxxxxxxxxxxx C:\>set AWS_SECRET_ACCESS_KEY=iOTbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # 古いアクセスキーの削除 C:\>aws iam delete-access-key --access-key-id AKIAxxxxxxxxxxxxxxxx
投稿者プロフィール
- 2015年8月入社。弊社はインフラ屋ですが、アプリも作ってみたいです。