Application Proxies

Configure standalone Mamori application/API proxies for access control and data privacy on the wire. Configuration topics include:

  • JSON filters

  • Masking

  • SSL

  • Logging

Portal Server Settings → Proxies → HTTP listener ports and PAC are documented under Proxies. For installation and deployment, see Install Application Proxy.

Configuration file JSON format

JSON files can be used to configure an application proxy.

To use a JSON configuration file when running a proxy in standalone mode pass in the -json=<jsonfile> parameter to the http_proxy_standalone.sh script. For example:

... -json="myfilters.json"

The config file can be uploaded to the Mamori server to manage the configuration in the server.

The JSON file configuration format is an array of API filters which define the rules for intercepting incoming HTTP/S client requests. Each filter specifies the interception criteria and and one or more MASK transformations to apply to the API response data.

  • each filter defines a series of matching conditions to be able to identify which client HTTP request to intercept
  • each transformation specifies the response attributes to mask elementSpec and the MASK function to apply function

For example:

[
  {
    "name": "REST API",
    "system": "testsystem",
    "path": "/my-rest-api", <-- API endpoint to target
    "method": null,   
    "queryParameters": null,
    "headers": null,
    "body": null,
    "owner": "test",
    "active": 1,
    "transformations": [
      {
        "name": "default",          <-- user/role to apply to
        "priority": 1,
        "elementSpec": "$..price",  <-- JSON PATH for all price fields
        "function": "MASK FULL",    <-- Masking function to apply
      }
    ]
  },
  {
    "name": "XML API",
    "system": "testsystem",
    "path": "/my-xml-api", <-- API endpoint to target
    "method": null,
    "queryParameters": null,
    "headers": null,
    "body": null,
    "owner": "test",
    "active": 1,
    "transformations": [
      {
        "name": "default",         <-- user/role to apply to
        "priority": 1,
        "elementSpec": "//salary", <-- XML PATH for all salary fields
        "function": "MASK FULL",   <-- Masking function to apply
      }
    ]
  }
]
  • name - the filter/rule name
  • system - the system to apply the rule to
  • path - the HTTP request URL path to match on (regexp e.g .* is supported) e.g /info
  • method - the HTTP request method to match on e.g GET, POST, PUT
  • queryParameters - the HTTP request query parameters e.g op=getUserData
  • headers - the HTTP request headers to match on e.g X-OP=getUserData
  • body - the HTTP request body to match on e.g (regexp e.g .* is supported) e.g .*SOMEKEY

*Transformations - specify fields to mask **

To specify which response fields/attributes to mask set the filter attribute elementSpec.

The proxy supports 2 elementSpec types:

For example:

To target all title fields in a JSON response use the JSON path: $..title

To target all title fields in an XML response us the XML path: //title

Note, if the XML payload uses namespaces (as is common in SOAP responses) you must specify the namespace in your xpath e.g //ns:title or use local-name() if you don't know the specific namespace e.g //*\[local-name()='title'\].

Transformations - applying masking functions

Each transformation specifies the set of XML/JSON fields to target (elementSpec), the role/user that the transform applies too (name),and the mask/hash function to apply (function).

Masking function reference

FunctionDescription
MASK ALLMasks all characters with X or supplied mask character
MASK FIRSTMasks first N characters with X or supplied mask character
MASK LASTMasks last N characters with X or supplied mask character
MASK SUBSTRINGMasks a substring (start,end) characters with X or supplied mask character
MASK CCMasks the digits in a CC number
MASK SSNMasks all digits in a SSN
MASK PHONEMasks the last 4 digits of a phone number
MASK DATETIMEGenerates a random datetime or adds a days. If the input is String the datetime format must be supplied as a function arg
MASK DATEGenerates a random date or adds a days. If the input is a String, the date format must be supplied as a function arg
MASK DECIMALGenerates a random double to the specified number of digits and precision (decimals)
MASK INTGenerates a random long of the same length as the input
MASK EMAILMasks all characters with * or supplied mask character
MASK EMAIL KEEP SUFFIXMasks domain characters with * or supplied mask character
MASK EMAIL KEEP DOMAINMasks suffix characters with * or supplied mask character
MASK OUTMasks the first % with X or supplied mask character. Percentage defaults to 0.6 if not specified
MASK RANDOMMasks letters and digits with randomly generated letters and digits
MASK HASHMasks letters and digits with supplied hashing function e.g "MD5"
MASK HASH NUMERICMasks letters and digits with supplied hashing function e.g "SHA-1" to supplied length
MASK ROWQLIK only. Masks all rows where the column value matches the supplied regexp in the function args.
REVEALReveal a masked attribute

Dealing with SSL

Overview

By default the application/API proxies use a self signed certificate. Some browsers such as Chrome (and also curl) will raise an SSL error if you attempt to use HTTPS to access your API via the proxy.

Bypass the certificate check

If using CURL you can bypass the certificate check by using the curl flag --insecure.

For some browsers, it is possible to configure the browser to ignore the cert check.

Otherwise, you can either configure the proxy to use a valid certificate and private key for the domain you are proxying or deploy the proxy behind HAPROXY or NGINX or APACHE which handles the SSL terminator - this is the recommended option.

To use a certificate and key with a proxy

To add a cert/key, configure the location of the certificate and key files in config/proxy-<system>.properties:

