prod{access,vider}: implement
Prodaccess/Prodvider allow issuing short-lived certificates for all SSO
users to access the kubernetes cluster.
Currently, all users get a personal-$username namespace in which they
have adminitrative rights. Otherwise, they get no access.
In addition, we define a static CRB to allow some admins access to
everything. In the future, this will be more granular.
We also update relevant documentation.
Change-Id: Ia18594eea8a9e5efbb3e9a25a04a28bbd6a42153
diff --git a/cluster/clustercfg/ca.py b/cluster/clustercfg/ca.py
index 4d359c7..9ed2053 100644
--- a/cluster/clustercfg/ca.py
+++ b/cluster/clustercfg/ca.py
@@ -4,6 +4,7 @@
import os
from six import StringIO
import subprocess
+import tempfile
logger = logging.getLogger(__name__)
@@ -32,6 +33,20 @@
"expiry": "168h"
},
"profiles": {
+ "intermediate": {
+ "expiry": "8760h",
+ "usages": [
+ "signing",
+ "key encipherment",
+ "cert sign",
+ "crl sign",
+ "server auth",
+ "client auth",
+ ],
+ "ca_constraint": {
+ "is_ca": True,
+ },
+ },
"server": {
"expiry": "8760h",
"usages": [
@@ -156,12 +171,17 @@
return key, csr
- def sign(self, csr, save=None):
+ def sign(self, csr, save=None, profile='client-server'):
logging.info("{}: Signing CSR".format(self))
ca = self._cert
cakey = self.ss.plaintext(self._secret_key)
+
+ config = tempfile.NamedTemporaryFile(mode='w')
+ json.dump(_ca_config, config)
+ config.flush()
+
out = self._cfssl_call(['sign', '-ca=' + ca, '-ca-key=' + cakey,
- '-profile=client-server', '-'], stdin=csr)
+ '-profile='+profile, '-config='+config.name, '-'], stdin=csr)
cert = out['cert']
if save is not None:
name = os.path.join(self.cdir, save)
@@ -170,6 +190,7 @@
f.write(cert)
f.close()
+ config.close()
return cert
def upload(self, c, remote_cert):
@@ -181,7 +202,7 @@
class ManagedCertificate(object):
- def __init__(self, ca, name, hosts, o=None, ou=None):
+ def __init__(self, ca, name, hosts, o=None, ou=None, profile='client-server'):
self.ca = ca
self.hosts = hosts
@@ -190,6 +211,7 @@
self.cert = '{}.cert'.format(name)
self.o = o
self.ou = ou
+ self.profile = profile
self.ensure()
@@ -230,7 +252,7 @@
logger.info("{}: Generating...".format(self))
key, csr = self.ca.gen_key(self.hosts, o=self.o, ou=self.ou, save=self.key)
- self.ca.sign(csr, save=self.cert)
+ self.ca.sign(csr, save=self.cert, profile=self.profile)
def upload(self, c, remote_cert, remote_key, concat_ca=False):
logger.info("Uploading Cert {} to {} & {}".format(self, remote_cert, remote_key))
diff --git a/cluster/clustercfg/clustercfg.py b/cluster/clustercfg/clustercfg.py
index 24fa745..b6d790b 100644
--- a/cluster/clustercfg/clustercfg.py
+++ b/cluster/clustercfg/clustercfg.py
@@ -57,7 +57,7 @@
def configure_k8s(username, ca, cert, key):
subprocess.check_call([
'kubectl', 'config',
- 'set-cluster', cluster,
+ 'set-cluster', 'admin.' + cluster,
'--certificate-authority=' + ca,
'--embed-certs=true',
'--server=https://' + cluster + ':4001',
@@ -71,13 +71,13 @@
])
subprocess.check_call([
'kubectl', 'config',
- 'set-context', cluster,
- '--cluster=' + cluster,
+ 'set-context', 'admin.' + cluster,
+ '--cluster=' + 'admin.' + cluster,
'--user=' + username,
])
subprocess.check_call([
'kubectl', 'config',
- 'use-context', cluster,
+ 'use-context', 'admin.' + cluster,
])
@@ -86,6 +86,18 @@
sys.stderr.write("Usage: admincreds q3k\n")
return 1
username = args[0]
+ print("")
+ print("WARNING WARNING WARNING WARNING WARNING WARNING")
+ print("===============================================")
+ print("")
+ print("You are requesting ADMIN credentials.")
+ print("")
+ print("You likely shouldn't be doing this, and")
+ print("instead should be using `prodaccess`.")
+ print("")
+ print("===============================================")
+ print("WARNING WARNING WARNING WARNING WARNING WARNING")
+ print("")
## Make kube certificates.
certs_root = os.path.join(local_root, 'cluster/certs')
@@ -169,6 +181,10 @@
## Make kube certificates.
ca_kube = ca.CA(ss, certs_root, 'kube', 'kubernetes main CA')
+ # Make prodvider intermediate CA.
+ c = ca_kube.make_cert('ca-kube-prodvider', o='Warsaw Hackerspace', ou='kubernetes prodvider intermediate', hosts=['kubernetes prodvider intermediate CA'], profile='intermediate')
+ c.ensure()
+
# Make kubelet certificate (per node).
c = ca_kube.make_cert('kube-kubelet-'+fqdn, o='system:nodes', ou='Kubelet', hosts=['system:node:'+fqdn, fqdn])
c.upload_pki(r, pki_config('kube.kubelet'))