Skip to main content

5 posts tagged with "graylog"

View All Tags

· 2 min read
Shunsuke Suzuki

terraform provider graylog で alert condition と stream rule の import を実装しました。

そこで import を実装する方法を紹介したいと思います。

terraform でリソースをimportするにはリソースがimportをサポートしている必要があります。 schema.Resource の Importer フィールドですね。リソースがIDだけでGet出来る場合、schema.ImportStatePassthroughを使えば終わりです。 一方、Graylogのalert condition や stream rule はIDだけでなく、stream id も必要になります。 terraform import コマンドは1つの引数しか取らないため、サポートできないのでは?と以前まで思っていました。 そういった場合、次のようにStateFuncを実装すればサポートできます。

https://github.com/suzuki-shunsuke/go-graylog/pull/59/commits/baee1165f49d2bc21b6ea7551ceff6b7daf01543#diff-f41be2a3640efd12ad4e808d77c5c8d5

# "/" で区切って stream id と ID を渡す
$ terraform import graylog_alarm_callback.test 5bb1b4b5c9e77bbbbbbbbbbb/5c4acaefc9e77bbbbbbbbbbb

区切り文字は何でも良いのでしょうが、公式のprovider が "/" で区切っていたのでそれに従うことにしました。

https://www.terraform.io/docs/providers/google/r/spanner_database.html#import

https://godoc.org/github.com/hashicorp/terraform/helper/schema#ImportStatePassthrough の実装を見てみれば分かりますが、 StateFunc の中では GET API を叩いてリソースを取得したりはしません。 terraform import コマンドの標準出力を見ると分かりますが refresh を実行しているのでそこでGETしているようです。 StateFunc は *schema.ResourceData の配列を返しますが、これは1度のGETで複数のリソースを取得するようなAPIをサポートするためのようです。

以上、terraform import の実装方法について紹介しました。

· 3 min read
Shunsuke Suzuki

Graylogを運用してきて感じているAlert機能周りの課題をリストアップします。 自分のGraylogの理解が不十分で勘違いしている部分もあるかもしれませんが、ご了承ください。 Graylogのバージョンは 2.5.0 です。 ここでいう「メンション」とは、Slackのようなチャットツールのメンションを指します。 リストの詳細を書きだしてみたものの、リストだけでだいたい言いたいことが言えてしまっていたのと、単なる愚痴っぽくなってしまったので、 リストだけに留めます。

2018-12-31 追記

元々 Alert Condition, Notification の APIがないと勘違いしていたのですが、 実はちゃんとあったので terraform で管理できるように go-graylog を更新しました。

課題リスト

  • APIでAlert Condition, Notificationを管理できない
    • APIがないので terraform でサポートも出来ない
    • 数が増えるとWeb UIでは管理が辛い・修正漏れや設定ミスが出やすい
  • Condition, NotificationがStreamに紐づく
    • ConditionによってNotificationを変えられない
      • 条件に応じてアラートの文面・通知先・メンション先・メンションの有無を変えられない (正確にはテンプレートエンジンで頑張ればある程度対応できるかもしれないが、個人的にはテンプレートそのものを切り替えたい)
    • ConditionやNotificationを複数のStreamで使い回せない
  • (少なくとも標準機能では)時間帯によってアラートの挙動を変更できない
  • Pluginを使うにしてもどれを使ったら良いか分からない
    • もっとGraylogがメジャーになれば状況も変わるかもしれない

· 6 min read
Shunsuke Suzuki

以前 Graylog を Terraform で管理する記事を書きました。

https://suzuki-shunsuke.github.io/graylog-terraform/

今回はそれを CI/CD で実行できるようにした話です。

ただし、今回の内容は Graylog に限らず Terraform を CI/CD で実行する方法として使えると思います。

