mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-25 22:54:57 +02:00
Implement support for running specific CLI commands as root
fixes #7380
This commit is contained in:
parent
d3c9e052e9
commit
80a3298b5e
@ -333,66 +333,73 @@ int Main(void)
|
|||||||
rc = 0;
|
rc = 0;
|
||||||
} else if (command) {
|
} else if (command) {
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
String group = Application::GetRunAsGroup();
|
if (command->GetImpersonationLevel() == ImpersonateRoot) {
|
||||||
|
if (getuid() != 0) {
|
||||||
errno = 0;
|
Log(LogCritical, "cli", "This command must be run as root.");
|
||||||
struct group *gr = getgrnam(group.CStr());
|
return 0;
|
||||||
|
|
||||||
if (!gr) {
|
|
||||||
if (errno == 0) {
|
|
||||||
Log(LogCritical, "cli")
|
|
||||||
<< "Invalid group specified: " << group;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
} else {
|
|
||||||
Log(LogCritical, "cli")
|
|
||||||
<< "getgrnam() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
}
|
} else if (command && command->GetImpersonationLevel() == ImpersonateIcinga) {
|
||||||
|
String group = Application::GetRunAsGroup();
|
||||||
|
|
||||||
if (getgid() != gr->gr_gid) {
|
errno = 0;
|
||||||
if (!vm.count("reload-internal") && setgroups(0, NULL) < 0) {
|
struct group *gr = getgrnam(group.CStr());
|
||||||
Log(LogCritical, "cli")
|
|
||||||
<< "setgroups() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
if (!gr) {
|
||||||
return EXIT_FAILURE;
|
if (errno == 0) {
|
||||||
|
Log(LogCritical, "cli")
|
||||||
|
<< "Invalid group specified: " << group;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
} else {
|
||||||
|
Log(LogCritical, "cli")
|
||||||
|
<< "getgrnam() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setgid(gr->gr_gid) < 0) {
|
if (getgid() != gr->gr_gid) {
|
||||||
Log(LogCritical, "cli")
|
if (!vm.count("reload-internal") && setgroups(0, NULL) < 0) {
|
||||||
<< "setgid() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
Log(LogCritical, "cli")
|
||||||
return EXIT_FAILURE;
|
<< "setgroups() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
||||||
}
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
String user = Application::GetRunAsUser();
|
if (setgid(gr->gr_gid) < 0) {
|
||||||
|
Log(LogCritical, "cli")
|
||||||
errno = 0;
|
<< "setgid() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
||||||
struct passwd *pw = getpwnam(user.CStr());
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
if (!pw) {
|
|
||||||
if (errno == 0) {
|
|
||||||
Log(LogCritical, "cli")
|
|
||||||
<< "Invalid user specified: " << user;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
} else {
|
|
||||||
Log(LogCritical, "cli")
|
|
||||||
<< "getpwnam() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// also activate the additional groups the configured user is member of
|
|
||||||
if (getuid() != pw->pw_uid) {
|
|
||||||
if (!vm.count("reload-internal") && initgroups(user.CStr(), pw->pw_gid) < 0) {
|
|
||||||
Log(LogCritical, "cli")
|
|
||||||
<< "initgroups() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setuid(pw->pw_uid) < 0) {
|
String user = Application::GetRunAsUser();
|
||||||
Log(LogCritical, "cli")
|
|
||||||
<< "setuid() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
errno = 0;
|
||||||
return EXIT_FAILURE;
|
struct passwd *pw = getpwnam(user.CStr());
|
||||||
|
|
||||||
|
if (!pw) {
|
||||||
|
if (errno == 0) {
|
||||||
|
Log(LogCritical, "cli")
|
||||||
|
<< "Invalid user specified: " << user;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
} else {
|
||||||
|
Log(LogCritical, "cli")
|
||||||
|
<< "getpwnam() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// also activate the additional groups the configured user is member of
|
||||||
|
if (getuid() != pw->pw_uid) {
|
||||||
|
if (!vm.count("reload-internal") && initgroups(user.CStr(), pw->pw_gid) < 0) {
|
||||||
|
Log(LogCritical, "cli")
|
||||||
|
<< "initgroups() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setuid(pw->pw_uid) < 0) {
|
||||||
|
Log(LogCritical, "cli")
|
||||||
|
<< "setuid() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\"";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
@ -77,6 +77,11 @@ std::vector<String> AgentSetupCommand::GetArgumentSuggestions(const String& argu
|
|||||||
return CLICommand::GetArgumentSuggestions(argument, word);
|
return CLICommand::GetArgumentSuggestions(argument, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImpersonationLevel AgentSetupCommand::GetImpersonationLevel(void) const
|
||||||
|
{
|
||||||
|
return ImpersonateRoot;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entry point for the "agent setup" CLI command.
|
* The entry point for the "agent setup" CLI command.
|
||||||
*
|
*
|
||||||
|
@ -40,6 +40,7 @@ public:
|
|||||||
virtual void InitParameters(boost::program_options::options_description& visibleDesc,
|
virtual void InitParameters(boost::program_options::options_description& visibleDesc,
|
||||||
boost::program_options::options_description& hiddenDesc) const;
|
boost::program_options::options_description& hiddenDesc) const;
|
||||||
virtual std::vector<String> GetArgumentSuggestions(const String& argument, const String& word) const;
|
virtual std::vector<String> GetArgumentSuggestions(const String& argument, const String& word) const;
|
||||||
|
virtual ImpersonationLevel GetImpersonationLevel(void) const;
|
||||||
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
|
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -159,6 +159,11 @@ void CLICommand::InitParameters(boost::program_options::options_description& vis
|
|||||||
boost::program_options::options_description& hiddenDesc) const
|
boost::program_options::options_description& hiddenDesc) const
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
ImpersonationLevel CLICommand::GetImpersonationLevel(void) const
|
||||||
|
{
|
||||||
|
return ImpersonateIcinga;
|
||||||
|
}
|
||||||
|
|
||||||
bool CLICommand::ParseCommand(int argc, char **argv, po::options_description& visibleDesc,
|
bool CLICommand::ParseCommand(int argc, char **argv, po::options_description& visibleDesc,
|
||||||
po::options_description& hiddenDesc,
|
po::options_description& hiddenDesc,
|
||||||
po::positional_options_description& positionalDesc,
|
po::positional_options_description& positionalDesc,
|
||||||
|
@ -32,6 +32,13 @@ namespace icinga
|
|||||||
std::vector<String> I2_CLI_API GetBashCompletionSuggestions(const String& type, const String& word);
|
std::vector<String> I2_CLI_API GetBashCompletionSuggestions(const String& type, const String& word);
|
||||||
std::vector<String> I2_CLI_API GetFieldCompletionSuggestions(const Type *type, const String& word);
|
std::vector<String> I2_CLI_API GetFieldCompletionSuggestions(const Type *type, const String& word);
|
||||||
|
|
||||||
|
enum ImpersonationLevel
|
||||||
|
{
|
||||||
|
ImpersonateNone,
|
||||||
|
ImpersonateRoot,
|
||||||
|
ImpersonateIcinga
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A CLI command.
|
* A CLI command.
|
||||||
*
|
*
|
||||||
@ -50,6 +57,7 @@ public:
|
|||||||
virtual int GetMaxArguments(void) const;
|
virtual int GetMaxArguments(void) const;
|
||||||
virtual void InitParameters(boost::program_options::options_description& visibleDesc,
|
virtual void InitParameters(boost::program_options::options_description& visibleDesc,
|
||||||
boost::program_options::options_description& hiddenDesc) const;
|
boost::program_options::options_description& hiddenDesc) const;
|
||||||
|
virtual ImpersonationLevel GetImpersonationLevel(void) const;
|
||||||
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const = 0;
|
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const = 0;
|
||||||
virtual std::vector<String> GetArgumentSuggestions(const String& argument, const String& word) const;
|
virtual std::vector<String> GetArgumentSuggestions(const String& argument, const String& word) const;
|
||||||
virtual std::vector<String> GetPositionalSuggestions(const String& word) const;
|
virtual std::vector<String> GetPositionalSuggestions(const String& word) const;
|
||||||
|
@ -51,6 +51,11 @@ int FeatureDisableCommand::GetMaxArguments(void) const
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImpersonationLevel FeatureDisableCommand::GetImpersonationLevel(void) const
|
||||||
|
{
|
||||||
|
return ImpersonateRoot;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entry point for the "feature disable" CLI command.
|
* The entry point for the "feature disable" CLI command.
|
||||||
*
|
*
|
||||||
|
@ -40,6 +40,7 @@ public:
|
|||||||
virtual int GetMinArguments(void) const;
|
virtual int GetMinArguments(void) const;
|
||||||
virtual int GetMaxArguments(void) const;
|
virtual int GetMaxArguments(void) const;
|
||||||
virtual std::vector<String> GetPositionalSuggestions(const String& word) const;
|
virtual std::vector<String> GetPositionalSuggestions(const String& word) const;
|
||||||
|
virtual ImpersonationLevel GetImpersonationLevel(void) const;
|
||||||
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
|
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -51,6 +51,11 @@ int FeatureEnableCommand::GetMaxArguments(void) const
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImpersonationLevel FeatureEnableCommand::GetImpersonationLevel(void) const
|
||||||
|
{
|
||||||
|
return ImpersonateRoot;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entry point for the "feature enable" CLI command.
|
* The entry point for the "feature enable" CLI command.
|
||||||
*
|
*
|
||||||
|
@ -40,6 +40,7 @@ public:
|
|||||||
virtual int GetMinArguments(void) const;
|
virtual int GetMinArguments(void) const;
|
||||||
virtual int GetMaxArguments(void) const;
|
virtual int GetMaxArguments(void) const;
|
||||||
virtual std::vector<String> GetPositionalSuggestions(const String& word) const;
|
virtual std::vector<String> GetPositionalSuggestions(const String& word) const;
|
||||||
|
virtual ImpersonationLevel GetImpersonationLevel(void) const;
|
||||||
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
|
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,6 +58,11 @@ void RepositoryCommitCommand::InitParameters(boost::program_options::options_des
|
|||||||
("simulate", "Simulate to-be-committed changes");
|
("simulate", "Simulate to-be-committed changes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImpersonationLevel RepositoryCommitCommand::GetImpersonationLevel(void) const
|
||||||
|
{
|
||||||
|
return ImpersonateRoot;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entry point for the "repository commit" CLI command.
|
* The entry point for the "repository commit" CLI command.
|
||||||
*
|
*
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
virtual String GetShortDescription(void) const;
|
virtual String GetShortDescription(void) const;
|
||||||
virtual void InitParameters(boost::program_options::options_description& visibleDesc,
|
virtual void InitParameters(boost::program_options::options_description& visibleDesc,
|
||||||
boost::program_options::options_description& hiddenDesc) const;
|
boost::program_options::options_description& hiddenDesc) const;
|
||||||
|
virtual ImpersonationLevel GetImpersonationLevel(void) const;
|
||||||
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
|
virtual int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user