Skip to content

Commit cd164de

Browse files
dtomcejtraefiker
authored andcommitted
Add Feature-Policy header support
1 parent c0ef5ce commit cd164de

File tree

15 files changed

+194
-41
lines changed

15 files changed

+194
-41
lines changed

Gopkg.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/content/middlewares/headers.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,10 @@ The `publicKey` implements HPKP to prevent MITM attacks with forged certificates
370370

371371
The `referrerPolicy` allows sites to control when browsers will pass the Referer header to other sites.
372372

373+
### `featurePolicy`
374+
375+
The `featurePolicy` allows sites to control browser features.
376+
373377
### `isDevelopment`
374378

375379
Set `isDevelopment` to true when developing.

docs/content/reference/dynamic-configuration/docker-labels.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
- "traefik.http.middlewares.middleware09.headers.isdevelopment=true"
5252
- "traefik.http.middlewares.middleware09.headers.publickey=foobar"
5353
- "traefik.http.middlewares.middleware09.headers.referrerpolicy=foobar"
54+
- "traefik.http.middlewares.middleware09.headers.featurepolicy=foobar"
5455
- "traefik.http.middlewares.middleware09.headers.sslforcehost=true"
5556
- "traefik.http.middlewares.middleware09.headers.sslhost=foobar"
5657
- "traefik.http.middlewares.middleware09.headers.sslproxyheaders.name0=foobar"

docs/content/reference/dynamic-configuration/file.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
contentSecurityPolicy = "foobar"
162162
publicKey = "foobar"
163163
referrerPolicy = "foobar"
164+
featurePolicy = "foobar"
164165
isDevelopment = true
165166
[http.middlewares.Middleware09.headers.customRequestHeaders]
166167
name0 = "foobar"

docs/content/reference/dynamic-configuration/file.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ http:
194194
contentSecurityPolicy: foobar
195195
publicKey: foobar
196196
referrerPolicy: foobar
197+
featurePolicy: foobar
197198
isDevelopment: true
198199
Middleware10:
199200
ipWhiteList:

docs/content/reference/dynamic-configuration/marathon-labels.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"traefik.http.middlewares.middleware09.headers.isdevelopment": "true",
5252
"traefik.http.middlewares.middleware09.headers.publickey": "foobar",
5353
"traefik.http.middlewares.middleware09.headers.referrerpolicy": "foobar",
54+
"traefik.http.middlewares.middleware09.headers.featurepolicy": "foobar",
5455
"traefik.http.middlewares.middleware09.headers.sslforcehost": "true",
5556
"traefik.http.middlewares.middleware09.headers.sslhost": "foobar",
5657
"traefik.http.middlewares.middleware09.headers.sslproxyheaders.name0": "foobar",
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[global]
2+
checkNewVersion = false
3+
sendAnonymousUsage = false
4+
5+
[log]
6+
level = "DEBUG"
7+
8+
[entryPoints]
9+
[entryPoints.web]
10+
address = ":8000"
11+
12+
[providers.file]
13+
filename = "{{ .SelfFilename }}"
14+
15+
## dynamic configuration ##
16+
17+
[http.routers]
18+
[http.routers.router1]
19+
rule = "Host(`test.localhost`)"
20+
middlewares = ["secure"]
21+
service = "service1"
22+
23+
[http.routers.router2]
24+
rule = "Host(`test2.localhost`)"
25+
service = "service1"
26+
27+
[http.middlewares]
28+
[http.middlewares.secure.headers]
29+
featurePolicy = "vibrate 'none';"
30+
31+
[http.services]
32+
[http.services.service1.loadBalancer]
33+
[[http.services.service1.loadBalancer.servers]]
34+
url = "http://127.0.0.1:9000"

integration/headers_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,43 @@ func (s *HeadersSuite) TestCorsResponses(c *check.C) {
113113
c.Assert(err, checker.IsNil)
114114
}
115115
}
116+
117+
func (s *HeadersSuite) TestSecureHeadersResponses(c *check.C) {
118+
file := s.adaptFile(c, "fixtures/headers/secure.toml", struct{}{})
119+
defer os.Remove(file)
120+
cmd, display := s.traefikCmd(withConfigFile(file))
121+
defer display(c)
122+
123+
err := cmd.Start()
124+
c.Assert(err, checker.IsNil)
125+
defer cmd.Process.Kill()
126+
127+
backend := startTestServer("9000", http.StatusOK)
128+
defer backend.Close()
129+
130+
err = try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
131+
c.Assert(err, checker.IsNil)
132+
133+
testCase := []struct {
134+
desc string
135+
expected http.Header
136+
reqHost string
137+
}{
138+
{
139+
desc: "Feature-Policy Set",
140+
expected: http.Header{
141+
"Feature-Policy": {"vibrate 'none';"},
142+
},
143+
reqHost: "test.localhost",
144+
},
145+
}
146+
147+
for _, test := range testCase {
148+
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
149+
c.Assert(err, checker.IsNil)
150+
req.Host = test.reqHost
151+
152+
err = try.Request(req, 500*time.Millisecond, try.HasHeaderStruct(test.expected))
153+
c.Assert(err, checker.IsNil)
154+
}
155+
}

pkg/config/dynamic/fixtures/sample.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@
384384
contentSecurityPolicy = "foobar"
385385
publicKey = "foobar"
386386
referrerPolicy = "foobar"
387+
featurePolicy = "foobar"
387388
isDevelopment = true
388389
[http.middlewares.Middleware8.headers.customRequestHeaders]
389390
name0 = "foobar"
@@ -476,4 +477,4 @@
476477
[tls.stores.Store1]
477478
[tls.stores.Store1.defaultCertificate]
478479
certFile = "foobar"
479-
keyFile = "foobar"
480+
keyFile = "foobar"

pkg/config/dynamic/middlewares.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ type Headers struct {
167167
ContentSecurityPolicy string `json:"contentSecurityPolicy,omitempty" toml:"contentSecurityPolicy,omitempty" yaml:"contentSecurityPolicy,omitempty"`
168168
PublicKey string `json:"publicKey,omitempty" toml:"publicKey,omitempty" yaml:"publicKey,omitempty"`
169169
ReferrerPolicy string `json:"referrerPolicy,omitempty" toml:"referrerPolicy,omitempty" yaml:"referrerPolicy,omitempty"`
170+
FeaturePolicy string `json:"featurePolicy,omitempty" toml:"featurePolicy,omitempty" yaml:"featurePolicy,omitempty"`
170171
IsDevelopment bool `json:"isDevelopment,omitempty" toml:"isDevelopment,omitempty" yaml:"isDevelopment,omitempty"`
171172
}
172173

@@ -208,6 +209,7 @@ func (h *Headers) HasSecureHeadersDefined() bool {
208209
h.ContentSecurityPolicy != "" ||
209210
h.PublicKey != "" ||
210211
h.ReferrerPolicy != "" ||
212+
h.FeaturePolicy != "" ||
211213
h.IsDevelopment)
212214
}
213215

0 commit comments

Comments
 (0)