Systems ManagerのRunCommandでSSHを使わずにShellライクにコマンドを実行する

スタートプラン

おはようございます。加藤です。
今日はSystems Managerを使ってEC2の中身をSSHせずに管理する方法を紹介します。
SSHレスによるメリットは以下のようなものがあります。

  • 公開鍵・秘密鍵を管理しなくてよい
  • ネットワークが繋がっていなくても操作できる
    • プライベートなネットワークなど

私はTerraformでAWSを触ることが多いので、抜粋ですがTerraformのコードも記載しておきます。

環境・前提

項目 バージョン
MacOS 10.13.3(17D102)
Go 1.9.3
ssm-sh v0.3.0

手順

EC2にアタッチするロールを作成

  1. IAM管理画面に切り替え
  2. ロールメニューを選択
  3. ロール作成
    1. ロールを使用するサービスに"EC2"を選択
    2. "AmazonEC2RoleforSSM"をアタッチ
    3. 任意のロール名を指定する(ここでは"AmazonEC2RoleforSSM"とした)

iam.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
resource "aws_iam_instance_profile" "ec2role_for_ssm" {
  name  = "ec2role_for_ssm"
  role = "${aws_iam_role.ec2role_for_ssm.name}"
}
 
resource "aws_iam_role" "ec2role_for_ssm" {
  name = "EC2RoleforSSM"
  path = "/"
   
  assume_role_policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Principal": {
               "Service": "ec2.amazonaws.com"
            },
            "Effect": "Allow",
            "Sid": ""
        }
    ]
}
EOF
}
 
resource "aws_iam_role_policy_attachment" "ec2role_for_ssm_attachment0" {
    role = "${aws_iam_role.ec2role_for_ssm.name}"
    policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
}

管理するEC2を作成

  1. EC2管理画面に切り替え
  2. セキュリティグループを作成
    1. インバウンド許可なし
    2. アウトバウンド全許可
  3. EC2を2台作成
    1. 作成したセキュリティグループを割り当て
    2. 作成したIAMロールを割り当て

セキュリティグループ

方向 プロトコル ポート範囲 送信元/先
アウトバウンド すべて すべて 0.0.0.0/0
アウトバウンド すべて すべて ::/0

インスタンスパラメータ

インスタンス名 タイプ AMI_ID
amzn t2.micro ami-ceafcba8
amzn2 t2.micro ami-c2680fa4
security_group.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## Outbound only
### security group
resource "aws_security_group" "outbound_only" {
  name        = "outbound_only"
  description = "outbound_only"
  vpc_id      = "${aws_vpc.main.id}"
 
  tags {
    Name = "outbound_only"
    Project = "${var.project["name"]}"
    DeployBy = "Terraform"
  }
}
 
### security group rule
 
resource "aws_security_group_rule" "outbound_only_rule_egress0" {
    type = "egress"
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
 
    security_group_id = "${aws_security_group.outbound_only.id}"
}
instance.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
resource "aws_instance" "amzn1" {
    ami = "ami-ceafcba8"
    instance_type = "t2.micro"
    subnet_id = "${aws_subnet.public0.id}"
    vpc_security_group_ids = ["${aws_security_group.outbound_only.id}"]
    key_name = "${aws_key_pair.main.key_name}"
    iam_instance_profile = "${aws_iam_instance_profile.ec2role_for_ssm.name}"
 
    tags {
      Name = "amzn1"
      Project = "${var.project["name"]}"
      DeployBy = "Terraform"
    }
}
resource "aws_instance" "amzn2" {
    ami = "ami-c2680fa4"
    instance_type = "t2.micro"
    subnet_id = "${aws_subnet.public1.id}"
    vpc_security_group_ids = ["${aws_security_group.outbound_only.id}"]
    key_name = "${aws_key_pair.main.key_name}"
    iam_instance_profile = "${aws_iam_instance_profile.ec2role_for_ssm.name}"
 
    tags {
      Name = "amzn2"
      Project = "${var.project["name"]}"
      DeployBy = "Terraform"
    }
}

マネジメントコンソール・AWS CLIから操作する

本記事では紹介しません、参考URLを記載しておきます。

ssm-shから操作する

ssm-shはGo言語で書かれたツールです。Systems Managerのsend commandsを利用しSSHせずにShellライクでコマンドを使えます。  

バージョンが<=1、OSSなので、使用は自己責任でお願い致します。  

インストール

1
go get -u github.com/itsdalmo/ssm-sh

ヘルプ確認

ヘルプを確認してみます。デフォルトリージョンがeu-west-1になっているので、日本リージョンを明示的に指定する必要があるようです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ssm-sh   --help
Usage:
  ssm-sh [OPTIONS] <list | run | shell>
 
Application Options:
  -v, --version  Print the version and exit.
 
