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}}
|
basicAuth = [{{range getBasicAuth $container}}
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{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}}
|
{{if hasRequestHeaders $container}}
|
||||||
[frontends."frontend-{{$frontend}}".headers.customrequestheaders]
|
[frontends."frontend-{{$frontend}}".headers.customrequestheaders]
|
||||||
{{range $k, $v := getRequestHeaders $container}}
|
{{range $k, $v := getRequestHeaders $container}}
|
||||||
|
@ -216,6 +262,24 @@ var _templatesDockerTmpl = []byte(`{{$backendServers := .Servers}}
|
||||||
{{range $k, $v := getResponseHeaders $container}}
|
{{range $k, $v := getResponseHeaders $container}}
|
||||||
{{$k}} = "{{$v}}"
|
{{$k}} = "{{$v}}"
|
||||||
{{end}}
|
{{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}}
|
{{end}}
|
||||||
[frontends."frontend-{{$frontend}}".routes."route-frontend-{{$frontend}}"]
|
[frontends."frontend-{{$frontend}}".routes."route-frontend-{{$frontend}}"]
|
||||||
rule = "{{getFrontendRule $container}}"
|
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.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.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.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.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) |
|
| `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
|
### On Service
|
||||||
|
|
||||||
Services labels can be used for overriding default behaviour
|
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 {
|
func (p *Provider) loadDockerConfig(containersInspected []dockerData) *types.Configuration {
|
||||||
var DockerFuncMap = template.FuncMap{
|
var DockerFuncMap = template.FuncMap{
|
||||||
"getBackend": p.getBackend,
|
"getBackend": p.getBackend,
|
||||||
"getIPAddress": p.getIPAddress,
|
"getIPAddress": p.getIPAddress,
|
||||||
"getPort": p.getPort,
|
"getPort": p.getPort,
|
||||||
"getWeight": p.getWeight,
|
"getWeight": p.getWeight,
|
||||||
"getDomain": p.getDomain,
|
"getDomain": p.getDomain,
|
||||||
"getProtocol": p.getProtocol,
|
"getProtocol": p.getProtocol,
|
||||||
"getPassHostHeader": p.getPassHostHeader,
|
"getPassHostHeader": p.getPassHostHeader,
|
||||||
"getPriority": p.getPriority,
|
"getPriority": p.getPriority,
|
||||||
"getEntryPoints": p.getEntryPoints,
|
"getEntryPoints": p.getEntryPoints,
|
||||||
"getBasicAuth": p.getBasicAuth,
|
"getBasicAuth": p.getBasicAuth,
|
||||||
"getFrontendRule": p.getFrontendRule,
|
"getFrontendRule": p.getFrontendRule,
|
||||||
"getRedirect": p.getRedirect,
|
"getRedirect": p.getRedirect,
|
||||||
"hasCircuitBreakerLabel": p.hasCircuitBreakerLabel,
|
"hasCircuitBreakerLabel": p.hasCircuitBreakerLabel,
|
||||||
"getCircuitBreakerExpression": p.getCircuitBreakerExpression,
|
"getCircuitBreakerExpression": p.getCircuitBreakerExpression,
|
||||||
"hasLoadBalancerLabel": p.hasLoadBalancerLabel,
|
"hasLoadBalancerLabel": p.hasLoadBalancerLabel,
|
||||||
"getLoadBalancerMethod": p.getLoadBalancerMethod,
|
"getLoadBalancerMethod": p.getLoadBalancerMethod,
|
||||||
"hasMaxConnLabels": p.hasMaxConnLabels,
|
"hasMaxConnLabels": p.hasMaxConnLabels,
|
||||||
"getMaxConnAmount": p.getMaxConnAmount,
|
"getMaxConnAmount": p.getMaxConnAmount,
|
||||||
"getMaxConnExtractorFunc": p.getMaxConnExtractorFunc,
|
"getMaxConnExtractorFunc": p.getMaxConnExtractorFunc,
|
||||||
"getSticky": p.getSticky,
|
"getSticky": p.getSticky,
|
||||||
"getStickinessCookieName": p.getStickinessCookieName,
|
"getStickinessCookieName": p.getStickinessCookieName,
|
||||||
"hasStickinessLabel": p.hasStickinessLabel,
|
"hasStickinessLabel": p.hasStickinessLabel,
|
||||||
"getIsBackendLBSwarm": p.getIsBackendLBSwarm,
|
"getIsBackendLBSwarm": p.getIsBackendLBSwarm,
|
||||||
"hasServices": p.hasServices,
|
"hasServices": p.hasServices,
|
||||||
"getServiceNames": p.getServiceNames,
|
"getServiceNames": p.getServiceNames,
|
||||||
"getServicePort": p.getServicePort,
|
"getServicePort": p.getServicePort,
|
||||||
"getServiceWeight": p.getServiceWeight,
|
"getServiceWeight": p.getServiceWeight,
|
||||||
"getServiceProtocol": p.getServiceProtocol,
|
"getServiceProtocol": p.getServiceProtocol,
|
||||||
"getServiceEntryPoints": p.getServiceEntryPoints,
|
"getServiceEntryPoints": p.getServiceEntryPoints,
|
||||||
"getServiceBasicAuth": p.getServiceBasicAuth,
|
"getServiceBasicAuth": p.getServiceBasicAuth,
|
||||||
"getServiceFrontendRule": p.getServiceFrontendRule,
|
"getServiceFrontendRule": p.getServiceFrontendRule,
|
||||||
"getServicePassHostHeader": p.getServicePassHostHeader,
|
"getServicePassHostHeader": p.getServicePassHostHeader,
|
||||||
"getServicePriority": p.getServicePriority,
|
"getServicePriority": p.getServicePriority,
|
||||||
"getServiceBackend": p.getServiceBackend,
|
"getServiceBackend": p.getServiceBackend,
|
||||||
"getServiceRedirect": p.getServiceRedirect,
|
"getServiceRedirect": p.getServiceRedirect,
|
||||||
"getWhitelistSourceRange": p.getWhitelistSourceRange,
|
"getWhitelistSourceRange": p.getWhitelistSourceRange,
|
||||||
"getRequestHeaders": p.getRequestHeaders,
|
"hasRequestHeaders": p.hasLabel(types.LabelFrontendRequestHeader),
|
||||||
"getResponseHeaders": p.getResponseHeaders,
|
"getRequestHeaders": p.getRequestHeaders,
|
||||||
"hasRequestHeaders": p.hasRequestHeaders,
|
"hasResponseHeaders": p.hasLabel(types.LabelFrontendResponseHeader),
|
||||||
"hasResponseHeaders": p.hasResponseHeaders,
|
"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
|
// filter containers
|
||||||
filteredContainers := fun.Filter(func(container dockerData) bool {
|
filteredContainers := fun.Filter(func(container dockerData) bool {
|
||||||
|
@ -807,14 +843,11 @@ func (p *Provider) getBasicAuth(container dockerData) []string {
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) hasRequestHeaders(container dockerData) bool {
|
func (p *Provider) hasLabel(label string) func(container dockerData) bool {
|
||||||
label, err := getLabel(container, types.LabelFrontendRequestHeader)
|
return func(container dockerData) bool {
|
||||||
return err == nil && len(label) > 0
|
label, err := getLabel(container, label)
|
||||||
}
|
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) getRequestHeaders(container dockerData) map[string]string {
|
func (p *Provider) getRequestHeaders(container dockerData) map[string]string {
|
||||||
|
@ -843,6 +876,124 @@ func parseCustomHeaders(container dockerData, containerType string) map[string]s
|
||||||
return customHeaders
|
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 {
|
func (p *Provider) getRedirect(container dockerData) string {
|
||||||
if entryPointredirect, err := getLabel(container, types.LabelFrontendRedirect); err == nil {
|
if entryPointredirect, err := getLabel(container, types.LabelFrontendRedirect); err == nil {
|
||||||
return entryPointredirect
|
return entryPointredirect
|
||||||
|
|
|
@ -80,6 +80,52 @@
|
||||||
basicAuth = [{{range getBasicAuth $container}}
|
basicAuth = [{{range getBasicAuth $container}}
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{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}}
|
{{if hasRequestHeaders $container}}
|
||||||
[frontends."frontend-{{$frontend}}".headers.customrequestheaders]
|
[frontends."frontend-{{$frontend}}".headers.customrequestheaders]
|
||||||
{{range $k, $v := getRequestHeaders $container}}
|
{{range $k, $v := getRequestHeaders $container}}
|
||||||
|
@ -91,6 +137,24 @@
|
||||||
{{range $k, $v := getResponseHeaders $container}}
|
{{range $k, $v := getResponseHeaders $container}}
|
||||||
{{$k}} = "{{$v}}"
|
{{$k}} = "{{$v}}"
|
||||||
{{end}}
|
{{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}}
|
{{end}}
|
||||||
[frontends."frontend-{{$frontend}}".routes."route-frontend-{{$frontend}}"]
|
[frontends."frontend-{{$frontend}}".routes."route-frontend-{{$frontend}}"]
|
||||||
rule = "{{getFrontendRule $container}}"
|
rule = "{{getFrontendRule $container}}"
|
||||||
|
|
|
@ -16,6 +16,24 @@ const (
|
||||||
LabelFrontendEntryPoints = LabelPrefix + "frontend.entryPoints"
|
LabelFrontendEntryPoints = LabelPrefix + "frontend.entryPoints"
|
||||||
LabelFrontendRequestHeader = LabelPrefix + "frontend.headers.customrequestheaders"
|
LabelFrontendRequestHeader = LabelPrefix + "frontend.headers.customrequestheaders"
|
||||||
LabelFrontendResponseHeader = LabelPrefix + "frontend.headers.customresponseheaders"
|
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"
|
LabelFrontendPassHostHeader = LabelPrefix + "frontend.passHostHeader"
|
||||||
LabelFrontendPassTLSCert = LabelPrefix + "frontend.passTLSCert"
|
LabelFrontendPassTLSCert = LabelPrefix + "frontend.passTLSCert"
|
||||||
LabelFrontendPriority = LabelPrefix + "frontend.priority"
|
LabelFrontendPriority = LabelPrefix + "frontend.priority"
|
||||||
|
|
Loading…
Reference in a new issue