This repository provides an example configuration for sending events from Contrast's Universal Forwarder to Grafana Loki using Vector as the log aggregator. The setup is containerized using Docker Compose for easy deployment.
- Contrast Universal Forwarder: Sends detailed attack event data from Contrast ADR agents.
- Vector: Collects and forwards logs from the Universal Forwarder to Grafana Loki.
- Grafana Loki: Stores and indexes logs for querying and visualization in Grafana.
- Docker Compose: Orchestrates the services for local development and testing.
- Prometheus (Optional): Receives metrics from Vector for monitoring.
Below are example screenshots of what you can achieve with this setup in Grafana:
Dashboard JSON is available for import to Grafana in the dashboards folder.
- Docker and Docker Compose
- Contrast Universal Forwarder credentials and configuration
- Loki endpoint (cloud or self-hosted)
git clone https://github.com/Contrast-Security-OSS/universal-forwarder-grafana-loki.git
cd universal-forwarder-grafana-lokiCopy the .env.tmpl file to .env and fill in the required secrets:
cp .env.tmpl .envEdit .env and provide the necessary values:
# Loki configuration
LOKI_ENDPOINT="your-loki-endpoint-url"
LOKI_USER="your-loki-username (if required)"
LOKI_TOKEN="your-loki-api-token (if required)"
# Prometheus configuration (optional, for metrics)
PROMETHEUS_ENDPOINT="your-prometheus-endpoint-url (optional)"
PROMETHEUS_USER="your-prometheus-username (if required)"
PROMETHEUS_TOKEN="your-prometheus-api-token (if required)"
Note
Never commit your .env file to version control. Use .env.tmpl as a template for sharing required variables.
Edit conf/contrast.yaml to customize sources, sinks, and transforms if needed. By default, it is set up to:
- Ingest logs from Contrast Universal Forwarder
- Forward logs to Loki using the
lokisink - Expose metrics for Prometheus
If you do not have Prometheus setup or do not want metrics from Vector to be sent to Prometheus, remove conf/vector.yaml before running.
docker-compose up -dThis will start Vector.
Important
The Vector instance must be reachable from the outbound IP addresses for your Contrast SaaS instance so that the Contrast Universal Forwarder can send JSON events to it. This typically means exposing the relevant Vector port as defined in your contrast.yaml and docker-compose.yml.
Follow the Universal Forwarder documentation providing the externally accessible Vector URL (e.g., http://your-public-ip:9000 or your domain name) as the destination for log forwarding.
Caution
It is strongly recommended to setup TLS on the Vector http_server source and to use a https URL. Refer to the Vector documentation for more details on this configuration. Not doing so will mean event data is transmitted in the clear.
- Access your Grafana instance and add Loki as a data source if not already configured.
- Query logs to verify events are being ingested.