AWS Options:
  -p, --profile= AWS Profile to use. (If you are not using Vaulted).
  -r, --region=  Region to target. (default: eu-west-1)
 
Help Options:
  -h, --help     Show this help message
 
Available commands:
  list   List managed instances. (aliases: ls)
  run    Run a command on the targeted instances.
  shell  Start an interactive shell. (aliases: sh)

インスタンス一覧取得

listコマンドを使って管理できるインスタンス一覧を取得します。

1
ssm-sh -r ap-northeast-1 list
1
2
3
Instance ID         | Name  | State   | Image ID     | Platform         | Version | IP         | Status | Last pinged
i-055d87cb9xxxxxxxx | amzn2 | running | ami-c2680fa4 | Amazon Linux     | 2.0     | 10.0.1.195 | Online | 2018-03-06 09:12
i-0219de9d6xxxxxxxx | amzn1 | running | ami-ceafcba8 | Amazon Linux AMI | 2017.09 | 10.0.0.230 | Online | 2018-03-06 09:12

意図した通りの情報を取得できています。

ワンライナー実行

ワンライナーという言い方は適切でないかもしれません...
コマンド実行が完了後にすぐに操作端末のShellに戻ってくるモードです。
試しにコマンドを実行してみます。

1
ssh-sh -r (リージョン) run -t (インスタンスID) (コマンド)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
### amzn
 
ssm-sh -r ap-northeast-1 run -t i-0219de9d6xxxxxxxx cat /etc/os-release
Initialized with targets: [i-0219de9d6xxxxxxxx]
Use ctrl-c to abort the command early.
 
 
i-0219de9d6xxxxxxxx - Success:
NAME="Amazon Linux AMI"
VERSION="2017.09"
ID="amzn"
ID_LIKE="rhel fedora"
VERSION_ID="2017.09"
PRETTY_NAME="Amazon Linux AMI 2017.09"
ANSI_COLOR="0;33"
CPE_NAME="cpe:/o:amazon:linux:2017.09:ga"
 
### amzn2
 
ssm-sh -r ap-northeast-1 run -t i-055d87cb9xxxxxxxx cat /etc/os-release
Initialized with targets: [i-055d87cb9xxxxxxxx]
Use ctrl-c to abort the command early.
 
 
i-055d87cb9xxxxxxxx - Success:
NAME="Amazon Linux"
VERSION="2.0 (2017.12)"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2.0"
PRETTY_NAME="Amazon Linux 2.0 (2017.12) LTS Release Candidate"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2.0"

おお!ばっちり動作していますね

Shellライク

ここが本記事のメインです。実際に触ってみます。

1
ssh-sh -r (リージョン) shell -t (インスタンスID)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
ssm-sh -r ap-northeast-1 shell -t i-055d87cb9xxxxxxxx
Initialized with targets: [i-055d87cb9xxxxxxxx]
Type 'exit' to exit. Use ctrl-c to abort running commands.
 
» pwd
 
i-055d87cb9xxxxxxxx - Success:
/usr/bin
 
» whoami
 
i-055d87cb9xxxxxxxx - Success:
root
 
» ping -c 3 amazonaws.com
 
i-055d87cb9xxxxxxxx - Success:
PING amazonaws.com (72.21.206.80) 56(84) bytes of data.
64 bytes from 206-80.amazon.com (72.21.206.80): icmp_seq=1 ttl=223 time=187 ms
64 bytes from 206-80.amazon.com (72.21.206.80): icmp_seq=2 ttl=223 time=187 ms
64 bytes from 206-80.amazon.com (72.21.206.80): icmp_seq=3 ttl=223 time=188 ms
 
--- amazonaws.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 187.578/187.785/188.156/0.565 ms
 
 
i-055d87cb9xxxxxxxx - Success:
54.250.xxx.xxx
 
» cd /root
 
i-055d87cb9xxxxxxxx - Success:
 
» pwd
 
i-055d87cb9xxxxxxxx - Success:
/usr/bin
 
» exit

しっかりと動作しました!
cdでディレクトリ移動ができないのは想定どおりです、コマンド1つごとのSSMのRunShellScriptが走っていて連続性が無いためです。
なので以下のような操作も行えません。

  • TUI
  • yes/no など応答を求めるもの

Systems Managerを確認するとしっかりとコマンド履歴が残っていました。

あとがき

前回のブログでSSでの管理についても触れて欲しかったとコメントを頂いたのがきっかけでこの記事を書こうと思いました。
今回は扱いませんでしたが、エージェントを入れればオンプレミスにあるサーバもSSM管理下の置くことができます。
SSMは本当に便利ですね、もっと活用していこうと思います。

最初は自分でツールを作ろうとしましたが、社内で相談してみるとこのツールを教えてもらいブログにしました。

スタートプラン