Zabbix API(1.8)を使ってみた

Zabbix 1.8 の API に関してはWeb 上にいろいろ情報があるので、大いにはまった権限周りを中心にメモする。

ドキュメント

日本語では Zabbix 1.8 系と 2.0 系の両方を解説した次の記事がある。これを読めば、API のことはひと通りわかるハズ。

Think It : 第4回 Zabbix APIを使った外部ツールとの連携
http://thinkit.co.jp/story/2012/05/11/3541

オフィシャルドキュメントとして、次の API の概要とセッション例がある

処理の流れ

  1.  API 用ユーザを追加
  2.  認証トークンを取得
  3.  認証トークンを設定して API を呼び出す

zabbix-api-flow

プロトコルは JSON-RPC
オフィシャルブログに “Getting started with Zabbix API” という記事があるので、これを参考に監視対象のホストを取得する API を使ってみる。

API 用ユーザを追加

Administrations -> Users から API 用ユーザを追加する。

注意すべきは、以下の項目

  • Groups
  • User type
  • User rights

Groups/User rights
API を使うには、API access グループに属していなければいけないので、このグループに属させること。

User type

Zabbix では API で利用するユーザを Web 管理画面のセッション管理を流用して実装されている。
API を使って許可される操作は、API に設定した権限によって変わる。

User typeZabbix Super Admin の場合、無条件で何でもできる。

Zabbix Super Admin 以外の場合、権限を許可してあげないといけない。
Users -> User groups の API access グループに Read-write や Read only の権限を付与する。rights テーブルに permission が 3(Read-write)、2(Read only) でインサートされる。

認証トークンの取得

API ユーザを追加したところで、ようやく API を操作する。
認証トークンの取得は、メソッド user.login はたは user.authenticate で行う。

$ curl -H "Accept: application/json" -H "Content-type: application/json" http://localhost/zabbix/api_jsonrpc.php -i -X POST -d '{"jsonrpc":"2.0", "method":"user.login", "params":{"user":"api", "password":"api"}, "auth":null, "id":0}'
HTTP/1.1 200 OK
Date: Sun, 10 Feb 2013 06:24:02 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
Set-Cookie: zbx_sessionid=a08c5c826c0e1e48a51b836e93a2b388
Set-Cookie: zbx_sessionid=a08c5c826c0e1e48a51b836e93a2b388
Content-Length: 68
Connection: close
Content-Type: application/json

{"jsonrpc":"2.0","result":"a08c5c826c0e1e48a51b836e93a2b388","id":0}

レスポンスの result キーが認証トークン(セッションID)。
sessions テーブルには、以下のようなレコードが追加される。

zabbix=# select * from sessions;
            sessionid             | userid | lastaccess | status
----------------------------------+--------+------------+--------
 a08c5c826c0e1e48a51b836e93a2b388 |      3 | 1360477442 |      0
(1 row)

API のエラー例

user または password を間違えた場合は、以下の様なレスポンスが返される。

{
   "jsonrpc" : "2.0",
   "error" : {
      "data" : "Login name or password is incorrect",
      "message" : "Invalid params.",
      "code" : -32602
   },
   "id" : 0
}

ホスト一覧の取得

取得した認証トークンを利用して host.get メソッドでホスト一覧を取得する。
params をいじることで、フィルター条件やレスポンス内容を細かく制御できる。

$ curl -H "Accept: application/json" -H "Content-type: application/json" http://localhost/zabbix/api_jsonrpc.php  -X POST -d '{"jsonrpc":"2.0", "method":"host.get", "params":{"output":["hostid", "name"]}, "auth":"a08c5c826c0e1e48a51b836e93a2b388", "id":2}' | json_pp
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   260  100   131  100   129   1080   1063 --:--:-- --:--:-- --:--:--  1119
{
   "jsonrpc" : "2.0",
   "id" : 2,
   "result" : [
      {
         "name" : "(10047,0,01234a01,\"\",1,192.168.13.20,10050,0,0,\"\",0,0,0,0,0,0,6",
         "hostid" : "10047"
      }
   ]
}

API のエラー例

不正なセッションIDを渡した場合

{
   "jsonrpc" : "2.0",
   "error" : {
      "data" : "Not authorized",
      "message" : "Invalid params.",
      "code" : -32602
   },
   "id" : 2
}

不正なメソッド(host.get のかわりに hosts.get)を渡した場合

