Using qlik-cli with Qlik Sense Enterprise client-managed Repository API (QRS)
Overview
In this tutorial, you are going to learn how to authorize qlik-cli to connect to Qlik Sense Enterprise client-managed instances using JSON web tokens (JWT).
- Create a public / private key pair for signing JWTs
- Configure JWT virtual proxy
- Create a JWT
- Configure a context in qlik-cli
- Test the connection
- Review the available Qlik Repository Service (QRS) commands
- Review the Token.js code
Requirements
- qlik-cli version 1.5.0 or higher
- A Qlik Sense Enterprise client-managed instance
- Access to create virtual proxies in Qlik Sense. This demo uses an account with the RootAdmin role assigned.
Create a public / private key pair for signing JWTs
Open a terminal window and use openssl to generate public and private keys. Store the private key someplace safe and don’t share it. The public key is used in the configuration section.
openssl genrsa -out privatekey.pem 4096
openssl req -new -x509 -key privatekey.pem -out publickey.cer -days 1825
Note If you are using Windows, you need to download and install openssl. You can obtain a copy of openssl from here.
Configure JWT virtual proxy
Open a browser and authenticate to the Qlik Management Console (QMC) on your
client-managed site at https://<server_hostname>/qmc
.
In the menu panel on the left side of the screen, click Virtual proxies in the Configure System section.
At the bottom of the screen, click the Create new button.
In the virtual proxy configuration screen, use the menu on the right side of the screen to navigate through the configuration steps.
Click Identification and provide a description, a prefix, and a session cookie header name.
If you are copying the screenshot, enter jwt for the description and prefix, and append it to the end of the cookie header name.
Note All three values must be unique within a Qlik Sense instance. It’s not possible to have virtual proxies that share prefixes or session cookies.
Click Authentication and set the inputs to the following values:
- Anonymous access mode: No anonymous user
- Authentication method: JWT
Changing the authentication method surfaces additional inputs that you must populate.
- JWT certificate: Open the public key file created earlier, copy the entire contents as-is, and paste it into the input box
- JWT attribute for UserID: This is the key in the JWT payload that the virtual proxy looks for to get the userid
- JWT attribute for UserDirectory: This is the key in the JWT payload that the virtual proxy looks for to get the user directory
- Intended audience: This is a parameter for signature verification of the JWT when it’s passed from the client to the virtual proxy. If the audience in the JWT doesn’t match the value input here, authorization is going to fail.
Note It’s possible to map attributes from a JWT to Qlik Sense attributes, however, that capability is out of scope for this tutorial. See Virtual proxy configuration in Qlik help.
Click Load Balancing from the menu on the right side of the screen and add a new server node. In this tutorial, the Central node is used.
Click Advanced. Uncheck the https secure attribute and set the SameSite attribute to “No Attribute.”
Note Only perform this step for testing purposes only. Make sure the configuration is secure in production environments. See Editing a Virtual Proxy in Qlik help for more information on the secure and SameSite attributes.
In the Advanced section there is a Host allow list. If you are not connecting to this Qlik Sense server via it’s machine name, then add the domain or IP address of the Qlik Sense server to the Host allow list. In this example, the connection to the server is made via its IP address, therefore the IP address has been added to the allow list.
With the virtual proxy configured, click Apply.
Click the Proxies menu item on the right side of the screen. This brings up the list of proxies this virtual proxy may be linked to.
Press the Link button and add the Central proxy to the configuration.
JWT format for Qlik Sense authorization
The JWT is made of three pieces:
- The payload.
- The signing options.
- The private key for signing the token.
The payload
Here is a sample payload for a Qlik JWT used with Qlik Sense Enterprise on Windows. You need to substitute values that are valid for your environment.
// Creating a Qlik Sense on Windows payload.
const payload = {
userid: 'harry',
userdirectory: 'qsefw',
name: 'Hardcore Harry',
email: 'harry@example.com',
groups: ['Adminstrators', 'Sales', 'Marketing'],
};
The signing options
Here is a sample signing options object for the JWT you are creating:
const signingOptions = {
algorithm: 'RS256',
expiresIn: '365d',
audience: '112adams',
};
Note The format of the signing options and the payload of a JWT for Qlik Sense Enterprise on Windows differs from Qlik Sense Enterprise SaaS. For more information on Qlik Sense Enterprise SaaS JWTs, see the tutorial on creating signed tokens for jwt authorization.
The private key for signing the token
Read the private key into the token generator using fs and then create the token using the jsonwebtoken node module.
// This is the private key to encrypt the JWT. This example uses certificates
// generated by the Qlik Sense Enterprise on Windows server.
const jwtEncryptionKey = fs.readFileSync('<path to the private key pem file');
// Create the token
const token = jsonWebToken.sign(payload, jwtEncryptionKey, signingOptions);
Run the code in a command line or terminal window (full code snippet at the end
of the tutorial) node token.js
. In the console window, the signed JWT appears
and can be used as a bearer token for accessing Qlik Sense on Windows.
## Bearer token
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiJoYXJyeSIsInVzZXJkaXJlY3RvcnkiOiJxc2VmdyIsIm5hbWUiOiJIYXJkY29yZSBIYXJyeSIsImVtYWlsIjoiaGFycnlAZXhhbXBsZS5jb20iLCJncm91cHMiOlsiQWRtaW5zdHJhdG9ycyIsIlNhbGVzIiwiTWFya2V0aW5nIl0sImlhdCI6MTYwMzgxOTYyOSwiZXhwIjoxNjM1MzU1NjI5LCJhdWQiOiIxMTJhZGFtcyJ9.gDWFqJ8fZbo9QpF52CnlhKCMsHal2AcobIVwhVCpnbLfpmc-Z_k4uUWGh2TxaSucjQ5-k5I9s9sNgIPskqaVQN2JanFXxIJKRFow9LbuSbImZs74RsQ6TqsoJTu7_5eKLv2VRAqoh6Tqabl5vma1JdhHbsTKGixt8yGZI7Q2QNjObQq8hAh6VveNWcUVkB60LEMOPiipij7VTKQ7IQg-rG4XA8xgYxbOb6i3Q6miY4kGSGujbsjtYLevEJQlEZtij2JMMDeH_nwH2MWhWhOBL1TpAAUKkCOxPFDjGacxGvkObAOFjL-Ztx0LdVwF2BXxVerQ1xKyl0YpLErS4d576Q
Configure a context in qlik-cli
Open a terminal window and use the context command to add the Qlik Sense Enterprise on Windows server to qlik-cli.
##qlik context create <contextName> --server <serverUrl> --server-type windows --api-key <JWTToken>
qlik context create QSEoW --server https://192.168.254.243/jwt --server-type windows --api-key eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiJoYXJyeSIsInVzZXJkaXJlY3RvcnkiOiJxc2VmdyIsIm5hbWUiOiJIYXJkY29yZSBIYXJyeSIsImVtYWlsIjoiaGFycnlAZXhhbXBsZS5jb20iLCJncm91cHMiOlsiQWRtaW5zdHJhdG9ycyIsIlNhbGVzIiwiTWFya2V0aW5nIl0sImlhdCI6MTYwMzgxOTYyOSwiZXhwIjoxNjM1MzU1NjI5LCJhdWQiOiIxMTJhZGFtcyJ9.gDWFqJ8fZbo9QpF52CnlhKCMsHal2AcobIVwhVCpnbLfpmc-Z_k4uUWGh2TxaSucjQ5-k5I9s9sNgIPskqaVQN2JanFXxIJKRFow9LbuSbImZs74RsQ6TqsoJTu7_5eKLv2VRAqoh6Tqabl5vma1JdhHbsTKGixt8yGZI7Q2QNjObQq8hAh6VveNWcUVkB60LEMOPiipij7VTKQ7IQg-rG4XA8xgYxbOb6i3Q6miY4kGSGujbsjtYLevEJQlEZtij2JMMDeH_nwH2MWhWhOBL1TpAAUKkCOxPFDjGacxGvkObAOFjL-Ztx0LdVwF2BXxVerQ1xKyl0YpLErS4d576Q
To use the context after setting it, enter qlik context use <contextName>
Test the connection
In the terminal window opened earlier, test the connection by entering the command to list the applications on the server.
Note Access qrs commands in qlik-cli starting with
qlik qrs
. In addition, when you connect to the server using the qlik-cli, if there is no trusted certificate installed on the system certificate validation fails. Instruct qlik-cli to ignore certificate validation errors by using the--insecure
flag.
# set the context to the Qlik Sense Enterprise on Windows server
# replacing <contextName> with the context name set in qlik-cli
# qlik context use <contextName>
qlik context use QSEoW
# list the applications on the server
qlik qrs app ls --insecure
// returns JSON like below
[
{
"id": "931d847e-b36a-4511-9547-6cc0f46b1b9c",
"name": "ConsumerSales",
"appId": "",
"publishTime": "2020-10-21T12:48:16.987Z",
"published": true,
"stream": {
"id": "387f4d65-c171-4120-9db0-3cd537b469a8",
"name": "CNPDemo",
"privileges": null
},
"savedInProductVersion": "12.688.0",
"migrationHash": "64d115e925e2167bba72939c2d8a80e6beef4a56",
"availabilityStatus": 5,
"privileges": null
}
]
List of available Qlik Repository Service (QRS) commands
Here is a list of commands available in qlik-cli to interact with QRS.
qlik qrs --help
Usage:
qlik qrs [flags]
qlik qrs [command]
Available Commands:
app Manage apps
appcontent Upload or remove content used in apps
applicationlog Get the log for a specific application
appstatus Get migration status of an app
binarydownload Download binary
cache Empty the cache in the Qlik Sense Repository Service (QRS)
compositeevent Manage composite event triggers for specific
tasks e.g. reload
compositeeventoperational Get the status of a composite event
compositeeventruleoperational Get the rule status of a composite event
contentlibrary Manage static content that can be used in
e.g. Qlik Sense apps
custom Manage custom resources
custompropertydefinition Manage custom properties that can be applied to a resource
dataconnection Manage data connections that enables selection
and loading of data from different data sources
download Download exported apps, reload tasks or
SAML metadata
executionresult Get the execution result for a specific task
executionsession Get the status of a specific task during execution
extension Manage extensions used for apps
managementconsolelog Get the log for the management console
reloadtask Create reload tasks and corresponding triggers (events)
reloadtaskoperational Get the status of a reload task
schemaevent Manage schema event triggers
schemaeventoperational Get the status of a schema event
selection Manage selections that refer to a specific enitity type
servicestatus Get status of the service
staticcontent Get a list of the static content files in,
for example, a content library.
staticcontentreference Get the mapping between the external path
and the physical file in the repository
for all static content
staticcontentreferencebase Get the mapping between the external path and
the physical file in the repository for base
static content
stream Manage streams that are used for published apps
tag Manage tags that can be applied to a resource
task Manage tasks that can be executed by
the Qlik Sense Scheduler
taskoperational Get status of a task
user Manage resources owned by a specific user
userdirectory Manage user directory connectors (UDCs)
Token.js code sample
This is the full code to generate a JWT.
const jsonWebToken = require('jsonwebtoken');
const fs = require('fs');
// This is the private key to encrypt the JWT. This example uses certificates
// generated by the Qlik Sense Enterprise on Windows server.
const jwtEncryptionKey = fs.readFileSync('<path to the private key pem file');
// kid and issuer have to match with the IdP config and the audience has to
// be qlik.api/jwt-login-session
const signingOptions = {
algorithm: 'RS256',
expiresIn: '365d',
audience: '112adams',
};
// Creating a Qlik Sense on Windows payload.
const payload = {
userid: 'harry',
userdirectory: 'qsefw',
name: 'Hardcore Harry',
email: 'harry@example.com',
groups: ['Adminstrators', 'Sales', 'Marketing'],
};
// Create the token
const token = jsonWebToken.sign(payload, jwtEncryptionKey, signingOptions);
console.log(token);