Experimental: Update traefik Host() rules for v3

This commit is contained in:
Tom Wiesing 2023-04-12 19:21:11 +02:00
parent 34db2e1923
commit 285aaff77d
No known key found for this signature in database
10 changed files with 60 additions and 13 deletions

3
go.mod
View file

@ -21,6 +21,7 @@ require (
github.com/yuin/goldmark-meta v1.1.0 github.com/yuin/goldmark-meta v1.1.0
golang.org/x/crypto v0.8.0 golang.org/x/crypto v0.8.0
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/exp v0.0.0-20230321023759-10a507213a29
golang.org/x/net v0.9.0
golang.org/x/sync v0.1.0 golang.org/x/sync v0.1.0
golang.org/x/term v0.7.0 golang.org/x/term v0.7.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@ -63,8 +64,8 @@ require (
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect
golang.org/x/mod v0.9.0 // indirect golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sys v0.7.0 // indirect golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.1.0 // indirect golang.org/x/time v0.1.0 // indirect
golang.org/x/tools v0.7.0 // indirect golang.org/x/tools v0.7.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect

2
go.sum
View file

@ -180,6 +180,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View file

@ -5,7 +5,7 @@ import (
"net/url" "net/url"
"strings" "strings"
"github.com/tkw1536/pkglib/collection" "golang.org/x/net/idna"
) )
type HTTPConfig struct { type HTTPConfig struct {
@ -80,10 +80,7 @@ func (hcfg HTTPConfig) Domains(sub string) []string {
// HostRule returns a HostRule for the provided subdomain. // HostRule returns a HostRule for the provided subdomain.
// See Domains() for usage of sub. // See Domains() for usage of sub.
func (hcfg HTTPConfig) HostRule(sub string) string { func (hcfg HTTPConfig) HostRule(sub string) string {
quoted := collection.MapSlice(hcfg.Domains(sub), func(name string) string { return MakeHostRule(hcfg.Domains(sub)...)
return "`" + name + "`"
})
return fmt.Sprintf("Host(%s)", strings.Join(quoted, ","))
} }
// HTTPSEnabledEnv returns "true" if https is enabled, and "false" otherwise. // HTTPSEnabledEnv returns "true" if https is enabled, and "false" otherwise.
@ -141,3 +138,36 @@ func TrimSuffixFold(s string, suffix string) string {
func (cfg HTTPConfig) DefaultHostRule() string { func (cfg HTTPConfig) DefaultHostRule() string {
return cfg.HostRule("") return cfg.HostRule("")
} }
// MakeHostRule builds a new Host() rule string to be used by traefik.
func MakeHostRule(hosts ...string) string {
var builder strings.Builder
first := true
for _, host := range hosts {
// HACK HACK HACK: Very minimal domain validation to prevent validation.
// Just skip everything that isn't a domain.
if strings.Contains(host, "`") {
continue
}
if first {
builder.WriteString("||Host(`")
} else {
builder.WriteString("Host(`")
}
// domain should be punycode!
domain, err := idna.ToASCII(host)
if err != nil {
domain = host
}
builder.WriteString(domain)
builder.WriteString("`)")
first = false
}
return builder.String()
}

View file

@ -2,7 +2,8 @@ DATA_PATH=${DATA_PATH}
RUNTIME_DIR=${RUNTIME_DIR} RUNTIME_DIR=${RUNTIME_DIR}
SLUG=${SLUG} SLUG=${SLUG}
VIRTUAL_HOST=${VIRTUAL_HOST} HOSTNAME=${HOSTNAME}
HOST_RULE=${HOST_RULE}
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME} DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
HTTPS_ENABLED=${HTTPS_ENABLED} HTTPS_ENABLED=${HTTPS_ENABLED}

View file

@ -4,14 +4,14 @@ services:
barrel: barrel:
build: . build: .
restart: always restart: always
hostname: ${VIRTUAL_HOST}.wisski hostname: ${HOSTNAME}
# label it with the current slug # label it with the current slug
labels: labels:
- "traefik.enable=True" - "traefik.enable=True"
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}" - "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
- "traefik.http.routers.wisski_${SLUG}.rule=Host(`${VIRTUAL_HOST}`)" - "traefik.http.routers.wisski_${SLUG}.rule=${HOST_RULE}"
- "traefik.http.routers.wisski_${SLUG}.tls=${HTTPS_ENABLED}" - "traefik.http.routers.wisski_${SLUG}.tls=${HTTPS_ENABLED}"
- "traefik.http.routers.wisski_${SLUG}.tls.certresolver=distillery" - "traefik.http.routers.wisski_${SLUG}.tls.certresolver=distillery"
- "traefik.http.services.wisski_${SLUG}.loadbalancer.server.port=8080" - "traefik.http.services.wisski_${SLUG}.loadbalancer.server.port=8080"

View file

@ -25,7 +25,8 @@ func (barrel *Barrel) Stack() component.StackWithResources {
"DOCKER_NETWORK_NAME": barrel.Malt.Config.Docker.Network(), "DOCKER_NETWORK_NAME": barrel.Malt.Config.Docker.Network(),
"SLUG": barrel.Slug, "SLUG": barrel.Slug,
"VIRTUAL_HOST": barrel.Domain(), "HOST_RULE": barrel.HostRule(),
"HOSTNAME": barrel.Hostname(),
"HTTPS_ENABLED": barrel.Malt.Config.HTTP.HTTPSEnabledEnv(), "HTTPS_ENABLED": barrel.Malt.Config.HTTP.HTTPSEnabledEnv(),
"DATA_PATH": filepath.Join(barrel.FilesystemBase, "data"), "DATA_PATH": filepath.Join(barrel.FilesystemBase, "data"),

View file

@ -1,5 +1,5 @@
SLUG=${SLUG} SLUG=${SLUG}
VIRTUAL_HOST=${VIRTUAL_HOST} HOST_RULE=${HOST_RULE}
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME} DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
HTTPS_ENABLED=${HTTPS_ENABLED} HTTPS_ENABLED=${HTTPS_ENABLED}

View file

@ -32,7 +32,8 @@ func (reserve *Reserve) Stack() component.StackWithResources {
"DOCKER_NETWORK_NAME": reserve.Malt.Config.Docker.Network(), "DOCKER_NETWORK_NAME": reserve.Malt.Config.Docker.Network(),
"SLUG": reserve.Slug, "SLUG": reserve.Slug,
"VIRTUAL_HOST": reserve.Domain(), "HOST_RULE": reserve.HostRule(),
"HOSTNAME": reserve.Hostname(),
"HTTPS_ENABLED": reserve.Malt.Config.HTTP.HTTPSEnabledEnv(), "HTTPS_ENABLED": reserve.Malt.Config.HTTP.HTTPSEnabledEnv(),
}, },
} }