{
   "jsonrpc" : "2.0",
   "error" : {
      "data" : "Resource (hosts) does not exist",
      "message" : "Invalid params.",
      "code" : -32602
   },
   "id" : 2
}

不正なメソッド(host.get のかわりに host.get)を渡した場合

{
   "jsonrpc" : "2.0",
   "error" : {
      "data" : "Action (gets) does not exist",
      "message" : "Invalid params.",
      "code" : -32602
   },
   "id" : 2
}

Python に移植

cURL のデモを Python に移植する。
Python では標準ライブラリ以外に requests を利用するので、インストールされていなければ $ pip install requests すること。

セッションID の有効期間

ユーザのセッション情報は sessions テーブルで管理されている。このテーブルではセッションIDを発行したタイムスタンプは持っておらず、最後に操作したタイムスタンプだけ持っている。Web 管理画面で操作していれば、Auto-logout を設定しているユーザの場合、一定期間操作指定なければセッションが切れる。
一方で API で操作している場合、実行された SQL を眺める限り、リクエストされたセッション ID が存在するかどうかはチェックしているが

  •  セッションのタイムスタンプの更新
  •  Auto-logout の時間が切れているかのチェック

などはおこなっておらず、一度発行されたセッション ID はいつまでも再利用可能。

user.logout メソッドを呼んで無効(sessions.status = 1)にするつもりだったみたいだけど、つい最近(2013-Jan-16)リリースされた 1.8.16 までは不具合で API を呼び出せなかったので古いバージョンを使っている場合は注意が必要。

ZABBIX BUGS AND ISSUES ZBX-3907 : Logout API operation doesn’t work
https://support.zabbix.com/browse/ZBX-3907

認証トークンを取得するオーバーヘッドが減って、頻繁に API を使う上では便利だろうけど、この設計思想はどうだろうね。

API 呼び出し時の権限チェック

API 呼び出し時にユーザのタイプやユーザの権限チェックを行なっているロジックは、host.get の場合 zabbix-1.8.15/frontends/php/api/classes/class.chost.php の186 行目以降にある。(api/classes フォルダの各ファイルにコピペされている模様)

// editable + PERMISSION CHECK
                if((USER_TYPE_SUPER_ADMIN == $user_type) || $options['nopermissions']){
                }
                else{
                        $permission = $options['editable'] ? PERM_READ_WRITE : PERM_READ_ONLY;

                        $sql_parts['where'][] = 'EXISTS ('.
                                                        ' SELECT hh.hostid '.
                                                        ' FROM hosts hh, hosts_groups hgg, rights r, users_groups ug '.
                                                        ' WHERE hh.hostid=h.hostid '.
                                                                ' AND hh.hostid=hgg.hostid '.
                                                                ' AND r.id=hgg.groupid '.
                                                                ' AND r.groupid=ug.usrgrpid '.
                                                                ' AND ug.userid='.$userid.
                                                                ' AND r.permission>='.$permission.
                                                                ' AND NOT EXISTS( '.
                                                                        ' SELECT hggg.groupid '.
                                                                        ' FROM hosts_groups hggg, rights rr, users_groups gg '.
                                                                        ' WHERE hggg.hostid=hgg.hostid '.
                                                                                ' AND rr.id=hggg.groupid '.
                                                                                ' AND rr.groupid=gg.usrgrpid '.
                                                                                ' AND gg.userid='.$userid.
                                                                                ' AND rr.permission<'.$permission.
                                                                ' )) ';
                }
... snip
Tagged with: , ,
Posted in middleware

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
  • RT @__apf__: How to write a research paper: a guide for software engineers & practitioners. docs.google.com/presentation/d… /cc @inwyrd 1 week ago
  • RT @HayatoChiba: 昔、自然と対話しながら数学に打ち込んだら何かを悟れるのではと思いたち、専門書1つだけ持ってパワースポットで名高い奈良の山奥に1週間籠ったことがある。しかし泊まった民宿にドカベンが全巻揃っていたため、水島新司と対話しただけで1週間過ぎた。 それ… 3 weeks ago
  • RT @googlecloud: Ever wonder what underwater fiber optic internet cables look like? Look no further than this deep dive w/ @NatAndLo: https… 3 weeks ago
  • @ijin UTC+01:00 な時間帯で生活しています、、、 6 months ago
  • RT @mattcutts: Google's world-class Site Reliability Engineering team wrote a new book: amazon.com/Site-Reliabili… It's about managing produc… 9 months ago
%d bloggers like this: