+++ /dev/null
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Max Carrara <m.carrara@proxmox.com>
-Date: Tue, 2 Jan 2024 13:02:51 +0000
-Subject: [PATCH] backport: mgr/dashboard: simplify authentication protocol
-
-This is a backport of https://github.com/ceph/ceph/pull/54710 which
-fixes the Ceph Dashboard not being able to launch on Ceph Reef running
-on Debian Bookworm.
-
-This is achieved by removing the dependency on `PyJWT` (Python) and thus
-transitively also removing the dependency on `cryptography` (Python).
-For more information, see the original pull request.
-
-Note that the Ceph Dashboard still cannot be used if TLS is activated,
-because `pyOpenSSL` is used to verify certs during launch. Disabling
-TLS via `ceph config set mgr mgr/dashboard/ssl false` and using e.g.
-a reverse proxy can be used as a workaround.
-
-A separate patch is required to allow the dashboard to run with TLS
-enabled.
-
-Fixes: https://forum.proxmox.com/threads/ceph-warning-post-upgrade-to-v8.129371
-Signed-off-by: Daniel Persson <mailto.woden@gmail.com>
-Signed-off-by: Max Carrara <m.carrara@proxmox.com>
----
- ceph.spec.in | 4 --
- debian/control | 1 -
- src/pybind/mgr/dashboard/constraints.txt | 1 -
- src/pybind/mgr/dashboard/exceptions.py | 12 ++++
- .../mgr/dashboard/requirements-lint.txt | 1 +
- .../mgr/dashboard/requirements-test.txt | 1 +
- src/pybind/mgr/dashboard/requirements.txt | 1 -
- src/pybind/mgr/dashboard/services/auth.py | 70 ++++++++++++++++---
- 8 files changed, 75 insertions(+), 16 deletions(-)
-
-diff --git a/ceph.spec.in b/ceph.spec.in
-index f0dd8e8a941..6fb61aed8d2 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 32e7bb45ce4..289b28877a8 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/constraints.txt b/src/pybind/mgr/dashboard/constraints.txt
-index 55f81c92dec..fd614104880 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 96cbc523356..d396a38d2c3 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-lint.txt b/src/pybind/mgr/dashboard/requirements-lint.txt
-index d82fa1ace1d..5fe9957c32a 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
-+PyJWT~=2.0
-diff --git a/src/pybind/mgr/dashboard/requirements-test.txt b/src/pybind/mgr/dashboard/requirements-test.txt
-index d2566bab59f..5066c7a59b6 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
-+PyJWT~=2.0
-diff --git a/src/pybind/mgr/dashboard/requirements.txt b/src/pybind/mgr/dashboard/requirements.txt
-index 8003d62a552..292971819c9 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 f13963abffd..3c600231252 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 @@ class JwtManager(object):
- 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 @@ class JwtManager(object):
- '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 @@ class JwtManager(object):
- @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 @@ class JwtManager(object):
- )
- 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']
---
-2.39.2
-
+++ /dev/null
-From 620b68a348f07145c49c12668576a89dee8198cb Mon Sep 17 00:00:00 2001
-From: Kefu Chai <tchaikov@gmail.com>
-Date: Fri, 15 Dec 2023 19:01:46 +0800
-Subject: [PATCH] cmake/modules/BuildRocksDB.cmake: inherit parent's CMAKE_CXX_FLAGS
-
-CMake allows us to customize `CMAKE_CXX_FLAGS` by setting CXXFLAGS
-environmental variable. and Debian's debhelper also sets CXXFLAGS
-when it builds cmake projects for customizing the building flags.
-
-but we fail to populate this setting down when building external
-projects. this is important when it comes to the projects which
-is critical to the performance. RocksDB is one of them.
-
-in this change, we pass the `CMAKE_CXX_FLAGS` down in
-`BuildRocksDB.cmake` so that its `CMAKE_CXX_FLAGS` contains
-the same set of `CMAKE_CXX_FLAGS` used by its parent project.
-
-this should help with the performance in the bluestore, where
-RocksDB is used.
-
-Signed-off-by: Kefu Chai <tchaikov@gmail.com>
- [TL: squashed in "cmake/modules/BuildRocksDB.cmake: use string(APPEND
- ..) when appropriate" ]
-Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
----
- cmake/modules/BuildRocksDB.cmake | 4 ++--
- cmake/modules/BuildRocksDB.cmake | 1 +
- 2 files changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/cmake/modules/BuildRocksDB.cmake b/cmake/modules/BuildRocksDB.cmake
-index f9a28274c40..e0208f6545b 100644
---- a/cmake/modules/BuildRocksDB.cmake
-+++ b/cmake/modules/BuildRocksDB.cmake
-@@ -52,12 +52,13 @@ function(build_rocksdb)
- endif()
- include(CheckCXXCompilerFlag)
- check_cxx_compiler_flag("-Wno-deprecated-copy" HAS_WARNING_DEPRECATED_COPY)
-+ set(rocksdb_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- if(HAS_WARNING_DEPRECATED_COPY)
-- set(rocksdb_CXX_FLAGS -Wno-deprecated-copy)
-+ string(APPEND rocksdb_CXX_FLAGS " -Wno-deprecated-copy")
- endif()
- check_cxx_compiler_flag("-Wno-pessimizing-move" HAS_WARNING_PESSIMIZING_MOVE)
- if(HAS_WARNING_PESSIMIZING_MOVE)
-- set(rocksdb_CXX_FLAGS "${rocksdb_CXX_FLAGS} -Wno-pessimizing-move")
-+ string(APPEND rocksdb_CXX_FLAGS " -Wno-pessimizing-move")
- endif()
- if(rocksdb_CXX_FLAGS)
- list(APPEND rocksdb_CMAKE_ARGS -DCMAKE_CXX_FLAGS='${rocksdb_CXX_FLAGS}')