From 594f15051d0ca868639bb729ff0d0251d81d1669 Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Thu, 13 Dec 2018 17:42:38 -0500 Subject: [PATCH] MM-13498: fix subpath assets rewrite (#9997) * MM-13498: check that subpath rewrite of csp meta tag succeeds * MM-13498: fix subpath assets rewrite --- utils/subpath.go | 8 ++++++-- utils/subpath_test.go | 34 +++++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/utils/subpath.go b/utils/subpath.go index be06a73ef1..e691aa9d8a 100644 --- a/utils/subpath.go +++ b/utils/subpath.go @@ -69,9 +69,13 @@ func UpdateAssetsSubpath(subpath string) error { script := fmt.Sprintf("window.publicPath='%s'", newPath) scriptHash := sha256.Sum256([]byte(script)) - reCSP := regexp.MustCompile(``) + reCSP := regexp.MustCompile(``) + if results := reCSP.FindAllString(newRootHtml, -1); len(results) == 0 { + return fmt.Errorf("failed to find 'Content-Security-Policy' meta tag to rewrite") + } + newRootHtml = reCSP.ReplaceAllLiteralString(newRootHtml, fmt.Sprintf( - ``, + ``, base64.StdEncoding.EncodeToString(scriptHash[:]), )) diff --git a/utils/subpath_test.go b/utils/subpath_test.go index 6e417e1c51..4d8d05506c 100644 --- a/utils/subpath_test.go +++ b/utils/subpath_test.go @@ -1,6 +1,7 @@ package utils_test import ( + "fmt" "io/ioutil" "os" "path/filepath" @@ -38,6 +39,7 @@ func TestUpdateAssetsSubpath(t *testing.T) { MainCSS string ManifestJSON string Subpath string + ExpectedError error ExpectedRootHTML string ExpectedMainCSS string ExpectedManifestJSON string @@ -48,6 +50,7 @@ func TestUpdateAssetsSubpath(t *testing.T) { baseCss, baseManifestJson, "", + nil, baseRootHtml, baseCss, baseManifestJson, @@ -58,16 +61,29 @@ func TestUpdateAssetsSubpath(t *testing.T) { baseCss, baseManifestJson, "/", + nil, baseRootHtml, baseCss, baseManifestJson, }, + { + "content security policy not found", + contentSecurityPolicyNotFoundHtml, + baseCss, + baseManifestJson, + "/subpath", + fmt.Errorf("failed to find 'Content-Security-Policy' meta tag to rewrite"), + contentSecurityPolicyNotFoundHtml, + baseCss, + baseManifestJson, + }, { "subpath", baseRootHtml, baseCss, baseManifestJson, "/subpath", + nil, subpathRootHtml, subpathCss, subpathManifestJson, @@ -78,6 +94,7 @@ func TestUpdateAssetsSubpath(t *testing.T) { subpathCss, subpathManifestJson, "/nested/subpath", + nil, newSubpathRootHtml, newSubpathCss, newSubpathManifestJson, @@ -88,6 +105,7 @@ func TestUpdateAssetsSubpath(t *testing.T) { subpathCss, baseManifestJson, "/", + nil, resetRootHtml, baseCss, baseManifestJson, @@ -100,7 +118,11 @@ func TestUpdateAssetsSubpath(t *testing.T) { ioutil.WriteFile(filepath.Join(tempDir, model.CLIENT_DIR, "main.css"), []byte(testCase.MainCSS), 0700) ioutil.WriteFile(filepath.Join(tempDir, model.CLIENT_DIR, "manifest.json"), []byte(testCase.ManifestJSON), 0700) err := utils.UpdateAssetsSubpath(testCase.Subpath) - require.NoError(t, err) + if testCase.ExpectedError != nil { + require.Equal(t, testCase.ExpectedError, err) + } else { + require.NoError(t, err) + } contents, err := ioutil.ReadFile(filepath.Join(tempDir, model.CLIENT_DIR, "root.html")) require.NoError(t, err) @@ -193,19 +215,21 @@ func TestGetSubpathFromConfig(t *testing.T) { } } -const baseRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` +const contentSecurityPolicyNotFoundHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` + +const baseRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` const baseCss = `@font-face{font-family:FontAwesome;src:url(/static/files/674f50d287a8c48dc19ba404d20fe713.eot);src:url(/static/files/674f50d287a8c48dc19ba404d20fe713.eot?#iefix&v=4.7.0) format("embedded-opentype"),url(/static/files/af7ae505a9eed503f8b8e6982036873e.woff2) format("woff2"),url(/static/files/fee66e712a8a08eef5805a46892932ad.woff) format("woff"),url(/static/files/b06871f281fee6b241d60582ae9369b9.ttf) format("truetype"),url(/static/files/677433a0892aaed7b7d2628c313c9775.svg#fontawesomeregular) format("svg");font-weight:400;font-style:normal}` -const subpathRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` +const subpathRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` const subpathCss = `@font-face{font-family:FontAwesome;src:url(/subpath/static/files/674f50d287a8c48dc19ba404d20fe713.eot);src:url(/subpath/static/files/674f50d287a8c48dc19ba404d20fe713.eot?#iefix&v=4.7.0) format("embedded-opentype"),url(/subpath/static/files/af7ae505a9eed503f8b8e6982036873e.woff2) format("woff2"),url(/subpath/static/files/fee66e712a8a08eef5805a46892932ad.woff) format("woff"),url(/subpath/static/files/b06871f281fee6b241d60582ae9369b9.ttf) format("truetype"),url(/subpath/static/files/677433a0892aaed7b7d2628c313c9775.svg#fontawesomeregular) format("svg");font-weight:400;font-style:normal}` -const newSubpathRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` +const newSubpathRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` const newSubpathCss = `@font-face{font-family:FontAwesome;src:url(/nested/subpath/static/files/674f50d287a8c48dc19ba404d20fe713.eot);src:url(/nested/subpath/static/files/674f50d287a8c48dc19ba404d20fe713.eot?#iefix&v=4.7.0) format("embedded-opentype"),url(/nested/subpath/static/files/af7ae505a9eed503f8b8e6982036873e.woff2) format("woff2"),url(/nested/subpath/static/files/fee66e712a8a08eef5805a46892932ad.woff) format("woff"),url(/nested/subpath/static/files/b06871f281fee6b241d60582ae9369b9.ttf) format("truetype"),url(/nested/subpath/static/files/677433a0892aaed7b7d2628c313c9775.svg#fontawesomeregular) format("svg");font-weight:400;font-style:normal}` -const resetRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` +const resetRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` const baseManifestJson = `{ "icons": [