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
elementSpecand the MASK function to applyfunction
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 namesystem- the system to apply the rule topath- the HTTP request URL path to match on (regexp e.g .* is supported) e.g /infomethod- the HTTP request method to match on e.g GET, POST, PUTqueryParameters- the HTTP request query parameters e.g op=getUserDataheaders- the HTTP request headers to match on e.g X-OP=getUserDatabody- 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 JSON data use json-path, which can be tested at Online json-path tester
-
For SOAP/XML data use XPath, which can be tested at Online XPath tester
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
| Function | Description |
|---|---|
| MASK ALL | Masks all characters with X or supplied mask character |
| MASK FIRST | Masks first N characters with X or supplied mask character |
| MASK LAST | Masks last N characters with X or supplied mask character |
| MASK SUBSTRING | Masks a substring (start,end) characters with X or supplied mask character |
| MASK CC | Masks the digits in a CC number |
| MASK SSN | Masks all digits in a SSN |
| MASK PHONE | Masks the last 4 digits of a phone number |
| MASK DATETIME | Generates a random datetime or adds a days. If the input is String the datetime format must be supplied as a function arg |
| MASK DATE | Generates a random date or adds a days. If the input is a String, the date format must be supplied as a function arg |
| MASK DECIMAL | Generates a random double to the specified number of digits and precision (decimals) |
| MASK INT | Generates a random long of the same length as the input |
| MASK EMAIL | Masks all characters with * or supplied mask character |
| MASK EMAIL KEEP SUFFIX | Masks domain characters with * or supplied mask character |
| MASK EMAIL KEEP DOMAIN | Masks suffix characters with * or supplied mask character |
| MASK OUT | Masks the first % with X or supplied mask character. Percentage defaults to 0.6 if not specified |
| MASK RANDOM | Masks letters and digits with randomly generated letters and digits |
| MASK HASH | Masks letters and digits with supplied hashing function e.g "MD5" |
| MASK HASH NUMERIC | Masks letters and digits with supplied hashing function e.g "SHA-1" to supplied length |
| MASK ROW | QLIK only. Masks all rows where the column value matches the supplied regexp in the function args. |
| REVEAL | Reveal 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>.propertiesconfiguration file in a terminal window. -
Set the user extraction mechanism to
simpleauth. Add the following configuration to extract the user from a requestAuthorizationHTTP 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.
-
Open the
config/proxy-<system>.propertiesconfiguration 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.
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
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.