今回実現したのは以下のことです。

  • PR時にテストをする
  • plan/* tag を push すると terraform plan が実行される
  • apply/* tag を push すると terraform apply が実行され、tfstate がコミット、プッシュされる

ソースコード

https://github.com/suzuki-shunsuke/example/tree/master/graylog-terraform に置いておきました。

CI/CD用の user, role を作成する

まずは role を作成します。

resource "graylog_role" "terraform" {
name = "terraform"
description = "terraform"

permissions = [
"dashboards:*",
"indexsets:*",
"inputs:*",
"roles:*",
"streams:*",
"users:*",
]
}

permission は terraform で管理するリソースのみ付与しますが、 それでも結構強い権限を付与するので取扱に注意してください。

よりちゃんと権限管理するのであれば project ごとに role, user を分けるという手もありそうですが、そうすると管理も大変そうです。

次に user を作成します。

resource "graylog_user" "terraform" {
username = "terraform"
email = "terraform@example.com"
full_name = "terraform"

roles = [
"terraform",
"Reader",
]
}

Reader か Admin は必須らしいのでReaderを付与しています。

http://docs.graylog.org/en/2.5/pages/users_and_roles/permission_system.html

Every user needs to at least have the standard “Reader” permissions but those do not provide any access to data or maintenance functionalities.

次にこのユーザーの token を発行します。

http://docs.graylog.org/en/2.5/pages/configuration/rest_api.html#creating-and-using-access-token

$ curl -u <username>:<password> -H 'Accept: application/json' -X POST 'https://graylog.example.com/api/users/<username>/tokens/<tokenname>?pretty=true'

発行したトークンを CI/CD にクレデンシャルとしてセットします。 やり方は利用するCI/CDによって変わります。

以降は drone ci という CI/CD プラットフォームを前提に書きますが、 travis ci や circle ci, jenkins など他のCI/CDでも考え方は一緒だと思います。

.drone.yml は 以下のようになります。

---
pipeline:
envsubst:
image: suzukishunsuke/alpine-envsubst:0.1.0
commands:
- envsubst < terraform.tfvars.tpl > terraform.tfvars
secrets:
- source: terraform_token_prod
target: graylog_auth_name
when:
event: tag
plan:
image: &terraform_image "suzukishunsuke/terraform-graylog:0.1.2"
commands:
- terraform init
- terraform validate
- terraform fmt -check
- terraform plan
when:
event: tag
ref: refs/tags/plan/*
apply:
image: *terraform_image
commands:
- terraform init
- terraform validate
- terraform plan
- terraform fmt -check
- terraform apply -auto-approve
when:
event: tag
ref: refs/tags/apply/*
git:
image: plugins/git
commands:
- sh drone_pipeline_commands/git.sh
when:
event: tag
ref: refs/tags/apply/*
validate:
image: *terraform_image
environment:
- "TF_VAR_auth_name=dummy"
- "TF_VAR_auth_password=token"
- "TF_VAR_web_endpoint_uri=https://graylog.example.com/api"
commands:
- terraform init
- terraform validate
- terraform fmt -check
when:
event: pull_request

まずは terraform を実行するための Docker Image を用意しました。

https://hub.docker.com/r/suzukishunsuke/terraform-graylog/

PR時のテストでは terraform validate と terraform fmt を実行します。

  validate:
image: *terraform_image
environment:
- "TF_VAR_auth_name=dummy"
- "TF_VAR_auth_password=token"
- "TF_VAR_web_endpoint_uri=https://graylog.example.com/api"
commands:
- terraform init
- terraform validate
- terraform fmt -check
when:
event: pull_request

TF_VAR_ で始まるのが terraform の変数です。

https://www.terraform.io/docs/configuration/variables.html#environment-variables

token は適当な文字列をセットしてください。PR時には実際にgraylog の API を呼ばないので適当なので問題ありません。

次に plan/* と tag を push すると terraform plan が実行されます。 この結果を見て terraform apply を実行します。

これは drone の secrets の都合なのですが、secrets の環境変数は全部大文字になってしまうため TF_VAR_auth_name という環境変数をセットできません。そのため envsubst を使って terraform.tfvars に token を書き込んでいます。

  envsubst:
image: suzukishunsuke/alpine-envsubst:0.1.0
commands:
- envsubst < terraform.tfvars.tpl > terraform.tfvars
secrets:
- source: terraform_token_prod
target: graylog_auth_name
when:
event: tag

terraform.tfvars.tpl はこんな感じです。

web_endpoint_uri = "https://graylog.example.com/api"
auth_name = "$GRAYLOG_AUTH_NAME"
auth_password = "token"

plan を実行する step です。

  plan:
image: &terraform_image "suzukishunsuke/terraform-graylog:0.1.2"
commands:
- terraform init
- terraform validate
- terraform fmt -check
- terraform plan
when:
event: tag
ref: refs/tags/plan/*

apply/* と tag を push すると terraform apply が実行されます。

  apply:
image: *terraform_image
commands:
- terraform init
- terraform validate
- terraform plan
- terraform fmt -check
- terraform apply -auto-approve
when:
event: tag
ref: refs/tags/apply/*

terraform.tfstate をコミット, プッシュします。

  git:
image: plugins/git
commands:
- sh drone_pipeline_commands/git.sh
when:
event: tag
ref: refs/tags/apply/*

drone_pipeline_commands/git.sh はこんな感じです。

git status --porcelain || exit 1
if `git diff --exit-code --quiet terraform.tfstate`; then
echo "terraform.tfstate isn't changed"
exit 0
else
git config user.name drone
git config user.email drone@example.com
git add . || exit 1
git commit -m "build: commit by drone" || exit 1
git push origin HEAD:master || exit 1
fi

terraform.tfstate に変化があった場合のみ コミット・プッシュするようにしています。 この辺のやり方はもっとうまいやり方があるかもしれません (自分のシェルスクリプト力が低いため)。

terraform plan-detailed-exitcode オプションを使うのが良い気がします。

  -detailed-exitcode  Return detailed exit codes when the command exits. This
will change the meaning of exit codes to:
0 - Succeeded, diff is empty (no changes)
1 - Errored
2 - Succeeded, there is a diff

以上 Graylog の Terraform を CI/CD で実行する方法を紹介しました。 Graylog に限らず、 Terraform を CI/CD で実行する方法として使えると思うので参考になれば幸いです。

· 5 min read
Shunsuke Suzuki

Graylogのリソースを terraform で管理するために作った terraform provider を紹介します。 Graylogとは何かはこちらを読んでください。

Graylogには様々なリソースがあります。

  • User
  • Role
  • Input
  • Index Set
  • Stream
  • Stream Rule
  • Dashboard
  • Alert
  • etc

これらのリソースはWeb UIから作成したり出来るわけですが、 Web UIでポチポチするのは疲れますし、ソースコードで管理したいものです(Infrastructure as Code)。 また、Web UIからでは細かな権限管理は出来ず(限られた権限管理しか出来ない)、APIを使ってする必要があります。

APIを使って管理できるツールを探したものの見つからなかったので、 APIを使ってGraylog用のterraform providerを自作しています。

https://github.com/suzuki-shunsuke/go-graylog

GraylogのAPIの種類は非常に多く、残念ながらカバーできているのは一部だけですが、以下のようなものをサポートしています。

  • Alert Condition
  • Alert Notification (Alarm Callback)
  • Input
  • User
  • Role
  • Index Set
  • Stream
  • Stream Rule
  • Dashboard
  • Ldap Setting

Role はサポートしているので権限管理は問題なく出来ます。 Dashboard Widget もサポートしたいです。

出来れば Alert の設定も出来ると良いのですが、Alertに関するCRUD APIが提供されていない(GETのみ)ので、サポートできません。

terraform を使った管理方法

以下では自分の管理方法を紹介します。

https://github.com/suzuki-shunsuke/example/tree/master/graylog-terraform

にサンプルが置いてあります。

基本はプロジェクトごとに

  1. Index Set, Stream, Role といったリソースを作成
  2. User に Role を付与

という流れになります。

1のプロジェクトごとの設定は terraform の module という形でまとめてしまい、プロジェクトごとにディレクトリを作成しています。

terraform provider の開発について

terraform provider の開発はドキュメントが少なく動かしつつ手探りで書いていたりしています。 terraform provider の開発に興味のある方はこの辺を見てみると良いと思います。

あとは https://github.com/terraform-providers/terraform-provider-google のような公式の provider のソースコードも参考になります。

最後に

API を使って terraform provider を開発することで、Infrastructure as Code をある程度実現できました。

  • Stream Rule と Dashboard をサポートできていない
  • Alertに関するCRUD APIが提供されていない(GETのみ)ので、サポートできない

という問題がクリア出来てないので、そこをクリアしたいです。

また、

  • まだ terraform を CI で出来ていない(ローカルから実行している)
  • 新しいプロジェクトやユーザーの追加の際に雛形を自動生成できるツールを作りたい(特に、新しく参画した人のためにあると良い)

といった点も改善したいです(出来たら記事にしたいと思います)。

2018-12-03 追記

2018-12-31 追記

  • Alert Condition, Notification をサポートしました

· 10 min read
Shunsuke Suzuki

Java 製の OSS ログ管理システム Graylog の紹介です。 Graylog については幾つかに分けて記事を書きたいと思います。 今回はGraylogの入門的な内容になります。

なお、本記事中で「現在」「現時点」といった場合、特に断りがなければ記事執筆時点 2018-11-27 を指します。

Graylog のバージョン

検証に用いるGraylogのバージョンは 2.4.6 になります。

OSSバージョンとEnterpriseバージョンがありますが、本記事ではOSSバージョンを使用します。

Graylog とは

Kibana と Elasticsearch(以下ES) を使ったことがある人は、Kibanaに代わるものだと思っていただくとイメージしやすいかと思います。 ログはGraylogそのものが保持するのではなく、ESにインデキシングされます。 Kibana同様、ESに収集されたログを検索したり、ダッシュボードを作ったり出来ます。 ダッシュボードに関してはKibanaのほうが優れているようにも思えますが、 Graylogは認証・認可によりダッシュボードやログを操作できる人を制限・管理することが出来ます。

Graylogでログを管理する場合、ユーザーは直接ESにはログを送らず、Graylogを経由して送ります。 ESに対するGraylog以外のアクセスを制限し直接ESにアクセスされるのを防ぐことが出来ます。

Graylog は多機能なシステムであり、ログを整形したり、アラートを飛ばしたり、他のシステムにログをフォワードしたりすることも出来ます。 marketplace でサードパーティの plugin が公開されており、機能を拡張することが出来ます。 APIも提供されており、ある程度自動化が可能です。

認証・認可

オンプレミスでログを管理する場合、社外からは勿論社内からのアクセスも制限したいです。 Graylog では LDAP や Active Directory によってアクセスを制限できます。 リソース毎に誰が何を出来るか設定できます。

http://docs.graylog.org/en/2.5/pages/users_and_roles/external_auth.html

ログの収集

ログの収集をするには Graylog で幾つかのリソースを作成する必要があります。

  • Input
  • Index Set
  • Stream
  • Stream Rule

Input はログの入力のフォーマットの設定であり、 どのポートでどういったフォーマットのログを受け付けるかという設定になります。 フォーマットは様々なものがサポートされています。

  • AWS Flow Logs
  • AWS Cloud Watch Logs
  • AWS Cloud Trail
  • Beats
  • CEF AMQP
  • CEF Kafka
  • CEF TCP
  • CEF UDP
  • Fake HTTP Message
  • GELF AMQP
  • GELF HTTP
  • GELF Kafka
  • GELF TCP
  • GELF UDP
  • JSON Path
  • NetFlow UDP
  • Raw AMQP
  • Syslog AMQP
  • Syslog Kafka
  • Syslog TCP
  • Syslog UDP

この設定はログを収集するアプリケーションごとに設定するというより、グローバルな設定なので、他のアプリケーションで既に同じ形式でログを収集していたら新たに設定する必要はありません。

Index SetはESのIndexの論理的なセットです。 GraylogはESの複数のIndexを1つのセットとして管理します。 Index Setの設定で古いログを自動でcloseしたり削除したりする事ができるのでログの管理が楽になります。 ESのログは収集しているだけだとどんどん肥大化していってしまうので、Curatorなどを使って古いものを消したりする必要がありますが、そういったことをGraylogが自動でやってくれます。

Stream はGraylogに収集されたログを分類する仕組みです。 Stream毎に検索したりダッシュボードを作ったりアラートを飛ばしたりログの閲覧を制限したりします。 分類の仕方は自由ですが、自分はアプリケーション毎にStreamを作っています。 Stream毎にStream Ruleを定義し、Stream Ruleの条件にマッチしたログはそのStreamに振り分けられます。 自分はfluentdから送ったログの tag によってStreamを分けています。

ログを送る

公式ドキュメントに幾つかログの送り方が紹介されています。

http://docs.graylog.org/en/2.5/pages/sending_data.html

自分が主にやっているのが

ここまでやればログを検索したり出来ます。

Alert

http://docs.graylog.org/en/2.5/pages/streams/alerts.html

アラートの設定は

  • Condition: アラートの条件
  • Notification: アラート先(どこにアラートを飛ばすか)

の2つに分かれます。それぞれStreamに関連づいた設定です。

Condition では

  • Field content condition
  • Field aggregation condition
  • Message count condition

といった条件で設定できます。

Notification は標準では

  • HTTP(Webhook)
  • Email

の2種類しかないのですが、pluginで Slack などにも通知することが出来ます。 自分は https://github.com/graylog-labs/graylog-plugin-slack を使って Slack に通知しています。

Notification のメッセージのテンプレートは自由に変えられますが、どういったテンプレートが良いかは難しいです。 自分は次のような感じにしています。

${alert_condition.title}

${foreach backlog message}
<https://graylog.example.com/streams/${stream.id}/search?rangetype=absolute&from=${message.timestamp}&to=${message.timestamp} | link> ${message.message}
${end}

graylog の URL は適宜置き換えてください。 link の部分を変数(${message.message}とか)にするとリンクが壊れてしまうことがあったので固定文字列にしています。

graylog-plugin-slack の設定で Graylog URL (optional)を設定しないと ${stream_url} などが空になってしまうことに注意してください。 自分は optional なので元々設定していなかったのでハマりました(ググっても分からなかった)。 Graylog URLという設定は notification 毎に変えるようなものでもないのでglobalに設定できるとよいのですが、どうも出来なそうです。

また、テンプレート中で使える変数の中にmessageのURLはないそうです。

https://community.graylog.org/t/message-url-in-alert-notification/1916

そのため、message.timestamp を from と to に指定して検索するという回りくどい(?)ことをしています。

ダッシュボードの作成

ダッシュボードの作成は

  1. Dashboardページ: 空のDashboardを作る
  2. Stream ページ: クエリを実行したりしてグラフを作る
  3. Stream ページ: グラフをDashboardに追加する
  4. Dashboardページ: グラフを並び替えたりする

詳細は割愛するので http://docs.graylog.org/en/2.5/pages/dashboards.html を読んでください。

権限管理

Graylogの権限管理では User と Role という概念があり、 Role の permissions としてどのリソースにどういった操作を許可するか定義し、 User に Role を付与します。

http://docs.graylog.org/en/2.5/pages/users_and_roles/permission_system.html#permissions

permissions として定義できるものは公式なドキュメントが見つからないのですが、APIで取得できます。

https://gist.github.com/suzuki-shunsuke/e371f1bd2716cde31d6fa89bf39f0e77

例えば streams:read は全てのStreamをreadする権限となりますし、 streams:read:<stream id> とすれば特定のStreamのみreadする権限となります。

プロジェクトごとにroleを定義してプロジェクトの関係者に付与したり、アルバイトや正社員といった雇用形態に応じてroleを定義したり、色々な利用方法はあると思います。

こういったRoleのpermissionの定義はWeb UIからも出来ますが、 残念ながらWeb UIからではなくAPIを用いないと定義できないpermissionもあります。 そのため、自分は Graylog APIを用いて terraform provider を開発し、terraform で Roleの作成を行っています。

最後に

以上、自分が主に使っているGraylogの機能を紹介しました。 Graylogは多機能で自分が使っていない、分かっていない機能が色々あります。 興味のある方は調べてみてください。