🛰️

AWS EC2 の22番ポートを閉じつつセキュアにリモートコマンドを実行する #SSM

に公開

はじめに

EC2インスタンスに対して何か操作をしたい時に SSH を用いてログインして作業をすることはよくあると思います。
SSH はインスタンスのシェルに直接入って操作が可能なので、直感的な操作が可能である一方で、
SSHキー の扱い等には気を配る必要があります。

そこで、AWS Systems Manager (SSM) の機能を用いることで、AWSの認証情報を使いつつセキュアにリモートコマンドを実行することができます。
また、接続先をインスタンスIDで指定するため、Elastic IP を振っていないインスタンスを再起動して Public IP が変わってしまったとしてもコマンドの接続先を変更する必要がありません。

日中しか使わない踏み台サーバーのIPを固定するために Elastic IP を振っていたり、夜間も休日も起動しっぱなしにしていませんか?
もしくは、CICDからリモートコマンドを実行するためにSSHキーをリポジトリにアップしていませんか?

SSM で全部解決できます。

SSM について

SSM はAWSが提供する サーバー管理サービス です。
AWS上のEC2インスタンスやオンプレミスのサーバー等のあらゆるサーバーを一元的に管理するための各種機能を提供します。

SSM でリモートコマンドを実行するための機能

SSM でリモートコマンド実行するためには以下の2つの方法があります。
どちらの方法でも適切な権限設定とホストサーバーに SSM Agent をインストールする必要があります。
EC2の場合は大抵のAMIでプリインストールされています。

機能 特徴
Run Command 非対話式で複数行のリモートコマンドを一括実行できる
複数インスタンスに対して同時にコマンドを実行することもできる

CICD等からコマンドを実行したい場合はこれを使う
Session Manager 対話式でSSHのようにコマンドを実行できる
利用にはクライアントPCにプラグインをインストールする必要がある

SSHの代替として利用したい場合や、踏み台サーバーにアクセスする場合はこれを使う

EC2の場合はどちらも無料で利用出来ます。
オンプレの場合は追加のプランが必要になったりします。
-> オンプレミスインスタンス管理を参照

SSM のリモートコマンド実行の仕組み

雑なフロー図

説明文

SSM におけるリモートコマンドはEC2インスタンス内の SSM Agent が SSM に対して定期的にポーリングすることで実現されています。
このポーリングは443番ポートのアウトバウントのみで行われるため、インバウンドルールを最小限にすることができます。
-> エンドポイントへの接続の部分を参照
また、AWS CLIによる認証を行うため、実行権限のあるユーザーしかリモートコマンドを実行できないような仕組みになっています。

SSH と比較した際の SSM の利点

SSH と 比較した際の SSM を使う利点としては、主に以下の3つがあります。

  1. AWS の認証情報を使って認証とアクセスを行うためSSHキーを管理する必要がなくなり、セキュリテイリスクが低減する
  2. 22番ポートへのインバウンドを閉鎖できるためセキュリティリスクが低減する
  3. Public IP を考慮しなくてよくなるため、場合によってはコスト削減につながる

    Elastic IPはインスタンスの起動状態に関わらずIPあたり月3.6$かかるようになりました。
    特に社内ツールや踏み台サーバー等の利用者がいない時間帯は停止しても問題ないインスタンスで、再起動するたびにPublic IPが振り直されるのを防ぐためにElastic IPを使っていたり、そもそも再起動させないように運用しているインスタンスがある場合はコスト削減が期待できます。

考慮すべきこと

SSM は SSH と違って AWS が提供するサービスであるため、場合によってはサービス自体に問題が発生する可能性もあります。
そのため緊急時のアクセス手段として、管理者等がSSHキーを保持しておいて、いざとなれば SSH もできるようにしておくことも大事になります。

普段は22番ポートは閉鎖しておいて緊急時のみ解放する

構築方法

ユースケース別に構築方法を解説します。
ユースケース1: 非対話式にローカルからEC2にリモートコマンドを実行したい場合

ユースケース2: SSHの代替として対話式のシェルでローカルからEC2にアクセスしたい場合

ユースケース3: Github Actions からEC2にリモートコマンドを実行したい場合

