実践!AWS CDK #25 Session Manager で SSH 接続
はじめに
AWS Systems Manager(SSM)の Session Manager を介した ローカルマシンから EC2 インスタンスへの SSH 接続方法をご紹介します。
EC2 のセキュリティグループでは SSH の 22 番ポートを開放する必要はありません。
ただし EC2 用のキーペアは作成する必要があります。
正直、CDK との関連はあまりないのですが備忘録的に本シリーズに組み込みたいと思います。
前回の記事はこちら。
AWS 構成図
現在の構成はこちらです。
SSM の Session Manager を利用して VPC 内の EC2 にアクセスします。
本記事をシリーズに組み込んだ理由の一つとして、現在の構成や設定では既に Session Manager が EC2 に接続可能な状態であるということが挙げられます。
Session Manager でハマった場合は、以下の記事を参考に設定を確認してみてください。
実装
キーペアを EC2 のプロパティに組み込む必要があるため、その部分だけ修正します。
まずは devio-stg-key-pair
という名前のキーペアを作成します。
名前のみ指定し、その他の項目はデフォルト値で OK です。
作成と同時にキーファイル devio-stg-key-pair.pem
がダウンロードされるので、保存しておきます。デフォルトの状態だと SSH セッション開始時に次のようなパーミッションエラーが発生するので chmod
コマンドで権限を絞っておきましょう。
Warning: Permanently added 'i-0fbfdfdd68a4f79f5' (ECDSA) to the list of known hosts. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0644 for 'devio-stg-key-pair.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 "devio-stg-key-pair.pem": bad permissions ec2-user@i-0fbfdfdd68a4f79f5: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
以下のコマンドを実行することでエラーは解消されます。
$ chmod 400 devio-stg-key-pair.pem
次に cdk.json
に Context を追加します。キーペアが指定された場合はそれを EC2 に関連付け、指定されない場合は従来通りキーペア無しで構築するようにします。
{ "app": "npx ts-node --prefer-ts-exts bin/devio.ts", "versionReporting": false, "context": { "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, "@aws-cdk/core:enableStackNameDuplicates": "true", "aws-cdk:enableDiffNoFail": "true", "@aws-cdk/core:stackRelativeExports": "true", "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, "@aws-cdk/aws-kms:defaultKeyPolicies": true, "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, "systemName": "devio", "envType": "stg", "keyName": "" } }
EC2 クラスの変更は以下の通りです。
~ 省略 ~ private createInstance(scope: cdk.Construct, resourceInfo: ResourceInfo): CfnInstance { const instance = new CfnInstance(scope, resourceInfo.id, { availabilityZone: resourceInfo.availabilityZone, iamInstanceProfile: this.instanceProfileEc2.ref, imageId: Ec2.latestImageIdAmazonLinux2, instanceType: Ec2.instanceType, securityGroupIds: [this.securityGroupEc2.attrGroupId], subnetId: resourceInfo.subnetId(), tags: [{ key: 'Name', value: this.createResourceName(scope, resourceInfo.resourceName) }], userData: fs.readFileSync(Ec2.userDataFilePath, 'base64') }); const keyName = scope.node.tryGetContext('keyName'); if (keyName) { instance.keyName = keyName; } return instance; } }
Context のキー keyName
に値が入っていればその値(キーペア名)を EC2 インスタンスに設定しています。
デプロイ時は次のように keyName を設定します。
$ cdk deploy --context keyName=devio-stg-key-pair
設定
AWS の公式ドキュメント に従い、設定を行います。
大前提として、SSM の Session Manager で EC2 インスタンスが表示されることを確認しておきましょう。
Session Manager プラグインのインストール
こちらも公式ドキュメントを参考に Session Manager プラグインをローカルマシンにインストールします。
以下は Mac における 2021/09 時点の方法です。正式なインストール手順は公式ドキュメントを参照してください。
インストーラーのダウンロード
$ 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
正常にインストールされたことの確認
$ session-manager-plugin The Session Manager plugin is installed successfully. Use the AWS CLI to start a session.
上記のメッセージが表示されれば OK です。
SSH 設定ファイルの更新
~/.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'"
特定のプロファイルを指定したい場合はここに書く必要があります。(後述の SSH コマンド実行時では NG)
# SSH over Session Manager host i-* mi-* ~省略~ --parameters 'portNumber=%p' --profile cm-personal"
セッションの開始
SSH のセッションを開始するには次のフォーマットで SSH コマンドを実行します。
$ ssh -i /path/my-key-pair.pem username@instance-id
以下の設定で実際にローカルマシンからコマンドを実行してみます。
- username:
ec2-user
- instance-id:
i-0fbfdfdd68a4f79f5
無事、EC2 インスタンスにログインできました。
便利ですね。
こちらが対象のインスタンス情報です。
セキュリティグループは ALB からの 80 番ポートしか許可していません。
セキュリティも安心です。
GitHub
今回のソースコードは コチラ です。
おわりに
この機能を利用することで EC2 インスタンスに SSH 用のポートを開けることなく、ローカルマシンから SSH 接続ができるようになります。セキュリティも向上しますし、場合によっては踏み台サーバーが不要になりコスト削減ができるかもしれません。興味がある場合はお試しください。
リンク
- Session Manager を通じて SSH 接続を有効にする | AWS Systems Manager User Guide
- AWS CLI 用の Session Manager プラグインをインストールする | AWS Systems Manager User Guide
- セッションを開始する | AWS Systems Manager User Guide
- 【初心者向け】Session Manager でインスタンスが表示されない時のトラブルシュート | DevelopersIO
- セッションマネージャー越しにSSHアクセスすると何が嬉しいのか | DevelopersIO
- AWS Systems Manager セッションマネージャーでSSH・SCPできるようになりました | DevelopersIO