Riemann is a flexible event stream processing system for monitoring and distributed system monitoring. It receives events from networked hosts and applications, processes them through streams, and can forward to various outputs. As a central event processor with significant visibility into system state, Riemann requires proper security configuration. This guide covers security measures for production Riemann deployments.
Riemann architecture includes these security-sensitive components:
Key security concerns include network access control, event injection prevention, stream security, API access control, and data protection.
Configure firewall rules for Riemann:
# Riemann TCP interface (default port 5555)
ufw allow from 10.0.0.0/8 to any port 5555 proto tcp
# Riemann UDP interface (default port 5555)
ufw allow from 10.0.0.0/8 to any port 5555 proto udp
# WebSocket interface (default port 5556)
ufw allow from 10.0.0.0/8 to any port 5556 proto tcp
# HTTP API (default port 5557)
ufw allow from 10.0.0.0/8 to any port 5557 proto tcp
# Block external access
ufw deny from any to any port 5555 proto tcp
ufw deny from any to any port 5555 proto udp
ufw deny from any to any port 5556 proto tcp
ufw deny from any to any port 5557 proto tcp
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: riemann-network-policy
spec:
podSelector:
matchLabels:
app: riemann
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 5555
- protocol: TCP
port: 5556
- protocol: TCP
port: 5557
Configure Riemann binding:
; /etc/riemann/riemann.config
(let [host "10.0.1.100" ; Bind to specific interface
port 5555]
(tcp-server {:host host
:port port})
(udp-server {:host host
:port port})
(ws-server {:host host
:port 5556})
(http-server {:host host
:port 5557}))
Configure authentication for TCP/UDP interfaces:
; /etc/riemann/riemann.config
; Riemann doesn't have built-in authentication
; Use TLS and network access control instead
(tcp-server {:host "10.0.1.100"
:port 5555
:tls? true
:key "/etc/riemann/ssl/server.key"
:cert "/etc/riemann/ssl/server.crt"
:ca-cert "/etc/riemann/ssl/ca.crt"})
Secure HTTP API access:
; /etc/riemann/riemann.config
; Use reverse proxy for authentication
(http-server {:host "127.0.0.1" ; Bind to localhost
:port 5557})
Configure reverse proxy authentication:
# /etc/nginx/sites-available/riemann
location /api/ {
auth_basic "Riemann API";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:5557;
}
Implement stream-based filtering:
; /etc/riemann/riemann.config
; Filter events by source
(streams
(where (host #"^10\.0\.") ; Only accept from internal network
index)
(where (service #"^internal-")
index)
; Reject all other events
(where true
(fn [event]
(log/warn "Rejected event from" (:host event))
nil)))
Implement client certificate authentication:
; /etc/riemann/riemann.config
(tcp-server {:host "10.0.1.100"
:port 5555
:tls? true
:key "/etc/riemann/ssl/server.key"
:cert "/etc/riemann/ssl/server.crt"
:ca-cert "/etc/riemann/ssl/ca.crt"
:client-auth :need}) ; Require client certificates
Configure TLS for Riemann server:
; /etc/riemann/riemann.config
(tcp-server {:host "10.0.1.100"
:port 5555
:tls? true
:key "/etc/riemann/ssl/server.key"
:cert "/etc/riemann/ssl/server.crt"
:ca-cert "/etc/riemann/ssl/ca.crt"
:cipher-suites ["TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"]})
Generate certificates:
# Create CA
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
-subj "/CN=Riemann CA/O=Company"
# Create server certificate
openssl req -new -nodes -newkey rsa:2048 \
-keyout server.key -out server.csr \
-subj "/CN=riemann.company.com"
openssl x509 -req -days 365 -in server.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt
Configure TLS for WebSocket:
; /etc/riemann/riemann.config
(ws-server {:host "10.0.1.100"
:port 5556
:tls? true
:key "/etc/riemann/ssl/server.key"
:cert "/etc/riemann/ssl/server.crt"
:ca-cert "/etc/riemann/ssl/ca.crt"})
Configure TLS for Riemann clients:
; Client configuration example
(require '[riemann.client :as rc])
(def client (rc/tcp-client {:host "riemann.company.com"
:port 5555
:ssl? true
:key "/etc/riemann/ssl/client.key"
:cert "/etc/riemann/ssl/client.crt"
:ca-cert "/etc/riemann/ssl/ca.crt"}))
Prevent malicious event injection:
; /etc/riemann/riemann.config
(streams
; Validate event fields
(where (fn [event]
(and (:host event)
(:service event)
(:state event)
(string? (:host event))
(string? (:service event))
(string? (:state event))))
index)
; Reject invalid events
(where true
(fn [event]
(log/warn "Invalid event:" event)
nil)))
Secure stream processing:
; /etc/riemann/riemann.config
; Rate limiting per host
(def rate-limits (atom {}))
(streams
(where true
(fn [event]
(let [host (:host event)
limit (get @rate-limits host 0)]
(if (< limit 100) ; 100 events per second
(do
(swap! rate-limits update host (fnil inc 0))
event)
(do
(log/warn "Rate limit exceeded for" host)
nil))))))
Secure HTTP API endpoints:
| Endpoint | Risk Level | Access Control |
|---|---|---|
GET /api/events |
Medium | Authenticated |
POST /api/events/1 |
Low | Authenticated |
GET /api/query |
Medium | Authenticated |
POST /api/query |
High | Admin only |
GET /api/config |
High | Admin only |
Implement via reverse proxy:
# /etc/nginx/sites-available/riemann
location /api/query {
auth_basic "Query API";
auth_basic_user_file /etc/nginx/.htpasswd.admin;
proxy_pass http://localhost:5557;
}
location /api/ {
auth_basic "Riemann API";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:5557;
}
Protect in-memory indices:
; /etc/riemann/riemann.config
; Limit index size
(index {:ttl 3600 ; 1 hour TTL
:max-events 100000}) ; Maximum events in index
Protect Riemann configuration:
# Set restrictive permissions
chown root:riemann /etc/riemann/riemann.config
chmod 640 /etc/riemann/riemann.config
# Encrypt sensitive configuration
gpg -c /etc/riemann/riemann.config
Protect sensitive event data:
; /etc/riemann/riemann.config
; Redact sensitive fields
(streams
(where true
(fn [event]
(-> event
(assoc :metric nil) ; Remove metric if sensitive
(update :description #(when % (subs % 0 (min 100 (count %)))))))))
Secure Riemann logs:
# Set restrictive permissions
chown riemann:adm /var/log/riemann
chmod 750 /var/log/riemann
# Configure log rotation
cat > /etc/logrotate.d/riemann << EOF
/var/log/riemann/*.log {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
create 640 riemann adm
}
EOF
Secure JVM configuration:
# /etc/riemann/riemann.env
# Limit JVM memory
JAVA_OPTS="-Xmx2g -Xms512m"
# Enable security manager
JAVA_OPTS="$JAVA_OPTS -Djava.security.manager"
# Security policy
JAVA_OPTS="$JAVA_OPTS -Djava.security.policy=/etc/riemann/java.policy"
Enable logging:
; /etc/riemann/riemann.config
(logging/init {:file "/var/log/riemann/riemann.log"
:level :info
:pattern "%-5level [%d{ISO8601}] %msg%n"})
Log events for audit:
; /etc/riemann/riemann.config
(streams
; Log all events
(where true
(fn [event]
(log/info "Event:" (:host event) (:service event) (:state event))
event))
; Log state changes
(changed-state
(fn [event]
(log/warn "State changed:" (:host event) (:service event))
event)))
Monitor Riemann for security events:
; /etc/riemann/riemann.config
; Alert on high event rate
(streams
(rate 100 ; Events per second threshold
(fn [events]
(log/warn "High event rate detected")
; Send alert
(email "security@company.com" "High Event Rate" "Riemann detected high event rate"))))
Forward logs to SIEM:
# /etc/rsyslog.d/riemann.conf
:programname, isequal, "riemann" /var/log/riemann/syslog.log
:programname, isequal, "riemann" @siem.company.com:514