curlを使ってSplunk REST API経由でsplunkをリモート操作する

# はじめに
SplunkはREST APIを提供しており、REST APIのEndpointにアクセスすることでSplunkをリモート操作することができます。
本ドキュメントでは、curlを用いてSplunkサーバーのREST APIにアクセスし、Splunkをリモートで操作するための手法と例についてご紹介させていただきます。

# SplunkのREST APIを使うための前提条件
SplunkのREST APIを使うためにはいくつか条件があります。

### 通信
クライアントとSplunkサーバ間でマネジメントポートの通信許可がされていることが必要です。
curlを実行するクライアントからSplunkの管理ポート(デフォルト:8089)への通信が許可されている必要があります。

### 権限
REST APIのEndpointにアクセスする時はSplunkの認証情報を指定する必要があります。この認証情報に含めるSplunkユーザは、REST APIのEndpointに対する操作(GET/POST/DELETE)に応じた権限(capability)が付与されている必要があります。

例1:REST APIでSplunkの設定を参照したい
・・・認証情報のSplunkユーザーに`rest_properties_get`権限が必要

例2:REST APIでSplunkの設定を変更したい
・・・認証情報のSplunkユーザーに`rest_properties_set`権限が必要

2020年4月現在のSplunk最新バージョン(8.0.3)では、以下の権限があるようです。

|  |
|:-:|
| rest_apps_management |
| rest_apps_view |
| rest_properties_get |
| rest_properties_set |

これらCapabilityが、REST APIのEndpointのどの操作に対する権限があるかは、残念ながら公開されていないようです。
ですので、CapabilityがEndpointへの何の操作が許可されているか、権限名称から察する必要があります。

### admin使用時のパスワード
認証情報にadminを指定する場合、デフォルトパスワードを使用していないこと

REST APIのEndopointにアクセスするときに使う認証情報について、splunk管理者ユーザー(デフォルト:admin)を指定する場合、ユーザーのパスワードをデフォルトから変更する必要があります。(デフォルト:changeme)

# REST APIのEndpointへのリクエスト方法
REST APIのEndpointにアクセスするためには、以下のどちらかの認証方法を指定する必要があります。

1.ユーザー/パスワード認証
2.アクセストークン認証

## ユーザー/パスワード認証
curlコマンドの-uオプションでユーザ/パスワードを直接指定する方法です。
後述するアクセストークン認証に比べ、シンプルな記述で認証情報を指定することができます。
しかし、認証情報が平文でネットワーク上を流れるので、検証などセキュリティへの配慮が少ない環境での使用に留めておくべきでしょう。

```
curl [-X GET|POST] -k -u <username>:<password> https://<splunk uri>:<management_port>/services/<REST API endpoint>
```

## アクセストークン認証
まずアクセストークンを取得し、そのトークンを使ってREST APIのEndpointにアクセスする方法です。
アクセストークン取得時にユーザー/パスワード認証同様に、認証情報が平文で流れてしまうのですが、前述の方式に比べセキュアにEndpointにアクセスすることができます。

まず、`/services/auth/login`エンドポイントにアクセスし、アクセストークンを取得します。

```
curl -k https://<splunk uri>:<management_port>/services/auth/login -d username=<username> -d password=<password>
```

次に、レスポンスに含まれるsessionKeyタグで囲まれた文字列がアクセストークンになりますので、それを控えます。
※ログインに失敗した場合は取得できません。

```
<response>
  <sessionKey>192fd3e46afd246da7ea7f109e7f95fd</sessionKey>
</response>
```

その後、curl実行時にヘッダー指定オプション(-H)で`Authorization: Splunk`ヘッダーにアクセストークンを含めてEndpointにアクセスします。

```
curl -k -H "Authorization: Splunk 192fd3e46afd246da7ea7f109e7f95fd" https://<splunk uri>:<management_port>/services/<REST API endpoint>
```

なお、Splunkバージョン7.3以降、GUIでトークンを取得できるようになりました。この方法で取得したアクセストークンを使う場合は、`Authorization: Bearer`ヘッダーを指定します。

```
curl -k -H "Authorization: Bearer 192fd3e46a31246da7ea7f109e7f95fd" https://<splunk uri>:<management_port>/services/<REST API endpoint>
```

# curlを使った操作例

