feat(trustedtypes): update vite config and the webassets integration to work with TT

This commit is contained in:
Jack Westbrook
2025-03-03 09:52:52 +01:00
parent db4ef2d0be
commit 5e8f0c6f52
5 changed files with 38 additions and 11 deletions
+18 -3
View File
@@ -34,6 +34,7 @@ type ViteManifestEntry struct {
IsDynamicEntry bool `json:"isDynamicEntry"`
IsEntry bool `json:"isEntry"`
Src string `json:"src"`
Name string `json:"name"`
}
type Manifest map[string]ViteManifestEntry
@@ -142,8 +143,10 @@ func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) {
return nil, fmt.Errorf("failed to read assets-manifest.json %w", err)
}
// TODO: This is a temporary hack to get the entrypoints for the vite frontend loading.
var entryPointJSAssets []dtos.EntryPointAsset
// TODO: This is temporary to get the entrypoints for the vite frontend loading.
// We need trusted types up front otherwise the entire app will fail to load if they're enabled.
var trustedTypePolicyAsset *dtos.EntryPointAsset
var otherJSAssets []dtos.EntryPointAsset
var preloadJSAssets []dtos.EntryPointAsset
var darkCSS, lightCSS string
@@ -155,7 +158,11 @@ func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) {
Integrity: "",
}
if strings.HasSuffix(entry.File, ".js") {
entryPointJSAssets = append(entryPointJSAssets, asset)
if entry.Name == "trustedTypePolicies" {
trustedTypePolicyAsset = &asset
} else {
otherJSAssets = append(otherJSAssets, asset)
}
preloadJSAssets = getPreloadChunks(manifest, entry.Src)
}
if entry.Src == "sass/grafana.dark.scss" && entry.IsEntry {
@@ -192,6 +199,14 @@ func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) {
// return nil, fmt.Errorf("missing swagger entry, try running `yarn build`")
// }
var entryPointJSAssets []dtos.EntryPointAsset
entryPointJSAssets = append([]dtos.EntryPointAsset{*trustedTypePolicyAsset}, otherJSAssets...)
if entryPointJSAssets == nil {
return nil, fmt.Errorf("no entrypoints found in assets manifest, try running `yarn build`")
}
rsp := &dtos.EntryPointAssets{
JSFiles: entryPointJSAssets,
PreloadJSFiles: preloadJSAssets,
+4 -5
View File
@@ -1,7 +1,6 @@
import { textUtil } from '@grafana/data';
import { config } from '@grafana/runtime';
import { sanitizeUrl } from '@braintree/sanitize-url';
const CSP_REPORT_ONLY_ENABLED = config.bootData.settings.cspReportOnlyEnabled;
const CSP_REPORT_ONLY_ENABLED = window.grafanaBootData!.settings.cspReportOnlyEnabled;
export const defaultTrustedTypesPolicy = {
createHTML: (string: string, source: string, sink: string) => {
@@ -14,7 +13,7 @@ export const defaultTrustedTypesPolicy = {
createScript: (string: string) => string,
createScriptURL: (string: string, source: string, sink: string) => {
if (!CSP_REPORT_ONLY_ENABLED) {
return textUtil.sanitizeUrl(string);
return sanitizeUrl(string);
}
console.error('[ScriptURL not sanitized with Trusted Types]', string, source, sink);
return string;
@@ -22,7 +21,7 @@ export const defaultTrustedTypesPolicy = {
};
if (
config.bootData.settings.trustedTypesDefaultPolicyEnabled &&
window.grafanaBootData!.settings.trustedTypesDefaultPolicyEnabled &&
window.trustedTypes &&
window.trustedTypes.createPolicy
) {
-1
View File
@@ -1,6 +1,5 @@
import './viteGlobals';
import 'vite/modulepreload-polyfill';
import './core/trustedTypePolicies';
// TODO: Vite does this differently...
// declare let __webpack_public_path__: string;
+1 -1
View File
@@ -1,7 +1,7 @@
[security]
content_security_policy = true
content_security_policy_template = """script-src 'self' 'unsafe-eval' 'unsafe-inline' 'strict-dynamic' $NONCE;object-src 'none';font-src 'self';style-src 'self' 'unsafe-inline' blob:;img-src * data:;base-uri 'self';connect-src 'self' grafana.com ws://$ROOT_PATH wss://$ROOT_PATH;manifest-src 'self';media-src 'none';form-action 'self';"""
content_security_policy_template = """require-trusted-types-for 'script'; script-src 'self' 'unsafe-eval' 'unsafe-inline' 'strict-dynamic' $NONCE;object-src 'none';font-src 'self';style-src 'self' 'unsafe-inline' blob:;img-src * data:;base-uri 'self';connect-src 'self' grafana.com ws://$ROOT_PATH wss://$ROOT_PATH;manifest-src 'self';media-src 'none';form-action 'self';"""
enable_frontend_sandbox_for_plugins = sandbox-app-test,sandbox-test-datasource,sandbox-test-panel
[feature_toggles]
+15 -1
View File
@@ -28,7 +28,21 @@ export default defineConfig(({ command }) => ({
// use manifest for backend integration in production
manifest: 'public/build/.vite/manifest.json',
rollupOptions: {
input: ['./public/app/index.ts', './public/sass/grafana.dark.scss', './public/sass/grafana.light.scss'],
input: [
// trustedTypePolicies.ts is a special case because it needs to be loaded before the index.js and vendor.js
// otherwise the policy is not applied and grafana fails to load.
'./public/app/core/trustedTypePolicies.ts',
'./public/app/index.ts',
'./public/sass/grafana.dark.scss',
'./public/sass/grafana.light.scss',
],
output: {
manualChunks(id) {
if (id.includes('@braintree/sanitize-url')) {
return 'braintree';
}
},
},
},
outDir: 'build_tmp',
assetsDir: 'public/build',