diff --git a/.golangci.toml b/.golangci.toml index b1499a28e..a6527dc33 100644 --- a/.golangci.toml +++ b/.golangci.toml @@ -111,6 +111,7 @@ "SA1019: cfg.SSLTemporaryRedirect is deprecated", "SA1019: cfg.SSLHost is deprecated", "SA1019: cfg.SSLForceHost is deprecated", + "SA1019: cfg.FeaturePolicy is deprecated", ] [[issues.exclude-rules]] path = "(.+)_test.go" diff --git a/docs/content/middlewares/http/headers.md b/docs/content/middlewares/http/headers.md index 6247c7208..8878d2863 100644 --- a/docs/content/middlewares/http/headers.md +++ b/docs/content/middlewares/http/headers.md @@ -435,8 +435,16 @@ The `referrerPolicy` allows sites to control whether browsers forward the `Refer ### `featurePolicy` +!!! warning + + Deprecated in favor of `permissionsPolicy` + The `featurePolicy` allows sites to control browser features. +### `permissionsPolicy` + +The `permissionsPolicy` allows sites to control browser features. + ### `isDevelopment` Set `isDevelopment` to `true` when developing to mitigate the unwanted effects of the `AllowedHosts`, SSL, and STS options. diff --git a/go.mod b/go.mod index a579f7a08..d42085f0e 100644 --- a/go.mod +++ b/go.mod @@ -75,7 +75,7 @@ require ( github.com/uber/jaeger-client-go v2.29.1+incompatible github.com/uber/jaeger-lib v2.2.0+incompatible github.com/unrolled/render v1.0.2 - github.com/unrolled/secure v1.0.7 + github.com/unrolled/secure v1.0.9 github.com/vdemeester/shakers v0.1.0 github.com/vulcand/oxy v1.3.0 github.com/vulcand/predicate v1.1.0 diff --git a/go.sum b/go.sum index 6188edebf..62084b397 100644 --- a/go.sum +++ b/go.sum @@ -181,8 +181,6 @@ github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3h github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY= -github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -1026,13 +1024,15 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/unrolled/render v1.0.2 h1:dGS3EmChQP3yOi1YeFNO/Dx+MbWZhdvhQJTXochM5bs= github.com/unrolled/render v1.0.2/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= -github.com/unrolled/secure v1.0.7 h1:BcQHp3iKZyZCKj5gRqwQG+5urnGBF00wGgoPPwtheVQ= -github.com/unrolled/secure v1.0.7/go.mod h1:uGc1OcRF8gCVBA+ANksKmvM85Hka6SZtQIbrKc3sHS4= +github.com/unrolled/secure v1.0.9 h1:BWRuEb1vDrBFFDdbCnKkof3gZ35I/bnHGyt0LB0TNyQ= +github.com/unrolled/secure v1.0.9/go.mod h1:fO+mEan+FLB0CdEnHf6Q4ZZVNqG+5fuLFnP8p0BXDPI= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= diff --git a/integration/fixtures/headers/secure.toml b/integration/fixtures/headers/secure.toml index 08a12319b..47404d616 100644 --- a/integration/fixtures/headers/secure.toml +++ b/integration/fixtures/headers/secure.toml @@ -34,7 +34,7 @@ [http.middlewares] [http.middlewares.secure.headers] - featurePolicy = "vibrate 'none';" + permissionsPolicy = "microphone=()," [http.services] [http.services.service1.loadBalancer] diff --git a/integration/headers_test.go b/integration/headers_test.go index a5e9e7e67..6e4b7e9b9 100644 --- a/integration/headers_test.go +++ b/integration/headers_test.go @@ -137,9 +137,9 @@ func (s *HeadersSuite) TestSecureHeadersResponses(c *check.C) { internalReqHost string }{ { - desc: "Feature-Policy Set", + desc: "Permissions-Policy Set", expected: http.Header{ - "Feature-Policy": {"vibrate 'none';"}, + "Permissions-Policy": {"microphone=(),"}, }, reqHost: "test.localhost", internalReqHost: "internal.localhost", @@ -185,7 +185,7 @@ func (s *HeadersSuite) TestMultipleSecureHeadersResponses(c *check.C) { reqHost string }{ { - desc: "Feature-Policy Set", + desc: "Multiple Secure Headers Set", expected: http.Header{ "X-Frame-Options": {"DENY"}, "X-Content-Type-Options": {"nosniff"}, diff --git a/pkg/anonymize/anonymize_config_test.go b/pkg/anonymize/anonymize_config_test.go index 6e69f1c8f..d874beb7e 100644 --- a/pkg/anonymize/anonymize_config_test.go +++ b/pkg/anonymize/anonymize_config_test.go @@ -226,6 +226,7 @@ func TestDo_dynamicConfiguration(t *testing.T) { PublicKey: "foo", ReferrerPolicy: "foo", FeaturePolicy: "foo", + PermissionsPolicy: "foo", IsDevelopment: true, }, Errors: &dynamic.ErrorPage{ diff --git a/pkg/anonymize/testdata/anonymized-dynamic-config.json b/pkg/anonymize/testdata/anonymized-dynamic-config.json index fc4e32e6a..b48bbc3bc 100644 --- a/pkg/anonymize/testdata/anonymized-dynamic-config.json +++ b/pkg/anonymize/testdata/anonymized-dynamic-config.json @@ -178,6 +178,7 @@ "publicKey": "xxxx", "referrerPolicy": "foo", "featurePolicy": "foo", + "permissionsPolicy": "foo", "isDevelopment": true }, "errors": { diff --git a/pkg/config/dynamic/middlewares.go b/pkg/config/dynamic/middlewares.go index dbcbba186..775e6d034 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -185,8 +185,10 @@ type Headers struct { ContentSecurityPolicy string `json:"contentSecurityPolicy,omitempty" toml:"contentSecurityPolicy,omitempty" yaml:"contentSecurityPolicy,omitempty"` PublicKey string `json:"publicKey,omitempty" toml:"publicKey,omitempty" yaml:"publicKey,omitempty"` ReferrerPolicy string `json:"referrerPolicy,omitempty" toml:"referrerPolicy,omitempty" yaml:"referrerPolicy,omitempty" export:"true"` - FeaturePolicy string `json:"featurePolicy,omitempty" toml:"featurePolicy,omitempty" yaml:"featurePolicy,omitempty" export:"true"` - IsDevelopment bool `json:"isDevelopment,omitempty" toml:"isDevelopment,omitempty" yaml:"isDevelopment,omitempty" export:"true"` + // Deprecated: use PermissionsPolicy instead. + FeaturePolicy string `json:"featurePolicy,omitempty" toml:"featurePolicy,omitempty" yaml:"featurePolicy,omitempty" export:"true"` + PermissionsPolicy string `json:"permissionsPolicy,omitempty" toml:"permissionsPolicy,omitempty" yaml:"permissionsPolicy,omitempty" export:"true"` + IsDevelopment bool `json:"isDevelopment,omitempty" toml:"isDevelopment,omitempty" yaml:"isDevelopment,omitempty" export:"true"` } // HasCustomHeadersDefined checks to see if any of the custom header elements have been set. @@ -229,6 +231,7 @@ func (h *Headers) HasSecureHeadersDefined() bool { h.PublicKey != "" || h.ReferrerPolicy != "" || h.FeaturePolicy != "" || + h.PermissionsPolicy != "" || h.IsDevelopment) } diff --git a/pkg/config/label/label_test.go b/pkg/config/label/label_test.go index a976c2e9a..7935418d9 100644 --- a/pkg/config/label/label_test.go +++ b/pkg/config/label/label_test.go @@ -68,6 +68,7 @@ func TestDecodeConfiguration(t *testing.T) { "traefik.http.middlewares.Middleware8.headers.publickey": "foobar", "traefik.http.middlewares.Middleware8.headers.referrerpolicy": "foobar", "traefik.http.middlewares.Middleware8.headers.featurepolicy": "foobar", + "traefik.http.middlewares.Middleware8.headers.permissionspolicy": "foobar", "traefik.http.middlewares.Middleware8.headers.sslforcehost": "true", "traefik.http.middlewares.Middleware8.headers.sslhost": "foobar", "traefik.http.middlewares.Middleware8.headers.sslproxyheaders.name0": "foobar", @@ -580,6 +581,7 @@ func TestDecodeConfiguration(t *testing.T) { PublicKey: "foobar", ReferrerPolicy: "foobar", FeaturePolicy: "foobar", + PermissionsPolicy: "foobar", IsDevelopment: true, }, }, @@ -1063,6 +1065,7 @@ func TestEncodeConfiguration(t *testing.T) { PublicKey: "foobar", ReferrerPolicy: "foobar", FeaturePolicy: "foobar", + PermissionsPolicy: "foobar", IsDevelopment: true, }, }, @@ -1204,6 +1207,7 @@ func TestEncodeConfiguration(t *testing.T) { "traefik.HTTP.Middlewares.Middleware8.Headers.PublicKey": "foobar", "traefik.HTTP.Middlewares.Middleware8.Headers.ReferrerPolicy": "foobar", "traefik.HTTP.Middlewares.Middleware8.Headers.FeaturePolicy": "foobar", + "traefik.HTTP.Middlewares.Middleware8.Headers.PermissionsPolicy": "foobar", "traefik.HTTP.Middlewares.Middleware8.Headers.SSLForceHost": "true", "traefik.HTTP.Middlewares.Middleware8.Headers.SSLHost": "foobar", "traefik.HTTP.Middlewares.Middleware8.Headers.SSLProxyHeaders.name0": "foobar", diff --git a/pkg/middlewares/headers/headers.go b/pkg/middlewares/headers/headers.go index 5d4c2224c..5ed9f2807 100644 --- a/pkg/middlewares/headers/headers.go +++ b/pkg/middlewares/headers/headers.go @@ -30,6 +30,9 @@ func handleDeprecation(ctx context.Context, cfg *dynamic.Headers) { if cfg.SSLForceHost { log.FromContext(ctx).Warn("SSLForceHost is deprecated, please use RedirectScheme middleware instead.") } + if cfg.FeaturePolicy != "" { + log.FromContext(ctx).Warn("FeaturePolicy is deprecated, please use PermissionsPolicy header instead.") + } } type headers struct { diff --git a/pkg/middlewares/headers/secure.go b/pkg/middlewares/headers/secure.go index 240efec17..0186de311 100644 --- a/pkg/middlewares/headers/secure.go +++ b/pkg/middlewares/headers/secure.go @@ -37,6 +37,7 @@ func newSecure(next http.Handler, cfg dynamic.Headers, contextKey string) *secur SSLProxyHeaders: cfg.SSLProxyHeaders, STSSeconds: cfg.STSSeconds, FeaturePolicy: cfg.FeaturePolicy, + PermissionsPolicy: cfg.PermissionsPolicy, SecureContextKey: contextKey, } diff --git a/pkg/middlewares/headers/secure_test.go b/pkg/middlewares/headers/secure_test.go index 5eb3ac562..ce2b93a7c 100644 --- a/pkg/middlewares/headers/secure_test.go +++ b/pkg/middlewares/headers/secure_test.go @@ -130,6 +130,13 @@ func Test_newSecure_modifyResponse(t *testing.T) { }, expected: http.Header{"Feature-Policy": []string{"vibrate 'none';"}}, }, + { + desc: "PermissionsPolicy", + cfg: dynamic.Headers{ + PermissionsPolicy: "microphone=(),", + }, + expected: http.Header{"Permissions-Policy": []string{"microphone=(),"}}, + }, { desc: "STSSeconds", cfg: dynamic.Headers{ diff --git a/pkg/provider/kv/kv_test.go b/pkg/provider/kv/kv_test.go index ad996b1ed..24dc3b86b 100644 --- a/pkg/provider/kv/kv_test.go +++ b/pkg/provider/kv/kv_test.go @@ -104,6 +104,7 @@ func Test_buildConfiguration(t *testing.T) { "traefik/http/middlewares/Middleware09/headers/contentTypeNosniff": "true", "traefik/http/middlewares/Middleware09/headers/accessControlAllowCredentials": "true", "traefik/http/middlewares/Middleware09/headers/featurePolicy": "foobar", + "traefik/http/middlewares/Middleware09/headers/permissionsPolicy": "foobar", "traefik/http/middlewares/Middleware09/headers/forceSTSHeader": "true", "traefik/http/middlewares/Middleware09/headers/sslRedirect": "true", "traefik/http/middlewares/Middleware09/headers/sslHost": "foobar", @@ -596,6 +597,7 @@ func Test_buildConfiguration(t *testing.T) { PublicKey: "foobar", ReferrerPolicy: "foobar", FeaturePolicy: "foobar", + PermissionsPolicy: "foobar", IsDevelopment: true, }, },