ここでは、curlでREST API Endpointにアクセスし、Splunkをリモート操作する例をご紹介します。
全てのEndpointは紹介しきれないため、詳細を知りたい方は[公式マニュアル](https://docs.splunk.com/Documentation/Splunk/latest/RESTREF/RESTprolog)をご参照ください。

※以下のコマンド例では、説明をシンプルにするためにユーザー/パスワード認証方式を用いています。

## Splunkの再起動
ユースケース
 - 何らかの事情でSplunkサーバーに直接ログインできない場合
 - リモートでUniversalForwarderのSplunkを再起動したい場合

``` :Splunkの再起動を行なう。
curl -k -X POST https://192.168.1.1:8089/services/server/control/restart -u admin:<password>
```

## 取り込み対象ファイルの追加
ユースケース
 - あるSplunkサーバーにログ取り込み設定を追加する場合
 - あるUniversalForwarderにログ取り込み設定を追加する場合

``` :Splunkサーバーの/var/log/secureを取り込む設定を追加する。
curl -k -X POST https://192.168.1.1:8089/services/server/input/monitor/add -d name=/var/log/secure -u admin:password
```

## 取り込み対象ファイルの確認
ユースケース
 - あるSplunkサーバーでどのファイルを取り込む設定にしているか確認する場合

``` :ファイル取り込み設定をjson形式で表示する
curl -k https://192.168.1.1:8089/services/data/inputs/monitor?output_mode=json
```

## データ受信・転送
ユースケース
 - あるSplunkサーバーを他のサーバーからデータを受信できるようにする場合

``` :別のSplunkサーバーからデータを受信できるようにする。(データ受信ポート9997)
curl -k -X POST https://192.168.1.2:8089/services/data/inputs/tcp/cooked/" -d name=9997 -u admin:password
```

ユースケース
 - あるSplunkサーバーに送られるデータを他のサーバーに転送できるようにする場合

``` :Splunkサーバーに送られたデータを別のSplunkサーバー(192.168.1.2)に転送する。(データ受信ポート9997)
curl -k -X POST https://192.168.1.1:8089/services/data/outputs/tcp/server -d name=192.168.1.2:9997 -u admin:password
```

## 分散サーチ
ユースケース
 - あるSplunkサーバーから他のSplunkサーバーのデータ（インデックス）をサーチできるようにする場合

``` :分散サーチピア(192.168.1.3)を追加する
curl -k -X POST https://192.168.1.1:8089/services/search/distributed/peers -d name=192.168.1.3:8089 -d remoteUsername=admin -d remotePassword=password -u admin:password
```

## 保存済みサーチ（レポート、アラート）
ユースケース
 - あるSplunkサーバーの保存済みサーチ設定をまとめて確認したい場合

``` :保存済みサーチの情報を表示
curl -k -X POST https://192.168.1.1:8089/servicesNS/-/-/saved/searches/ -u admin:password
```

``` :App"customapp"の保存済みサーチ"hogehoge"を無効化
curl -k -X POST https://192.168.1.1:8089/servicesNS/nobody/customapp/saved/searches/hogehoge -d disabled=1 -u admin:password
```

## フォワーダー管理
ユースケース
 - あるSplunkサーバーのフォワーダー管理対象を一覧形式で確認したい場合

``` :デプロイメントクライアントを確認
curl -k -X POST https://192.168.1.1:8089/services/deployment/server/clients -u admin:password
```

ユースケース
 - あるSplunkサーバーのサーバークラスを更新したい場合

``` :サーバークラスを更新
curl -k -X POST https://192.168.1.1:8089/services/deployment/server/config/_reload -u admin:password
```

# 余談
 - EndpointへのレスポンスはAtom Syndication Formatに従ったxml形式で出力されます。
ただし、Endpointによっては、Endpointのパラメータに`?output_mode=xxxx`を指定することで、xml以外の形式で出力することができるようです。
参考:[Encoding schemes](https://docs.splunk.com/Documentation/Splunk/latest/RESTUM/RESTusing#Encoding_schemes)

 - splunkのCLIコマンドによる操作も内部ではREST API Endpointにアクセスして操作しているようです。

 - Endpointのアクセスログは、Splunkの内部動作ログに出力されます。
具体的には、`$SPLUNK_HOME/var/log/splunk/splunkd_access.log`にREST API Endpointへのリクエストが記録されるようです。
※`$SPLUNK_HOME`はSplunkのインストールディレクトリを表しています。

# 参考文献
[REST API User's Manual](https://docs.splunk.com/Documentation/Splunk/latest/RESTUM/RESTusing)
[Authentication and authorization](https://docs.splunk.com/Documentation/Splunk/latest/RESTUM/RESTusing#Authentication_and_authorization)
[REST API Reference Manual](https://docs.splunk.com/Documentation/Splunk/latest/RESTREF/RESTprolog)