Skip to content

Commit

Permalink
Add support for proxies #190 (#4203)
Browse files Browse the repository at this point in the history
For #190
See spec on #4152 
See #1776 for a related PR for the feature with the core implementation
for proxies in wininet

This PR adds basic support for using proxies. Most of the changes are
for enabling the configuration and blocking of the feature. This feature
will be gated behind an experimental feature setting

* Added Group Policy and Admin settings for enabling/disabling the use
of proxy CLI arguments and for setting a default proxy.
  + Pending: Internal review for new Group Policy
+ Extended `AdminSettings` to support settings with string values,
instead of only bool flags. The implementation is mostly a copy of the
bool case. In the future we should look back at it to reduce duplication
of code.
+ Added a `set` subcommand to `settings` that can set the admin settings
* Added CLI arguments to select a proxy on each different invocation of
winget, or to disable the use of a default one.
* Updated calls to wininet and cpprestsdk to use the provided proxy, and
added plumbing to get the arguments from the command line to the point
of use.
* Changed the flow around downloads to force winget to use proxies if
available.

Manually tested on a VM using mitmproxy
Pending: Adding automated tests tests.

Co-authored-by: yao-msft <[email protected]>
  • Loading branch information
florelis and yao-msft authored Mar 14, 2024
1 parent 8a00654 commit 7cea3d9
Show file tree
Hide file tree
Showing 79 changed files with 999 additions and 220 deletions.
11 changes: 11 additions & 0 deletions doc/Settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,14 @@ You can enable the feature as shown below.
"configuration03": true
},
```

### proxy

This feature enables the use of web proxies.
You can enable the feature as shown below.

```json
"experimentalFeatures": {
"proxy": true
},
```
17 changes: 17 additions & 0 deletions doc/admx/DesktopAppInstaller.admx
Original file line number Diff line number Diff line change
Expand Up @@ -166,5 +166,22 @@
<decimal value="0" />
</disabledValue>
</policy>
<policy name="EnableWindowsPackageManagerProxyCommandLineOptions" class="Machine" displayName="$(string.EnableWindowsPackageManagerProxyCommandLineOptions)" explainText="$(string.EnableWindowsPackageManagerProxyCommandLineOptionsExplanation)" key="Software\Policies\Microsoft\Windows\AppInstaller" valueName="EnableWindowsPackageManagerProxyCommandLineOptions">
<parentCategory ref="AppInstaller" />
<supportedOn ref="windows:SUPPORTED_Windows_10_0_RS5" />
<enabledValue>
<decimal value="1" />
</enabledValue>
<disabledValue>
<decimal value="0" />
</disabledValue>
</policy>
<policy name="WindowsPackageManagerDefaultProxy" class="Machine" displayName="$(string.WindowsPackageManagerDefaultProxy)" explainText="$(string.WindowsPackageManagerDefaultProxyExplanation)" presentation="$(presentation.WindowsPackageManagerDefaultProxy)" key="Software\Policies\Microsoft\Windows\AppInstaller">
<parentCategory ref="AppInstaller" />
<supportedOn ref="windows:SUPPORTED_Windows_10_0_RS5" />
<elements>
<text id="WindowsPackageManagerDefaultProxy" valueName="DefaultProxy" />
</elements>
</policy>
</policies>
</policyDefinitions>
20 changes: 19 additions & 1 deletion doc/admx/en-US/DesktopAppInstaller.adml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ If you disable or do not configure this setting, users will not be able to insta

If you disable this policy, users will not be able execute the Windows Package Manager CLI, and PowerShell cmdlets.

If you enable, or do not configuring this policy, users will be able to execute the Windows Package Manager CLI commands, and PowerShell cmdlets. (Provided “Enable App Installer” policy is not disabled).
If you enable, or do not configure this policy, users will be able to execute the Windows Package Manager CLI commands, and PowerShell cmdlets. (Provided “Enable App Installer” policy is not disabled).

This policy does not override the “Enable App Installer” policy.</string>
<string id="EnableWindowsPackageManagerConfiguration">Enable Windows Package Manager Configuration</string>
Expand All @@ -109,6 +109,19 @@ If you disable or do not configure this setting, users will not be able to insta
If you enable or do not configure this setting, users will be able to use the Windows Package Manager configuration feature.

If you disable this setting, users will not be able to use the Windows Package Manager configuration feature.</string>
<string id="EnableWindowsPackageManagerProxyCommandLineOptions">Enable Windows Package Manager Proxy command line options</string>
<string id="EnableWindowsPackageManagerProxyCommandLineOptionsExplanation">
This policy controls whether the Windows Package Manager usage of proxy can be configured by users through the command line.

If you enable this setting, users will be able to configure the Windows Package Manager's use of proxy through the command line.

If you disable or do not configure this setting, users will not be able to to configure the Windows Package Manager's use of proxy through the command line.</string>
<string id="WindowsPackageManagerDefaultProxy">Set Windows Package Manager Default Proxy</string>
<string id="WindowsPackageManagerDefaultProxyExplanation">This policy controls the default proxy used by the Windows Package Manager.

If you disable or do not configure this setting, no proxy will be used by default.

If you enable this setting, the specified proxy will be used by default.</string>
</stringTable>
<presentationTable>
<presentation id="SourceAutoUpdateInterval">
Expand All @@ -120,6 +133,11 @@ If you disable this setting, users will not be able to use the Windows Package M
<presentation id="AllowedSources">
<listBox refId="AllowedSources" required="false">Allowed Sources: </listBox>
</presentation>
<presentation id="WindowsPackageManagerDefaultProxy">
<textBox refId="WindowsPackageManagerDefaultProxy">
<label>Default Proxy</label>
</textBox>
</presentation>
</presentationTable>
</resources>
</policyDefinitionResources>
20 changes: 19 additions & 1 deletion schemas/JSON/settings/settings.export.schema.0.1.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,26 @@
"description": "Enable installing local manifests.",
"type": "boolean",
"default": false
},
"InstallerHashOverride": {
"description": "Enable overriding installer hash validation.",
"type": "boolean",
"default": false
},
"LocalArchiveMalwareScanOverride": {
"description": "Enable overriding malware scan for local archives.",
"type": "boolean",
"default": false
},
"ProxyCommandLineOptions": {
"description": "Enable using command line options for proxy.",
"type": "boolean",
"default": false
},
"DefaultProxy": {
"description": "Default proxy.",
"type": "string"
}
}
},
"UserSettingsFile": {
"description": "Path for the winget's user settings file.",
Expand Down
9 changes: 7 additions & 2 deletions schemas/JSON/settings/settings.schema.0.2.json
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,13 @@
"type": "boolean",
"default": false
},
"configuration": {
"description": "Enable support for configuration",
"configuration03": {
"description": "Enable support for configuration schema 0.3",
"type": "boolean",
"default": false
},
"proxy": {
"description": "Enable support for proxies",
"type": "boolean",
"default": false
}
Expand Down
21 changes: 18 additions & 3 deletions src/AppInstallerCLICore/Argument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ namespace AppInstaller::CLI
return { type, "enable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::EnableDisable };
case Execution::Args::Type::AdminSettingDisable:
return { type, "disable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::EnableDisable };
case Execution::Args::Type::SettingName:
return { type, "setting"_liv };
case Execution::Args::Type::SettingValue:
return { type, "value"_liv };

// Upgrade command
case Execution::Args::Type::All:
Expand Down Expand Up @@ -233,6 +237,11 @@ namespace AppInstaller::CLI
case Execution::Args::Type::AcceptSourceAgreements:
return { type, "accept-source-agreements"_liv, ArgTypeCategory::ExtendedSource };

case Execution::Args::Type::Proxy:
return { type, "proxy"_liv, ArgTypeCategory::CopyValueToSubContext, ArgTypeExclusiveSet::Proxy };
case Execution::Args::Type::NoProxy:
return { type, "no-proxy"_liv, ArgTypeCategory::CopyFlagToSubContext, ArgTypeExclusiveSet::Proxy };

case Execution::Args::Type::ToolVersion:
return { type, "version"_liv, 'v' };

Expand Down Expand Up @@ -268,7 +277,7 @@ namespace AppInstaller::CLI
case Args::Type::MultiQuery:
return Argument{ type, Resource::String::MultiQueryArgumentDescription, ArgumentType::Positional }.SetCountLimit(128);
case Args::Type::Manifest:
return Argument{ type, Resource::String::ManifestArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, Settings::TogglePolicy::Policy::LocalManifestFiles, Settings::AdminSetting::LocalManifestFiles };
return Argument{ type, Resource::String::ManifestArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, Settings::TogglePolicy::Policy::LocalManifestFiles, Settings::BoolAdminSetting::LocalManifestFiles };
case Args::Type::Id:
return Argument{ type, Resource::String::IdArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
case Args::Type::Name:
Expand Down Expand Up @@ -308,7 +317,7 @@ namespace AppInstaller::CLI
case Args::Type::InstallLocation:
return Argument{ type, Resource::String::LocationArgumentDescription, ArgumentType::Standard };
case Args::Type::HashOverride:
return Argument{ type, Resource::String::HashOverrideArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::HashOverride, Settings::AdminSetting::InstallerHashOverride };
return Argument{ type, Resource::String::HashOverrideArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::HashOverride, Settings::BoolAdminSetting::InstallerHashOverride };
case Args::Type::AcceptPackageAgreements:
return Argument{ type, Resource::String::AcceptPackageAgreementsArgumentDescription, ArgumentType::Flag };
case Args::Type::NoUpgrade:
Expand All @@ -324,7 +333,7 @@ namespace AppInstaller::CLI
case Args::Type::SkipDependencies:
return Argument{ type, Resource::String::SkipDependenciesArgumentDescription, ArgumentType::Flag, false };
case Args::Type::IgnoreLocalArchiveMalwareScan:
return Argument{ type, Resource::String::IgnoreLocalArchiveMalwareScanArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::LocalArchiveMalwareScanOverride, Settings::AdminSetting::LocalArchiveMalwareScanOverride };
return Argument{ type, Resource::String::IgnoreLocalArchiveMalwareScanArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::LocalArchiveMalwareScanOverride, Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride };
case Args::Type::SourceName:
return Argument{ type, Resource::String::SourceNameArgumentDescription, ArgumentType::Positional, false };
case Args::Type::SourceArg:
Expand Down Expand Up @@ -379,6 +388,10 @@ namespace AppInstaller::CLI
return Argument{ type, Resource::String::AllowRebootArgumentDescription, ArgumentType::Flag };
case Args::Type::IgnoreResumeLimit:
return Argument{ type, Resource::String::IgnoreResumeLimitArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Resume };
case Args::Type::Proxy:
return Argument{ type, Resource::String::ProxyArgumentDescription, ArgumentType::Standard, ExperimentalFeature::Feature::Proxy, TogglePolicy::Policy::ProxyCommandLineOptions, BoolAdminSetting::ProxyCommandLineOptions };
case Args::Type::NoProxy:
return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Proxy, TogglePolicy::Policy::ProxyCommandLineOptions, BoolAdminSetting::ProxyCommandLineOptions };
default:
THROW_HR(E_UNEXPECTED);
}
Expand All @@ -394,6 +407,8 @@ namespace AppInstaller::CLI
args.push_back(ForType(Args::Type::RetroStyle));
args.push_back(ForType(Args::Type::VerboseLogs));
args.emplace_back(Args::Type::DisableInteractivity, Resource::String::DisableInteractivityArgumentDescription, ArgumentType::Flag, false);
args.push_back(ForType(Args::Type::Proxy));
args.push_back(ForType(Args::Type::NoProxy));
}

std::string Argument::GetUsageString() const
Expand Down
12 changes: 8 additions & 4 deletions src/AppInstallerCLICore/Argument.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ namespace AppInstaller::CLI
PurgePreserve = 0x4,
PinType = 0x8,
StubType = 0x10,
Proxy = 0x20,

// This must always be at the end
Max
Expand Down Expand Up @@ -211,7 +212,7 @@ namespace AppInstaller::CLI
Argument::Visibility GetVisibility() const;
Settings::ExperimentalFeature::Feature Feature() const { return m_feature; }
Settings::TogglePolicy::Policy GroupPolicy() const { return m_groupPolicy; }
Settings::AdminSetting AdminSetting() const { return m_adminSetting; }
Settings::BoolAdminSetting AdminSetting() const { return m_adminSetting; }

Argument& SetRequired(bool required) { m_required = required; return *this; }
Argument& SetCountLimit(size_t countLimit) { m_countLimit = countLimit; return *this; }
Expand All @@ -237,12 +238,15 @@ namespace AppInstaller::CLI
Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, bool required, Settings::ExperimentalFeature::Feature feature) :
m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_required(required), m_feature(feature) {}

Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) :
Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) :
m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}

Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) :
Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) :
m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}

Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::ExperimentalFeature::Feature feature, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) :
m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_feature(feature), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}

ArgumentCommon m_argCommon;
Resource::StringId m_desc;
bool m_required = false;
Expand All @@ -251,6 +255,6 @@ namespace AppInstaller::CLI
size_t m_countLimit = 1;
Settings::ExperimentalFeature::Feature m_feature = Settings::ExperimentalFeature::Feature::None;
Settings::TogglePolicy::Policy m_groupPolicy = Settings::TogglePolicy::Policy::None;
Settings::AdminSetting m_adminSetting = Settings::AdminSetting::Unknown;
Settings::BoolAdminSetting m_adminSetting = Settings::BoolAdminSetting::Unknown;
};
}
2 changes: 1 addition & 1 deletion src/AppInstallerCLICore/Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ namespace AppInstaller::CLI
throw GroupPolicyException(arg.GroupPolicy());
}

if (arg.AdminSetting() != AdminSetting::Unknown && !Settings::IsAdminSettingEnabled(arg.AdminSetting()) && execArgs.Contains(arg.ExecArgType()))
if (arg.AdminSetting() != BoolAdminSetting::Unknown && !Settings::IsAdminSettingEnabled(arg.AdminSetting()) && execArgs.Contains(arg.ExecArgType()))
{
auto setting = Settings::AdminSettingToString(arg.AdminSetting());
AICLI_LOG(CLI, Error, << "Trying to use argument: " << arg.Name() << " disabled by admin setting " << setting);
Expand Down
4 changes: 2 additions & 2 deletions src/AppInstallerCLICore/Commands/DownloadCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ namespace AppInstaller::CLI
Argument::ForType(Args::Type::CustomHeader),
Argument::ForType(Args::Type::AuthenticationMode),
Argument::ForType(Args::Type::AuthenticationAccount),
Argument::ForType(Execution::Args::Type::AcceptPackageAgreements),
Argument::ForType(Execution::Args::Type::AcceptSourceAgreements),
Argument::ForType(Args::Type::AcceptPackageAgreements),
Argument::ForType(Args::Type::AcceptSourceAgreements),
};
}

Expand Down
10 changes: 9 additions & 1 deletion src/AppInstallerCLICore/Commands/RootCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,21 @@ namespace AppInstaller::CLI
Execution::TableOutput<2> adminSettingsTable{ context.Reporter, { Resource::String::AdminSettingHeader, Resource::String::StateHeader } };

// Output the admin settings.
for (const auto& setting : Settings::GetAllAdminSettings())
for (const auto& setting : Settings::GetAllBoolAdminSettings())
{
adminSettingsTable.OutputLine({
std::string{ AdminSettingToString(setting)},
Resource::LocString{ IsAdminSettingEnabled(setting) ? Resource::String::StateEnabled : Resource::String::StateDisabled }
});
}
for (const auto& setting : Settings::GetAllStringAdminSettings())
{
auto settingValue = GetAdminSetting(setting);
adminSettingsTable.OutputLine({
std::string{ AdminSettingToString(setting)},
settingValue ? Utility::LocIndString{ settingValue.value() } : Resource::LocString{ Resource::String::StateDisabled }
});
}
adminSettingsTable.Complete();
}

Expand Down
Loading

0 comments on commit 7cea3d9

Please sign in to comment.