diff options
author | Simo Sorce <simo@redhat.com> | 2015-10-13 15:38:42 -0400 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2015-11-11 11:37:15 -0500 |
commit | 0abd2a6c4ac66b905430d3cad95c1b2a23bda40f (patch) | |
tree | 07d779127331e3e7b4dc8fa03ecc181845a3ff29 | |
parent | d944441d2a6d0c8619e61ba7ceff16d6b147a76b (diff) | |
download | custodia-0abd2a6c4ac66b905430d3cad95c1b2a23bda40f.tar.gz custodia-0abd2a6c4ac66b905430d3cad95c1b2a23bda40f.tar.xz custodia-0abd2a6c4ac66b905430d3cad95c1b2a23bda40f.zip |
Add Authentication module for Kubernetes node
This authentication module connects to docker to figure out the pod
name associated to the PID requesting the service by ay of discovering
the container id via the process cgroup namespace.
The pod name as set in the metadata label named 'io.kubernetes.pod.name'
is then used as the 'remote_user' attribute on the request.
Signed-off-by: Simo Sorce <simo@redhat.com>
-rw-r--r-- | custodia/kubernetes/__init__.py | 0 | ||||
-rw-r--r-- | custodia/kubernetes/node.py | 73 | ||||
-rwxr-xr-x | setup.py | 2 |
3 files changed, 74 insertions, 1 deletions
diff --git a/custodia/kubernetes/__init__.py b/custodia/kubernetes/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/custodia/kubernetes/__init__.py diff --git a/custodia/kubernetes/node.py b/custodia/kubernetes/node.py new file mode 100644 index 0000000..5d4f863 --- /dev/null +++ b/custodia/kubernetes/node.py @@ -0,0 +1,73 @@ +# Copyright (C) 2015 Custodia Project Contributors - see LICENSE file + +import re + +from docker import Client + +from custodia import log +from custodia.httpd.authenticators import HTTPAuthenticator + +DEFAULT_REGEX = r'/docker-([0-9a-f]{64})\.scope' +DEFUALT_DOCKER_URI = 'unix://var/run/docker.sock' + + +class NodeAuth(HTTPAuthenticator): + + def __init__(self, config=None): + super(NodeAuth, self).__init__(config) + if self.config is not None: + regex = self.config.get('docker_regex', DEFAULT_REGEX) + self.docker_uri = self.config.get('docker_uri', DEFUALT_DOCKER_URI) + else: + regex = DEFAULT_REGEX + self.docker_uri = DEFUALT_DOCKER_URI + self.id_filter = re.compile(regex) + + def _pid2dockerid(self, pid): + with open('/proc/%i/cgroup' % pid) as f: + for line in f: + mo = self.id_filter.search(line) + if mo is not None: + return mo.group(1) + return None + + def handle(self, request): + creds = request.get('creds') + if creds is None: + self.logger.debug('Missing "creds" on request') + return None + dockerid = self._pid2dockerid(int(creds['pid'])) + if dockerid is None: + self.logger.debug("Didn't find docker ID for pid %s", creds['pid']) + return None + + try: + dc = Client(base_url=self.docker_uri) + data = dc.inspect_container(dockerid) + data_id = data['Id'] + data_labels = dict(data['Config']['Labels']) + except Exception as err: # pylint: disable=broad-except + self.logger.debug("Failed to query docker for [%s:%s]: %s", + creds['pid'], dockerid, err) + self.audit_svc_access(log.AUDIT_SVC_AUTH_FAIL, + request['client_id'], dockerid) + return False + + if data_id != dockerid: + self.logger.debug("Docker ID %s not found!", dockerid) + self.audit_svc_access(log.AUDIT_SVC_AUTH_FAIL, + request['client_id'], dockerid) + return False + + podname = data_labels.get('io.kubernetes.pod.name') + if podname is None: + self.logger.debug("Pod Name not found for Docker ID %s", dockerid) + self.audit_svc_access(log.AUDIT_SVC_AUTH_FAIL, + request['client_id'], dockerid) + return False + + self.audit_svc_access(log.AUDIT_SVC_AUTH_PASS, + request['client_id'], dockerid) + request['client_id'] = dockerid + request['remote_user'] = podname + return True @@ -12,7 +12,7 @@ setup( maintainer_email='simo@redhat.com', url='https://github.com/simo5/custodia', packages=['custodia', 'custodia.httpd', 'custodia.store', - 'custodia.message'], + 'custodia.message', 'custodia.kubernetes'], data_files=[('share/man/man7', ["man/custodia.7"]), ('share/doc/custodia', ['LICENSE', 'README', 'API.md']), ('share/doc/custodia/examples', ['custodia.conf']), |