From 72c8f2f753eba3bc06ce9c75da61510e8a35a6d2 Mon Sep 17 00:00:00 2001 From: WHBANG <38547944+WHBANG@users.noreply.github.com> Date: Fri, 11 Aug 2023 14:50:33 +0800 Subject: [PATCH] feat(security): Support to use the principal of Unix account for authentication (#1569) https://github.com/apache/incubator-pegasus/issues/1568 When kerberos authentication is enabled: - The config 'krb5_keytab' and 'krb5_principal' is not empty, which means that pegasus completes the kinit action by itself. - When the value of both is empty, the user needs to complete the kinit action by himself, and pegasus will obtain the principal of the current unix account for authentication. --- src/runtime/security/init.cpp | 10 +++++++++ src/runtime/security/kinit_context.cpp | 28 ++++++++++++++++++++++++++ src/runtime/security/kinit_context.h | 1 + 3 files changed, 39 insertions(+) diff --git a/src/runtime/security/init.cpp b/src/runtime/security/init.cpp index 36d78e567c..870dd32204 100644 --- a/src/runtime/security/init.cpp +++ b/src/runtime/security/init.cpp @@ -23,11 +23,14 @@ #include "utils/errors.h" #include "utils/flags.h" #include "utils/fmt_logging.h" +#include "utils/strings.h" namespace dsn { namespace security { +DSN_DECLARE_bool(enable_auth); DSN_DECLARE_string(krb5_config); DSN_DECLARE_string(krb5_keytab); +DSN_DECLARE_string(krb5_principal); /*** * set kerberos envs(for more details: @@ -43,6 +46,13 @@ void set_krb5_env(bool is_server) error_s init_kerberos(bool is_server) { + // When FLAGS_enable_auth is set but lacks of necessary parameters to execute kinit by itself, + // then try to obtain the principal under the current Unix account for identity + // authentication automatically. + if (FLAGS_enable_auth && utils::is_empty(FLAGS_krb5_keytab) && + utils::is_empty(FLAGS_krb5_principal)) { + return run_get_principal_without_kinit(); + } // set kerberos env set_krb5_env(is_server); diff --git a/src/runtime/security/kinit_context.cpp b/src/runtime/security/kinit_context.cpp index 08ff5eea86..7b281d5d3a 100644 --- a/src/runtime/security/kinit_context.cpp +++ b/src/runtime/security/kinit_context.cpp @@ -93,6 +93,9 @@ class kinit_context : public utils::singleton public: // implementation of 'kinit -k -t ' error_s kinit(); + // If kinit has been executed outside the program, then directly obtain the principal + // information of the unix account for permission verification. + error_s get_principal_without_kinit(); const std::string &username() const { return _user_name; } private: @@ -174,6 +177,26 @@ error_s kinit_context::kinit() return error_s::ok(); } +// obtain _principal info under the current unix account for permission verification. +error_s kinit_context::get_principal_without_kinit() +{ + // get krb5_ctx + init_krb5_ctx(); + + // acquire credential cache handle + KRB5_RETURN_NOT_OK(krb5_cc_default(_krb5_context, &_ccache), + "couldn't acquire credential cache handle"); + + // get '_principal' from '_ccache' + KRB5_RETURN_NOT_OK(krb5_cc_get_principal(_krb5_context, _ccache, &_principal), + "get principal from cache failed"); + + // get '_user_name' from '_principal' + RETURN_NOT_OK(parse_username_from_principal()); + + return error_s::ok(); +} + void kinit_context::init_krb5_ctx() { static std::once_flag once; @@ -333,6 +356,11 @@ error_s kinit_context::wrap_krb5_err(krb5_error_code krb5_err, const std::string error_s run_kinit() { return kinit_context::instance().kinit(); } +error_s run_get_principal_without_kinit() +{ + return kinit_context::instance().get_principal_without_kinit(); +} + const std::string &get_username() { return kinit_context::instance().username(); } } // namespace security } // namespace dsn diff --git a/src/runtime/security/kinit_context.h b/src/runtime/security/kinit_context.h index 05a0de3993..bb97a43f22 100644 --- a/src/runtime/security/kinit_context.h +++ b/src/runtime/security/kinit_context.h @@ -24,6 +24,7 @@ namespace dsn { namespace security { extern error_s run_kinit(); +extern error_s run_get_principal_without_kinit(); extern const std::string &get_username(); } // namespace security } // namespace dsn