View file

@ -11,7 +11,7 @@ services:
- "traefik.enable=True" - "traefik.enable=True"
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}" - "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
- "traefik.http.routers.reserve_${SLUG}.rule=Host(`${VIRTUAL_HOST}`)" - "traefik.http.routers.reserve_${SLUG}.rule=${HOST_RULE}"
- "traefik.http.routers.reserve_${SLUG}.tls=${HTTPS_ENABLED}" - "traefik.http.routers.reserve_${SLUG}.tls=${HTTPS_ENABLED}"
- "traefik.http.routers.reserve_${SLUG}.tls.certresolver=distillery" - "traefik.http.routers.reserve_${SLUG}.tls.certresolver=distillery"
- "traefik.http.services.reserve_${SLUG}.loadbalancer.server.port=8043" - "traefik.http.services.reserve_${SLUG}.loadbalancer.server.port=8043"

View file

@ -2,6 +2,8 @@ package liquid
import ( import (
"net/url" "net/url"
"github.com/FAU-CDI/wisski-distillery/internal/config"
) )
// Domain returns the full domain name of this WissKI // Domain returns the full domain name of this WissKI
@ -9,6 +11,15 @@ func (liquid *Liquid) Domain() string {
return liquid.Config.HTTP.HostFromSlug(liquid.Slug) return liquid.Config.HTTP.HostFromSlug(liquid.Slug)
} }
func (liquid *Liquid) Hostname() string {
return liquid.Domain() + ".wisski"
}
// HostRule returns a host rule for this wisski
func (liquid *Liquid) HostRule() string {
return config.MakeHostRule(liquid.Domain())
}
// URL returns the public URL of this instance // URL returns the public URL of this instance
func (liquid *Liquid) URL() *url.URL { func (liquid *Liquid) URL() *url.URL {
// setup domain and path // setup domain and path