
Splunk Federated Analytics を試してみた
2024/11/12 に Splunk Cloud で Federated Analytics が利用可能になったのですが、ついにパートナー環境でも検証できるようになったのでやってみました。
Federated Analytics 誕生の背景と課題
まず、この機能の概要について背景とともに確認しておきます。
デジタル社会が進む中、企業が保有するデータはますます多くなっている状況かと思います。
これまで SIEM では、データの分析基盤という側面に加え、データの保管要件を担うように設計されていることも少なからずありました。
一方、「Amazon S3 のようなサービスを代表に、デジタル化がもたらす大量のデータを安価に安心して保管できるサービスは、非常に多くのユーザーに親しまれてきました。
そんな中、SIEM 上でデータを保管する上で問題となってくるのが、S3などのサービスとは比べ物にならないコストです。
もう一点、セキュリティのログ分析の対象となるログソースは様々で、セキュリティベンダー機器のログ、Windows OSログ、Linux OSログ、IdPなど認証ベンダーのログ、クラウドベンダーのログなど多岐に渡ります。歴史的には、Syslogなどのログフォーマットがありますが、セキュリティイベントのための共通化規格ではないため、異種のログ間をグループ化する定義はなく、セキュリティ分析の際にはアナリストのスキルに大きく依存せざるをえませんでした。
この問題を解消するため、2022年にセキュリティイベントの標準スキーマとして OCSF(Open Cybersecurity Schema Framework) が誕生しました。そして、その OCSF に則ってセキュリティイベントの自動変換し Amazon S3 へ保管するサービスとして、Amazon Security Lake が AWS から提供されています。
Splunk Federated Analytics はこの Amazon Security Lake と連携し、高速で頻繁に検索する必要があるデータに対しては AWS Security Lake から Splunk Cloud に取り込みます。
一方、低頻度な分析用途や、データとして分析の価値があるか分からないようなデータに関しては、Splunk Cloud とリモートで接続だけしておいて、必要となった時に都度データのダイレクトクエリを行います。
その時、データフォーマットは OCSF で正規化されたデータとして扱うことができるようになります。
類似した機能で、Splunk Federated Search for S3 がありましたが、Federated Analytics は OCSF で正規化されたデータを扱うこと、データの取り込み・ダイレクトクエリを一元的に管理し、よりデータパイプラインがシンプルになりました。
Federated Search for S3 参考ブログ
前提
Splunk Federated Analytics を利用するためにAWS、Splunkのそれぞれで以下の条件を満たしている必要がありますので、事前に用意・確認をしておきます。
AWS
- Amazon Security Lake を有効にしている
- AWS Organizations で組織の証跡を有効にしている
- 複数リージョンのデータを連携したい場合は、Amazon Security Lake のロールアップリージョンを行い、ロールアップリージョン先を Splunk Cloud がデプロイされているリージョンと同じリージョンにする必要があります
- Amazon Security Lake のサブスクライバーの作成は、Splunk Cloud がデプロイされているリージョンと同じリージョンにする必要があります
Splunk Cloud
- Splunk Cloud ライセンスを購入済み
- Data Scan Units のライセンスを購入済み
- Splunk Federated Analytics 有効のため Splunk 営業へ事前連絡
AWS Organizations の設定と、Amazon Security Lake を開始するまでの設定手順はこの記事ではご紹介しませんが、これから設定される方は以下の記事を参考にしてください。
やってみる
前置きが長くなりましたが、Splunk Federated Analytics の設定をやってみます。
設定の流れは以下の通りです。
- AWS側前提の確認(Amazon Security Lake)
- Splunk Cloud - Security Lake federated provider の設定
- Amazon Security Lake - サブスクライバー(data access)の設定
- Amazon Security Lake - サブスクライバー(query access)の設定
- AWS RAM - AWS Glue Data Catalog が共有されていることを確認
- Splunk Cloud - data lake index の設定
- Splunk Cloud - federated index の設定
- Splunk Cloud - data lake index の検索、federated index の検索
Splunk Cloud の画面と、AWS の画面をいったりきたりするので、画像を添付しながら説明していこうと思います。
Federated Provider (Amazon Security Lake) の設定
Splunk Cloud、AWS の両方の画面を開きながら設定を行っていきます。
まず最初に Splunk Cloud の画面です。
Settings
の Federation
を選択します。
Federated Providers
の Add federated provider
を選択し、Amazon Security Lake
を選択します。
好きな名前で Provider name
を設定します。例では、AWS-Federated-Analytics
としました。
次に進むと、以下のような画面が表示されるので、網掛け部分の Splunk側のAWS アカウントID
と Enternal ID
をそれぞれコピーしておきます。
また、データ連携元のAWSアカウントのリージョンと同じ必要があるので、念の為こちらも確認しておきます。
次に、AWSコンソールに画面を移します。
Security Lake の サブスクライバー
で作成を行います。
サブスクライバーを入力して(例では SplunkCloudDataAccess
)、データアクセス方法に S3
と SQS キュー
を選択します。
アカウントID
と 外部ID
では、Splunk Cloud の画面で表示されていたものを貼り付け、作成します。
(今回 すべてのログとイベントのソース
で設定していますが、ログイベントごとに連携必要なものだけを選択することも可能です。)
作成したサブスクライバーの情報を開き、AWS ロール ARN
、サブスクリプションエンドポイント
を確認しておきます。
次に Splunk Cloud の設定に戻り、確認した AWS ロール ARN
、サブスクリプションエンドポイント
の値を入力します。
そのまま少し下にスクロールすると、同じような画面がありますが、こちらはQuery Access用のサブスクライバーに設定する情報が表示されています。
Splunk側のAWS アカウントID
と Enternal ID
をそれぞれコピーしておきます。
次にAWSマネジメントコンソールに戻り、もう一つサブスクライバーを作成します。
サブスクライバー名は、SplunkCloudQueryAccess
にしました。
設定ができたらAWSマネジメントコンソールで RAM (Resource Access Manager) を開き、リソース(AWS Lake Formation)が共有できていることを確認します。
詳細の確認ため、クリックして、リソース共有名 名前
と、リソース共有ARN ARN
をコピーします。
Splunk Cloud の画面で、それぞれコピーした値を貼り付け、次に進みます。
もう一度、AWSマネジメントコンソールの画面で次は、glue:Database
の リソースID
と glue:Table
の リソースID
を確認します。
Splunk Cloud の画面で、glue:Database
の リソースID
と glue:Table
の リソースID
を入力していきます。
glue:Table
の リソースID
は データベース名
/
以降の文字列を入力していきます。
データインジェストのための詳細な設定を行っていきます。
Data Lake Index name
では、デフォルトの値が入っていますが、任意の名前で変更するこも可能です。
Event class
では、それぞれの項目でプルダウンを展開すると、イベントを選択でき、取り込むかどうかを絞り込むことができます。
Retention period
では、1日 〜 31日 までの間で選択することが可能です。ここから伺える通り、Splunk Cloud ではあくまで分析の高速化やリアルタイム分析を行うための機能で、保管用途としての利用ケースではなさそうです。
今回は、デフォルト状態で進めていきます。
ダイレクトクエリのための詳細な設定になります。
Federated index name
では、デフォルトの値が入っていますが、任意の名前で変更するこも可能です。(デフォルトの名前は長くなりがちになりそうなので、本番では名前を変更したほうが良さそうです)
Time partition settings
では、Security Lake内のタイムフォーマットとSplunk Cloud内のタイムフォーマットを合わせる必要があるのですが、Federated Anlytics の場合は、そのままでも特に不都合はないかと思いますので、デフォルトで進めます。
最後に設定内容を確認して、保存します。
検索してみる
再度、settings
の Federation
で作成したインデックスを確認します。
まず、Data lake indexes
で確認できるインデックスは、Splunk Cloud に取り込んでいるインデックスになります。
これらのインデックスは、ローカルに取り込まれている状態なので、高速な従来のSPL文と同様のコマンドで検索できます。
data lake index
は6種類用意されていて、それぞれが OCSF のカテゴリーと一致する名前で設定されているとあります。
Set up data ingest and retention rules for data lake indexes - Splunk Documentation
OCSF のカテゴリーは以下から確認でき、System Activity
, Findings
, Identity & Access Management
, Network Activity
, Discovery
, Application Activity
が該当します。
その他に、Remediation
と Unmanned Systems
がありますが、この2つは割り当てられていないようです。
Open Cybersecurity Schema Framework
また、上記 OCSF ドキュメントリンク内には、カテゴリーに所属するクラスが確認できます。
AWS のそれぞれのログソースが OCSF にどうマッピングされているかを確認しておきます。
(下記公式ドキュメントからの転記したテーブルを確認します)
Open Cybersecurity Schema Framework (OCSF) in Security Lake - Amazon Security Lake
ソース | medata.product.name | metadata.product.vendor_name | metadata.product.feature.name | class_name | metadata.version |
---|---|---|---|---|---|
CloudTrail Lambda Data Events | CloudTrail | AWS | Data | API Activity | 1.1.0 |
CloudTrail Management Events | CloudTrail | AWS | Management | API Activity, Authentication, Account Change | 1.1.0 |
CloudTrail S3 Data Events | CloudTrail | AWS | Data | API Activity | 1.1.0 |
Route 53 | Route 53 | AWS | Resolver Query Logs | DNS Activity | 1.1.0 |
VPC Flow Logs | Amazon VPC | AWS | Flowlogs | Network Activity | 1.1.0 |
EKS Audit Logs | Amazon EKS | AWS | Elastic Kubernetes Service | API Activity | 1.1.0 |
AWS WAFv2 Logs | AWS WAF | AWS | - | HTTP Activity | 1.1.0 |
CloudTrail の管理イベント(CloudTrail Management Events)の場合は、API Activity
, Authentication
, Account Change
の3つのクラス(class_name
)にマッピングされています。
このうちクラス API Activity
はカテゴリー Application Activity
にクラス Authentication
とクラス Account Change
はカテゴリー Identity & Access Management
に所属しているので、dl_application_activity_index
と dl_identity_access_management_index
の data lake index に保管されていることになります。
もう一点テーブルから確認しておくと、CloudTrail の管理イベントは、metadata.product.feature.name
= Management
と metadata.product.name
= CloudTrail
にマッピングされていることが分かります。
以下のSPL文で CloudTrail の管理イベントを検索してみます。
(index=dl_application_activity_index OR index=dl_identity_access_management_index) AND metadata.product.feature.name=Management AND metadata.product.name=CloudTrail
下記のように、CloudTrail の管理イベントを検索することができました。
ただ、OCSF の世界では、ログソースが〇〇
でと検索ロジックを考えるのではなく、OCSF のカテゴリーやクラス単位で検索ロジックを組むことで、ログソースではなく、セキュリティ観点でのどんな タイプ のログで検索したい、などと出来るので、異種のログ間を横断的にかつセキュリティ分析観点でロジックを組んでいくことができます。
これが、OCSF で正規化する一番のモチベーションです。
下記のドキュメントのクエリ例を参考にしてみます。
Example Security Lake queries for CloudTrail data - Amazon Security Lake
(過去7日間のAWSサービスに対する不正な試み)
参考ですが、Amazon Athena を代表にSQLだと以下のようなクエリです。
SELECT
time_dt,
api.service.name,
api.operation,
api.response.error,
api.response.message,
api.response.data,
cloud.region,
actor.user.uid,
src_endpoint.ip,
http_request.user_agent
FROM "amazon_security_lake_glue_db_us_east_1"."amazon_security_lake_table_us_east_1_cloud_trail_mgmt_2_0"
WHERE time_dt BETWEEN CURRENT_TIMESTAMP - INTERVAL '7' DAY AND CURRENT_TIMESTAMP
AND api.response.error in (
'Client.UnauthorizedOperation',
'Client.InvalidPermission.NotFound',
'Client.OperationNotPermitted',
'AccessDenied')
ORDER BY time desc
LIMIT 25
SPL文だと以下のように検索可能です。
index=* metadata.product.feature.name=Management api.response.error IN ("Client.UnauthorizedOperation","Client.InvalidPermission.NotFound","Client.OperationNotPermitted","AccessDenied") earliest=-7d
| table _time, api.service.name, api.operation, api.response.error, api.response.message, api.response.data, cloud.region, actor.user.uid, src_endpoint.ip, http_request.user_agent
| sort 25 - _time
(過去7日間の全てのIAMアクティビティ)
同じく参考、SQL
SELECT *
FROM "amazon_security_lake_glue_db_us_east_1"."amazon_security_lake_table_us_east_1_cloud_trail_mgmt_2_0"
WHERE time_dt BETWEEN CURRENT_TIMESTAMP - INTERVAL '7' DAY AND CURRENT_TIMESTAMP
AND api.service.name = 'iam.amazonaws.com'
ORDER BY time desc
LIMIT 25
SPLだと以下のようにクエリします。
index=* metadata.product.feature.name=Management api.service.name="iam.amazonaws.com" earliest=-7d
| sort 25 = _time
| table *
今度は、Federated Index
に対してダイレクトクエリをやってみます。
同じく OCSF で正規化されたフィールドが利用可能ですが、インデックスの部分が data lake index
とは異なる点に注意です。
Federated Index
では、AWS Glue table が Splunk のインデックスとイコールになります。
また sdselect
というコマンドによる検索となり、SQLベースの検索方法に変わります。
data lake index
で試したクエリと同じものを、今度は federated index
で検索します。
(過去7日間のAWSサービスに対する不正な試み)
参考に Amazon Athena を代表にSQLだと以下のようなクエリです。
SELECT
time_dt,
api.service.name,
api.operation,
api.response.error,
api.response.message,
api.response.data,
cloud.region,
actor.user.uid,
src_endpoint.ip,
http_request.user_agent
FROM "amazon_security_lake_glue_db_us_east_1"."amazon_security_lake_table_us_east_1_cloud_trail_mgmt_2_0"
WHERE time_dt BETWEEN CURRENT_TIMESTAMP - INTERVAL '7' DAY AND CURRENT_TIMESTAMP
AND api.response.error in (
'Client.UnauthorizedOperation',
'Client.InvalidPermission.NotFound',
'Client.OperationNotPermitted',
'AccessDenied')
ORDER BY time desc
LIMIT 25
SPL文だと以下のように検索可能です。
| sdselect
time_dt,
api.service.name,
api.operation,
api.response.error,
api.response.message,
api.response.data,
cloud.region,
actor.user.uid,
src_endpoint.ip,
http_request.user_agent
FROM federated:dlf_my-federated_amazon_security_lake_table_us_east_1_cloud_trail_mgmt_2_0_index
WHERE api.response.error = "Client.UnauthorizedOperation" OR api.response.error = "Client.InvalidPermission.NotFound" OR api.response.error = "Client.OperationNotPermitted" OR api.response.error = "Client.OperationNotPermitted" OR api.response.error = "AccessDenied" AND _time > relative_time(now(), "-7d")
LIMIT 25
現時点では、sdselect
では WHERE
の条件式に in
がサポートされていません。
ですので、api.response.error
の条件を全て OR
で並べて書く必要があります。
また、時間を扱う場合は、time_dt
(Glueカタログで定義されていたタイムスタンプ)の代わりに Splunk 内部で使えるよう変換された _time
を利用する必要があります。
AND _time > relative_time(now(), "-7d")
のようにして使っています。
時間指定については、Splunk検索画面のタイムピッカーを使うことができますので、そちらを使う方が直感的で簡単です。(今回は参考元のSQLサンプルクエリと比較するためにあえて、WHERE
で時間指定しています。)
また、SPL文内に時間指定を書いた場合は、タイムピッカーよりも条件が優先されます。
下記の表示結果をよく見ていただくと分かるのですが、表示上はタイムピッカーで指定した時間で検索されていそうに見えます。
実際には、SPL文で指定した、7日前から現在までの時間
の条件で検索されています。
この点については少し分かりにくい UI かなと思いましたので、今後の改善に期待です。
こちらも data lake index
で試したクエリと同じものを、今度は federated index
で検索します。
(過去7日間の全てのIAMアクティビティ)
同じく参考、SQL
SELECT *
FROM "amazon_security_lake_glue_db_us_east_1"."amazon_security_lake_table_us_east_1_cloud_trail_mgmt_2_0"
WHERE time_dt BETWEEN CURRENT_TIMESTAMP - INTERVAL '7' DAY AND CURRENT_TIMESTAMP
AND api.service.name = 'iam.amazonaws.com'
ORDER BY time desc
LIMIT 25
SPLだと以下のようにクエリします。
| sdselect *
FROM federated:dlf_my-federated_amazon_security_lake_table_us_east_1_cloud_trail_mgmt_2_0_index
WHERE _time > relative_time(now(), "-7d")
AND api.service.name = "iam.amazonaws.com"
ORDERBY time_dt desc
LIMIT 25
こちらも検索することができました。
検索のやり方については、もっと色々と試してみる必要があるなと思いましたが、またの機会にして今回はこの程度にしようと思います。
まとめ
Amazon Security Lake からのシームレスなデータ取り込みと、ダイレクト検索を Splunk Cloud で実施することができました。
ユースケースごとで柔軟な使い方ができるようになったと思う一方、sdselect
は従来の SPLクエリ
とは異なるテクニックが必要かなと思いますし、今後もっと使いやすくなるようアップデートされていくのではと思いました。
この記事がどなたかの一助になれば幸いです。