はじめに
GoのAWS SDKを使用してAWSのEC2インスタンスにコマンドを送信し、その結果を取得してみました。sshで接続してからのコマンド実行ではなく、AWS Systems Manager (SSM)の機能を使用してEC2インスタンスにコマンドを実行させました。
前提条件
- SSM Agentのインストール: EC2インスタンスにSSM Agentがインストールされている必要があります。これにより、EC2のインスタンスがAWS Systems Managerと通信できるようになります。多くのAWS提供のAMIにはSSM Agentが事前にインストールされています。また、今回やりませんでしたが、手動でインストールすることもできます
- 権限の設定: コマンドを実行するためには、IAMロールやポリシーを設定し、必要な権限を付与する必要があります。例えば、EC2インスタンスには、AmazonSSMManagedInstanceCoreポリシーをアタッチしたIAMロールを設定することでSSMからEC2に対してコマンド実行できるようになります
EC2インスタンスをSystems Managerのマネージドインスタンスとして登録(権限の設定)
今回は、Systems Managerの「高速セットアップ」機能を使用し、Default Host Management Configuration (DHMC)を設定しました。これにより、対象のEC2インスタンスに自動的にAmazonSSMManagedEC2InstanceDefaultPolicyが適用され、Systems Managerのマネージドインスタンスとして登録されます。この場合でも、SSMからEC2に対してコマンドを実行できるようになります。
以下は、DHMC設定時のキャプチャです。
作成したコードについて
GoのAWS SDKを使用してEC2インスタンスでコマンドを実行するコードです。SSMの機能を使用してEC2に対してコマンドを実行します。
コマンド実行
package main
import (
"fmt"
"log"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ssm"
)
// 中間のコードを省略
// 1.AWSセッションの作成
sess, err := session.NewSessionWithOptions(session.Options{
Config: aws.Config{
Region: aws.String("ap-northeast-1"), // 適切なリージョンを指定
},
Profile: "default", // 適切なプロファイルを指定
})
if err != nil {
log.Fatalf("Failed to create session: %v", err)
}
// 2. SSMクライアントの作成
ssmClient := ssm.New(sess)
// 3. コマンドの設定と送信
instanceId := "your-instance-id" // EC2インスタンスIDを指定
cmdstring := "echo Hello, World!" // 実行したいコマンドを指定
output, err := ssmClient.SendCommand(&ssm.SendCommandInput{
InstanceIds: []*string{aws.String(instanceId)},
DocumentName: aws.String("AWS-RunShellScript"),
Parameters: map[string][]*string{
"commands": {
aws.String(cmdstring),
},
},
})
if err != nil {
log.Fatalf("Failed to send command: %v", err)
return
}
// 4. コマンド実行結果の取得
commandID := output.Command.CommandId
time.Sleep(5 * time.Second) // 5秒待つ
result, err := ssmClient.GetCommandInvocation(&ssm.GetCommandInvocationInput{
CommandId: commandID,
InstanceId: aws.String(instanceId),
})
if err != nil {
log.Fatalf("Failed to get command result: %v", err)
return
}
// コマンドの出力を表示
fmt.Printf("Command output: %s\n", *result.StandardOutputContent)
コードの説明
次の処理をおこなっています。
-
AWSセッションの作成
AWS SDKのセッションを作成します。リージョンとプロファイルを指定して、AWSリソースにアクセスするための設定を行います -
SSMクライアントの作成
作成したセッションを使用して、SSMクライアントを初期化しています。 -
コマンドの設定と送信
SendCommandメソッドを使用して、指定したEC2のインスタンスにコマンドを送信しています。AWS-RunShellScriptドキュメントを使用して、シェルコマンドを実行するように設定しています -
コマンド実行結果の取得
ssmClient.SendCommandが実行完了までまたないため、5秒間WaitしたのGetCommandInvocationメソッドを使用して、実行したコマンドの結果を取得させていますが、実際には、result.statusがsuccessになるまでループさせて待つ方法がいいと思います。
おわりに
GoのAWS SDKを使用してEC2インスタンスにコマンドを実行し、その結果を取得しました。セキュリティと権限の管理には気を付ける必要がありますが、プログラムによる制御でリモートからコマンドを実行できるため、運用や管理が自動化、効率化できると思います。