Skip to content

Instantly share code, notes, and snippets.

@akhiljalagam
Last active October 31, 2019 10:47
Show Gist options
  • Save akhiljalagam/c93b565842a9f9d55aca7652814c5967 to your computer and use it in GitHub Desktop.
Save akhiljalagam/c93b565842a9f9d55aca7652814c5967 to your computer and use it in GitHub Desktop.
grafana proxying dashboard queries based on user account...
worker_processes 2;
events {
worker_connections 1024;
}
http {
# access_log off;
access_log /var/log/nginx/access.log;
keepalive_timeout 65;
resolver 8.8.8.8;
# leaving here in case we need some lua code as we used to have in here (see git)
lua_ssl_trusted_certificate "root-certs.pem";
lua_ssl_verify_depth 2;
lua_package_path "$prefix/lualib/?.lua;;";
lua_shared_dict locks 1M;
lua_shared_dict cache 10M;
# see https://github.com/openresty/lua-resty-core
init_by_lua '
require "resty.core"
';
# =================================================
# https rewrites
# =================================================
# http traffic redirects to HTTPS
server {
listen 80;
server_name www.rhythmon.com;
rewrite ^/(.*) https://www.rhythmon.com/$1 permanent;
}
server {
listen 80;
server_name forums.rhythmon.com;
rewrite ^/(.*) https://forums.rhythmon.com/$1 permanent;
}
# http apex zone traffic redirects to https on www.
server {
listen 80;
server_name rhythmon.com;
rewrite ^/(.*) https://www.rhythmon.com/$1 permanent;
}
# =================================================
# forums
# =================================================
server {
listen 443 ssl;
server_name forums.rhythmon.com;
ssl_certificate /opt/openresty/nginx/certs/forums.rhythmon.crt;
ssl_certificate_key /opt/openresty/nginx/certs/forums.key;
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
root /opt/openresty/nginx/html;
index index.html index.htm;
# all other traffic to the spring app, which does its own protection with spring security + pac4j
location / {
proxy_pass http://forums.int.rhythmon.com:5080/;
}
}
# =================================================
# spring and grafana
# =================================================
server {
listen 443 ssl;
server_name www.rhythmon.com;
ssl_certificate /opt/openresty/nginx/certs/www.rhythmon.crt;
ssl_certificate_key /opt/openresty/nginx/certs/host.key;
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
root /opt/openresty/nginx/html;
index index.html index.htm;
# redirect root visitors to home page within web app
#location = / {
# return 301 https://www.rhythmon.com/a;
#}
# endpoints that get passed straight through to grafana, no security
location /g/dashboard/snapshot/ {
proxy_pass http://grafana.int.rhythmon.com:3000/dashboard/snapshot/;
}
location /g/public/ {
proxy_pass http://grafana.int.rhythmon.com:3000/public/;
}
# It seems nginx needs two entries in this case - if I omit this one, the one below matches /g/api/snapshots, but proxies with
# a trailing /, i.e. /g/api/snapshots/, which causes a 404 in grafana
#
location /g/api/snapshots {
auth_request /auth/hard;
auth_request_set $email $upstream_http_x_rhythmon_email;
auth_request_set $grafanaUser $upstream_http_x_rhythmon_grafanauser;
proxy_set_header x-user $grafanaUser;
proxy_pass http://grafana.int.rhythmon.com:3000/api/snapshots;
}
# soft auth is needed here: anyone can GET, but to POST, the user must be logged in.
location /g/api/snapshots/ {
auth_request /auth/soft;
auth_request_set $email $upstream_http_x_rhythmon_email;
auth_request_set $grafanaUser $upstream_http_x_rhythmon_grafanauser;
proxy_set_header x-user $grafanaUser;
proxy_pass http://grafana.int.rhythmon.com:3000/api/snapshots/;
}
# Endpoint for database queries that grafana proxies straight through to influxdb. We intercept them
# and inject our own where clause to filter by account ID for just the logged in user's data, effectively adding user-level security to
# grafana and influxdb. Sample query url:
#
# GET http://influxdb.int.rhythmon.com/api/datasources/proxy/1/query?db=heart&q=SELECT mean("value") FROM "reversalEvent"
# WHERE "windowSize" = '5' AND time > 1463187791s and time < 1463360289s GROUP BY time(1m) fill(null)&epoch=ms
location /g/api/datasources/proxy/1/query {
# this auth service returns user's email, account ID in response headers along
# with the original query but with an account filter injected into it
auth_request /auth/hard/withQueryMunging/targettingInfluxDB;
auth_request_set $email $upstream_http_x_rhythmon_email;
auth_request_set $filteredQuery $upstream_http_x_filtered_query;
auth_request_set $grafanaUser $upstream_http_x_rhythmon_grafanauser;
access_by_lua_block {
ngx.log(ngx.STDERR, "setting grafana user to " .. ngx.var.grafanaUser)
ngx.log(ngx.STDERR, "filtered query is " .. ngx.var.filteredQuery)
}
proxy_set_header x-user $grafanaUser;
proxy_pass http://grafana.int.rhythmon.com:3000/api/datasources/proxy/1/query?db=heart&epoch=ms&q=$filteredQuery;
}
# same as above, but for datasource 2 - i.e. a spring endpoint over the mysql instance that emulates the influxdb protocol
location /g/api/datasources/proxy/4/query {
auth_request /auth/hard/withQueryMunging/targettingMysql;
auth_request_set $filteredQuery $upstream_http_x_filtered_query;
proxy_pass http://spring.int.rhythmon.com:8080/api/influxDBMysql/query?query=$filteredQuery;
}
# default for remaining grafana endpoints (as per https://github.com/grafana/grafana/issues/2066)
# that don't need any rewriting, just hard security
location /g/ {
auth_request /auth/hard;
auth_request_set $email $upstream_http_x_rhythmon_email;
# auth_request_set $userID $upstream_http_x_rhythmon_userid;
auth_request_set $grafanaUser $upstream_http_x_rhythmon_grafanauser;
access_by_lua_block {
ngx.log(ngx.STDERR, "setting grafana user to " .. ngx.var.grafanaUser)
}
proxy_set_header x-user $grafanaUser;
proxy_pass http://grafana.int.rhythmon.com:3000/;
}
# all other traffic to the spring app, which does its own protection with spring security + pac4j
location / {
proxy_pass http://spring.int.rhythmon.com:8080/;
}
#============================
# auth calls against the local spring app
#============================
location = /auth/soft {
proxy_pass http://spring.int.rhythmon.com:8080/api/authCheck/soft;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
location = /auth/hard {
proxy_pass http://spring.int.rhythmon.com:8080/api/authCheck/hard;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
location = /auth/hard/withQueryMunging/targettingInfluxDB {
proxy_pass http://spring.int.rhythmon.com:8080/api/authCheck/hard/withQueryMunging/targettingInfluxDB;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
location = /auth/hard/withQueryMunging/targettingMysql {
proxy_pass http://spring.int.rhythmon.com:8080/api/authCheck/hard/withQueryMunging/targettingMysql;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment