Skip to content

Commit

Permalink
feat(security): Support to use the principal of Unix account for auth…
Browse files Browse the repository at this point in the history
…entication (apache#1569)

apache#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.
  • Loading branch information
WHBANG authored Aug 11, 2023
1 parent 7fe41d4 commit 72c8f2f
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/runtime/security/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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);

Expand Down
28 changes: 28 additions & 0 deletions src/runtime/security/kinit_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ class kinit_context : public utils::singleton<kinit_context>
public:
// implementation of 'kinit -k -t <keytab_file> <principal>'
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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
1 change: 1 addition & 0 deletions src/runtime/security/kinit_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 72c8f2f

Please sign in to comment.