Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.2:Staging:F
python-kubernetes
base64-padding-fix.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File base64-padding-fix.patch of Package python-kubernetes
From 9029dd735bdb3c2c5870925f69a7897b2b27dbd1 Mon Sep 17 00:00:00 2001 From: Can Bulut Bayburt <cbbayburt@suse.com> Date: Wed, 2 Oct 2019 12:28:04 +0200 Subject: [PATCH] Backport base64 padding fix --- config/kube_config.py | 21 ++++++++-- config/kube_config_test.py | 101 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 114 insertions(+), 8 deletions(-) diff --git kubernetes/config/kube_config.py kubernetes/config/kube_config.py index 958959e..019c947 100644 --- kubernetes/config/kube_config.py +++ kubernetes/config/kube_config.py @@ -259,18 +259,31 @@ class KubeConfigLoader(object): if 'config' not in provider: return - parts = provider['config']['id-token'].split('.') + reserved_characters = frozenset(["=", "+", "/"]) + token = provider['config']['id-token'] + if any(char in token for char in reserved_characters): + # Invalid jwt, as it contains url-unsafe chars + return + + parts = token.split('.') if len(parts) != 3: # Not a valid JWT - return None + return + + padding = (4 - len(parts[1]) % 4) * '=' + if len(padding) == 3: + # According to spec, 3 padding characters cannot occur + # in a valid jwt + # https://tools.ietf.org/html/rfc7515#appendix-C + return if PY3: jwt_attributes = json.loads( - base64.b64decode(parts[1]).decode('utf-8') + base64.b64decode(parts[1] + padding).decode('utf-8') ) else: jwt_attributes = json.loads( - base64.b64decode(parts[1] + "==") + base64.b64decode(parts[1] + padding) ) expire = jwt_attributes.get('exp') diff --git kubernetes/config/kube_config_test.py kubernetes/config/kube_config_test.py index ae9dc22..0deec79 100644 --- kubernetes/config/kube_config_test.py +++ kubernetes/config/kube_config_test.py @@ -47,6 +47,10 @@ def _base64(string): return base64.standard_b64encode(string.encode()).decode() +def _urlsafe_unpadded_b64encode(string): + return base64.urlsafe_b64encode(string.encode()).decode().rstrip('=') + + def _format_expiry_datetime(dt): return dt.strftime(EXPIRY_DATETIME_FORMAT) @@ -94,12 +98,33 @@ TEST_CLIENT_CERT_BASE64 = _base64(TEST_CLIENT_CERT) TEST_OIDC_TOKEN = "test-oidc-token" TEST_OIDC_INFO = "{\"name\": \"test\"}" -TEST_OIDC_BASE = _base64(TEST_OIDC_TOKEN) + "." + _base64(TEST_OIDC_INFO) -TEST_OIDC_LOGIN = TEST_OIDC_BASE + "." + TEST_CLIENT_CERT_BASE64 +TEST_OIDC_BASE = ".".join([ + _urlsafe_unpadded_b64encode(TEST_OIDC_TOKEN), + _urlsafe_unpadded_b64encode(TEST_OIDC_INFO) +]) +TEST_OIDC_LOGIN = ".".join([ + TEST_OIDC_BASE, + _urlsafe_unpadded_b64encode(TEST_CLIENT_CERT_BASE64) +]) TEST_OIDC_TOKEN = "Bearer %s" % TEST_OIDC_LOGIN TEST_OIDC_EXP = "{\"name\": \"test\",\"exp\": 536457600}" -TEST_OIDC_EXP_BASE = _base64(TEST_OIDC_TOKEN) + "." + _base64(TEST_OIDC_EXP) -TEST_OIDC_EXPIRED_LOGIN = TEST_OIDC_EXP_BASE + "." + TEST_CLIENT_CERT_BASE64 +TEST_OIDC_EXP_BASE = _urlsafe_unpadded_b64encode( + TEST_OIDC_TOKEN) + "." + _urlsafe_unpadded_b64encode(TEST_OIDC_EXP) +TEST_OIDC_EXPIRED_LOGIN = ".".join([ + TEST_OIDC_EXP_BASE, + _urlsafe_unpadded_b64encode(TEST_CLIENT_CERT) +]) +TEST_OIDC_CONTAINS_RESERVED_CHARACTERS = ".".join([ + _urlsafe_unpadded_b64encode(TEST_OIDC_TOKEN), + _urlsafe_unpadded_b64encode(TEST_OIDC_INFO).replace("a", "+"), + _urlsafe_unpadded_b64encode(TEST_CLIENT_CERT) +]) +TEST_OIDC_INVALID_PADDING_LENGTH = ".".join([ + _urlsafe_unpadded_b64encode(TEST_OIDC_TOKEN), + "aaaaa", + _urlsafe_unpadded_b64encode(TEST_CLIENT_CERT) +]) + TEST_OIDC_CA = _base64(TEST_CERTIFICATE_AUTH) @@ -406,6 +431,22 @@ class TestKubeConfigLoader(BaseTestCase): "user": "expired_oidc_nocert" } }, + { + "name": "oidc_contains_reserved_character", + "context": { + "cluster": "default", + "user": "oidc_contains_reserved_character" + + } + }, + { + "name": "oidc_invalid_padding_length", + "context": { + "cluster": "default", + "user": "oidc_invalid_padding_length" + + } + }, { "name": "user_pass", "context": { @@ -592,6 +633,38 @@ class TestKubeConfigLoader(BaseTestCase): } } }, + { + "name": "oidc_contains_reserved_character", + "user": { + "auth-provider": { + "name": "oidc", + "config": { + "client-id": "tectonic-kubectl", + "client-secret": "FAKE_SECRET", + "id-token": TEST_OIDC_CONTAINS_RESERVED_CHARACTERS, + "idp-issuer-url": "https://example.org/identity", + "refresh-token": + "lucWJjEhlxZW01cXI3YmVlcYnpxNGhzk" + } + } + } + }, + { + "name": "oidc_invalid_padding_length", + "user": { + "auth-provider": { + "name": "oidc", + "config": { + "client-id": "tectonic-kubectl", + "client-secret": "FAKE_SECRET", + "id-token": TEST_OIDC_INVALID_PADDING_LENGTH, + "idp-issuer-url": "https://example.org/identity", + "refresh-token": + "lucWJjEhlxZW01cXI3YmVlcYnpxNGhzk" + } + } + } + }, { "name": "user_pass", "user": { @@ -790,6 +863,26 @@ class TestKubeConfigLoader(BaseTestCase): self.assertTrue(loader._load_auth_provider_token()) self.assertEqual("Bearer abc123", loader.token) + def test_oidc_fails_if_contains_reserved_chars(self): + loader = KubeConfigLoader( + config_dict=self.TEST_KUBE_CONFIG, + active_context="oidc_contains_reserved_character", + ) + self.assertEqual( + loader._load_oid_token("oidc_contains_reserved_character"), + None, + ) + + def test_oidc_fails_if_invalid_padding_length(self): + loader = KubeConfigLoader( + config_dict=self.TEST_KUBE_CONFIG, + active_context="oidc_invalid_padding_length", + ) + self.assertEqual( + loader._load_oid_token("oidc_invalid_padding_length"), + None, + ) + def test_user_pass(self): expected = FakeConfig(host=TEST_HOST, token=TEST_BASIC_TOKEN) actual = FakeConfig() -- 2.16.4
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor