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 (
informerStop = make(chan struct{})
)
const vikingSecretSelector = "app=varnish-ingress"
const vikingSecretSelector = "viking.uplex.de/secret"
// The next two functions satisify type TweakListOptionsFunc in
// k8s.io/client-go/informers/internalinterfaces, for use in the
......
......@@ -3,7 +3,7 @@ kind: Secret
metadata:
name: adm-secret
labels:
app: varnish-ingress
viking.uplex.de/secret: admin
type: Opaque
data:
admin: XGASQn0dd/oEsWh5WMXUpmKAKNZYnQGsHSmO/nHkv1w=
......
......@@ -3,5 +3,5 @@ kind: Secret
metadata:
name: tls-cert
labels:
app: varnish-ingress
viking.uplex.de/secret: pem
type: Opaque
......@@ -4,7 +4,7 @@ metadata:
name: adm-secret
namespace: cafe
labels:
app: varnish-ingress
viking.uplex.de/secret: admin
type: Opaque
data:
admin: ByIQphD6z6UY3nEXAVS+AlrQUXgzg2dcT1Zd1rG1l4M=
......
......@@ -4,7 +4,7 @@ metadata:
name: adm-secret
namespace: kube-system
labels:
app: varnish-ingress
viking.uplex.de/secret: admin
type: Opaque
data:
admin: f/y/Vt0O7rnL3m5LM2upu/ImjA6paITHmvYYEQ1Qrfg=
......
......@@ -4,5 +4,5 @@ metadata:
name: tls-cert
namespace: cafe
labels:
app: varnish-ingress
viking.uplex.de/secret: pem
type: Opaque
......@@ -4,5 +4,5 @@ metadata:
name: tls-cert
namespace: kube-system
labels:
app: varnish-ingress
viking.uplex.de/secret: pem
type: Opaque
......@@ -4,7 +4,7 @@ metadata:
name: adm-secret
namespace: kube-system
labels:
app: varnish-ingress
viking.uplex.de/secret: admin
type: Opaque
data:
admin: f/y/Vt0O7rnL3m5LM2upu/ImjA6paITHmvYYEQ1Qrfg=
......
......@@ -4,5 +4,5 @@ metadata:
name: tls-cert
namespace: kube-system
labels:
app: varnish-ingress
viking.uplex.de/secret: pem
type: Opaque
......@@ -4,7 +4,7 @@ metadata:
name: coffee-secret
namespace: cafe
labels:
app: varnish-ingress
viking.uplex.de/secret: admin
type: Opaque
data:
admin: BhjBhxjqrbCnW2eYLoUL+C2TN51a8sWQIfL9oRWPY2E=
......
......@@ -4,7 +4,7 @@ metadata:
name: tea-secret
namespace: cafe
labels:
app: varnish-ingress
viking.uplex.de/secret: admin
type: Opaque
data:
admin: IZqtwnccuVoCblGaTq8yK8mOk8gtLwWmbZq17tpcdwo=
......
......@@ -4,5 +4,5 @@ metadata:
name: tls-cert
namespace: cafe
labels:
app: varnish-ingress
viking.uplex.de/secret: pem
type: Opaque
......@@ -4,7 +4,7 @@ metadata:
name: coffee-secret
namespace: cafe
labels:
app: varnish-ingress
viking.uplex.de/secret: admin
type: Opaque
data:
admin: BhjBhxjqrbCnW2eYLoUL+C2TN51a8sWQIfL9oRWPY2E=
......
......@@ -4,7 +4,7 @@ metadata:
name: tea-secret
namespace: cafe
labels:
app: varnish-ingress
viking.uplex.de/secret: admin
type: Opaque
data:
admin: IZqtwnccuVoCblGaTq8yK8mOk8gtLwWmbZq17tpcdwo=
......
......@@ -4,5 +4,5 @@ metadata:
name: tls-cert
namespace: cafe
labels:
app: varnish-ingress
viking.uplex.de/secret: pem
type: Opaque
......@@ -3,7 +3,7 @@ kind: Secret
metadata:
name: coffee-creds
labels:
app: varnish-ingress
viking.uplex.de/secret: auth
type: Opaque
stringData:
coffee-admin: superpowers
......@@ -16,7 +16,7 @@ kind: Secret
metadata:
name: tea-creds
labels:
app: varnish-ingress
viking.uplex.de/secret: auth
type: Opaque
stringData:
tea-admin: awesomeness
......
......@@ -3,7 +3,7 @@ kind: Secret
metadata:
name: proxy-creds
labels:
app: varnish-ingress
viking.uplex.de/secret: auth
type: Opaque
stringData:
proxy-admin: studly
......
......@@ -4,7 +4,7 @@ metadata:
name: adm-secret
namespace: varnish-ingress
labels:
app: varnish-ingress
viking.uplex.de/secret: admin
type: Opaque
data:
admin: XGASQn0dd/oEsWh5WMXUpmKAKNZYnQGsHSmO/nHkv1w=
......
......@@ -4,5 +4,5 @@ metadata:
namespace: varnish-ingress
name: tls-cert
labels:
app: varnish-ingress
viking.uplex.de/secret: pem
type: Opaque
......@@ -45,9 +45,46 @@ const (
admSecretKey = "admin"
dplaneSecretKey = "dataplaneapi"
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...Create(secret) if it's new?
func (worker *NamespaceWorker) updateCertSecret(spec *haproxy.SecretSpec) error {
......@@ -56,12 +93,12 @@ func (worker *NamespaceWorker) updateCertSecret(spec *haproxy.SecretSpec) error
if err != nil {
return err
}
if tlsSecret.Type != tlsSecretType {
if tlsSecret.Type != api_v1.SecretTypeTLS {
return fmt.Errorf("Ingress TLS Secret %s/%s: type is %s, "+
"should be %s",
tlsSecret.ObjectMeta.Namespace,
tlsSecret.ObjectMeta.Name, tlsSecret.Type,
tlsSecretType)
string(api_v1.SecretTypeTLS))
}
crt, ok := tlsSecret.Data["tls.crt"]
if !ok {
......@@ -243,7 +280,7 @@ func (worker *NamespaceWorker) enqueueIngsForTLSSecret(
}
func (worker *NamespaceWorker) getDplaneSecret() (string, []byte, error) {
secrets, err := worker.vsecr.List(varnishIngressSelector)
secrets, err := worker.vsecr.List(vikingAdmSecretSelector)
if err != nil {
return "", nil, err
}
......@@ -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)
}
app, ok := secret.Labels[labelKey]
if !ok || app != labelVal {
worker.log.Infof("Not a Varnish secret: %s/%s",
if isPem, err := isPemSecret(secret); err != nil {
return err
} else if isPem {
worker.log.Infof("PEM Secret %s/%s: no sync necessary",
secret.Namespace, secret.Name)
syncCounters.WithLabelValues(worker.namespace, "Secret",
"Ignore").Inc()
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)
if err != nil {
return err
......@@ -307,7 +360,7 @@ func (worker *NamespaceWorker) syncSecret(key string) error {
if len(svcs) == 0 {
worker.log.Infof("No Varnish services with admin secret: %s/%s",
secret.Namespace, secret.Name)
return worker.updateVcfgsForSecret(secret.Name)
return nil
}
err = worker.setSecret(secret)
......@@ -333,12 +386,38 @@ func (worker *NamespaceWorker) deleteSecret(obj interface{}) error {
return nil
}
if secr.Type == tlsSecretType {
if secr.Type == api_v1.SecretTypeTLS {
worker.log.Infof("Deleting TLS Secret: %s/%s", secr.Namespace,
secr.Name)
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)
svcs, err := worker.getVarnishSvcsForSecret(secr.Name)
if err != nil {
......@@ -349,7 +428,7 @@ func (worker *NamespaceWorker) deleteSecret(obj interface{}) error {
if len(svcs) == 0 {
worker.log.Infof("No Varnish services with admin secret: %s/%s",
secr.Namespace, secr.Name)
return worker.updateVcfgsForSecret(secr.Name)
return nil
}
secretKey := secr.Namespace + "/" + secr.Name
......
......@@ -43,6 +43,7 @@ import (
const (
labelKey = "app"
labelVal = "varnish-ingress"
vikingLabelPfx = "viking.uplex.de/"
)
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