Configurable custom response headers for server (#13045)

* Configurable custom response headers for server

The server.customResponseHeaders configuration allows users to configure
custom headers to send on all responses to the client from anywhere in
the Kibana server.

This can be useful for setting headers like x-frame-options when you
don't want people embedding even Kibana dashboards in an iframe.

* Consistent header overriding and explicit unknown
This commit is contained in:
Court Ewing 2017-07-21 18:35:02 -04:00 committed by GitHub
parent 776ad0d531
commit 7a918f17d2
3 changed files with 25 additions and 14 deletions

View file

@ -14,6 +14,7 @@ you'll need to update your `kibana.yml` file. You can also enable SSL and set a
`server.maxPayloadBytes:`:: *Default: 1048576* The maximum payload size in bytes for incoming server requests.
`server.name:`:: *Default: "your-hostname"* A human-readable display name that identifies this Kibana instance.
`server.defaultRoute:`:: *Default: "/app/kibana"* This setting specifies the default route when opening Kibana. You can use this setting to modify the landing page when opening Kibana.
`server.customResponseHeaders:`:: *Default: `{}`* Header names and values to send on all responses to the client from the Kibana server.
`elasticsearch.url:`:: *Default: "http://localhost:9200"* The URL of the Elasticsearch instance to use for all your
queries.
`elasticsearch.preserveHost:`:: *Default: true* When this settings value is true Kibana uses the hostname specified in
@ -23,25 +24,25 @@ to this Kibana instance.
dashboards. Kibana creates a new index if the index doesnt already exist.
`kibana.defaultAppId:`:: *Default: "discover"* The default application to load.
[[tilemap-settings]]`tilemap.url:`:: The URL to the tile
service that Kibana uses to display map tiles in tilemap visualizations. By default, Kibana reads this url from an external metadata service, but users can still override this parameter to use their own Tile Map Service. For example: `"https://tiles.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana"`
service that Kibana uses to display map tiles in tilemap visualizations. By default, Kibana reads this url from an external metadata service, but users can still override this parameter to use their own Tile Map Service. For example: `"https://tiles.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana"`
`tilemap.options.minZoom:`:: *Default: 1* The minimum zoom level.
`tilemap.options.maxZoom:`:: *Default: 10* The maximum zoom level.
`tilemap.options.attribution:`:: *Default: `"© [Elastic Maps Service](https://www.elastic.co/elastic-maps-service)"`* The map attribution string.
`tilemap.options.subdomains:`:: An array of subdomains used by the tile service.
Specify the position of the subdomain the URL with the token `{s}`.
[[regionmap-settings]] `regionmap`:: Specifies additional vector layers for use in <<regionmap, Region Map>> visualizations.
Each layer object points to an external vector file that contains a geojson FeatureCollection.
The file must use the WGS84 coordinate reference system and only include polygons.
If the file is hosted on a separate domain from Kibana, the server needs to be CORS-enabled so Kibana can download the file.
The url field also serves as a unique identifier for the file.
Each layer can contain multiple fields to indicate what properties from the geojson features you want to expose.
[[regionmap-settings]] `regionmap`:: Specifies additional vector layers for use in <<regionmap, Region Map>> visualizations.
Each layer object points to an external vector file that contains a geojson FeatureCollection.
The file must use the WGS84 coordinate reference system and only include polygons.
If the file is hosted on a separate domain from Kibana, the server needs to be CORS-enabled so Kibana can download the file.
The url field also serves as a unique identifier for the file.
Each layer can contain multiple fields to indicate what properties from the geojson features you want to expose.
The field.description is the human readable text that is shown in the Region Map visualization's field menu.
An optional attribution value can be added as well.
The following example shows a valid regionmap configuration.
regionmap:
layers:
layers:
- name: "Departments of France"
url: "http://my.cors.enabled.server.org/france_departements.geojson"
attribution: "INRAP"
@ -49,8 +50,8 @@ The following example shows a valid regionmap configuration.
- name: "department"
description: "Full department name"
- name: "INSEE"
description: "INSEE numeric identifier"
description: "INSEE numeric identifier"
`elasticsearch.username:` and `elasticsearch.password:`:: If your Elasticsearch is protected with basic authentication,
these settings provide the username and password that the Kibana server uses to perform maintenance on the Kibana index at
startup. Your Kibana users still need to authenticate with Elasticsearch, which is proxied through the Kibana server.

View file

@ -53,6 +53,7 @@ export default () => Joi.object({
autoListen: Joi.boolean().default(true),
defaultRoute: Joi.string().default('/app/kibana').regex(/^\//, `start with a slash`),
basePath: Joi.string().default('').allow('').regex(/(^$|^\/.*[^\/]$)/, `start with a slash, don't end with one`),
customResponseHeaders: Joi.object().unknown(true).default({}),
ssl: Joi.object({
enabled: Joi.boolean().default(false),
redirectHttpFromPort: Joi.number(),

View file

@ -75,12 +75,21 @@ export default async function (kbnServer, server, config) {
server.ext('onPreResponse', function (req, reply) {
const response = req.response;
const customHeaders = {
...config.get('server.customResponseHeaders'),
'kbn-name': kbnServer.name,
'kbn-version': kbnServer.version,
};
if (response.isBoom) {
response.output.headers['kbn-name'] = kbnServer.name;
response.output.headers['kbn-version'] = kbnServer.version;
response.output.headers = {
...response.output.headers,
...customHeaders
};
} else {
response.header('kbn-name', kbnServer.name);
response.header('kbn-version', kbnServer.version);
Object.keys(customHeaders).forEach(name => {
response.header(name, customHeaders[name]);
});
}
return reply.continue();