作業環境

  • Debian Bookworm (Windows 上で Devcontainer を実行)
  • AWS CLI v2.28.17
  • EC2 (Amazon Linux 2023)
  • Terraform (IaC)

Terraform を用いてインフラ構築を行なっているため、具体的なコードを記載しますので参考にしてください。

ユースケース1: 非対話式にローカルからリモートコマンドを実行して結果を確認する

Run Command を使います。
ざっくりとした手順は以下です。

  1. VPCを作成し、セキュリティグループのアウトバウンドルールで443番ポートを許可する
  2. 上記のVPCに SSM Agent がプリインストールされているAMIを指定してEC2インスタンスを起動
  3. EC2用のIAMロール (インスタンスプロファイルロール) を作成してインスタンスに付与
  4. インスタンスプロファイルロールに AmazonSSMManagedInstanceCore ポリシーを付与
  5. aws cli で認証する
  6. クライアントから aws ssm send-command を実行してリモートコマンドを発行
  7. クライアントから aws ssm get-command-invocation で結果を確認
  8. (Option) 22番ポートのインバウンドを無効にして検証する

Terraform での構築例

VPC と EC2 はそれぞれモジュール化しています。
https://github.com/kazeusagi/terraform-ssm/blob/main/terraform/environments/usecase-1/main.tf

1. VPCを作成し、セキュリティグループのアウトバウンドルールで443番ポートを許可する

Terraform での VPC モジュール例

VPC のモジュール定義は以下

以下、抜粋

variables.tf
variable "name" {
  description = "名前"
  type        = string
}

variable "allow_ssh" {
  description = "SSHを許可するか"
  type        = bool
}
main.tf
# 以下を作成します。
# VPC, Subnet, Internet Gateway, Default Route Table, Default Network ACL, Default Security Group

# VPC
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    "Name" = "${var.name}-vpc"
  }
}



# Subnet
resource "aws_subnet" "public_1a" {
  vpc_id = aws_vpc.main.id

  cidr_block              = "10.0.1.0/24"
  availability_zone       = "ap-northeast-1a"
  map_public_ip_on_launch = true # パブリックIPを自動割り当て

  tags = {
    Name = "${var.name}-subnet-public-1a"
  }
}



# Internet Gateway
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "${var.name}-igw"
  }
}



# Default Route Table
resource "aws_default_route_table" "public" {
  default_route_table_id = aws_vpc.main.default_route_table_id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }

  tags = {
    Name = "${var.name}-rtb-public"
  }
}
resource "aws_route_table_association" "public_1a" {
  subnet_id      = aws_subnet.public_1a.id
  route_table_id = aws_default_route_table.public.id
}



# Default Network ACL
resource "aws_default_network_acl" "main" {
  default_network_acl_id = aws_vpc.main.default_network_acl_id
  subnet_ids             = [aws_subnet.public_1a.id]

  ingress {
    protocol   = -1
    rule_no    = 100
    action     = "allow"
    cidr_block = "0.0.0.0/0"
    from_port  = 0
    to_port    = 0
  }
  egress {
    protocol   = -1
    rule_no    = 100
    action     = "allow"
    cidr_block = "0.0.0.0/0"
    from_port  = 0
    to_port    = 0
  }

  tags = {
    Name = "${var.name}-acl"
  }
}



# Default Security Group
resource "aws_default_security_group" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "${var.name}-sg"
  }
}

## インターネット -> VPC: SSH 許可
resource "aws_vpc_security_group_ingress_rule" "ingress_ssh" {
  count = var.allow_ssh ? 1 : 0 # true の場合のみ作成

  security_group_id = aws_default_security_group.main.id
  cidr_ipv4         = "0.0.0.0/0"
  ip_protocol       = "tcp"
  from_port         = 22
  to_port           = 22
}

## インターネット -> VPC: HTTP 許可
resource "aws_vpc_security_group_ingress_rule" "ingress_http" {
  security_group_id = aws_default_security_group.main.id
  cidr_ipv4         = "0.0.0.0/0"
  ip_protocol       = "tcp"
  from_port         = 80
  to_port           = 80
}

## VPC -> インターネット: すべて許可
resource "aws_vpc_security_group_egress_rule" "egress_all" {
  security_group_id = aws_default_security_group.main.id
  cidr_ipv4         = "0.0.0.0/0"
  ip_protocol       = "-1" # 全てのポート
}