mockserver.dynamicallyCreateCertificateAuthorityCertificate=false
mockserver.privateKeyPath=...     <-- your private key file
mockserver.x509CertificatePath=...<-- your certificate file

To generate a certificate for your domain you can use sites such as letsencrypt.org.

Example SSL/proxy forward NGINX config

An example NGINX for handling SSL and forwarding to a Qlik proxy running on a local port.

upstream qlik {
    server 127.0.0.1:8080; <-- Qlik proxy
}

server {
       server_name qlik.foo.com;

       listen 80;
       listen [::]:80;

       root /var/www/html;

       index some-file-that-does-not-exist;
       error_page 403 @gotohttps;
       error_page 404 @gotohttps;

       location / {
                try_files $uri $uri/ =404;
       }

       location @gotohttps {
                rewrite ^ https://$host$request_uri permanent;
       }
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}


server {
       server_name qlik.foo.com;

        # SSL configuration
        #
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        index index.html;
        root /var/www/html;

        ssl_certificate /etc/nginx/ssl/nginx.crt;
        ssl_certificate_key /etc/nginx/ssl/nginx.key;

        location / {
             proxy_pass http://qlik/;
             proxy_redirect off;
             proxy_http_version 1.1;
             proxy_set_header X-Forwarded-For $remote_addr;
             proxy_set_header Connection $connection_upgrade;
             proxy_set_header Upgrade $http_upgrade;
             proxy_read_timeout 7d;
             proxy_send_timeout 7d;
        }
}

Extracting the user from an HTTP/S request

Out of the box the application/API proxies provide two mechanisms to identify the requesting user:

  • Simple - extracts user details from a request header, query parameter or form field using a simple regular-expression based mechanism. This mechanism works with schemes such as Basic Authorisation.

  • Token - Maps a token to a user. This assumes signin occurs via the proxy and can only be used in a non clustered environment.

Method one: Simple

  • Open the config/proxy-<system>.properties configuration file in a terminal window.

  • Set the user extraction mechanism to simpleauth. Add the following configuration to extract the user from a request Authorization HTTP header:

authentication=simpleauth
simpleauth.header=Authorization        <-- or simpleauth.formfield=user or simpleauth.queryparam=user or simpleauth.body.regexp=.. or simpleauth.body=xpath or json path
simpleauth.header.regexp=.*

Will handle basic Authorization:

Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l <-- user is extracted as Aladdin

Alternatively, if using a different header, specify that and use a Regular Expression to extract the username from the header value:

simpleauth.header=MySpecialAuthHeader       <-- name of the header to use
simpleauth.header.regexp=.*                 <-- Optional Regular expression to extract the username from the header contents (can be null)

Method two: Token

This mechanism extracts the user name from a signin/login and tracks the token to allow the user to be identified on subsequent requests.

This mechanism only works if the proxy is the only way to access the API and is able to intercept the signin.
  • Open the config/proxy-<system>.properties configuration file in a terminal window.

  • Set the extraction mechanism to tokenauth. Add the following configuration to extract the login token and user from an auth server

authentication=tokenauth

# Authorisation server
auth.remotehost=....
auth.remoteport=443

# On a user sign in
tokenauth.signin.path=(/users/sign_in|/users/session_data)
tokenauth.signin.method=

# User name and token extraction. Specify how to extract the user and token on sign in
tokenauth.user.body=$..email        <-- can also be in a header, query parameter or form field or body
tokenauth.token.body=$..token       <-- can also be in a header, query parameter or form field or body

# On a user signout
# Stops token from being tracked
tokenauth.signout.path=/users/sign_outec
tokenauth.signout.method=DELETE

# On all other requests extract token from token header
simpleauth.header=token

Once the user has been extracted, the proxy can determine the user's roles and determine which masking rules to apply.

If the user cannot be determined from the request the proxy will fallback to the default rules

Monitoring and Logging

By default the proxies publish various metrics about the JVM and endpoints to the proxy log and the Mamori server monitoring sub-system.

The metrics can be viewed inside the the Mamori server Influx/Grafana dashboards.

By default two monitoring channels are enabled:

  • InfluxDb
  • Proxy Log

More information on Influx configuration properties can be found at influx configuration

Upgrading Grafana

To upgrade Grafana run the command below in your Mamori server.

sudo docker exec -it mamori /opt/mamori/grafana/update-grafana.sh

To Activate

  • Open the monitoring properties configuration file at /opt/mamori/server/http-proxy-<version>/config/monitoring.properties.
  • Set the following properties:
influx.enabled=true
logging.enabled=true

To Deactivate

  • Open the monitoring properties file at /opt/mamori/server/http-proxy-<version>/http-proxy-<version>/config/monitoring.properties.

  • Set the following properties:

influx.enabled=false
logging.enabled=false
If influx is not in use set `influx.enabled=false`

Proxy log files

  • Application Proxy log -- /opt/mamori/server/http-proxy-<version>/log/proxy-<system>-<instance>.log
  • Service issues log -- /var/log/syslog

Proxy healthcheck endpoint

The proxy heartbeat/healthcheck is on http/s:<proxy host>:<port>/healthcheck. If the proxy is up, it will return a status 200.


Edit this page on GitHub Updated at Sat, Sep 12, 2026