JEA ロール機能

JEA エンドポイントを作成するときに、JEA セッションでユーザーに許可する操作を説明するロール機能を 1 つ以上定義する必要があります。 ロール機能は、.psrc 拡張子を持つ PowerShell データ ファイルです。このファイルには、接続ユーザーが利用できるすべてのコマンドレット、関数、プロバイダー、外部プログラムが列挙されています。

許可するコマンドを決定する

ロール機能ファイルを作成するときの最初の手順は、ユーザーが何にアクセスする必要があるかを検討することです。 要件の収集プロセスには時間がかかることがありますが、重要なプロセスです。 ユーザーに使用を許可するコマンドや関数があまりにも少ないと、仕事ができなくなります。 ユーザーに使用を許可するコマンドや関数があまりにも多すぎると、本来意図した以上の操作が可能になることがあり、セキュリティ姿勢を弱めることになります。

このプロセスをどのように進めるかは、組織と目標によって決まります。 次のヒントが役に立つことがあります。

  1. 仕事を行うためにユーザーが使用しているコマンドを確認します。 たとえば、IT スタッフに調査を行ったり、自動化スクリプトを調べたり、PowerShell セッションのトランスクリプトとログを分析したりします。
  2. 可能な限り、コマンド ライン ツールで行っていたことを PowerShell の同じ操作に更新し、最良の監査と JEA カスタマイズを実現します。 外部プログラムは、JEA のネイティブ PowerShell コマンドレットまたは関数ほど細かに制約することはできません。
  3. コマンドレットの範囲を制限し、特定のパラメーターまたはパラメーター値のみを許可します。 これは特に、ユーザーがシステムの一部のみを管理する場合に重要です。
  4. カスタム関数を作成し、複雑なコマンドや JEA では制約が難しいコマンドの代わりに使用します。 複雑なコマンドをラップするか、追加の検証ロジックを適用する単純な関数を利用すれば、管理者やエンドユーザーにとって制御機能がさらに使いやすくなります。
  5. ユーザーや自動化サービスに許可するコマンドの範囲をテストし、必要に応じて調整します。

危険性を含むコマンドの例

JEA エンドポイントでユーザーのアクセス許可の昇格が許可されないように、コマンドを慎重に選択することが重要です。

重要

JEA セッションでユーザーの successCommands に必要な重要な情報は、多くの場合、昇格された特権で実行されます。

次の一覧に、制約のない状態で許可される場合に悪意を持って使用されるおそれがあるコマンドの例を示します。 このリストですべてを網羅しているわけではありません。最初に注意するべきものとして提示しているにすぎません。

  • リスク: JEA をバイパスするための管理者権限を接続ユーザーに付与する

    例:

    Add-LocalGroupMember -Member 'CONTOSO\jdoe' -Group 'Administrators'
    

    関連するコマンド:

    • Add-ADGroupMember
    • Add-LocalGroupMember
    • net.exe
    • dsadd.exe
  • リスク: マルウェア、悪用、カスタム スクリプトなどの任意のコードを実行して保護をバイパスする

    例:

    Start-Process -FilePath '\\san\share\malware.exe'
    

    関連するコマンド:

    • Start-Process
    • New-Service
    • Invoke-Item
    • Invoke-WmiMethod
    • Invoke-CimMethod
    • Invoke-Expression
    • Invoke-Command
    • New-ScheduledTask
    • Register-ScheduledJob

ロール機能ファイルを作成する

New-PSRoleCapabilityFile コマンドレットで新しい PowerShell ロール機能ファイルを作成できます。

New-PSRoleCapabilityFile -Path .\MyFirstJEARole.psrc

ロールに必要なコマンドのみを許可するように、作成したロール機能ファイルを編集する必要があります。 PowerShell ヘルプ ドキュメントには、ファイルの構成例が含まれています。

PowerShell のコマンドレットと関数を許可する

