summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorBazaah2024-03-16 17:41:30 +0000
committerBazaah2024-03-23 10:30:33 +0000
commit836304d4d7a8ab4741e2497cc9a40671cb5044a3 (patch)
treeb792fce6449af69289d3ad3b6e160558a722ce0a
parentbfe55db9e8ccdcc304ffc992e5a585cd9fb2e80f (diff)
downloadaur-836304d4d7a8ab4741e2497cc9a40671cb5044a3.tar.gz
repo: backport mgr/dashboard fix for python-cryptography issues
Removes the (limited) runtime usages of python-jwt, and therefore, python-cryptography from the mgr dashboard module. This should restore dashboard functionality, if used alongside a patched pyo3 for python-bcrypt. Upstream-Ref: https://github.com/ceph/ceph/commit/33d8befcabe3e60d9ccf6e4fdc2598c4db22934b References: https://github.com/ceph/ceph/pull/55689 References: https://tracker.ceph.com/issues/63529 References: https://github.com/bazaah/aur-ceph/issues/20 References: https://git.st8l.com/luxolus/pyo3/commit/44d6919168621b46e4e884130ca43338655b020c
-rw-r--r--ceph-18.2.2-backport-mgr-dashboard-simplify-authentication-protocol.patch323
1 files changed, 323 insertions, 0 deletions
diff --git a/ceph-18.2.2-backport-mgr-dashboard-simplify-authentication-protocol.patch b/ceph-18.2.2-backport-mgr-dashboard-simplify-authentication-protocol.patch
new file mode 100644
index 000000000000..2f398465c887
--- /dev/null
+++ b/ceph-18.2.2-backport-mgr-dashboard-simplify-authentication-protocol.patch
@@ -0,0 +1,323 @@
+From fcbd8fdae9d80d9a9bd61838aeaf41b504a5888a Mon Sep 17 00:00:00 2001
+From: Daniel Persson <mailto.woden@gmail.com>
+Date: Wed, 29 Nov 2023 09:39:51 +0000
+Subject: [PATCH 1/3] mgr/dashboard: Simplify authentication protocol By
+ removing the dependency to PyJWT we also remove the dependency to the
+ cryptographic library which in the dashboard module will create a crash. In
+ newer implementations of the library PyO3 is used to run rust code in order
+ to encrypt with Elliptic Curves. This is never used in the dashboard
+ communication so a much simpler implementation where we only use the hmac
+ sha256 algorithm to create the signed JWT message could be used.
+
+Fixes: https://forum.proxmox.com/threads/ceph-warning-post-upgrade-to-v8.129371
+Signed-off-by: Daniel Persson <mailto.woden@gmail.com>
+(cherry picked from commit c616a9d017b5fcc85bb5c1556bccf4c77cc3899e)
+---
+ src/pybind/mgr/dashboard/constraints.txt | 1 -
+ src/pybind/mgr/dashboard/exceptions.py | 12 ++++
+ src/pybind/mgr/dashboard/requirements.txt | 1 -
+ src/pybind/mgr/dashboard/services/auth.py | 70 ++++++++++++++++++++---
+ src/pybind/mgr/dashboard/tox.ini | 1 +
+ 5 files changed, 74 insertions(+), 11 deletions(-)
+
+diff --git a/src/pybind/mgr/dashboard/constraints.txt b/src/pybind/mgr/dashboard/constraints.txt
+index 55f81c92dec06..fd6141048800a 100644
+--- a/src/pybind/mgr/dashboard/constraints.txt
++++ b/src/pybind/mgr/dashboard/constraints.txt
+@@ -1,6 +1,5 @@
+ CherryPy~=13.1
+ more-itertools~=8.14
+-PyJWT~=2.0
+ bcrypt~=3.1
+ python3-saml~=1.4
+ requests~=2.26
+diff --git a/src/pybind/mgr/dashboard/exceptions.py b/src/pybind/mgr/dashboard/exceptions.py
+index 96cbc52335613..d396a38d2c3a2 100644
+--- a/src/pybind/mgr/dashboard/exceptions.py
++++ b/src/pybind/mgr/dashboard/exceptions.py
+@@ -121,3 +121,15 @@ class GrafanaError(Exception):
+
+ class PasswordPolicyException(Exception):
+ pass
++
++
++class ExpiredSignatureError(Exception):
++ pass
++
++
++class InvalidTokenError(Exception):
++ pass
++
++
++class InvalidAlgorithmError(Exception):
++ pass
+diff --git a/src/pybind/mgr/dashboard/requirements.txt b/src/pybind/mgr/dashboard/requirements.txt
+index 8003d62a5523f..292971819c9c6 100644
+--- a/src/pybind/mgr/dashboard/requirements.txt
++++ b/src/pybind/mgr/dashboard/requirements.txt
+@@ -1,7 +1,6 @@
+ bcrypt
+ CherryPy
+ more-itertools
+-PyJWT
+ pyopenssl
+ requests
+ Routes
+diff --git a/src/pybind/mgr/dashboard/services/auth.py b/src/pybind/mgr/dashboard/services/auth.py
+index f13963abffdd4..3c6002312524d 100644
+--- a/src/pybind/mgr/dashboard/services/auth.py
++++ b/src/pybind/mgr/dashboard/services/auth.py
+@@ -1,17 +1,19 @@
+ # -*- coding: utf-8 -*-
+
++import base64
++import hashlib
++import hmac
+ import json
+ import logging
+ import os
+ import threading
+ import time
+ import uuid
+-from base64 import b64encode
+
+ import cherrypy
+-import jwt
+
+ from .. import mgr
++from ..exceptions import ExpiredSignatureError, InvalidAlgorithmError, InvalidTokenError
+ from .access_control import LocalAuthenticator, UserDoesNotExist
+
+ cherrypy.config.update({
+@@ -33,7 +35,7 @@ class JwtManager(object):
+ @staticmethod
+ def _gen_secret():
+ secret = os.urandom(16)
+- return b64encode(secret).decode('utf-8')
++ return base64.b64encode(secret).decode('utf-8')
+
+ @classmethod
+ def init(cls):
+@@ -45,6 +47,54 @@ def init(cls):
+ mgr.set_store('jwt_secret', secret)
+ cls._secret = secret
+
++ @classmethod
++ def array_to_base64_string(cls, message):
++ jsonstr = json.dumps(message, sort_keys=True).replace(" ", "")
++ string_bytes = base64.urlsafe_b64encode(bytes(jsonstr, 'UTF-8'))
++ return string_bytes.decode('UTF-8').replace("=", "")
++
++ @classmethod
++ def encode(cls, message, secret):
++ header = {"alg": cls.JWT_ALGORITHM, "typ": "JWT"}
++ base64_header = cls.array_to_base64_string(header)
++ base64_message = cls.array_to_base64_string(message)
++ base64_secret = base64.urlsafe_b64encode(hmac.new(
++ bytes(secret, 'UTF-8'),
++ msg=bytes(base64_header + "." + base64_message, 'UTF-8'),
++ digestmod=hashlib.sha256
++ ).digest()).decode('UTF-8').replace("=", "")
++ return base64_header + "." + base64_message + "." + base64_secret
++
++ @classmethod
++ def decode(cls, message, secret):
++ split_message = message.split(".")
++ base64_header = split_message[0]
++ base64_message = split_message[1]
++ base64_secret = split_message[2]
++
++ decoded_header = json.loads(base64.urlsafe_b64decode(base64_header))
++
++ if decoded_header['alg'] != cls.JWT_ALGORITHM:
++ raise InvalidAlgorithmError()
++
++ incoming_secret = base64.urlsafe_b64encode(hmac.new(
++ bytes(secret, 'UTF-8'),
++ msg=bytes(base64_header + "." + base64_message, 'UTF-8'),
++ digestmod=hashlib.sha256
++ ).digest()).decode('UTF-8').replace("=", "")
++
++ if base64_secret != incoming_secret:
++ raise InvalidTokenError()
++
++ # We add ==== as padding to ignore the requirement to have correct padding in
++ # the urlsafe_b64decode method.
++ decoded_message = json.loads(base64.urlsafe_b64decode(base64_message + "===="))
++ now = int(time.time())
++ if decoded_message['exp'] < now:
++ raise ExpiredSignatureError()
++
++ return decoded_message
++
+ @classmethod
+ def gen_token(cls, username):
+ if not cls._secret:
+@@ -59,13 +109,13 @@ def gen_token(cls, username):
+ 'iat': now,
+ 'username': username
+ }
+- return jwt.encode(payload, cls._secret, algorithm=cls.JWT_ALGORITHM) # type: ignore
++ return cls.encode(payload, cls._secret) # type: ignore
+
+ @classmethod
+ def decode_token(cls, token):
+ if not cls._secret:
+ cls.init()
+- return jwt.decode(token, cls._secret, algorithms=cls.JWT_ALGORITHM) # type: ignore
++ return cls.decode(token, cls._secret) # type: ignore
+
+ @classmethod
+ def get_token_from_header(cls):
+@@ -99,8 +149,8 @@ def get_username(cls):
+ @classmethod
+ def get_user(cls, token):
+ try:
+- dtoken = JwtManager.decode_token(token)
+- if not JwtManager.is_blocklisted(dtoken['jti']):
++ dtoken = cls.decode_token(token)
++ if not cls.is_blocklisted(dtoken['jti']):
+ user = AuthManager.get_user(dtoken['username'])
+ if user.last_update <= dtoken['iat']:
+ return user
+@@ -110,10 +160,12 @@ def get_user(cls, token):
+ )
+ else:
+ cls.logger.debug('Token is block-listed') # type: ignore
+- except jwt.ExpiredSignatureError:
++ except ExpiredSignatureError:
+ cls.logger.debug("Token has expired") # type: ignore
+- except jwt.InvalidTokenError:
++ except InvalidTokenError:
+ cls.logger.debug("Failed to decode token") # type: ignore
++ except InvalidAlgorithmError:
++ cls.logger.debug("Only the HS256 algorithm is supported.") # type: ignore
+ except UserDoesNotExist:
+ cls.logger.debug( # type: ignore
+ "Invalid token: user %s does not exist", dtoken['username']
+diff --git a/src/pybind/mgr/dashboard/tox.ini b/src/pybind/mgr/dashboard/tox.ini
+index 47756e946e125..271df286ec5e8 100644
+--- a/src/pybind/mgr/dashboard/tox.ini
++++ b/src/pybind/mgr/dashboard/tox.ini
+@@ -20,6 +20,7 @@ addopts =
+ deps =
+ -rrequirements.txt
+ -cconstraints.txt
++ PyJWT
+
+ [base-test]
+ deps =
+
+From d456590743aa26d7d253b20294f5aa33544ab8a7 Mon Sep 17 00:00:00 2001
+From: Daniel Persson <mailto.woden@gmail.com>
+Date: Sun, 3 Dec 2023 08:03:47 +0000
+Subject: [PATCH 2/3] mgr/dashboard: Changes suggested after review by
+ @epuertat.
+
+Move the JWT requirement to the test requirements file. Also remove JWT from ceph specification and debian build.
+
+Signed-off-by: Daniel Persson <mailto.woden@gmail.com>
+(cherry picked from commit c1ea66fe12f86e7a63681cba860fb91b1ea86e12)
+---
+ ceph.spec.in | 4 ----
+ debian/control | 1 -
+ src/pybind/mgr/dashboard/requirements-test.txt | 1 +
+ src/pybind/mgr/dashboard/tox.ini | 1 -
+ 4 files changed, 1 insertion(+), 6 deletions(-)
+
+diff --git a/ceph.spec.in b/ceph.spec.in
+index ff8aa5aafbff8..c4281abc5bfbb 100644
+--- a/ceph.spec.in
++++ b/ceph.spec.in
+@@ -412,7 +412,6 @@ BuildRequires: xmlsec1-nss
+ BuildRequires: xmlsec1-openssl
+ BuildRequires: xmlsec1-openssl-devel
+ BuildRequires: python%{python3_pkgversion}-cherrypy
+-BuildRequires: python%{python3_pkgversion}-jwt
+ BuildRequires: python%{python3_pkgversion}-routes
+ BuildRequires: python%{python3_pkgversion}-scipy
+ BuildRequires: python%{python3_pkgversion}-werkzeug
+@@ -425,7 +424,6 @@ BuildRequires: libxmlsec1-1
+ BuildRequires: libxmlsec1-nss1
+ BuildRequires: libxmlsec1-openssl1
+ BuildRequires: python%{python3_pkgversion}-CherryPy
+-BuildRequires: python%{python3_pkgversion}-PyJWT
+ BuildRequires: python%{python3_pkgversion}-Routes
+ BuildRequires: python%{python3_pkgversion}-Werkzeug
+ BuildRequires: python%{python3_pkgversion}-numpy-devel
+@@ -617,7 +615,6 @@ Requires: ceph-prometheus-alerts = %{_epoch_prefix}%{version}-%{release}
+ Requires: python%{python3_pkgversion}-setuptools
+ %if 0%{?fedora} || 0%{?rhel}
+ Requires: python%{python3_pkgversion}-cherrypy
+-Requires: python%{python3_pkgversion}-jwt
+ Requires: python%{python3_pkgversion}-routes
+ Requires: python%{python3_pkgversion}-werkzeug
+ %if 0%{?weak_deps}
+@@ -626,7 +623,6 @@ Recommends: python%{python3_pkgversion}-saml
+ %endif
+ %if 0%{?suse_version}
+ Requires: python%{python3_pkgversion}-CherryPy
+-Requires: python%{python3_pkgversion}-PyJWT
+ Requires: python%{python3_pkgversion}-Routes
+ Requires: python%{python3_pkgversion}-Werkzeug
+ Recommends: python%{python3_pkgversion}-python3-saml
+diff --git a/debian/control b/debian/control
+index 837a55a371670..e7b123ec381e7 100644
+--- a/debian/control
++++ b/debian/control
+@@ -91,7 +91,6 @@ Build-Depends: automake,
+ python3-all-dev,
+ python3-cherrypy3,
+ python3-natsort,
+- python3-jwt <pkg.ceph.check>,
+ python3-pecan <pkg.ceph.check>,
+ python3-bcrypt <pkg.ceph.check>,
+ tox <pkg.ceph.check>,
+diff --git a/src/pybind/mgr/dashboard/requirements-test.txt b/src/pybind/mgr/dashboard/requirements-test.txt
+index da283d0b64aaa..aa80b3336b540 100644
+--- a/src/pybind/mgr/dashboard/requirements-test.txt
++++ b/src/pybind/mgr/dashboard/requirements-test.txt
+@@ -2,3 +2,4 @@ pytest-cov
+ pytest-instafail
+ pyfakefs==4.5.0
+-jsonschema
++jsonschema~=4.0
++PyJWT~=2.0
+diff --git a/src/pybind/mgr/dashboard/tox.ini b/src/pybind/mgr/dashboard/tox.ini
+index 271df286ec5e8..47756e946e125 100644
+--- a/src/pybind/mgr/dashboard/tox.ini
++++ b/src/pybind/mgr/dashboard/tox.ini
+@@ -20,7 +20,6 @@ addopts =
+ deps =
+ -rrequirements.txt
+ -cconstraints.txt
+- PyJWT
+
+ [base-test]
+ deps =
+
+From 04b3792228415fa0320eb2e28c60e00fac68d3d8 Mon Sep 17 00:00:00 2001
+From: Daniel Persson <mailto.woden@gmail.com>
+Date: Sun, 3 Dec 2023 09:46:56 +0000
+Subject: [PATCH 3/3] mgr/dashboard: Updated test dependencies
+
+Seemed that the test dependencies was separated in two different requirements files
+one for the testing and one for linting. Added the JWT dependency in the linting file
+as well.
+
+Signed-off-by: Daniel Persson <mailto.woden@gmail.com>
+(cherry picked from commit 06765e648acb1676d5d563c631b8d8fc08b5323c)
+---
+ src/pybind/mgr/dashboard/requirements-lint.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/pybind/mgr/dashboard/requirements-lint.txt b/src/pybind/mgr/dashboard/requirements-lint.txt
+index 57e5191574083..571c92a4ebfbc 100644
+--- a/src/pybind/mgr/dashboard/requirements-lint.txt
++++ b/src/pybind/mgr/dashboard/requirements-lint.txt
+@@ -9,3 +9,4 @@ autopep8==1.5.7
+ pyfakefs==4.5.0
+ isort==5.5.3
+-jsonschema==4.16.0
++jsonschema~=4.0
++PyJWT~=2.0