Add docker security headers via labels
This commit is contained in:
parent
bee8ebb00b
commit
7063da1c7d
5 changed files with 369 additions and 50 deletions
|
@ -205,6 +205,52 @@ var _templatesDockerTmpl = []byte(`{{$backendServers := .Servers}}
|
|||
basicAuth = [{{range getBasicAuth $container}}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
[frontends."frontend-{{$frontend}}".headers]
|
||||
{{if hasSSLRedirectHeaders $container}}
|
||||
SSLRedirect = {{getSSLRedirectHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasSSLTemporaryRedirectHeaders $container}}
|
||||
SSLTemporaryRedirect = {{getSSLTemporaryRedirectHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasSSLHostHeaders $container}}
|
||||
SSLHost = {{getSSLHostHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasSTSSecondsHeaders $container}}
|
||||
STSSeconds = {{getSTSSecondsHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasSTSIncludeSubdomainsHeaders $container}}
|
||||
STSIncludeSubdomains = {{getSTSIncludeSubdomainsHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasSTSPreloadHeaders $container}}
|
||||
STSPreload = {{getSTSPreloadHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasForceSTSHeaderHeaders $container}}
|
||||
ForceSTSHeader = {{getForceSTSHeaderHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasFrameDenyHeaders $container}}
|
||||
FrameDeny = {{getFrameDenyHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasCustomFrameOptionsValueHeaders $container}}
|
||||
CustomFrameOptionsValue = {{getCustomFrameOptionsValueHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasContentTypeNosniffHeaders $container}}
|
||||
ContentTypeNosniff = {{getContentTypeNosniffHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasBrowserXSSFilterHeaders $container}}
|
||||
BrowserXSSFilter = {{getBrowserXSSFilterHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasContentSecurityPolicyHeaders $container}}
|
||||
ContentSecurityPolicy = {{getContentSecurityPolicyHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasPublicKeyHeaders $container}}
|
||||
PublicKey = {{getPublicKeyHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasReferrerPolicyHeaders $container}}
|
||||
ReferrerPolicy = {{getReferrerPolicyHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasIsDevelopmentHeaders $container}}
|
||||
IsDevelopment = {{getIsDevelopmentHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasRequestHeaders $container}}
|
||||
[frontends."frontend-{{$frontend}}".headers.customrequestheaders]
|
||||
{{range $k, $v := getRequestHeaders $container}}
|
||||
|
@ -216,6 +262,24 @@ var _templatesDockerTmpl = []byte(`{{$backendServers := .Servers}}
|
|||
{{range $k, $v := getResponseHeaders $container}}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if hasAllowedHostsHeaders $container}}
|
||||
[frontends."frontend-{{$frontend}}".headers.AllowedHosts]
|
||||
{{range getAllowedHostsHeaders $container}}
|
||||
"{{.}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if hasHostsProxyHeaders $container}}
|
||||
[frontends."frontend-{{$frontend}}".headers.HostsProxyHeaders]
|
||||
{{range getHostsProxyHeaders $container}}
|
||||
"{{.}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if hasSSLProxyHeaders $container}}
|
||||
[frontends."frontend-{{$frontend}}".headers.SSLProxyHeaders]
|
||||
{{range $k, $v := getSSLProxyHeaders $container}}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
[frontends."frontend-{{$frontend}}".routes."route-frontend-{{$frontend}}"]
|
||||
rule = "{{getFrontendRule $container}}"
|
||||
|
|
|
@ -169,11 +169,33 @@ Labels can be used on containers to override default behaviour.
|
|||
| `traefik.frontend.entryPoints=http,https` | Assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints` |
|
||||
| `traefik.frontend.auth.basic=EXPR` | Sets basic authentication for that frontend in CSV format: `User:Hash,User:Hash` |
|
||||
| `traefik.frontend.whitelistSourceRange:RANGE` | List of IP-Ranges which are allowed to access. An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. |
|
||||
| `traefik.frontend.headers.customrequestheaders=EXPR ` | Provides the container with custom request headers that will be appended to each request forwarded to the container. Format: `HEADER:value,HEADER2:value2` |
|
||||
| `traefik.frontend.headers.customresponseheaders=EXPR` | Appends the headers to each response returned by the container, before forwarding the response to the client. Format: `HEADER:value,HEADER2:value2` |
|
||||
| `traefik.docker.network` | Set the docker network to use for connections to this container. If a container is linked to several networks, be sure to set the proper network name (you can check with `docker inspect <container_id>`) otherwise it will randomly pick one (depending on how docker is returning them). For instance when deploying docker `stack` from compose files, the compose defined networks will be prefixed with the `stack` name. |
|
||||
| `traefik.frontend.redirect=https` | Enables Redirect to another entryPoint for that frontend (e.g. HTTPS) |
|
||||
|
||||
#### Security Headers
|
||||
|
||||
| Label | Description |
|
||||
|-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `traefik.frontend.headers.allowedHosts=EXPR` | Provides a list of allowed hosts that requests will be processed. Format: `Host1,Host2` |
|
||||
|`traefik.frontend.headers.customrequestheaders=EXPR ` | Provides the container with custom request headers that will be appended to each request forwarded to the container. Format: `HEADER:value,HEADER2:value2` |
|
||||
| `traefik.frontend.headers.customresponseheaders=EXPR` | Appends the headers to each response returned by the container, before forwarding the response to the client. Format: `HEADER:value,HEADER2:value2` |
|
||||
|`traefik.frontend.headers.hostsProxyHeaders=EXPR ` | Provides a list of headers that the proxied hostname may be stored. Format: `HEADER1,HEADER2` |
|
||||
| `traefik.frontend.headers.SSLRedirect=true` | Forces the frontend to redirect to SSL if a non-SSL request is sent. |
|
||||
| `traefik.frontend.headers.SSLTemporaryRedirect=true` | Forces the frontend to redirect to SSL if a non-SSL request is sent, but by sending a 302 instead of a 301. |
|
||||
| `traefik.frontend.headers.SSLHost=HOST` | This setting configures the hostname that redirects will be based on. Default is "", which is the same host as the request. |
|
||||
| `traefik.frontend.headers.SSLProxyHeaders=EXPR` | Header combinations that would signify a proper SSL Request (Such as X-Forwarded-For:https). Format: `HEADER:value,HEADER2:value2` |
|
||||
| `traefik.frontend.headers.STSSeconds=315360000` | Sets the max-age of the STS header. |
|
||||
| `traefik.frontend.headers.STSIncludeSubdomains=true` | Adds the IncludeSubdomains section of the STS header. |
|
||||
| `traefik.frontend.headers.STSPreload=true` | Adds the preload flag to the STS header. |
|
||||
| `traefik.frontend.headers.forceSTSHeader=false` | Adds the STS header to non-SSL requests. |
|
||||
| `traefik.frontend.headers.frameDeny=false` | Adds the `X-Frame-Options` header with the value of `DENY`. |
|
||||
| `traefik.frontend.headers.customFrameOptionsValue=VALUE` | Overrides the `X-Frame-Options` header with the custom value. |
|
||||
| `traefik.frontend.headers.contentTypeNosniff=true` | Adds the `X-Content-Type-Options` header with the value `nosniff`. |
|
||||
| `traefik.frontend.headers.browserXSSFilter=true` | Adds the X-XSS-Protection header with the value `1; mode=block`. |
|
||||
| `traefik.frontend.headers.contentSecurityPolicy=VALUE` | Adds CSP Header with the custom value. |
|
||||
| `traefik.frontend.headers.publicKey=VALUE` | Adds pinned HTST public key header. |
|
||||
| `traefik.frontend.headers.referrerPolicy=VALUE` | Adds referrer policy header. |
|
||||
| `traefik.frontend.headers.isDevelopment=false` | This will cause the AllowedHosts, SSLRedirect, and STSSeconds/STSIncludeSubdomains options to be ignored during development. When deploying to production, be sure to set this to false. |
|
||||
### On Service
|
||||
|
||||
Services labels can be used for overriding default behaviour
|
||||
|
|
|
@ -260,46 +260,82 @@ func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *s
|
|||
|
||||
func (p *Provider) loadDockerConfig(containersInspected []dockerData) *types.Configuration {
|
||||
var DockerFuncMap = template.FuncMap{
|
||||
"getBackend": p.getBackend,
|
||||
"getIPAddress": p.getIPAddress,
|
||||
"getPort": p.getPort,
|
||||
"getWeight": p.getWeight,
|
||||
"getDomain": p.getDomain,
|
||||
"getProtocol": p.getProtocol,
|
||||
"getPassHostHeader": p.getPassHostHeader,
|
||||
"getPriority": p.getPriority,
|
||||
"getEntryPoints": p.getEntryPoints,
|
||||
"getBasicAuth": p.getBasicAuth,
|
||||
"getFrontendRule": p.getFrontendRule,
|
||||
"getRedirect": p.getRedirect,
|
||||
"hasCircuitBreakerLabel": p.hasCircuitBreakerLabel,
|
||||
"getCircuitBreakerExpression": p.getCircuitBreakerExpression,
|
||||
"hasLoadBalancerLabel": p.hasLoadBalancerLabel,
|
||||
"getLoadBalancerMethod": p.getLoadBalancerMethod,
|
||||
"hasMaxConnLabels": p.hasMaxConnLabels,
|
||||
"getMaxConnAmount": p.getMaxConnAmount,
|
||||
"getMaxConnExtractorFunc": p.getMaxConnExtractorFunc,
|
||||
"getSticky": p.getSticky,
|
||||
"getStickinessCookieName": p.getStickinessCookieName,
|
||||
"hasStickinessLabel": p.hasStickinessLabel,
|
||||
"getIsBackendLBSwarm": p.getIsBackendLBSwarm,
|
||||
"hasServices": p.hasServices,
|
||||
"getServiceNames": p.getServiceNames,
|
||||
"getServicePort": p.getServicePort,
|
||||
"getServiceWeight": p.getServiceWeight,
|
||||
"getServiceProtocol": p.getServiceProtocol,
|
||||
"getServiceEntryPoints": p.getServiceEntryPoints,
|
||||
"getServiceBasicAuth": p.getServiceBasicAuth,
|
||||
"getServiceFrontendRule": p.getServiceFrontendRule,
|
||||
"getServicePassHostHeader": p.getServicePassHostHeader,
|
||||
"getServicePriority": p.getServicePriority,
|
||||
"getServiceBackend": p.getServiceBackend,
|
||||
"getServiceRedirect": p.getServiceRedirect,
|
||||
"getWhitelistSourceRange": p.getWhitelistSourceRange,
|
||||
"getRequestHeaders": p.getRequestHeaders,
|
||||
"getResponseHeaders": p.getResponseHeaders,
|
||||
"hasRequestHeaders": p.hasRequestHeaders,
|
||||
"hasResponseHeaders": p.hasResponseHeaders,
|
||||
"getBackend": p.getBackend,
|
||||
"getIPAddress": p.getIPAddress,
|
||||
"getPort": p.getPort,
|
||||
"getWeight": p.getWeight,
|
||||
"getDomain": p.getDomain,
|
||||
"getProtocol": p.getProtocol,
|
||||
"getPassHostHeader": p.getPassHostHeader,
|
||||
"getPriority": p.getPriority,
|
||||
"getEntryPoints": p.getEntryPoints,
|
||||
"getBasicAuth": p.getBasicAuth,
|
||||
"getFrontendRule": p.getFrontendRule,
|
||||
"getRedirect": p.getRedirect,
|
||||
"hasCircuitBreakerLabel": p.hasCircuitBreakerLabel,
|
||||
"getCircuitBreakerExpression": p.getCircuitBreakerExpression,
|
||||
"hasLoadBalancerLabel": p.hasLoadBalancerLabel,
|
||||
"getLoadBalancerMethod": p.getLoadBalancerMethod,
|
||||
"hasMaxConnLabels": p.hasMaxConnLabels,
|
||||
"getMaxConnAmount": p.getMaxConnAmount,
|
||||
"getMaxConnExtractorFunc": p.getMaxConnExtractorFunc,
|
||||
"getSticky": p.getSticky,
|
||||
"getStickinessCookieName": p.getStickinessCookieName,
|
||||
"hasStickinessLabel": p.hasStickinessLabel,
|
||||
"getIsBackendLBSwarm": p.getIsBackendLBSwarm,
|
||||
"hasServices": p.hasServices,
|
||||
"getServiceNames": p.getServiceNames,
|
||||
"getServicePort": p.getServicePort,
|
||||
"getServiceWeight": p.getServiceWeight,
|
||||
"getServiceProtocol": p.getServiceProtocol,
|
||||
"getServiceEntryPoints": p.getServiceEntryPoints,
|
||||
"getServiceBasicAuth": p.getServiceBasicAuth,
|
||||
"getServiceFrontendRule": p.getServiceFrontendRule,
|
||||
"getServicePassHostHeader": p.getServicePassHostHeader,
|
||||
"getServicePriority": p.getServicePriority,
|
||||
"getServiceBackend": p.getServiceBackend,
|
||||
"getServiceRedirect": p.getServiceRedirect,
|
||||
"getWhitelistSourceRange": p.getWhitelistSourceRange,
|
||||
"hasRequestHeaders": p.hasLabel(types.LabelFrontendRequestHeader),
|
||||
"getRequestHeaders": p.getRequestHeaders,
|
||||
"hasResponseHeaders": p.hasLabel(types.LabelFrontendResponseHeader),
|
||||
"getResponseHeaders": p.getResponseHeaders,
|
||||
"hasAllowedHostsHeaders": p.hasLabel(types.LabelFrontendAllowedHosts),
|
||||
"getAllowedHostsHeaders": p.getAllowedHostsHeaders,
|
||||
"hasHostsProxyHeaders": p.hasLabel(types.LabelFrontendHostsProxyHeaders),
|
||||
"getHostsProxyHeaders": p.getHostsProxyHeaders,
|
||||
"hasSSLRedirectHeaders": p.hasLabel(types.LabelFrontendSSLRedirect),
|
||||
"getSSLRedirectHeaders": p.getSSLRedirectHeaders,
|
||||
"hasSSLTemporaryRedirectHeaders": p.hasLabel(types.LabelFrontendSSLTemporaryRedirect),
|
||||
"getSSLTemporaryRedirectHeaders": p.getSSLTemporaryRedirectHeaders,
|
||||
"hasSSLHostHeaders": p.hasLabel(types.LabelFrontendSSLHost),
|
||||
"getSSLHostHeaders": p.getSSLHostHeaders,
|
||||
"hasSSLProxyHeaders": p.hasLabel(types.LabelFrontendSSLProxyHeaders),
|
||||
"getSSLProxyHeaders": p.getSSLProxyHeaders,
|
||||
"hasSTSSecondsHeaders": p.hasLabel(types.LabelFrontendSTSSeconds),
|
||||
"getSTSSecondsHeaders": p.getSTSSecondsHeaders,
|
||||
"hasSTSIncludeSubdomainsHeaders": p.hasLabel(types.LabelFrontendSTSIncludeSubdomains),
|
||||
"getSTSIncludeSubdomainsHeaders": p.getSTSIncludeSubdomainsHeaders,
|
||||
"hasSTSPreloadHeaders": p.hasLabel(types.LabelFrontendSTSPreload),
|
||||
"getSTSPreloadHeaders": p.getSTSPreloadHeaders,
|
||||
"hasForceSTSHeaderHeaders": p.hasLabel(types.LabelFrontendForceSTSHeader),
|
||||
"getForceSTSHeaderHeaders": p.getForceSTSHeaderHeaders,
|
||||
"hasFrameDenyHeaders": p.hasLabel(types.LabelFrontendFrameDeny),
|
||||
"getFrameDenyHeaders": p.getFrameDenyHeaders,
|
||||
"hasCustomFrameOptionsValueHeaders": p.hasLabel(types.LabelFrontendCustomFrameOptionsValue),
|
||||
"getCustomFrameOptionsValueHeaders": p.getCustomFrameOptionsValueHeaders,
|
||||
"hasContentTypeNosniffHeaders": p.hasLabel(types.LabelFrontendContentTypeNosniff),
|
||||
"getContentTypeNosniffHeaders": p.getContentTypeNosniffHeaders,
|
||||
"hasBrowserXSSFilterHeaders": p.hasLabel(types.LabelFrontendBrowserXSSFilter),
|
||||
"getBrowserXSSFilterHeaders": p.getBrowserXSSFilterHeaders,
|
||||
"hasContentSecurityPolicyHeaders": p.hasLabel(types.LabelFrontendContentSecurityPolicy),
|
||||
"getContentSecurityPolicyHeaders": p.getContentSecurityPolicyHeaders,
|
||||
"hasPublicKeyHeaders": p.hasLabel(types.LabelFrontendPublicKey),
|
||||
"getPublicKeyHeaders": p.getPublicKeyHeaders,
|
||||
"hasReferrerPolicyHeaders": p.hasLabel(types.LabelFrontendReferrerPolicy),
|
||||
"getReferrerPolicyHeaders": p.getReferrerPolicyHeaders,
|
||||
"hasIsDevelopmentHeaders": p.hasLabel(types.LabelFrontendIsDevelopment),
|
||||
"getIsDevelopmentHeaders": p.getIsDevelopmentHeaders,
|
||||
}
|
||||
// filter containers
|
||||
filteredContainers := fun.Filter(func(container dockerData) bool {
|
||||
|
@ -807,14 +843,11 @@ func (p *Provider) getBasicAuth(container dockerData) []string {
|
|||
return []string{}
|
||||
}
|
||||
|
||||
func (p *Provider) hasRequestHeaders(container dockerData) bool {
|
||||
label, err := getLabel(container, types.LabelFrontendRequestHeader)
|
||||
return err == nil && len(label) > 0
|
||||
}
|
||||
|
||||
func (p *Provider) hasResponseHeaders(container dockerData) bool {
|
||||
label, err := getLabel(container, types.LabelFrontendResponseHeader)
|
||||
return err == nil && len(label) > 0
|
||||
func (p *Provider) hasLabel(label string) func(container dockerData) bool {
|
||||
return func(container dockerData) bool {
|
||||
label, err := getLabel(container, label)
|
||||
return err == nil && len(label) > 0
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Provider) getRequestHeaders(container dockerData) map[string]string {
|
||||
|
@ -843,6 +876,124 @@ func parseCustomHeaders(container dockerData, containerType string) map[string]s
|
|||
return customHeaders
|
||||
}
|
||||
|
||||
func (p *Provider) getAllowedHostsHeaders(container dockerData) []string {
|
||||
return getSliceStringHeaders(container, types.LabelFrontendAllowedHosts)
|
||||
}
|
||||
|
||||
func (p *Provider) getHostsProxyHeaders(container dockerData) []string {
|
||||
return getSliceStringHeaders(container, types.LabelFrontendHostsProxyHeaders)
|
||||
}
|
||||
|
||||
func (p *Provider) getSSLRedirectHeaders(container dockerData) bool {
|
||||
return getBoolHeader(container, types.LabelFrontendSSLRedirect)
|
||||
}
|
||||
|
||||
func (p *Provider) getSSLTemporaryRedirectHeaders(container dockerData) bool {
|
||||
return getBoolHeader(container, types.LabelFrontendSSLTemporaryRedirect)
|
||||
}
|
||||
|
||||
func (p *Provider) getSSLHostHeaders(container dockerData) string {
|
||||
label, _ := getLabel(container, types.LabelFrontendSSLHost)
|
||||
return label
|
||||
}
|
||||
|
||||
func (p *Provider) getSSLProxyHeaders(container dockerData) map[string]string {
|
||||
ProxyHeaders := make(map[string]string)
|
||||
if label, err := getLabel(container, types.LabelFrontendSSLProxyHeaders); err == nil {
|
||||
for _, headers := range strings.Split(label, ",") {
|
||||
pair := strings.Split(headers, ":")
|
||||
if len(pair) != 2 {
|
||||
log.Warnf("Could not load header %v, skipping...", pair)
|
||||
} else {
|
||||
ProxyHeaders[pair[0]] = pair[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(ProxyHeaders) == 0 {
|
||||
log.Errorf("Could not load any SSL Proxy Headers")
|
||||
}
|
||||
return ProxyHeaders
|
||||
}
|
||||
|
||||
func (p *Provider) getSTSSecondsHeaders(container dockerData) int64 {
|
||||
label, _ := getLabel(container, types.LabelFrontendSTSSeconds)
|
||||
i, err := strconv.ParseInt(label, 10, 64)
|
||||
if err == nil && i > 0 {
|
||||
return i
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *Provider) getSTSIncludeSubdomainsHeaders(container dockerData) bool {
|
||||
return getBoolHeader(container, types.LabelFrontendSTSIncludeSubdomains)
|
||||
}
|
||||
|
||||
func (p *Provider) getSTSPreloadHeaders(container dockerData) bool {
|
||||
return getBoolHeader(container, types.LabelFrontendSTSPreload)
|
||||
}
|
||||
|
||||
func (p *Provider) getForceSTSHeaderHeaders(container dockerData) bool {
|
||||
return getBoolHeader(container, types.LabelFrontendForceSTSHeader)
|
||||
}
|
||||
|
||||
func (p *Provider) getFrameDenyHeaders(container dockerData) bool {
|
||||
return getBoolHeader(container, types.LabelFrontendFrameDeny)
|
||||
}
|
||||
|
||||
func (p *Provider) getCustomFrameOptionsValueHeaders(container dockerData) string {
|
||||
label, _ := getLabel(container, types.LabelFrontendCustomFrameOptionsValue)
|
||||
return label
|
||||
}
|
||||
|
||||
func (p *Provider) getContentTypeNosniffHeaders(container dockerData) bool {
|
||||
return getBoolHeader(container, types.LabelFrontendContentTypeNosniff)
|
||||
}
|
||||
|
||||
func (p *Provider) getBrowserXSSFilterHeaders(container dockerData) bool {
|
||||
return getBoolHeader(container, types.LabelFrontendBrowserXSSFilter)
|
||||
}
|
||||
|
||||
func (p *Provider) getContentSecurityPolicyHeaders(container dockerData) string {
|
||||
label, _ := getLabel(container, types.LabelFrontendContentSecurityPolicy)
|
||||
return label
|
||||
}
|
||||
|
||||
func (p *Provider) getPublicKeyHeaders(container dockerData) string {
|
||||
label, _ := getLabel(container, types.LabelFrontendPublicKey)
|
||||
return label
|
||||
}
|
||||
|
||||
func (p *Provider) getReferrerPolicyHeaders(container dockerData) string {
|
||||
label, _ := getLabel(container, types.LabelFrontendReferrerPolicy)
|
||||
return label
|
||||
}
|
||||
|
||||
func (p *Provider) getIsDevelopmentHeaders(container dockerData) bool {
|
||||
return getBoolHeader(container, types.LabelFrontendIsDevelopment)
|
||||
}
|
||||
|
||||
func getSliceStringHeaders(container dockerData, containerType string) []string {
|
||||
value := []string{}
|
||||
if label, err := getLabel(container, containerType); err == nil {
|
||||
for _, sublabels := range strings.Split(label, ",") {
|
||||
if len(sublabels) == 0 {
|
||||
log.Warnf("Could not load header %v, skipping", sublabels)
|
||||
} else {
|
||||
value = append(value, sublabels)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(value) == 0 {
|
||||
log.Errorf("Could not load %v headers", containerType)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func getBoolHeader(container dockerData, containerType string) bool {
|
||||
label, err := getLabel(container, containerType)
|
||||
return err == nil && len(label) > 0 && strings.EqualFold(strings.TrimSpace(label), "true")
|
||||
}
|
||||
|
||||
func (p *Provider) getRedirect(container dockerData) string {
|
||||
if entryPointredirect, err := getLabel(container, types.LabelFrontendRedirect); err == nil {
|
||||
return entryPointredirect
|
||||
|
|
|
@ -80,6 +80,52 @@
|
|||
basicAuth = [{{range getBasicAuth $container}}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
[frontends."frontend-{{$frontend}}".headers]
|
||||
{{if hasSSLRedirectHeaders $container}}
|
||||
SSLRedirect = {{getSSLRedirectHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasSSLTemporaryRedirectHeaders $container}}
|
||||
SSLTemporaryRedirect = {{getSSLTemporaryRedirectHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasSSLHostHeaders $container}}
|
||||
SSLHost = {{getSSLHostHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasSTSSecondsHeaders $container}}
|
||||
STSSeconds = {{getSTSSecondsHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasSTSIncludeSubdomainsHeaders $container}}
|
||||
STSIncludeSubdomains = {{getSTSIncludeSubdomainsHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasSTSPreloadHeaders $container}}
|
||||
STSPreload = {{getSTSPreloadHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasForceSTSHeaderHeaders $container}}
|
||||
ForceSTSHeader = {{getForceSTSHeaderHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasFrameDenyHeaders $container}}
|
||||
FrameDeny = {{getFrameDenyHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasCustomFrameOptionsValueHeaders $container}}
|
||||
CustomFrameOptionsValue = {{getCustomFrameOptionsValueHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasContentTypeNosniffHeaders $container}}
|
||||
ContentTypeNosniff = {{getContentTypeNosniffHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasBrowserXSSFilterHeaders $container}}
|
||||
BrowserXSSFilter = {{getBrowserXSSFilterHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasContentSecurityPolicyHeaders $container}}
|
||||
ContentSecurityPolicy = {{getContentSecurityPolicyHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasPublicKeyHeaders $container}}
|
||||
PublicKey = {{getPublicKeyHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasReferrerPolicyHeaders $container}}
|
||||
ReferrerPolicy = {{getReferrerPolicyHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasIsDevelopmentHeaders $container}}
|
||||
IsDevelopment = {{getIsDevelopmentHeaders $container}}
|
||||
{{end}}
|
||||
{{if hasRequestHeaders $container}}
|
||||
[frontends."frontend-{{$frontend}}".headers.customrequestheaders]
|
||||
{{range $k, $v := getRequestHeaders $container}}
|
||||
|
@ -91,6 +137,24 @@
|
|||
{{range $k, $v := getResponseHeaders $container}}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if hasAllowedHostsHeaders $container}}
|
||||
[frontends."frontend-{{$frontend}}".headers.AllowedHosts]
|
||||
{{range getAllowedHostsHeaders $container}}
|
||||
"{{.}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if hasHostsProxyHeaders $container}}
|
||||
[frontends."frontend-{{$frontend}}".headers.HostsProxyHeaders]
|
||||
{{range getHostsProxyHeaders $container}}
|
||||
"{{.}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if hasSSLProxyHeaders $container}}
|
||||
[frontends."frontend-{{$frontend}}".headers.SSLProxyHeaders]
|
||||
{{range $k, $v := getSSLProxyHeaders $container}}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
[frontends."frontend-{{$frontend}}".routes."route-frontend-{{$frontend}}"]
|
||||
rule = "{{getFrontendRule $container}}"
|
||||
|
|
|
@ -16,6 +16,24 @@ const (
|
|||
LabelFrontendEntryPoints = LabelPrefix + "frontend.entryPoints"
|
||||
LabelFrontendRequestHeader = LabelPrefix + "frontend.headers.customrequestheaders"
|
||||
LabelFrontendResponseHeader = LabelPrefix + "frontend.headers.customresponseheaders"
|
||||
LabelFrontendAllowedHosts = LabelPrefix + "frontend.headers.allowedHosts"
|
||||
LabelFrontendHostsProxyHeaders = LabelPrefix + "frontend.headers.hostsProxyHeaders"
|
||||
LabelFrontendSSLRedirect = LabelPrefix + "frontend.headers.SSLRedirect"
|
||||
LabelFrontendSSLTemporaryRedirect = LabelPrefix + "frontend.headers.SSLTemporaryRedirect"
|
||||
LabelFrontendSSLHost = LabelPrefix + "frontend.headers.SSLHost"
|
||||
LabelFrontendSSLProxyHeaders = LabelPrefix + "frontend.headers.SSLProxyHeaders"
|
||||
LabelFrontendSTSSeconds = LabelPrefix + "frontend.headers.STSSeconds"
|
||||
LabelFrontendSTSIncludeSubdomains = LabelPrefix + "frontend.headers.STSIncludeSubdomains"
|
||||
LabelFrontendSTSPreload = LabelPrefix + "frontend.headers.STSPreload"
|
||||
LabelFrontendForceSTSHeader = LabelPrefix + "frontend.headers.forceSTSHeader"
|
||||
LabelFrontendFrameDeny = LabelPrefix + "frontend.headers.frameDeny"
|
||||
LabelFrontendCustomFrameOptionsValue = LabelPrefix + "frontend.headers.customFrameOptionsValue"
|
||||
LabelFrontendContentTypeNosniff = LabelPrefix + "frontend.headers.contentTypeNosniff"
|
||||
LabelFrontendBrowserXSSFilter = LabelPrefix + "frontend.headers.browserXSSFilter"
|
||||
LabelFrontendContentSecurityPolicy = LabelPrefix + "frontend.headers.contentSecurityPolicy"
|
||||
LabelFrontendPublicKey = LabelPrefix + "frontend.headers.publicKey"
|
||||
LabelFrontendReferrerPolicy = LabelPrefix + "frontend.headers.referrerPolicy"
|
||||
LabelFrontendIsDevelopment = LabelPrefix + "frontend.headers.isDevelopment"
|
||||
LabelFrontendPassHostHeader = LabelPrefix + "frontend.passHostHeader"
|
||||
LabelFrontendPassTLSCert = LabelPrefix + "frontend.passTLSCert"
|
||||
LabelFrontendPriority = LabelPrefix + "frontend.priority"
|
||||
|
|
Loading…
Reference in a new issue