ユーザーが PowerShell コマンドレットまたは関数を実行することを承認するには、コマンドレットまたは関数名を VisibleCmdlets フィールドまたは VisibleFunctions フィールドに追加します。 コマンドがコマンドレットであるか、関数であるかわからない場合、Get-Command <name> を実行し、出力の CommandType プロパティを確認してください。

VisibleCmdlets = @('Restart-Computer', 'Get-NetIPAddress')

特定のコマンドレットまたは関数の範囲が必要以上に広いことがあります。 たとえば、DNS 管理者には、DNS サービスを再起動するためのアクセスのみが必要な場合があります。 マルチテナント環境では、テナントにセルフサービス管理ツールがあります。 テナントが管理できるリソースは、そのテナントのリソースに限定する必要があります。 そのような場合、コマンドレットまたは関数から公開するパラメーターを制限できます。

VisibleCmdlets = @{
    Name       = 'Restart-Computer'
    Parameters = @{ Name = 'Name' }
}

さらに進んだシナリオでは、ユーザーがこれらのパラメーターに使用できる値も制限する必要があります。 ロール機能では、許可する入力を決定する一連の値または正規表現パターンを定義できます。

VisibleCmdlets = @(
    @{
        Name       = 'Restart-Service'
        Parameters = @{ Name = 'Name'; ValidateSet = @('Dns', 'Spooler') }
    }
    @{
        Name       = 'Start-Website'
        Parameters = @{ Name = 'Name'; ValidatePattern = 'HR_*' }
    }
)

Note

利用できるパラメーターを制限した場合でも、一般的な PowerShell パラメーターは常に許可されます。 それらを Prameters フィールドに明示的にリストしないでください。

次の一覧では、表示されるコマンドレットまたは関数をカスタマイズできるさまざまな方法について説明します。 VisibleCmdlets フィールドで下のあらゆる要素を組み合わせることができます。

  • ユース ケース: パラメーターで制限を設定せずに、ユーザーが My-Func を実行することを許可します。

    @{ Name = 'My-Func' }
    
  • ユース ケース: パラメーターで制限を設定せずに、ユーザーが MyModule から My-Func を実行することを許可します。

    @{ Name = 'MyModule\My-Func' }
    
  • ユース ケース: ユーザーが動詞 My で始まる任意のコマンドレットまたは関数を実行することを許可します。

    @{ Name = 'My-*' }
    
  • ユース ケース: ユーザーが名詞 Func を含む任意のコマンドレットまたは関数を実行することを許可します。

    @{ Name = '*-Func' }
    
  • ユース ケース: パラメーター Param1Param2 を設定して、ユーザーが My-Func を実行することを許可します。 あらゆる値をパラメーターに指定できます。

    @{ Name = 'My-Func'; Parameters = @{ Name = 'Param1'}, @{ Name = 'Param2' }}
    
  • ユース ケース: パラメーター Param1 を設定して、ユーザーが My-Func を実行することを許可します。 パラメーターには、Value1Value2 のみを指定できます。

    @{
        Name       = 'My-Func'
        Parameters = @{ Name = 'Param1'; ValidateSet = @('Value1', 'Value2') }
    }
    
  • ユース ケース: パラメーター Param1 を設定して、ユーザーが My-Func を実行することを許可します。 パラメーターには、contoso で始まる任意の値を指定できます。

    @{
        Name       = 'My-Func'
        Parameters = @{ Name = 'Param1'; ValidatePattern = 'contoso.*' }
    }
    

警告

セキュリティに関するベスト プラクティスとしては、表示されるコマンドレットまたは関数を定義するときにワイルドカードを使用することはお勧めできません。 代わりに、命名規則が同じ他のコマンドが意図せずに許可されるような状況を回避するために、問題のないコマンドを 1 つずつ明示的にリストアップしてください。

ValidatePatternValidateSet の両方を同じコマンドレットまたは関数に適用することはできません。

適用すると、ValidatePattern によって ValidateSet がオーバーライドされます。

