PowerShellでSplunkのREST APIにリクエストを投げる方法について

PowerShellにはcurl相当のことができるコマンドとして、Invoke-WebRequestメソッドが用意されています。
よって、このコマンド使えばcurlと同じ感覚でSplunkのREST APIにリクエスト投げればいいじゃんと思ってたら色々手こずったのでまとめました。

※Powershellのバージョン:5.1.1/Splunkバージョン:7.2.4で実施した内容になります。

# Invoke-WebRequest実行前に必要なこと

結論から述べますと、SplunkのREST APIにリクエストを投げるにはPowershell側で以下の準備が必要です。
1.(Invoke-WebRequest実行時の)自己証明書使用チェックの無効化
2.(PSで使用する)SSL/TLSプロトコルの変更
3.認証情報オブジェクト(PSCredential)の作成

## 1.(Invoke-WebRequest実行時の)自己証明書チェックの無効化
自己証明書が使われているサーバーに対し、Invoke-WebRequestコマンドでhttpsのリクエストを投げると、Powershellデフォルトではリクエストを弾いてしまうようです。
Splunkデフォルトでは自己証明書が使われるので、Invoke-WebRequest実行時にNGにならないようにPowershellのデフォルトの挙動を変更します。

※Splunkサーバー側で自己証明書を使っていない場合はこの対応は不要です（未検証）

## 2.(PSで使用する)SSL/TLSプロトコルの指定

Splunkバージョン6.6以降、SSL/TLSプロトコルはデフォルトでTLS1.2が使用されていますが、※
PowerShellはデフォルトではSSL3またはTLS1.0を使用するようです。
よってPowerShell側のSSL/TLSプロトコルを変更します。

※Splunkデフォルトで$SPLUNK_HOME/etc/system/default/server.confのsslConfigスタンザにあるsslVersionsアトリビュートが適用されるようです。

## 3.認証情報の作成

SplunkにREST APIを投げる場合は認証情報が必要になります。
一方でInvoke-WebRequestで認証情報を指定するときは-Credentialオプションを指定するのですが、機密情報(パスワード)を含めるにはPSCredentialオブジェクトを指定する必要があるようです。

よって、Invoke-WebRequestコマンド実行前にSplunkのユーザー/パスワード情報を含めたPSCredentialオブジェクトを作成しておきます。

## 1～3.準備作業まとめスニペット
ここまでの準備作業をまとめると以下のコマンドになります。

※Splunkデフォルトのパスワード(changeme)ではREST APIを受け付けないため、デフォルトから変更する必要があります。ご注意ください。

``` powershell: 
# 1.Invoke-WebRequest実行時に自己証明書チェックが無効になるようにする。
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

# 2.SSL/TLSプロトコルを変更する。(TLS1.2を使うようにする)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# 3.認証情報オブジェクトを作成する。
$USER = "admin"
$PASS = "password"
$SECPASS = ConvertTo-SecureString $PASS -AsPlainText -Force
$CRED = New-Object System.Management.Automation.PSCredential($USER, $SECPASS)

```

これら準備を行ったあと、Invoke-WebRequest実行時に-Credentialオプションで認証情報オブジェクトを指定することでSplunkのREST APIにリクエストを投げることができるようになります。

# REST APIコマンドサンプル
以下にInvoke-WebRequestを使ったREST APIのサンプルをご紹介します。

## Splunkサーバー再起動
```powershell:
Invoke-WebRequest -Method POST "https://<targethost>:8089/services/server/control/restart"  -Credential $CRED

# <targethost> ・・・設定対象Splunkサーバーを指定します。
```
## 受信設定追加($SPLUNK_HOME/bin/splunk enable listenと同義)
```powershell:
Invoke-WebRequest -Method POST "https://<targethost>:8089/services/data/inputs/tcp/cooked/" -Body "name=<port>" -Credential $CRED

# <targethost> ・・・設定対象Splunkサーバーを指定します。
# <port> ・・・データ受信ポートを指定します。
# 設定完了後、$SPLUNK_HOME/etc/app/search/local/inputs.confにスタンザが追加されます。(なぜsearch Appに・・・)
```
## 転送設定追加($SPLUNK_HOME/bin/splunk add forward-monitorと同義)
```powershell:
Invoke-WebRequest -Method POST "https://<targethost>:8089/services/data/outputs/tcp/server" -Body "name=<receiverhost>:<port>" -Credential $CRED

# <targethost> ・・・設定対象Splunkサーバーを指定します。
# <receiverhost>・・・データを受信するSplunkサーバーを指定します。
# <port> ・・・データ受信ポートを指定します。
# 設定完了後、$SPLUNK_HOME/etc/system/local/outputs.confにスタンザが追加されます。
```

トークンを使った場合のやり方はまた別の機会に。。。

# 参考文献
PowerShellでTLS1.2や自己証明書への対応
https://www.uramiraikan.net/Works/entry-3424.html

Invoke-WebRequest
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-6

PSCredential Class
https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.pscredential?view=pscore-6.2.0

PowershellのInvoke-RestMethodをhttpsに実施すると失敗する
https://suzan2go.hatenablog.com/entry/2014/10/18/192246

PowerShell Scripting Weblog
http://winscript.jp/powershell/?s=-credential%83p%83%89%83%81%81%5B%83%5E

Splunk REST API Reference Manual
https://docs.splunk.com/Documentation/Splunk/latest/RESTREF/RESTprolog