Commit 18abf575 authored by Geoff Simmons's avatar Geoff Simmons

Redefine the labels used to identify relevant Secrets.

Use the label key viking.uplex.de/secret. The controller only reads
Secrets with this label, and with the field type:kubernetes.io/tls
(the latter are Secrets specified for Ingress).

Three values are permitted for the label:

admin: credentials for remote admin of Varnish and haproxy (Varnish
shared secret and Basic Auth password for the dataplane API).

pem: initially empty Secret into which the controller writes pem
files (concatenated crt and key), projected into a volume from
which haproxy reads at load time. Currently only with the hard-
wired name "tls-cert", so that RBAC update privileges can be
limited to this Secret.

auth: credentials for Basic and Proxy Auth, as configured via
the VarnishConfig custom resource.
parent 6b432437
...@@ -99,7 +99,7 @@ var ( ...@@ -99,7 +99,7 @@ var (
informerStop = make(chan struct{}) informerStop = make(chan struct{})
) )
const vikingSecretSelector = "app=varnish-ingress" const vikingSecretSelector = "viking.uplex.de/secret"
// The next two functions satisify type TweakListOptionsFunc in // The next two functions satisify type TweakListOptionsFunc in
// k8s.io/client-go/informers/internalinterfaces, for use in the // k8s.io/client-go/informers/internalinterfaces, for use in the
......
...@@ -3,7 +3,7 @@ kind: Secret ...@@ -3,7 +3,7 @@ kind: Secret
metadata: metadata:
name: adm-secret name: adm-secret
labels: labels:
app: varnish-ingress viking.uplex.de/secret: admin
type: Opaque type: Opaque
data: data:
admin: XGASQn0dd/oEsWh5WMXUpmKAKNZYnQGsHSmO/nHkv1w= admin: XGASQn0dd/oEsWh5WMXUpmKAKNZYnQGsHSmO/nHkv1w=
......
...@@ -3,5 +3,5 @@ kind: Secret ...@@ -3,5 +3,5 @@ kind: Secret
metadata: metadata:
name: tls-cert name: tls-cert
labels: labels:
app: varnish-ingress viking.uplex.de/secret: pem
type: Opaque type: Opaque
...@@ -4,7 +4,7 @@ metadata: ...@@ -4,7 +4,7 @@ metadata:
name: adm-secret name: adm-secret
namespace: cafe namespace: cafe
labels: labels:
app: varnish-ingress viking.uplex.de/secret: admin
type: Opaque type: Opaque
data: data:
admin: ByIQphD6z6UY3nEXAVS+AlrQUXgzg2dcT1Zd1rG1l4M= admin: ByIQphD6z6UY3nEXAVS+AlrQUXgzg2dcT1Zd1rG1l4M=
......
...@@ -4,7 +4,7 @@ metadata: ...@@ -4,7 +4,7 @@ metadata:
name: adm-secret name: adm-secret
namespace: kube-system namespace: kube-system
labels: labels:
app: varnish-ingress viking.uplex.de/secret: admin
type: Opaque type: Opaque
data: data:
admin: f/y/Vt0O7rnL3m5LM2upu/ImjA6paITHmvYYEQ1Qrfg= admin: f/y/Vt0O7rnL3m5LM2upu/ImjA6paITHmvYYEQ1Qrfg=
......
...@@ -4,5 +4,5 @@ metadata: ...@@ -4,5 +4,5 @@ metadata:
name: tls-cert name: tls-cert
namespace: cafe namespace: cafe
labels: labels:
app: varnish-ingress viking.uplex.de/secret: pem
type: Opaque type: Opaque
...@@ -4,5 +4,5 @@ metadata: ...@@ -4,5 +4,5 @@ metadata:
name: tls-cert name: tls-cert
namespace: kube-system namespace: kube-system
labels: labels:
app: varnish-ingress viking.uplex.de/secret: pem
type: Opaque type: Opaque
...@@ -4,7 +4,7 @@ metadata: ...@@ -4,7 +4,7 @@ metadata:
name: adm-secret name: adm-secret
namespace: kube-system namespace: kube-system
labels: labels:
app: varnish-ingress viking.uplex.de/secret: admin
type: Opaque type: Opaque
data: data:
admin: f/y/Vt0O7rnL3m5LM2upu/ImjA6paITHmvYYEQ1Qrfg= admin: f/y/Vt0O7rnL3m5LM2upu/ImjA6paITHmvYYEQ1Qrfg=
......
...@@ -4,5 +4,5 @@ metadata: ...@@ -4,5 +4,5 @@ metadata:
name: tls-cert name: tls-cert
namespace: kube-system namespace: kube-system
labels: labels:
app: varnish-ingress viking.uplex.de/secret: pem
type: Opaque type: Opaque
...@@ -4,7 +4,7 @@ metadata: ...@@ -4,7 +4,7 @@ metadata:
name: coffee-secret name: coffee-secret
namespace: cafe namespace: cafe
labels: labels:
app: varnish-ingress viking.uplex.de/secret: admin
type: Opaque type: Opaque
data: data:
admin: BhjBhxjqrbCnW2eYLoUL+C2TN51a8sWQIfL9oRWPY2E= admin: BhjBhxjqrbCnW2eYLoUL+C2TN51a8sWQIfL9oRWPY2E=
......
...@@ -4,7 +4,7 @@ metadata: ...@@ -4,7 +4,7 @@ metadata:
name: tea-secret name: tea-secret
namespace: cafe namespace: cafe
labels: labels:
app: varnish-ingress viking.uplex.de/secret: admin
type: Opaque type: Opaque
data: data:
admin: IZqtwnccuVoCblGaTq8yK8mOk8gtLwWmbZq17tpcdwo= admin: IZqtwnccuVoCblGaTq8yK8mOk8gtLwWmbZq17tpcdwo=
......
...@@ -4,5 +4,5 @@ metadata: ...@@ -4,5 +4,5 @@ metadata:
name: tls-cert name: tls-cert
namespace: cafe namespace: cafe
labels: labels:
app: varnish-ingress viking.uplex.de/secret: pem
type: Opaque type: Opaque
...@@ -4,7 +4,7 @@ metadata: ...@@ -4,7 +4,7 @@ metadata:
name: coffee-secret name: coffee-secret
namespace: cafe namespace: cafe
labels: labels:
app: varnish-ingress viking.uplex.de/secret: admin
type: Opaque type: Opaque
data: data:
admin: BhjBhxjqrbCnW2eYLoUL+C2TN51a8sWQIfL9oRWPY2E= admin: BhjBhxjqrbCnW2eYLoUL+C2TN51a8sWQIfL9oRWPY2E=
......
...@@ -4,7 +4,7 @@ metadata: ...@@ -4,7 +4,7 @@ metadata:
name: tea-secret name: tea-secret
namespace: cafe namespace: cafe
labels: labels:
app: varnish-ingress viking.uplex.de/secret: admin
type: Opaque type: Opaque
data: data:
admin: IZqtwnccuVoCblGaTq8yK8mOk8gtLwWmbZq17tpcdwo= admin: IZqtwnccuVoCblGaTq8yK8mOk8gtLwWmbZq17tpcdwo=
......
...@@ -4,5 +4,5 @@ metadata: ...@@ -4,5 +4,5 @@ metadata:
name: tls-cert name: tls-cert
namespace: cafe namespace: cafe
labels: labels:
app: varnish-ingress viking.uplex.de/secret: pem
type: Opaque type: Opaque
...@@ -3,7 +3,7 @@ kind: Secret ...@@ -3,7 +3,7 @@ kind: Secret
metadata: metadata:
name: coffee-creds name: coffee-creds
labels: labels:
app: varnish-ingress viking.uplex.de/secret: auth
type: Opaque type: Opaque
stringData: stringData:
coffee-admin: superpowers coffee-admin: superpowers
...@@ -16,7 +16,7 @@ kind: Secret ...@@ -16,7 +16,7 @@ kind: Secret
metadata: metadata:
name: tea-creds name: tea-creds
labels: labels:
app: varnish-ingress viking.uplex.de/secret: auth
type: Opaque type: Opaque
stringData: stringData:
tea-admin: awesomeness tea-admin: awesomeness
......
...@@ -3,7 +3,7 @@ kind: Secret ...@@ -3,7 +3,7 @@ kind: Secret
metadata: metadata:
name: proxy-creds name: proxy-creds
labels: labels:
app: varnish-ingress viking.uplex.de/secret: auth
type: Opaque type: Opaque
stringData: stringData:
proxy-admin: studly proxy-admin: studly
......
...@@ -4,7 +4,7 @@ metadata: ...@@ -4,7 +4,7 @@ metadata:
name: adm-secret name: adm-secret
namespace: varnish-ingress namespace: varnish-ingress
labels: labels:
app: varnish-ingress viking.uplex.de/secret: admin
type: Opaque type: Opaque
data: data:
admin: XGASQn0dd/oEsWh5WMXUpmKAKNZYnQGsHSmO/nHkv1w= admin: XGASQn0dd/oEsWh5WMXUpmKAKNZYnQGsHSmO/nHkv1w=
......
...@@ -4,5 +4,5 @@ metadata: ...@@ -4,5 +4,5 @@ metadata:
namespace: varnish-ingress namespace: varnish-ingress
name: tls-cert name: tls-cert
labels: labels:
app: varnish-ingress viking.uplex.de/secret: pem
type: Opaque type: Opaque
...@@ -45,9 +45,46 @@ const ( ...@@ -45,9 +45,46 @@ const (
admSecretKey = "admin" admSecretKey = "admin"
dplaneSecretKey = "dataplaneapi" dplaneSecretKey = "dataplaneapi"
certSecretName = "tls-cert" certSecretName = "tls-cert"
tlsSecretType = "kubernetes.io/tls" vikingSecretLabelKey = vikingLabelPfx + "secret"
vikingAdmSecretVal = "admin"
vikingPemSecretVal = "pem"
vikingAuthSecretVal = "auth"
) )
var (
vikingAdmSecretSet = labels.Set(map[string]string{
vikingSecretLabelKey: vikingAdmSecretVal,
})
// Selector for use in List() operations to find Secrets
// designated as admin secrets for this application (Varnish
// shared secret and dataplane API password for Basic Auth).
vikingAdmSecretSelector = labels.SelectorFromSet(vikingAdmSecretSet)
)
func isPemSecret(secret *api_v1.Secret) (bool, error) {
if secret.Name == certSecretName {
if val, ok := secret.Labels[vikingSecretLabelKey]; !ok {
return false, fmt.Errorf("Secret %s/%s lacks required "+
"label %s", secret.Namespace, secret.Name,
vikingSecretLabelKey)
} else if val != vikingPemSecretVal {
return false, fmt.Errorf("Secret %s/%s lacks required "+
"label value %s=%s", secret.Namespace,
secret.Name, vikingSecretLabelKey,
vikingPemSecretVal)
}
return true, nil
}
if val, ok := secret.Labels[vikingSecretLabelKey]; ok &&
val == vikingPemSecretVal {
return false, fmt.Errorf("Secret %s/%s: Secrets with label "+
"value %s=%s must have name %s", secret.Namespace,
secret.Name, vikingSecretLabelKey, vikingPemSecretVal,
certSecretName)
}
return false, nil
}
// XXX client...Update(secret) returns Secret // XXX client...Update(secret) returns Secret
// XXX client...Create(secret) if it's new? // XXX client...Create(secret) if it's new?
func (worker *NamespaceWorker) updateCertSecret(spec *haproxy.SecretSpec) error { func (worker *NamespaceWorker) updateCertSecret(spec *haproxy.SecretSpec) error {
...@@ -56,12 +93,12 @@ func (worker *NamespaceWorker) updateCertSecret(spec *haproxy.SecretSpec) error ...@@ -56,12 +93,12 @@ func (worker *NamespaceWorker) updateCertSecret(spec *haproxy.SecretSpec) error
if err != nil { if err != nil {
return err return err
} }
if tlsSecret.Type != tlsSecretType { if tlsSecret.Type != api_v1.SecretTypeTLS {
return fmt.Errorf("Ingress TLS Secret %s/%s: type is %s, "+ return fmt.Errorf("Ingress TLS Secret %s/%s: type is %s, "+
"should be %s", "should be %s",
tlsSecret.ObjectMeta.Namespace, tlsSecret.ObjectMeta.Namespace,
tlsSecret.ObjectMeta.Name, tlsSecret.Type, tlsSecret.ObjectMeta.Name, tlsSecret.Type,
tlsSecretType) string(api_v1.SecretTypeTLS))
} }
crt, ok := tlsSecret.Data["tls.crt"] crt, ok := tlsSecret.Data["tls.crt"]
if !ok { if !ok {
...@@ -243,7 +280,7 @@ func (worker *NamespaceWorker) enqueueIngsForTLSSecret( ...@@ -243,7 +280,7 @@ func (worker *NamespaceWorker) enqueueIngsForTLSSecret(
} }
func (worker *NamespaceWorker) getDplaneSecret() (string, []byte, error) { func (worker *NamespaceWorker) getDplaneSecret() (string, []byte, error) {
secrets, err := worker.vsecr.List(varnishIngressSelector) secrets, err := worker.vsecr.List(vikingAdmSecretSelector)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
...@@ -285,19 +322,35 @@ func (worker *NamespaceWorker) syncSecret(key string) error { ...@@ -285,19 +322,35 @@ func (worker *NamespaceWorker) syncSecret(key string) error {
} }
} }
if secret.Type == tlsSecretType { if secret.Type == api_v1.SecretTypeTLS {
return worker.enqueueIngsForTLSSecret(secret) return worker.enqueueIngsForTLSSecret(secret)
} }
app, ok := secret.Labels[labelKey] if isPem, err := isPemSecret(secret); err != nil {
if !ok || app != labelVal { return err
worker.log.Infof("Not a Varnish secret: %s/%s", } else if isPem {
worker.log.Infof("PEM Secret %s/%s: no sync necessary",
secret.Namespace, secret.Name) secret.Namespace, secret.Name)
syncCounters.WithLabelValues(worker.namespace, "Secret", syncCounters.WithLabelValues(worker.namespace, "Secret",
"Ignore").Inc() "Ignore").Inc()
return nil return nil
} }
secretType, ok := secret.Labels[vikingSecretLabelKey]
if !ok {
// Should be impossible due to informer filtering
return fmt.Errorf("Secret %s/%s lacks required label %s",
secret.Namespace, secret.Name, vikingSecretLabelKey)
}
if secretType == vikingAuthSecretVal {
return worker.updateVcfgsForSecret(secret.Name)
}
if secretType != vikingAdmSecretVal {
return fmt.Errorf("Secret %s/%s: unknown value %s for label %s",
secret.Namespace, secret.Name, secretType,
vikingSecretLabelKey)
}
svcs, err := worker.getVarnishSvcsForSecret(secret.Name) svcs, err := worker.getVarnishSvcsForSecret(secret.Name)
if err != nil { if err != nil {
return err return err
...@@ -307,7 +360,7 @@ func (worker *NamespaceWorker) syncSecret(key string) error { ...@@ -307,7 +360,7 @@ func (worker *NamespaceWorker) syncSecret(key string) error {
if len(svcs) == 0 { if len(svcs) == 0 {
worker.log.Infof("No Varnish services with admin secret: %s/%s", worker.log.Infof("No Varnish services with admin secret: %s/%s",
secret.Namespace, secret.Name) secret.Namespace, secret.Name)
return worker.updateVcfgsForSecret(secret.Name) return nil
} }
err = worker.setSecret(secret) err = worker.setSecret(secret)
...@@ -333,12 +386,38 @@ func (worker *NamespaceWorker) deleteSecret(obj interface{}) error { ...@@ -333,12 +386,38 @@ func (worker *NamespaceWorker) deleteSecret(obj interface{}) error {
return nil return nil
} }
if secr.Type == tlsSecretType { if secr.Type == api_v1.SecretTypeTLS {
worker.log.Infof("Deleting TLS Secret: %s/%s", secr.Namespace, worker.log.Infof("Deleting TLS Secret: %s/%s", secr.Namespace,
secr.Name) secr.Name)
return worker.deleteTLSSecret(secr) return worker.deleteTLSSecret(secr)
} }
// XXX quite a bit of code duplication with syncSecret above
if isPem, err := isPemSecret(secr); err != nil {
return err
} else if isPem {
worker.log.Infof("PEM Secret %s/%s: no sync necessary",
secr.Namespace, secr.Name)
syncCounters.WithLabelValues(worker.namespace, "Secret",
"Ignore").Inc()
return nil
}
secretType, ok := secr.Labels[vikingSecretLabelKey]
if !ok {
// Should be impossible due to informer filtering
return fmt.Errorf("Secret %s/%s lacks required label %s",
secr.Namespace, secr.Name, vikingSecretLabelKey)
}
if secretType == vikingAuthSecretVal {
return worker.updateVcfgsForSecret(secr.Name)
}
if secretType != vikingAdmSecretVal {
return fmt.Errorf("Secret %s/%s: unknown value %s for label %s",
secr.Namespace, secr.Name, secretType,
vikingSecretLabelKey)
}
worker.log.Infof("Deleting Secret: %s/%s", secr.Namespace, secr.Name) worker.log.Infof("Deleting Secret: %s/%s", secr.Namespace, secr.Name)
svcs, err := worker.getVarnishSvcsForSecret(secr.Name) svcs, err := worker.getVarnishSvcsForSecret(secr.Name)
if err != nil { if err != nil {
...@@ -349,7 +428,7 @@ func (worker *NamespaceWorker) deleteSecret(obj interface{}) error { ...@@ -349,7 +428,7 @@ func (worker *NamespaceWorker) deleteSecret(obj interface{}) error {
if len(svcs) == 0 { if len(svcs) == 0 {
worker.log.Infof("No Varnish services with admin secret: %s/%s", worker.log.Infof("No Varnish services with admin secret: %s/%s",
secr.Namespace, secr.Name) secr.Namespace, secr.Name)
return worker.updateVcfgsForSecret(secr.Name) return nil
} }
secretKey := secr.Namespace + "/" + secr.Name secretKey := secr.Namespace + "/" + secr.Name
......
...@@ -43,6 +43,7 @@ import ( ...@@ -43,6 +43,7 @@ import (
const ( const (
labelKey = "app" labelKey = "app"
labelVal = "varnish-ingress" labelVal = "varnish-ingress"
vikingLabelPfx = "viking.uplex.de/"
) )
var ( var (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment