-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Reporting] Internally correct the hostname to "localhost" if "server.host" is "0.0.0.0" #117022
Conversation
Pinging @elastic/kibana-reporting-services (Team:Reporting Services) |
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.
Thanks for adding this change @tsullivan , I'm sure this will prevent some bad config!
I have one question regarding re-checking the config that I'd like to get your thoughts on before approving.
💚 Build Succeeded
Metrics [docs]
History
To update your PR or re-run it, just comment with: |
for (const hostname of [ | ||
'0', | ||
'0.0', | ||
'0.0.0', | ||
'0.0.0.0', | ||
'0000:0000:0000:0000:0000:0000:0000:0000', | ||
'::', | ||
]) { | ||
it(`apply failover logic when hostname is given as ${hostname}`, async () => { |
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.
Jest provides tooling for such cases. Please use it.each
instead.
for (const hostname of [ | |
'0', | |
'0.0', | |
'0.0.0', | |
'0.0.0.0', | |
'0000:0000:0000:0000:0000:0000:0000:0000', | |
'::', | |
]) { | |
it(`apply failover logic when hostname is given as ${hostname}`, async () => { | |
it.each` | |
hostname | |
${'0'} | |
${'0.0'} | |
${'0.0.0'} | |
${'0.0.0.0'} | |
${'0000:0000:0000:0000:0000:0000:0000:0000'} | |
${'::'} | |
`('apply failover logic when hostname is given as $hostname', async ({ hostname }) => { |
expect(mockLogger.warn.mock.calls.length).toBe(1); | ||
expect(mockLogger.warn.mock.calls[0]).toMatchObject([ | ||
'Generating a random key for xpack.reporting.encryptionKey. To prevent sessions from being invalidated on restart, please set xpack.reporting.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.', | ||
]); |
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 understand that the change was about removing the any
. Since I have more relevant feedback below, maybe we can commit the following to prettify the code even more.
expect(mockLogger.warn.mock.calls.length).toBe(1); | |
expect(mockLogger.warn.mock.calls[0]).toMatchObject([ | |
'Generating a random key for xpack.reporting.encryptionKey. To prevent sessions from being invalidated on restart, please set xpack.reporting.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.', | |
]); | |
expect(mockLogger.warn).toHaveBeenCalledTimes(1); | |
expect(mockLogger.warn).toHaveBeenCalledWith( | |
'Generating a random key for xpack.reporting.encryptionKey. To prevent sessions from being invalidated on restart, please set xpack.reporting.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' | |
); |
const result = await createConfig$(mockCoreSetup, mockConfig$, mockLogger).toPromise(); | ||
expect(result.encryptionKey).toMatch('iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii'); | ||
expect((mockLogger.warn as any).mock.calls.length).toBe(0); | ||
expect(mockLogger.warn.mock.calls.length).toBe(0); |
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.
expect(mockLogger.warn.mock.calls.length).toBe(0); | |
expect(mockLogger.warn).not.toHaveBeenCalled(); |
@@ -108,7 +103,7 @@ describe('Reporting server createConfig$', () => { | |||
}, | |||
} | |||
`); | |||
expect((mockLogger.warn as any).mock.calls.length).toBe(0); | |||
expect(mockLogger.warn.mock.calls.length).toBe(0); |
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.
expect(mockLogger.warn.mock.calls.length).toBe(0); | |
expect(mockLogger.warn).not.toHaveBeenCalled(); |
const result = await createConfig$(mockCoreSetup, mockConfig$, mockLogger).toPromise(); | ||
|
||
expect(result.capture.browser.chromium).toMatchObject({ disableSandbox: false }); | ||
expect((mockLogger.warn as any).mock.calls.length).toBe(0); | ||
expect(mockLogger.warn.mock.calls.length).toBe(0); |
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.
expect(mockLogger.warn.mock.calls.length).toBe(0); | |
expect(mockLogger.warn).not.toHaveBeenCalled(); |
const result = await createConfig$(mockCoreSetup, mockConfig$, mockLogger).toPromise(); | ||
|
||
expect(result.capture.browser.chromium).toMatchObject({ disableSandbox: true }); | ||
expect((mockLogger.warn as any).mock.calls.length).toBe(0); | ||
expect(mockLogger.warn.mock.calls.length).toBe(0); |
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.
expect(mockLogger.warn.mock.calls.length).toBe(0); | |
expect(mockLogger.warn).not.toHaveBeenCalled(); |
const result = await createConfig$(mockCoreSetup, mockConfig$, mockLogger).toPromise(); | ||
|
||
expect(result.capture.browser.chromium).toMatchObject({ disableSandbox: expect.any(Boolean) }); | ||
expect((mockLogger.warn as any).mock.calls.length).toBe(0); | ||
expect(mockLogger.warn.mock.calls.length).toBe(0); |
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.
expect(mockLogger.warn.mock.calls.length).toBe(0); | |
expect(mockLogger.warn).not.toHaveBeenCalled(); |
mockCoreSetup.http.getServerInfo = jest.fn().mockImplementation( | ||
(): HttpServerInfo => ({ | ||
name: 'cool server', | ||
hostname, | ||
port: 5601, | ||
protocol: 'http', | ||
}) | ||
); |
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.
Could be simplified a bit.
mockCoreSetup.http.getServerInfo = jest.fn().mockImplementation( | |
(): HttpServerInfo => ({ | |
name: 'cool server', | |
hostname, | |
port: 5601, | |
protocol: 'http', | |
}) | |
); | |
mockCoreSetup.http.getServerInfo = jest.fn((): HttpServerInfo => ({ | |
name: 'cool server', | |
hostname, | |
port: 5601, | |
protocol: 'http', | |
})); |
const result = await createConfig$(mockCoreSetup, mockConfig$, mockLogger).toPromise(); | ||
expect(result.kibanaServer).toMatchObject({ | ||
hostname: 'localhost', | ||
port: 5601, | ||
protocol: 'http', | ||
}); |
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 it would be better to check that the promise is resolved and the result is not empty and has the property. In case when the test fails, jest can provide additional logging of where exactly it went wrong (e.g. promises rejects or empty result).
const result = await createConfig$(mockCoreSetup, mockConfig$, mockLogger).toPromise(); | |
expect(result.kibanaServer).toMatchObject({ | |
hostname: 'localhost', | |
port: 5601, | |
protocol: 'http', | |
}); | |
await expect( | |
createConfig$(mockCoreSetup, mockConfig$, mockLogger).toPromise() | |
).resolves.toHaveProperty( | |
'kibanaServer', | |
expect.objectContaining({ | |
hostname: 'localhost', | |
port: 5601, | |
protocol: 'http', | |
}) | |
); |
for (const address of ['0', '0.0', '0.0.0']) { | ||
it(`fails to validate "kibanaServer.hostname" with an invalid hostname: "${address}"`, () => { | ||
expect(() => | ||
ConfigSchema.validate({ | ||
kibanaServer: { hostname: address }, | ||
}) | ||
).toThrowError(`[kibanaServer.hostname]: value must be a valid hostname (see RFC 1123).`); | ||
}); | ||
} |
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.
for (const address of ['0', '0.0', '0.0.0']) { | |
it(`fails to validate "kibanaServer.hostname" with an invalid hostname: "${address}"`, () => { | |
expect(() => | |
ConfigSchema.validate({ | |
kibanaServer: { hostname: address }, | |
}) | |
).toThrowError(`[kibanaServer.hostname]: value must be a valid hostname (see RFC 1123).`); | |
}); | |
} | |
it.each` | |
hostname | |
${'0'} | |
${'0.0'} | |
${'0.0.0'} | |
`('fails to validate "kibanaServer.hostname" with an invalid hostname: "$hostname"', ({ hostname }) => { | |
expect(() => | |
ConfigSchema.validate({ | |
kibanaServer: { hostname }, | |
}) | |
).toThrowError(`[kibanaServer.hostname]: value must be a valid hostname (see RFC 1123).`); | |
}); |
for (const address of ['0.0.0.0', '0000:0000:0000:0000:0000:0000:0000:0000', '::']) { | ||
it(`fails to validate "kibanaServer.hostname" hostname as zero: "${address}"`, () => { | ||
expect(() => | ||
ConfigSchema.validate({ | ||
kibanaServer: { hostname: address }, | ||
}) | ||
).toThrowError( | ||
`[kibanaServer.hostname]: cannot use '0.0.0.0' as Kibana host name, consider using the default (localhost) instead` | ||
); | ||
}); | ||
} |
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.
for (const address of ['0.0.0.0', '0000:0000:0000:0000:0000:0000:0000:0000', '::']) { | |
it(`fails to validate "kibanaServer.hostname" hostname as zero: "${address}"`, () => { | |
expect(() => | |
ConfigSchema.validate({ | |
kibanaServer: { hostname: address }, | |
}) | |
).toThrowError( | |
`[kibanaServer.hostname]: cannot use '0.0.0.0' as Kibana host name, consider using the default (localhost) instead` | |
); | |
}); | |
} | |
it.each` | |
hostname | |
${'0.0.0.0'} | |
${'0000:0000:0000:0000:0000:0000:0000:0000'} | |
${'::'} | |
`('fails to validate "kibanaServer.hostname" hostname as zero: "$hostname"', ({ hostname }) => { | |
expect(() => | |
ConfigSchema.validate({ | |
kibanaServer: { hostname }, | |
}) | |
).toThrowError( | |
`[kibanaServer.hostname]: cannot use '0.0.0.0' as Kibana host name, consider using the default (localhost) instead` | |
); | |
}); |
validate(value) { | ||
if (ipaddr.isValid(value) && !sum(ipaddr.parse(value).toByteArray())) { | ||
// prevent setting a hostname that fails in Chromium on Windows | ||
return `cannot use '0.0.0.0' as Kibana host name, consider using the default (localhost) instead`; |
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.
Could we substitute the actual value here? It is going to be a valid IP address, so that it should not print anything insecure.
return `cannot use '0.0.0.0' as Kibana host name, consider using the default (localhost) instead`; | |
return `cannot use '${value}' as Kibana host name, consider using the default (localhost) instead`; |
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 left some minor suggestions regarding the tests code, but the change itself looks good to me. Great job 👍
….host" is "0.0.0.0" (elastic#117022) * [Reporting] Internal correction for server hostname if "server.host" is "0.0.0.0" * add schema validation * correction to the failover logic the test is validation * update per feedback * more check against invalid hostnames * remove silly translations for server logs * remove unused translations * improve the tests
….host" is "0.0.0.0" (#117022) (#117441) * [Reporting] Internal correction for server hostname if "server.host" is "0.0.0.0" * add schema validation * correction to the failover logic the test is validation * update per feedback * more check against invalid hostnames * remove silly translations for server logs * remove unused translations * improve the tests
Closes #113832
Summary
0.0.0.0
is not a valid value forxpack.reporting.kibanaServer.hostname
. This setting does not work on windows.server.host
is used as thexpack.reporting.kibanaServer.hostname
value, the value must be converted tolocalhost
.Checklist
Release Note
Fixed an issue where PDF/PNG reporting would break on Windows if the Kibana server hostname was
0.0.0.0