Expanding the package install utilities for Security Baseline to use the right package managers for all our current supported distros (#643)

This commit is contained in:
Marius Niculescu 2024-03-07 12:43:07 -08:00 коммит произвёл GitHub
Родитель 351cc427c8
Коммит b376be53e6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
4 изменённых файлов: 239 добавлений и 127 удалений

Просмотреть файл

@ -10,6 +10,7 @@ add_library(commonutils STATIC
DeviceInfoUtils.c
FileUtils.c
OtherUtils.c
PackageUtils.c
ProxyUtils.c
SocketUtils.c
SshUtils.c

Просмотреть файл

@ -490,103 +490,6 @@ int CheckFileSystemMountingOption(const char* mountFileName, const char* mountDi
return status;
}
static int CheckOrInstallPackage(const char* commandTemplate, const char* packageName, void* log)
{
char* command = NULL;
size_t packageNameLength = 0;
int status = ENOENT;
if ((NULL == commandTemplate) || (NULL == packageName) || ((0 == (packageNameLength = strlen(packageName)))))
{
OsConfigLogError(log, "CheckOrInstallPackage called with invalid arguments");
return EINVAL;
}
packageNameLength += strlen(commandTemplate) + 1;
if (NULL == (command = (char*)malloc(packageNameLength)))
{
OsConfigLogError(log, "CheckOrInstallPackage: out of memory");
return ENOMEM;
}
memset(command, 0, packageNameLength);
snprintf(command, packageNameLength, commandTemplate, packageName);
status = ExecuteCommand(NULL, command, false, false, 0, 0, NULL, NULL, log);
FREE_MEMORY(command);
return status;
}
int CheckPackageInstalled(const char* packageName, void* log)
{
const char* commandTemplate = "dpkg -l %s | grep ^ii";
int status = ENOENT;
if (0 == (status = CheckOrInstallPackage(commandTemplate, packageName, log)))
{
OsConfigLogInfo(log, "CheckPackageInstalled: '%s' is installed", packageName);
}
else if (EINVAL != status)
{
OsConfigLogInfo(log, "CheckPackageInstalled: '%s' is not installed", packageName);
}
return status;
}
int InstallPackage(const char* packageName, void* log)
{
const char* commandTemplate = "apt-get install -y %s";
int status = 0;
if (0 != (status = CheckPackageInstalled(packageName, log)))
{
if ((0 == (status = CheckOrInstallPackage(commandTemplate, packageName, log))) &&
(0 == (status = CheckPackageInstalled(packageName, log))))
{
OsConfigLogInfo(log, "InstallPackage: '%s' was successfully installed", packageName);
}
else
{
OsConfigLogError(log, "InstallPackage: installation of '%s' failed with %d", packageName, status);
}
}
else
{
OsConfigLogInfo(log, "InstallPackage: '%s' is already installed", packageName);
}
return status;
}
int UninstallPackage(const char* packageName, void* log)
{
const char* commandTemplate = "apt-get remove -y --purge %s";
int status = 0;
if (0 == (status = CheckPackageInstalled(packageName, log)))
{
if (0 == (status = CheckOrInstallPackage(commandTemplate, packageName, log)))
{
OsConfigLogInfo(log, "UninstallPackage: '%s' was successfully uninstalled", packageName);
}
else
{
OsConfigLogError(log, "UninstallPackage: uninstallation of '%s' failed with %d", packageName, status);
}
}
else if (EINVAL != status)
{
// Nothing to uninstall
status = 0;
}
return status;
}
static unsigned int GetNumberOfCharacterInstancesInFile(const char* fileName, char what)
{
unsigned int numberOf = 0;

Просмотреть файл

@ -0,0 +1,205 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "Internal.h"
const char* g_aptGet = "apt-get";
const char* g_dpkg = "dpkg";
const char* g_tdnf = "tdnf";
const char* g_dnf = "dnf";
const char* g_yum = "yum";
const char* g_zypper = "zypper";
static int IsPresent(const char* what, void* log)
{
const char* commandTemplate = "command -v %s";
char* command = NULL;
int status = ENOENT;
if (NULL == what)
{
OsConfigLogError(log, "IsPresent called with invalid argument");
return EINVAL;
}
if (NULL != (command = FormatAllocateString(commandTemplate, what)))
{
status = ExecuteCommand(NULL, command, false, false, 0, 0, NULL, NULL, log);
}
else
{
OsConfigLogError(log, "IsPresent: FormatAllocateString failed");
status = ENOMEM;
}
FREE_MEMORY(command);
return status;
}
static int CheckOrInstallPackage(const char* commandTemplate, const char* packageManager, const char* packageName, void* log)
{
char* command = NULL;
int status = ENOENT;
if ((NULL == commandTemplate) || (NULL == packageManager) || (NULL == packageName) || ((0 == strlen(packageName))))
{
OsConfigLogError(log, "CheckOrInstallPackage called with invalid arguments");
return EINVAL;
}
if (NULL == (command = FormatAllocateString(commandTemplate, packageManager, packageName)))
{
OsConfigLogError(log, "CheckOrInstallPackage: FormatAllocateString failed");
return ENOMEM;
}
status = ExecuteCommand(NULL, command, false, false, 0, 0, NULL, NULL, log);
FREE_MEMORY(command);
return status;
}
int CheckPackageInstalled(const char* packageName, void* log)
{
const char* commandTemplateDpkg = "%s -l %s | grep ^ii";
const char* commandTemplateAllElse = "%s list installed %s";
const char* commandTemplateZypper = "%s se -x %s";
int status = ENOENT;
if (0 == (status = IsPresent(g_dpkg, log)))
{
status = CheckOrInstallPackage(commandTemplateDpkg, g_dpkg, packageName, log);
}
else if (0 == (status = IsPresent(g_tdnf, log)))
{
status = CheckOrInstallPackage(commandTemplateAllElse, g_tdnf, packageName, log);
}
else if (0 == (status = IsPresent(g_dnf, log)))
{
status = CheckOrInstallPackage(commandTemplateAllElse, g_dnf, packageName, log);
}
else if (0 == (status = IsPresent(g_yum, log)))
{
status = CheckOrInstallPackage(commandTemplateAllElse, g_yum, packageName, log);
}
else if (0 == (status = IsPresent(g_zypper, log)))
{
status = CheckOrInstallPackage(commandTemplateZypper, g_zypper, packageName, log);
}
if (0 == status)
{
OsConfigLogInfo(log, "CheckPackageInstalled: '%s' is installed", packageName);
}
else
{
OsConfigLogInfo(log, "CheckPackageInstalled: '%s' is not found", packageName);
}
return status;
}
int InstallPackage(const char* packageName, void* log)
{
const char* commandTemplate = "%s install -y %s";
int status = ENOENT;
if (0 != (status = CheckPackageInstalled(packageName, log)))
{
if (0 == (status = IsPresent(g_aptGet, log)))
{
status = CheckOrInstallPackage(commandTemplate, g_aptGet, packageName, log);
}
else if (0 == (status = IsPresent(g_tdnf, log)))
{
status = CheckOrInstallPackage(commandTemplate, g_tdnf, packageName, log);
}
else if (0 == (status = IsPresent(g_dnf, log)))
{
status = CheckOrInstallPackage(commandTemplate, g_dnf, packageName, log);
}
else if (0 == (status = IsPresent(g_yum, log)))
{
status = CheckOrInstallPackage(commandTemplate, g_yum, packageName, log);
}
else if (0 == (status = IsPresent(g_zypper, log)))
{
status = CheckOrInstallPackage(commandTemplate, g_zypper, packageName, log);
}
if (0 == status)
{
status = CheckPackageInstalled(packageName, log);
}
if (0 == status)
{
OsConfigLogInfo(log, "InstallPackage: '%s' was successfully installed", packageName);
}
else
{
OsConfigLogError(log, "InstallPackage: installation of '%s' failed with %d", packageName, status);
}
}
else
{
OsConfigLogInfo(log, "InstallPackage: '%s' is already installed", packageName);
status = 0;
}
return status;
}
int UninstallPackage(const char* packageName, void* log)
{
const char* commandTemplateAptGet = "%s remove -y --purge %s";
const char* commandTemplateAllElse = "% remove -y %s";
int status = ENOENT;
if (0 == (status = CheckPackageInstalled(packageName, log)))
{
if (0 == (status = IsPresent(g_aptGet, log)))
{
status = CheckOrInstallPackage(commandTemplateAptGet, g_aptGet, packageName, log);
}
else if (0 == (status = IsPresent(g_tdnf, log)))
{
status = CheckOrInstallPackage(commandTemplateAllElse, g_tdnf, packageName, log);
}
else if (0 == (status = IsPresent(g_dnf, log)))
{
status = CheckOrInstallPackage(commandTemplateAllElse, g_dnf, packageName, log);
}
else if (0 == (status = IsPresent(g_yum, log)))
{
status = CheckOrInstallPackage(commandTemplateAllElse, g_yum, packageName, log);
}
else if (0 == (status = IsPresent(g_zypper, log)))
{
status = CheckOrInstallPackage(commandTemplateAllElse, g_zypper, packageName, log);
}
if ((0 == status) && (0 == CheckPackageInstalled(packageName, log)))
{
status = ENOENT;
}
if (0 == status)
{
OsConfigLogInfo(log, "UninstallPackage: '%s' was successfully uninstalled", packageName);
}
else
{
OsConfigLogError(log, "UninstallPackage: uninstallation of '%s' failed with %d", packageName, status);
}
}
else if (EINVAL != status)
{
OsConfigLogInfo(log, "InstallPackage: '%s' is not found", packageName);
status = 0;
}
return status;
}

Просмотреть файл

@ -1171,36 +1171,6 @@ TEST_F(CommonUtilsTest, CheckFileSystemMountingOption)
EXPECT_TRUE(Cleanup(m_path));
}
TEST_F(CommonUtilsTest, CheckInstallUninstallPackage)
{
EXPECT_EQ(EINVAL, CheckPackageInstalled(nullptr, nullptr));
EXPECT_EQ(EINVAL, InstallPackage(nullptr, nullptr));
EXPECT_EQ(EINVAL, UninstallPackage(nullptr, nullptr));
EXPECT_EQ(EINVAL, CheckPackageInstalled("", nullptr));
EXPECT_EQ(EINVAL, InstallPackage("", nullptr));
EXPECT_EQ(EINVAL, UninstallPackage("", nullptr));
if (0 == CheckPackageInstalled("apt", nullptr))
{
EXPECT_EQ(0, CheckPackageInstalled("ap*", nullptr));
EXPECT_NE(0, CheckPackageInstalled("~package_that_does_not_exist", nullptr));
EXPECT_NE(0, InstallPackage("~package_that_does_not_exist", nullptr));
// Nothing to uninstall
EXPECT_EQ(0, UninstallPackage("~package_that_does_not_exist", nullptr));
EXPECT_NE(0, CheckPackageInstalled("*~package_that_does_not_exist", nullptr));
EXPECT_NE(0, CheckPackageInstalled("~package_that_does_not_exist*", nullptr));
EXPECT_NE(0, CheckPackageInstalled("*~package_that_does_not_exist*", nullptr));
EXPECT_EQ(0, InstallPackage("rolldice", nullptr));
EXPECT_EQ(0, CheckPackageInstalled("rolldice", nullptr));
EXPECT_EQ(0, UninstallPackage("rolldice", nullptr));
}
}
TEST_F(CommonUtilsTest, GetNumberOfLinesInFile)
{
EXPECT_EQ(0, GetNumberOfLinesInFile(nullptr));
@ -1688,4 +1658,37 @@ TEST_F(CommonUtilsTest, RepairBrokenEolCharactersIfAny)
EXPECT_STREQ("\n\\Test\\123\n", value = RepairBrokenEolCharactersIfAny("\n\\Test\\123\\n"));
FREE_MEMORY(value);
}
TEST_F(CommonUtilsTest, CheckInstallUninstallPackage)
{
EXPECT_EQ(EINVAL, CheckPackageInstalled(nullptr, nullptr));
EXPECT_EQ(EINVAL, InstallPackage(nullptr, nullptr));
EXPECT_EQ(EINVAL, UninstallPackage(nullptr, nullptr));
EXPECT_EQ(EINVAL, CheckPackageInstalled("", nullptr));
EXPECT_EQ(EINVAL, InstallPackage("", nullptr));
EXPECT_EQ(EINVAL, UninstallPackage("", nullptr));
EXPECT_NE(0, CheckPackageInstalled("~package_that_does_not_exist", nullptr));
EXPECT_NE(0, InstallPackage("~package_that_does_not_exist", nullptr));
// Nothing to uninstall
EXPECT_EQ(0, UninstallPackage("~package_that_does_not_exist", nullptr));
EXPECT_NE(0, CheckPackageInstalled("*~package_that_does_not_exist", nullptr));
EXPECT_NE(0, CheckPackageInstalled("~package_that_does_not_exist*", nullptr));
EXPECT_NE(0, CheckPackageInstalled("*~package_that_does_not_exist*", nullptr));
if (0 == InstallPackage("rolldice", nullptr))
{
EXPECT_EQ(0, UninstallPackage("rolldice", nullptr));
EXPECT_NE(0, CheckPackageInstalled("rolldice", nullptr));
EXPECT_EQ(0, InstallPackage("rolldice", nullptr));
EXPECT_EQ(0, CheckPackageInstalled("rolldice", nullptr));
EXPECT_EQ(0, UninstallPackage("rolldice", nullptr));
}
EXPECT_NE(0, CheckPackageInstalled("rolldice", nullptr));
EXPECT_EQ(0, CheckPackageInstalled("gcc", nullptr));
}