VyattaのREST APIを使ってみる

ソフトウェアベースのネットワークゲートウェイVyattaの有料のVyatta Subscription Edition(VSE)では、REST APIを提供していて、外部からAPIを使って操作・管理をすることができます。

SoftLayerでは、Vyatta Gateway ApplianceでこのVSEを使用することができます。
インフラ全体を管理するためにはサーバーの構成管理だけでは不十分で、ネットワークやストレージもあわせて、統合的に管理する必要がありますが、Vyatta APIを活用すれば、サーバーだけでなくネットワークと連携してインフラを制御できるので、より統合的な形でインフラ全体を管理することができます。

まずは、Vyatta APIに関する情報と、curlコマンドによる使い方をまとめてみます。


# Vyatta側の設定

## HTTPSの有効化とバインド

リモートからAPIにアクセスするため、Vyatta側でHTTPSを有効にしておく必要があります。

```bash
vyatta# set service https listen-address 10.x.x.x
vyatta# commit
vyatta# save
```

SoftLayerのVyatta Gateway Applianceの場合、デフォルトではPrivate側のみHTTPSサービスがBINDされています。

```
vyatta@vyatta-tok02# show service https
 listen-address 10.x.x.x
[edit]

vyatta@vyatta-tok02# netstat -nat
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 10.x.x.x:443            0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:443           0.0.0.0:*               LISTEN
tcp        0      0 10.x.x.x:80             0.0.0.0:*               LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
[edit]
```


# Vyatta REST APIの基本

## APIの認証

以下のいずれかの方法でAPIへのアクセスの認証が可能です。

