HTTP Server¶
TLS¶
App Suite Proxy can be used for TLS termination of HTTP requests. The Server can be configured to use one certificate for all incoming requests or utilize Server Name Indication (SNI) to choose a different certificate from the configured keystore for each host. Each certificate has to provide the hostname in its alternative name extension. If only one certificate is present in the keystore, this certificate is used without any hostname matching. Wildcard certificates are also supported, from first subdomain level, like *.appsuite.com or *.customer.appsuite.com.
Configuration¶
Configuration takes place via properties in application.properties.
- zuul.ssl.openssl.allow
Optional Offloads TLS termination to OpenSSL via Java JNI. See https://netty.io/wiki/forked-tomcat-native.html for details. App Suite Proxy links and ships the
io.netty:netty-tcnative-boringssl-staticlibrary for that purpose.This will also affect outbound connections (Backend Pools::TLS)!
Default:
falseReloadable:
true- proxy.tls.enabled
Optional: Enables TLS
Default:
falseReloadable:
falseEnvVar:
PROXY_TLS_ENABLED- proxy.tls.port
Manadatory for TLS: TLS port
Default:
8443Reloadable:
falseEnvVar:
PROXY_TLS_PORT- proxy.tls.keystore.type
Manadatory for TLS: Keystore type
Default:
PKCS12Reloadable:
falseEnvVar:
PROXY_TLS_KEYSTORE_TYPE- proxy.tls.keystore
Manadatory for TLS: Path to keystore file
Default:
<empty>Reloadable:
falseEnvVar:
PROXY_TLS_KEYSTORE- proxy.tls.keystore.pass
Manadatory for TLS: Password to open keystore
Default:
<empty>Reloadable:
falseEnvVar:
PROXY_TLS_KEYSTORE_PASS- proxy.tls.ciphers
Optional: Set the cipher suites that should be supported
Default:
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
EnvVar:
PROXY_TLS_CIPHERS- proxy.tls.protocols
Optional: Set the protocols that should be supported
Default:
TLSv1.2, TLSv1.1, TLSv1Reloadable:
falseEnvVar:
PROXY_TLS_PROTOCOLS
Server Name Indication¶
Since SNI is enabled whenever TLS is enabled, this feature can be used by simply adding new certificates to the keystore and ensuring, that the hostname is provided in the certificates alternative name extension.
Note
So far, OpenSSL is not supported in cooperation with the SNI feature. If OpenSSL is desired, one single certificate should be present in the keystore.
Compression¶
GZip compression of HTTP response payload is supported and enabled by default. Response payloads are compressed, if the content type is known to be compressible and the HTTP request contained gzip as part of an Accept-Encoding header. In addition the content must exceed a certain size to be compressed.
Origin responses that are already compressed are streamed through as is and not re-compressed.
Configuration¶
Configuration takes place via properties in application.properties.
- zuul.response.gzip.filter.enabled
Optional: En-/disable GZip compression
Default:
trueReloadable:
true- zuul.min.gzip.body.size
Optional: Minimum response body size to apply compression in bytes
Default:
860Reloadable:
true- zuul.gzip.contenttypes
Optional: Comma-separated list of content types that apply for compression
Default:
text/html, application/x-javascript, text/css, application/javascript, text/javascript, text/plain, text/xml, application/json, application/vnd.ms-fontobject, application/x-font-opentype, application/x-font-truetype, application/x-font-ttf, application/xml, font/eot, font/opentype, font/otf, image/svg+xml, image/vnd.microsoft.icon
Reloadable:
true
PROXY Protocol¶
The PROXY protocol provides a convenient way to safely transport connection information such as a client’s address, client port and protocol across multiple layers of NAT or TCP proxies.
Configuration¶
The following settings are applicable to application.properties.
- proxy.proxyprotocol.expected
Optional: A boolean value to enable/disable PROXY protocol support. If enabled and a request was sent using PROXY protocol:
the original client IP and port are used as input for X-Forwarded headers
the original client IP is checked against any client IP restriction
Default:
falseReloadable:
falseEnvVar:
PROXY_PROTOCOL_EXPECTED
Example Setup¶
Find below an example configuration for an HAProxy docker container that has PROXY protocol enabled.
## Docker Compose
version: '3'
services:
haproxy:
image: haproxy:1.9.6
volumes:
- ./haproxy.config:/usr/local/etc/haproxy/haproxy.cfg:ro
ports:
- 80:80
expose:
- "80"
container_name: 'haproxy'
## Haproxy Config
global
maxconn 50
debug
defaults
mode tcp
timeout connect 5s
timeout client 25s
timeout server 25s
timeout queue 10s
frontend local.ox
bind 172.18.0.2:80
default_backend proxy
backend proxy
balance roundrobin
server server1 host.docker.internal:8080 send-proxy
## IP's and Ports
172.18.0.2:80 -> Container IP : Port
host.docker.internal:8080 -> appsuite-proxy IP : Port
Enable proxy protocol in configfile with send-proxy or send-proxy-v2. Disable by deleting the keywords.
For a local setup replace container- and appsuite-proxy IP with localhost. Finally start the HAProxy with haproxy -f cfgfile
Management Endpoint¶
App Suite Proxy comes with an additional management endpoint which allows administrators and third party systems to get access to runtime environment. Following topics are currently covered:
Prometheus Metrics
Microprofile Health Check
Configuration Reload
To enable management endpoint on startup set configuration property proxy.admin.port.enabled to
true. For a complete reference to all possible configuration properties and their defaults see section Settings.
Hint
To get an overview of all exposed endpoints open root entry at http://<server>:<port>
Settings¶
Note
All properties can be found in application.properties. If a property is missing, not set or the value is not in range the default value will be used.
- proxy.admin.port.enabled
Enables Management Endpoint
Default:
falseReloadable:
falseEnvVar:
PROXY_ADMIN_PORT_ENABLED- proxy.admin.port
The Management Endpoint Port. Supported port range 8081-9999
Default:
8888Reloadable:
falseEnvVar:
PROXY_ADMIN_PORT- proxy.admin.http.errorresponse.enabled
Get a detailed error message in case of any HTTP Error (4xx, 5xx). This property can be changed on runtime.
Default:
falseReloadable:
trueEnvVar:
PROXY_ADMIN_HTTP_ERRORRESPONSE_ENABLED- proxy.health.default.procedures.enabled
Register default health check procedures. See Developers Guide for prerequisites.
Default:
falseReloadable:
falseEnvVar:
PROXY_HEALTH_DEFAULT_PROCEDURES_ENABLED- proxy.health.default.package
Classes within this package will be registered on server startup. See Developers Guide for prerequisites.
Default:
io.ox.proxy.health.impl.checksReloadable:
falseEnvVar:
PROXY_HEALTH_DEFAULT_PACKAGE- proxy.health.jvm.threadcount.max
Health Check Threads- After exceeding this value the health check change to DOWN. Supported range 1 - Integer.MAX_VALUE. This property can be changed on runtime.
Default:
50Reloadable:
trueEnvVar:
PROXY_HEALTH_JVM_THREADCOUNT_MAX- proxy.health.jvm.heapmemory.maxpercentage
Health Check Memory - After exceeding this value the health check change to DOWN. 0.01 -> 1%, 0.99 -> 99% of max heap. Supported range 0.01 - 0.99. This property can be changed on runtime.
Default:
0.9Reloadable:
trueEnvVar:
PROXY_HEALTH_JVM_HEAPMEMORY_MAXPERCENTAGE- proxy.health.http
Health Check HTTP - If Endpoint is not available health check change to DOWN. If no value is present health check will be skipped. This property can be changed on runtime.
Default:
<empty>Reloadable:
trueEnvVar:
PROXY_HEALTH_HTTP- proxy.admin.openapi.enabled
Creates an additional Open API Endpoint when enabled. Endpoint is then available under
{{baseUrl}}/openapi,{{baseUrl}}/openapi.json,{{baseUrl}}/openapi.yaml. Must be set before Server Startup.Default:
falseReloadable:
falseEnvVar:
PROXY_ADMIN_OPENAPI_ENABLED- proxy.admin.properties.sanitizekeys
Property names containing one the given keys will be sanitized when exposing via HTTP API. The values of well known properties will be sanitized even if this parameter is not set. Those values are
.password,.secret,.key.,.token,.credentials. By setting this property keys will be added as additional keys to the list. Does not support regular expressionsDefault:
falseReloadable:
falseEnvVar:PROXY_ADMIN_PROPERTIES_SANITIZEKEYS- proxy.admin.properties.filter
Use positive filter where only property names matches the given value will be exposed via HTTP API. Leave this blank will disable the filter and lead to exposing all properties. Filter does not support regular expressions
Default: `` ``
Reloadable:
trueEnvVar:PROXY_ADMIN_PROPERTIES_FILTER
Sample¶
A sample configuration may look like this:
##################################################
##Management Tooling
##################################################
proxy.admin.port.enabled=true
proxy.admin.port=
proxy.admin.http.errorresponse.enabled=
proxy.admin.openapi.enabled=
###################################################
##Microprofile - Health Checks
###################################################
proxy.health.default.procedures.enabled=true
proxy.health.default.package=io.ox.proxy.health.impl.checks
proxy.health.jvm.threadcount.max=
proxy.health.jvm.heapmemory.maxpercentage=
proxy.health.http=
Note
This configuration will start the management listener on port 8888 and register all default health checks. Empty parameters will fall back to their default.
Microprofile Health Check¶
App Suite Proxy comes with an implementation of Microprofile Health API.
Some basic health checks are available by default and will be registered when enabled (see Settings). According to the API specification these health checks will be exposed to /health /health/live /health/ready.
Payload from http://<server>:<port>/health looks like the following example:
{
"status": "DOWN",
"checks": [
{
"name": "threads",
"state": "UP",
"data": {
"max thread count": 50,
"daemon thread count": 7,
"monitor deadlocked thread count": 0,
"thread count": 13,
"deadlocked thread count": 0,
"started thread count": 13,
"peak thread count": 13
}
},
{
"name": "http-check",
"state": "DOWN",
"data": {
"error": "java.net.ConnectException: Connection refused (Connection refused)",
"URI": "http://localhost:9999/ping"
}
},
{
"name": "heap-memory",
"state": "UP",
"data": {
"max %": "0.9",
"max": 3817865216,
"used": 69881976
}
}
],
"service": {
"name": "App Suite Proxy",
"version": "dev",
"date": "2019-10-31T11:58:18,745+0100",
"timeZone": "Europe/Berlin",
"locale": "de_DE",
"charset": "UTF-8"
}
}
Prometheus Metrics¶
Monitoring Metrics from server runtime will be exposed under /metrics. The format follows the Prometheus Format specification .
Payload from http://<server>:<port>/metrics looks like the following example:
# HELP zuul_filter_concurrency_current Current amount of concurrent requests for a filter
# TYPE zuul_filter_concurrency_current gauge
zuul_filter_concurrency_current{id="InitOidcSso.end",} 0.0
zuul_filter_concurrency_current{id="HttpRedirectFilter.end",} 0.0
zuul_filter_concurrency_current{id="GZipResponseCustomFilter.out",} 0.0
zuul_filter_concurrency_current{id="ProxyPassFilter.in",} 0.0
zuul_filter_concurrency_current{id="HttpSimpleResponseFilter.end",} 0.0
zuul_filter_concurrency_current{id="HeaderHandlingFilter.in",} 0.0
zuul_filter_concurrency_current{id="ZuulResponseFilter.out",} 0.0
Open API¶
Management Endpoint comes with an integrated Open API documentation which can be created while server startup, see section Settings. Once enabled the documentation is available at /openapi, /openapi.yaml and /openapi.json. /metrics. Use this endpoint to import the payload in a tool of your choise e.g. Postman, or use /application.wadl to help with client generation.
Payload from /openapi looks like the following example:
openapi: 3.0.1
info:
title: Appsuite-Proxy Management API
description: Description
termsOfService: http://swagger.io/terms/
contact:
email: devs@open-xchange.com
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
version: dev
paths:
/healthcheck:
get:
operationId: doHealthCheck
responses:
default:
description: default response
content:
'*/*': {}
/health:
get:
tags:
- Health Checks
summary: Health Check
description: Health Check according to microprofile Health API
operationId: getHealthResponse
responses:
default:
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorModel'
"200":
description: All Health Checks are UP
"503":
description: At least one Health Check failed with state DOWN
"500":
description: Health Check call could not be processed in backend. If property
enable API response errors is set to true see payload for futher details.
Command Line Tool¶
Appsuite Proxy comes with a command line tool which basically gives access to Proxy`s management API Endpoints. The command line tool can be installed as additional docker image or locally using gradle a task.
For more information see project`s readme. Once you have installed command line tool run appsuite-proxy --help to get a list with possible actions
root@2a1f20a3b3d7:/usr/local/bin# appsuite-proxy
Usage: appsuite-proxy [OPTIONS] COMMAND [ARGS]...
Command line tool can be used to perform management tasks from shell which
basically invoke Appsuite Proxy`s REST API Endpoints.
Options:
-u, --baseurl TEXT Base URL to proxy`s management API [default:
(http://127.0.0.1:8888)]
--debug Show debug output in case of any errors [default:
(False)]
--version Show the version and exit.
-h, --help Show this message and exit.
Commands:
config Actions calling Appsuite Proxy`s configuration endpoint
health Actions calling Appsuite Proxy`s health endpoint
metrics Actions calling Appsuite Proxy`s metrics endpoint
Run 'appsuite-proxy COMMAND --help' for more information
CLI Docker Image¶
Alternatively you can use appsuite-proxy-cli docker image which includes the clt. To use it you need just to run the image, e.g. docker run ImageId. This will show you the help text and you can just add options or commands on your next docker run call, e.g. docker run ImageId -v config get.