Security HubのイベントをZabbixに連携させてみた
AWSのイベントをZabbixに連携させたい
こんにちは、のんピ(@non____97)です。
皆さんはAWSのイベントをZabbixに連携させたいと思ったことはありますか? 私はもちろんありません。皆さんもないですよね。
先日、以下記事を投稿しました。
こちらはCloudWatchアラームのイベントをZabbix Serverに送りつけるというものです。
つまりは、CloudWatchアラームで検出できない = CloudWatchメトリクスで表現されないものについてはZabbixに連携することができません。例えば、Security HubやGuardDuty、AWS Healthなどがありますね。
そのような場合も上述の記事の類似の方法で対応することが可能です。
以降その方法について紹介します。
対応方法
対応方法はEventBridge RuleでLambda関数をキックして、Zabbix SenderでCloudWatchアラームのイベントをZabbix Serverに送ります。ただそれだけです。
ポイントはZabbix Senderのホストとアイテムキーの情報をEvenBridge RuleのInput Transformerで渡すというところです。
対応方法を図示すると以下の通りです。
EventBridge Rule、Lambda関数、Zabbixの事前準備としては以下があります。
- 監視したいイベントのEventBridge RuleのInput Transformerで以下の情報をLambda関数に渡すように設定
- Zabbixのホスト名
- Zabbixのアイテムのキー名
- オリジナルのイベント
- Lambda関数の環境変数に以下を設定
- Zabbix ServerのIPアドレス
- Zabbix Serverのポート番号
- Zabbixのホストとアイテムの設定
- Zabbixのトリガー設定
CloudWatchアラームの状態が遷移した場合は以下の処理が行われます。
- EventBridgeでイベント拾う
- Input Transformerに従い、Zabbixの情報をイベントに追加してLambda関数を起動
- Lambda関数に設定された環境変数を取得
- (2)と(3)で取得した情報をもとに、Zabbix SenderでCloudWatch AlarmのイベントをJSON stringifyして送信
使用するLambda関数のコードは以下の通りです。
import boto3 import os import json import logging from pyzabbix import ZabbixMetric, ZabbixSender logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): try: logger.info(event) # Get zabbix host and item key from event. zabbix_host = event['zabbixHost'] zabbix_item_key = event['zabbixItemKey'] if zabbix_host is None or zabbix_item_key is None: logger.error("Zabbix host and item key are not properly set") return zabbix_server_ip = os.getenv('ZABBIX_SERVER_IP_ADDRESS') zabbix_server_port = int(os.getenv('ZABBIX_SERVER_PORT')) zabbix_event_data = [ZabbixMetric(zabbix_host, zabbix_item_key, json.dumps(event['event']))] zabbix_sender = ZabbixSender(zabbix_server_ip, zabbix_server_port) zabbix_sender_response = zabbix_sender.send(zabbix_event_data) logger.info(zabbix_sender_response) except Exception as e: logger.error("Error occurred: {}".format(e))
py-zabbix
によりLambda関数の環境変数で指定したZabbix Serverに対して、イベントに含まれるZabbixのホストとキーを使ってアイテムを送りつけます。
今回の手法は監視対象が増えた場合に以下リソースを増やすだけです。監視対象の数だけLambda関数を用意する必要はありません。
- EventBridge Rule
- Zabbix側のホストとアイテム設定
そのままイベントを送りつけると、Zabbix側で見づらい場面もあるかと思います。その場合はEventBridge のInput TransformerやStep Functionsでイベントを整形すると良いでしょう。
Security Hub、GuardDuty、IAM Access Analyzerについては、セキュアアカウントをお申し込みいただいた場合やCMPからオプトインする「Amazon EventBridge通知設定」によって、先述のイベントが人間が見やすい形に整形されます。
抜粋 : [安全なAWSセキュリティ運用ナレッジ2022]セキュアアカウントの使い方 | DevelopersIO
こちらの整形後のイベントをLambda関数でZabbixに送りつける形でも良いと思います。
やってみた
検証環境
検証環境の構成図は以下の通りです。
今回はSecurity HubとGuardDutyのイベントを検知するようにしています。
こちらの検証環境は基本的にAWS CDKで用意しました。使用したコードは以下にあります。
先述の記事で使用したコードをforkして、イベント連携部分を追加しています。そのため、先述の記事と同様にデプロイ後はLambda関数のENIにElastic IPアドレスを手動で割り当てます。
Zabbixのホストとアイテムの作成
Zabbix Serverのセットアップは先述の記事と全く同じなので省略します。
Zabbixのホストとアイテムの作成から行います。
ZabbixのWebコンソールからConfiguration
-Hosts
のCreate host
をクリックします。
ホスト名とグループを入力および選択してAdd
をクリックします。
続いてアイテムの登録です。
適当なTypeをZabbix trapperにして適当なキー名を設定します。
GuardDuty用のアイテムも同様に設定します。
動作確認
それでは動作確認を行います。
GuardDutyは適当にサンプルイベントを生成させます。
サンプルイベントの生成方法は以下記事をご覧ください。
Security HubはSSM Documentを作成して、そちらをパブリックに公開させます。
早くSecurity Hubで検知して欲しいので関連するAWS Config Ruleであるsecurityhub-ssm-document-not-public-87050418
を手動で再評価させます。
Lambda関数のログを確認すると以下のようにログストリームが作成されていました。
記録されたログは以下のようになっていました。
START RequestId: 46d67f84-8bdd-491e-b4b4-7b9948c9a639 Version: $LATEST [INFO] 2023-08-09T01:15:12.070Z 46d67f84-8bdd-491e-b4b4-7b9948c9a639 {'event': {'version': '0', 'id': 'e3fbb9d3-cd37-db05-cf12-8cffafb37f9b', 'detail-type': 'Security Hub Findings - Imported', 'source': 'aws.securityhub', 'account': '<AWSアカウントID>', 'time': '2023-08-09T01:15:11Z', 'region': 'us-east-1', 'resources': ['arn:aws:securityhub:us-east-1::product/aws/guardduty/arn:aws:guardduty:us-east-1:<AWSアカウントID>:detector/00c2e1501b6f04f7be8f4d67c45ece60/finding/8c5fd1d14a8d467ca7a0686ffa721036'], 'detail': {'findings': [{'ProductArn': 'arn:aws:securityhub:us-east-1::product/aws/guardduty', 'Types': ['TTPs/Command and Control/CryptoCurrency:EC2-BitcoinTool.B', 'Effects/Resource Consumption/CryptoCurrency:EC2-BitcoinTool.B'], 'SourceUrl': 'https://us-east-1.console.aws.amazon.com/guardduty/home?region=us-east-1#/findings?macros=current&fId=8c5fd1d14a8d467ca7a0686ffa721036', 'Description': 'EC2 instance i-99999999 is communicating outbound with a known Bitcoin-related IP address 198.51.100.0.', 'ProductName': 'GuardDuty', 'FirstObservedAt': '2023-08-09T01:13:43.000Z', 'CreatedAt': '2023-08-09T01:13:43.115Z', 'LastObservedAt': '2023-08-09T01:13:43.000Z', 'CompanyName': 'Amazon', 'FindingProviderFields': {'Types': ['TTPs/Command and Control/CryptoCurrency:EC2-BitcoinTool.B', 'Effects/Resource Consumption/CryptoCurrency:EC2-BitcoinTool.B'], 'Severity': {'Normalized': 60, 'Label': 'HIGH', 'Product': 8}}, 'ProductFields': {'aws/guardduty/service/additionalInfo/threatListName': 'GeneratedFindingThreatListName', 'aws/guardduty/service/action/networkConnectionAction/remotePortDetails/portName': 'Unknown', 'aws/guardduty/service/archived': 'false', 'aws/guardduty/service/action/networkConnectionAction/remoteIpDetails/organization/asnOrg': 'GeneratedFindingASNOrg', 'aws/guardduty/service/additionalInfo/value': '{"threatListName":"GeneratedFindingThreatListName","sample":true}', 'aws/guardduty/service/action/networkConnectionAction/remoteIpDetails/geoLocation/lat': '0', 'aws/guardduty/service/action/networkConnectionAction/remoteIpDetails/ipAddressV4': '198.51.100.0', 'aws/guardduty/service/action/networkConnectionAction/remoteIpDetails/geoLocation/lon': '0', 'aws/guardduty/service/action/networkConnectionAction/blocked': 'false', 'aws/guardduty/service/action/networkConnectionAction/remotePortDetails/port': '8333', 'aws/guardduty/service/action/networkConnectionAction/remoteIpDetails/country/countryName': 'United States', 'aws/guardduty/service/serviceName': 'guardduty', 'aws/guardduty/service/action/networkConnectionAction/localIpDetails/ipAddressV4': '10.0.0.23', 'aws/guardduty/service/detectorId': '00c2e1501b6f04f7be8f4d67c45ece60', 'aws/guardduty/service/action/networkConnectionAction/remoteIpDetails/organization/org': 'GeneratedFindingORG', 'aws/guardduty/service/action/networkConnectionAction/connectionDirection': 'OUTBOUND', 'aws/guardduty/service/eventFirstSeen': '2023-08-09T01:13:43.000Z', 'aws/guardduty/service/eventLastSeen': '2023-08-09T01:13:43.000Z', 'aws/guardduty/service/evidence/threatIntelligenceDetails.0_/threatListName': 'GeneratedFindingThreatListName', 'aws/guardduty/service/action/networkConnectionAction/localPortDetails/portName': 'Unknown', 'aws/guardduty/service/action/actionType': 'NETWORK_CONNECTION', 'aws/guardduty/service/action/networkConnectionAction/remoteIpDetails/city/cityName': 'GeneratedFindingCityName', 'aws/guardduty/service/resourceRole': 'TARGET', 'aws/guardduty/service/action/networkConnectionAction/localPortDetails/port': '2000', 'aws/guardduty/service/action/networkConnectionAction/protocol': 'TCP', 'aws/guardduty/service/count': '1', 'aws/guardduty/service/additionalInfo/sample': 'true', 'aws/guardduty/service/action/networkConnectionAction/remoteIpDetails/organization/asn': '-1', 'aws/guardduty/service/additionalInfo/type': 'default', 'aws/guardduty/service/action/networkConnectionAction/remoteIpDetails/organization/isp': 'GeneratedFindingISP', 'aws/guardduty/service/evidence/threatIntelligenceDetails.0_/threatNames.0_': 'GeneratedFindingThreatName', 'aws/securityhub/FindingId': 'arn:aws:securityhub:us-east-1::product/aws/guardduty/arn:aws:guardduty:us-east-1:<AWSアカウントID>:detector/00c2e1501b6f04f7be8f4d67c45ece60/finding/8c5fd1d14a8d467ca7a0686ffa721036', 'aws/securityhub/ProductName': 'GuardDuty', 'aws/securityhub/CompanyName': 'Amazon'}, 'SchemaVersion': '2018-10-08', 'GeneratorId': 'arn:aws:guardduty:us-east-1:<AWSアカウントID>:detector/00c2e1501b6f04f7be8f4d67c45ece60', 'Sample': True, 'RecordState': 'ACTIVE', 'Title': 'EC2 instance i-99999999 communicating with a known Bitcoin-related IP address.', 'Workflow': {'Status': 'NEW'}, 'Severity': {'Normalized': 60, 'Label': 'HIGH', 'Product': 8}, 'UpdatedAt': '2023-08-09T01:13:43.115Z', 'WorkflowState': 'NEW', 'AwsAccountId': '<AWSアカウントID>', 'Region': 'us-east-1', 'Id': 'arn:aws:guardduty:us-east-1:<AWSアカウントID>:detector/00c2e1501b6f04f7be8f4d67c45ece60/finding/8c5fd1d14a8d467ca7a0686ffa721036', 'Resources': [{'Partition': 'aws', 'Type': 'AwsEc2Instance', 'Details': {'AwsEc2Instance': {'Type': 'm3.xlarge', 'VpcId': 'GeneratedFindingVPCId', 'ImageId': 'ami-99999999', 'IpV4Addresses': ['10.0.0.1', '198.51.100.0'], 'SubnetId': 'GeneratedFindingSubnetId', 'LaunchedAt': '2016-08-02T02:05:06.000Z', 'IamInstanceProfileArn': 'arn:aws:iam::<AWSアカウントID>:example/instance/profile'}}, 'Region': 'us-east-1', 'Id': 'arn:aws:ec2:us-east-1:<AWSアカウントID>:instance/i-99999999', 'Tags': {'GeneratedFindingInstanceTag1': 'GeneratedFindingInstanceValue1', 'GeneratedFindingInstanceTag2': 'GeneratedFindingInstanceTagValue2', 'GeneratedFindingInstanceTag3': 'GeneratedFindingInstanceTagValue3', 'GeneratedFindingInstanceTag4': 'GeneratedFindingInstanceTagValue4', 'GeneratedFindingInstanceTag5': 'GeneratedFindingInstanceTagValue5', 'GeneratedFindingInstanceTag6': 'GeneratedFindingInstanceTagValue6', 'GeneratedFindingInstanceTag7': 'GeneratedFindingInstanceTagValue7', 'GeneratedFindingInstanceTag8': 'GeneratedFindingInstanceTagValue8', 'GeneratedFindingInstanceTag9': 'GeneratedFindingInstanceTagValue9'}}], 'ProcessedAt': '2023-08-09T01:15:05.315Z'}]}}, 'zabbixHost': 'AWS Events', 'zabbixItemKey': 'aws.event.guardduty'} [INFO] 2023-08-09T01:15:12.091Z 46d67f84-8bdd-491e-b4b4-7b9948c9a639 { "processed": 1, "failed": 0, "total": 1, "time": "0.000303", "chunk": 1 } END RequestId: 46d67f84-8bdd-491e-b4b4-7b9948c9a639 REPORT RequestId: 46d67f84-8bdd-491e-b4b4-7b9948c9a639 Duration: 42.00 ms Billed Duration: 43 ms Memory Size: 128 MB Max Memory Used: 62 MB
エラーにはならず、Zabbix Senderの実行ができていそうですね。
ZabbixのWebコンソールからGuardDutyのアイテムを確認してみます。
このようなイベントが大量に登録されていました。実際に運用をする際は整形しないと見づらそうです。
Security Hubのアイテムも確認してみましょう。
こちらも問題なくアイテムにデータが登録されています。
どうしてもZabbixにAWSのイベントを送りつけたいという時に
Security HubのイベントをZabbixに連携させてみました。
監視をするにあたって、Zabbix側の設定が必要になるためオススメはしませんが。このような実装をせざるを得ない場面もあると思うので検証しました。
特段要件がなければ素直にAmazon SNSやAWS Chatbot、AWS User NotificationsなどAWSのサービスを使ってメールやSlack、Teamsに通知をするのが良いでしょう。
散々煽っていますがZabbixはサーバーやネットワーク機器を監視する際は非常に有用なソフトウェアです。私もお世話になりました。
ただし、AWSとの連携はどうしても不得手です。適材適所でサービスやツールを使い分けのがベターです。相性が悪いものを頑張って作り込もうとすると、むしろコストがかかったり、不幸になる人が出てきたりします。
この記事が誰かの助けになれば幸いです。
以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!