Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve configuration self elevation flow #4844

Merged
merged 9 commits into from
Oct 7, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Support module path in elevation scenario; working on tests
JohnMcPMS committed Sep 26, 2024
commit fbccc5dd4f1662614572e6ee6e86885e0bcd2e8a
72 changes: 71 additions & 1 deletion src/AppInstallerCLICore/ConfigurationDynamicRuntimeFactory.cpp
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
#include <AppInstallerStrings.h>
#include <winget/ILifetimeWatcher.h>
#include <winget/Security.h>
#include <winrt/Microsoft.Management.Configuration.SetProcessorFactory.h>

using namespace winrt::Windows::Foundation;
using namespace winrt::Microsoft::Management::Configuration;
@@ -40,7 +41,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
// have this implementation leverage that one with an event handler for the packaged specifics.
// TODO: Add SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties and pass values along to sets on creation
// In turn, any properties must only be set via the command line (or eventual UI requests to the user).
struct DynamicFactory : winrt::implements<DynamicFactory, IConfigurationSetProcessorFactory, winrt::cloaked<WinRT::ILifetimeWatcher>>, WinRT::LifetimeWatcherBase
struct DynamicFactory : winrt::implements<DynamicFactory, IConfigurationSetProcessorFactory, SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties, winrt::cloaked<WinRT::ILifetimeWatcher>>, WinRT::LifetimeWatcherBase
{
DynamicFactory();

@@ -58,12 +59,58 @@ namespace AppInstaller::CLI::ConfigurationRemoting

void SendDiagnostics(const IDiagnosticInformation& information);

Collections::IVectorView<winrt::hstring> AdditionalModulePaths() const
{
THROW_HR(E_NOTIMPL);
}

void AdditionalModulePaths(const Collections::IVectorView<winrt::hstring>&)
{
THROW_HR(E_NOTIMPL);
}

SetProcessorFactory::PwshConfigurationProcessorPolicy Policy() const
{
THROW_HR(E_NOTIMPL);
}

void Policy(SetProcessorFactory::PwshConfigurationProcessorPolicy)
{
THROW_HR(E_NOTIMPL);
}

SetProcessorFactory::PwshConfigurationProcessorLocation Location() const
{
return m_location;
}

void Location(SetProcessorFactory::PwshConfigurationProcessorLocation value)
{
auto pwshFactory = m_defaultRemoteFactory.as<SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties>();
pwshFactory.Location(value);
m_location = value;
}

winrt::hstring CustomLocation() const
{
return m_customLocation;
}

void CustomLocation(winrt::hstring value)
{
auto pwshFactory = m_defaultRemoteFactory.as<SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties>();
pwshFactory.CustomLocation(value);
m_customLocation = value;
}

private:
IConfigurationSetProcessorFactory m_defaultRemoteFactory;
winrt::event<EventHandler<IDiagnosticInformation>> m_diagnostics;
IConfigurationSetProcessorFactory::Diagnostics_revoker m_factoryDiagnosticsEventRevoker;
std::mutex m_diagnosticsMutex;
DiagnosticLevel m_minimumLevel = DiagnosticLevel::Informational;
SetProcessorFactory::PwshConfigurationProcessorLocation m_location = SetProcessorFactory::PwshConfigurationProcessorLocation::Default;
winrt::hstring m_customLocation;
};