ValidatePattern の詳細については、この「Hey, Scripting Guy!」投稿PowerShell 正規表現参照コンテンツをご覧ください。

外部コマンドと PowerShell スクリプトを許可する

ユーザーが JEA セッションで実行可能ファイルと PowerShell スクリプト (.ps1) を実行することを許可するには、VisibleExternalCommands フィールドに各プログラムの完全なパスを追加する必要があります。

VisibleExternalCommands = @(
    'C:\Windows\System32\whoami.exe'
    'C:\Program Files\Contoso\Scripts\UpdateITSoftware.ps1'
)

PowerShell コマンドレットおよび関数を使用すると、許可されるパラメーターを制御できるため、可能な場合は、承認する外部実行可能ファイルに相当する PowerShell コマンドレットまたは関数を使用します。

実行可能ファイルの多くでは、さまざまなパラメーターを指定することで、現在の状態を読み取ってからそれを変更することができます。

たとえば、システムでホストされているネットワーク共有を管理するファイル サーバー管理者ロールを考えてみてください。 共有の管理方法の 1 つは、net share を使用することです。 ただし、net.exe を許可すると、ユーザーがコマンド net group Administrators unprivilegedjeauser /add を使用して管理特権を取得するためにこのコマンドを使用する可能性があるため、危険です。 より安全なオプションは、Get-SmbShare コマンドレットを許可することです。これにより、得られる結果は同じですが、スコープははるかに制限されます。

JEA セッションで外部コマンドの利用をユーザーに許可するときは、実行可能ファイルの完全パスを常に指定してください。 これによりシステム上のどこかに置かれている、同じような名前の悪意のあるプログラムが実行されるのを防止します。

PowerShell プロバイダーへのアクセスを許可する

既定で、JEA セッションでは PowerShell プロバイダーを利用できません。 これにより機密情報や構成設定が接続ユーザーに公開されるリスクが軽減されます。

必要なときに、VisibleProviders コマンドを利用して PowerShell プロバイダーへのアクセスを許可できます。 プロバイダーの完全一覧が必要な場合、Get-PSProvider を実行してください。

VisibleProviders = 'Registry'

ファイル システム、レジストリ、証明書ストア、その他の機密プロバイダーにアクセスする必要がある単純な作業に関しては、ユーザーの代わりにプロバイダーとやりとりするカスタム関数の記述を検討してください。 JEA セッションで利用できる関数、コマンドレット、外部プログラムは、JEA と同じ制約の対象になりません。 既定では、これらはあらゆるプロバイダーにアクセスできます。 また、ユーザーが JEA エンドポイントとの間でファイルをコピーする必要がある場合は、ユーザー ドライブの使用も検討してください。

カスタム関数を作成する

ロール機能ファイルでカスタム関数を作成し、エンド ユーザーのために複雑なタスクを簡単にできます。 カスタム関数は、コマンドレット パラメーター値に高度な検証ロジックが必要なときにも便利です。 FunctionDefinitions で次のように単純な関数を記述できます。

VisibleFunctions = 'Get-TopProcess'

FunctionDefinitions = @{
    Name        = 'Get-TopProcess'
    ScriptBlock = {
        param($Count = 10)

        Get-Process |
            Sort-Object -Property CPU -Descending |
            Microsoft.PowerShell.Utility\Select-Object -First $Count
    }
}

重要

JEA ユーザーが実行できるように、VisibleFunctions フィールドにカスタム関数の名前を必ず追加してください。

カスタム関数の本文 (スクリプト ブロック) はシステムの既定の言語モードで実行され、JEA の言語制約の対象になりません。 つまり、関数はファイル システムとレジストリにアクセスし、ロール機能ファイルに表示されないコマンドを実行できます。 パラメーターを使用するときは、任意のコードを実行しないように注意してください。 Invoke-Expression のようなコマンドレットにユーザー入力がパイプ処理されないようにします。