- HTTP BASIC認証 (VyattaログインユーザーID、パスワードをbase64 encode)
- Temporary Session Keyを使う
 - [Software Engineering Crunch and more...: Session support in the Vyatta REST API](http://softengcrunch.blogspot.jp/2011/03/session-support-in-vyatta-rest-api.html)

### BASIC認証

以下のようにcurlコマンドを実行すると、HTTP requestに`Authorization: Basic dnlhdHRhxxxxxzgyQk1l`というフィールドが加えられています。これがBASIC認証の認証データで、base64エンコードされたユーザーIDとパスワードが送信されていることがわかります。

```bash:BASIC認証の例
$ curl -v -k -s -i -u vyatta:vyatta -H "Content-Length: 0" -H "Accept: application/json" -X POST https://10.x.x.x/rest/conf
* Hostname was NOT found in DNS cache
*   Trying 10.x.x.x...
* Connected to 10.x.x.x (10.x.x.x) port 443 (#0)
* TLS 1.0 connection using TLS_RSA_WITH_AES_256_CBC_SHA
* Server certificate: Vyatta Web GUI
* Server auth using Basic with user 'vyatta'
> POST /rest/conf HTTP/1.1
> Authorization: Basic dnlhdHRhxxxxxzgyQk1l
> User-Agent: curl/7.37.1
> Host: 10.x.x.x
> content-length:0
> Accept: application/json
>
< HTTP/1.1 201 Created
HTTP/1.1 201 Created
< Content-Type: application/json
Content-Type: application/json
< Location: rest/conf/BF7017C544FBC2B5
Location: rest/conf/BF7017C544FBC2B5
< Vyatta-Specification-Version: 0.3
Vyatta-Specification-Version: 0.3
< Cache-Control: no-cache
Cache-Control: no-cache
< Transfer-Encoding: chunked
Transfer-Encoding: chunked
< Date: Sat, 21 Feb 2015 12:59:27 GMT
Date: Sat, 21 Feb 2015 12:59:27 GMT
* Server lighttpd/1.4.28 is not blacklisted
< Server: lighttpd/1.4.28
Server: lighttpd/1.4.28
```

## リクエストの形式

リクエストのメソッドとURIによって、アクセスするリソースやAPIを指定することができます。

### URIの形式

Vyattaには以下の2種類の操作モードがあり、REST APIでもそれぞれに対応したURIが存在します。

- Operational Mode: システムの状態や設定情報を参照するするモード。設定の変更はできない
- Configuration Mode: 設定情報を変更・削除・commitできるモード

```
https://<vyatta IP>/rest/op/<path>      # Operational Mode
https://<vyatta IP>/rest/conf/<path>    # Configuration Mode
```

- vyatta IP: vyattaのIPアドレス
- `rest`: RESTでのアクセスを表す
- `op`: Operational modeのAPIを使用
-  `conf`: Configuration modeのAPIを使用
-  path : 実行するVyattaコマンドをパス形式で指定。Vyattaコマンドが `show vpn ipsec sa` であれば `show/vpn/ipsec/sa` と指定



## 基本的な使い方

### curlコマンドで使う

curlコマンドでURIを指定してREST APIにリクエストを送信することができます。

- GETの例

```
$ curl -k -s -i -u vyatta:vyatta -X GET http://192.168.1.202/rest/conf
```

- POSTの例

```
$ curl -k -s -i -u vyatta:vyatta -H "Content-Length: 0" -H "Accept: application/json" -X
￼POST http://192.168.1.202/rest/conf

HTTP/1.1 201 Created
Transfer-Encoding: chunked
Content-Type: application/json
Location: rest/op/D462E45FCEFBB5A5
Date: Fri, 19 Feb 2010 21:28:39 GMT
Server: lighttpd/1.4.19
```

#### デバック

HTTP request/responseを確認したい場合、`curl -v`オプションを指定すると詳細を表示することができます。

```bash
$ curl -v -k -s -i -u vyatta:vyatta -X GET https://10.x.x.x/rest/conf
* About to connect() to 10.x.x.x port 443 (#0)
*   Trying 10.x.x.x...
* Connected to 10.x.x.x (10.x.x.x) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_RSA_WITH_AES_256_CBC_SHA
* Server certificate:
* 	subject: L=Belmont,ST=CA,O=Vyatta Inc.,CN=Vyatta Web GUI,C=US
* 	start date: Feb 15 08:05:29 2015 GMT
* 	expire date: Feb 12 08:05:29 2025 GMT
* 	common name: Vyatta Web GUI
* 	issuer: L=Belmont,ST=CA,O=Vyatta Inc.,CN=Vyatta Web GUI,C=US
* Server auth using Basic with user 'vyatta'
> GET /rest/conf HTTP/1.1
> Authorization: Basic dnlhdHRhOkfdsfgyQk1l
> User-Agent: curl/7.29.0
> Host: 10.x.x.x
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Type: application/json
Content-Type: application/json
< Vyatta-Specification-Version: 0.3
Vyatta-Specification-Version: 0.3
< Cache-Control: no-cache
Cache-Control: no-cache
< Content-Length: 21
Content-Length: 21
< Date: Sun, 15 Feb 2015 15:09:14 GMT
Date: Sun, 15 Feb 2015 15:09:14 GMT
< Server: lighttpd/1.4.28
Server: lighttpd/1.4.28

<
{
  "message": " "
}
* Connection #0 to host 10.x.x.x left intact
```


# よく使うVyatta REST APIのReference

よく使われるVyattaのREST APIを整理します。

## Configuration Mode


| REST API Command       | Vyatta CLI command  |  備考       |
|----------------------|------------------------|-----------|
| `POST /rest/conf` | `$ configure` | ConfigセッションID(conf-id)を取得してConfiguration Modeに移行。以後このconf-idを通して設定の変更・適用を行う |
| `GET /rest/conf` | - | Activeなconf-idを取得 |
| `GET /rest/conf/<session-id>/<param>` | `# set`の後TABキーで子パラメータ候補を表示 | Config Modeのsetコマンドのパラメータ、子パラメータ等を表示 |
| `PUT /rest/conf/<session-id>/set/xxx/yyy` | `# set xxx yyy` | conf-idのセッションに対してsetコマンドを実行 |
| `PUT /rest/conf/<session-id>/delete/xxx/yyy` | `# delete xxx yyy` | conf-idのセッションに対してdeleteコマンドを実行 |
| `POST /rest/conf/<session-id>/commit` | `# commit` | configのcommit |
| `POST /rest/conf/<session-id>/save` | `# save` | configの保存 |
| `DELETE /rest/conf/<session-id>` | `# exit` | Config Modeからexit。conf-idが破棄される |


## Operational Mode

| REST API Command       | Vyatta CLI command  |  備考       |
|----------------------|------------------------|-----------|
| `POST /rest/op/<path>` | `<path>`のコマンドを実行 | Operational Modeのコマンドを実行してLocationを取得。 |
| `GET /rest/op/<Location>` | `<path>`のコマンドの結果を表示 | Locationにアクセスするとコマンドの出力が得られる |
| `GET /rest/op/<path>` | TABキーで子パラメータ候補を表示 | Operational modeのコマンドのパラメーター、子パラメータ等を表示 |
| `GET /rest/op` | - | Operational Modeで実行中のコマンド、出力結果が表示されていないプロセスを表示 |
| `DELETE /rest/op/<process-id>` | - | Operational modeのプロセスを終了 |


# Vyatta REST APIの使用例


## Configuration Mode

Configuration Modeでの処理は以下の順序で実行します。

1. Configuration Modeのconf-idを取得 (`POST /rest/conf`)
1. conf-idのセッションに対してConfigurationを行う (`PUT /rest/conf/<conf-id>/set/<path>`, `PUT /rest/conf/<conf-id>/delete/<path>`)
1. ConfigをCommit (`POST /rest/conf/<conf-id>/commit`)
1. ConfigをSave (`POST /rest/conf/<conf-id>/save`)


### Configuration Modeのセッションを取得

#### セッションを取得

```
$ curl -k -s -i -u vyatta:vyatta -H "Content-Length: 0" -H "Accept: application/json" -X POST https://10.x.x.x/rest/conf
HTTP/1.1 201 Created
Content-Type: application/json
Location: rest/conf/CDAAF2AA11A9D45F
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Transfer-Encoding: chunked
Date: Sat, 21 Feb 2015 13:18:37 GMT
Server: lighttpd/1.4.28
```

以下のように、セッションを識別するためにdescriptionを設定することもできます。

```
$ curl -k -s -i -u vyatta:vyatta -H "Content-Length: 0" -H "Accept: application/json" -X POST https://10.x.x.x/rest/conf/CONFIG_BY_API
HTTP/1.1 201 Created
Content-Type: application/json
Location: rest/conf/5460F22FE50CFCFD
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Transfer-Encoding: chunked
Date: Sat, 21 Feb 2015 14:04:22 GMT
Server: lighttpd/1.4.28
```

#### セッションを確認

セッションを確認します。作成した2つのセッションが表示されています。

```
$ curl -k -s -i -u vyatta:vyatta -X GET https://10.x.x.x/rest/conf
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Content-Length: 425
Date: Sat, 21 Feb 2015 14:04:34 GMT
Server: lighttpd/1.4.28

{
  "session": [
    {
      "id": "5460F22FE50CFCFD",
      "username": "vyatta",
      "description": "CONFIG_BY_API",
      "started": "1424527462",
      "modified": "false",
      "updated": "1424527462"
    },
    {
      "id": "CDAAF2AA11A9D45F",
      "username": "vyatta",
      "description": "",
      "started": "1424524717",
      "modified": "false",
      "updated": "1424524717"
    }
  ],
  "message": " "
}
```

以降では`5460F22FE50CFCFD`のセッションを使用します。


### セッションIDに対してConfigurationを実行

以下では、setコマンドでbond0インタフェースにIPアドレスを設定しています。
VyattaでのIPアドレスの設定ではネットマクスを/で指定する必要がありますがREST APIでは、ネットマスクを表す/と、URIの/と区別がつかないため、/のままではエラーになってしまいます。/を使う場合は、以下のようにURLエンコードされた`%2F`を使ってください。

```
$ curl -k -s -i -u vyatta:vyatta -X PUT https://10.x.x.x/rest/conf/5460F22FE50CFCFD/set/interfaces/bonding/bond0/address/192.168.10.1%2F24
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Transfer-Encoding: chunked
Date: Sat, 21 Feb 2015 14:12:35 GMT
Server: lighttpd/1.4.28
```

deleteコマンドも、同様にPUTメソッドで実行可能です。


### ConfigのCommit & Save

この時点ではまだ設定が適用されていません。ConfigをCommitして設定を反映させます。

```
$ curl -k -s -i -u vyatta:vyatta -H "Content-Length: 0" -H "Accept: application/json" -X POST https://10.x.x.x/rest/conf/5460F22FE50CFCFD/commit
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Content-Length: 21
Date: Sat, 21 Feb 2015 14:15:05 GMT
Server: lighttpd/1.4.28

{
  "message": " "
}
```

これで、実行中のVyattaには設定が反映されましたが、まだ設定ファイルには設定が保存されていないため、再起動すると元の設定に戻ってしまいます。saveを実行して設定をファイルに保存します

```
$ curl -k -s -i -u vyatta:vyatta -H "Content-Length: 0" -H "Accept: application/json" -X POST https://10.x.x.x/rest/conf/5460F22FE50CFCFD/save
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Content-Length: 79
Date: Sat, 21 Feb 2015 14:16:43 GMT
Server: lighttpd/1.4.28

{
  "message": " Saving configuration to '/config/config.boot'...\n Done\n "
}
```


### コマンド定義、子パラメータの表示

VyattaのConfiguration Modeで、setコマンドの後TABキーを押すと、以下のように子パラメータの候補が表示されます。

```
vyatta@vyatta-tok02# set
Possible completions:
 > cluster      Clustering
 > firewall     Firewall
 > interfaces   Network interfaces
 > load-balancing
                Configure load-balancing
 > nat          Network Address Translation (NAT) parameters
 > policy       Routing policy
 > protocols    Routing protocol parameters
 > service      Services
 > system       System parameters
 > test-definition
                Configure the definition of a test
 > traffic-policy
                Quality of Service (QOS) policy type
 > vpn          Virtual Private Network (VPN)
 > zone-policy  Configure zone-policy
```

同様の操作をAPIでも実行することができます。

```
$ curl -k -s -i -u vyatta:vyatta -X GET https://10.x.x.x/rest/conf/5460F22FE50CFCFD/
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Content-Length: 1408
Date: Sat, 21 Feb 2015 13:48:51 GMT
Server: lighttpd/1.4.28

{
  "children": [
    {
      "name": "service",
      "state": "active",
      "deactivate_state": "enable"
    },
    {
      "name": "system",
      "state": "active",
      "deactivate_state": "enable"
    },
    {
      "name": "protocols",
      "state": "active",
      "deactivate_state": "enable"
    },
    {
      "name": "interfaces",
      "state": "active",
      "deactivate_state": "enable"
    },
    {
      "name": "firewall",
      "state": "active",
      "deactivate_state": "enable"
    },
    {
      "name": "nat",
      "state": "none",
      "deactivate_state": "enable"
    },
    {
      "name": "zone-policy",
      "state": "none",
      "deactivate_state": "enable"
    },
    {
      "name": "vpn",
      "state": "none",
      "deactivate_state": "enable"
    },
    {
      "name": "cluster",
      "state": "none",
      "deactivate_state": "enable"
    },
    {
      "name": "test-definition",
      "state": "none",
      "deactivate_state": "enable"
    },
    {
      "name": "policy",
      "state": "none",
      "deactivate_state": "enable"
    },
    {
      "name": "load-balancing",
      "state": "none",
      "deactivate_state": "enable"
    },
    {
      "name": "traffic-policy",
      "state": "none",
      "deactivate_state": "enable"
    }
  ],
  "type": [
    "none"
  ],
  "deactivate_state": "enable",
  "is_changed": "true",
  "state": "active"
}
```

さらに子パラメータにわたっても候補を表示することが可能です。

```
$ curl -k -s -i -u vyatta:vyatta -X GET https://10.x.x.x/rest/conf/5460F22FE50CFCFD/vpn
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Content-Length: 565
Date: Sat, 21 Feb 2015 13:49:34 GMT
Server: lighttpd/1.4.28

{
  "children": [
    {
      "name": "pptp",
      "state": "none",
      "deactivate_state": "enable"
    },
    {
      "name": "l2tp",
      "state": "none",
      "deactivate_state": "enable"
    },
    {
      "name": "rsa-keys",
      "state": "none",
      "deactivate_state": "enable"
    },
    {
      "name": "ipsec",
      "state": "none",
      "deactivate_state": "enable"
    }
  ],
  "type": [
    "none"
  ],
  "deactivate_state": "enable",
  "help": " Virtual Private Network (VPN)",
  "is_changed": "false",
  "name": "vpn",
  "state": "none"
}
```


## Operational Mode

Operational Modeでの処理は以下の順序で実行します。

1. POSTでコマンド実行をリクエスト (`POST /rest/op/`)
1. ResponseからLocationを取得 (`Location: /rest/op/xxxxxxxxxxxxxxx`)
1. GETでLocationへアクセスするとコマンド実行結果の標準出力が得られる (`GET /rest/op/xxxxxxxxxxxxxxx`)


### コマンドの実行

```
$ curl -k -s -i -u vyatta:vyatta -H "Content-Length: 0" -H "Accept: application/json" -X POST https://10.x.x.x/rest/op/show/version
HTTP/1.1 201 Created
Content-Type: application/json
Location: rest/op/46826F1EB88B80F4
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Transfer-Encoding: chunked
Date: Sat, 21 Feb 2015 15:06:28 GMT
Server: lighttpd/1.4.28
```

コマンドを実行すると、Responseで`Location: rest/op/46826F1EB88B80F4`を取得しています。

### 取得したLocationにアクセス

コマンドの実行結果を出力するために、このLocationにアクセスしてAPIの実行結果を取得します。
以下のように`show version`コマンドの実行結果が返されます。

```
$ curl -k -s -i -u vyatta:vyatta -X GET https://10.x.x.x/rest/op/46826F1EB88B80F4
HTTP/1.1 200 OK
Content-Type: text/plain
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Content-Length: 456
Date: Sat, 21 Feb 2015 15:06:46 GMT
Server: lighttpd/1.4.28

Version:      VSE6.6R6
Description:  Brocade Vyatta 5415 vRouter 6.6 R6
Copyright:    2006-2014 Vyatta, Inc.
Built by:     autobuild@vyatta.com
Built on:     Thu Jun 26 23:44:07 UTC 2014
Build ID:     1406262347-dd268ed
System type:  Intel 64bit
Boot via:     disk
HW model:     X10SLH-N6-ST031
HW S/N:       0123456789
HW UUID:      00000000-0000-0000-0000-0CC47A1E8DA8
Uptime:       09:06:29 up 6 days, 53 min,  1 user,  load average: 0.07, 0.17, 0.17
```

#### 誤ったコマンドの場合

誤ったコマンドを実行した場合、エラーメッセージがそのまま返されます。

```
$ curl -k -s -i -u vyatta:Fkc82BMe -H "Content-Length: 0" -H "Accept: application/json" -X POST https://10.x.x.x/rest/op/show/veersion
HTTP/1.1 201 Created
Content-Type: application/json
Location: rest/op/9A11F8E835A36056
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Transfer-Encoding: chunked
Date: Sat, 21 Feb 2015 15:46:59 GMT
Server: lighttpd/1.4.28


$ curl -k -s -i -u vyatta:Fkc82BMe -X GET https://10.x.x.x/rest/op/9A11F8E835A36056
HTTP/1.1 200 OK
Content-Type: text/plain
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Content-Length: 37
Date: Sat, 21 Feb 2015 15:47:13 GMT
Server: lighttpd/1.4.28


  Invalid command: show [veersion]
```

#### Locationにアクセスしない場合

Locationにアクセスしない場合、出力結果は削除されずにどんどん蓄積されていきます。

```
$ curl -k -s -i -u vyatta:vyatta -X GET https://10.x.x.x/rest/op
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Content-Length: 356
Date: Sat, 21 Feb 2015 15:08:25 GMT
Server: lighttpd/1.4.28

{
  "process": [
    {
      "username": "vyatta",
      "started": "1424435506",
      "updated": "16466314",
      "id": "1F8C6DD257234D32",
      "command": "show 'version'"
    },
    {
      "username": "vyatta",
      "started": "1424531188",
      "updated": "16466314",
      "id": "46826F1EB88B80F4",
      "command": "show 'version'"
    }
  ]
}
```

### コマンド定義、子パラメータの表示

Operational ModeでTABキーを押すと子パラメータの候補が表示されるのと同様の操作を、APIでも実行することができます。

```
$ curl -k -s -i -u vyatta:vyatta -X GET https://10.x.x.x/rest/op/
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Content-Length: 437
Date: Sat, 21 Feb 2015 15:19:24 GMT
Server: lighttpd/1.4.28

{
  "children": [
    "renew",
    "force",
    "test",
    "telnet",
    "show",
    "monitor",
    "update",
    "poweroff",
    "clear",
    "reboot",
    "install",
    "mtrace",
    "format",
    "delete",
    "set",
    "release",
    "generate",
    "ping",
    "restart",
    "disconnect",
    "configure",
    "add",
    "rename",
    "reset",
    "copy",
    "connect",
    "clone",
    "traceroute"
  ],
  "action": "false"
}
```

```
$ curl -k -s -i -u vyatta:vyatta -X GET https://10.x.x.x/rest/op/show/interfaces/ethernet/eth0
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.3
Cache-Control: no-cache
Content-Length: 278
Date: Fri, 20 Feb 2015 12:28:58 GMT
Server: lighttpd/1.4.28

{
  "children": [
    "queue",
    "physical",
    "brief",
    "vif",
    "identify",
    "statistics"
  ],
  "enum": [
    "eth0",
    "eth1",
    "eth2",
    "eth3",
    "eth4",
    "eth5"
  ],
  "action": "true",
  "help": " Show specified ethernet interface information"
}
```


# 参考

- [20140404 vyatta users Group / REST API解説](http://www.slideshare.net/YukihiroKikuchi/20140404-vyatta-users-group)
- [Vyatta Documentation: Remote Access API](http://www.brocade.com/downloads/documents/html_product_manuals/vyatta/vyatta_5400_manual/Remote%20Access%20API/wwhelp/wwhimpl/js/html/wwhelp.htm)
- Vyattaの以下のファイルにサンプルあり
 - /opt/vyatta/sbin/vyatta‐webgui2‐shell.pl
 - /opt/vyatta/sbin/vyatta‐webgui2‐op.pl
- [Software Engineering Crunch and more...: Session support in the Vyatta REST API](http://softengcrunch.blogspot.jp/2011/03/session-support-in-vyatta-rest-api.html)
- [Shell API - VyOS jp](http://wiki.vyos-users.jp/Shell_API) Shell APIというのもあるらしい