struct DynamicProcessorInfo
@@ -194,7 +241,30 @@ namespace AppInstaller::CLI::ConfigurationRemoting
std::string SerializeSetProperties()
{
Json::Value json{ Json::ValueType::objectValue };

json["path"] = winrt::to_string(m_configurationSet.Path());

std::string locationString;
switch (m_dynamicFactory->Location())
{
case SetProcessorFactory::PwshConfigurationProcessorLocation::AllUsers:
locationString = "AllUsers";
break;
case SetProcessorFactory::PwshConfigurationProcessorLocation::CurrentUser:
locationString = "CurrentUser";
break;
case SetProcessorFactory::PwshConfigurationProcessorLocation::Custom:
locationString = Utility::ConvertToUTF8(m_dynamicFactory->CustomLocation());
break;
case SetProcessorFactory::PwshConfigurationProcessorLocation::Default:
break;
}

if (!locationString.empty())
{
json["modulePath"] = locationString;
}

Json::StreamWriterBuilder writerBuilder;
writerBuilder.settings_["indentation"] = "\t";
return Json::writeString(writerBuilder, json);
3 changes: 1 addition & 2 deletions src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp
Original file line number Diff line number Diff line change
@@ -105,14 +105,13 @@ namespace AppInstaller::CLI::Workflow
if (Settings::ExperimentalFeature::IsEnabled(Settings::ExperimentalFeature::Feature::ConfigureSelfElevation) && !Runtime::IsRunningAsAdmin())
{
factory = ConfigurationRemoting::CreateDynamicRuntimeFactory();
// TODO: Implement SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties on dynamic factory
}
else
{
factory = ConfigurationRemoting::CreateOutOfProcessFactory();
Configuration::SetModulePath(context, factory);
}

Configuration::SetModulePath(context, factory);
return factory;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
metadata:
1e62d683-2999-44e7-81f7-6f8f35e8d731: true
resources:
- name: Name1
type: xE2ETestResource/E2ETestResourcePSModulePath
metadata:
repository: AppInstallerCLIE2ETestsRepo
securityContext: elevated
properties:
outputPath: E:\Temp\psmodpath.txt # TODO: Parameter support
#outputPath: <OUTPUT_PATH> # TODO: Parameter support
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ DscResourcesToExport = @(
'E2ETestResourceTypes'
'E2ETestResourceCrash'
'E2ETestResourcePID'
'E2ETestResourcePSModulePath'
)
HelpInfoURI = 'https://www.contoso.com/help'

Original file line number Diff line number Diff line change
@@ -289,7 +289,7 @@ class E2ETestResourceCrash
}
}

# This resource writes the current PID to the provided file path.
# This resource writes the current PID to the provided file path.
[DscResource()]
class E2ETestResourcePID
{
@@ -324,3 +324,34 @@ class E2ETestResourcePID
}
}
}

# This resource writes the current PSModulePath to the provided file path.
[DscResource()]
class E2ETestResourcePSModulePath
{
[DscProperty(Key)]
[string] $key

[DscProperty(Mandatory)]
[string] $outputPath

[E2ETestResourcePSModulePath] Get()
{
$result = @{
key = "E2ETestResourcePSModulePath"
outputPath = $this.outputPath
}

return $result
}

[bool] Test()
{
return $false
}

[void] Set()
{
Set-Content -Path $this.outputPath -Value $env:PSModulePath -Force
}
}
17 changes: 17 additions & 0 deletions src/ConfigurationRemotingServer/Program.cs
Original file line number Diff line number Diff line change
@@ -147,6 +147,20 @@ static int Main(string[] args)
if (metadataJson != null)
{
limitationSet.Path = metadataJson.Path;

if (metadataJson.ModulePath != null)
{
PowerShellConfigurationProcessorLocation parsedLocation = PowerShellConfigurationProcessorLocation.Default;
if (Enum.TryParse<PowerShellConfigurationProcessorLocation>(metadataJson.ModulePath, out parsedLocation))
{
factory.Location = parsedLocation;
}
else
{
factory.Location = PowerShellConfigurationProcessorLocation.Custom;
factory.CustomLocation = metadataJson.ModulePath;
}
}
}

// Set the limitation set in factory.
@@ -168,6 +182,9 @@ private class LimitationSetMetadata
{
[JsonPropertyName("path")]
public string Path { get; set; } = string.Empty;

[JsonPropertyName("modulePath")]
public string? ModulePath { get; set; } = null;
}

private static string GetExternalModulesPath()