github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/web/middlewares/secure_test.go (about) 1 package middlewares 2 3 import ( 4 "net/http" 5 "net/http/httptest" 6 "testing" 7 "time" 8 9 "github.com/cozy/cozy-stack/model/instance" 10 "github.com/cozy/cozy-stack/pkg/assets/dynamic" 11 "github.com/cozy/cozy-stack/pkg/config/config" 12 "github.com/cozy/cozy-stack/tests/testutils" 13 "github.com/labstack/echo/v4" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestSecure(t *testing.T) { 19 if testing.Short() { 20 t.Skip("an instance is required for this test: test skipped due to the use of --short flag") 21 } 22 23 config.UseTestFile(t) 24 config.GetConfig().Assets = "../../assets" 25 setup := testutils.NewSetup(t, t.Name()) 26 27 setup.SetupSwiftTest() 28 require.NoError(t, dynamic.InitDynamicAssetFS(config.FsURL().String()), "Could not init dynamic FS") 29 30 t.Run("SecureMiddlewareHSTS", func(t *testing.T) { 31 e := echo.New() 32 req, _ := http.NewRequest(echo.GET, "http://app.cozy.local/", nil) 33 rec := httptest.NewRecorder() 34 c := e.NewContext(req, rec) 35 h := Secure(&SecureConfig{ 36 HSTSMaxAge: 3600 * time.Second, 37 })(echo.NotFoundHandler) 38 _ = h(c) 39 assert.Equal(t, "max-age=3600; includeSubDomains", rec.Header().Get(echo.HeaderStrictTransportSecurity)) 40 }) 41 42 t.Run("SecureMiddlewareCSP", func(t *testing.T) { 43 e1 := echo.New() 44 req1, _ := http.NewRequest(echo.GET, "http://app.cozy.local/", nil) 45 rec1 := httptest.NewRecorder() 46 c1 := e1.NewContext(req1, rec1) 47 h1 := Secure(&SecureConfig{ 48 CSPConnectSrc: nil, 49 CSPFrameSrc: nil, 50 CSPScriptSrc: nil, 51 })(echo.NotFoundHandler) 52 _ = h1(c1) 53 54 e2 := echo.New() 55 req2, _ := http.NewRequest(echo.GET, "http://app.cozy.local/", nil) 56 rec2 := httptest.NewRecorder() 57 c2 := e2.NewContext(req2, rec2) 58 h2 := Secure(&SecureConfig{ 59 CSPConnectSrc: nil, 60 CSPFrameSrc: []CSPSource{CSPSrcAny}, 61 CSPScriptSrc: []CSPSource{CSPSrcSelf}, 62 })(echo.NotFoundHandler) 63 _ = h2(c2) 64 65 e3 := echo.New() 66 req3, _ := http.NewRequest(echo.GET, "http://app.cozy.local/", nil) 67 rec3 := httptest.NewRecorder() 68 c3 := e3.NewContext(req3, rec3) 69 h3 := Secure(&SecureConfig{ 70 CSPConnectSrc: []CSPSource{CSPSrcParent, CSPSrcSelf}, 71 CSPFrameSrc: []CSPSource{CSPSrcAny}, 72 CSPScriptSrc: []CSPSource{CSPSrcSiblings}, 73 })(echo.NotFoundHandler) 74 _ = h3(c3) 75 76 e4 := echo.New() 77 req4, _ := http.NewRequest(echo.GET, "http://app.cozy.local/", nil) 78 rec4 := httptest.NewRecorder() 79 c4 := e4.NewContext(req4, rec4) 80 c4.Set("instance", &instance.Instance{ContextName: "test"}) 81 h4 := Secure(&SecureConfig{ 82 CSPConnectSrc: nil, 83 CSPFrameSrc: []CSPSource{CSPSrcAny}, 84 CSPScriptSrc: []CSPSource{CSPSrcSelf}, 85 CSPPerContext: map[string]map[string]string{ 86 "test": { 87 "frame": "https://example.net", 88 "connect": "https://example.com", 89 }, 90 }, 91 })(echo.NotFoundHandler) 92 _ = h4(c4) 93 94 assert.Equal(t, "", rec1.Header().Get(echo.HeaderContentSecurityPolicy)) 95 assert.Equal(t, "script-src 'self';frame-src *;", rec2.Header().Get(echo.HeaderContentSecurityPolicy)) 96 assert.Equal(t, "script-src https://*.cozy.local;frame-src *;connect-src https://cozy.local 'self';", rec3.Header().Get(echo.HeaderContentSecurityPolicy)) 97 assert.Equal(t, "script-src 'self';frame-src * https://example.net;connect-src https://example.com;", rec4.Header().Get(echo.HeaderContentSecurityPolicy)) 98 }) 99 100 t.Run("AppendCSPRule", func(t *testing.T) { 101 r := appendCSPRule("", "frame-ancestors", "new-rule") 102 assert.Equal(t, "frame-ancestors new-rule;", r) 103 104 r = appendCSPRule("frame-ancestors;", "frame-ancestors", "new-rule") 105 assert.Equal(t, "frame-ancestors new-rule;", r) 106 107 r = appendCSPRule("frame-ancestors 1 2 3 ;", "frame-ancestors", "new-rule") 108 assert.Equal(t, "frame-ancestors 1 2 3 new-rule;", r) 109 110 r = appendCSPRule("frame-ancestors 1 2 3 ;", "frame-ancestors", "new-rule", "new-rule-2") 111 assert.Equal(t, "frame-ancestors 1 2 3 new-rule new-rule-2;", r) 112 113 r = appendCSPRule("frame-ancestors 'none';", "frame-ancestors", "new-rule") 114 assert.Equal(t, "frame-ancestors new-rule;", r) 115 116 r = appendCSPRule("script '*'; frame-ancestors 'self';", "frame-ancestors", "new-rule") 117 assert.Equal(t, "script '*'; frame-ancestors 'self' new-rule;", r) 118 119 r = appendCSPRule("script '*'; frame-ancestors 'self'; plop plop;", "frame-ancestors", "new-rule") 120 assert.Equal(t, "script '*'; frame-ancestors 'self' new-rule; plop plop;", r) 121 122 r = appendCSPRule("script '*'; toto;", "frame-ancestors", "new-rule") 123 assert.Equal(t, "script '*'; toto;frame-ancestors new-rule;", r) 124 }) 125 }