2. 上記のVPCに SSM Agent がプリインストールされているAMIを指定してEC2インスタンスを起動

大体のAMIには SSM Agent がプリインストールされています。
詳細はこちら
参考までに私は Amazon Linux 2023 amd64 (id: ami-07faa35bbd2230d90) を使用しました。

Terraform での EC2 モジュール例

EC2 のモジュール定義は以下

以下、抜粋

variables.tf
variable "name" {
  description = "名前"
  type        = string
}

variable "ami_id" {
  description = "AMI ID"
  type        = string
}

variable "instance_type" {
  description = "インスタンスタイプ"
  type        = string
}

variable "subnet_id" {
  description = "サブネットID"
  type        = string
}

variable "security_group_id" {
  description = "セキュリティグループID"
  type        = string
}

variable "enable_ssh" {
  description = "SSHを有効にするか"
  type        = bool
}

variable "enable_ssm" {
  description = "SSMを有効にするか"
  type        = bool
}
data.tf
# EC2の信頼ポリシー
data "aws_iam_policy_document" "ec2" {
  version = "2012-10-17"
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}
main.tf
# SSH Key: enable_ssh が true の場合のみ作成
resource "tls_private_key" "main" {
  algorithm = "RSA"
  rsa_bits  = 4096
}
resource "aws_key_pair" "main" {
  count      = var.enable_ssh ? 1 : 0
  key_name   = "${var.name}-key"
  public_key = tls_private_key.main.public_key_openssh
}




# インスタンスプロファイル用のロール
resource "aws_iam_role" "main" {
  name               = "${var.name}-ec2_Role"
  assume_role_policy = data.aws_iam_policy_document.ec2.json
}
# SSM 許可ポリシー: enable_ssm が true の場合のみアタッチ
resource "aws_iam_role_policy_attachment" "main" {
  count      = var.enable_ssm ? 1 : 0
  role       = aws_iam_role.main.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
# インスタンスプロファイル
resource "aws_iam_instance_profile" "main" {
  name = "${var.name}-ec2_InstanceProfile"
  role = aws_iam_role.main.name
}



# EC2
resource "aws_instance" "main" {
  ami                    = var.ami_id
  instance_type          = var.instance_type
  subnet_id              = var.subnet_id
  vpc_security_group_ids = [var.security_group_id]
  key_name               = var.enable_ssh ? aws_key_pair.main[0].key_name : null # enable_ssh が true の場合のみ設定
  iam_instance_profile   = aws_iam_instance_profile.main.name

  tags = {
    Name = "${var.name}-ec2"
  }
}



# SSH Keyをローカルに保存: enable_ssh が true の場合のみ保存
resource "local_file" "ssh_key" {
  count           = var.enable_ssh ? 1 : 0
  filename        = "${path.cwd}/.ssh/${var.name}-key.pem"
  content         = tls_private_key.main.private_key_pem
  file_permission = "0400"
  depends_on      = [aws_key_pair.main]
}
# IPアドレスをローカルに保存: enable_ssh が true の場合のみ保存
resource "local_file" "ip_address" {
  count      = var.enable_ssh ? 1 : 0
  filename   = "${path.cwd}/.ssh/${var.name}-ip.txt"
  content    = aws_instance.main.public_ip
  depends_on = [aws_instance.main]
}

3. EC2用のIAMロール (インスタンスプロファイルロール) を作成してインスタンスに付与

EC2インスタンスがAWSのリソースにアクセスする際の権限等を インスタンスプロファイル を使って設定します。
EC2からこのロールを使用するにはEC2自体にロールをアタッチする必要があり、またロール側でも以下のような信頼ポリシーを設定する必要があります。

https://github.com/kazeusagi/terraform-ssm/blob/main/terraform/modules/ec2/data.tf

より詳細なコードは手順2 -> main.tf -> インスタンスプロファイルの箇所を参照

4. インスタンスプロファイルロールに AmazonSSMManagedInstanceCore ポリシーを付与

EC2インスタンスが SSM にアクセスしてリモートコマンドの送受信をするのに必要な権限セットが AmazonSSMManagedInstanceCore ポリシーです。
-> 詳細はこちら

詳細なコードは手順2 -> main.tf -> インスタンスプロファイルの箇所を参照

5. aws cli で認証する

私は SSO を用いた認証を行っているので以下コマンドでログインします。

aws sso login

6. クライアントから aws ssm send-command を実行してリモートコマンドを発行

適切な instance-id を入力して実行してください。

aws ssm send-command \
  --instance-ids "i-1234567890abcdef" \
  --document-name "AWS-RunShellScript" \
  --parameters 'commands=[
    "echo Hello",
    "echo World !"
  ]'

