-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[HTTP Server] support TLS config hot reload via SIGHUP
#171823
Conversation
SIGHUP
3e851f6
to
0aa3d12
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self-review
// only hot-reloading TLS config - don't need to subscribe if TLS is initially disabled, | ||
// given we can't hot-switch from/to enabled/disabled. | ||
if (config.ssl.enabled) { | ||
const configSubscription = config$ | ||
.pipe(pairwise()) | ||
.subscribe(([{ ssl: prevSslConfig }, { ssl: newSslConfig }]) => { | ||
if (prevSslConfig.enabled !== newSslConfig.enabled) { | ||
this.log.warn( | ||
'Incompatible TLS config change detected - TLS cannot be toggled without a full server reboot.' | ||
); | ||
return; | ||
} | ||
|
||
const sameConfig = newSslConfig.isEqualTo(prevSslConfig); | ||
|
||
if (!sameConfig) { | ||
this.log.info('TLS configuration change detected - reloading TLS configuration.'); | ||
setTlsConfig(this.server!, newSslConfig); | ||
} | ||
}); | ||
this.subscriptions.push(configSubscription); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main addition / entry point of the PR. The HTTP server now has access to the config observable (instead of the config object) and listen to changes to check if the SSL config was updated. If so, we propagate the changes to the underlying tls server
function isServerTLS(server: HttpServer): server is TlsServer { | ||
return 'setSecureContext' in server; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: I could probably have used server instanceof TlsServer
instead, but tbh this works and is easier to stub for testing.
public isEqualTo(otherConfig: SslConfig) { | ||
if (this === otherConfig) { | ||
return true; | ||
} | ||
return isEqual(this, otherConfig); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had to implement a comparison func on the SslConfig
class. Wasn't strictly necessary, but it allows to know when the SSL config really changed to avoid propagating the changes on every SIGHUP (and also to have better logging given we only output an info message when the config really changed)
describe('setTlsConfig', () => { | ||
const CSP_CONFIG = cspConfig.schema.validate({}); | ||
const EXTERNAL_URL_CONFIG = externalUrlConfig.schema.validate({}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Integration test against a vanilla HAPI server
describe('HttpServer - TLS config', () => { | ||
let server: HttpServer; | ||
let logger: ReturnType<typeof loggingSystemMock.createLogger>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Integration test against our HttpServer
.
Pinging @elastic/kibana-core (Team:Core) |
💚 Build Succeeded
Metrics [docs]Public APIs missing comments
Public APIs missing exports
Unknown metric groupsAPI count
History
To update your PR or re-run it, just comment with: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pulle and ran the code and it works as intended. The implementation looks fine too.
One question that came to mind is making the change to SSL more noticeable. ATM, the info logs might get lost in a sea of debug logs. If we changed logging to warn on SSL certs updates, it might be more prevalent.
.pipe(pairwise()) | ||
.subscribe(([{ ssl: prevSslConfig }, { ssl: newSslConfig }]) => { | ||
if (prevSslConfig.enabled !== newSslConfig.enabled) { | ||
this.log.warn( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If someone's debugging why an update to their certs "isn't working", they might be tempted to enable debug logging. Warning logs can get lost in those.
I wonder if we shouldn't make the warning more prominent 🤔
const sameConfig = newSslConfig.isEqualTo(prevSslConfig); | ||
|
||
if (!sameConfig) { | ||
this.log.info('TLS configuration change detected - reloading TLS configuration.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should also be a warning log: If someone's intentionally making a change/update they'll know to ignore the log line. If, however, something's gone wrong and we're using logs to figure out what happened, we'd be less likely to ignore a warning log entry than an info-level one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The whole SIGHUP reload chain's logging is INFO based (which is the correct level ihmo, it's informative), so I think I'd rather keep that consistent.
return this.config$.pipe( | ||
map((config) => config.get(path)), | ||
distinctUntilChanged(isEqual), | ||
ignoreUnchanged ? distinctUntilChanged(isEqual) : identity, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you made me look identity
up 😉
💔 All backports failed
Manual backportTo create the backport manually run:
Questions ?Please refer to the Backport tool documentation |
) ## Summary Fix elastic#54368 Add support for hot reloading the Kibana server's TLS configuration, using the same `SIGHUP`-based reload signal, as already implemented for other parts of the Kibana configuration (e.g `logging`) **Note:** - hot reloading is only supported for the server TLS configuration (`server.ssl`), not for the whole `server.*` config prefix - swaping the certificate files (without modifying the kibana config itself) is supported - it is not possible to toggle TLS (enabling or disabling) without restarting Kibana - hot reloading requires to force the process to reload its configuration by sending a `SIGHUP` signal ### Example / how to test #### Before ```yaml server.ssl.enabled: true server.ssl.certificate: /path-to-kibana/packages/kbn-dev-utils/certs/kibana.crt server.ssl.key: /path-to-kibana/packages/kbn-dev-utils/certs/kibana.key ``` <img width="550" alt="Screenshot 2023-11-23 at 15 11 28" src="https://github.com/elastic/kibana/assets/1532934/1226d161-a9f2-4d62-a3de-37161829f187"> #### Changing the config ```yaml server.ssl.enabled: true server.ssl.certificate: /path-to-kibana/packages/kbn-dev-utils/certs/elasticsearch.crt server.ssl.key: /path-to-kibana/packages/kbn-dev-utils/certs/elasticsearch.key ``` ```bash kill -SIGHUP {KIBANA_PID} ``` <img width="865" alt="Screenshot 2023-11-23 at 15 18 21" src="https://github.com/elastic/kibana/assets/1532934/c9412b2e-d70e-4cf0-8eaf-4db70a45af60"> #### After <img width="547" alt="Screenshot 2023-11-23 at 15 18 43" src="https://github.com/elastic/kibana/assets/1532934/c839f04f-4adb-456d-a174-4f0ebd5c234c"> ## Release notes It is now possible to hot reload Kibana's TLS (`server.ssl`) configuration by updating it and then sending a `SIGHUP` signal to the Kibana process. Note that TLS cannot be toggled (disabled/enabled) that way, and that hot reload only works for the TLS configuration, not other properties of the `server` config prefix. --------- Co-authored-by: kibanamachine <[email protected]> (cherry picked from commit 87213e7) # Conflicts: # src/core/tsconfig.json
💚 All backports created successfully
Note: Successful backport PRs will be merged automatically after passing CI. Questions ?Please refer to the Backport tool documentation |
…tic#171823) (elastic#171907) # Backport This will backport the following commits from `main` to `8.11`: - [[HTTP Server] support TLS config hot reload via `SIGHUP` (elastic#171823)](elastic#171823) <!--- Backport version: 8.9.8 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Pierre Gayvallet","email":"[email protected]"},"sourceCommit":{"committedDate":"2023-11-24T09:05:27Z","message":"[HTTP Server] support TLS config hot reload via `SIGHUP` (elastic#171823)\n\n## Summary\r\n\r\nFix https://github.com/elastic/kibana/issues/54368\r\n\r\nAdd support for hot reloading the Kibana server's TLS configuration,\r\nusing the same `SIGHUP`-based reload signal, as already implemented for\r\nother parts of the Kibana configuration (e.g `logging`)\r\n\r\n**Note:**\r\n- hot reloading is only supported for the server TLS configuration\r\n(`server.ssl`), not for the whole `server.*` config prefix\r\n- swaping the certificate files (without modifying the kibana config\r\nitself) is supported\r\n- it is not possible to toggle TLS (enabling or disabling) without\r\nrestarting Kibana\r\n- hot reloading requires to force the process to reload its\r\nconfiguration by sending a `SIGHUP` signal\r\n\r\n### Example / how to test\r\n\r\n#### Before\r\n\r\n```yaml\r\nserver.ssl.enabled: true\r\nserver.ssl.certificate: /path-to-kibana/packages/kbn-dev-utils/certs/kibana.crt\r\nserver.ssl.key: /path-to-kibana/packages/kbn-dev-utils/certs/kibana.key\r\n```\r\n\r\n<img width=\"550\" alt=\"Screenshot 2023-11-23 at 15 11 28\"\r\nsrc=\"https://github.com/elastic/kibana/assets/1532934/1226d161-a9f2-4d62-a3de-37161829f187\">\r\n\r\n#### Changing the config\r\n\r\n```yaml\r\nserver.ssl.enabled: true\r\nserver.ssl.certificate: /path-to-kibana/packages/kbn-dev-utils/certs/elasticsearch.crt\r\nserver.ssl.key: /path-to-kibana/packages/kbn-dev-utils/certs/elasticsearch.key\r\n```\r\n\r\n```bash\r\nkill -SIGHUP {KIBANA_PID}\r\n```\r\n\r\n<img width=\"865\" alt=\"Screenshot 2023-11-23 at 15 18 21\"\r\nsrc=\"https://github.com/elastic/kibana/assets/1532934/c9412b2e-d70e-4cf0-8eaf-4db70a45af60\">\r\n\r\n#### After\r\n\r\n<img width=\"547\" alt=\"Screenshot 2023-11-23 at 15 18 43\"\r\nsrc=\"https://github.com/elastic/kibana/assets/1532934/c839f04f-4adb-456d-a174-4f0ebd5c234c\">\r\n\r\n## Release notes\r\n\r\nIt is now possible to hot reload Kibana's TLS (`server.ssl`)\r\nconfiguration by updating it and then sending a `SIGHUP` signal to the\r\nKibana process.\r\n\r\nNote that TLS cannot be toggled (disabled/enabled) that way, and that\r\nhot reload only works for the TLS configuration, not other properties of\r\nthe `server` config prefix.\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <[email protected]>","sha":"87213e7efe4420b0edf72d471056fe78cbd9df60","branchLabelMapping":{"^v8.12.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:enhancement","Feature:http","Team:Core","backport:prev-minor","v8.12.0"],"number":171823,"url":"https://github.com/elastic/kibana/pull/171823","mergeCommit":{"message":"[HTTP Server] support TLS config hot reload via `SIGHUP` (elastic#171823)\n\n## Summary\r\n\r\nFix https://github.com/elastic/kibana/issues/54368\r\n\r\nAdd support for hot reloading the Kibana server's TLS configuration,\r\nusing the same `SIGHUP`-based reload signal, as already implemented for\r\nother parts of the Kibana configuration (e.g `logging`)\r\n\r\n**Note:**\r\n- hot reloading is only supported for the server TLS configuration\r\n(`server.ssl`), not for the whole `server.*` config prefix\r\n- swaping the certificate files (without modifying the kibana config\r\nitself) is supported\r\n- it is not possible to toggle TLS (enabling or disabling) without\r\nrestarting Kibana\r\n- hot reloading requires to force the process to reload its\r\nconfiguration by sending a `SIGHUP` signal\r\n\r\n### Example / how to test\r\n\r\n#### Before\r\n\r\n```yaml\r\nserver.ssl.enabled: true\r\nserver.ssl.certificate: /path-to-kibana/packages/kbn-dev-utils/certs/kibana.crt\r\nserver.ssl.key: /path-to-kibana/packages/kbn-dev-utils/certs/kibana.key\r\n```\r\n\r\n<img width=\"550\" alt=\"Screenshot 2023-11-23 at 15 11 28\"\r\nsrc=\"https://github.com/elastic/kibana/assets/1532934/1226d161-a9f2-4d62-a3de-37161829f187\">\r\n\r\n#### Changing the config\r\n\r\n```yaml\r\nserver.ssl.enabled: true\r\nserver.ssl.certificate: /path-to-kibana/packages/kbn-dev-utils/certs/elasticsearch.crt\r\nserver.ssl.key: /path-to-kibana/packages/kbn-dev-utils/certs/elasticsearch.key\r\n```\r\n\r\n```bash\r\nkill -SIGHUP {KIBANA_PID}\r\n```\r\n\r\n<img width=\"865\" alt=\"Screenshot 2023-11-23 at 15 18 21\"\r\nsrc=\"https://github.com/elastic/kibana/assets/1532934/c9412b2e-d70e-4cf0-8eaf-4db70a45af60\">\r\n\r\n#### After\r\n\r\n<img width=\"547\" alt=\"Screenshot 2023-11-23 at 15 18 43\"\r\nsrc=\"https://github.com/elastic/kibana/assets/1532934/c839f04f-4adb-456d-a174-4f0ebd5c234c\">\r\n\r\n## Release notes\r\n\r\nIt is now possible to hot reload Kibana's TLS (`server.ssl`)\r\nconfiguration by updating it and then sending a `SIGHUP` signal to the\r\nKibana process.\r\n\r\nNote that TLS cannot be toggled (disabled/enabled) that way, and that\r\nhot reload only works for the TLS configuration, not other properties of\r\nthe `server` config prefix.\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <[email protected]>","sha":"87213e7efe4420b0edf72d471056fe78cbd9df60"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.12.0","labelRegex":"^v8.12.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/171823","number":171823,"mergeCommit":{"message":"[HTTP Server] support TLS config hot reload via `SIGHUP` (elastic#171823)\n\n## Summary\r\n\r\nFix https://github.com/elastic/kibana/issues/54368\r\n\r\nAdd support for hot reloading the Kibana server's TLS configuration,\r\nusing the same `SIGHUP`-based reload signal, as already implemented for\r\nother parts of the Kibana configuration (e.g `logging`)\r\n\r\n**Note:**\r\n- hot reloading is only supported for the server TLS configuration\r\n(`server.ssl`), not for the whole `server.*` config prefix\r\n- swaping the certificate files (without modifying the kibana config\r\nitself) is supported\r\n- it is not possible to toggle TLS (enabling or disabling) without\r\nrestarting Kibana\r\n- hot reloading requires to force the process to reload its\r\nconfiguration by sending a `SIGHUP` signal\r\n\r\n### Example / how to test\r\n\r\n#### Before\r\n\r\n```yaml\r\nserver.ssl.enabled: true\r\nserver.ssl.certificate: /path-to-kibana/packages/kbn-dev-utils/certs/kibana.crt\r\nserver.ssl.key: /path-to-kibana/packages/kbn-dev-utils/certs/kibana.key\r\n```\r\n\r\n<img width=\"550\" alt=\"Screenshot 2023-11-23 at 15 11 28\"\r\nsrc=\"https://github.com/elastic/kibana/assets/1532934/1226d161-a9f2-4d62-a3de-37161829f187\">\r\n\r\n#### Changing the config\r\n\r\n```yaml\r\nserver.ssl.enabled: true\r\nserver.ssl.certificate: /path-to-kibana/packages/kbn-dev-utils/certs/elasticsearch.crt\r\nserver.ssl.key: /path-to-kibana/packages/kbn-dev-utils/certs/elasticsearch.key\r\n```\r\n\r\n```bash\r\nkill -SIGHUP {KIBANA_PID}\r\n```\r\n\r\n<img width=\"865\" alt=\"Screenshot 2023-11-23 at 15 18 21\"\r\nsrc=\"https://github.com/elastic/kibana/assets/1532934/c9412b2e-d70e-4cf0-8eaf-4db70a45af60\">\r\n\r\n#### After\r\n\r\n<img width=\"547\" alt=\"Screenshot 2023-11-23 at 15 18 43\"\r\nsrc=\"https://github.com/elastic/kibana/assets/1532934/c839f04f-4adb-456d-a174-4f0ebd5c234c\">\r\n\r\n## Release notes\r\n\r\nIt is now possible to hot reload Kibana's TLS (`server.ssl`)\r\nconfiguration by updating it and then sending a `SIGHUP` signal to the\r\nKibana process.\r\n\r\nNote that TLS cannot be toggled (disabled/enabled) that way, and that\r\nhot reload only works for the TLS configuration, not other properties of\r\nthe `server` config prefix.\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <[email protected]>","sha":"87213e7efe4420b0edf72d471056fe78cbd9df60"}}]}] BACKPORT-->
Summary
Fix #54368
Add support for hot reloading the Kibana server's TLS configuration, using the same
SIGHUP
-based reload signal, as already implemented for other parts of the Kibana configuration (e.glogging
)Note:
server.ssl
), not for the wholeserver.*
config prefixSIGHUP
signalExample / how to test
Before
Changing the config
kill -SIGHUP {KIBANA_PID}
After
Release notes
It is now possible to hot reload Kibana's TLS (
server.ssl
) configuration by updating it and then sending aSIGHUP
signal to the Kibana process.Note that TLS cannot be toggled (disabled/enabled) that way, and that hot reload only works for the TLS configuration, not other properties of the
server
config prefix.