上記の例では、簡潔な Select-Object ではなく、完全修飾モジュール名 (FQMN) Microsoft.PowerShell.Utility\Select-Object が使用されていることに注目してください。 ロール機能ファイルに定義されている関数は、JEA セッションの範囲に入ります。この範囲には、JEA で作成されるプロキシ関数が含まれ、既存のコマンドが制約されます。

既定では、Select-Object は、オブジェクト上で任意プロパティを選択することができない、すべての JEA セッションの制約付きコマンドレットです。 関数で制約なしの Select-Object を使用するには、FQMN を使用して、完全な実装を明示的に要求する必要があります。 JEA セッションの制約付きコマンドレットはすべて、関数から呼び出されるときに同じ制約があります。 詳細については、「about_Command_Precedence」(コマンドの優先順位について) を参照してください。

複数のカスタム関数を記述する場合、それらを PowerShell スクリプト モジュールに入れると利便性が高まります。 組み込みやサードパーティのモジュールの場合のように、VisibleFunctions フィールドを利用し、JEA セッションでこれらの関数を表示させることができます。

JEA セッションでタブ補完が正しく機能するためには、VisibleFunctions リストに組み込み関数 tabexpansion2 を含める必要があります。

構成でロール機能を使用できるようにする

PowerShell 6 より前の場合、PowerShell でロール機能ファイルを検出できるようにするには、ファイルを PowerShell モジュールの RoleCapabilities フォルダーに格納する必要があります。 モジュールは $env:PSModulePath 環境変数に含まれるあらゆるフォルダーに保存できますが、$env:SystemRoot\System32 や、信頼されていないユーザーがファイルを変更できる可能性があるフォルダーには配置しないでください。

次の例では、ロール機能ファイルをホストするための ContosoJEA という名前の PowerShell スクリプト モジュールを $env:ProgramFiles パスに作成します。

# Create a folder for the module
$modulePath = Join-Path $env:ProgramFiles "WindowsPowerShell\Modules\ContosoJEA"
New-Item -ItemType Directory -Path $modulePath

# Create an empty script module and module manifest.
# At least one file in the module folder must have the same name as the folder itself.
$rootModulePath = Join-Path $modulePath "ContosoJEAFunctions.psm1"
$moduleManifestPath = Join-Path $modulePath "ContosoJEA.psd1"
New-Item -ItemType File -Path $RootModulePath
New-ModuleManifest -Path $moduleManifestPath -RootModule "ContosoJEAFunctions.psm1"

# Create the RoleCapabilities folder and copy in the PSRC file
$rcFolder = Join-Path $modulePath "RoleCapabilities"
New-Item -ItemType Directory $rcFolder
Copy-Item -Path .\MyFirstJEARole.psrc -Destination $rcFolder

PowerShell モジュールの詳細については、PowerShell モジュールの概要に関するページを参照してください。

PowerShell 6 以降では、RoleDefinitions プロパティがセッション構成ファイルに追加されました。 このプロパティを使用すると、使用するロールの定義のロール構成ファイルの場所を指定できます。 「New-PSSessionConfigurationFile」に記載されている例を参照してください。

ロール機能を更新する

ロール機能ファイルを編集していつでも設定を更新できます。 ロール機能の更新後に新しく JEA セッションを起動すると、変更後の機能が反映されます。

そのため、ロール機能フォルダーのアクセスを制御することはとても重要となります。 ロール機能ファイルの変更は、非常に信頼できる管理者にのみ許可する必要があります。 信頼されていないユーザーにロール機能ファイルの変更を許可すると、特権を昇格させるコマンドレットの利用を簡単に許可してしまいます。

ロール機能へのアクセスを管理者がロックダウンする場合、ローカル システムにロール機能ファイルとそれが含まれるモジュールへの読み取り専用アクセス権が与えられるようにします。

ロール機能を結合する方法

ユーザーは、JEA セッションに入るときに、セッション構成ファイルの一致するすべてのロール機能へのアクセスが与えられます。 JEA では、ロールで許可される、最も制限の少ないコマンド セットをユーザーに与えようとします。

