-
Notifications
You must be signed in to change notification settings - Fork 8.1k
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] Add support for configuring a CDN (part I) #169408
Merged
jloleysens
merged 21 commits into
elastic:main
from
jloleysens:introduce-cdn-as-config-and-use-it
Oct 21, 2023
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
79d7aea
checkpoint 0: added new concept of "StaticAssets" and renamed a few t…
jloleysens cf9ef1e
add new files
jloleysens 78cd78c
added config to allow use of cdns w.r.t. csp
jloleysens e8969c3
more tests!
jloleysens 8a3f036
remove # private
jloleysens f64cf84
minor tweaks
jloleysens a5a6e9c
server bootstrap JS from kibana server
jloleysens bc68067
added cdn test file
jloleysens d209f6a
I guess we won't make translations static yet
jloleysens 45c43e7
added a comment
jloleysens d9f2c2a
update tests
jloleysens 02a2781
added static assets test and minor refactor
jloleysens b9787a0
update CSP based on feedback and added a test
jloleysens deb0031
fix http config
jloleysens c16b0b2
Merge branch 'main' into introduce-cdn-as-config-and-use-it
jloleysens 5cbb75a
rename var
jloleysens 8654895
slight update to tests
jloleysens a9fe5fa
update test snapshot
jloleysens 8b68ba3
remove scoped static assets path
jloleysens 35c6a49
Merge branch 'main' into introduce-cdn-as-config-and-use-it
jloleysens 2d03945
update jest test
jloleysens File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
1 change: 1 addition & 0 deletions
1
packages/core/http/core-http-server-internal/src/__snapshots__/http_config.test.ts.snap
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
57 changes: 57 additions & 0 deletions
57
packages/core/http/core-http-server-internal/src/cdn.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { CdnConfig } from './cdn'; | ||
|
||
describe('CdnConfig', () => { | ||
it.each([ | ||
['https://cdn.elastic.co', 'cdn.elastic.co'], | ||
['https://foo.bar', 'foo.bar'], | ||
['http://foo.bar', 'foo.bar'], | ||
['https://cdn.elastic.co:9999', 'cdn.elastic.co:9999'], | ||
['https://cdn.elastic.co:9999/with-a-path', 'cdn.elastic.co:9999'], | ||
])('host as expected for %p', (url, expected) => { | ||
expect(CdnConfig.from({ url }).host).toEqual(expected); | ||
}); | ||
|
||
it.each([ | ||
['https://cdn.elastic.co', 'https://cdn.elastic.co'], | ||
['https://foo.bar', 'https://foo.bar'], | ||
['http://foo.bar', 'http://foo.bar'], | ||
['https://cdn.elastic.co:9999', 'https://cdn.elastic.co:9999'], | ||
['https://cdn.elastic.co:9999/with-a-path', 'https://cdn.elastic.co:9999/with-a-path'], | ||
])('base HREF as expected for %p', (url, expected) => { | ||
expect(CdnConfig.from({ url }).baseHref).toEqual(expected); | ||
}); | ||
|
||
it.each([['foo'], ['#!']])('throws for invalid URLs (%p)', (url) => { | ||
expect(() => CdnConfig.from({ url })).toThrow(/Invalid URL/); | ||
}); | ||
|
||
it('handles empty urls', () => { | ||
expect(CdnConfig.from({ url: '' }).baseHref).toBeUndefined(); | ||
expect(CdnConfig.from({ url: '' }).host).toBeUndefined(); | ||
}); | ||
|
||
it('generates the expected CSP additions', () => { | ||
const cdnConfig = CdnConfig.from({ url: 'https://foo.bar:9999' }); | ||
expect(cdnConfig.getCspConfig()).toEqual({ | ||
connect_src: ['foo.bar:9999'], | ||
font_src: ['foo.bar:9999'], | ||
img_src: ['foo.bar:9999'], | ||
script_src: ['foo.bar:9999'], | ||
style_src: ['foo.bar:9999'], | ||
worker_src: ['foo.bar:9999'], | ||
}); | ||
}); | ||
|
||
it('generates the expected CSP additions when no URL is provided', () => { | ||
const cdnConfig = CdnConfig.from({ url: '' }); | ||
expect(cdnConfig.getCspConfig()).toEqual({}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { URL, format } from 'node:url'; | ||
import type { CspAdditionalConfig } from './csp'; | ||
|
||
export interface Input { | ||
url?: string; | ||
} | ||
|
||
export class CdnConfig { | ||
private url: undefined | URL; | ||
constructor(url?: string) { | ||
if (url) { | ||
this.url = new URL(url); // This will throw for invalid URLs | ||
} | ||
} | ||
|
||
public get host(): undefined | string { | ||
return this.url?.host ?? undefined; | ||
} | ||
|
||
public get baseHref(): undefined | string { | ||
if (this.url) { | ||
return this.url.pathname === '/' ? this.url.origin : format(this.url); | ||
} | ||
} | ||
|
||
public getCspConfig(): CspAdditionalConfig { | ||
const host = this.host; | ||
if (!host) return {}; | ||
return { | ||
font_src: [host], | ||
img_src: [host], | ||
script_src: [host], | ||
style_src: [host], | ||
worker_src: [host], | ||
connect_src: [host], | ||
}; | ||
} | ||
|
||
public static from(input: Input = {}) { | ||
return new CdnConfig(input.url); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
packages/core/http/core-http-server-internal/src/static_assets.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { StaticAssets } from './static_assets'; | ||
import { BasePath } from './base_path_service'; | ||
import { CdnConfig } from './cdn'; | ||
|
||
describe('StaticAssets', () => { | ||
let basePath: BasePath; | ||
let cdnConfig: CdnConfig; | ||
let staticAssets: StaticAssets; | ||
beforeEach(() => { | ||
basePath = new BasePath('/test'); | ||
cdnConfig = CdnConfig.from(); | ||
staticAssets = new StaticAssets(basePath, cdnConfig); | ||
}); | ||
it('provides fallsback to server base path', () => { | ||
expect(staticAssets.getHrefBase()).toEqual('/test'); | ||
}); | ||
|
||
it('provides the correct HREF given a CDN is configured', () => { | ||
cdnConfig = CdnConfig.from({ url: 'https://cdn.example.com/test' }); | ||
staticAssets = new StaticAssets(basePath, cdnConfig); | ||
expect(staticAssets.getHrefBase()).toEqual('https://cdn.example.com/test'); | ||
}); | ||
}); |
28 changes: 28 additions & 0 deletions
28
packages/core/http/core-http-server-internal/src/static_assets.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import type { BasePath } from './base_path_service'; | ||
import { CdnConfig } from './cdn'; | ||
|
||
export interface IStaticAssets { | ||
getHrefBase(): string; | ||
} | ||
|
||
export class StaticAssets implements IStaticAssets { | ||
jloleysens marked this conversation as resolved.
Show resolved
Hide resolved
|
||
constructor(private readonly basePath: BasePath, private readonly cdnConfig: CdnConfig) {} | ||
/** | ||
* Returns a href (hypertext reference) intended to be used as the base for constructing | ||
* other hrefs to static assets. | ||
*/ | ||
getHrefBase(): string { | ||
if (this.cdnConfig.baseHref) { | ||
return this.cdnConfig.baseHref; | ||
} | ||
return this.basePath.serverBasePath; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 would just have gone with
Partial<CspConfigType>
, but what you did is probably better 😄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.
Yeah, I had that initially, but there is other funky stuff in there and I wanted scope the overrides to just the policy directives