SSMネタの第3弾です
ことの発端
社長:「〇〇のAWSアカウントの請求額、高いねんけど」
社長:「ClientVPNが一番しめてるわ」
社長:「なんとかならん?」
このClientVPNはプライベートにあるWindowsサーバへ接続するためで、利用するのはWindows上で動いてるソフトのメンテ用になってます
何かあるとき(トラブル時)しか使わないので常時ClientVPNを置いておくのはもったいないってことで、ClientVPNをやめてSSMに置き換えてみます(インフラ民はSSMでつないでるのでClientVPNは使ってません)
やりたいこと
- RDPだけに制限したい
- 接続先を特定のWindowsサーバだけにしたい
RDPだけに制限する
RDPのポートだけに接続するSSMドキュメントを作成する
AWS-StartPortForwardingSession
はどのポートでも接続することができるため、このドキュメントをコピーして新たにRDPのポートだけのドキュメントを作成します
以下はドキュメントのコンテンツ内容です
{
"schemaVersion": "1.0",
"description": "Document to start port forwarding session over Session Manager",
"sessionType": "Port",
"parameters": {
"localPortNumber": {
"type": "String",
"description": "(Optional) Port number on local machine to forward traffic to. An open port is chosen at run-time if not provided",
"allowedPattern": "^([0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
"default": "0"
}
},
"properties": {
"portNumber": "3389",
"type": "LocalPortForwarding",
"localPortNumber": "{{ localPortNumber }}"
}
}
変更箇所は parameters
から portNumber
を削除して、properties
の portNumber
を 3389 の固定にするだけです
上記のファイルで新たにドキュメントを作成
aws ssm create-document --content file://rdp_forward_document.json --name RdpForwardingSession --document-type Session --document-format JSON
IAMユーザを作成
IAMユーザはSSMだけ使えるようにしたいので「プログラムによるアクセス」で作成します
IAMユーザに作成したドキュメントを許可するポリシーを設定します
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ssm:StartSession",
"Resource": [
"arn:aws:ssm:ap-northeast-1:xxxxxxxxxxxx:document/RdpForwardingSession"
]
},
{
"Effect": "Allow",
"Action": "ssm:TerminateSession",
"Resource": "arn:aws:ssm:ap-northeast-1:xxxxxxxxxxxx:session/${aws:username}-*"
}
]
}
ssm:TerminateSession
では自分自身のsessionだけを対象とするため、${aws:username}-*
とします
試しにテストしてみます
$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX --document-name RdpForwardingSession
Starting session with SessionId: hoge-xxxxxxxxxxxxxxxxx
Port 13389 opened for sessionId hoge-xxxxxxxxxxxxxxxxx.
$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX --document-name AWS-StartPortForwardingSession --parameters 'portNumber=3389'
An error occurred (AccessDeniedException) when calling the StartSession operation: User: arn:aws:iam::xxxxxxxxxxxx:user/hoge is not authorized to perform: ssm:StartSession on resource: arn:aws:ssm:ap-northeast-1::document/AWS-StartPortForwardingSession
AWS-StartPortForwardingSession
は AccessDenied となったので意図通りのようです
Document指定なしでも試してみます
$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX
Starting session with SessionId: hoge-xxxxxxxxxxxxxxxxx
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.
PS C:\Windows\system32>
あれ・・・? 入れる・・・
AWSのドキュメントを確認してみます
AWS CLI でセッションドキュメントのアクセス許可チェックを適用する
デフォルトでは、IAM ユーザーポリシーでセッションを開始するアクセス許可がアカウントのユーザーに付与されている場合、そのユーザーはこの
SSM-SessionManagerRunShell
SSM ドキュメントにアクセスできます。つまり、AWS CLI を使用してstart-session
コマンドを実行し、--document-name
オプションでドキュメントを指定しない場合、システムはSSM-SessionManagerRunShell
を使用してセッションを開始します。セッションは、ユーザーの IAM ポリシーでSSM-SessionManagerRunShell
ドキュメントへのアクセスが明示的に許可されていない場合でも開始されます。
なるほど・・・
デフォルトまたは任意のセッションドキュメントへのアクセスを制限するには、ユーザーにセッションドキュメントへのアクセスが明示的に許可されているかどうかを検証する条件要素を、ユーザーの IAM ポリシーに追加できます。この条件が適用されると、ユーザーは
start-session
AWS CLI コマンドの--document-name
オプションの値を指定する必要があります。
ってことなのでポリシーに明示的に許可されているかどうの条件を追加します
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ssm:StartSession",
"Resource": [
"arn:aws:ssm:ap-northeast-1:XXXXXXXXXXXX:document/RdpForwardingSession"
],
"Condition": {
"BoolIfExists": {
"ssm:SessionDocumentAccessCheck": "true"
}
}
},
{
"Effect": "Allow",
"Action": "ssm:TerminateSession",
"Resource": "arn:aws:ssm:ap-northeast-1:XXXXXXXXXXXX:session/${aws:username}-*"
}
]
}
もう再度テスト
$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX
An error occurred (AccessDeniedException) when calling the StartSession operation: User: arn:aws:iam::xxxxxxxxxxxx:user/hoge is not authorized to perform: ssm:StartSession on resource: arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-XXXXXXXXXXXXXXXXX
AccessDenied となりました
これで1つ目の課題はOKになりました
接続先を特定のInstanceだけにする
2つ目の課題、接続先も制限したいのでResourceにInstanceのARNを追加します
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ssm:StartSession",
"Resource": [
"arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-XXXXXXXXXXXXXXXXX",
"arn:aws:ssm:ap-northeast-1:XXXXXXXXXXXX:document/RdpForwardingSession"
],
"Condition": {
"BoolIfExists": {
"ssm:SessionDocumentAccessCheck": "true"
}
}
},
{
"Effect": "Allow",
"Action": "ssm:TerminateSession",
"Resource": "arn:aws:ssm:ap-northeast-1:XXXXXXXXXXXX:session/${aws:username}-*"
}
]
}
試しに別のInstanceへ接続
$ aws ssm start-session --target i-YYYYYYYYYYYYYYYYY
An error occurred (AccessDeniedException) when calling the StartSession operation: User: arn:aws:iam::xxxxxxxxxxxx:user/hoge is not authorized to perform: ssm:StartSession on resource: arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-YYYYYYYYYYYYYYYYY
あとは、AccessKey/SecretAccessKey と aws cliコマンドをべた書きしたバッチファイルをメンテする人に渡せばOK
これでなんとかClientVPNを撤廃できそう
SSMネタが続いたので次回は違うものにしよう・・・