AKHQ configuration
Pagination
akhq.pagination.page-sizenumber of topics per page (default : 25)
Avro Serializer
akhq.avro-serializer.json.serialization.inclusionsis list of ObjectMapper serialization inclusions that is used for converting Avro message to more readable Json format in the UI. Supports Enums of JsonInclude.Include from Jackson library
Topic List
akhq.topic.internal-regexpsis list of regexp to be considered as internal (internal topic can't be deleted or updated)akhq.topic.stream-regexpsis list of regexp to be considered as internal stream topic
Topic creation default values
These parameters are the default values used in the topic creation page.
akhq.topic.replicationDefault number of replica to useakhq.topic.partitionDefault number of partition
Topic Data
akhq.topic-data.size: max record per page (default: 50)akhq.topic-data.poll-timeout: The time, in milliseconds, spent waiting in poll if data is not available in the buffer (default: 1000).akhq.topic-data.kafka-max-message-length: Max message length allowed to send to UI when retrieving a list of records (dafault: 1000000 bytes).
Ui Settings
Topics
akhq.ui-options.topic.default-viewis default list view (ALL, HIDE_INTERNAL, HIDE_INTERNAL_STREAM, HIDE_STREAM) (default: HIDE_INTERNAL)akhq.ui-options.topic.skip-consumer-groupshide consumer groups columns on topic listakhq.ui-options.topic.skip-last-recordhide the last records on topic listakhq.ui-options.topic.show-all-consumer-groupsexpand lists of consumer groups on topic listakhq.ui-options.topic.groups-default-viewis the default consumer groups list view on topic screen/consumer groups tab (ALL, HIDE_EMPTY) (default: ALL). HIDE_EMPTY increases performance, especially on cluster with a lot of consumer groups
Topic Data
akhq.ui-options.topic-data.sort: default sort order (OLDEST, NEWEST) (default: OLDEST)
Cluster
akhq.ui-options.cluster.order: define custom ordering for clusters in the sidebar (optional). Clusters listed in this array will appear first in the specified order, followed by any unlisted clusters in alphabetical order.
Example:
akhq:
ui-options:
cluster:
order:
- "production-cluster"
- "staging-cluster"
- "development-cluster"
Inject some css or javascript
akhq.html-head: Append some head tags on the webserver application Mostly useful in order to inject some css or javascript to customize the web application.
Examples, add a environment information on the left menu:
akhq:
html-head: |
<style type="text/css">
.logo-wrapper:after {
display: block;
content: "Local";
position: relative;
text-transform: uppercase;
text-align: center;
color: white;
margin-top: 10px;
}
</style>
Custom HTTP response headers
To add headers to every response please add the headers like in following example:
akhq:
server:
customHttpResponseHeaders:
- name: "Content-Security-Policy"
value: "default-src 'none'; frame-src 'self'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; frame-ancestors 'self'; form-action 'self'; upgrade-insecure-requests"
- name: "X-Permitted-Cross-Domain-Policies"
value: "none"
Data Masking
If you want to hide some data in your records, there are two approaches.
Regex Masking
You can use regex masking - configure this with the following filters. These will be applied to all record values and keys.
akhq:
security:
data-masking:
mode: regex # Note - this is not explicitly required as regex is the 'default' masker that gets applied for backwards compatibility
filters:
- description: "Masks value for secret-key fields"
search-regex: '"(secret-key)":".*"'
replacement: '"$1":"xxxx"'
- description: "Masks last digits of phone numbers"
search-regex: '"([\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?)[0-9]{4,6}"'
replacement: '"$1xxxx"'
JSON Masking
This is useful for records which are interpreted as JSON on deserialization to strings - for example, Avro records, or normal JSON payloads. These can be configured per-topic, and you can select distinct fields to mask/unmask. There are two JSON masking modes: json_show_by_default and json_mask_by_default.
Show by default config
This means, by default, nothing is masked. If you wish to mask data this way, you can:
- Set a value in
akhq.security.data-masking.jsonMaskReplacement(this defaults toxxxx) - Set
akhq.security.data-masking.modetojson_show_by_default - Add as many filters as desired under
akhq.security.data-masking.json-filters(see below for an example) to select fields you want to mask
By default, the topic field in each filter is matched against the full topic name as an exact, case-insensitive string. Set akhq.security.data-masking.enable-regex-topic-filters to true to instead treat topic as a case-insensitive Java regular expression that must match the entire topic name. For example, with regex topic filters enabled, topic: user-events-.* will match topic names like user-events-login and USER-EVENTS-AUDIT, but topic: users will not match users-archive. When multiple filters match the same topic, the keys from all matching filters are combined, and the order of filters does not matter.
A filter without a topic is ignored (with a warning in the logs). With regex topic filters enabled, a topic that is not a valid regular expression fails with a PatternSyntaxException when the masker is created; when they are disabled, any topic is safe because it is matched literally.
NOTES: If you are using RecordNameStrategy on a topic with multiple record types, there is (currently) no way to distinguish between different records, so any records which have the JSON field at the selected path(s) will be masked.
akhq:
security:
data-masking:
mode: json_show_by_default
jsonMaskReplacement: xxxx
enable-regex-topic-filters: true
json-filters:
- description: Mask sensitive values
topic: users
keys:
- name
- dateOfBirth
- address.firstLine
- address.town
- metadata.notes
- description: Mask the status on all user-related topics
topic: user.*
keys:
- status
Given a record on users that looks like:
{
"specialId": 123,
"status": "ACTIVE",
"name": "John Smith",
"dateOfBirth": "01-01-1991",
"address": [
{
"firstLine": "123 Example Avenue",
"town": "Faketown",
"country": "United Kingdom"
},
{
"firstLine": "123 Previous Avenue",
"town": "Previoustown",
"country": "United Kingdom"
}
],
"metadata": {
"trusted": true,
"rating": "10",
"notes": "All in good order"
}
}
With the above configuration, both filters match the users topic (the exact name users also matches the regex user.*), so their keys are combined and the record will appear as:
{
"specialId": 123,
"status": "xxxx",
"name": "xxxx",
"dateOfBirth": "xxxx",
"address": [
{
"firstLine": "xxxx",
"town": "xxxx",
"country": "United Kingdom"
},
{
"firstLine": "xxxx",
"town": "xxxx",
"country": "United Kingdom"
}
],
"metadata": {
"trusted": true,
"rating": "10",
"notes": "xxxx"
}
}
Note how arrays are automatically understood where relevant. In other words, address.firstLine will apply to both of the following:
{
"address": {
"firstLine": "This field!"
}
}
and
{
"address": [
{
"firstLine": "This field!"
},
{
"firstLine": "And this one!"
}
]
}
Mask by default config
This means, by default, everything is masked. This is useful in production scenarios where data must be carefully selected and made available to users of AKHQ - usually this is for regulatory compliance of personal/sensitive information.
PLEASE NOTE: This has the side effect of being unable to show unstructured data at all. This is because if the schema registry is down, the binary data would otherwise be unfilterable. Instead, a placeholder message is shown.
If you wish to mask data this way, you can:
- Set a value in
akhq.security.data-masking.jsonMaskReplacement(this defaults toxxxx) - Set
akhq.security.data-masking.modetojson_mask_by_default - Add as many filters as desired under
akhq.security.data-masking.json-filters(see below for an example) to select fields you want to show
By default, the topic field in each filter is matched against the full topic name as an exact, case-insensitive string. Set akhq.security.data-masking.enable-regex-topic-filters to true to instead treat topic as a case-insensitive Java regular expression that must match the entire topic name. For example, with regex topic filters enabled, topic: user-events-.* will match topic names like user-events-login and USER-EVENTS-AUDIT, but topic: users will not match users-archive. When multiple filters match the same topic, the keys from all matching filters are combined, and the order of filters does not matter.
A filter without a topic is ignored (with a warning in the logs). With regex topic filters enabled, a topic that is not a valid regular expression fails with a PatternSyntaxException when the masker is created; when they are disabled, any topic is safe because it is matched literally.
NOTES: If you are using RecordNameStrategy on a topic with multiple record types, there is (currently) no way to distinguish between different records, so any records which have the JSON field at the selected path(s) will be shown.
akhq:
security:
data-masking:
mode: json_mask_by_default
jsonMaskReplacement: xxxx
enable-regex-topic-filters: true
json-filters:
- description: Unmask non-sensitive values
topic: users
keys:
- specialId
- status
- address.country
- metadata.trusted
- metadata.rating
- description: Unmask the name on all user-related topics
topic: user.*
keys:
- name
Given a record on users that looks like:
{
"specialId": 123,
"status": "ACTIVE",
"name": "John Smith",
"dateOfBirth": "01-01-1991",
"address": [
{
"firstLine": "123 Example Avenue",
"town": "Faketown",
"country": "United Kingdom"
},
{
"firstLine": "123 Previous Avenue",
"town": "Previoustown",
"country": "United Kingdom"
}
],
"metadata": {
"trusted": true,
"rating": "10",
"notes": "All in good order"
}
}
With the above configuration, both filters match the users topic (the exact name users also matches the regex user.*), so their keys are combined and the record will appear as:
{
"specialId": 123,
"status": "ACTIVE",
"name": "John Smith",
"dateOfBirth": "xxxx",
"address": [
{
"firstLine": "xxxx",
"town": "xxxx",
"country": "United Kingdom"
},
{
"firstLine": "xxxx",
"town": "xxxx",
"country": "United Kingdom"
}
],
"metadata": {
"trusted": true,
"rating": "10",
"notes": "xxxx"
}
}
Note how arrays are automatically understood where relevant. In other words, address.firstLine will apply to both of the following:
{
"address": {
"firstLine": "This field!"
}
}
and
{
"address": [
{
"firstLine": "This field!"
},
{
"firstLine": "And this one!"
}
]
}
No masking required
You can set akhq.security.data-masking.mode to none to disable masking altogether.
Audit
If you want to audit user action that modified topics or consumer group state, you can configure akhq to send audit events to a pre-configured cluster:
akhq:
audit:
enabled: true
cluster-id: my-audit-cluster-plain-text
topic-name: audit