Systems Managerのスクリプト実行でgithubとS3をサポートしました
ウィスキー、シガー、パイプをこよなく愛する、と書き出すと読まれない可能性もあるようですが気にしない事にした大栗です。
EC2の管理を行えるSystems ManagerでgithubやS3に配置したファイルをローカルにダウンロードして実行することが可能になりました。
AWS-RunRemoteScript ドキュメント
AWS-RunRemoteScriptドキュメントは、github(プライベートリポジトリを含む)とS3にあるファイルをダウンロードして、実行を行うSSMドキュメントです。
ドキュメントの詳細
AWS-RunRemoteScript
の概要をCLIで確認します。CreatedDate
が 1508980336.016 なので 2017-10-26 01:12:16 UTCに作成されています。
{ "Document": { "Status": "Active", "Hash": "80c872204542b86fd0f8e399413eaae27a4c371a15332228f07afd71188cbbb6", "Name": "AWS-RunRemoteScript", "Parameters": [ { "Type": "String", "Name": "sourceType", "Description": "(Required) Specify the source type." }, { "DefaultValue": "{}", "Type": "StringMap", "Name": "sourceInfo", "Description": "(Required) Specify the information required to access the resource from the source. If source type is GitHub, then you can specify any of the following: 'owner', 'repository', 'path', 'getOptions', 'tokenInfo'. If source type is S3, then you can specify 'path'." }, { "DefaultValue": "", "Type": "String", "Name": "commandLine", "Description": "(Required) Specify the command line to be executed. The following formats of commands can be run: 'pythonMainFile.py argument1 argument2', 'ansible-playbook -i \"localhost,\" -c local example.yml'" }, { "DefaultValue": "", "Type": "String", "Name": "workingDirectory", "Description": "(Optional) The path where the content will be downloaded and executed from on your instance." }, { "DefaultValue": "3600", "Type": "String", "Name": "executionTimeout", "Description": "(Optional) The time in seconds for a command to complete before it is considered to have failed. Default is 3600 (1 hour). Maximum is 28800 (8 hours)." } ], "Tags": [], "DocumentType": "Command", "PlatformTypes": [ "Windows", "Linux" ], "DocumentVersion": "1", "HashType": "Sha256", "CreatedDate": 1508980336.016, "Owner": "Amazon", "SchemaVersion": "2.2", "DefaultVersion": "1", "LatestVersion": "1", "Description": "Execute scripts stored in a remote location. The following remote locations are currently supported: GitHub (public and private) and Amazon S3 (S3). The following script types are currently supported: #! support on Linux and file associations on Windows." } }
次にドキュメントの中身を見ていきましょう。mainSteps
を見るとaws:downloadContent
プラグインでファイルをダウンロードして、Windowsの場合に'aws:runPowerShellScript'でPowerShellを実行、Linuxの場合にaws:runShellScript
でスクリプトを実行するという複合ドキュメントになっていることが分かります。
{ "schemaVersion": "2.2", "description": "Execute scripts stored in a remote location. The following remote locations are currently supported: GitHub (public and private) and Amazon S3 (S3). The following script types are currently supported: #! support on Linux and file associations on Windows.", "parameters": { "sourceType": { "description": "(Required) Specify the source type.", "type": "String", "allowedValues": [ "GitHub", "S3" ] }, "sourceInfo": { "description": "(Required) Specify the information required to access the resource from the source. If source type is GitHub, then you can specify any of the following: 'owner', 'repository', 'path', 'getOptions', 'tokenInfo'. If source type is S3, then you can specify 'path'.", "type": "StringMap", "displayType": "textarea", "default": {} }, "commandLine": { "description": "(Required) Specify the command line to be executed. The following formats of commands can be run: 'pythonMainFile.py argument1 argument2', 'ansible-playbook -i \"localhost,\" -c local example.yml'", "type": "String", "default": "" }, "workingDirectory": { "type": "String", "default": "", "description": "(Optional) The path where the content will be downloaded and executed from on your instance.", "maxChars": 4096 }, "executionTimeout": { "description": "(Optional) The time in seconds for a command to complete before it is considered to have failed. Default is 3600 (1 hour). Maximum is 28800 (8 hours).", "type": "String", "default": "3600", "allowedPattern": "([1-9][0-9]{0,3})|(1[0-9]{1,4})|(2[0-7][0-9]{1,3})|(28[0-7][0-9]{1,2})|(28800)" } }, "mainSteps": [ { "action": "aws:downloadContent", "name": "downloadContent", "inputs": { "sourceType": "{{ sourceType }}", "sourceInfo": "{{ sourceInfo }}", "destinationPath": "{{ workingDirectory }}" } }, { "precondition": { "StringEquals": [ "platformType", "Windows" ] }, "action": "aws:runPowerShellScript", "name": "runPowerShellScript", "inputs": { "runCommand": [ "", "$directory = Convert-Path .", "$env:PATH += \";$directory\"", " {{ commandLine }}", "if ($?) {", " exit $LASTEXITCODE", "} else {", " exit 255", "}", "" ], "workingDirectory": "{{ workingDirectory }}", "timeoutSeconds": "{{ executionTimeout }}" } }, { "precondition": { "StringEquals": [ "platformType", "Linux" ] }, "action": "aws:runShellScript", "name": "runShellScript", "inputs": { "runCommand": [ "", "directory=$(pwd)", "export PATH=$PATH:$directory", " {{ commandLine }} ", "" ], "workingDirectory": "{{ workingDirectory }}", "timeoutSeconds": "{{ executionTimeout }}" } } ] }
実行時のパラメータ
スクリプトのダウンロード元によって、実行時のパラメータが異なります。
パラメータ | 必須/任意 | 内容 | 備考 |
---|---|---|---|
sourceType | 必須 | "GitHub"または"S3" | |
sourceInfo | 必須 | ダウンロード元情報 | 詳細は後述 |
commandLine | 必須 | スクリプト名 | 実行するスクリプト名 |
workingDirectory | 任意 | 実行時ディレクトリ | スクリプトを実行する時のディレクトリ |
executionTimeout | 任意 | デフォルトは36oo秒。1〜28800。 | 実行タイムアウトの秒数 |
sourceInfo
はaws:downloadContent
プラグインで使用するパラメータなので、ドキュメントを確認します。
項目 | S3 | github (Public) |
github (Private) |
備考 |
---|---|---|---|---|
owner | 不要 | 必須 | 必須 | githubのオーナー。 |
repository | 不要 | 必須 | 必須 | githubのリポジトリ名。 |
path | 必須 | 必須 | 必須 | ダウンロードするファイルのパス。 |
getOptions | 不要 | 任意 | 任意 | ダウンロード元のブランチやコミットIDを指定します。 |
tokenInfo | 不要 | 任意 | 必須 | githubのアクセストークンを指定します。 |
例として、以下のようになります。
{ "owner": "maroon1st", "repository": "blog-test-20171030-private", "path": "test_guthub_private.sh", "tokenInfo": "{{ssm-secure:github-token}}" }
試してみる
事前準備
ここではSSM Agentがデフォルトで入っているAmazon Linux AMI 2017.09.0を対象としています。設定内容としては、以下の点に注意して下さい。
- インターネットへのアクセス(SSMのエンドポイントへのアクセス)が可能
- IAM Roleで
AmazonEC2RoleforSSM
ポリシーとAWSKeyManagementServicePowerUser
ポリシーを設定する
ただし、SSM Agentのデフォルトバージョンが2.1.4.0と少し古いので最新にします。EC2のコンソールでコマンドの実行
メニューからコマンドを実行
をクリックします。
ドキュメントでAWS-UpdateSSMAgent
を選択して、対象インスタンスを選びRun
をクリックします。
少し経つとコマンドが成功します。
出力でログを見るとバージョンが2.1.4.0から最新の2.2.64.0にアップデートしたことが分かります。
S3のスクリプト
サンプルとして、こんな感じのスクリプトをS3に配置します。
#!/bin/bash date echo RunScript From S3 New Version ! curl -s -w '\n' http://169.254.169.254/latest/meta-data/local-hostname curl -s -w '\n' http://169.254.169.254/latest/meta-data/instance-id curl -s -w '\n' http://169.254.169.254/latest/meta-data/placement/availability-zone
S3のリンクを控えておきます。
EC2のコンソールでコマンドの実行
メニューから、またコマンドを実行
をクリックして、ドキュメントでAWS-RunRemoteScript
を選択して、対象インスタンスを選びます。
Source Type
をS3にして、Source Info
でpathに先程のS3のリンクURLを設定します。Command Line
ではスクリプト名を指定します。必要な項目を入力したらRun
をクリックします。
このように成功します。downloadContent
、runPowerShellScript
、runShellScript
の3個のプラグインが動いていることが分かります。
出力を表示させると以下のようになり、downloadContent
でファイルをダウンロードして、runPowerShellScript
をスキップし、runShellScript
でスクリプトが実行されていることが分かります。
github(Public)のスクリプト
サンプルとして、githubにmaroon1st/blog-test-20171030というパブリックリポジトリを作成しました。
#!/bin/bash date echo RunScript From github ! curl -s -w '\n' http://169.254.169.254/latest/meta-data/local-hostname curl -s -w '\n' http://169.254.169.254/latest/meta-data/instance-id curl -s -w '\n' http://169.254.169.254/latest/meta-data/placement/availability-zone
このリポジトリを使って試します。
今までと同様にEC2のコンソールでコマンドの実行
メニューから、またコマンドを実行
をクリックして、ドキュメントでAWS-RunRemoteScript
を選択して、対象インスタンスを選びます。
Source Type
をgithubにします。Source Info
は以下のように入力します。
{ "owner": "maroon1st", "repository": "blog-test-20171030", "path": "test_guthub.sh" }
Command Line
ではスクリプト名を指定します。必要な項目を入力したらRun
をクリックします。
普通にスクリプトが実行されます。
github(Private)のスクリプト
サンプルとして、githubにmaroon1st/blog-test-20171030-privateというプライベートリポジトリを作成しました。
実行するスクリプトはこんな感じです。
#!/bin/bash date echo RunScript From github private ! curl -s -w '\n' http://169.254.169.254/latest/meta-data/local-hostname curl -s -w '\n' http://169.254.169.254/latest/meta-data/instance-id curl -s -w '\n' http://169.254.169.254/latest/meta-data/placement/availability-zone
githubではSettings -> Developer settingsからaccess tokenを作成しておきます。Rum Commandでgithubのaccess tokenを指定する必要がありますが、access tokenは機密情報です。そのためEC2 Systems Managerパラメータストアで暗号化して保存します。
EC2コンソールのパラメータストア -> パラメータの作成 をクリックします。
タイプ
で安全な文字列
(SecureString)を選択します。そしてKMS キー ID
ではデフォルト以外のキーを選択します。デフォルトキーを選択するとKMSへのアクセス権限がなくても復号化できてしまうため意味がありません。access tokenを値
に入力してパラメータの作成
をクリックします。なお、使用するKMS キーで設定しているIAM Roleをキーユーザーに設定しておくことを忘れないでください。
これでアクセスキーの登録が完了しました。
ここからは先程と同様にコマンドを実行
をクリックして、ドキュメントでAWS-RunRemoteScript
を選択して、対象インスタンスを選びます。
Source Info
以外はパブリックリポジトリと同様に入力します。Source Info
は以下のように入力します。tokenInfoにaccess tokenを設定するのですが、パラメータストアで安全な文字列にしているため{{ssm-secure:パラメータ名}}となる形式で設定します。ここでは{{ssm-secure:github-token}}
となります。
{ "owner": "maroon1st", "repository": "blog-test-20171030-private", "path": "test_guthub_private.sh", "tokenInfo": "{{ssm-secure:github-token}}" }
実行結果を見ると、このようにスクリプトが実行されています。
さいごに
今回githubやS3に保存されているファイルを使って実行できるようになりました。
Amazon Linux 2017.09ではSSM Agentがデフォルトで入っているため素の状態からでもOSにログインせずスクリプトの実行までできるようになりました。githubのプライベートリポジトリのファイルでも使用可能であるため、内部向けスクリプトでも使用できます。
この機能によりOSの設定の自由度が上がり、OSから上のメンテナンスもやりやすくなったのではないでしょうか。