diff --git a/cluster/juju/layers/kubeapi-load-balancer/config.yaml b/cluster/juju/layers/kubeapi-load-balancer/config.yaml index ad33ef60adc..a4678ae02f3 100644 --- a/cluster/juju/layers/kubeapi-load-balancer/config.yaml +++ b/cluster/juju/layers/kubeapi-load-balancer/config.yaml @@ -3,3 +3,9 @@ options: type: int default: 443 description: The port to run the loadbalancer + extra_sans: + type: string + default: "" + description: | + Space-separated list of extra SAN entries to add to the x509 certificate + created for the load balancers. diff --git a/cluster/juju/layers/kubeapi-load-balancer/reactive/load_balancer.py b/cluster/juju/layers/kubeapi-load-balancer/reactive/load_balancer.py index 8ed601e3cd3..bd4a2bbb9d6 100644 --- a/cluster/juju/layers/kubeapi-load-balancer/reactive/load_balancer.py +++ b/cluster/juju/layers/kubeapi-load-balancer/reactive/load_balancer.py @@ -22,7 +22,9 @@ from charms import layer from charms.reactive import when, when_any, when_not from charms.reactive import set_state, remove_state from charmhelpers.core import hookenv +from charmhelpers.core import host from charmhelpers.contrib.charmsupport import nrpe +from charms.reactive.helpers import data_changed from charms.layer import nginx @@ -44,12 +46,36 @@ def request_server_certificates(tls): hookenv.unit_private_ip(), socket.gethostname(), ] + # maybe they have extra names they want as SANs + extra_sans = hookenv.config('extra_sans') + if extra_sans and not extra_sans == "": + sans.extend(extra_sans.split()) # Create a path safe name by removing path characters from the unit name. certificate_name = hookenv.local_unit().replace('/', '_') # Request a server cert with this information. tls.request_server_cert(common_name, sans, certificate_name) +@when('config.changed.extra_sans', 'certificates.available') +def update_certificate(tls): + # Using the config.changed.extra_sans flag to catch changes. + # IP changes will take ~5 minutes or so to propagate, but + # it will update. + request_server_certificates(tls) + + +@when('certificates.server.cert.available', + 'nginx.available', 'tls_client.server.certificate.written') +def kick_nginx(tls): + # we are just going to sighup it, but still want to avoid kicking it + # without need + if data_changed('cert', tls.get_server_cert()): + # certificate changed, so sighup nginx + hookenv.log("Certificate information changed, sending SIGHUP to nginx") + host.service_restart('nginx') + remove_state('tls_client.server.certificate.written') + + @when('config.changed.port') def close_old_port(): config = hookenv.config() diff --git a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py index 1b5b83967ab..87cd4f4b3a9 100644 --- a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py +++ b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py @@ -469,17 +469,17 @@ def send_data(tls): tls.request_server_cert(common_name, sans, certificate_name) -@when('config.changed', 'certificates.available') +@when('config.changed.extra_sans', 'certificates.available') def update_certificate(tls): - # I using the config.changed flag instead of something more - # specific to try and catch ip changes. Being a little - # spammy here is ok because the cert layer checks for - # changes to the cert before issuing a new one + # Using the config.changed.extra_sans flag to catch changes. + # IP changes will take ~5 minutes or so to propagate, but + # it will update. send_data(tls) @when('certificates.server.cert.available', - 'kubernetes-master.components.started') + 'kubernetes-master.components.started', + 'tls_client.server.certificate.written') def kick_api_server(tls): # need to be idempotent and don't want to kick the api server # without need @@ -487,6 +487,7 @@ def kick_api_server(tls): # certificate changed, so restart the api server hookenv.log("Certificate information changed, restarting api server") set_state('kube-apiserver.do-restart') + remove_state('tls_client.server.certificate.written') @when('kubernetes-master.components.started')