Skip to content
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

Merged
merged 9 commits into from
Nov 3, 2021

Conversation

tsullivan
Copy link
Member

@tsullivan tsullivan commented Nov 1, 2021

Closes #113832

Summary

  • 0.0.0.0 is not a valid value for xpack.reporting.kibanaServer.hostname. This setting does not work on windows.
  • If the server.host is used as the xpack.reporting.kibanaServer.hostname value, the value must be converted to localhost.

Checklist

  • Test on Windows

Release Note

Fixed an issue where PDF/PNG reporting would break on Windows if the Kibana server hostname was 0.0.0.0

@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-reporting-services (Team:Reporting Services)

@tsullivan tsullivan added the SharedUX/fix-it-week Bugs that have been groomed and queued up for the team's next fix it week label Nov 1, 2021
Copy link
Contributor

@jloleysens jloleysens left a 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.

x-pack/plugins/reporting/server/config/schema.ts Outdated Show resolved Hide resolved
x-pack/plugins/reporting/server/config/create_config.ts Outdated Show resolved Hide resolved
@tsullivan tsullivan enabled auto-merge (squash) November 3, 2021 03:00
@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

✅ unchanged

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

Comment on lines +150 to +158
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 () => {
Copy link
Contributor

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.

Suggested change
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 }) => {

Comment on lines +46 to 49
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.',
]);
Copy link
Contributor

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.

Suggested change
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
expect(mockLogger.warn.mock.calls.length).toBe(0);
expect(mockLogger.warn).not.toHaveBeenCalled();

Comment on lines +170 to +177
mockCoreSetup.http.getServerInfo = jest.fn().mockImplementation(
(): HttpServerInfo => ({
name: 'cool server',
hostname,
port: 5601,
protocol: 'http',
})
);
Copy link
Contributor

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.

Suggested change
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',
}));

Comment on lines +180 to +185
const result = await createConfig$(mockCoreSetup, mockConfig$, mockLogger).toPromise();
expect(result.kibanaServer).toMatchObject({
hostname: 'localhost',
port: 5601,
protocol: 'http',
});
Copy link
Contributor

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).

Suggested change
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',
})
);

Comment on lines +291 to +299
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).`);
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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).`);
});

Comment on lines +301 to +311
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`
);
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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`;
Copy link
Contributor

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.

Suggested change
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`;

Copy link
Contributor

@dokmic dokmic left a 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 👍

@tsullivan tsullivan merged commit e1bf92c into elastic:main Nov 3, 2021
@tsullivan tsullivan deleted the reporting/usable-hostname branch November 3, 2021 17:26
tsullivan added a commit to tsullivan/kibana that referenced this pull request Nov 3, 2021
….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
tsullivan added a commit that referenced this pull request Nov 4, 2021
….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
@sophiec20 sophiec20 added the (Deprecated) Feature:Reporting Use Reporting:Screenshot, Reporting:CSV, or Reporting:Framework instead label Aug 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
(Deprecated) Feature:Reporting Use Reporting:Screenshot, Reporting:CSV, or Reporting:Framework instead release_note:fix SharedUX/fix-it-week Bugs that have been groomed and queued up for the team's next fix it week v8.0.0 v8.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Reporting] Avoid using 0.0.0.0 as the hostname for Chromium to open
6 participants