VisibleCmdlets と VisibleFunctions

最も複雑な結合ロジックがコマンドレットと関数に適用され、JEA でそのパラメーターとパラメーター値が制限されます。

ルールは次のようになります。

  1. コマンドレットが 1 つのロールでのみ表示される場合、適用可能なパラメーター制約に従ってユーザーに表示されます。
  2. あるコマンドレットが複数のロールで表示されるとき、そのコマンドレットで各ロールに同じ制約が与えられる場合、その制約の下でユーザーに表示されます。
  3. あるコマンドレットが複数のロールで表示されるとき、ロールごとにパラメーター セットが異なる場合、そのコマンドレットとすべてのロールで定義されているすべてのパラメーターがユーザーに表示されます。 1 つのロールにパラメーターの制約がない場合、すべてのパラメーターが許可されます。
  4. あるロールでコマンドレット パラメーターの検証セットまたは検証パターンが定義され、別のロールでそのパラメーターは許可されるが、パラメーター値は制約されない場合、その検証セットまたはパターンは無視されます。
  5. 複数のロールの同じコマンドレット パラメーターに 1 つの検証セットが定義されている場合、すべての検証セットのすべての値が許可されます。
  6. 複数のロールの同じコマンドレット パラメーターに 1 つの検証パターンが定義されている場合、いずれかのパターンに一致するすべての値が許可されます。
  7. 複数のロールに 1 つの検証セットが定義されているとき、別のロールで、同じコマンドレット パラメーターに 1 つの検証パターンが定義されている場合、その検証セットは無視され、残りの検証パターンにルール (6) が適用されます。

以下には、これらの規則に従ってロールをマージする方法の例を示します。

# Role A Visible Cmdlets
$roleA = @{
    VisibleCmdlets = @(
        'Get-Service'
         @{
            Name       = 'Restart-Service'
            Parameters = @{ Name = 'DisplayName'; ValidateSet = 'DNS Client' }
        }
    )
}

# Role B Visible Cmdlets
$roleB = @{
    VisibleCmdlets = @(
        @{
            Name       = 'Get-Service';
            Parameters = @{ Name = 'DisplayName'; ValidatePattern = 'DNS.*' }
        }
        @{
            Name       = 'Restart-Service'
            Parameters = @{ Name = 'DisplayName'; ValidateSet = 'DNS Server' }
        }
    )
}

# Resulting permissions for a user who belongs to both role A and B
# - The constraint in role B for the DisplayName parameter on Get-Service
#   is ignored because of rule #4
# - The ValidateSets for Restart-Service are merged because both roles use
#   ValidateSet on the same parameter per rule #5
$mergedAandB = @{
    VisibleCmdlets = @(
        'Get-Service'
        @{
            Name = 'Restart-Service';
            Parameters = @{
                Name = 'DisplayName'
                ValidateSet = 'DNS Client', 'DNS Server'
            }
        }
    )
}

VisibleExternalCommands、VisibleAliases、VisibleProviders、ScriptsToProcess

ロール機能ファイルの他のすべてのフィールドは、許可される外部コマンド、エイリアス、プロバイダー、スタートアップ スクリプトの累積セットに追加されます。 JEA ユーザーは、1 つのロール機能で使用できるあらゆるコマンド、エイリアス、プロバイダー、スクリプトを利用できます。

あるロール機能からのプロバイダーと別のロール機能からのコマンドレット/関数/コマンドが組み合わされることで、本来の意図とは異なるシステム リソース アクセスがユーザーに与えられるような事態が発生しないように注意してください。 たとえば、あるロールで Remove-Item コマンドレットが許可され、別のロールで FileSystem プロバイダーが許可される場合、JEA ユーザーがコンピューター上のファイルを削除する可能性があります。 効果的なユーザー アクセス許可を確認する方法については、JEA の監査に関する記事に追加情報があります。

次のステップ

セッション構成ファイルを作成する