How to integrate Grafana into our internal Tools / Admin Panel using AuthProxy?

Grafana is a wonderful charting tool, as it can provide beautiful charts and visualizations for the data. Integrating Grafana charts with internal tools can reveal great potential. The internal tools are custom dashboards, admin panels and CRUD apps that enable teams to automate processes.

Grafana comes with built-in authentication. The user has to go through its login screen to see its dashboard.

Grafana login screen

Now our user has to do two authentications: one for the internal device and the other for Grafana. Multiple authentications can create a poor user experience. So how can we integrate Grafana authentication with our internal device authentication, so that our users can have a seamless experience and only have to sign in once?

In this tutorial, we will learn how to integrate Grafana with our internal app AuthProxy Grafana’s module. We will be using a custom reverse proxy for this.

Quick Overview of Reverse Proxy

A reverse proxy is a proxy server that acts like a middleware responsible for protecting the identity of the server to the client. Well, it increases security.

Generally, authentication layers are present along with the proxy level load balancer. Multiple applications can be accessed with the same login by setting up authentication at the reverse proxy level; For example, Google Single Sign-in provides access to Drive, Docs, Maps, Gmail, etc.

Users requesting servers via the Internet
Users requesting servers via the Internet

Adding Grafana to Our Cluster

We can easily add Grafana to our cluster with the help of Helm chart or we can run it as Kubernetes manifest file.

The architecture, when the Grafana service is directly exposed to the main reverse proxy, is as follows:

Adding Grafana Service to Architecture

Adding Grafana Service to Architecture

Both services maintain their authentication separately, so managing users can be a real pain.

To remove this double authentication, we are going to use AuthProxy module, which will make authentication pluggable. We will also update the config file to enable users to auto-sign up.

Grafana AuthProxy Feature

Grafana AuthProxy The module can make Grafana authentication pluggable. So, a reverse proxy can sit in front of Grafana and take over the responsibility of user authentication.

Note that the Grafana database will be used for further authorization purposes. We are just eliminating the authentication responsibility and passing it on to our internal tool which will act like a reverse proxy.

Our final architecture will look like this:

Grafana with Authenticator Proxy Module

Grafana with Authenticator Proxy Module

Now that we understand the principle, let’s begin.

Composite code is present in this repository.

Condition

  • Docker or Kubernetes Cluster

Steps to start Grafana with AuthProxy

1. Inside your working directory, a . create data directory and create a file in it: Grafana.ini, This data/grafana.iniOur configuration file will be .

Add the following code to it:

[server]
protocol= http
domain= localhost
http_port= 3000
root_url= "%(protocol)s://%(domain)s:%(http_port)s/grafana/"
serve_from_sub_path= true

[auth.proxy]
enabled = true
# HTTP Header name that will contain the username or email
header_name = X-WEBAUTH-USER
# HTTP Header property, defaults to `username` but can also be `email`
header_property = username
# Set to `true` to enable auto sign up of users who do not exist in Grafana DB. Defaults to `true`.
auto_sign_up = true
# Define cache time to live in minutes
# If combined with Grafana LDAP integration it is also the sync interval
sync_ttl = 60
# Limit where auth proxy requests come from by configuring a list of IP addresses.
# This can be used to prevent users spoofing the X-WEBAUTH-USER header.
# Example `whitelist = 192.168.1.1, 192.168.1.0/24, 2001::23, 2001::0/120`
whitelist =
# Optionally define more headers to sync other user attributes
# Example `headers = Name:X-WEBAUTH-NAME Role:X-WEBAUTH-ROLE Email:X-WEBAUTH-EMAIL Groups:X-WEBAUTH-GROUPS`
headers =
# Non-ASCII strings in header values are encoded using quoted-printable encoding
;headers_encoded = false
# Check out docs on this for more details on the below setting
enable_login_token = false

2. Let’s now start a Docker container and attach a volume to it which contains the above config file:

docker run --name grafana --rm -v "$PWD/data:/etc/grafana" -p 3000:3000 grafana/grafana

3. Now let’s hit Grafana using curl request:

curl -H "X-WEBAUTH-USER: admin"  http://localhost:3000/api/users

We can see the list of existing users without any authentication.

Output of GET request to Grafana


Above is the output of the GET request to Grafana.

Steps to attach reverse proxy code to our internal app

1. We need to add the following snippet to our internal tool:

// NewProxy takes target host and creates a reverse proxy
func NewProxy(targetHost string) (*httputil.ReverseProxy, error) {
	url, err := url.Parse(targetHost) //targetHost is the url of grafana in case of docker it will be http://localhost:3000.
  // For k8s it will be http://SERVICE_NAME.NAMESPACE.svc.local:PORT
	if err != nil {
		return nil, err
	}
	proxy := httputil.NewSingleHostReverseProxy(url) //create reverse proxy object
	originalDirector := proxy.Director
	proxy.Director = func(req *http.Request) {
		originalDirector(req)
    // read username from request body & 
    // authenticate the user and pass its user name to header as follows
    // "admin" user will have all privileges
    // rest users will have access as per authorization policy
    user := "admin"
		req.Header.Set("X-WEBAUTH-USER", user)
	}
	return proxy, nil
}

// ProxyRequestHandler handles the http request using proxy
func ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		proxy.ServeHTTP(w, r)
	}
}

2. Yes, that’s it. Now we can create new users in Grafana DB by plugging authentication into our internal tool service.

Repository code is available.

Now run the code using go run main.go and access our internal app which is printing hello world,

internal applications
internal applications

We can access Grafana on the same login and same port. Wonderful, isn’t it?

Grafana within our internal app

Grafana within our internal app

Hooray, we’ve made it, and we don’t need to do multiple authentication anymore!

But wait! We cannot forget the following important points:

  • In production K8s cluster Grafana service will not be exposed to any load balancer and should be treated as ClusterIP,
  • The “administrator” user plays an important role. Be aware of passing the Write header to the reverse proxy.
  • New users will be created automatically according to the configuration file we have enabled auto_sign_up,

Leave a Comment