LoginSignup
11
8

More than 3 years have passed since last update.

PowerShellで認証プロキシ越え

Last updated at Posted at 2019-03-22

目的

Invoke-RestMethod コマンドレットや Invoke-WebRequest コマンドレットをユーザ認証のあるプロキシサーバを越えて使用するための設定を行う。

成功例

$proxyServer  = "http://xxx.xxx.xxx:8080"    # 未設定の場合はIEの設定を利用する
$proxyUser    = "xxxxx"                      # 未設定の場合は認証なしとみなす
$proxyPassword= "xxxxx"                      # 未設定の場合はプロンプトする

if (-not $proxyServer) {
    $proxy = [System.Net.WebRequest]::GetSystemWebProxy()
    if ($proxy) { $proxyServer = $proxy.GetProxy("http://example.com").AbsoluteUri }
}
if ($proxyServer) {
    $proxy = New-Object System.Net.WebProxy $proxyServer, $True
    if ($proxyUser) {
        if ($proxyPassword) { 
            $securePassword = ConvertTo-SecureString $proxyPassword -AsPlainText -Force
            $proxy.Credentials = New-Object -TypeName System.Management.Automation.PSCredential $proxyUser,$securePassword
        } else {
            $proxy.Credentials = Get-Credential -UserName $proxyUser -Message "プロキシサーバのパスワードを入力して下さい。"
        }
    }
    [System.Net.WebRequest]::DefaultWebProxy = $proxy
}

失敗例(本当はこちらを使いたい)

なぜ失敗するのか不明(環境依存のバグかも。ネット上に Win7, Win8.1 で失敗、Win10 で成功との情報あり)。
(2019.7.23更新) Win10での成功を確認しました。

$proxyServer  = "http://xxx.xxx.xxx:8080"    # 未設定の場合はIEの設定を利用する
$proxyUser    = "xxxxx"                      # 未設定の場合は認証なしとみなす
$proxyPassword= "xxxxx"                      # 未設定の場合はプロンプトする

if (-not $proxyServer) {
    $proxy = [System.Net.WebRequest]::GetSystemWebProxy()
    if ($proxy) { $proxyServer = $proxy.GetProxy("http://example.com").AbsoluteUri }
}
if ($proxyServer) {
    if ($proxyUser) {
        if ($proxyPassword) { 
            $securePassword = ConvertTo-SecureString $proxyPassword -AsPlainText -Force
            $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $proxyUser,$securePassword
        } else {
            $credential = Get-Credential -UserName $proxyUser -Message "プロキシサーバのパスワードを入力して下さい。"
        }
        $PSDefaultParameterValues = @{ "Invoke-RestMethod:Proxy"=$proxyServer; "Invoke-RestMethod:ProxyCredential"=$credential;
                                       "Invoke-WebRequest:Proxy"=$proxyServer; "Invoke-WebRequest:ProxyCredential"=$credential }
    } else {
        $PSDefaultParameterValues = @{ "Invoke-RestMethod:Proxy"=$proxyServer;
                                       "Invoke-WebRequest:Proxy"=$proxyServer  }
    }
}

追記(2019.7.27)

スクリプト内へのパスワード記載(平文)を避ける方法について3つ程考察してみます。

方法1 既定の資格情報(DefaultCredentials)の利用

プロキシサーバの認証が、Windowsと共通であれば、既定の資格情報が利用できますので、Invoke-RestMethod コマンドレットや Invoke-WebRequest コマンドレットのパラメータとして ProxyCredentialの代わりに-ProxyUseDefaultCredentialsを指定することができます。

方法2 資格情報マネージャーに格納された資格情報の利用

プロキシサーバの認証情報を資格情報マネージャーに格納されているキャッシュから取得します。資格情報マネージャーの情報にアクセスするためには、advapi32.dll の ReadCredW 関数を使う必要あります。
PowerShell から ReadCredW を呼び出して Credential オブジェクトとして返す関数の例が、ここここにありますが、数行で実装という訳にはいきません。手軽に使うには、ちょっと...って感じですね。

(2020.10.24追記)
WinRTを利用して $null = [Windows.Security.Credentials.PasswordVault,.,ContentType=WindowsRuntime]; $vault = (New-Object Windows.Security.Credentials.PasswordVault).RetrieveAll(); $vault.RetrievePassword(); $vault で取得できるようです。

方法3 暗号化された文字列としてスクリプト内に埋め込む

ConvertFrom-SecureString コマンドレットで、\$securePassword を暗号化された文字列に変換して、それをスクリプト内に保存します。SecureString に戻すには ConvertTo-SecureString コマンドレットを使用します。

クリエイティブ・コモンズ 表示 - 継承 4.0 国際

11
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8