Kubernetes security header annotations
This commit is contained in:
parent
ad07a6ab2b
commit
4cb6241e93
5 changed files with 251 additions and 60 deletions
|
@ -421,6 +421,52 @@ var _templatesKubernetesTmpl = []byte(`[backends]{{range $backendName, $backend
|
||||||
whitelistSourceRange = [{{range $frontend.WhitelistSourceRange}}
|
whitelistSourceRange = [{{range $frontend.WhitelistSourceRange}}
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{end}}]
|
||||||
|
[frontends."{{$frontendName}}".headers]
|
||||||
|
SSLRedirect = {{$frontend.Headers.SSLRedirect}}
|
||||||
|
SSLTemporaryRedirect = {{$frontend.Headers.SSLTemporaryRedirect}}
|
||||||
|
SSLHost = "{{$frontend.Headers.SSLHost}}"
|
||||||
|
STSSeconds = {{$frontend.Headers.STSSeconds}}
|
||||||
|
STSIncludeSubdomains = {{$frontend.Headers.STSIncludeSubdomains}}
|
||||||
|
STSPreload = {{$frontend.Headers.STSPreload}}
|
||||||
|
ForceSTSHeader = {{$frontend.Headers.ForceSTSHeader}}
|
||||||
|
FrameDeny = {{$frontend.Headers.FrameDeny}}
|
||||||
|
CustomFrameOptionsValue = "{{$frontend.Headers.CustomFrameOptionsValue}}"
|
||||||
|
ContentTypeNosniff = {{$frontend.Headers.ContentTypeNosniff}}
|
||||||
|
BrowserXSSFilter = {{$frontend.Headers.BrowserXSSFilter}}
|
||||||
|
ContentSecurityPolicy = "{{$frontend.Headers.ContentSecurityPolicy}}"
|
||||||
|
PublicKey = "{{$frontend.Headers.PublicKey}}"
|
||||||
|
ReferrerPolicy = "{{$frontend.Headers.ReferrerPolicy}}"
|
||||||
|
IsDevelopment = {{$frontend.Headers.IsDevelopment}}
|
||||||
|
{{if $frontend.Headers.CustomRequestHeaders}}
|
||||||
|
[frontends."{{$frontendName}}".headers.customrequestheaders]
|
||||||
|
{{range $k, $v := $frontend.Headers.CustomRequestHeaders}}
|
||||||
|
{{$k}} = "{{$v}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{if $frontend.Headers.CustomResponseHeaders}}
|
||||||
|
[frontends."{{$frontendName}}".headers.customresponseheaders]
|
||||||
|
{{range $k, $v := $frontend.Headers.CustomResponseHeaders}}
|
||||||
|
{{$k}} = "{{$v}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{if $frontend.Headers.AllowedHosts}}
|
||||||
|
[frontends."{{$frontendName}}".headers.AllowedHosts]
|
||||||
|
{{range $frontend.Headers.AllowedHosts}}
|
||||||
|
"{{.}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{if $frontend.Headers.HostsProxyHeaders}}
|
||||||
|
[frontends."{{$frontendName}}".headers.HostsProxyHeaders]
|
||||||
|
{{range $frontend.Headers.HostsProxyHeaders}}
|
||||||
|
"{{.}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{if $frontend.Headers.SSLProxyHeaders}}
|
||||||
|
[frontends."{{$frontendName}}".headers.SSLProxyHeaders]
|
||||||
|
{{range $k, $v := $frontend.Headers.SSLProxyHeaders}}
|
||||||
|
{{$k}} = "{{$v}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
{{range $routeName, $route := $frontend.Routes}}
|
{{range $routeName, $route := $frontend.Routes}}
|
||||||
[frontends."{{$frontendName}}".routes."{{$routeName}}"]
|
[frontends."{{$frontendName}}".routes."{{$routeName}}"]
|
||||||
rule = "{{$route.Rule}}"
|
rule = "{{$route.Rule}}"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Træfik can be configured to use Kubernetes Ingress as a backend configuration.
|
Træfik can be configured to use Kubernetes Ingress as a backend configuration.
|
||||||
|
|
||||||
See also [Kubernetes user guide](/user-guide/kubernetes).
|
See also [Kubernetes user guide](/user-guide/kubernetes).
|
||||||
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
@ -102,7 +102,7 @@ Annotations can be used on containers to override default behaviour for the whol
|
||||||
Override the default frontend rule type. Default: `PathPrefix`.
|
Override the default frontend rule type. Default: `PathPrefix`.
|
||||||
- `traefik.frontend.priority: "3"`
|
- `traefik.frontend.priority: "3"`
|
||||||
Override the default frontend rule priority.
|
Override the default frontend rule priority.
|
||||||
- `traefik.frontend.redirect: https`:
|
- `traefik.frontend.redirect: https`:
|
||||||
Enables Redirect to another entryPoint for that frontend (e.g. HTTPS).
|
Enables Redirect to another entryPoint for that frontend (e.g. HTTPS).
|
||||||
- `traefik.frontend.entryPoints: http,https`
|
- `traefik.frontend.entryPoints: http,https`
|
||||||
Override the default frontend endpoints.
|
Override the default frontend endpoints.
|
||||||
|
@ -132,6 +132,32 @@ As known from nginx when used as Kubernetes Ingress Controller, a list of IP-Ran
|
||||||
An unset or empty list allows all Source-IPs 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.
|
If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access.
|
||||||
|
|
||||||
|
#### Security annotations
|
||||||
|
|
||||||
|
The following security annotations can be applied to the ingress object to add security features:
|
||||||
|
|
||||||
|
| Annotation | Description |
|
||||||
|
|----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `ingress.kubernetes.io/allowed-hosts:EXPR` | Provides a list of allowed hosts that requests will be processed. Format: `Host1,Host2` |
|
||||||
|
| `ingress.kubernetes.io/custom-request-headers:EXPR ` | Provides the container with custom request headers that will be appended to each request forwarded to the container. Format: `HEADER:value,HEADER2:value2` |
|
||||||
|
| `ingress.kubernetes.io/custom-response-headers:EXPR` | Appends the headers to each response returned by the container, before forwarding the response to the client. Format: `HEADER:value,HEADER2:value2` |
|
||||||
|
| `ingress.kubernetes.io/proxy-headers:EXPR ` | Provides a list of headers that the proxied hostname may be stored. Format: `HEADER1,HEADER2` |
|
||||||
|
| `ingress.kubernetes.io/ssl-redirect:true` | Forces the frontend to redirect to SSL if a non-SSL request is sent. |
|
||||||
|
| `ingress.kubernetes.io/ssl-temporary-redirect:true` | Forces the frontend to redirect to SSL if a non-SSL request is sent, but by sending a 302 instead of a 301. |
|
||||||
|
| `ingress.kubernetes.io/ssl-host:HOST` | This setting configures the hostname that redirects will be based on. Default is "", which is the same host as the request. |
|
||||||
|
| `ingress.kubernetes.io/ssl-proxy-headers:EXPR` | Header combinations that would signify a proper SSL Request (Such as `X-Forwarded-For:https`). Format: `HEADER:value,HEADER2:value2` |
|
||||||
|
| `ingress.kubernetes.io/hsts-max-age:315360000` | Sets the max-age of the HSTS header. |
|
||||||
|
| `ngress.kubernetes.io/hsts-include-subdomains:true` | Adds the IncludeSubdomains section of the STS header. |
|
||||||
|
| `ingress.kubernetes.io/hsts-preload:true` | Adds the preload flag to the HSTS header. |
|
||||||
|
| `ingress.kubernetes.io/force-hsts:false` | Adds the STS header to non-SSL requests. |
|
||||||
|
| `ingress.kubernetes.io/frame-deny:false` | Adds the `X-Frame-Options` header with the value of `DENY`. |
|
||||||
|
| `ingress.kubernetes.io/custom-frame-options-value:VALUE` | Overrides the `X-Frame-Options` header with the custom value. |
|
||||||
|
| `ingress.kubernetes.io/content-type-nosniff:true` | Adds the `X-Content-Type-Options` header with the value `nosniff`. |
|
||||||
|
| `ingress.kubernetes.io/browser-xss-filter:true` | Adds the X-XSS-Protection header with the value `1; mode=block`. |
|
||||||
|
| `ingress.kubernetes.io/content-security-policy:VALUE` | Adds CSP Header with the custom value. |
|
||||||
|
| `ingress.kubernetes.io/public-key:VALUE` | Adds pinned HTST public key header. |
|
||||||
|
| `ingress.kubernetes.io/referrer-policy:VALUE` | Adds referrer policy header. |
|
||||||
|
| `ingress.kubernetes.io/is-development:false` | This will cause the `AllowedHosts`, `SSLRedirect`, and `STSSeconds`/`STSIncludeSubdomains` options to be ignored during development.<br>When deploying to production, be sure to set this to false. |
|
||||||
|
|
||||||
### Authentication
|
### Authentication
|
||||||
|
|
||||||
|
|
62
provider/kubernetes/annotations_parser.go
Normal file
62
provider/kubernetes/annotations_parser.go
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
package kubernetes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containous/traefik/log"
|
||||||
|
"github.com/containous/traefik/provider"
|
||||||
|
"github.com/containous/traefik/types"
|
||||||
|
"k8s.io/client-go/pkg/apis/extensions/v1beta1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getBoolAnnotation(meta *v1beta1.Ingress, name string, defaultValue bool) bool {
|
||||||
|
annotationValue := defaultValue
|
||||||
|
annotationStringValue, ok := meta.Annotations[name]
|
||||||
|
switch {
|
||||||
|
case !ok:
|
||||||
|
// No op.
|
||||||
|
case annotationStringValue == "false":
|
||||||
|
annotationValue = false
|
||||||
|
case annotationStringValue == "true":
|
||||||
|
annotationValue = true
|
||||||
|
default:
|
||||||
|
log.Warnf("Unknown value '%s' for %s, falling back to %s", name, types.LabelFrontendPassTLSCert, defaultValue)
|
||||||
|
}
|
||||||
|
return annotationValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStringAnnotation(meta *v1beta1.Ingress, name string) string {
|
||||||
|
value := meta.Annotations[name]
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSliceAnnotation(meta *v1beta1.Ingress, name string) []string {
|
||||||
|
var value []string
|
||||||
|
if annotation, ok := meta.Annotations[name]; ok && annotation != "" {
|
||||||
|
value = provider.SplitAndTrimString(annotation)
|
||||||
|
}
|
||||||
|
if len(value) == 0 {
|
||||||
|
log.Debugf("Could not load %v annotation, skipping...", name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMapAnnotation(meta *v1beta1.Ingress, name string) map[string]string {
|
||||||
|
value := make(map[string]string)
|
||||||
|
if annotation := meta.Annotations[name]; annotation != "" {
|
||||||
|
for _, v := range strings.Split(annotation, ",") {
|
||||||
|
pair := strings.Split(v, ":")
|
||||||
|
if len(pair) != 2 {
|
||||||
|
log.Debugf("Could not load annotation (%v) with value: %v, skipping...", name, pair)
|
||||||
|
} else {
|
||||||
|
value[pair[0]] = pair[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(value) == 0 {
|
||||||
|
log.Debugf("Could not load %v annotation, skipping...", name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
|
@ -30,12 +30,32 @@ const (
|
||||||
ruleTypePathPrefix = "PathPrefix"
|
ruleTypePathPrefix = "PathPrefix"
|
||||||
ruleTypeReplacePath = "ReplacePath"
|
ruleTypeReplacePath = "ReplacePath"
|
||||||
|
|
||||||
annotationKubernetesIngressClass = "kubernetes.io/ingress.class"
|
annotationKubernetesIngressClass = "kubernetes.io/ingress.class"
|
||||||
annotationKubernetesAuthRealm = "ingress.kubernetes.io/auth-realm"
|
annotationKubernetesAuthRealm = "ingress.kubernetes.io/auth-realm"
|
||||||
annotationKubernetesAuthType = "ingress.kubernetes.io/auth-type"
|
annotationKubernetesAuthType = "ingress.kubernetes.io/auth-type"
|
||||||
annotationKubernetesAuthSecret = "ingress.kubernetes.io/auth-secret"
|
annotationKubernetesAuthSecret = "ingress.kubernetes.io/auth-secret"
|
||||||
annotationKubernetesRewriteTarget = "ingress.kubernetes.io/rewrite-target"
|
annotationKubernetesRewriteTarget = "ingress.kubernetes.io/rewrite-target"
|
||||||
annotationKubernetesWhitelistSourceRange = "ingress.kubernetes.io/whitelist-source-range"
|
annotationKubernetesWhitelistSourceRange = "ingress.kubernetes.io/whitelist-source-range"
|
||||||
|
annotationKubernetesSSLRedirect = "ingress.kubernetes.io/ssl-redirect"
|
||||||
|
annotationKubernetesHSTSMaxAge = "ingress.kubernetes.io/hsts-max-age"
|
||||||
|
annotationKubernetesHSTSIncludeSubdomains = "ingress.kubernetes.io/hsts-include-subdomains"
|
||||||
|
annotationKubernetesCustomRequestHeaders = "ingress.kubernetes.io/custom-request-headers"
|
||||||
|
annotationKubernetesCustomResponseHeaders = "ingress.kubernetes.io/custom-response-headers"
|
||||||
|
annotationKubernetesAllowedHosts = "ingress.kubernetes.io/allowed-hosts"
|
||||||
|
annotationKubernetesProxyHeaders = "ingress.kubernetes.io/proxy-headers"
|
||||||
|
annotationKubernetesSSLTemporaryRedirect = "ingress.kubernetes.io/ssl-temporary-redirect"
|
||||||
|
annotationKubernetesSSLHost = "ingress.kubernetes.io/ssl-host"
|
||||||
|
annotationKubernetesSSLProxyHeaders = "ingress.kubernetes.io/ssl-proxy-headers"
|
||||||
|
annotationKubernetesHSTSPreload = "ingress.kubernetes.io/hsts-preload"
|
||||||
|
annotationKubernetesForceHSTSHeader = "ingress.kubernetes.io/force-hsts"
|
||||||
|
annotationKubernetesFrameDeny = "ingress.kubernetes.io/frame-deny"
|
||||||
|
annotationKubernetesCustomFrameOptionsValue = "ingress.kubernetes.io/custom-frame-options-value"
|
||||||
|
annotationKubernetesContentTypeNosniff = "ingress.kubernetes.io/content-type-nosniff"
|
||||||
|
annotationKubernetesBrowserXSSFilter = "ingress.kubernetes.io/browser-xss-filter"
|
||||||
|
annotationKubernetesContentSecurityPolicy = "ingress.kubernetes.io/content-security-policy"
|
||||||
|
annotationKubernetesPublicKey = "ingress.kubernetes.io/public-key"
|
||||||
|
annotationKubernetesReferrerPolicy = "ingress.kubernetes.io/referrer-policy"
|
||||||
|
annotationKubernetesIsDevelopment = "ingress.kubernetes.io/is-development"
|
||||||
)
|
)
|
||||||
|
|
||||||
const traefikDefaultRealm = "traefik"
|
const traefikDefaultRealm = "traefik"
|
||||||
|
@ -53,7 +73,7 @@ type Provider struct {
|
||||||
lastConfiguration safe.Safe
|
lastConfiguration safe.Safe
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) newK8sClient() (Client, error) {
|
func (p Provider) newK8sClient() (Client, error) {
|
||||||
withEndpoint := ""
|
withEndpoint := ""
|
||||||
if p.Endpoint != "" {
|
if p.Endpoint != "" {
|
||||||
withEndpoint = fmt.Sprintf(" with endpoint %v", p.Endpoint)
|
withEndpoint = fmt.Sprintf(" with endpoint %v", p.Endpoint)
|
||||||
|
@ -166,18 +186,18 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
passHostHeader := getAnnotationPassHostHeader(i, p)
|
passHostHeader := getBoolAnnotation(i, types.LabelFrontendPassHostHeader, !p.DisablePassHostHeaders)
|
||||||
passTLSCert := getAnnotationPassTLSCert(i, p)
|
passTLSCert := getBoolAnnotation(i, types.LabelFrontendPassTLSCert, p.EnablePassTLSCert)
|
||||||
|
|
||||||
if realm := i.Annotations[annotationKubernetesAuthRealm]; realm != "" && realm != traefikDefaultRealm {
|
if realm := i.Annotations[annotationKubernetesAuthRealm]; realm != "" && realm != traefikDefaultRealm {
|
||||||
log.Errorf("Value for annotation %q on ingress %s/%s invalid: no realm customization supported", annotationKubernetesAuthRealm, i.ObjectMeta.Namespace, i.ObjectMeta.Name)
|
log.Errorf("Value for annotation %q on ingress %s/%s invalid: no realm customization supported", annotationKubernetesAuthRealm, i.ObjectMeta.Namespace, i.ObjectMeta.Name)
|
||||||
delete(templateObjects.Backends, r.Host+pa.Path)
|
delete(templateObjects.Backends, r.Host+pa.Path)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
entryPoints := getEntrypoints(i)
|
entryPoints := getSliceAnnotation(i, types.LabelFrontendEntryPoints)
|
||||||
|
|
||||||
whitelistSourceRangeAnnotation := i.Annotations[annotationKubernetesWhitelistSourceRange]
|
whitelistSourceRange := getSliceAnnotation(i, annotationKubernetesWhitelistSourceRange)
|
||||||
whitelistSourceRange := provider.SplitAndTrimString(whitelistSourceRangeAnnotation)
|
|
||||||
|
|
||||||
entryPointRedirect, _ := i.Annotations[types.LabelFrontendRedirect]
|
entryPointRedirect, _ := i.Annotations[types.LabelFrontendRedirect]
|
||||||
|
|
||||||
|
@ -188,7 +208,30 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
priority := p.getPriority(pa, i)
|
priority := getPriority(i)
|
||||||
|
|
||||||
|
headers := types.Headers{
|
||||||
|
CustomRequestHeaders: getMapAnnotation(i, annotationKubernetesCustomRequestHeaders),
|
||||||
|
CustomResponseHeaders: getMapAnnotation(i, annotationKubernetesCustomResponseHeaders),
|
||||||
|
AllowedHosts: getSliceAnnotation(i, annotationKubernetesAllowedHosts),
|
||||||
|
HostsProxyHeaders: getSliceAnnotation(i, annotationKubernetesProxyHeaders),
|
||||||
|
SSLRedirect: getBoolAnnotation(i, annotationKubernetesSSLRedirect, false),
|
||||||
|
SSLTemporaryRedirect: getBoolAnnotation(i, annotationKubernetesSSLTemporaryRedirect, false),
|
||||||
|
SSLHost: getStringAnnotation(i, annotationKubernetesSSLHost),
|
||||||
|
SSLProxyHeaders: getMapAnnotation(i, annotationKubernetesSSLProxyHeaders),
|
||||||
|
STSSeconds: getSTSSeconds(i),
|
||||||
|
STSIncludeSubdomains: getBoolAnnotation(i, annotationKubernetesHSTSIncludeSubdomains, false),
|
||||||
|
STSPreload: getBoolAnnotation(i, annotationKubernetesHSTSPreload, false),
|
||||||
|
ForceSTSHeader: getBoolAnnotation(i, annotationKubernetesForceHSTSHeader, false),
|
||||||
|
FrameDeny: getBoolAnnotation(i, annotationKubernetesFrameDeny, false),
|
||||||
|
CustomFrameOptionsValue: getStringAnnotation(i, annotationKubernetesCustomFrameOptionsValue),
|
||||||
|
ContentTypeNosniff: getBoolAnnotation(i, annotationKubernetesContentTypeNosniff, false),
|
||||||
|
BrowserXSSFilter: getBoolAnnotation(i, annotationKubernetesBrowserXSSFilter, false),
|
||||||
|
ContentSecurityPolicy: getStringAnnotation(i, annotationKubernetesContentSecurityPolicy),
|
||||||
|
PublicKey: getStringAnnotation(i, annotationKubernetesPublicKey),
|
||||||
|
ReferrerPolicy: getStringAnnotation(i, annotationKubernetesReferrerPolicy),
|
||||||
|
IsDevelopment: getBoolAnnotation(i, annotationKubernetesIsDevelopment, false),
|
||||||
|
}
|
||||||
|
|
||||||
templateObjects.Frontends[r.Host+pa.Path] = &types.Frontend{
|
templateObjects.Frontends[r.Host+pa.Path] = &types.Frontend{
|
||||||
Backend: r.Host + pa.Path,
|
Backend: r.Host + pa.Path,
|
||||||
|
@ -200,6 +243,7 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
|
||||||
WhitelistSourceRange: whitelistSourceRange,
|
WhitelistSourceRange: whitelistSourceRange,
|
||||||
Redirect: entryPointRedirect,
|
Redirect: entryPointRedirect,
|
||||||
EntryPoints: entryPoints,
|
EntryPoints: entryPoints,
|
||||||
|
Headers: headers,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(r.Host) > 0 {
|
if len(r.Host) > 0 {
|
||||||
|
@ -312,37 +356,21 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
|
||||||
return &templateObjects, nil
|
return &templateObjects, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEntrypoints(i *v1beta1.Ingress) []string {
|
func (p Provider) loadConfig(templateObjects types.Configuration) *types.Configuration {
|
||||||
entrypointsAnnotation, ok := i.Annotations[types.LabelFrontendEntryPoints]
|
var FuncMap = template.FuncMap{}
|
||||||
if ok {
|
configuration, err := p.GetConfiguration("templates/kubernetes.tmpl", FuncMap, templateObjects)
|
||||||
return strings.Split(entrypointsAnnotation, ",")
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
}
|
}
|
||||||
return nil
|
return configuration
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBoolAnnotation(meta v1.ObjectMeta, name string, defaultValue bool) bool {
|
func getSTSSeconds(i *v1beta1.Ingress) int64 {
|
||||||
annotationValue := defaultValue
|
value, err := strconv.ParseInt(i.ObjectMeta.Annotations[annotationKubernetesHSTSMaxAge], 10, 64)
|
||||||
annotationStringValue, ok := meta.Annotations[name]
|
if err == nil && value > 0 {
|
||||||
switch {
|
return value
|
||||||
case !ok:
|
|
||||||
// No op.
|
|
||||||
case annotationStringValue == "false":
|
|
||||||
annotationValue = false
|
|
||||||
case annotationStringValue == "true":
|
|
||||||
annotationValue = true
|
|
||||||
default:
|
|
||||||
log.Warnf("Unknown value '%s' for %s, falling back to %s", name, types.LabelFrontendPassTLSCert, defaultValue)
|
|
||||||
}
|
}
|
||||||
return annotationValue
|
return 0
|
||||||
}
|
|
||||||
|
|
||||||
func getAnnotationPassHostHeader(i *v1beta1.Ingress, p *Provider) bool {
|
|
||||||
return getBoolAnnotation(i.ObjectMeta, types.LabelFrontendPassHostHeader, p.getPassHostHeader())
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAnnotationPassTLSCert(i *v1beta1.Ingress, p *Provider) bool {
|
|
||||||
return getBoolAnnotation(i.ObjectMeta, types.LabelFrontendPassTLSCert, p.getPassTLSCert())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRuleForPath(pa v1beta1.HTTPIngressPath, i *v1beta1.Ingress) string {
|
func getRuleForPath(pa v1beta1.HTTPIngressPath, i *v1beta1.Ingress) string {
|
||||||
|
@ -364,7 +392,7 @@ func getRuleForPath(pa v1beta1.HTTPIngressPath, i *v1beta1.Ingress) string {
|
||||||
return strings.Join(rules, ";")
|
return strings.Join(rules, ";")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) getPriority(path v1beta1.HTTPIngressPath, i *v1beta1.Ingress) int {
|
func getPriority(i *v1beta1.Ingress) int {
|
||||||
priority := 0
|
priority := 0
|
||||||
|
|
||||||
priorityRaw, ok := i.Annotations[types.LabelFrontendPriority]
|
priorityRaw, ok := i.Annotations[types.LabelFrontendPriority]
|
||||||
|
@ -464,20 +492,3 @@ func shouldProcessIngress(ingressClass string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) getPassHostHeader() bool {
|
|
||||||
return !p.DisablePassHostHeaders
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) getPassTLSCert() bool {
|
|
||||||
return p.EnablePassTLSCert
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) loadConfig(templateObjects types.Configuration) *types.Configuration {
|
|
||||||
var FuncMap = template.FuncMap{}
|
|
||||||
configuration, err := p.GetConfiguration("templates/kubernetes.tmpl", FuncMap, templateObjects)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
}
|
|
||||||
return configuration
|
|
||||||
}
|
|
||||||
|
|
|
@ -32,6 +32,52 @@
|
||||||
whitelistSourceRange = [{{range $frontend.WhitelistSourceRange}}
|
whitelistSourceRange = [{{range $frontend.WhitelistSourceRange}}
|
||||||
"{{.}}",
|
"{{.}}",
|
||||||
{{end}}]
|
{{end}}]
|
||||||
|
[frontends."{{$frontendName}}".headers]
|
||||||
|
SSLRedirect = {{$frontend.Headers.SSLRedirect}}
|
||||||
|
SSLTemporaryRedirect = {{$frontend.Headers.SSLTemporaryRedirect}}
|
||||||
|
SSLHost = "{{$frontend.Headers.SSLHost}}"
|
||||||
|
STSSeconds = {{$frontend.Headers.STSSeconds}}
|
||||||
|
STSIncludeSubdomains = {{$frontend.Headers.STSIncludeSubdomains}}
|
||||||
|
STSPreload = {{$frontend.Headers.STSPreload}}
|
||||||
|
ForceSTSHeader = {{$frontend.Headers.ForceSTSHeader}}
|
||||||
|
FrameDeny = {{$frontend.Headers.FrameDeny}}
|
||||||
|
CustomFrameOptionsValue = "{{$frontend.Headers.CustomFrameOptionsValue}}"
|
||||||
|
ContentTypeNosniff = {{$frontend.Headers.ContentTypeNosniff}}
|
||||||
|
BrowserXSSFilter = {{$frontend.Headers.BrowserXSSFilter}}
|
||||||
|
ContentSecurityPolicy = "{{$frontend.Headers.ContentSecurityPolicy}}"
|
||||||
|
PublicKey = "{{$frontend.Headers.PublicKey}}"
|
||||||
|
ReferrerPolicy = "{{$frontend.Headers.ReferrerPolicy}}"
|
||||||
|
IsDevelopment = {{$frontend.Headers.IsDevelopment}}
|
||||||
|
{{if $frontend.Headers.CustomRequestHeaders}}
|
||||||
|
[frontends."{{$frontendName}}".headers.customrequestheaders]
|
||||||
|
{{range $k, $v := $frontend.Headers.CustomRequestHeaders}}
|
||||||
|
{{$k}} = "{{$v}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{if $frontend.Headers.CustomResponseHeaders}}
|
||||||
|
[frontends."{{$frontendName}}".headers.customresponseheaders]
|
||||||
|
{{range $k, $v := $frontend.Headers.CustomResponseHeaders}}
|
||||||
|
{{$k}} = "{{$v}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{if $frontend.Headers.AllowedHosts}}
|
||||||
|
[frontends."{{$frontendName}}".headers.AllowedHosts]
|
||||||
|
{{range $frontend.Headers.AllowedHosts}}
|
||||||
|
"{{.}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{if $frontend.Headers.HostsProxyHeaders}}
|
||||||
|
[frontends."{{$frontendName}}".headers.HostsProxyHeaders]
|
||||||
|
{{range $frontend.Headers.HostsProxyHeaders}}
|
||||||
|
"{{.}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{if $frontend.Headers.SSLProxyHeaders}}
|
||||||
|
[frontends."{{$frontendName}}".headers.SSLProxyHeaders]
|
||||||
|
{{range $k, $v := $frontend.Headers.SSLProxyHeaders}}
|
||||||
|
{{$k}} = "{{$v}}"
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
{{range $routeName, $route := $frontend.Routes}}
|
{{range $routeName, $route := $frontend.Routes}}
|
||||||
[frontends."{{$frontendName}}".routes."{{$routeName}}"]
|
[frontends."{{$frontendName}}".routes."{{$routeName}}"]
|
||||||
rule = "{{$route.Rule}}"
|
rule = "{{$route.Rule}}"
|
||||||
|
|
Loading…
Reference in a new issue