AWS Systems Managerインベントリはどのアプリケーション情報を収集しているのか調べてみた

しばたです。
先日弊社吉井によりAWS Systems Managerインベントリの機能を使い「管理している EC2 インスタンスにインストールされているソフトウェアとそのバージョンを一覧表示する」記事が公開されました。
Systems ManagerインベントリではSSM Agentの機能で対象となるEC2インスタンスにインストールされているアプリケーション情報を収集しています。
ここで単純に「インストールされているアプリケーション」と記載しましたが、実際には各OSにおけるアプリケーションのインストール方法およびその検出方法は千差万別です。
本記事ではSystems ManagerインベントリおよびSSM Agentがどの様な「アプリケーション」を検出対象としているか調べてみました。
ドキュメントの記載
まずはドキュメントを当たってみます。
ユーザーガイドを調べてみると、
インベントリを設定して、次のメタデータのタイプを収集できます。
* アプリケーション : アプリケーション名、発行元、バージョンなど。
[ ・・・(中略)・・・ { "typeName" : "AWS:Application", "version": "1.1", "attributes":[ { "name": "Name", "dataType": "STRING"}, { "name": "ApplicationType", "dataType": "STRING"}, { "name": "Publisher", "dataType": "STRING"}, { "name": "Version", "dataType": "STRING"}, { "name": "InstalledTime", "dataType": "STRING"}, { "name": "Architecture", "dataType": "STRING"}, { "name": "URL", "dataType": "STRING"}, { "name": "Summary", "dataType": "STRING"}, { "name": "PackageId", "dataType": "STRING"}, { "name": "Release", "dataType": "STRING"}, { "name": "Epoch", "dataType": "STRING"} ] }, ・・・(後略)・・・ }
とあり、「アプリケーション」で収集される情報はわかるものの、”何を” 収集対象にしているか記載されているものを見つけることはできませんでした。
(もし記載されているドキュメントがある様でしたらコメントをお願いします...)
SSM Agentのソースを読む
皆さんもご存じかもしれませんがSSM AgentはGitHubでソースが公開されています。
「ドキュメントが無ければソースを読めば良いじゃない」ということでソースを読んでみました。
本記事では現在の最新バージョンであるVer.2.3.539.0を対象としています。
aws:softwareInventory
SSM Agentは各機能をプラグイン形式で保持しており、Systems Managerインベントリに関わる機能はaws:softwareInventory
プラグインが担っています。
そしてこのソースの配下にあるgatherers/application
がアプリケーション情報を収集する機能となっています。
Windowsにおけるアプリケーション情報
Windowsでのアプリケーション情報収集の実装はdataProvider_windows.go
に記述されています。
ソース中のコメントに
// dataProvider_windows.go 114行目付近より抜粋 /* Note: We get list of installed apps by using powershell to query registry from 2 locations: Path-1 => HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* Path-2 => HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* Path-2 is used to get a list of 32 bit apps running on a 64 bit OS (when 64bit agent is running on 64bit OS) For all other scenarios we use Path-1 to get the list of installed apps. Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724072(v=vs.85).aspx ・・・(後略)・・・ */
とある様に、レジストリ、
HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\
HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\
配下にある情報を読んでアプリケーション情報を取得しています。
このレジストリキーはMSIインストーラーなどによってインストールされた場合に追加される領域で「プログラムと機能(プログラムの追加と削除)」で表示される情報の大元となっています。
Windowsの詳しい方あれば"ごく普通"だと思っていただけるでしょう。
Linuxにおけるアプリケーション情報
Linuxでのアプリケーション情報収集の実装はdataProvider_unix.go
に記述されています。
こちらの実装ではアプリケーション情報をrpm
またはdpkg(dpkg-query)
から取得しています。
最初にdpkg-query
でアプリケーション情報の取得を試み、dpkg
がインストールされていないなどのエラーとなった場合rpm
を使う実装となっています。
コマンド的にはそれぞれ、
dpkg-query -W
rpm -qa
を内部で発行しています。
ソースとしては以下のあたりの記述となります。
// dataProvider_windows.go 75行目付近より抜粋 // collectPlatformDependentApplicationData collects all application data from the system using rpm or dpkg query. func collectPlatformDependentApplicationData(context context.T) (appData []model.ApplicationData) { var err error log := context.Log() args := []string{dpkgArgsToGetAllApplications, dpkgQueryFormat} cmd := dpkgCmd // try dpkg first, if any error occurs, use rpm if appData, err = getApplicationData(context, cmd, args); err != nil { log.Info("Getting applications information using dpkg failed, trying rpm now") cmd = rpmCmd args = []string{rpmCmdArgToGetAllApplications, rpmQueryFormat, rpmQueryFormatArgs} if appData, err = getApplicationData(context, cmd, args); err != nil { log.Errorf("Unable to detect package manager - hence no inventory data for %v", GathererName) } } return }
確認してみた
かなり雑な方法ですがWindows Server 2019、Amazon Linux 2のEC2インスタンスをそれぞれ1台ずつ用意し、PowerShell Coreのアプリケーションを各インスタンスに以下の様にインストールしてみます。
- Stableバージョン(Ver.6.2.0)はMSIインストーラーおよびYum(rpm)からインストール
- Previewバージョン(Ver.6.2.0-rc1)はzip/tarファイルをダウンロード、解凍展開してインストール
インストーラーを使わないPreviewバージョンの方はSystems Managerインベントリに乗らないはずです。 Systems Managerの各種設定は最初に紹介した記事の通り行います。
Windows Server 2019でのセットアップ
ざっくりこんな感じです。本筋ではないので細かい説明は端折ります。
# StableバージョンはMSIインストーラーでインストール(自作スクリプト) Set-ExecutionPolicy Bypass -Scope Process -Force; [Net.ServicePointManager]::SecurityProtocol=[Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/stknohg/PSCoreUpdate/master/FirstTimeInstaller/Install-LatestPowerShell.ps1')) # PreviewバージョンはZipでインストール (※Preview版もMSIでインストールできます) cd ~ Invoke-WebRequest -Uri https://github.com/PowerShell/PowerShell/releases/download/v6.2.0-rc.1/PowerShell-6.2.0-rc.1-win-x64.zip -OutFile .\PowerShell-6.2.0-rc.1-win-x64.zip Expand-Archive -LiteralPath .\PowerShell-6.2.0-rc.1-win-x64.zip -DestinationPath 'C:\Program Files\PowerShell\6-preview'
Amazon Linux 2でのセットアップ
ざっくりこんな感じです。こちらも本筋ではないので細かい説明は端折ります。
# StableバージョンはYum(rpm)でインストール curl https://packages.microsoft.com/config/rhel/7/prod.repo | sudo tee /etc/yum.repos.d/microsoft.repo sudo yum install -y powershell # PreviewバージョンはZipでインストール (※Preview版もYumからインストールできます) cd ~ curl -LO https://github.com/PowerShell/PowerShell/releases/download/v6.2.0-rc.1/powershell-6.2.0-rc.1-linux-x64.tar.gz sodu mkdir /opt/microsoft/powershell/6-preview cd /opt/microsoft/powershell/6-preview sudo tar -xzvf ~/powershell-6.2.0-rc.1-linux-x64.tar.gz sudo chmod 755 ./pwsh sudo ln -s /opt/microsoft/powershell/6-preview/pwsh /usr/bin/pwsh-preview
結果の確認
詳細ビューからざっくりpowershsll
の名を持つアプリケーションを検索してみます。
# クエリが雑なのは許してほしい... select name, packageid, version, resourceid from aws_application where lower(name) like 'powershell%' order by packageid
結果はこの通りStableバージョンのPowerShellのみ収集されており、Preview版は収集されませんでした。
余談
ちなみに、Previewバージョンをインストーラーからインストールすると下図の様にちゃんと収集対象となります。
(Previewバージョンをインストーラーからインストールした場合)
最後に
ざっとこんな感じです。
結果としてSystems Managerインベントリは、
- Windowsでは「
プログラムと機能
」に表示される情報を収集する - Linuxでは
dpkg-query
またはrpm
コマンドからアプリケーション情報を収集する
ことがわかりました。
具体的に取得できる情報を知ることでSystems Managerインベントリをより有効に活用できると思います。