# Building a SIEM - 5 - Building Grafana
04-30-2025
Tags: #Grafana #SIEM
Links: [[Building a SIEM - 4 - Graylog Inputs, Wazuh Tuning, and Agents]]
---
**Table of Contents**
- [[#Introduction|Introduction]]
- [[#Installing Grafana on Ubuntu|Installing Grafana on Ubuntu]]
- [[#Installing Grafana on Ubuntu#Enabling HTTPS with Custom Certs|Enabling HTTPS with Custom Certs]]
- [[#Setting Up Grafana For Wazuh Access|Setting Up Grafana For Wazuh Access]]
- [[#On Grafana, On Dashboard|On Grafana, On Dashboard]]
- [[#What Are Data Links in Grafana?|What Are Data Links in Grafana?]]
- [[#Using Grafana|Using Grafana]]
- [[#Building A Dashboard|Building A Dashboard]]
- [[#Building A Dashboard#Other Panels I Created|Other Panels I Created]]
- [[#Conclusion|Conclusion]]
- [[#References|References]]
---
## Introduction
SIEM (Security Information and Event Management) systems are essential for security monitoring, incident detection, and response. While Wazuh offers native dashboards built on Kibana, many users find Kibana to be sluggish and limiting when it comes to customization.
Grafana, on the other hand, provides a faster, more flexible experience, especially for creating beautiful and performant dashboards tailored to specific needs. This blog post documents my journey setting up Grafana to visualize Wazuh logs and building a SOC-style dashboard with powerful security insights.
## Installing Grafana on Ubuntu
Complete the following steps to install Grafana OSS from the APT repository:
1. Install the prerequisite packages:
```bash
sudo apt-get install -y apt-transport-https software-properties-common wget
```
2. Import the GPG key:
```bash
sudo mkdir -p /etc/apt/keyrings/
wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg > /dev/null
```
3. To add a repository for stable releases, run the following command:
```bash
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
```
4. Run the following command to update the list of available packages:
```bash
sudo apt-get update
```
5. To install Grafana OSS, run the following command:
```bash
sudo apt-get install grafana
```
6. Start and enable the service, then check on its status
```shell
sudo systemctl daemon-reload
sudo systemctl enable --now grafana-server
sudo systemctl status grafana-server
```
### Enabling HTTPS with Custom Certs
To secure your Grafana instance with HTTPS using Wazuh Indexer certs:
1. Create a secure folder for Grafana certs:
```
sudo mkdir /etc/grafana/certs
sudo cp /etc/wazuh-indexer/certs/wazuh-indexer.pem /etc/grafana/certs/
sudo cp /etc/wazuh-indexer/certs/wazuh-indexer-key.pem /etc/grafana/certs/
```
2. Set correct ownership and permissions:
```
sudo chown -R grafana:grafana /etc/grafana/certs/
sudo chmod 400 /etc/grafana/certs/*
```
Open the `/etc/grafana/grafana.ini` file to apply configuration settings to your Grafana instance.
remove the semi-colon (;) to uncomment these lines:
- protocol = https
- http_port = 3000
- cert_file = /etc/grafana/certs/wazuh-indexer.pem
- cert_key = /etc/grafana/private/wazuh-indexer-key.pem
then
`systemctl start grafana-server`
Go to `https://<localhost>:3000` and you should see the login page, using the wazuh certificate.
- Default login credentials are `admin`:`admin`
Grafana will ask to change your password, so come up with a good passphrase!
## Setting Up Grafana For Wazuh Access
To allow Grafana to query the Wazuh Indexer:
1. **Login to Wazuh Dashboards**
2. Navigate to **Security > Roles** and create a role `grafana_role` with:
- **Cluster permissions:** `cluster_monitor`
- **Index permissions:** `read`, `indices:admin/mappings/get` on `*`
- **Tenant permissions:** `global_tenant` → `Read only`
3. **Map a user to the role:**
- Go to **Security > Internal Users**, create a user `grafana` with a password
- Go back to **Roles > grafana_role > Mapped Users**, and map the new `grafana` user to the new role.
> This setup allows Grafana read-only access to all indices. Fine-tuning permissions later will improve security.
Take note of your index name — in my case, created by Graylog, it was `castledefender`.
---
## On Grafana, On Dashboard
1. touch `Add your first data source` S
2. Scroll to the bottom, and click "Add plugins", then add the "OpenSearch" plugin and install it.
3. Create a new data source
4. Touch `OpenSearch`
5. Use the following:
1. Call it `Wazuh`
2. Connection: use `https://127.0.0.1:9200`
3. Use **Basic Auth**
4. Use the Grafana user credentials that I just created in Wazuh
5. check the **Skip TLS Verify** since I'm using self-signed certs
6. Under ElasticSearch, in **Index Name** put `<myIndexName>*` (e.g. wazuh-alerts-castledefender*)
7. In Time Field name, remove the `@` and just have `timestamp`
8. Make sure to click on the `Get Version and Save` button to fill in what version you are using.
9. In logs, Message field name, put `rule_description`
10. level field name, put `syslog_level`
11. Datalinks enable you to click on data points and get context fast:
Put the following:
```
field: ^data_vulnerability_cve$
URL: https://nvd.nist.gov/vuln/detail/${__value.raw}
URL Label: NIST CVE Database
Field: ^_id$
URL: https://127.0.0.1:3000/explore?left=%5B%22now-6h%22,%22now%22,%22WAZUH%22,%7B%22refId%22:%22A%22,%22query%22:%22_id:${__value.raw}%22,%22alias%22:%22%22,%22metrics%22:%5B%7B%22id%22:%221%22,%22type%22:%22logs%22,%22settings%22:%7B%22limit%22:%22500%22%7D%7D%5D,%22bucketAggs%22:%5B%5D,%22timeField%22:%22timestamp%22%7D%5D
URL Label: View Event Details
```
## What Are Data Links in Grafana?
**Data Links** let you turn specific values inside a panel (like a table or log viewer) into clickable hyperlinks.
They’re useful when you want to:
- **Jump to a detail view** of a log entry
- **Query external tools** (e.g., CVE lookups, threat intelligence)
- **Cross-reference data** between panels or external apps
You define a **field name** (e.g., `_id` or `data.vulnerability.cve`) and specify a **URL template** that includes dynamic parts (e.g., `${__value.raw}` or `${__data.fields.field_name}`).
For example, if we look at the CVE Lookup Datalink that we just put:
```
Field name: ^data_vulnerability_cve$
URL: https://nvd.nist.gov/vuln/detail/${__value.raw} URL Label: NIST CVE Database
```
- **Field**: Matches fields with the exact name `data_vulnerability_cve` using regex.
- **URL**: When a CVE like `CVE-2023-4567` appears in your log/event, Grafana turns it into: `https://nvd.nist.gov/vuln/detail/CVE-2023-4567`
- **Label**: Shows a nice link title in the UI like _"NIST CVE Database"_ instead of a raw URL.
![[grafana_wazuh_setup.png]]
## Using Grafana
Before jumping into dashboards, go to **Explore** in the sidebar and test out your data source using basic queries. This helps confirm everything’s connected correctly and gives you a feel for what fields are available.
## Building A Dashboard
Now let's build a custom dashboard to visualize all of this data.
First, I install **Sankey**, via terminal on our SIEM server
```shell
grafana-cli plugins install netsage-sankey-panel
```
then restart grafana with `systemctl restart grafana-server`
Now I have access to the Sankey Panel. When I go to create a new dashboard, I can select that as my Visualization.
But, I'm going to have to do a little bit of a dance.
To know what fields I want to display in my Dashboard, I need to use Graylog, and check the field names that are in the logs.
For example, let’s map **network connections triggered by Sysmon**:
1. Use Graylog to identify log fields:
- Search for: `rule_group2: sysmon_eid3_detections`
- Fields: `data_win_eventdata_sourceIp`, `data_win_eventdata_destinationIp`, `data_win_eventdata_destinationPort`
2. In Grafana:
- Choose **Sankey Panel**
- Under **Group By**, select the fields in order:
- `data_win_eventdata_sourceIp`
- `data_win_eventdata_destinationIp`
- `data_win_eventdata_destinationPort`
3. Under **Transformations**:
- Use **Organize Fields by Name**
- Rename fields to: `SOURCE IP`, `DESTINATION IP`, `DESTINATION PORT`
Click **Save Dashboard** and enjoy your new visualization!
<div style="text-align: center;"> <img src="grafana_dash.png" alt="Grafana Dashboard"> </div>
### Other Panels I Created
- **Active Response Histogram**: shows which agents triggered AR actions
- **Top Triggered Attack Rules (7d)**: helps identify high-noise or hot targets
- **Networked Process Count**: shows processes generating network connections
- **External Connections by Process**: where suspicious processes are communicating
- **Virustotal Submission Integration**: Visualize clean and malicious submissions via my Virustotal API
<div style="text-align: center;">
<img src="grafana_full_dash.png" alt="Grafana Full Dashboard">
</div>
<div style="text-align: center;">
<img src="grafana_virustotal.png" alt="Grafana Full Dashboard">
</div>
## Conclusion
Building your own Grafana dashboards on top of Wazuh gives you:
- Lightning-fast log exploration
- Sharper, clearer insights into threats
- The power to customize visuals your way
- A cleaner alternative to the default Kibana fork
This setup gives me visibility and context at a glance — ideal for building out my home lab SOC and practicing real-world defensive operations.
As I continue to grow as a cybersecurity cloud engineer and SOC analyst, these tools not only make me more effective — they help me tell the story behind the data.
The sky is the limit!
---
## References
>Grafana APT download instructions: https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/
>https://socfortress.medium.com/part-6-best-open-source-siem-dashboards-5dad09fa4d0e
>https://grafana.com/grafana/dashboards/
>https://www.youtube.com/watch?v=qR5BH-bKpOg&t=690s
>Wazuh, *Add a Read Only User*: https://documentation.wazuh.com/current/user-manual/user-administration/rbac.html