ElasticのIntegrations(Cisco ASA)にバグをプルリクを投げて修正した話

# 概要

私の現職はElasticの技術コンサルなのですが、あるときお客様が利用されている[Cisco ASAのログを取り込むIntegration](https://docs.elastic.co/en/integrations/cisco_asa)でログのパース処理にバグがあるのを見つけました。バグは[Issue](https://github.com/elastic/integrations/issues/5946)を上げれば開発チームが適切に対応してくれますが、原因が明確で、かつなるべく早期に修正することが望ましかったこともあり、今回自分で修正して[プルリク](https://github.com/elastic/integrations/pull/5948)を投げて取り込んでもらいました。

この記事ではIntegrationのIngest Pipelineの箇所を修正してテストするあたりの方法についてメモしておこうと思います。

 # 読んでおくべきもの

Elastic Integrationにコントリビュートする際には、まずGithubのリポジトリに[Contributing Guide](https://github.com/elastic/integrations/blob/main/CONTRIBUTING.md)があるので目を通します。

また[公式のブログ](https://www.elastic.co/blog/review-testing-methods-for-elastic-integrations-using-the-elastic-package-tool)にも同じ様なIntegrationのテストに関する内容の記事があるのでそちらも参照してください。

 # 環境準備

Integrationをテストする場合、例えば今回のようにIngestion Pipelineの修正であれば少なくともElasticsearchが必要で、他に例えばダッシュボードに修正を入れる場合は当然Kibanaなどそのほかのコンポーネントも必要になります。Elasticではその辺りの一式を揃えるための [elastic-package](https://github.com/elastic/elastic-package) というツールを提供しています。

[最新版のリリースページ](https://github.com/elastic/elastic-package/releases/latest)から適切なパッケージをダウンロードします。展開すると`elastic-package`コマンドの実行ファイルがあるので、これをパスの通ったところに配置します。

macOSの場合、ダウンロード後そのまま実行しようとするとセキュリティーの設定で起動できないため、以下のコマンドで実行を許可します。

```sh
$ xattr -r -d com.apple.quarantine elastic-package
```

以下のコマンドで動作確認します。

```sh
$ elastic-package -h
elastic-package - Command line tool for developing Elastic Integrations
...(略)...
```

問題なければ、以下のコマンドでElasticsearchを起動します。このコマンドはDockerコンテナでElasticsearchを起動しようとするため、Dockerデスクトップ等が起動してdockerが使える状態になっていることを確認してください。

```
$ elastic-package stack up -d --services=elasticsearch
Boot up the Elastic stack
Using profile /Users/daixque/.elastic-package/profiles/default.
Remember to load stack environment variables using 'eval "$(elastic-package stack shellinit)"'.
Elasticsearch host: https://127.0.0.1:9200
Kibana host: https://127.0.0.1:5601
Username: elastic
Password: changeme
Local package-registry will serve packages from these sources:
- Proxy to https://epr.elastic.co
Done
```

# 実際のIntegrationをテストする

ツールの準備ができたので、対象のIntegrationをまずは変更なしでテストしてみようと思います。

まずは[Integrationsのリポジトリ](https://github.com/elastic/integrations)をクローンします。

```sh
$ git clone git@github.com:elastic/integrations.git
```

そして当該インテグレーションのディレクトリ、は今回の場合cisco_asaまで移動します。

```sh
$ cd integrations/packages/cisco_asa
```

ここで以下のコマンドで環境変数を設定します。

```sh
eval "$(elastic-package stack shellinit)"
```

この状態で`elastic-package test pipeline`コマンドを実行すると、このパッケージにあるpipelineのテストを実行することができます。

```
$ elastic-package test pipeline
Run pipeline tests for the package
--- Test results for package: cisco_asa - START ---
╭───────────┬─────────────┬───────────┬──────────────────────────────┬────────┬──────────────╮
│ PACKAGE   │ DATA STREAM │ TEST TYPE │ TEST NAME                    │ RESULT │ TIME ELAPSED │
├───────────┼─────────────┼───────────┼──────────────────────────────┼────────┼──────────────┤
│ cisco_asa │ log         │ pipeline  │ test-additional-messages.log │ PASS   │ 421.967796ms │
│ cisco_asa │ log         │ pipeline  │ test-anyconnect-messages.log │ PASS   │ 104.689755ms │
│ cisco_asa │ log         │ pipeline  │ test-asa-fix.log             │ PASS   │  81.822325ms │
│ cisco_asa │ log         │ pipeline  │ test-asa-missing-groups.log  │ PASS   │  70.271211ms │
│ cisco_asa │ log         │ pipeline  │ test-asa.log                 │ PASS   │  1.10996308s │
│ cisco_asa │ log         │ pipeline  │ test-dap-records.log         │ PASS   │  15.545565ms │
│ cisco_asa │ log         │ pipeline  │ test-filtered.log            │ PASS   │  50.683596ms │
│ cisco_asa │ log         │ pipeline  │ test-hostnames.log           │ PASS   │   8.502888ms │
│ cisco_asa │ log         │ pipeline  │ test-non-canonical.log       │ PASS   │  44.813717ms │
│ cisco_asa │ log         │ pipeline  │ test-not-ip.log              │ PASS   │  16.815382ms │
│ cisco_asa │ log         │ pipeline  │ test-sample.log              │ PASS   │ 286.142844ms │
│ cisco_asa │ log         │ pipeline  │ test-sip.log                 │ PASS   │  14.722426ms │
╰───────────┴─────────────┴───────────┴──────────────────────────────┴────────┴──────────────╯
--- Test results for package: cisco_asa - END   ---
Done
```

ここまでくればあとはパイプラインの実装とテストを追加・修正して、期待通り動作するようになったらプルリクを投げられますね。

実際の修正内容などは私のプルリクなども参考にしてください。

https://github.com/elastic/integrations/pull/5948

# 自分でビルドしてインストールする

Elastic Integrationsは基本的にはElasticがFleet経由で提供するもので、直接ユーザーがインストールすることを前提とはしていませんが、今回の様に自分で修正したりあるいは新規に作成した場合には、KibanaのAPI経由でインストールすることも可能です。

まずはcisco_asaなどIntegrationのディレクトリにて以下のコマンドを実行し、パッケージをビルドします。

```sh
$ elastic-package build
```

するとzip形式のパッケージが作成されます。これをKibanaにアップロードします。方法は以下に記載されています。

https://github.com/elastic/elastic-package/blob/main/docs/howto/install_package.md#customization

```sh
$ export ELASTIC_PACKAGE_KIBANA_HOST="https://kibana:5601"
$ export ELASTIC_PACKAGE_ELASTICSEARCH_USERNAME="elastic"
$ export ELASTIC_PACKAGE_ELASTICSEARCH_PASSWORD="xxx"

$ elastic-package install --zip path/to/build/packages/cisco_asa-2.16.0.zip -v
```

あるいはKibana APIで直接アップロードすることも可能です。[こちらのIssue](https://github.com/elastic/kibana/issues/148599)が参考になります。
curlを使ってアップロードする場合、以下の様なコマンドになります。

```sh
$ curl -XPOST \
  -H 'content-type: application/zip' \
  -H 'kbn-xsrf: true' \
  https://kibana:5601/api/fleet/epm/packages \
  -u elastic:password \
  --data-binary @cisco_asa-2.16.0.zip
```

# 参考

この記事からのスピンアウトっていう感じで、elastic-packageコマンドを使ってElastic Stackを簡単に立ち上げる方法を書きました。

https://qiita.com/daixque/items/819b03bfa19acd371af6