From 89319c641f015409a58261e5dd9e70a7ce6bd514 Mon Sep 17 00:00:00 2001 From: Tim Waugh Date: Mon, 7 Sep 2015 12:58:28 +0100 Subject: [PATCH] Use service account token for authentication (fixes #237) --- osbs/core.py | 32 +++++++++++++++++++++++++++++++- osbs/http.py | 6 +++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/osbs/core.py b/osbs/core.py index 4784859cd..cdd5c3b0a 100755 --- a/osbs/core.py +++ b/osbs/core.py @@ -7,6 +7,7 @@ """ from __future__ import print_function, unicode_literals, absolute_import import json +import os import logging from osbs.kerberos_ccache import kerberos_ccache_init @@ -32,6 +33,11 @@ logger = logging.getLogger(__name__) +# How to authenticate from within a pod +SERVICEACCOUNT_SECRET = "/var/run/secrets/kubernetes.io/serviceaccount" +SERVICEACCOUNT_TOKEN = "token" +SERVICEACCOUNT_CACRT = "ca.crt" + def check_response(response): if response.status_code not in (httplib.OK, httplib.CREATED): @@ -66,11 +72,31 @@ def __init__(self, openshift_api_url, openshift_api_version, openshift_oauth_url self.kerberos_keytab = kerberos_keytab self.kerberos_principal = kerberos_principal self.kerberos_ccache = kerberos_ccache + self.token = None + self.ca = None if use_auth is None: self.use_auth = bool(use_kerberos or (username and password)) + if not self.use_auth: + # Are we running inside a pod? If so, we will have a + # token available which can be used for authentication + try: + with open(os.path.join(SERVICEACCOUNT_SECRET, + SERVICEACCOUNT_TOKEN), + mode='rt') as tfp: + self.token = tfp.read().rstrip() + + ca = os.path.join(SERVICEACCOUNT_SECRET, + SERVICEACCOUNT_CACRT) + if os.access(ca, os.R_OK): + self.ca = ca + except IOError: + # No token available + pass + else: + # We can authenticate using the supplied token + self.use_auth = True else: self.use_auth = use_auth - self.token = None @property def os_oauth_url(self): @@ -103,6 +129,10 @@ def _request_args(self, with_auth=True, **kwargs): else: raise OsbsAuthException("You need to provide both client certificate and key.") + # Do we have a ca.crt? If so, use it + if self.verify_ssl and self.ca is not None: + kwargs["ca"] = self.ca + return headers, kwargs def _post(self, url, with_auth=True, **kwargs): diff --git a/osbs/http.py b/osbs/http.py index ebbc2ed43..8836ad03d 100644 --- a/osbs/http.py +++ b/osbs/http.py @@ -152,7 +152,7 @@ class HttpStream(object): """ def __init__(self, url, method, data=None, kerberos_auth=False, - allow_redirects=True, verify_ssl=True, use_json=False, + allow_redirects=True, verify_ssl=True, ca=None, use_json=False, headers=None, stream=False, username=None, password=None, client_cert=None, client_key=None, verbose=False): self.finished = False # have we read all data? @@ -192,6 +192,10 @@ def __init__(self, url, method, data=None, kerberos_auth=False, self.c.setopt(pycurl.DEBUGFUNCTION, self._curl_debug) self.c.setopt(pycurl.SSL_VERIFYPEER, 1 if verify_ssl else 0) self.c.setopt(pycurl.SSL_VERIFYHOST, 2 if verify_ssl else 0) + if ca: + logger.info("Setting CAINFO to %r", ca) + self.c.setopt(pycurl.CAINFO, ca) + self.c.setopt(pycurl.VERBOSE, 1 if verbose else 0) if username and password: username = username.encode('utf-8')