summaryrefslogtreecommitdiffstats
path: root/custodia/kubernetes/authz.py
diff options
context:
space:
mode:
Diffstat (limited to 'custodia/kubernetes/authz.py')
-rw-r--r--custodia/kubernetes/authz.py66
1 files changed, 66 insertions, 0 deletions
diff --git a/custodia/kubernetes/authz.py b/custodia/kubernetes/authz.py
new file mode 100644
index 0000000..4342f6f
--- /dev/null
+++ b/custodia/kubernetes/authz.py
@@ -0,0 +1,66 @@
+# Copyright (C) 2015 Custodia Project Contributors - see LICENSE file
+
+import requests
+
+from custodia import log
+from custodia.httpd.authorizers import HTTPAuthorizer
+
+DEFAULT_API_SERVER = 'http://localhost:8080'
+
+
+class KubeAuthz(HTTPAuthorizer):
+
+ def __init__(self, config=None):
+ super(KubeAuthz, self).__init__(config)
+ self.path = self.config.get('path', '/nodes')
+ self.secrets = self.config.get('secrets', '/secrets')
+ self.label = self.config.get('secrets_label', 'secrets_namespace')
+ self.server_api = self.config.get('kube_api_server',
+ DEFAULT_API_SERVER)
+
+ def handle(self, request):
+ reqpath = path = request.get('path', '')
+ prefix = path
+
+ while prefix.startswith('/'):
+ if prefix == self.path:
+ break
+ else:
+ prefix, _ = prefix.rsplit('/', 1)
+
+ if prefix != self.path:
+ self.logger.debug("Prefix %s does not match path %s",
+ prefix, reqpath)
+ return None
+
+ trail = path[len(prefix) + 1:]
+
+ (namespace, podname, secret) = trail.split('/', 2)
+ self.logger.debug("Checking if pod %s,%s has access to secret %s",
+ namespace, podname, secret)
+
+ try:
+ r = requests.get('%s/api/v1/namespaces/%s/pods/%s' % (
+ self.server_api, namespace, podname))
+ r.raise_for_status()
+ data = r.json()
+ node_id = data["spec"]["nodeName"]
+ secrets_namespace = data["metadata"]["labels"][self.label]
+ except Exception: # pylint: disable=broad-except
+ self.logger.exception("Failed to fecth data from Kube API Server")
+ self.audit_svc_access(log.AUDIT_SVC_AUTHZ_FAIL,
+ request['client_id'], path)
+ return False
+
+ if node_id != request.get("remote_user"):
+ self.logger.debug("Node authenticated as %s, but pod is believed "
+ "to be running on %s",
+ request.get("remote_user"), node_id)
+ self.audit_svc_access(log.AUDIT_SVC_AUTHZ_FAIL,
+ request['client_id'], path)
+ return False
+
+ request['path'] = '/'.join([self.secrets, secrets_namespace, secret])
+ self.audit_svc_access(log.AUDIT_SVC_AUTHZ_PASS, request['client_id'],
+ "%s -> %s" % (path, request['path']))
+ return True