SIEM on Amazon OpenSearch Serviceを使う機会があったのですが、セキュリティ調査は奥が深い!!もっと勉強がしたい!!! と思っていたところ、ワークショップを発見しました。
どうせならじっくりゆっくり学習したいので、AWS上ではなくローカル環境で構築してみました。
SIEM on Amazon OpenSearch Serviceを使う機会があったのですが、セキュリティ調査は奥が深い!!もっと勉強がしたい!!! と思っていたところ、ワークショップを発見しました。
どうせならじっくりゆっくり学習したいので、AWS上ではなくローカル環境で構築してみました。
過去にQiitaに投稿した内容のアーカイブです。
arm64向けのKibanaのコンテナイメージの作成に成功したので、Kubernetes上で構築してみました。 (コンテナイメージの作成方法とDocker Composeでの構築はこちらを参照)
wget https://get.helm.sh/helm-v3.3.1-linux-arm64.tar.gz
tar zxvf helm-v3.3.1-linux-arm64.tar.gz
cd linux-arm64/
sudo install helm /usr/local/bin
動作確認
$ helm version
version.BuildInfo{Version:"v3.3.1", GitCommit:"249e5215cde0c3fa72e27eb7a30e8d55c9696144", GitTreeState:"clean", GoVersion:"go1.14.7"}
$
Elastic Stack Kubernetes Helm Charts https://github.com/elastic/helm-charts
helm repo add elastic https://helm.elastic.co
$ helm search repo elastic
NAME CHART VERSION APP VERSION DESCRIPTION
elastic/elasticsearch 7.9.1 7.9.1 Official Elastic helm chart for Elasticsearch
elastic/apm-server 7.9.1 7.9.1 Official Elastic helm chart for Elastic APM Server
elastic/filebeat 7.9.1 7.9.1 Official Elastic helm chart for Filebeat
elastic/kibana 7.9.1 7.9.1 Official Elastic helm chart for Kibana
elastic/logstash 7.9.1 7.9.1 Official Elastic helm chart for Logstash
elastic/metricbeat 7.9.1 7.9.1 Official Elastic helm chart for Metricbeat
$
Helmのインストールの前にPersistentVolumeを作成します。
apiVersion: v1
kind: PersistentVolume
metadata:
name: es-pv-volume
labels:
type: local
app: elasticsearch-master
spec:
storageClassName: standard
capacity:
storage: 1Gi
persistentVolumeReclaimPolicy: Delete
accessModes:
- ReadWriteOnce
hostPath:
path: "/data/elasticsearch"
/data/elasticsearchディレクトリを自動生成させると、rootユーザーが所有者となってPodの起動が失敗しましたので、先にホストOS側で準備しておきます
mkdir /data/elasticsearch
chown 1000:1000 /data/elasticsearch
minikube環境向けのサンプルがありますので、そちらを元にしました。imageTag
とreplicas
だけ独自に足しました。
https://github.com/elastic/helm-charts/tree/master/elasticsearch/examples/minikube
---
imageTag: 7.9.1
replicas: 1
## Permit co-located instances for solitary minikube virtual machines.
antiAffinity: "soft"
## Shrink default JVM heap.
esJavaOpts: "-Xmx128m -Xms128m"
## Allocate smaller chunks of memory per pod.
resources:
requests:
cpu: "100m"
memory: "512M"
limits:
cpu: "1000m"
memory: "512M"
## Request smaller persistent volumes.
volumeClaimTemplate:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "standard"
resources:
requests:
storage: 100M
helm install elasticsearch elastic/elasticsearch --values ./values.yml
うまく行けば一式起動します
$ kubectl get service,statefulset,pod,persistentvolumeclaim,persistentvolume --namespace=default -l app=elasticsearch-master
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/elasticsearch-master ClusterIP 10.103.52.98 <none> 9200/TCP,9300/TCP 6h38m
service/elasticsearch-master-headless ClusterIP None <none> 9200/TCP,9300/TCP 6h38m
NAME READY AGE
statefulset.apps/elasticsearch-master 1/1 6h38m
NAME READY STATUS RESTARTS AGE
pod/elasticsearch-master-0 1/1 Running 2 6h38m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/elasticsearch-master-elasticsearch-master-0 Bound es-pv-volume 1Gi RWO standard 6h38m
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/es-pv-volume 1Gi RWO Delete Bound default/elasticsearch-master-elasticsearch-master-0 standard 6h43m
$
Kibanaもvalues.ymlを用意します。
Kibanaはarm64向けコンテナイメージが提供されていないので、自前で作成しました。 (詳しい説明はこちら)
---
image: "ghcr.io/moritalous/ghcr/kibana-arm64"
imageTag: 7.9.1
service:
type: NodePort
port: 5601
nodePort: 30601
helm install kibana elastic/kibana --values ./values.yml
起動確認
$ kubectl get service,deployment,pod --namespace=default -l app=kibana
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kibana-kibana NodePort 10.109.131.74 <none> 5601:30601/TCP 8h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kibana-kibana 1/1 1 1 8h
NAME READY STATUS RESTARTS AGE
pod/kibana-kibana-56b7b6c95c-vj6sv 1/1 Running 0 7h37m
$
http://raspberrypi.local:30601/
過去にQiitaに投稿した内容のアーカイブです。
正月休みに勉強しようと思って、Elasticsearch実践ガイドを買いました。 Amazonで買ったけど、インプレスで電子書籍版が半額😱😱😱(期間限定のようです) 初心者の私にはちょうどいい入門書でした!
前からやりたかった、Kibanaを使わずにKibanaっぽいグラフを作ることができました~!
OS: Ubuntu 18.04.1 (on VirtualBox) ホスト名:ubuntu.local
https://www.elastic.co/guide/en/elasticsearch/reference/current/deb.html https://www.elastic.co/guide/en/kibana/current/deb.html https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-installation.html を参考に。
sudo apt update
sudo apt install openjdk-8-jre-headless
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
sudo apt install apt-transport-https
OSS版をインストールしたかったのでこちら
echo "deb https://artifacts.elastic.co/packages/oss-6.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-6.x.list
sudo apt update
sudo apt install elasticsearch-oss kibana-oss metricbeat-oss
## localhost以外からのアクセスを許可する
network.host: 0.0.0.0
http.port: 9200
transport.host: localhost
transport.tcp.port: 9300
## JavaScriptからのCORSアクセスを許可する
http.cors.enabled: true
http.cors.allow-origin: "*"
## localhost以外からのアクセスを許可する
server.host: "0.0.0.0"
sudo systemctl enable elasticsearch.service
sudo systemctl enable kibana.service
sudo systemctl start elasticsearch.service
sudo systemctl start kibana.service
http://ubuntu.local:9200
にアクセス
レスポンスがかえって来たら成功。
{
"name" : "fXjgLKE",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "WGnyRmUuSZemH70_ABZ3pg",
"version" : {
"number" : "6.5.4",
"build_flavor" : "oss",
"build_type" : "deb",
"build_hash" : "d2ef93d",
"build_date" : "2018-12-17T21:17:40.758843Z",
"build_snapshot" : false,
"lucene_version" : "7.5.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
Kibanahttp://ubuntu.local:5601
にアクセス。Kibanaの画面が表示されたら成功。
Kibanaにダッシュボードを追加
metricbeat setup --dashboards
sudo systemctl enable metricbeat.service
sudo systemctl start metricbeat.service
Metricbeatのデータが上手くElasticsearchに入れば、Kibanaでこんな画面が見れます
Google Charts ( https://developers.google.com/chart/?hl=ja ) でグラフ化します。
ElasticsearchのREST APIで検索します。Aggregationでいい感じに平均値を取得します。
POST http://ubuntu.local:9200/metricbeat-*/_search
{
"size": 0,
"query": {
"bool": {
"filter": {
"range": {
"@timestamp": {
"gte": "now-7d"
}
}
},
"must": [{
"match": {
"metricset.name": "cpu"
}
}, {
"match": {
"beat.hostname": "ubuntu"
}
}]
}
},
"aggs": {
"date_histogram": {
"date_histogram": {
"field": "@timestamp",
"interval": "10m"
},
"aggs": {
"system_cpu_total_pct": {
"avg": {
"field": "system.cpu.total.pct"
}
}
}
}
}
}
{
"took" : 16,
"timed_out" : false,
"_shards" : {
"total" : 4,
"successful" : 4,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 9239,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"date_histogram" : {
"buckets" : [
{
"key_as_string" : "2019-01-01T14:50:00.000Z",
"key" : 1546354200000,
"doc_count" : 59,
"system_cpu_total_pct" : {
"value" : 1.2820169491525424
}
},
{
"key_as_string" : "2019-01-01T15:00:00.000Z",
"key" : 1546354800000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.7167333333333333
}
},
{
"key_as_string" : "2019-01-01T15:10:00.000Z",
"key" : 1546355400000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.6058666666666668
}
},
{
"key_as_string" : "2019-01-01T15:20:00.000Z",
"key" : 1546356000000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.5145166666666667
}
},
{
"key_as_string" : "2019-01-01T15:30:00.000Z",
"key" : 1546356600000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.5042166666666666
}
},
{
"key_as_string" : "2019-01-03T02:10:00.000Z",
"key" : 1546481400000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.09896666666666668
}
},
{
"key_as_string" : "2019-01-03T02:20:00.000Z",
"key" : 1546482000000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.10701666666666668
}
},
{
"key_as_string" : "2019-01-03T02:30:00.000Z",
"key" : 1546482600000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.09681666666666668
}
},
{
"key_as_string" : "2019-01-03T02:40:00.000Z",
"key" : 1546483200000,
"doc_count" : 60,
"system_cpu_total_pct" : {
"value" : 0.13956666666666667
}
},
{
"key_as_string" : "2019-01-03T02:50:00.000Z",
"key" : 1546483800000,
"doc_count" : 27,
"system_cpu_total_pct" : {
"value" : 0.09644444444444444
}
}
]
}
}
}
このJSONをいい感じに変換して、Google Chartsで折れ線グラフにしてみます。
できました。
ソースはこんな感じで
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<div id="chart" style="width: 900px; height: 500px"></div>
</body>
</html>
google.charts.load('current', {
'packages': ['corechart']
});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var url = 'http://ubuntu.local:9200/metricbeat-*/_search'
var data = {
"size": 0,
"query": {
"bool": {
"filter": {
"range": {
"@timestamp": {
"gte": "now-7d"
}
}
},
"must": [{
"match": {
"metricset.name": "cpu"
}
}, {
"match": {
"beat.hostname": "ubuntu"
}
}]
}
},
"aggs": {
"date_histogram": {
"date_histogram": {
"field": "@timestamp",
"interval": "10m"
},
"aggs": {
"system_cpu_total_pct": {
"avg": {
"field": "system.cpu.total.pct"
}
}
}
}
}
}
fetch(url, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
return response.json()
}).then(function (response) {
var data = []
data.push(['日付', 'CPU使用率'])
for (const date_histogram of response.aggregations.date_histogram.buckets) {
var key = date_histogram.key
var value = date_histogram.system_cpu_total_pct.value
data.push([new Date(key), value * 100])
}
return data
}).then(function (response) {
var data = google.visualization.arrayToDataTable(response)
var options = {
title: 'CPU使用率',
hAxis: {
format: 'M/d H:mm'
},
legend: {
position: 'bottom'
}
};
var chart = new google.visualization.AreaChart(document.getElementById('chart'));
chart.draw(data, options);
})
}
初心者のためのRest APIから覚えるElasticsearch https://qiita.com/_bsoo/items/d880831e644175782ee0
elasticsearchでlocalhost以外からのアクセスを許可する方法 https://qiita.com/fuku2014/items/c2e2ffc07da5e2d2ba05
過去にQiitaに投稿した内容のアーカイブです。
AWS IoTのデータをKibanaに表示するを実際にやってみました。
記事の投稿以降、AWS IoTが直接Elasticsearch Serviceと連携できる様になったとのことで、そのあたりも試しました。
【アップデート】 AWS IoT が Elasticsearch Service と CloudWatch に連携できるようになりました https://aws.amazon.com/jp/blogs/news/aws-iot-update/
なんと、サーバー側はノンコーディングです。
元記事と基本的に同じです。
まずは、立ち上がりが遅いElasticsearchを先に立ち上げておきましょう。
Domain nameを plant-sensor
、Instance typeはt2.micro.elasticsearch
が選べなかったのでt2.small.elasticsearch (Free tire eligible)
、Instance countは 1
、Strage typeは EBS
に設定します。
Kibana のURLをクリックするとKibana4の画面が表示されます。EndpointのURLはAWS IoTで使います(自動で設定されます)。
元記事の通りしようとしても、画面構成が違うのか、メニューが見つかりません。なので、順を追って解説します。
(こんな感じでしたっけ?)
「Get started」を押します。そして、左メニューの[Registory]->[Things]を選択します。 「Register a thing」を押します。
plant-sensor
という名前のThingを作成。
左メニューの[Security]を選び、「Create certificate」を選択します。
色々ダウンロードできますので、一旦すべてダウンロードした後、「Activate」を押します。
ダウンロードできるもの
続いてPolicyを作成。トップ画面の左メニューの[Policies]を選び、「Create a Policy」を選択します。
名前をつけ、とりあえずActionはiot:*
としました。Resource ARNについてですが、キャプチャではtopic/replaceWithATopic
となってますが、plant/sensors
または*/*
などに変えましょう。
certificateとPolicyの紐付け 左メニューの[Certificates]を再度選び、先程作成したceritificateを選択。「Actions」メニューの「Attatch policy」を選ぶ。
同様に、「Attatch thing」も行います。
最後にRuleを作成します。トップ画面の左メニューの[Rules]を選び、「Create a rule」を選択します。
今回は plant/sensors
というトピック名でデータを飛ばそうと思うので、Topic filterに plant/sensors
を設定します。
Actionの指定は、「Add Action」ボタンを押して行います。
2017/3/14時点で以下のActionが選べます。一番下の「Elasticsearch Service」を選びます。
Elasticsearch Service用の設定画面が出ます。
IDに${newuuid()}
、Indexにtimestamp
、Typeにtimestamp
と指定し、IAMロールも追加します。
これで、Thing, Certificate, Policy, Ruleが作成できました。元記事のように一覧では表示されないようです。
元記事の通り、plant-sensor.jsを作成します。 そして実行です。
実行してみましょう。
$ npm init
$ npm install --save aws-iot-device-sdk
$ node plant-sensor.js
connect
{"timestamp":"2017-03-14T15:19:47.401Z","humidity":45,"temperature":19,"lux":32701,"moisture":309}
{"timestamp":"2017-03-14T15:19:48.405Z","humidity":43,"temperature":19,"lux":33473,"moisture":309}
{"timestamp":"2017-03-14T15:19:49.406Z","humidity":44,"temperature":19,"lux":30713,"moisture":295}
{"timestamp":"2017-03-14T15:19:50.408Z","humidity":42,"temperature":20,"lux":31499,"moisture":296}
{"timestamp":"2017-03-14T15:19:51.414Z","humidity":46,"temperature":20,"lux":30687,"moisture":315}
{"timestamp":"2017-03-14T15:19:52.417Z","humidity":46,"temperature":20,"lux":31960,"moisture":302}
{"timestamp":"2017-03-14T15:19:53.420Z","humidity":45,"temperature":20,"lux":30782,"moisture":301}
Kibanaを起動すると、エラー画面のような形となりますが、初期設定ができていないからだと思います。
Index name or pattern
のところにtimestamp
といれると、設定できます。
Discoverタブを見てみると、ちゃんとデータが来ているのを確認できます。
では、チャートを作ってみましょう。Visualizeタブで、以下の様な感じでグラフを作成します。
最後にダッシュボードを作成します。Dashboardタブを選択して、Add visualization で先ほど作成したチャートをポンポンと選択していくだけです!
元記事を作成された、@hideyuki さん、勝手に更新版を投稿してしまいました。ありがとうございます。