PSScriptAnalyzer導入とCI化の知識マップ(知識グラフ)
この記事は、PowerShell公式の静的解析モジュールPSScriptAnalyzerを社内スクリプトへ導入する実務手順を扱う。PSScriptAnalyzerSettings.psd1という1つの設定ファイルをリポジトリに置くことで、VS Codeの拡張機能とGitHub ActionsのCIが同じ基準で解析するように整える。重大度はルールごとに決まっており、平文パスワード検出などのルールはError指定だけでは素通りするため、資格情報系のルールは名前を明示してCIの失敗条件に加えるべきだとしている。既存資産には、まずErrorをゼロにし、次に変更ファイルだけを厳格に解析する段階導入を勧め、テストを書かずに初日から効果が出るPSScriptAnalyzerをPesterより先に導入する順序を推奨している。
PSScriptAnalyzer
PowerShellスクリプトを静的解析するMicrosoft公式のツール。
GitHub Actions
GitHubが提供する、リポジトリのイベントをトリガーにワークフローを実行するCI/CDサービス。
Invoke-ScriptAnalyzer
PSScriptAnalyzerのルールに基づいてスクリプトやモジュールを解析するコマンドレット。
SuppressMessageAttribute
特定の関数やスクリプトに対してPSScriptAnalyzerの指摘を個別に抑止する属性。Justification引数に理由を書くことが求められる。
PSScriptAnalyzerSettings.psd1
Severity・IncludeRules・ExcludeRules・Rulesなどを記述し、開発者とCIが同じ基準で解析するための設定ファイル。
VS CodeのPowerShell拡張機能
Visual Studio Code上でPowerShellの編集・デバッグを支援する拡張機能。PSScriptAnalyzerを内蔵し、編集中にその場で警告を表示する。
PSAvoidUsingPlainTextForPassword
パラメーターで平文パスワードを受け取っていないかを検出するPSScriptAnalyzerのルール。重大度はWarning。
PSUseDeclaredVarsMoreThanAssignments
代入されたが一度も参照されていない変数を検出するPSScriptAnalyzerのルール。変数名のタイプミスを実バグとして拾える。
Invoke-Formatter
設定ファイルのルールに基づいてPowerShellスクリプトのテキストを整形するコマンドレット。
Pester
PowerShellスクリプトの自動テストを書くためのテストフレームワーク。
PSScriptAnalyzerの段階導入
重大度Errorをゼロにする第1段階、変更ファイルのみを厳格に解析する第2段階、除外ルールを徐々に外す第3段階という順で既存資産へ静的解析を導入していく進め方。
変更ファイルのみを対象にした差分解析
ベースブランチとの差分を取り、変更されたps1/psm1/psd1ファイルだけをPSScriptAnalyzerの解析対象にすることで、既存の負債を残したまま新しい問題の増加だけを止める手法。
第2段階
actions/checkoutのfetch-depth: 0
GitHub Actionsのactions/checkoutで履歴全体を取得する指定。差分チェックでベースブランチとの比較を行うために必要になる。
GITHUB_BASE_REF
pull_requestイベントでPRのターゲットブランチ名が入るGitHub Actionsの既定環境変数。push時は空になる。
PSAvoidUsingConvertToSecureStringWithPlainText
平文の文字列からSecureStringを生成していないかを検出するPSScriptAnalyzerのルール。重大度はError。
PSAvoidUsingUsernameAndPasswordParams
ユーザー名とパスワードを別々のパラメーターで受け取っていないかを検出するPSScriptAnalyzerのルール。重大度はError。
重大度に関係なく落とすルールの明示リスト
重大度がWarningでも資格情報関連など常に失敗条件へ含めたいPSScriptAnalyzerのルール名を、CIの判定コードに明示的に列挙したもの。
PSScriptAnalyzerはInvoke-ScriptAnalyzerコマンドレットでスクリプトやモジュールを解析する
PSScriptAnalyzerはSuppressMessageAttributeによる指摘の個別抑止を提供する
PSScriptAnalyzerの解析対象ルールと重大度はPSScriptAnalyzerSettings.psd1で構成できる
VS CodeのPowerShell拡張機能はPSScriptAnalyzerを内蔵し、編集中にその場で警告を表示する
VS Code拡張機能の設定powershell.scriptAnalysis.settingsPathの既定値がPSScriptAnalyzerSettings.psd1のため、この名前でリポジトリ直下に置くと編集中の警告とCIの判定基準がそろう
本記事が組み立てるPSScriptAnalyzerのCIワークフローでは、GitHub Actionsのワークフローはステップの中でInvoke-ScriptAnalyzerを呼び出して解析を実行する
PSScriptAnalyzerは平文パスワード検出ルールPSAvoidUsingPlainTextForPasswordを組み込みルールとして持つ
PSScriptAnalyzerは未使用変数検出ルールPSUseDeclaredVarsMoreThanAssignmentsを持ち、変数名のタイプミスという実バグを拾える
Invoke-ScriptAnalyzerの-Fixによる自動修正のうち、整形の処理はInvoke-Formatterが担う
テストコードを書かずに初日から効果が出るPSScriptAnalyzerを、テストを書く作業が必要なPesterより先に導入するのが実務的だとされる
段階導入はPSScriptAnalyzerによる解析の実行を前提とする
段階導入の第2段階は、変更ファイルのみを厳格に解析する差分チェックを前提とする
GitHub Actionsで差分解析を行う場合、ベースブランチとの比較に履歴が必要なため、actions/checkoutでfetch-depth: 0を指定するか、ベースブランチを明示的にfetchすることを前提とする。GitHub Actions以外の実行環境や手元での差分解析には当てはまらない
GitHub Actionsで差分解析を行う場合、比較先をmainに固定せずPRのターゲットブランチを使うため、GITHUB_BASE_REFの参照を前提とする。GitHub Actions以外の実行環境ではこの変数は存在しない
本記事が想定するCI環境では、変更ファイルのみの差分解析はGitHub Actionsのワークフローの中で実行される
差分解析は取得した変更ファイルを1つずつInvoke-ScriptAnalyzerに渡して結果を集約する
PSScriptAnalyzerは平文からSecureStringを生成する行為を検出するPSAvoidUsingConvertToSecureStringWithPlainTextを持つ
PSScriptAnalyzerはユーザー名とパスワードを別パラメーターで受け取る設計を検出するPSAvoidUsingUsernameAndPasswordParamsを持つ
重大度に関係なく落とすルール名の明示リストには、重大度Warningでも見逃せないPSAvoidUsingPlainTextForPasswordが含まれる
重大度に関係なく落とすルール名の明示リストには、PSAvoidUsingConvertToSecureStringWithPlainTextが含まれる
重大度に関係なく落とすルール名の明示リストには、PSAvoidUsingUsernameAndPasswordParamsが含まれる
本記事が組み立てるCIワークフローでは、失敗条件は重大度Errorに加え、この明示リストのルールに一致した指摘も含める