成功したら CommandId をコピーしておきます。

7. クライアントから aws ssm get-command-invocation で結果を確認

適切な instance-idcommand-id を入力して実行してください。

aws ssm get-command-invocation \
  --instance-id "i-1234567890abcdef" \
  --command-id "12345678-90ab-cdef-ghij-klmnopqrstuv"

成功したら StandardOutputContentHello World ! と表示されるはずです。

実行できない場合

AWSコンソールで AWS Systems Manager -> フリートマネージャー に進んでいただくと SSM でリモートコマンドが実行可能なインスタンス一覧が表示されます。
ここに表示されなければこちらの必須条件のうちの何が満たされていない可能性があるのでもう一度確認してみて下さい。

フリートマネージャーの画面例

ユースケース2: SSHの代替として対話式のシェルをローカルから実行する

Session Manager を使います。
また、前提条件としてユースケース1の環境構築が完了している必要があります。

というのも Session Manager を使うには Run Command の環境に追加の手順が必要だからです。

以下、ざっくり手順

  1. Run Command の実行に必要な環境の構築
  2. Session Manager Plugin のインストール
  3. aws ssm start-session コマンドで接続

1. Run Command の実行に必要な環境の構築

ユースケース1を参照してください。

2. Session Manager Plugin のインストール

こちらを参考に、OSに合ったインストール方法を参照して実施してください。
私は Devcontainer なので以下のように対応しています。

https://github.com/kazeusagi/terraform-ssm/blob/0b900d9c3487faee1b2da313eaf0f21e0859810d/.devcontainer/onCreateCommand.sh

aws ssm start-session コマンドで接続

aws cli でログイン後に以下コマンドで対話式のシェルを起動できます。

aws ssm start-session --target i-1234567890abcdef

ユースケース3: Github Actions からリモートコマンドを実行する

Run Command を使います。
そのため、ユースケース1の環境構築が完了している必要があります。
また、Github Actions から AWS へのアクセスには OpenID Connect (OIDC) を使います。

以下、ざっくり手順

  1. Run Command の実行に必要な環境の構築
  2. OpenID Connet Provider (IdP) の作成
  3. IdP のアクセス制御を行うためのIAMロールの作成
  4. SSM への最小権限ポリシーを作成してIAMロールにアタッチ
  5. 作成したIAMロールのARNや対象のインスタンスのID等をCICD上から参照できるように Environments を作成する
  6. ワークフロー定義を作成
    • AWSへ認証 (Assume Roleで指定したロールの権限を引き継ぐ)
    • aws ssm send-command でリモートコマンドを実行
    • aws ssm wait command-executed でリモートコマンドの完了まで待機
    • aws ssm get-command-invocation でリモートコマンドの実行結果を表示

Terraform での構築例

OIDC に必要な IDプロバイダ と プロバイダに割り当てるロール と ロールに割り当てる最小権限ポリシー をまとめて一つのモジュールに定義しています。
また、Github Actions で利用する Environments の生成も Terraform から実施しています。
https://github.com/kazeusagi/terraform-ssm/blob/03fd022609428b8d35b63a3177256c143672aaa2/terraform/environments/usecase-3/main.tf

1. Run Command の実行に必要な環境の構築

ユースケース1を参照してください。

2. OpenID Connet Provider (IdP) の作成

Terraform での OIDC モジュール例

OIDC 関連のモジュール定義は以下

抜粋

variables.tf
variable "allowed_github_repositories" {
  description = "許可するGithubリポジトリの一覧"
  type        = list(string)
}

