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

Add tests for configure mixed elevation #4487

Merged
merged 14 commits into from
Jun 14, 2024
8 changes: 4 additions & 4 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ pseudocode
PSHOST
psobject
ptstr
publickey
publickey
PVD
pvk
pvm
Expand Down Expand Up @@ -412,8 +412,8 @@ servercert
servercertificate
setmetadatabymanifestid
SETTINGCHANGE
SETTINGMAPPING
sfs
SETTINGMAPPING
sfs
sfsclient
SHCONTF
SHGDN
Expand All @@ -435,7 +435,7 @@ Srinivasan
srs
startswith
STARTUPINFOW
STDMETHODCALLTYPE
STDMETHODCALLTYPE
storeapps
storeorigin
STRRET
Expand Down
1 change: 1 addition & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ jobs:
testSelector: 'testAssemblies'
testAssemblyVer2: '**\Microsoft.Management.Configuration.UnitTests.dll'
searchFolder: '$(buildOutDir)\Microsoft.Management.Configuration.UnitTests'
testFiltercriteria: 'Category!=OutOfProcOnly'
codeCoverageEnabled: false
platform: '$(buildPlatform)'
configuration: '$(BuildConfiguration)'
Expand Down
51 changes: 50 additions & 1 deletion src/AppInstallerCLICore/ConfigurationDynamicRuntimeFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,28 @@ namespace AppInstaller::CLI::ConfigurationRemoting
{
namespace anonymous
{
#ifndef DISABLE_TEST_HOOKS
constexpr std::wstring_view EnableTestModeTestGuid = L"1e62d683-2999-44e7-81f7-6f8f35e8d731";
constexpr std::wstring_view ForceHighIntegrityLevelUnitsTestGuid = L"f698d20f-3584-4f28-bc75-28037e08e651";
constexpr std::wstring_view EnableRestrictedIntegrityLevelTestGuid = L"1e62d683-2999-44e7-81f7-6f8f35e8d731";

// Checks the configuration set metadata for a specific test guid that controls the behavior flow.
bool GetConfigurationSetMetadataOverride(const ConfigurationSet& configurationSet, const std::wstring_view& testGuid)
{
auto metadataOverride = configurationSet.Metadata().TryLookup(testGuid);
if (metadataOverride)
{
auto metadataOverrideProperty = metadataOverride.try_as<IPropertyValue>();
if (metadataOverrideProperty && metadataOverrideProperty.Type() == PropertyType::Boolean)
{
return metadataOverrideProperty.GetBoolean();
}
}

return false;
}
#endif

struct DynamicProcessorInfo
{
IConfigurationSetProcessorFactory Factory;
Expand All @@ -26,7 +48,12 @@ namespace AppInstaller::CLI::ConfigurationRemoting

DynamicSetProcessor(IConfigurationSetProcessorFactory defaultRemoteFactory, IConfigurationSetProcessor defaultRemoteSetProcessor, const ConfigurationSet& configurationSet) : m_configurationSet(configurationSet)
{
#ifndef DISABLE_TEST_HOOKS
m_currentIntegrityLevel = GetConfigurationSetMetadataOverride(m_configurationSet, EnableTestModeTestGuid) ? Security::IntegrityLevel::Medium : Security::GetEffectiveIntegrityLevel();
#elif
m_currentIntegrityLevel = Security::GetEffectiveIntegrityLevel();
#endif

m_setProcessors.emplace(m_currentIntegrityLevel, DynamicProcessorInfo{ defaultRemoteFactory, defaultRemoteSetProcessor });
}

Expand Down Expand Up @@ -56,7 +83,11 @@ namespace AppInstaller::CLI::ConfigurationRemoting
});

// Create set and unit processor for current unit.
#ifndef DISABLE_TEST_HOOKS
Security::IntegrityLevel requiredIntegrityLevel = GetConfigurationSetMetadataOverride(m_configurationSet, ForceHighIntegrityLevelUnitsTestGuid) ? Security::IntegrityLevel::High : GetIntegrityLevelForUnit(unit);
#elif
Security::IntegrityLevel requiredIntegrityLevel = GetIntegrityLevelForUnit(unit);
#endif

auto itr = m_setProcessors.find(requiredIntegrityLevel);
if (itr == m_setProcessors.end())
Expand All @@ -79,11 +110,23 @@ namespace AppInstaller::CLI::ConfigurationRemoting
}
else if (securityContextLower == L"restricted")
{
#ifndef DISABLE_TEST_HOOKS
if (GetConfigurationSetMetadataOverride(m_configurationSet, EnableRestrictedIntegrityLevelTestGuid))
{
return Security::IntegrityLevel::Medium;
}
else
{
THROW_WIN32(ERROR_NOT_SUPPORTED);
}
#elif

// Not supporting elevated callers downgrading at the moment.
THROW_WIN32(ERROR_NOT_SUPPORTED);

// Technically this means the default level of the user token, so if UAC is disabled it would be the only integrity level (aka current).
//return Security::IntegrityLevel::Medium;
#endif
}
else if (securityContextLower == L"current")
{
Expand Down Expand Up @@ -172,7 +215,13 @@ namespace AppInstaller::CLI::ConfigurationRemoting
// If we got here, the only option is that the current integrity level is not High.
if (integrityLevel == Security::IntegrityLevel::High)
{
factory = CreateOutOfProcessFactory(true, SerializeSetProperties(), SerializeHighIntegrityLevelSet());
#ifndef DISABLE_TEST_HOOKS
bool useRunAs = !GetConfigurationSetMetadataOverride(m_configurationSet, EnableTestModeTestGuid);
#elif
bool useRunAs = true;
#endif

factory = CreateOutOfProcessFactory(useRunAs, SerializeSetProperties(), SerializeHighIntegrityLevelSet());
}
else
{
Expand Down
3 changes: 1 addition & 2 deletions src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ namespace AppInstaller::CLI::Workflow
IConfigurationSetProcessorFactory factory;

// Since downgrading is not currently supported, only use dynamic if not running as admin.
if (Settings::ExperimentalFeature::IsEnabled(Settings::ExperimentalFeature::Feature::ConfigureSelfElevation) &&
!Runtime::IsRunningAsAdmin())
if (Settings::ExperimentalFeature::IsEnabled(Settings::ExperimentalFeature::Feature::ConfigureSelfElevation) && !Runtime::IsRunningAsAdmin())
{
factory = ConfigurationRemoting::CreateDynamicRuntimeFactory();
// TODO: Implement SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties on dynamic factory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ namespace Microsoft.Management.Configuration.Processor
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Runtime.CompilerServices;
using System.Text;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// <copyright file="Constants.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
Expand All @@ -20,5 +20,25 @@ public class Constants
/// The namespace where xUnit traits will be defined.
/// </summary>
public const string NamespaceNameForTraits = "Microsoft.Management.Configuration.UnitTests.Helpers";

/// <summary>
/// The dynamic runtime factory handler identifier.
/// </summary>
public const string DynamicRuntimeHandlerIdentifier = "{73fea39f-6f4a-41c9-ba94-6fd14d633e40}";

/// <summary>
/// Test guid for enabling test mode for the dynamic runtime factory. Forces factory to exclude 'runas' verb and sets current IL to medium.
/// </summary>
public const string EnableDynamicFactoryTestMode = "1e62d683-2999-44e7-81f7-6f8f35e8d731";

/// <summary>
/// Test guid for allowing the restricted integrity level to be supported.
/// </summary>
public const string EnableRestrictedIntegrityLevelTestGuid = "5cae3226-185f-4289-815c-3c089d238dc6";

/// <summary>
/// Test guid for forcing units to have a high integrity level during the final routing of unit processor creation.
/// </summary>
public const string ForceHighIntegrityLevelUnitsTestGuid = "f698d20f-3584-4f28-bc75-28037e08e651";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ internal static class Errors
public static readonly int WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE_ADMIN = unchecked((int)0x8A15C111);
public static readonly int WINGET_CONFIG_ERROR_NOT_SUPPORTED_BY_PROCESSOR = unchecked((int)0x8A15C112);

// Limitation Set Errors
public static readonly int CORE_INVALID_OPERATION = unchecked((int)0x80131509);

#pragma warning restore SA1025 // Code should not contain multiple whitespace in a row
#pragma warning restore SA1600 // Elements should be documented
#pragma warning restore SA1310 // Field names should not contain underscore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// -----------------------------------------------------------------------------
// <copyright file="OutOfProcOnlyAttribute.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------------

namespace Microsoft.Management.Configuration.UnitTests.Helpers
{
using System;
using Xunit.Sdk;

/// <summary>
/// Trait used to mark a test as only for the out of proc scenario. Should not be run for the in-proc scenario
/// </summary>
[TraitDiscoverer(OutOfProcOnlyDiscoverer.TypeName, Constants.AssemblyNameForTraits)]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class OutOfProcOnlyAttribute : Attribute, ITraitAttribute
{
/// <summary>
/// Initializes a new instance of the <see cref="OutOfProcOnlyAttribute"/> class.
/// </summary>
public OutOfProcOnlyAttribute()
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// -----------------------------------------------------------------------------
// <copyright file="OutOfProcOnlyDiscoverer.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------------

namespace Microsoft.Management.Configuration.UnitTests.Helpers
{
using System.Collections.Generic;
using Xunit.Abstractions;
using Xunit.Sdk;

/// <summary>
/// Enables integration with xUnit trait system.
/// </summary>
public class OutOfProcOnlyDiscoverer : ITraitDiscoverer
{
/// <summary>
/// The type name for this discoverer.
/// </summary>
public const string TypeName = Constants.NamespaceNameForTraits + ".OutOfProcOnlyDiscoverer";

/// <summary>
/// Initializes a new instance of the <see cref="OutOfProcOnlyDiscoverer"/> class.
/// </summary>
public OutOfProcOnlyDiscoverer()
{
}

/// <summary>
/// Gets the trait information for the OutOfProcOnlyAttribute.
/// </summary>
/// <param name="traitAttribute">The trait information.</param>
/// <returns>Trait name/value pairs.</returns>
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
{
yield return new KeyValuePair<string, string>("Category", "OutOfProcOnly");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// <copyright file="ConfigurationDetailsTests.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
Expand Down
Loading
Loading