commit 81765e12703249623c9f33e873a342a9a00fcdb1
parent 8a805ccbe9dbb2cd87709bfa4bce11e8a0fd2510
Author: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date: Thu, 15 Dec 2022 15:12:58 -0800
Add additional admin setting to match security related group policies (#2772)
Diffstat:
7 files changed, 84 insertions(+), 13 deletions(-)
diff --git a/src/AppInstallerCLICore/Argument.cpp b/src/AppInstallerCLICore/Argument.cpp
@@ -58,7 +58,7 @@ namespace AppInstaller::CLI
case Args::Type::InstallLocation:
return Argument{ "location"_liv, 'l', Args::Type::InstallLocation, Resource::String::LocationArgumentDescription, ArgumentType::Standard };
case Args::Type::HashOverride:
- return Argument{ "ignore-security-hash"_liv, NoAlias, Args::Type::HashOverride, Resource::String::HashOverrideArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::HashOverride };
+ return Argument{ "ignore-security-hash"_liv, NoAlias, Args::Type::HashOverride, Resource::String::HashOverrideArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::HashOverride, Settings::AdminSetting::InstallerHashOverride };
case Args::Type::AcceptPackageAgreements:
return Argument{ "accept-package-agreements"_liv, NoAlias, Args::Type::AcceptPackageAgreements, Resource::String::AcceptPackageAgreementsArgumentDescription, ArgumentType::Flag };
case Args::Type::NoUpgrade:
@@ -72,7 +72,7 @@ namespace AppInstaller::CLI
case Args::Type::Help:
return Argument{ "help"_liv, APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_CHAR, Args::Type::Help, Resource::String::HelpArgumentDescription, ArgumentType::Flag };
case Args::Type::IgnoreLocalArchiveMalwareScan:
- return Argument{ "ignore-local-archive-malware-scan"_liv, NoAlias, Args::Type::IgnoreLocalArchiveMalwareScan, Resource::String::IgnoreLocalArchiveMalwareScanArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::LocalArchiveMalwareScanOverride };
+ return Argument{ "ignore-local-archive-malware-scan"_liv, NoAlias, Args::Type::IgnoreLocalArchiveMalwareScan, Resource::String::IgnoreLocalArchiveMalwareScanArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::LocalArchiveMalwareScanOverride, Settings::AdminSetting::LocalArchiveMalwareScanOverride };
case Args::Type::SourceName:
return Argument{ "name"_liv, 'n', Args::Type::SourceName,Resource::String::SourceNameArgumentDescription, ArgumentType::Positional, false };
case Args::Type::SourceArg:
diff --git a/src/AppInstallerCLICore/Argument.h b/src/AppInstallerCLICore/Argument.h
@@ -147,8 +147,8 @@ namespace AppInstaller::CLI
Argument(std::string_view name, char alias, Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, bool required, Settings::ExperimentalFeature::Feature feature) :
m_name(name), m_alias(alias), m_execArgType(execArgType), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_required(required), m_feature(feature) {}
- Argument(std::string_view name, char alias, Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy) :
- m_name(name), m_alias(alias), m_execArgType(execArgType), m_desc(std::move(desc)), m_type(type), m_groupPolicy(groupPolicy) {}
+ Argument(std::string_view name, char alias, Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) :
+ m_name(name), m_alias(alias), m_execArgType(execArgType), m_desc(std::move(desc)), m_type(type), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}
Argument(std::string_view name, char alias, Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) :
m_name(name), m_alias(alias), m_execArgType(execArgType), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}
@@ -171,8 +171,8 @@ namespace AppInstaller::CLI
Argument(std::string_view name, char alias, std::string_view alternateName, Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, bool required, Settings::ExperimentalFeature::Feature feature) :
m_name(name), m_alias(alias), m_alternateName(alternateName), m_execArgType(execArgType), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_required(required), m_feature(feature) {}
- Argument(std::string_view name, char alias, std::string_view alternateName, Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy) :
- m_name(name), m_alias(alias), m_alternateName(alternateName), m_execArgType(execArgType), m_desc(std::move(desc)), m_type(type), m_groupPolicy(groupPolicy) {}
+ Argument(std::string_view name, char alias, std::string_view alternateName, Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) :
+ m_name(name), m_alias(alias), m_alternateName(alternateName), m_execArgType(execArgType), m_desc(std::move(desc)), m_type(type), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}
Argument(std::string_view name, char alias, std::string_view alternateName, Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) :
m_name(name), m_alias(alias), m_alternateName(alternateName), m_execArgType(execArgType), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}
diff --git a/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp b/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp
@@ -5,6 +5,7 @@
#include "winget/Archive.h"
#include "winget/Filesystem.h"
#include "PortableFlow.h"
+#include <winget/AdminSettings.h>
using namespace AppInstaller::Manifest;
@@ -27,7 +28,8 @@ namespace AppInstaller::CLI::Workflow
}
else
{
- if (context.Args.Contains(Execution::Args::Type::IgnoreLocalArchiveMalwareScan))
+ if (context.Args.Contains(Execution::Args::Type::IgnoreLocalArchiveMalwareScan) &&
+ Settings::IsAdminSettingEnabled(Settings::AdminSetting::LocalArchiveMalwareScanOverride))
{
AICLI_LOG(CLI, Warning, << "Archive scan detected malware. Proceeding due to --ignore-local-archive-malware-scan");
context.Reporter.Warn() << Resource::String::ArchiveFailedMalwareScanOverridden << std::endl;
diff --git a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp
@@ -5,6 +5,7 @@
#include "winget/Filesystem.h"
#include <AppInstallerMsixInfo.h>
+#include <winget/AdminSettings.h>
namespace AppInstaller::CLI::Workflow
{
@@ -331,18 +332,18 @@ namespace AppInstaller::CLI::Workflow
{
context.Reporter.Error() << Resource::String::InstallerHashMismatchAdminBlock << std::endl;
}
+ else if (!Settings::IsAdminSettingEnabled(Settings::AdminSetting::InstallerHashOverride))
+ {
+ context.Reporter.Error() << Resource::String::InstallerHashMismatchError << std::endl;
+ }
else if (overrideHashMismatch)
{
context.Reporter.Warn() << Resource::String::InstallerHashMismatchOverridden << std::endl;
return;
}
- else if (Settings::GroupPolicies().IsEnabled(Settings::TogglePolicy::Policy::HashOverride))
- {
- context.Reporter.Error() << Resource::String::InstallerHashMismatchOverrideRequired << std::endl;
- }
else
{
- context.Reporter.Error() << Resource::String::InstallerHashMismatchError << std::endl;
+ context.Reporter.Error() << Resource::String::InstallerHashMismatchOverrideRequired << std::endl;
}
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_INSTALLER_HASH_MISMATCH);
diff --git a/src/AppInstallerCLITests/WorkFlow.cpp b/src/AppInstallerCLITests/WorkFlow.cpp
@@ -36,6 +36,7 @@
#include <Commands/UninstallCommand.h>
#include <Commands/UpgradeCommand.h>
#include <Commands/SourceCommand.h>
+#include <winget/AdminSettings.h>
#include <winget/LocIndependent.h>
#include <winget/ManifestYamlParser.h>
#include <winget/PathVariable.h>
@@ -1285,7 +1286,36 @@ TEST_CASE("InstallFlow_Zip_ArchiveScanFailed", "[InstallFlow][workflow]")
REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::ArchiveFailedMalwareScan).get()) != std::string::npos);
}
-TEST_CASE("InstallFlow_Zip_ArchiveScanOverride", "[InstallFlow][workflow]")
+TEST_CASE("InstallFlow_Zip_ArchiveScanOverride_AdminSettingDisabled", "[InstallFlow][workflow]")
+{
+ TestCommon::TempFile installResultPath("TestExeInstalled.txt");
+ TestCommon::TestUserSettings testSettings;
+ testSettings.Set<Setting::EFZipInstall>(true);
+
+ std::ostringstream installOutput;
+ TestContext context{ installOutput, std::cin };
+ auto previousThreadGlobals = context.SetForCurrentThread();
+ OverrideForShellExecute(context);
+ context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_Zip_Exe.yaml").GetPath().u8string());
+ context.Args.AddArg(Execution::Args::Type::IgnoreLocalArchiveMalwareScan);
+
+ DisableAdminSetting(AppInstaller::Settings::AdminSetting::LocalArchiveMalwareScanOverride);
+
+ bool overrideArchiveScanResult = false;
+ AppInstaller::Archive::TestHook_SetScanArchiveResult_Override(&overrideArchiveScanResult);
+
+ InstallCommand install({});
+ install.Execute(context);
+ INFO(installOutput.str());
+
+ REQUIRE_TERMINATED_WITH(context, APPINSTALLER_CLI_ERROR_ARCHIVE_SCAN_FAILED);
+
+ // Verify Installer was not called
+ REQUIRE(!std::filesystem::exists(installResultPath.GetPath()));
+ REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::ArchiveFailedMalwareScan).get()) != std::string::npos);
+}
+
+TEST_CASE("InstallFlow_Zip_ArchiveScanOverride_AdminSettingEnabled", "[InstallFlow][workflow]")
{
TestCommon::TempFile installResultPath("TestExeInstalled.txt");
TestCommon::TestUserSettings testSettings;
@@ -1300,6 +1330,8 @@ TEST_CASE("InstallFlow_Zip_ArchiveScanOverride", "[InstallFlow][workflow]")
context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_Zip_Exe.yaml").GetPath().u8string());
context.Args.AddArg(Execution::Args::Type::IgnoreLocalArchiveMalwareScan);
+ EnableAdminSetting(AppInstaller::Settings::AdminSetting::LocalArchiveMalwareScanOverride);
+
bool overrideArchiveScanResult = false;
AppInstaller::Archive::TestHook_SetScanArchiveResult_Override(&overrideArchiveScanResult);
diff --git a/src/AppInstallerCommonCore/AdminSettings.cpp b/src/AppInstallerCommonCore/AdminSettings.cpp
@@ -17,6 +17,8 @@ namespace AppInstaller::Settings
{
constexpr std::string_view s_AdminSettingsYaml_LocalManifestFiles = "LocalManifestFiles"sv;
constexpr std::string_view s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore = "BypassCertificatePinningForMicrosoftStore"sv;
+ constexpr std::string_view s_AdminSettingsYaml_InstallerHashOverride = "InstallerHashOverride"sv;
+ constexpr std::string_view s_AdminSettingsYaml_LocalArchiveMalwareScanOverride = "LocalArchiveMalwareScanOverride"sv;
// Attempts to read a single scalar value from the node.
template<typename Value>
@@ -38,6 +40,8 @@ namespace AppInstaller::Settings
{
bool LocalManifestFiles = false;
bool BypassCertificatePinningForMicrosoftStore = false;
+ bool InstallerHashOverride = false;
+ bool LocalArchiveMalwareScanOverride = false;
};
struct AdminSettingsInternal
@@ -73,6 +77,12 @@ namespace AppInstaller::Settings
case AdminSetting::BypassCertificatePinningForMicrosoftStore:
m_settingValues.BypassCertificatePinningForMicrosoftStore = enabled;
break;
+ case AdminSetting::InstallerHashOverride:
+ m_settingValues.InstallerHashOverride = enabled;
+ break;
+ case AdminSetting::LocalArchiveMalwareScanOverride:
+ m_settingValues.LocalArchiveMalwareScanOverride = enabled;
+ break;
default:
return;
}
@@ -97,6 +107,10 @@ namespace AppInstaller::Settings
return m_settingValues.LocalManifestFiles;
case AdminSetting::BypassCertificatePinningForMicrosoftStore:
return m_settingValues.BypassCertificatePinningForMicrosoftStore;
+ case AdminSetting::InstallerHashOverride:
+ return m_settingValues.InstallerHashOverride;
+ case AdminSetting::LocalArchiveMalwareScanOverride:
+ return m_settingValues.LocalArchiveMalwareScanOverride;
default:
return false;
}
@@ -138,6 +152,8 @@ namespace AppInstaller::Settings
TryReadScalar<bool>(document, s_AdminSettingsYaml_LocalManifestFiles, m_settingValues.LocalManifestFiles);
TryReadScalar<bool>(document, s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore, m_settingValues.BypassCertificatePinningForMicrosoftStore);
+ TryReadScalar<bool>(document, s_AdminSettingsYaml_InstallerHashOverride, m_settingValues.InstallerHashOverride);
+ TryReadScalar<bool>(document, s_AdminSettingsYaml_LocalArchiveMalwareScanOverride, m_settingValues.LocalArchiveMalwareScanOverride);
}
bool AdminSettingsInternal::SaveAdminSettings()
@@ -146,6 +162,8 @@ namespace AppInstaller::Settings
out << YAML::BeginMap;
out << YAML::Key << s_AdminSettingsYaml_LocalManifestFiles << YAML::Value << m_settingValues.LocalManifestFiles;
out << YAML::Key << s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore << YAML::Value << m_settingValues.BypassCertificatePinningForMicrosoftStore;
+ out << YAML::Key << s_AdminSettingsYaml_InstallerHashOverride << YAML::Value << m_settingValues.InstallerHashOverride;
+ out << YAML::Key << s_AdminSettingsYaml_LocalArchiveMalwareScanOverride << YAML::Value << m_settingValues.LocalArchiveMalwareScanOverride;
out << YAML::EndMap;
return m_settingStream.Set(out.str());
@@ -164,6 +182,14 @@ namespace AppInstaller::Settings
{
result = AdminSetting::BypassCertificatePinningForMicrosoftStore;
}
+ else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_InstallerHashOverride, in))
+ {
+ result = AdminSetting::InstallerHashOverride;
+ }
+ else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_LocalArchiveMalwareScanOverride, in))
+ {
+ result = AdminSetting::LocalArchiveMalwareScanOverride;
+ }
return result;
}
@@ -176,6 +202,10 @@ namespace AppInstaller::Settings
return s_AdminSettingsYaml_LocalManifestFiles;
case AdminSetting::BypassCertificatePinningForMicrosoftStore:
return s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore;
+ case AdminSetting::InstallerHashOverride:
+ return s_AdminSettingsYaml_InstallerHashOverride;
+ case AdminSetting::LocalArchiveMalwareScanOverride:
+ return s_AdminSettingsYaml_LocalArchiveMalwareScanOverride;
default:
return "Unknown"sv;
}
@@ -189,6 +219,10 @@ namespace AppInstaller::Settings
return TogglePolicy::Policy::LocalManifestFiles;
case AdminSetting::BypassCertificatePinningForMicrosoftStore:
return TogglePolicy::Policy::BypassCertificatePinningForMicrosoftStore;
+ case AdminSetting::InstallerHashOverride:
+ return TogglePolicy::Policy::HashOverride;
+ case AdminSetting::LocalArchiveMalwareScanOverride:
+ return TogglePolicy::Policy::LocalArchiveMalwareScanOverride;
default:
return TogglePolicy::Policy::None;
}
diff --git a/src/AppInstallerCommonCore/Public/winget/AdminSettings.h b/src/AppInstallerCommonCore/Public/winget/AdminSettings.h
@@ -12,6 +12,8 @@ namespace AppInstaller::Settings
Unknown = 0,
LocalManifestFiles,
BypassCertificatePinningForMicrosoftStore,
+ InstallerHashOverride,
+ LocalArchiveMalwareScanOverride,
Max,
};