variable "allow_ssm" {
  description = "SSMを許可するか"
  type        = bool
  default     = false
}
main.tf
# IDプロバイダ
resource "aws_iam_openid_connect_provider" "main" {
  url            = "https://token.actions.githubusercontent.com"
  client_id_list = ["sts.amazonaws.com"]
}



# IDプロバイダに割り当てるロール: AssumeRoleの許可設定を行う
module "iam_oidc_role" {
  source                      = "../role"
  name                        = "GithubActionsOIDCRole"
  iam_oidc_provider_arn       = aws_iam_openid_connect_provider.main.arn
  allowed_github_repositories = var.allowed_github_repositories
}



# SSMへの最小権限のポリシー
module "iam_oidc_policy_ssm" {
  count  = var.allow_ssm ? 1 : 0
  source = "../policy/ssm"
  name   = "GithubActionsOIDCRole_SSMPolicy"
}



# ポリシーをロールにアタッチ
resource "aws_iam_role_policy_attachment" "ssm" {
  count      = var.allow_ssm ? 1 : 0
  role       = module.iam_oidc_role.name
  policy_arn = module.iam_oidc_policy_ssm[0].arn
}

OIDC を解説しだすと終わらなくなってしまうので、技術的な詳細は公式ドキュメントを参照ください。

3. IdP のアクセス制御を行うためのIAMロールの作成

Terraform での OIDC IAMロール モジュール例

OIDC IAM ロール のモジュール定義は以下

抜粋

variables.tf
variable "name" {
  type        = string
  description = "IAMロールの名前"
}

variable "iam_oidc_provider_arn" {
  type        = string
  description = "OIDCプロバイダーのARN"
}

