feat(consulcatalog): add custom Headers tags.
This commit is contained in:
parent
8e7ac513b6
commit
238acd9330
3 changed files with 180 additions and 0 deletions
|
@ -55,6 +55,7 @@ func (p *CatalogProvider) buildConfiguration(catalog []catalogUpdate) *types.Con
|
|||
"getErrorPages": p.getErrorPages,
|
||||
"hasRateLimit": p.getFuncHasAttributePrefix(label.BaseFrontendRateLimit),
|
||||
"getRateLimit": p.getRateLimit,
|
||||
"getHeaders": p.getHeaders,
|
||||
}
|
||||
|
||||
var allNodes []*api.ServiceEntry
|
||||
|
@ -336,6 +337,37 @@ func (p *CatalogProvider) getRateLimit(tags []string) *types.RateLimit {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *CatalogProvider) getHeaders(tags []string) *types.Headers {
|
||||
headers := &types.Headers{
|
||||
CustomRequestHeaders: p.getMapAttribute(label.SuffixFrontendRequestHeaders, tags),
|
||||
CustomResponseHeaders: p.getMapAttribute(label.SuffixFrontendResponseHeaders, tags),
|
||||
SSLProxyHeaders: p.getMapAttribute(label.SuffixFrontendHeadersSSLProxyHeaders, tags),
|
||||
AllowedHosts: p.getSliceAttribute(label.SuffixFrontendHeadersAllowedHosts, tags),
|
||||
HostsProxyHeaders: p.getSliceAttribute(label.SuffixFrontendHeadersHostsProxyHeaders, tags),
|
||||
SSLHost: p.getAttribute(label.SuffixFrontendHeadersSSLHost, tags, ""),
|
||||
CustomFrameOptionsValue: p.getAttribute(label.SuffixFrontendHeadersCustomFrameOptionsValue, tags, ""),
|
||||
ContentSecurityPolicy: p.getAttribute(label.SuffixFrontendHeadersContentSecurityPolicy, tags, ""),
|
||||
PublicKey: p.getAttribute(label.SuffixFrontendHeadersPublicKey, tags, ""),
|
||||
ReferrerPolicy: p.getAttribute(label.SuffixFrontendHeadersReferrerPolicy, tags, ""),
|
||||
STSSeconds: p.getInt64Attribute(label.SuffixFrontendHeadersSTSSeconds, tags, 0),
|
||||
SSLRedirect: p.getBoolAttribute(label.SuffixFrontendHeadersSSLRedirect, tags, false),
|
||||
SSLTemporaryRedirect: p.getBoolAttribute(label.SuffixFrontendHeadersSSLTemporaryRedirect, tags, false),
|
||||
STSIncludeSubdomains: p.getBoolAttribute(label.SuffixFrontendHeadersSTSIncludeSubdomains, tags, false),
|
||||
STSPreload: p.getBoolAttribute(label.SuffixFrontendHeadersSTSPreload, tags, false),
|
||||
ForceSTSHeader: p.getBoolAttribute(label.SuffixFrontendHeadersForceSTSHeader, tags, false),
|
||||
FrameDeny: p.getBoolAttribute(label.SuffixFrontendHeadersFrameDeny, tags, false),
|
||||
ContentTypeNosniff: p.getBoolAttribute(label.SuffixFrontendHeadersContentTypeNosniff, tags, false),
|
||||
BrowserXSSFilter: p.getBoolAttribute(label.SuffixFrontendHeadersBrowserXSSFilter, tags, false),
|
||||
IsDevelopment: p.getBoolAttribute(label.SuffixFrontendHeadersIsDevelopment, tags, false),
|
||||
}
|
||||
|
||||
if !headers.HasSecureHeadersDefined() && !headers.HasCustomHeadersDefined() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
// Base functions
|
||||
|
||||
func (p *CatalogProvider) parseTagsToNeutralLabels(tags []string) map[string]string {
|
||||
|
@ -372,6 +404,16 @@ func (p *CatalogProvider) getFuncSliceAttribute(name string) func(tags []string)
|
|||
}
|
||||
}
|
||||
|
||||
func (p *CatalogProvider) getMapAttribute(name string, tags []string) map[string]string {
|
||||
rawValue := getTag(p.getPrefixedName(name), tags, "")
|
||||
|
||||
if len(rawValue) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return label.ParseMapValue(p.getPrefixedName(name), rawValue)
|
||||
}
|
||||
|
||||
func (p *CatalogProvider) getFuncIntAttribute(name string, defaultValue int) func(tags []string) int {
|
||||
return func(tags []string) int {
|
||||
return p.getIntAttribute(name, tags, defaultValue)
|
||||
|
|
|
@ -1166,3 +1166,88 @@ func TestCatalogProviderGetRateLimit(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCatalogProviderGetHeaders(t *testing.T) {
|
||||
p := &CatalogProvider{
|
||||
Prefix: "traefik",
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
tags []string
|
||||
expected *types.Headers
|
||||
}{
|
||||
{
|
||||
desc: "should return nil when no tags",
|
||||
tags: []string{},
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
desc: "should return a struct when has tags",
|
||||
tags: []string{
|
||||
label.TraefikFrontendRequestHeaders + "=Access-Control-Allow-Methods:POST,GET,OPTIONS || Content-type: application/json; charset=utf-8",
|
||||
label.TraefikFrontendResponseHeaders + "=Access-Control-Allow-Methods:POST,GET,OPTIONS || Content-type: application/json; charset=utf-8",
|
||||
label.TraefikFrontendSSLProxyHeaders + "=Access-Control-Allow-Methods:POST,GET,OPTIONS || Content-type: application/json; charset=utf-8",
|
||||
label.TraefikFrontendAllowedHosts + "=foo,bar,bor",
|
||||
label.TraefikFrontendHostsProxyHeaders + "=foo,bar,bor",
|
||||
label.TraefikFrontendSSLHost + "=foo",
|
||||
label.TraefikFrontendCustomFrameOptionsValue + "=foo",
|
||||
label.TraefikFrontendContentSecurityPolicy + "=foo",
|
||||
label.TraefikFrontendPublicKey + "=foo",
|
||||
label.TraefikFrontendReferrerPolicy + "=foo",
|
||||
label.TraefikFrontendSTSSeconds + "=666",
|
||||
label.TraefikFrontendSSLRedirect + "=true",
|
||||
label.TraefikFrontendSSLTemporaryRedirect + "=true",
|
||||
label.TraefikFrontendSTSIncludeSubdomains + "=true",
|
||||
label.TraefikFrontendSTSPreload + "=true",
|
||||
label.TraefikFrontendForceSTSHeader + "=true",
|
||||
label.TraefikFrontendFrameDeny + "=true",
|
||||
label.TraefikFrontendContentTypeNosniff + "=true",
|
||||
label.TraefikFrontendBrowserXSSFilter + "=true",
|
||||
label.TraefikFrontendIsDevelopment + "=true",
|
||||
},
|
||||
expected: &types.Headers{
|
||||
CustomRequestHeaders: map[string]string{
|
||||
"Access-Control-Allow-Methods": "POST,GET,OPTIONS",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
CustomResponseHeaders: map[string]string{
|
||||
"Access-Control-Allow-Methods": "POST,GET,OPTIONS",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
SSLProxyHeaders: map[string]string{
|
||||
"Access-Control-Allow-Methods": "POST,GET,OPTIONS",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
AllowedHosts: []string{"foo", "bar", "bor"},
|
||||
HostsProxyHeaders: []string{"foo", "bar", "bor"},
|
||||
SSLHost: "foo",
|
||||
CustomFrameOptionsValue: "foo",
|
||||
ContentSecurityPolicy: "foo",
|
||||
PublicKey: "foo",
|
||||
ReferrerPolicy: "foo",
|
||||
STSSeconds: 666,
|
||||
SSLRedirect: true,
|
||||
SSLTemporaryRedirect: true,
|
||||
STSIncludeSubdomains: true,
|
||||
STSPreload: true,
|
||||
ForceSTSHeader: true,
|
||||
FrameDeny: true,
|
||||
ContentTypeNosniff: true,
|
||||
BrowserXSSFilter: true,
|
||||
IsDevelopment: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
result := p.getHeaders(test.tags)
|
||||
|
||||
assert.Equal(t, test.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,59 @@
|
|||
|
||||
{{end}}
|
||||
|
||||
{{ $headers := getHeaders $service.Attributes }}
|
||||
{{ if $headers }}
|
||||
[frontends."frontend-{{ $service.ServiceName }}".headers]
|
||||
SSLRedirect = {{ $headers.SSLRedirect }}
|
||||
SSLTemporaryRedirect = {{ $headers.SSLTemporaryRedirect }}
|
||||
SSLHost = "{{ $headers.SSLHost }}"
|
||||
STSSeconds = {{ $headers.STSSeconds }}
|
||||
STSIncludeSubdomains = {{ $headers.STSIncludeSubdomains }}
|
||||
STSPreload = {{ $headers.STSPreload }}
|
||||
ForceSTSHeader = {{ $headers.ForceSTSHeader }}
|
||||
FrameDeny = {{ $headers.FrameDeny }}
|
||||
CustomFrameOptionsValue = "{{ $headers.CustomFrameOptionsValue }}"
|
||||
ContentTypeNosniff = {{ $headers.ContentTypeNosniff }}
|
||||
BrowserXSSFilter = {{ $headers.BrowserXSSFilter }}
|
||||
ContentSecurityPolicy = "{{ $headers.ContentSecurityPolicy }}"
|
||||
PublicKey = "{{ $headers.PublicKey }}"
|
||||
ReferrerPolicy = "{{ $headers.ReferrerPolicy }}"
|
||||
IsDevelopment = {{ $headers.IsDevelopment }}
|
||||
|
||||
{{ if $headers.AllowedHosts }}
|
||||
AllowedHosts = [{{ range $headers.AllowedHosts }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{ if $headers.HostsProxyHeaders }}
|
||||
HostsProxyHeaders = [{{ range $headers.HostsProxyHeaders }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{ if $headers.CustomRequestHeaders }}
|
||||
[frontends."frontend-{{ $service.ServiceName }}".headers.customRequestHeaders]
|
||||
{{ range $k, $v := $headers.CustomRequestHeaders }}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{ if $headers.CustomResponseHeaders }}
|
||||
[frontends."frontend-{{ $service.ServiceName }}".headers.customResponseHeaders]
|
||||
{{ range $k, $v := $headers.CustomResponseHeaders }}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{ if $headers.SSLProxyHeaders }}
|
||||
[frontends."frontend-{{ $service.ServiceName }}".headers.SSLProxyHeaders]
|
||||
{{range $k, $v := $headers.SSLProxyHeaders}}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
[frontends."frontend-{{ $service.ServiceName }}".routes."route-host-{{ $service.ServiceName }}"]
|
||||
rule = "{{ getFrontendRule $service }}"
|
||||
|
||||
|
|
Loading…
Reference in a new issue