diff --git a/src/v/security/CMakeLists.txt b/src/v/security/CMakeLists.txt index 405ec27b79a28..beb51578a66a2 100644 --- a/src/v/security/CMakeLists.txt +++ b/src/v/security/CMakeLists.txt @@ -18,6 +18,7 @@ v_cc_library( credential.cc gssapi_authenticator.cc gssapi_principal_mapper.cc + jwt.cc krb5.cc krb5_configurator.cc license.cc @@ -41,7 +42,6 @@ v_cc_library( v::rpc absl::flat_hash_map absl::flat_hash_set - cryptopp re2 gssapi_krb5 krb5 diff --git a/src/v/security/jwt.cc b/src/v/security/jwt.cc new file mode 100644 index 0000000000000..594b1ef6c5446 --- /dev/null +++ b/src/v/security/jwt.cc @@ -0,0 +1,23 @@ +/* + * Copyright 2024 Redpanda Data, Inc. + * + * Licensed as a Redpanda Enterprise file under the Redpanda Community + * License (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://github.com/redpanda-data/redpanda/blob/master/licenses/rcl.md + */ +#include "security/jwt.h" + +namespace security::oidc::detail { +bytes base64_url_decode(std::string_view sv) { return base64url_to_bytes(sv); }; + +std::optional +base64_url_decode(json::Value const& v, std::string_view field) { + auto b64 = string_view<>(v, field); + if (!b64.has_value()) { + return std::nullopt; + } + return base64_url_decode(b64.value()); +} +} // namespace security::oidc::detail diff --git a/src/v/security/jwt.h b/src/v/security/jwt.h index e23c7ced2d490..00523c3548bda 100644 --- a/src/v/security/jwt.h +++ b/src/v/security/jwt.h @@ -19,6 +19,7 @@ #include "security/oidc_error.h" #include "strings/string_switch.h" #include "strings/utf8.h" +#include "utils/base64.h" #include #include @@ -26,7 +27,6 @@ #include #include #include -#include #include #include @@ -95,33 +95,10 @@ time_point(json::Value const& doc, std::string_view field) { typename Clock::time_point(std::chrono::seconds(it->value.GetInt64())); } -template -auto base64_url_decode(bytes_view sv) { - // TODO: Replace this with non-CryptoPP implementation - // TODO: https://github.com/redpanda-data/core-internal/issues/1132 - CryptoPP::Base64URLDecoder decoder; +bytes base64_url_decode(std::string_view sv); - decoder.Put(sv.data(), sv.size()); - decoder.MessageEnd(); - - StringT decoded; - if (auto size = decoder.MaxRetrievable(); size != 0) { - decoded.resize(size); - decoder.Get( - reinterpret_cast(decoded.data()), decoded.size()); - } - return decoded; -}; - -template -std::optional -base64_url_decode(json::Value const& v, std::string_view field) { - auto b64 = string_view(v, field); - if (!b64.has_value()) { - return std::nullopt; - } - return base64_url_decode(b64.value()); -} +std::optional +base64_url_decode(json::Value const& v, std::string_view field); } // namespace detail @@ -445,7 +422,7 @@ inline result make_rs256_verifier(json::Value const& jwk) { } auto key = crypto::key::load_rsa_public_key(n.value(), e.value()); return verifier{rs256_verifier{std::move(key)}}; - } catch (CryptoPP::Exception const& ex) { + } catch (base64_url_decoder_exception const&) { return errc::jwk_invalid; } catch (crypto::exception const&) { return errc::jwk_invalid; @@ -506,25 +483,26 @@ class verifier { // Verify the JWS signature and return the JWT result verify(jws const& jws) const { std::string_view sv(jws._encoded); - std::vector jose_enc; + std::vector jose_enc; jose_enc.reserve(3); boost::algorithm::split( jose_enc, - detail::char_view_cast(sv), + detail::char_view_cast(sv), [](char c) { return c == '.'; }); if (jose_enc.size() != 3) { return errc::jws_invalid_parts; } - constexpr auto make_dom = [](bytes_view bv) -> result { + constexpr auto make_dom = + [](std::string_view bv) -> result { try { auto bytes = detail::base64_url_decode(bv); auto str = detail::char_view_cast(bytes); json::Document dom; dom.Parse(str.data(), str.length()); return dom; - } catch (CryptoPP::Exception const& ex) { + } catch (base64_url_decoder_exception const&) { return errc::jws_invalid_b64; } };