variable "allowed_github_repositories" {
  type        = list(string)
  description = "許可するリポジトリの一覧"
}
data.tf
# リポジトリの許可設定等を定義したカスタム信頼ポリシー
data "aws_iam_policy_document" "assume_role" {
  # Github Actionsからの信頼ポリシー
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRoleWithWebIdentity"]
    # フェデレーション認証(外部の認証プロバイダー)を使用
    principals {
      type        = "Federated"
      identifiers = [var.iam_oidc_provider_arn]
    }
    # aud を見て aws 向けに発行されたトークンであることを確認
    condition {
      test     = "StringEquals"
      variable = "token.actions.githubusercontent.com:aud"
      values   = ["sts.amazonaws.com"]
    }
    # sub を見て許可されているリポジトリであることを確認
    condition {
      test     = "StringEquals"
      variable = "token.actions.githubusercontent.com:sub"
      values   = var.allowed_github_repositories
    }
  }
}
main.tf
# カスタム信頼ポリシーを設定してロールを作成
# MEMO: カスタム信頼ポリシーはロールに直接定義されるため作成されない
resource "aws_iam_role" "main" {
  name               = var.name
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

data.tf が肝です。
IAMロール の作成時に誰がそのロールにアクセス可能か (信頼ポリシー) を設定します。
ここでは、Github Actions の OIDC から IAMロール への Assume Role を許可するように設定しています。
また condition ブロックでより厳密に条件を指定しています。

ここで作成したロールのARNはCICD上で参照するのでどこかに保存しておきましょう。
-> 手順5 で対応します。

4. SSM への最小権限ポリシーを作成してIAMロールにアタッチ

Terraform での OIDC IAMロール モジュール例

OIDC からSSMするための最小権限ポリシー のモジュール定義は以下

抜粋

variables.tf
variable "name" {
  type        = string
  description = "ポリシーの名前"
}
data.tf
# SSMへの最小権限ポリシー
data "aws_iam_policy_document" "main" {
  statement {
    effect = "Allow"
    actions = [
      "ssm:SendCommand",
      "ssm:GetCommandInvocation"
    ]
    resources = ["*"]
  }
}
main.tf
resource "aws_iam_policy" "main" {
  name   = var.name
  policy = data.aws_iam_policy_document.main.json
}

ここでの肝も data.tf です。
aws ssm send-command の実行には ssm:SendCommand
aws ssm get-command-invocation には ssm:GetCommandInvocation の権限がそれぞれ必要になります。

5. 作成したIAMロールのARNや対象のインスタンスのID等をCICD上から参照できるように Environments を作成する

Terraform での Github Environments モジュール例

モジュール定義は以下

抜粋

variables.tf
variable "name" {
  description = "名前"
  type        = string
}

variable "secrets" {
  description = "作成するシークレットのマップ"
  type        = map(string)
}

variable "variables" {
  description = "作成するの変数のマップ"
  type        = map(string)
}
data.tf
data "github_repository" "main" {
  full_name = "kazeusagi/terraform-ssm"
}
main.tf
# Environmentの作成
resource "github_repository_environment" "main" {
  repository  = data.github_repository.main.name
  environment = var.name
}

# Secretの作成
resource "github_actions_environment_secret" "main" {
  for_each        = var.secrets
  repository      = data.github_repository.main.name
  environment     = github_repository_environment.main.environment
  secret_name     = each.key
  plaintext_value = each.value
}

# Variableの作成
resource "github_actions_environment_variable" "main" {
  for_each      = var.variables
  repository    = data.github_repository.main.name
  environment   = github_repository_environment.main.environment
  variable_name = each.key
  value         = each.value
}

CICD上からリモートコマンドを実行するには以下の変数が必要になります。

変数名 内容 Secret
AWS_REGION ログインするリージョン どっちでも
ASSUME_ROLE_ARN ログインして委任するIAMロールのARN
INSTANCE_ID リモートコマンド実行先のインスタンスID どっちでも

6. ワークフロー定義を作成

ワークフロー定義ファイルの例
.github/workflows/ssm.yml (再利用可能なワークフロー)
# 再利用可能なワークフロー: SSM
name: SSM

on:
  workflow_call:
    inputs:
      environment:
        type: string
        required: true
        description: 対象の環境(dev, stg, prod)

env:
  AWS_REGION: ${{ vars.AWS_REGION }}
  ASSUME_ROLE_ARN: ${{ secrets.ASSUME_ROLE_ARN }}
  INSTANCE_ID: ${{ secrets.INSTANCE_ID }}

jobs:
  plan:
    name: SSM
    runs-on: ubuntu-latest
    environment: ${{ inputs.environment }}
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup AWS
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-region: ${{ env.AWS_REGION }}
          role-to-assume: ${{ env.ASSUME_ROLE_ARN }}

      - name: SSM Send Command
        id: send_command
        run: |
          COMMAND_ID=$(aws ssm send-command \
            --instance-ids ${{ env.INSTANCE_ID }} \
            --document-name "AWS-RunShellScript" \
            --parameters 'commands=[
              "echo Hello",
              "echo From",
              "echo Github Actions !"
            ]' \
            --output text \
            --query 'Command.CommandId'
          )
          echo "command_id=$COMMAND_ID" >> $GITHUB_OUTPUT

      - name: SSM Wait Command
        run: |
          aws ssm wait command-executed \
            --instance-id ${{ env.INSTANCE_ID }} \
            --command-id ${{ steps.send_command.outputs.command_id }}

      - name: SSM Get Command Result
        run: |
          aws ssm get-command-invocation \
            --instance-id ${{ env.INSTANCE_ID }} \
            --command-id ${{ steps.send_command.outputs.command_id }} \
            --output json \
            --query '{
              status: Status,
              output: StandardOutputContent,
              error: StandardErrorContent
            }'
.github/workflows/ssm-dev.yml (呼び出し側)
name: SSM | Dev

on:
  push:
    branches:
      - develop

jobs:
  plan:
    name: SSM workflow call
    uses: ./.github/workflows/ssm.yml
    permissions:
      id-token: write
      contents: read
    with:
      environment: dev
    secrets: inherit

AWS認証の際に role-to-assume に委任したいロールのARNを設定することで、
Github Actions 上からそのロールとして実際にAWSのリソースにアクセスできます。
そのため、キー情報等を一切含めることなくリモートコマンドを実行可能です🎉

成功すると以下のように結果が出力されます。
出力の例

最後に

ここまで読んでいただきありがとうございます。
SSM はとてもいい機能なので皆さんに知ってもらいたいという気持ちからつい熱が入ってしまい果てしなく長くなってしまいました。。
また、大分めちゃくちゃな書き方をしてしまったので、不明点やご指摘点等ありましたらコメントいただけたらと思います!

HCプロデューステックブログ

Discussion