Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MINOR: refactor quic configuration #701

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .aspell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ allowed:
- optim
- prometheus
- configmaps
- quic
170 changes: 88 additions & 82 deletions pkg/handler/quic.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,82 +29,101 @@ type Quic struct {
IPv6 bool
}

func (q *Quic) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annotations) (err error) {
var errs utils.Errors
defer func() {
err = errs.Result()
}()
var bindv4Present, bindv6Present bool
binds, errBindsGet := h.FrontendBindsGet(h.FrontHTTPS)
if errBindsGet != nil {
errs.Add(errBindsGet)
func (q *Quic) enableQuic(h haproxy.HAProxy) (err error) {
var binds []models.Bind
var bindIPv4Exists, bindIPv6Exists bool

err = q.altSvcRule(h)
if err != nil {
return
}

for _, bind := range binds {
bindv4Present = bindv4Present || bind.Name == QUIC4BIND
bindv6Present = bindv6Present || bind.Name == QUIC6BIND
existingBinds, err := h.FrontendBindsGet(h.FrontHTTPS)
if err != nil {
return
}

ipv4Func := func() {
if bindv4Present {
return
if q.IPv4 || q.IPv6 {
for _, existingBind := range existingBinds {
if existingBind.Name == QUIC4BIND {
bindIPv4Exists = true
}
if existingBind.Name == QUIC6BIND {
bindIPv6Exists = true
}
}
}

errFrontendBindCreate := h.FrontendBindCreate(h.FrontHTTPS, models.Bind{
Address: func() (addr string) {
addr = "quic4@" + q.AddrIPv4
return
}(),
Port: utils.PtrInt64(q.QuicBindPort),
addBind := func(addr string, bindName string, v4v6 bool) {
binds = append(binds, models.Bind{
Address: addr,
Port: utils.PtrInt64(q.QuicBindPort),
BindParams: models.BindParams{
Name: QUIC4BIND,
Name: bindName,
Ssl: true,
SslCertificate: q.CertDir,
Alpn: "h3",
V4v6: v4v6,
},
})
errs.Add(errFrontendBindCreate)
instance.ReloadIf(errFrontendBindCreate == nil, "quic binding v4 created")
}

ipv6Func := func() {
if bindv6Present {
return
}
errFrontendBindCreate := h.FrontendBindCreate(h.FrontHTTPS, models.Bind{
Address: func() (addr string) {
addr = "quic6@" + q.AddrIPv6
return
}(),
Port: utils.PtrInt64(q.QuicBindPort),
BindParams: models.BindParams{
Name: QUIC6BIND,
Ssl: true,
SslCertificate: q.CertDir,
Alpn: "h3",
},
})
errs.Add(errFrontendBindCreate)
instance.ReloadIf(errFrontendBindCreate == nil, "quic binding v6 created")
if q.IPv4 && !bindIPv4Exists {
addBind("quic4@"+q.AddrIPv4, QUIC4BIND, false)
}
if q.IPv6 && !bindIPv6Exists {
addBind("quic6@"+q.AddrIPv6, QUIC6BIND, true)
}

ipv4DeleteFunc := func() {
if !bindv4Present {
return
for _, bind := range binds {
err = h.FrontendBindCreate(h.FrontHTTPS, bind)
if err != nil {
return err
}
errFrontendBindDelete := h.FrontendBindDelete(h.FrontHTTPS, QUIC4BIND)
errs.Add(errFrontendBindDelete)
instance.ReloadIf(errFrontendBindDelete == nil, "quic binding v4 removed")
}

ipv6DeleteFunc := func() {
if !bindv6Present {
return
if len(binds) > 0 {
instance.Reload("QUIC enabled")
}
return
}

func (q *Quic) disableQuic(h haproxy.HAProxy) (err error) {
errors := utils.Errors{}
if q.IPv6 {
errors.Add(h.FrontendBindDelete(h.FrontHTTPS, QUIC6BIND))
}
if q.IPv4 {
errors.Add(h.FrontendBindDelete(h.FrontHTTPS, QUIC4BIND))
}
err = errors.Result()
if err == nil {
instance.Reload("QUIC disabled")
}
return
}

func (q *Quic) altSvcRule(h haproxy.HAProxy) (err error) {
errors := utils.Errors{}
logger.Debug("quic redirect rule to be created")
errors.Add(h.AddRule(h.FrontHTTPS, rules.RequestRedirectQuic{}, false))
logger.Debug("quic set header rule to be created")
errors.Add(h.AddRule(h.FrontHTTPS, rules.SetHdr{
HdrName: "alt-svc",
Response: true,
HdrFormat: fmt.Sprintf("\"h3=\\\":%d\\\"; ma="+q.MaxAge+"\"", q.QuicAnnouncePort),
}, false))
return errors.Result()
}

func (q *Quic) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annotations) (err error) {
sslOffloadEnabled := h.FrontendSSLOffloadEnabled(h.FrontHTTPS)
if !sslOffloadEnabled {
logger.Warning("quic requires SSL offload to be enabled")
if err := q.disableQuic(h); err != nil {
return err
}
errFrontendBindDelete := h.FrontendBindDelete(h.FrontHTTPS, QUIC6BIND)
errs.Add(errFrontendBindDelete)
instance.ReloadIf(errFrontendBindDelete == nil, "quic binding v6 removed")
return nil
}

maxAge := common.GetValue("quic-alt-svc-max-age", k.ConfigMaps.Main.Annotations)
Expand All @@ -116,38 +135,25 @@ func (q *Quic) Update(k store.K8s, h haproxy.HAProxy, a annotations.Annotations)

nsSslCertificateAnn, nameSslCertificateAnn, err := common.GetK8sPath("ssl-certificate", k.ConfigMaps.Main.Annotations)
if err != nil || (nameSslCertificateAnn == "") {
errs.Add(err)
ipv4Func = ipv4DeleteFunc
ipv6Func = ipv6DeleteFunc
} else {
namespaceSslCertificate := k.Namespaces[nsSslCertificateAnn]
var sslSecret *store.Secret
if namespaceSslCertificate != nil {
sslSecret = namespaceSslCertificate.Secret[nameSslCertificateAnn]
}

if sslSecret == nil || sslSecret.Status == store.DELETED {
ipv4Func = ipv4DeleteFunc
ipv6Func = ipv6DeleteFunc
} else {
logger.Debug("quic redirect rule to be created")
errs.Add(h.AddRule(h.FrontHTTPS, rules.RequestRedirectQuic{}, false))
logger.Debug("quic set header rule to be created")
errs.Add(h.AddRule(h.FrontHTTPS, rules.SetHdr{
HdrName: "alt-svc",
Response: true,
HdrFormat: fmt.Sprintf("\"h3=\\\":%d\\\";ma="+maxAge+";\"", q.QuicAnnouncePort),
}, false))
if err := q.disableQuic(h); err != nil {
return err
}
return nil
}

if q.IPv4 {
ipv4Func()
namespaceSslCertificate := k.Namespaces[nsSslCertificateAnn]
var sslSecret *store.Secret
if namespaceSslCertificate != nil {
sslSecret = namespaceSslCertificate.Secret[nameSslCertificateAnn]
}

if q.IPv6 {
ipv6Func()
if sslSecret == nil || sslSecret.Status == store.DELETED {
logger.Warning("quic requires valid and existing ssl-certificate")
if err := q.disableQuic(h); err != nil {
return err
}
return nil
}

return
return q.enableQuic(h)
}
Loading