Version 1.0
This first version of Butler Auth includes support for these authentication providers:
- Microsoft
- Okta
- Auth0
- Keycloak
- LDAP
- Local file
- Single user
Docker containers are available on Docker Hub for both Intel and ARM architectures.
This the multi-page printable view of this section. Click here to print.
This first version of Butler Auth includes support for these authentication providers:
Docker containers are available on Docker Hub for both Intel and ARM architectures.
The goal of the Butler Auth project is to make it easy to add strong/flexible/custom authentication strategies to Qlik Sense Enterprise on Windows (QSEoW).
QSEoW has very good, built-in access control and authorization.
In practice this means that QSEoW enforces that users only can access resources they are allowed to access.
There is however no authentication what so ever in QSEoW.
This is quite reasonable - Qlik Sense is an analytics tool and should focus on this rather than the intricancies of ensuring that users are who they claim to be. That job is better left to those specializing in that particular field.
Butler Auth is the link between QSEoW and services that specialize in authentication and security.
Butler Auth is written in Node.js and runs on most modern operating systems.
Some authentication providers are developed as part of the Butler Auth project, but most come from Passport.js.
You can run Butler Auth on the same server as Qlik Sense, in a Docker container on a Linux server, in Kubernetes, on Mac OS, on Raspberry Pi (not a good idea.. but possible and proven to work).
Butler Auth is a member of a group of tools collectively referred to as the “Butler family”, more info here.
This picture might be useful to understand what Butle Auth does and how it fits into the larger system map around Qlik Sense:
Butler Auth is part of a group of tools that all aim to improve, simplify or extend various aspects of Qlik products.
Most tools focus on Qlik Sense Enterprise on Windows, but some have wider use within the Qlik ecosystem.
All members of the Butler family can be downloaded from Ptarmigan Labs' GitHub page.
Development of the Butler tools is sponsored by Ptarmigan Labs AB, which is an IT consultancy company in Stockholm, Sweden.
Projects with production grade release status are (as of this writing):
Makes it easier to add strong/flexible/custom authentication flows to Qlik Sense Enterprise on Windows.
Out of the box Butler Auth supports Google, Microsoft, Facebook, Okta, Auth0, LDAP and a few more authentication providers.
Butler Auth is designed to be extensible. It’s therefore relatively easy to add new authentication providers.
butler-auth.ptarmiganlabs.com (This site!)
The original Butler. Offers various utilities that make it easier to develop Sense apps, as well as simplifying day 2 operations.
Real-time operational metrics for Qlik Sense.
It simplifies day 2 operations ([1], [2]) and is a must-have if you are responsible for a Sense environment with more than a dozen or so users.
Key features include
Butler Cache Warmer. Cache warming is the process of proactively forcing Sense apps to be loaded into the Sense server’s memory, so they are readily available when users open them.
Once again - if your Sense environment serve more than a dozen users, you should consider a cache warming tool.
github.com/ptarmiganlabs/butler-cw
No matter if you are a single developer creating Sense apps, or have lots of developers doing this, having app templates is a good idea:
github.com/ptarmiganlabs/butler-app-duplicator
This tool is mainly of interest if you have lots of QVDs and apps, but when that’s the case it’s of paramount importance to understand what apps use which QVDs. In other words what data lineage looks like.
Butler Spyglass also extracts full load scripts for all Sense apps, creating a historical record of all load scripts for all Sense apps.
github.com/ptarmiganlabs/butler-spyglass
This tool makes it easy to tap into the Qlik Sense notification API. From there you can get all kinds of notifications, including task reload failures and changes in session state (user login/logout etc).
github.com/ptarmiganlabs/butler-notifier
Visual looks is important when it comes to analytics, and this holds true also for Sense apps.
The Butler Icon Uploader makes it easy to upload icon libraries (for example Font Awesome) to Qlik Sense Enterprise.
With such icons available, Sense app developers can then use professional quality sheet and app icons in their Sense apps.
All your use of Qlik Sense Enterprise on Windows is subject to the licensing and other terms you have received from Qlik.
These may in theory differ between Qlik’s customers and also change over time.
You are yourself responsible for complying with terms.
If Butler Auth offers or enables features that do not align with the licesning terms you have received from Qlik, it is still your responsibility to comply with Qlik’s terms and conditions.
None of the companies and/or individuals that have at some point contributed to Butler Auth, should at any time, in any way, be held liable for how you use Butler Auth.
If you already use Microsoft Azure, Google, Okta or Auth0 as identify provider, you probably want to do the same also for Qlik Sense.
A very common setup (possibly the most common) is to use Active Directory for storing user info and credentials, and then talk to AD using the LDAP protocol.
QSEoW natively supports syncing user names from some service using LDAP, this does not include passwords though.
This is actually not authentication at all, it’s just a way to sync user names and attributes from a directory service to QSEoW, using the LDAP protocol.
LDAP can however also be used to authenticate users, and Butler Auth supports this.
One use case is thus to get both the Qlik Sense user directory info (i.e. user names and attributes) and authenticate users via LDAP.
Keycloak is a very powerful, open source identity provider.
In situations where open source solutions are preferred or mandated the combination of Keycloak and Butler Auth provides a 100% open source authentication solution for QSEoW.
If you have multiple authentication solutions Butler Auth can be used to support several (or all) of them.
For example, let’s assume Okta is the primary authentication provider in your company but you also use Google’s tools (GMail, Sheets, Docs etc).
Butler Auth can then be configured for both Okta and Google authentication, with the effect that users can use either service when logging into Sense.
Sometimes you want all access to Qlik Sense to happen via a specific user account.
Admittedly, this might not be a very common scenario. But consider a trade show or other event where people should be able to test some Qlik Sense based application - ideally without having to log in at all.
You could solve this by using a Qlik Sense license that allows for anonymous users - but that’s probably overkill if the purpose is a simple demo event.
Another option is to use Butler Auth to force all access to Sense to use a single Sense account.
Given Sense’s limits on number of simultaneous sessions, only a handful (or less) people can try that Sense app at once - but it might be good enough for this specific use case.
Another use case would be to show a dashboard on a set of monitors in the office.
January 2021 note: Given how rarely people are in offices nowadays and the non-existing nature of trade shows, the use cases above might be pretty theoretical during coming months/years…
In the spirit of not copying information to several places, the version history is kept as annotations of each release on the GitHub release page.
Version numbers include up to 3 levels, for example version 4.6.2 (which is a fictitious version):
4 is the major version. It is increased when Butler Auth has added major new features, or in other ways changed in major ways. If following this principle, breaking changes should always result in a bumped major version.
6 is the minor version. This indicates a smaller update, when one or a few minor features have been added.
2 is the patch level. When individual bugs are fixed, these are released with an increased patch level.
Note 1: Major and minor updates usually include bug fixes too.
Note 2: If a version of 5.2 is mentioned, this implicitly means 5.2.0.
Butler Auth is an open source project, using the MIT license.
This means that all source code, documentation etc is available as-is, at no cost.
It however also means that anyone interested can - and is encouraged to - contribute to the project!
Butler Auth is developed in Node.js, with support from various NPM modules.
Specifically, most authentication providers are implemented using Passport.js.
We use Hugo to format and generate this documentation site and the Docsy theme for styling and site structure.
Hugo is an open-source static site generator that provides us with templates, content organisation in a standard directory structure, and a website generation engine. You write the pages in Markdown (or HTML if you want), and Hugo wraps them up into a website.
All submissions, including submissions by project members, require review.
We use GitHub pull requests for this purpose. Consult GitHub Help for more information on using pull requests.
We use GitHub’s discussion boards to discuss ideas, features, issues and everything else relating to Butler Auth.
Butler Auth itself lives in https://github.com/ptarmiganlabs/butler-auth.
The doc site lives in https://github.com/ptarmiganlabs/butler-auth-docs.
All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult GitHub Help for more information on using pull requests.
As obvious as it might sound: Please test your proposed changes properly before submitting pull requests.
If you’ve found a problem - or have a feature suggestion - with Butler Auth or this documentation site, but you’re not sure how to fix it yourself, please create an issue in the Butler Auth or Butler Auth docs repos. You can also create an issue about a specific doc page by clicking the Create project issue button in the top right hand corner of the page.
Follow the installation instructions - they will guide through the setup process, including requirements and customisation.
Once everything is installed you need to edit the configuration file to suit your specific needs.
Feel free to browse through the examples to get an understanding of how Butler Auth can be used.
There are also Youtube videos showing Butler Auth in action.
There isn’t really any right or wrong here.
What’s right for your company might be unacceptable for another company, and vice versa.
This page is intended to make you think and consider the options you have.
The authentication providers supported by Butler Auth generally belong to either of two categories:
Commercial identity and authentication providers such as Okta and Auth0.
These companies have entire teams dedicated to creating secure solutions for their customers.
But the transparency is limited or non-existing. They will for sure use open standards like OAuth 2.0, OpenID etc - but you will never know exactly what their specific implementations look like.
In other words: You will never be able to audit the code responsible for your authentication flow - you have to trust that these companies know what they are doing.
Open source libraries provide full transparency. You can audit them if/when needed.
The downside is that these libraries are sometimes developed by individuals or companies that no longer actively maintain them. Which in worst case could mean that new security issues are discovered in a standard authentication protocol, but the open source libraries are not quickly updated - or not updated at all.
In this case you’d be using a library with security issues associated with it. While this is rare, it’s a real possibility.
Butler Auth relies heavily on the authentication strategies available via Passport.js.
This is an open source authentication library boasting 500+ various kinds of authentication strategies.
Now, there will be some duplicates (for example several different Passport.js strategies offering Google authentication) and most of those 500+ strategies will be rather obscure - with the associated risk of not being supported.
The big ones - Google, Microsoft, generic OAuth 2.0, Auth0, LDAP, OpenID etc - are generall well supported and kept up to date.
For that reason they are also used in Butler Auth.
If you do not trust the various authentication modules that are part of Passport.js, you should not use them via Butler Auth.
Butler Auth is simply a thin wrapper around those modules.
So how should you reason if you have the luxury of deciding yourself what authentication solution to use?
If low cost and ease of setup is the main focus you should go with the big, established service providers. Google, Microsoft, GitHub, Amazon etc. By using open source authentication modules you won’t have any cost for the software or service.
These are reasonably easy to set up and get working.
If you have high security requirements and prefer (or must use) open source, Keycloak is a good option.
Keycloak can however be challenging to set up properly, at least if you also want to lock it down to meet specific security requirements. It’s like a Swiss army knife of authentication, with many, many tools in it…
There is simply a risk of configuring it incorrectly and not achieve the desired security level as a result.
If you can accept some costs associated with authentication you could use one of the commercial services. With some of them you can still use Google/Microsoft/… authentication if so desired, but you offload that integration work to the service provider.
Given the cross platform nature of Node.js (which is the language Butler Auth is written in), Butler Auth can run on lots of different hardware platforms and operating systems.
It is therefore difficult to give detailed installation instructions for each possible installation scenario. This site thus tries to explain how to get started with Butler Auth in some of the most common scenarios.
Sorry - there is no installer for Butler Auth.
You will need to work a bit on the command line to set things up.
It’s not as bad as it sounds though, the instructions here should help you to get started.
Either you install a few pieces of software (most notably Node.js and some node modules), or you run Butler Auth in a Docker container.
Either way you also need to edit Butler Auth’s configuration file and provide certificates exported from Qlik Sense Enterprise.
If you have access to or can set up a Docker runtime environment, this is by far the preferred way of running Butler Auth.
Installation is less error prone compared to installing Butler Auth as a Node.js app, you get all the benefits from the Docker ecosystem (monitoring of running containers etc), and upgrades to future Butler Auth ersions become trivial.
If you have access to a Kubernetes cluster, that is usually an even better option than Docker. Kubernetes can be daunting when first approached, but will give you superb reliability, failover and restarts if a server goes down or becomes unresponsive etc.
Rancher’s K3s is a great way to get started with Kubnernetes. Fully featured, well supported and a vibrant developer community.
Prerequisites for running Butler Auth in Docker:
What | Comment |
---|---|
Qlik Sense Enterprise on Windows | Mandatory. Butler Auth is developed with Qlik Sense Enterprise on Windows in mind. |
Docker | Mandatory. A Docker runtime environment on any supported platform. This means you can run Butler Auth on any platform where Docker is available, including Linux, Mac OS, Windows and most cloud providers. Kubernetes is also a great option for running Butler Auth! |
InfluxDB | Optional. A database for realtime information, used to store metrics around Butler’s own memory usage over time (if this feature is enabled). |
The following steps give some guidance on how to get Butler Auth running on Docker.
Here Mac OS has been used, things will look different on Linux and Windows.
➜ ~ mkdir /Users/goran/butler-auth
➜ ~ cd /Users/goran/butler-auth
➜ butler-auth mkdir -p config/certificate
➜ butler-auth mkdir sessions
➜ butler-auth mkdir log
➜ butler-auth wget https://raw.githubusercontent.com/ptarmiganlabs/butler-auth/main/src/docker-compose.yaml
--2021-01-20 13:58:54-- https://raw.githubusercontent.com/ptarmiganlabs/butler-auth/main/src/docker-compose.yaml
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.128.133, 151.101.64.133, 151.101.192.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.128.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 754 [text/plain]
Saving to: ‘docker-compose.yaml’
docker-compose.yaml 100%[========================================================================================================================================================================>] 754 --.-KB/s in 0s
2021-01-20 13:58:54 (37.8 MB/s) - ‘docker-compose.yaml’ saved [754/754]
➜ butler-auth
➜ butler-auth cat docker-compose.yaml
# docker-compose.yml
version: '3.3'
services:
butler-auth:
image: ptarmiganlabs/butler-auth:1.0.0
container_name: butler-auth
restart: always
ports:
- "8081:8081" # http/web server used to serve sample login forms included in Butler Auth
- "8761:8761" # REST API called by Qlik Sense Enterprise when users should be authenticated
volumes:
# Make config file and logs accessible outside of container
- "./config:/nodeapp/config"
- "./log:/nodeapp/log"
- "./sessions:/nodeapp/sessions"
- "/path/to/tls/cert:/nodeapp/config/tls"
environment:
- "NODE_ENV=production"
logging:
driver: json-file
options:
max-file: "5"
max-size: "5m"
➜ butler-auth
At this point you should
production.yaml
.docker-compose.yaml
file.local-file
auth provider, you also need a corresponding YAML file where user info is stored. There is a template file in the GitHub repository./path/to/tls/cert:/nodeapp/config/tls
in docker-compose.yaml
must point to your TLS certificates.When done, you should see something like this:
➜ butler-auth tree
.
├── config
│ ├── certificate
│ │ ├── client.pem
│ │ ├── client_key.pem
│ │ └── root.pem
│ ├── production.yaml
│ └── users.yaml
├── docker-compose.yaml
├── log
└── sessions
4 directories, 6 files
➜ butler-auth
At this point everything is ready and you can start the Butler Auth container using docker-compose (IP addresses and URLs have been slightly scrambled below):
➜ butler-auth docker-compose up
Creating network "butler-auth_default" with the default driver
Pulling butler-auth (ptarmiganlabs/butler-auth:1.0.0)...
1.0.0: Pulling from ptarmiganlabs/butler-auth
22f9b9782fc3: Already exists
072739d44e4f: Already exists
5111f27e9600: Already exists
dc22afea6082: Already exists
0ad0b403cda0: Already exists
bca65cadbc25: Already exists
c1e57ccc1a03: Already exists
2571476d0e73: Already exists
e3719000bb2c: Already exists
d09cb7e3b7d4: Pull complete
76d111860f8b: Pull complete
c30b9b6a8b26: Pull complete
e75f642798c7: Pull complete
5b06a9fb8f94: Pull complete
Digest: sha256:545e81b4a638cb2f50b7718723cd60528e91a237349429279a90928c95fa420f
Status: Downloaded newer image for ptarmiganlabs/butler-auth:1.0.0
Creating butler-auth ... done
Attaching to butler-auth
butler-auth | 2021-01-19T06:22:18.070Z info: CONFIG: Influxdb enabled: true
butler-auth | 2021-01-19T06:22:18.075Z info: CONFIG: Influxdb host IP: 1.2.3.4
butler-auth | 2021-01-19T06:22:18.075Z info: CONFIG: Influxdb host port: 8086
butler-auth | 2021-01-19T06:22:18.076Z info: CONFIG: Influxdb db name: butlerauth
butler-auth | 2021-01-19T06:22:18.413Z info: AUTH-LOCALFILE: Setting up endpoints.
butler-auth | 2021-01-19T06:22:18.415Z info: AUTH-LOCALFILE: Loading user list.
butler-auth | 2021-01-19T06:22:18.419Z info: AUTH-LOCALFILE: Successfully loaded users from file.
butler-auth | 2021-01-19T06:22:18.420Z debug: AUTH-LOCALFILE: Users loaded from file: [
butler-auth | {
butler-auth | "username": "anna",
butler-auth | "fullName": "Anna Svenson",
butler-auth | "password": "aaa",
butler-auth | "comment": "Root admin user"
butler-auth | },
butler-auth | {
butler-auth | "username": "joe",
butler-auth | "fullName": "Joe Jonson",
butler-auth | "password": "bbb",
butler-auth | "comment": "Regular user"
butler-auth | }
butler-auth | ]
butler-auth | 2021-01-19T06:22:18.421Z info: AUTH-LDAP: Setting up endpoints.
butler-auth | 2021-01-19T06:22:18.421Z info: AUTH-GOOGLEOAUTH: Setting up endpoints.
butler-auth | 2021-01-19T06:22:18.422Z info: AUTH-FACEBOOK: Setting up endpoints.
butler-auth | 2021-01-19T06:22:18.423Z info: AUTH-MICROSOFT: Setting up endpoints.
butler-auth | 2021-01-19T06:22:18.424Z info: AUTH-OKTA: Setting up endpoints.
butler-auth | 2021-01-19T06:22:18.425Z info: AUTH-KEYCLOAK: Setting up endpoints.
butler-auth | 2021-01-19T06:22:18.425Z info: AUTH-AUTH0: Setting up endpoints.
butler-auth | 2021-01-19T06:22:18.426Z debug: HEARTBEAT: Setting up heartbeat to remote: http://healthcheck.mycompany.com/ping/12345678-1234-1234-1234-b10b81583522
butler-auth | 2021-01-19T06:22:18.428Z info: --------------------------------------
butler-auth | 2021-01-19T06:22:18.428Z info: Starting Butler authenticator
butler-auth | 2021-01-19T06:22:18.428Z info: Log level: debug
butler-auth | 2021-01-19T06:22:18.428Z info: App version: 1.0.0
butler-auth | 2021-01-19T06:22:18.428Z info: --------------------------------------
butler-auth | 2021-01-19T06:22:18.458Z info: MAIN: REST server now listening on butler-auth:8761
butler-auth | 2021-01-19T06:22:18.459Z info: MAIN: Web server now listening on butler-auth:8081
butler-auth | 2021-01-19T06:22:18.478Z info: CONFIG: Found InfluxDB database: butlerauth
butler-auth | 2021-01-19T06:22:18.597Z debug: HEARTBEAT: Sent heartbeat to http://healthcheck.mycompany.com/ping/12345678-1234-1234-1234-b10b81583522
What you see on your screen will depend on which Butler Auth version you are using and what features are enabled.
While Qlik Sense Enterprise is a Windows only system, Butler Auth runs on any OS where Node.js is available.
Butler Auth has been succesfully used using standard Node.js - during development and production - on Windows, Linux (Debian and Ubuntu tested) and Mac OS.
Prerequisites:
What | Comment |
---|---|
Sense Enterprise | Mandatory. Butler Auth is developed with Qlik Sense Enterprise on Windows in mind. |
Node.js | Mandatory. |
InfluxDB | Optional. A database for realtime information, used to store metrics around Butler Auth’s own memory usage over time (if this feature is enabled). |
Install node.js
Butler Auth was developed and tested using the 64 bit version of Node.js. The most recent LTS (Long Term Support) version of Node.js is a good choice for running Butler. At time of this writing, Node.js 14.5 is used.
Decide where to install Butler Auth
It is usually a good starting point to run Butler Auth on a Sense server.
On the other hand, you might want to keep the Sense servers as clean as possible (with respect to software running on them). If that is a priority you should install Butler Auth on some other server. A small “utility” or “misc” server can often be useful for running various add-on services to Qlik Sense.
The bottom line is that Butler Auth can run on any server, as long as Node.js is available and there is network connectivity to the actual Qlik Sense server(s).
Download Butler Auth
Download the repository zip from the releases page file or clone the Butler Auth repository using your git tool of choice. Both options achieve the same thing, i.e. a directory such as d:\node\butler-auth, which is then Butler Auth’s root directory.
Install node dependencies
From a Windows command prompt (assuming the Butler ZIP file/repository was extracted to d:\node\butler-auth):
d:
cd \node\butler-auth\src
npm install
This will download and install the Node.js modules used by Butler Auth.
Configuration
Configuration of Butler Auth is done more or less the same way as configuring for Docker, i.e. get certificates from Qlik Sense Enterprise on Windows > store them in suitable location > refer to those cert files from production.yaml
file etc.
More details are then available in the on the Configuration pages.
A description of the config file format is available here.
Butler Auth uses configuration files in YAML format. The config files are stored in the src/config
folder.
Trying to run Butler Auth with the default config file (the one included in the files download from GitHub) will not work - you need to adapt it to your server environment.
The name of the config file matters. Butler Auth looks for an environment variable called “NODE_ENV” and then tries to load a config file named with the value found in NODE_ENV.
For example:
NODE_ENV=production
Butler will look for a config file config/production.yaml
.
The method for setting environment variables varies between different operating systems:
On Windows:
set NODE_ENV=production
Mac OS or Linux
export NODE_ENV=production
If using Docker, the NODE_ENV environment varible is set in the docker-compose.yml file (as already done in the sample docker-compose file.)
These settings are mandatory.
While logging to disk files is optional, logging to console will always happen.
You should also set a log level.
Do note though that Butler expects the configuration properties below to exist in the config file, but will ignore their values if the related features are disabled.
Logging tells you what Butler Auth has done in the past.
Who logged in when, if you like.
Temporarily increasing logging verbosity can also be very useful when setting up new authentication providers.
Don’t forget to dial back the logging level once everthing works though!
---
ButlerAuth:
...
...
# Logging configuration
logLevel: info # Log level. Possible log levels are silly, debug, verbose, info, warn, error
fileLogging: false # true/false to enable/disable logging to disk file
logDirectory: log # Subdirectory where log files are stored. Absolute or relative path accepted.
...
...
These settings are optional.
If you don’t need this feature just disable it and leave the default values in the config as they are.
Do note though that Butler Auth expects the configuration properties below to exist in the config file, but will ignore their values if the related features are disabled.
A tool like Butler Auth should be viewed as mission critical, at least if the Qlik Sense environment as such is considered mission critical.
But how can you know whether Butler Auth itself is working?
Somehow Butler Auth itself should be monitored.
Butler Auth (and most other tools in the Butler family) has a heartbeat feature.
It sends periodic messages to a monitoring tool, which can then alert if Butler hasn’t checked in as expected.
Healthchecks.io is an example of such as tool. It’s open source but also has a SaaS option if so preferred. Highly recommended!
More info on using Healthchecks.io with the Butler family can be found in this blog post.
---
Butler:
...
...
# Heartbeats can be used to send "I'm alive" messages to any other tool, e.g. a infrastructure monitoring tool
# The concept is simple: The remoteURL will be called at the specified frequency. The receiving tool will then know
# that Butler Auth is alive.
heartbeat:
enable: false # Enable/disable healthcheck pings
remoteURL: http://my.monitoring.server/some/path/
frequency: frequency: 60000 # Milliseconds
...
...
These settings are optional.
If you don’t need this feature just disable it and leave the default values in the config as they are.
Do note though that Butler Auth expects the configuration properties below to exist in the config file, but will ignore their values if the related features are disabled.
Note: Sending health check messages is only meaningful when running Butler Auth as a Docker container.
---
Butler:
...
...
# Docker health checks are used when running Butler Auth as a Docker container.
# The Docker engine will call the container's health check REST endpoint with a set interval to determine
# whether the container is alive/well or not.
# If you are not running Butler Auth in Docker you can safely disable this feature.
dockerHealthCheck:
enable: false # Control whether a REST endpoint will be set up to serve Docker health check messages
port: 12398 # Port the Docker health check service runs on (if enabled)
...
...
These settings are optional.
If you don’t need this feature just disable it and leave the default values in the config as they are.
Do note though that Butler Auth expects the configuration properties below to exist in the config file, but will ignore their values if the related features are disabled.
In some cases - especially when investigating issues or bugs - it can be useful to get log messages telling how long Butler Auth has been running and how much memory it uses.
This feature is called “uptime monitoring” and can be enabled in the main config file.
The logging interval is configurable, as is the log level required for uptime messages to be shown.
The memory usage data can optionally be written to InfluxDB, from where it can later be viewed in Grafana.
If the specified InfluxDB database does not exist it will be created. The same is true for the retenion policy.
Select a reasonable retention policy and logging frequency!
You will rarely if ever need to know how much memory Butler Auth used a month ago… A retention policy of 1-2 weeks is usually a good start, with logging every few minutes.
---
Butler:
...
...
# Uptime monitor
uptimeMonitor:
enable: false # Should uptime messages be written to the console and log files?
frequency: 300000 # Milliseconds
logLevel: info # Starting at what log level should uptime messages be shown?
storeInInfluxdb:
enable: false
hostIP: <IP or host name>
hostPort: 8086
auth:
enable: false
username: user_joe
password: joesecret
dbName: butlerauth
instanceTag: DEV # Tag that can be used to differentiate data from multiple Butler Auth instances
# Default retention policy that should be created in InfluxDB when Butler Auth creates a new database there.
# Any data older than retention policy threshold will be purged from InfluxDB.
retentionPolicy:
name: 10d
duration: 10d
...
...
These settings are mandatory.
Do note though that Butler Auth expects the configuration properties below to exist in the config file, but will ignore their values if the related features are disabled.
Butler Auth exposes a REST server which Qlik Sense will call when a user connects to a Qlik Sense virtual proxy.
There are then different REST API endpoints for different authentication providers.
The REST server is also responding to the callbacks that happen as part of for example an OAuth 2.0 authentication flow. When the authentication provider has given green light, that provider’s callback endpoint on the REST server is called.
Secondly, a http server is used to serve a sample web based login interface.
This web site is for inspiration only. It has hard coded URLs that need to be changed before it is useful in your own environment. Still, it can serve as a basis for your own, custom/branded login page for Qlik Sense.
Each authentication provider that rely on some kind of web interface for entering user name and password has a url
property the main YAML config file (for example ButlerAuth.authProvider.ldap.url
). Those property can be used to direct authentication requests to your own, custom login user interfaces.
The settings below control the behvaiour of those two servers.
---
ButlerAuth:
...
...
# Server and https settings
server:
rest: # The REST server is the authentication server called by Qlik Sense.
host: <FQDN> # Hostname of the REST server. Would be container name when running under Docker, otherwise something like qliksenseauth.mydomain.com.
port: 8761 # Port where the REST server will listen
rateLimit: # Used to limit number of authentication requests during a given time window. Used to prevent brute forcing attacks.
enable: false # Enable/disable rate limiting for this REST API. true/false.
windowSize: 60000 # How long (milliseconds) is the time window we're capping # of logins for? Default 5 min if not specified.
maxCalls: 100 # Max # of logins from Qlik Sense during time window above. Default 100 if not specified.
tls: # Many 3rd party auth providers require the OAuth 2 server to use https.
enable: true # Enable/disable https. While always recommended, https is strictly not needed for local file authentication, for example.
cert: /path/to/certfile.cer # TLS certificate file
key: /path/to/certfile.key # TLS key file
password: # Passphrase for TLS key file, if used
web: # The web/http server used to serve the sample login pages included in Butler Auth
host: <FQDN> # FQDN of the http server
port: 8081 # Port where the http server will listen
tls: # Used to secure the http server with TLS. I.e. https.
enable: true
cert: /path/to/certfile.cer
key: /path/to/certfile.key
password:
...
...
These settings are mandatory.
You could in theory disable all the authentication providers, but then you don’t need Butler Auth to begin with.
In other words: Enable at least one provider.
A core concept of Butler Auth is that of authentication providers, or just providers.
A provider’s purpose is to offer a way to authenticate users.
Once users are authenticated they are forwarded to Qlik Sense.
Providers can be individually enabled and disabled, i.e. there are no dependencies between providers.
Likewise, there are no limitations on how many or which providers can be enabled at the same time.
Each provider has it’s own settings in the config file.
If new providers are added to Butler Auth they will need to be configured in the config file.
---
ButlerAuth:
...
...
# Auth providers are responsible for authenticating users before they are forwarded to Qlik Sense Enterprise.
authProvider:
localFile: # "Local file" provider reads user data from a file on disk
enable: false
url: https://<FQDN>:8081 # URL where login UI for this provider is available
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userFile: ./config/users.yaml # YAML file containing usernames and passwords
ldap: # "LDAP" provider
enable: false
url: https://<FQDN>:8081 # URL where login UI for this provider is available
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
ldapServer: # Information about the LDAP server to authenticate against
host: <ldap(s)://ldap.mydomain.com> # Both normal (ldap://) and secure (ldaps://) LDAP is supported
port: 636 # Usually 389 for LDAP and 636 for LDAPS
bindUser: '<domain\username>' # Service account used to log into the LDAP server
bindPwd: <password> # Password of service account
searchBase: '<dc=...,dc=...,dc=...>' # Base path from which authentication attempts will start
searchFilter: '(&(objectcategory=person)(objectclass=user)(|(samaccountname={{username}})(mail={{username}})))' # Filter used to get info about users in LDAP server
tls:
# Settings here will override default TLS behaviour.
# Useful for example if your cert is for another domain wrt the host name of the LDAP server.
# If a setting is empty it will simply be ignored by Butler Auth.
# Necessary if the LDAP server isusing a self-signed certificate
# Should point to a PEM coded CA certificate file.
ca:
singleUser: # "Single user" provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userId: goran # A user that already exists in QLik Sense. All access to Sense will be done using this user.
google: # "Google" OAuth2 provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
facebook: # "Facebook" OAuth2 provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
microsoft: # "Microsoft" OAuth2 provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <client ID>
clientSecret: <Client>
okta: # "Okta" provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
oktaDomain: <Okta domain from Google admin console> # E.q. https://myid-123456.okta.com'
idp:
keycloak: # "Keycloak" provider
enable: true
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
host: <FQDN of Keycloak server> # E.g. https://keycloak.mydomain.com
realm: # E.g. ptarmiganlabs
authorizationURL: <URL> # E.g. https://keycloak.mydomain.com/auth/realms/<myrealm>/protocol/openid-connect/auth
tokenURL: <URL> # E.g. https://keycloak.mydomain.com/auth/realms/<myrealm>/protocol/openid-connect/token
userInfoURL: <URL> # E.g. https://keycloak.mydomain.com/auth/realms/<myrealm>/protocol/openid-connect/userinfo
auth0: # "Auth0" provider
enable: true
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
issuerBaseURL: <FQDN> # E.g. mycompany.eu.auth0.com
baseURL: <URL> # FQDN of Butler Auth, e.g. https://qliksenseauth.mycompany.com:8761'
clientId: <Client ID>
clientSecret: <Client secret>
...
...
These settings tell Butler Auth where to find the certificates it needs to communicate with Qlik Sense Enterprise.
---
ButlerAuth:
...
...
# Settings relating to Qlik Sense
qlikSense:
# Certificates to use when calling Sense APIs. Get these from the Certificate Export in QMC.
certFile:
# If running under Docker, use these paths:
# clientCert: /nodeapp/config/certificate/client.pem
# clientCertKey: /nodeapp/config/certificate/client_key.pem
# clientCertCA: /nodeapp/config/certificate/root.pem
# If running as a native Node.js app, point to where the cert files are stored:
clientCert: /path/to/client.pem
clientCertKey: /path/to/client_key.pem
clientCertCA: /path/to/root.pem
clientCertPassphrase:
...
...
How to start and keep Butler Auth running varies depending on whether you are using Docker or a native Node.js approach.
Starting Butler Auth is easy.
First configure the docker-compose.yml
file as needed, then start the Docker container in interactive mode (with output sent to the screen). This is useful to ensure everything works as intended when first setting up Butler Auth.
docker-compose up
Once everything works as intended, hit ctrl-c
to stop the service.
Then start it again in deameon (background) mode:
docker-compose up -d
From here on the Docker enviromment will make sure Butler is always running, including restarting it if it for some reason stops.
Starting Butler Auth as a Node.js task is easy too:
d:
cd \node\butler-auth\src
node index.js
It is of course also possible to put those commands in a command file (.bat on Windows, .sh etc on other platforms) file and execute that file instead.
As Butler Auth is the kind of service that (probably) should always be running on a server, it makes sense using a Node.js process monitor to keep it alive (if running as a Docker container you get this for free).
On Windows you can use the excellent Nssm tool to make Butler Auth run as a Windows Service, with all the benefits that follow (can be monitored using operations tools, automatic restarts etc).
If running Butler Auth as a Node.js app on Linux, PM2 and Forever are two good process monitors.
Once Butler Auth is running it’s a good idea to also monitor it. Otherwise you stand the risk of not getting notified if it for some reason misbehaves.
Butler Auth will log data on its memory usage to InfluxDB if
ButlerAuth.uptimeMonitor.enable
and ButlerAuth.uptimeMonitor.storeInInfluxdb.enable
properties are both set to true
.Assuming everything is correctly set up, you can then create a Grafana dashboard showing Butler Auth’s memory use over time.
You can also set up alerts in Grafana if so desired, with notifications going to most IM tools and email.
The following metrics are logged to InfluxDB, in a measurement called butlerauth_memory_usage
:
Each measurement is also tagged with a tag called butlerauth_instance
. This tag is set in the main config file and is used in complex environments to separate between different Butler Auth instances.
A Grafana dashboard can look like this. Note that one of the available metrics (external
) is not used in this particular dashboard. It’s still logged to InfluxDB though.
There is a sample Grafana dashboard in Butler’s GitHub repo.
Butler Auth includes a small demo web site that makes it easy to try the various authentication providers (assuming you have accounts with them, of course).
The site is just a single page with links to each authentication provider supported by Butler Auth:
Note:
The demo site has hard coded links to a specific Qlik Sense Enterprise on Windows server.
This means you can view the demo site above, but when clicking the links you won’t be able to connect to the Sense server.
Instructions for customising the demo site are available here.
Auth0 is an interesting authentication provider in that they offer both a user directory service, but also “passthrough authentication” to other auth providers such as Google, GitHub, Microsoft etc.
It’s thus possible to set up Butler Auth to work with Auth0, and then via Auth0 get access to their entire list of supported auth providers.
The settings in the config file are:
auth0: # "Auth0" provider
enable: true
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
issuerBaseURL: <FQDN> # E.g. mycompany.eu.auth0.com
baseURL: <URL> # FQDN of Butler Auth, e.g. https://qliksenseauth.mycompany.com:8761'
clientId: <Client ID>
clientSecret: <Client secret>
Field | Description |
---|---|
enable | Enable or disable this authentication provider. true/false. |
userDirectory | The Qlik Sense Enterprise user directory that will be used once the user has been authenticated by the authentication provider. |
userIdShort | The provider will return the user’s email address. If userIdShort is set to true , the @ character and email domain will be stripped from the email address returned by the provider. For example, “joe@company.com” would become just “joe”. true/false. |
issuerBaseURL | The URL pointing to Auth0’s service. You get this from Auth0. For Ptarmigan Labs (who’s located in Europe/EU), the URL could be ptarmiganlabs.eu.auth0.com . |
baseURL | URL to Butler Auth. For Ptarmigan Labs this could be https://qliksenseauth.ptarmiganlabs.net:8761 |
clientId | Client ID from Auth0 |
clientSecret | Client secret from Auth0 |
These are the general steps to set up Auth0 for use with Butler Auth.
Log in to your Auth0 dasboard (https://manage.auth0.com/dashboard).
Go to the applications section, then create a new application. You can go through the step-by-step wizard, but it’s usually easier to just fill in the needed fields on the Settings tab.
Fill in the specifics of your application on the Settings tab. There are lots of fields here, the important ones are
Name
: Application’s name. “Qlik Sense Enterprise” or “Butler Auth” could be good names, but anything goes.Description
: Not mandatory, but it’s a good idea to write down a few words what the Auth0 does and its intended use cases.Application Logo
: If you want your users to see a logo when authentication, this is where it’s set.Application Type
: Set to “Regular Web Application”.Token Endpoint Authentication Method
: Set to “Post”.Allowed Callback URLs
: This one is important from a security perspective. Set to the fully qualified domain name (FQDN) of Butler Auth, for example https://qliksenseauth.ptarmiganlabs.net:8761/auth/auth0/redirect
. This is a list of URLs that Auth0 is authorized to call back to once the user has been successfully authenticated.Move on to the Connections tab. If you have previously set up “connections” (which is Auth0’s word for other authentication providers), this is where you enable them.
Facebook offers authentication using OAuth 2.0.
The settings in the config file are:
facebook: # "Facebook" OAuth2 provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
Field | Description |
---|---|
enable | Enable or disable this authentication provider. true/false. |
userDirectory | The Qlik Sense Enterprise user directory that will be used once the user has been authenticated by the authentication provider. |
userIdShort | The provider will return the user’s email address. If userIdShort is set to true , the @ character and email domain will be stripped from the email address returned by the provider. For example, “joe@company.com” would become just “joe”. true/false. |
clientId | Client ID from Facebook |
clientSecret | Client secret from Facebook |
General steps to set up Facebook Login for use with Butler Auth.
Log in to Facebook’s developer site https://developers.facebook.com.
Go to the applications section, then create a new application:
“Create App” > “Build Connected Experiences” > Enter app name and contact email > “Create App” > “Not a robot..”.
Add the Facebook Login product to the newly created app:
Click “Set Up” on the Facebook Login product > “Other” as platform.
Open the basic settings:
Copy the App ID
and App Secret
from the screen above to the Butler Auth config file.
Google offers authentication using OAuth 2.0.
The settings in the config file are:
google: # "Google" OAuth2 provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
Field | Description |
---|---|
enable | Enable or disable this authentication provider. true/false. |
userDirectory | The Qlik Sense Enterprise user directory that will be used once the user has been authenticated by the authentication provider. |
userIdShort | The provider will return the user’s email address. If userIdShort is set to true , the @ character and email domain will be stripped from the email address returned by the provider. For example, “joe@company.com” would become just “joe”. true/false. |
clientId | Client ID from Google |
clientSecret | Client secret from Google |
General steps to set up Google for use with Butler Auth.
https://<FQDN of Butler Auth>:<Butler Auth REST port>/oauth2callback
. Note that Butler Auth’s REST API port can be changed in the main config file of Butler Auth. At least one URI is required.The settings in the config file are:
keycloak: # "Keycloak" provider
enable: true
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
host: <FQDN of Keycloak server> # E.g. https://keycloak.mydomain.com
realm: # E.g. ptarmiganlabs
authorizationURL: <URL> # E.g. https://keycloak.mydomain.com/auth/realms/<myrealm>/protocol/openid-connect/auth
tokenURL: <URL> # E.g. https://keycloak.mydomain.com/auth/realms/<myrealm>/protocol/openid-connect/token
userInfoURL: <URL> # E.g. https://keycloak.mydomain.com/auth/realms/<myrealm>/protocol/openid-connect/userinfo
Field | Description |
---|---|
enable | Enable or disable this authentication provider. true/false. |
userDirectory | The Qlik Sense Enterprise user directory that will be used once the user has been authenticated by the authentication provider. |
userIdShort | The provider will return the user’s email address. If userIdShort is set to true , the @ character and email domain will be stripped from the email address returned by the provider. For example, “joe@company.com” would become just “joe”. true/false. |
clientId | Client ID from Keycloak’s *realm* > Clients > *client* > Settings page. |
clientSecret | Client secret from Keycloak’s *realm* > Clients > *client* > Credentials page. |
host | Full URL to Keycloak |
realm | Keycloak realm to use. |
authorizationURL | See below for instruction on how to get this. |
tokenURL | See below for instruction on how to get this. |
userInfoURL | See below for instruction on how to get this. |
General steps to set up Keycloak for use with Butler Auth.
In the examples below Keycloak is available at http://qliksenseauth.ptarmiganlabs.net:8082
.
This works for demonstration purposes, but in a production scenario https should be used.
Log in to the Keycloak admin console.
If you don’t already have a Keycloak realm, create one via the menu in the upper left corner.
Fill in the realm settings. The screen shots below only gives some guidance, you are STRONGLY encouraged to review all settings. The Frontend URL
is the URL where Butler Auth will call Keycloak.
Open the Clients
menu on the left. Add a new one.
Fill in the details of the new client.
… and lower part of that page…
The Valid Redirect URIs
is a list of approved/allowed sources. Only calls originating from these URIs will be handled by this Keycloak realm/client.
In our case, this is the callback URL of Butler Auth.
The Credentials
tab contains the Client secret that should be copied to Butler Auth.
The settings on the remaining tabs of the client configuration are used to fine-tune the authentication setup. The default values should work as a starting point though.
If you don’t already have any users in Keycloak it’s easy to set up one for testing purposes.
Open the Users
menu on the left. Click the Add user
button in upper right corner.
Keycloak has a cool feature similar to the one offered by Auth0, where you can use another, 3rd party identity provider for the actual authentication work.
For example, you can set up Butler Auth to use Keycloak (and have all the benefits offered by Keycloak), and then have Keycloak forward the authentication requqests to IdPs such as Microsoft, Google, Facebook, LinkedIn, Twitter, GitHub and others.
The settings in the config file are:
ldap: # "LDAP" provider
enable: false
url: https://<FQDN>:8081 # URL where login UI for this provider is available
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
ldapServer: # Information about the LDAP server to authenticate against
host: <ldap(s)://ldap.mydomain.com> # Both normal (ldap://) and secure (ldaps://) LDAP is supported
port: 636 # Usually 389 for LDAP and 636 for LDAPS
bindUser: '<domain\username>' # Service account used to log into the LDAP server
bindPwd: <password> # Password of service account
searchBase: '<dc=...,dc=...,dc=...>' # Base path from which authentication attempts will start
searchFilter: '(&(objectcategory=person)(objectclass=user)(|(samaccountname={{username}})(mail={{username}})))' # Filter used to get info about users in LDAP server
tls:
# Settings here will override default TLS behaviour.
# Useful for example if your cert is for another domain wrt the host name of the LDAP server.
# If a setting is empty it will simply be ignored by Butler Auth.
# Necessary if the LDAP server isusing a self-signed certificate
# Should point to a PEM coded CA certificate file.
ca:
Field | Description |
---|---|
enable | Enable or disable this authentication provider. true/false. |
url | Tells Butler Auth where it should send the user when it’s time to enter his/her username and password. A basic web page for entering LDAP credentials is included in Butler Auth, but for production scenarios you probably want to create your own login page. |
userDirectory | The Qlik Sense Enterprise user directory that will be used once the user has been authenticated by the authentication provider. |
host | Host where LDAP server is running. ldap://ldap.mydomain.com is insecure/not encryptet, ldaps://ldap.mydomain.com is secure. Use ldaps if possible. |
port | Port to use on LDAP server. Usually 636 for ldaps, 389 for ldap. |
bindUser | User to log in with on LDAP server. Usually a service account of some kind. |
bindPwd | Password for bindUser. |
searchBase | The base path from which authentication attempts will be done. For an Active Directory domain called sales at company mycompany.com it could be dc=sales,dc=mycompany,dc=com' |
searchFilter | Filter used to determine if a user exists in the LDAP server. The example above should be a good starting point for standard-install Active Directory servers. |
ca | If ldaps is used and the LDAP server is configured with proper certificates that use publicly recognizable certificate authorities, this ca section is not needed. If self-signed certificates are used you need to specify the CA certificate here for ldaps to work. |
If you want to use the built-in login page to begin with, it’s configured like this:
https://butlerauth.company.com
, with the http server set up to listen on port 8081.https://butlerauth.company.com:8081/auth-providers.html
.ButlerAuth.authProvider.ldap.url
to https://butlerauth.company.com:8081
Here is the built-in LDAP login page:
Configuring the directory server (which Butler Auth talks to using the LDAP protocol) is beyond the scope of this site.
The settings in the config file are:
localFile: # "Local file" provider reads user data from a file on disk
enable: false
url: https://<FQDN>:8081 # URL where login UI for this provider is available
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userFile: ./config/users.yaml # YAML file containing usernames and passwords
Field | Description |
---|---|
enable | Enable or disable this authentication provider. true/false. |
url | Tells Butler Auth where it should send the user when it’s time to enter his/her username and password. A basic web page for entering local-file credentials is included in Butler Auth, but for production scenarios you probably want to create your own login page. |
userDirectory | The Qlik Sense Enterprise user directory that will be used once the user has been authenticated by the authentication provider. |
userFile | A YAML file containing usernames and passwords. |
If you want to use the built-in login page to begin with, it’s configured like this:
https://butlerauth.company.com
, with the http server set up to listen on port 8081.https://butlerauth.company.com:8081/auth-providers.html
.ButlerAuth.authProvider.localFile.url
to https://butlerauth.company.com:8081
Here is the built-in local file login page:
The file containing user credentials is YAML-formatted:
users:
- username: anna
fullName: Anna Svenson
password: aaa
comment: Root admin user
- username: joe
fullName: Joe Jonson
password: bbb
comment: Regular user
Make sure to secure this file properly.
Anyone with access to this file can log into Qlik Sense as any of the users in the file.
The settings in the config file are:
microsoft: # "Microsoft" OAuth2 provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <client ID>
clientSecret: <Client>
Field | Description |
---|---|
enable | Enable or disable this authentication provider. true/false. |
userDirectory | The Qlik Sense Enterprise user directory that will be used once the user has been authenticated by the authentication provider. |
userIdShort | The provider will return the user’s email address. If userIdShort is set to true , the @ character and email domain will be stripped from the email address returned by the provider. For example, “joe@company.com” would become just “joe”. true/false. |
clientId | Client ID from Microsoft |
clientSecret | Client secret from Microsoft |
These are the general steps to set up Microsoft for use with Butler Auth.
Log in to the Miceosoft Azure portal.
Go to the App registrations page.
The screen shots below show a minimum configuration - you should review all fields to make sure the configuration is correct for your specific use case.
On the application overview tab you find the Client ID, among other things.
On the Branding tab you can upload an image that’s shown when users authenticate.
On the Authentication tab you set the Redirect URIs. This is the URL where Butler Auth is running, appended with “/auth/microsoft/redirect”.
On the Secrets tab you find the Client secret that should be copied to the Butler Auth config file.
The settings in the config file are:
okta: # "Okta" provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
oktaDomain: <Okta domain from Google admin console> # E.q. https://myid-123456.okta.com'
idp:
Field | Description |
---|---|
enable | Enable or disable this authentication provider. true/false. |
userDirectory | The Qlik Sense Enterprise user directory that will be used once the user has been authenticated by the authentication provider. |
userIdShort | The provider will return the user’s email address. If userIdShort is set to true , the @ character and email domain will be stripped from the email address returned by the provider. For example, “joe@company.com” would become just “joe”. true/false. |
clientId | Client ID from Okta |
clientSecret | Client secret from Okta |
oktaDomain | The URL you get from Okta. Usually something like “sometext.okta.com |
idp | Can usually be left blank. |
These are the general steps to set up Okta for use with Butler Auth.
In the screen shots below Okta’s free tier is used - things might look different for you.
Sign into Okta. Go to the Applications
tab:
Create a new “Web” application and give it a good name:
Fill in Name
, Base URIs
(which is the Butler Auth URL) and Login redirect URIs
(which is Butler Auth’s Okta callback URL). Review the other fields to make sure they match your use case. Click Done
.
Add users as needed.
The settings in the config file are:
singleUser: # "Single user" provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userId: goran # A user that already exists in Qlik Sense. All access to Sense will be done using this user.
Field | Description |
---|---|
enable | Enable or disable this authentication provider. true/false. |
userDirectory | The Qlik Sense Enterprise user directory that will be used once the user has been authenticated by the authentication provider. |
userId | Qlik Sense user ID that all logins will use. |
A single web page provides an easy way to try out the different auth providers:
Each auth provider included on the demo site has a link that takes the user to Qlik Sense.
For example, clicking the Google icon the user will be sent to https://senseprod.ptarmiganlabs.net/ba-google
.
senseprod.ptarmiganlabs.net
is a Qlik Sense Enterprise on Windows server, with a virtual proxy called ba-google
(hint: ba=butlerauth).
That virtual proxy has the usual settings plus a link to a “authentication module” that should be used.
The authentication module is - surprise - part of Butler Auth. More specifically the REST API of Butler Auth has an endpoint named /auth/google
.
With Butler Auth’s REST API being hosted at https://qliksenseauth.ptarmiganlabs.net:8761
(this is all set in the main config file), the full URL for the virtual proxy’s authentication module is https://qliksenseauth.ptarmiganlabs.net:8761/auth/google
.
The list below should be a good starting point if you want to customize the demo site to your own server/network/Qlik Sense environment.
Butler Auth’s build in web server is always enabled, but must be configured.
Given the config below the web server will be running at https://qliksenseauth.ptarmiganlabs.net:8081
.
https is enabled using the specified certificate/key. In this case the certificate is not password protected (the password field is empty).
ButlerAuth:
server:
web: # The web/http server used to serve the sample login pages included in Butler Auth
host: qliksenseauth.ptarmiganlabs.net # Hostname of the http server. Would be container name when running under Docker.
port: 8081 # Port where the http server will listen
tls: # Used to secure the http server with TLS. I.e. https.
enable: true
cert: /path/to/cert/cert.cer
key: /path/to/cert.key
password:
You can have many virtual proxies in Qlik Sense, even if you have just a single Sense server.
Each virtual proxy implements exactly one authentication method, or uses anonymous access to Sense.
If you want to try all the auth providers offered by Butler Auth, you need to create one virtual proxy for each provider:
An example of a virtual proxy configuration for Google authentication is found up above on this page.
The demo site is included in the GitHub repository and in the image on Docker Hub. It’s located at /src/html
in the GitHub repository.
The html pages are reasonably basic, but a general understanding of html, css and Javascript is needed to understand how they work.
You must do some changes before using the demo site with your Sense server. Failing to do this will cause the authentication flows to fail, simply because the demo site won’t find your Sense server.
The needed changes are quite simple: Search for https://senseprod.ptarmiganlabs.net
in all files in the demo site and replace that URL with the URL to your Sense server.
Other than that, the pages only use paths relative to the http server’s base URL, meaning that the pages should work in your Sense environment without any changes. You might want to change look-and-feel etc though - feel free to use the provided pages as inspiration!
Butler Auth has an optional heartbeat feature, which when enabled will call a specific URL with a configurable interval.
A typical scenario is to use a monitoring tool such as Healthchecks.io to ensure that the heartbeats arrive on schedule.
That tool can then alert if the heartbeats don’t arrive on time.
Healthchecks.io is available both as a Docker image for self-hosting and as a SaaS offering.
Configuration of heartbeats is described here.
Here is a self-hosted Heahlthcheck.io instance used to monitor the Butler family of tools:
Another aspect of monitoring is to keep track of the internals of the service in question.
Butler Auth’s “uptime monitor” is an optional feature that can be enabled in the config file.
When enabled it will send metrics on how much memory Butler Auth uses to an InfluxDB database, as well as logging these metrics to the log files.
Logging to InfluxDB and log files can be individually enabled/disabled.
Once the metrics are in InfluxDB then can be viewed using Grafana:
The main config file has options for enabling Docker healthchecks.
If running Butler Auth in Kubernetes this feature can useful when setting up custom avaialability logic for K8s containers.
The production_template.yaml
config file looks like this:
ButlerAuth:
# Logging configuration
logLevel: info # Log level. Possible log levels are silly, debug, verbose, info, warn, error
fileLogging: false # true/false to enable/disable logging to disk file
logDirectory: log # Subdirectory where log files are stored. Absolute or relative path accepted.
# Heartbeats can be used to send "I'm alive" messages to any other tool, e.g. a infrastructure monitoring tool
# The concept is simple: The remoteURL will be called at the specified frequency. The receiving tool will then know
# that Butler Auth is alive.
heartbeat:
enable: false
remoteURL: http://my.monitoring.server/some/path/
frequency: 60000 # Milliseconds
# Docker health checks are used when running Butler Auth as a Docker container.
# The Docker engine will call the container's health check REST endpoint with a set interval to determine
# whether the container is alive/well or not.
# If you are not running Butler Auth in Docker you can safely disable this feature.
dockerHealthCheck:
enable: false # Control whether a REST endpoint will be set up to serve Docker health check messages
port: 12398 # Port the Docker health check service runs on (if enabled)
# Uptime monitor
uptimeMonitor:
enable: false # Should uptime messages be written to the console and log files?
frequency: 300000 # Milliseconds
logLevel: info # Starting at what log level should uptime messages be shown?
storeInInfluxdb:
enable: false
hostIP: <IP or host name>
hostPort: 8086
auth:
enable: false
username: user_joe
password: joesecret
dbName: butlerauth
instanceTag: DEV # Tag that can be used to differentiate data from multiple Butler instances
# Default retention policy that should be created in InfluxDB when Butler creates a new database there.
# Any data older than retention policy threshold will be purged from InfluxDB.
retentionPolicy:
name: 10d
duration: 10d
# Server and https settings
server:
rest: # The REST server is the authentication server called by Qlik Sense.
host: <FQDN> # Hostname of the REST server. Would be container name when running under Docker, otherwise something like qliksenseauth.mydomain.com.
port: 8761 # Port where the REST server will listen
rateLimit: # Used to limit number of authentication requests during a given time window. Used to prevent brute forcing attacks.
enable: false # Enable/disable rate limiting for this REST API. true/false.
windowSize: 60000 # How long (milliseconds) is the time window we're capping # of logins for? Default 5 min if not specified.
maxCalls: 100 # Max # of logins from Qlik Sense during time window above. Default 100 if not specified.
tls: # Many 3rd party auth providers require the OAuth 2 server to use https.
enable: true # Enable/disable https. While always recommended, https is strictly not needed for local file authentication, for example.
cert: /path/to/certfile.cer # TLS certificate file
key: /path/to/certfile.key # TLS key file
password: # Passphrase for TLS key file, if used
web: # The web/http server used to serve the sample login pages included in Butler Auth
host: <FQDN> # FQDN of the http server
port: 8081 # Port where the http server will listen
tls: # Used to secure the http server with TLS. I.e. https.
enable: true
cert: /path/to/certfile.cer
key: /path/to/certfile.key
password:
# Auth providers are responsible for authenticating users before they are forwarded to Qlik Sense Enterprise.
authProvider:
localFile: # "Local file" provider reads user data from a file on disk
enable: false
url: https://<FQDN>:8081 # URL where login UI for this provider is available
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userFile: ./config/users.yaml # YAML file containing usernames and passwords
ldap: # "LDAP" provider
enable: false
url: https://<FQDN>:8081 # URL where login UI for this provider is available
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
ldapServer: # Information about the LDAP server to authenticate against
host: <ldap(s)://ldap.mydomain.com> # Both normal (ldap://) and secure (ldaps://) LDAP is supported
port: 636 # Usually 389 for LDAP and 636 for LDAPS
bindUser: '<domain\username>' # Service account used to log into the LDAP server
bindPwd: <password> # Password of service account
searchBase: '<dc=...,dc=...,dc=...>' # Base path from which authentication attempts will start
searchFilter: '(&(objectcategory=person)(objectclass=user)(|(samaccountname={{username}})(mail={{username}})))' # Filter used to get info about users in LDAP server
tls:
# Settings here will override default TLS behaviour.
# Useful for example if your cert is for another domain wrt the host name of the LDAP server.
# If a setting is empty it will simply be ignored by Butler Auth.
# Necessary if the LDAP server isusing a self-signed certificate
# Should point to a PEM coded CA certificate file.
ca:
singleUser: # "Single user" provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userId: goran # A user that already exists in Qlik Sense. All access to Sense will be done using this user.
google: # "Google" OAuth2 provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
facebook: # "Facebook" OAuth2 provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
microsoft: # "Microsoft" OAuth2 provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <client ID>
clientSecret: <Client>
okta: # "Okta" provider
enable: false
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
oktaDomain: <Okta domain from Google admin console> # E.q. https://myid-123456.okta.com'
idp:
keycloak: # "Keycloak" provider
enable: true
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
clientId: <Client ID>
clientSecret: <Client secret>
host: <FQDN of Keycloak server> # E.g. https://keycloak.mydomain.com
realm: # E.g. ptarmiganlabs
authorizationURL: <URL> # E.g. https://keycloak.mydomain.com/auth/realms/<myrealm>/protocol/openid-connect/auth
tokenURL: <URL> # E.g. https://keycloak.mydomain.com/auth/realms/<myrealm>/protocol/openid-connect/token
userInfoURL: <URL> # E.g. https://keycloak.mydomain.com/auth/realms/<myrealm>/protocol/openid-connect/userinfo
auth0: # "Auth0" provider
enable: true
userDirectory: lab # Qlik Sense user directory that will be used for the authenticated user
userIdShort: true # If true, the email domain will be removed. I.e. "joe.smith@domain.com" will be changed to "joe.smith".
issuerBaseURL: <FQDN> # E.g. mycompany.eu.auth0.com
baseURL: <URL> # FQDN of Butler Auth, e.g. https://qliksenseauth.mycompany.com:8761'
clientId: <Client ID>
clientSecret: <Client secret>
# Settings relating to Qlik Sense
qlikSense:
# Certificates to use when calling Sense APIs. Get these from the Certificate Export in QMC.
certFile:
# If running under Docker, use these paths:
# clientCert: /nodeapp/config/certificate/client.pem
# clientCertKey: /nodeapp/config/certificate/client_key.pem
# clientCertCA: /nodeapp/config/certificate/root.pem
# If running as a native Node.js app, point to where the cert files are stored:
clientCert: /path/to/client.pem
clientCertKey: /path/to/client_key.pem
clientCertCA: /path/to/root.pem
clientCertPassphrase:
The default location for cert/key exports is (assuming a standard install of Qlik Sense) C:\ProgramData\Qlik\Sense\Repository\Exported Certificates\<name specified during certificate export>
The files needed by Butler Auth are client.pem
, client_key.pem
and root.pem
.
Passport.js is an open source library focusing on authentication.
From their own site:
Passport is authentication middleware for Node.js. Extremely flexible and modular, Passport can be unobtrusively dropped in to any Express-based web application. A comprehensive set of strategies support authentication using a username and password, Facebook, Twitter, and more.
Butler Auth uses Passport.js for many (but not all) authentication strategies.
Given that Passport.js uses a consistent interface for all authentication strategies it’s usually quite easy to add additional authentication providers to Butler Auth.
Cover page
Original by Jon Moore on Unsplash.
Some editing done before using it on this site.
Security is a whole field in its ownn.
What’s considered secure in one company might be considered insecure in another.
It’s a good idea to review your tools and services every now and then, for example making sure they are updated to include the latest secutity patches etc.
When in doubt, be paranoid.
Configure the firewall on the server where Buter Auth is running to only accept connections from IPs that matter. While convenient and tempting to leave servers open with respect to network traffic, it’s usually a very bad idea. Reduce the attack vectors whenever possible.
Butler Auth uses various Node.js modules from npm. If concerned about security, you should review these dependencies and decide whether there are issues in them or not.
Same thing with Butler Auth itself - while efforts have been made to make it secure, you need to decide for yourself whether the level of security is enough for your use case.
Butler is continuously checked for security vulnerabilities by using GitHub security audit, Snyk, npm audit and other tools.
That said, all software - including Butler Auth - has bugs and security issues.
Once again: YOU are responsible for determining if Butler Auth meets YOUR security requirements. The legal text is found in the MIT license.
Butler Auth uses https for all communication with Sense, using Sense’s certificates for authentication.
Butler is distributed under the MIT license.
MIT License
Copyright (c) 2020-2021 Göran Sander
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This documentation site was built using Hugo and consists of static web pages hosted on GitHub Pages.
GitHub probably keep log files for GitHub Pages, your visit to this documentation site is thus likely to be recorded there.
Google Analytics is used to track general site usage.
Aggregated Google Analytics data may be used to determine, and in some cases publicly communicate, how popular the site is.
Examples of aggregated metrics are how many users have visited the site, from where in the world they accessed the site, which specific pages are most visited etc.
No detailed Google Analytics data for this site will be shared with any third parties.