Skip to content

Commit 36b1518

Browse files
authored
Update configuration environment behavior (#5186)
## Change In response to some other discussions, update the configuration environment behavior: 1. Add an environment at the set level 2. Don't inherit environment data into child units, and don't promote environment data when serializing Updated the one consumer of environment (dynamic factory) to be responsible for the flow of the security context from the set to the immediate child units. Also improved serialization of groups to output the non-resource properties.
1 parent 53c9dbe commit 36b1518

12 files changed

+243
-71
lines changed

src/AppInstallerCLICore/ConfigurationDynamicRuntimeFactory.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ namespace AppInstaller::CLI::ConfigurationRemoting
139139
m_currentIntegrityLevel = Security::GetEffectiveIntegrityLevel();
140140
#endif
141141

142+
m_setIntegrityLevel = m_currentIntegrityLevel;
143+
m_setIntegrityLevel = SecurityContextToIntegrityLevel(m_configurationSet.Environment().Context());
144+
142145
// Check for multiple integrity level requirements
143146
bool multipleIntegrityLevels = false;
144147
bool higherIntegrityLevelsThanCurrent = false;
@@ -211,13 +214,13 @@ namespace AppInstaller::CLI::ConfigurationRemoting
211214
}
212215

213216
private:
214-
// Converts the string representation of SecurityContext to the integrity level
217+
// Converts the string representation of SecurityContext to the target integrity level for this instance
215218
Security::IntegrityLevel SecurityContextToIntegrityLevel(SecurityContext securityContext)
216219
{
217220
switch (securityContext)
218221
{
219222
case SecurityContext::Current:
220-
return m_currentIntegrityLevel;
223+
return m_setIntegrityLevel;
221224
case SecurityContext::Restricted:
222225
#ifndef AICLI_DISABLE_TEST_HOOKS
223226
if (m_enableRestrictedIntegrityLevel)
@@ -358,6 +361,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
358361

359362
winrt::com_ptr<DynamicFactory> m_dynamicFactory;
360363
Security::IntegrityLevel m_currentIntegrityLevel;
364+
Security::IntegrityLevel m_setIntegrityLevel;
361365
ProcessorMap m_setProcessors;
362366
ConfigurationSet m_configurationSet;
363367
std::once_flag m_createUnitSetProcessorsOnce;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// -----------------------------------------------------------------------------
2+
// <copyright file="ValueSetExtensions.cs" company="Microsoft Corporation">
3+
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
4+
// </copyright>
5+
// -----------------------------------------------------------------------------
6+
7+
namespace Microsoft.Management.Configuration.UnitTests.Helpers
8+
{
9+
using System;
10+
using System.Text;
11+
using Windows.Foundation.Collections;
12+
13+
/// <summary>
14+
/// Extensions for ValueSet.
15+
/// </summary>
16+
internal static class ValueSetExtensions
17+
{
18+
/// <summary>
19+
/// Converts the value set to YAML like output.
20+
/// </summary>
21+
/// <param name="set">The set to output.</param>
22+
/// <returns>The string.</returns>
23+
public static string ToYaml(this ValueSet set)
24+
{
25+
StringBuilder sb = new StringBuilder();
26+
ToYaml(set, sb);
27+
return sb.ToString();
28+
}
29+
30+
private static void ToYaml(ValueSet set, StringBuilder sb, int indentation = 0)
31+
{
32+
foreach (var keyValuePair in set)
33+
{
34+
bool addLine = true;
35+
36+
sb.Append(' ', indentation);
37+
sb.Append(keyValuePair.Key);
38+
sb.Append(": ");
39+
40+
if (keyValuePair.Value == null)
41+
{
42+
sb.Append("null");
43+
}
44+
else
45+
{
46+
switch (keyValuePair.Value)
47+
{
48+
case int i:
49+
sb.Append(i);
50+
break;
51+
case string s:
52+
sb.Append(s);
53+
break;
54+
case bool b:
55+
sb.Append(b);
56+
break;
57+
case ValueSet v:
58+
sb.AppendLine();
59+
ToYaml(v, sb, indentation + 2);
60+
addLine = false;
61+
break;
62+
default:
63+
throw new NotImplementedException($"Add ToYaml type `{keyValuePair.Value.GetType().Name}`");
64+
}
65+
}
66+
67+
if (addLine)
68+
{
69+
sb.AppendLine();
70+
}
71+
}
72+
}
73+
}
74+
}

src/Microsoft.Management.Configuration.UnitTests/Tests/OpenConfigurationSetTests.cs

+104-37
Large diffs are not rendered by default.

src/Microsoft.Management.Configuration/ConfigurationSet.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,16 @@ namespace winrt::Microsoft::Management::Configuration::implementation
283283
m_schemaUri = value;
284284
}
285285

286+
Configuration::ConfigurationEnvironment ConfigurationSet::Environment()
287+
{
288+
return *m_environment;
289+
}
290+
291+
implementation::ConfigurationEnvironment& ConfigurationSet::EnvironmentInternal()
292+
{
293+
return *m_environment;
294+
}
295+
286296
std::vector<Configuration::ConfigurationEnvironment> ConfigurationSet::GetUnitEnvironmentsInternal()
287297
{
288298
std::vector<impl::EnvironmentData> uniqueEnvironments;

src/Microsoft.Management.Configuration/ConfigurationSet.h

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33
#pragma once
44
#include "ConfigurationSet.g.h"
5+
#include "ConfigurationEnvironment.h"
56
#include "ConfigurationSetChangeData.h"
67
#include "ConfigurationStatus.h"
78
#include <winget/ILifetimeWatcher.h>
@@ -25,6 +26,7 @@ namespace winrt::Microsoft::Management::Configuration::implementation
2526
void Units(std::vector<Configuration::ConfigurationUnit>&& units);
2627
void Parameters(std::vector<Configuration::ConfigurationParameter>&& value);
2728
void ConfigurationSetChange(com_ptr<ConfigurationSetChangeData>& data, const std::optional<guid>& unitInstanceIdentifier);
29+
implementation::ConfigurationEnvironment& EnvironmentInternal();
2830
std::vector<Configuration::ConfigurationEnvironment> GetUnitEnvironmentsInternal();
2931
#endif
3032

@@ -68,6 +70,8 @@ namespace winrt::Microsoft::Management::Configuration::implementation
6870
Windows::Foundation::Uri SchemaUri();
6971
void SchemaUri(const Windows::Foundation::Uri& value);
7072

73+
Configuration::ConfigurationEnvironment Environment();
74+
7175
Windows::Foundation::Collections::IVector<Configuration::ConfigurationEnvironment> GetUnitEnvironments();
7276

7377
HRESULT STDMETHODCALLTYPE SetLifetimeWatcher(IUnknown* watcher);
@@ -91,6 +95,7 @@ namespace winrt::Microsoft::Management::Configuration::implementation
9195
Windows::Foundation::Uri m_schemaUri = nullptr;
9296
std::string m_inputHash;
9397
std::shared_ptr<ConfigurationStatus::SetChangeRegistration> m_setChangeRegistration;
98+
com_ptr<implementation::ConfigurationEnvironment> m_environment{ make_self<implementation::ConfigurationEnvironment>() };
9499
#endif
95100
};
96101
}

src/Microsoft.Management.Configuration/ConfigurationSetParser_0_3.cpp

+9-13
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,13 @@ namespace winrt::Microsoft::Management::Configuration::implementation
2323

2424
CHECK_ERROR(ParseValueSet(m_document, ConfigurationField::Metadata, false, result->Metadata()));
2525

26-
m_setEnvironment = make_self<implementation::ConfigurationEnvironment>();
27-
CHECK_ERROR(ExtractEnvironmentFromMetadata(result->Metadata(), *m_setEnvironment));
26+
CHECK_ERROR(ExtractEnvironmentFromMetadata(result->Metadata(), result->EnvironmentInternal()));
2827

2928
CHECK_ERROR(ParseParameters(result));
3029
CHECK_ERROR(ParseValueSet(m_document, ConfigurationField::Variables, false, result->Variables()));
3130

3231
std::vector<Configuration::ConfigurationUnit> units;
33-
CHECK_ERROR(ParseConfigurationUnitsFromField(m_document, ConfigurationField::Resources, *m_setEnvironment, units));
32+
CHECK_ERROR(ParseConfigurationUnitsFromField(m_document, ConfigurationField::Resources, units));
3433
result->Units(std::move(units));
3534

3635
result->SchemaVersion(GetSchemaVersion());
@@ -177,25 +176,25 @@ namespace winrt::Microsoft::Management::Configuration::implementation
177176
}
178177
}
179178

180-
void ConfigurationSetParser_0_3::ParseConfigurationUnitsFromField(const Node& document, ConfigurationField field, const ConfigurationEnvironment& defaultEnvironment, std::vector<Configuration::ConfigurationUnit>& result)
179+
void ConfigurationSetParser_0_3::ParseConfigurationUnitsFromField(const Node& document, ConfigurationField field, std::vector<Configuration::ConfigurationUnit>& result)
181180
{
182181
ParseSequence(document, field, false, Node::Type::Mapping, [&](const Node& item)
183182
{
184183
auto configurationUnit = make_self<ConfigurationUnit>();
185-
ParseConfigurationUnit(configurationUnit.get(), item, defaultEnvironment);
184+
ParseConfigurationUnit(configurationUnit.get(), item);
186185
result.emplace_back(*configurationUnit);
187186
});
188187
}
189188

190-
void ConfigurationSetParser_0_3::ParseConfigurationUnit(ConfigurationUnit* unit, const Node& unitNode, const ConfigurationEnvironment& defaultEnvironment)
189+
void ConfigurationSetParser_0_3::ParseConfigurationUnit(ConfigurationUnit* unit, const Node& unitNode)
191190
{
192191
// Set unknown intent as the new schema doesn't express it directly
193192
unit->Intent(ConfigurationUnitIntent::Unknown);
194193

195194
CHECK_ERROR(GetStringValueForUnit(unitNode, ConfigurationField::Name, true, unit, &ConfigurationUnit::Identifier));
196195
CHECK_ERROR(GetStringValueForUnit(unitNode, ConfigurationField::Type, true, unit, &ConfigurationUnit::Type));
197196
CHECK_ERROR(ParseValueSet(unitNode, ConfigurationField::Metadata, false, unit->Metadata()));
198-
CHECK_ERROR(ExtractEnvironmentForUnit(unit, defaultEnvironment));
197+
CHECK_ERROR(ExtractEnvironmentForUnit(unit));
199198
CHECK_ERROR(ValidateType(unit, unitNode, ConfigurationField::Type, false, true));
200199
CHECK_ERROR(GetStringArrayForUnit(unitNode, ConfigurationField::DependsOn, false, unit, &ConfigurationUnit::Dependencies));
201200

@@ -212,7 +211,7 @@ namespace winrt::Microsoft::Management::Configuration::implementation
212211
if (propertiesNode)
213212
{
214213
std::vector<Configuration::ConfigurationUnit> units;
215-
CHECK_ERROR(ParseConfigurationUnitsFromField(propertiesNode, ConfigurationField::Resources, unit->EnvironmentInternal(), units));
214+
CHECK_ERROR(ParseConfigurationUnitsFromField(propertiesNode, ConfigurationField::Resources, units));
216215
unit->Units(std::move(units));
217216
}
218217
}
@@ -294,13 +293,10 @@ namespace winrt::Microsoft::Management::Configuration::implementation
294293
}
295294
}
296295

297-
void ConfigurationSetParser_0_3::ExtractEnvironmentForUnit(ConfigurationUnit* unit, const ConfigurationEnvironment& defaultEnvironment)
296+
void ConfigurationSetParser_0_3::ExtractEnvironmentForUnit(ConfigurationUnit* unit)
298297
{
299-
auto& environmentInternal = unit->EnvironmentInternal();
300-
environmentInternal.DeepCopy(defaultEnvironment);
301-
302298
// Get unnested security context
303-
ExtractSecurityContext(unit, defaultEnvironment.Context());
299+
ExtractSecurityContext(unit);
304300

305301
// Get nested environment
306302
ExtractEnvironmentFromMetadata(unit->Metadata(), unit->EnvironmentInternal());

src/Microsoft.Management.Configuration/ConfigurationSetParser_0_3.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ namespace winrt::Microsoft::Management::Configuration::implementation
5353
ConfigurationParameter* parameter,
5454
void(ConfigurationParameter::* propertyFunction)(const Windows::Foundation::IInspectable& value));
5555

56-
void ParseConfigurationUnitsFromField(const AppInstaller::YAML::Node& document, ConfigurationField field, const ConfigurationEnvironment& defaultEnvironment, std::vector<Configuration::ConfigurationUnit>& result);
57-
virtual void ParseConfigurationUnit(ConfigurationUnit* unit, const AppInstaller::YAML::Node& unitNode, const ConfigurationEnvironment& defaultEnvironment);
56+
void ParseConfigurationUnitsFromField(const AppInstaller::YAML::Node& document, ConfigurationField field, std::vector<Configuration::ConfigurationUnit>& result);
57+
virtual void ParseConfigurationUnit(ConfigurationUnit* unit, const AppInstaller::YAML::Node& unitNode);
5858
// Determines if the given unit should be converted to a group.
5959
bool ShouldConvertToGroup(ConfigurationUnit* unit);
6060

@@ -63,10 +63,9 @@ namespace winrt::Microsoft::Management::Configuration::implementation
6363
void ExtractEnvironmentFromMetadata(const Windows::Foundation::Collections::ValueSet& metadata, ConfigurationEnvironment& targetEnvironment);
6464

6565
// Extracts the environment for a unit.
66-
void ExtractEnvironmentForUnit(ConfigurationUnit* unit, const ConfigurationEnvironment& defaultEnvironment);
66+
void ExtractEnvironmentForUnit(ConfigurationUnit* unit);
6767

6868
AppInstaller::YAML::Node m_document;
69-
com_ptr<ConfigurationEnvironment> m_setEnvironment;
7069
};
7170

7271
std::optional<std::pair<Windows::Foundation::PropertyType, bool>> ParseWindowsFoundationPropertyType(std::string_view value);

src/Microsoft.Management.Configuration/ConfigurationSetSerializer.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ namespace winrt::Microsoft::Management::Configuration::implementation
7777
{
7878
emitter << BeginMap;
7979

80+
WriteValues(emitter, WriteYamlValue);
81+
82+
emitter << EndMap;
83+
}
84+
85+
void WriteValues(AppInstaller::YAML::Emitter& emitter, void(*WriteYamlValue)(AppInstaller::YAML::Emitter& emitter, const winrt::Windows::Foundation::IInspectable& value))
86+
{
8087
if (m_valueSet)
8188
{
8289
for (const auto& [key, value] : m_valueSet)
@@ -100,8 +107,6 @@ namespace winrt::Microsoft::Management::Configuration::implementation
100107
WriteYamlValue(emitter, override.second);
101108
}
102109
}
103-
104-
emitter << EndMap;
105110
}
106111

107112
private:
@@ -171,6 +176,12 @@ namespace winrt::Microsoft::Management::Configuration::implementation
171176
writer.Write(emitter, WriteYamlValue);
172177
}
173178

179+
void ConfigurationSetSerializer::WriteYamlValueSetValues(AppInstaller::YAML::Emitter& emitter, const Windows::Foundation::Collections::ValueSet& valueSet, const std::vector<std::pair<ConfigurationField, Windows::Foundation::IInspectable>>& overrides)
180+
{
181+
anon::ValueSetWriter writer{ valueSet, overrides };
182+
writer.WriteValues(emitter, WriteYamlValue);
183+
}
184+
174185
void ConfigurationSetSerializer::WriteYamlStringArray(AppInstaller::YAML::Emitter& emitter, const Windows::Foundation::Collections::IVector<hstring>& values)
175186
{
176187
emitter << BeginSeq;

src/Microsoft.Management.Configuration/ConfigurationSetSerializer.h

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace winrt::Microsoft::Management::Configuration::implementation
3636
ConfigurationSetSerializer() = default;
3737

3838
static void WriteYamlValueSet(AppInstaller::YAML::Emitter& emitter, const Windows::Foundation::Collections::ValueSet& valueSet, const std::vector<std::pair<ConfigurationField, Windows::Foundation::IInspectable>>& overrides = {});
39+
static void WriteYamlValueSetValues(AppInstaller::YAML::Emitter& emitter, const Windows::Foundation::Collections::ValueSet& valueSet, const std::vector<std::pair<ConfigurationField, Windows::Foundation::IInspectable>>& overrides = {});
3940
static void WriteYamlValueSetIfNotEmpty(AppInstaller::YAML::Emitter& emitter, ConfigurationField key, const Windows::Foundation::Collections::ValueSet& valueSet, const std::vector<std::pair<ConfigurationField, Windows::Foundation::IInspectable>>& overrides = {});
4041
static void WriteYamlValueSetAsArray(AppInstaller::YAML::Emitter& emitter, const Windows::Foundation::Collections::ValueSet& valueSetArray);
4142

src/Microsoft.Management.Configuration/ConfigurationSetSerializer_0_3.cpp

+12-11
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,10 @@ namespace winrt::Microsoft::Management::Configuration::implementation
112112

113113
void AddEnvironmentToMetadata(
114114
Windows::Foundation::Collections::ValueSet& metadata,
115-
const Configuration::ConfigurationEnvironment& environment,
116-
const Configuration::ConfigurationEnvironment& commonEnvironment)
115+
const Configuration::ConfigurationEnvironment& environment)
117116
{
118117
AddEnvironmentToMetadata(metadata,
119-
environment.Context(), environment.ProcessorIdentifier(), environment.ProcessorProperties(),
120-
commonEnvironment.Context(), commonEnvironment.ProcessorIdentifier(), commonEnvironment.ProcessorProperties());
118+
environment.Context(), environment.ProcessorIdentifier(), environment.ProcessorProperties());
121119
}
122120
}
123121

@@ -131,8 +129,7 @@ namespace winrt::Microsoft::Management::Configuration::implementation
131129

132130
// Prepare an override if necessary
133131
Collections::ValueSet wingetMetadataOverride = nullptr;
134-
auto commonEnvironment = ConfigurationEnvironment::CalculateCommonEnvironment(configurationSet->GetUnitEnvironmentsInternal());
135-
AddEnvironmentToMetadata(wingetMetadataOverride, commonEnvironment);
132+
AddEnvironmentToMetadata(wingetMetadataOverride, configurationSet->EnvironmentInternal());
136133

137134
WriteYamlValueSetIfNotEmpty(emitter, ConfigurationField::Metadata, configurationSet->Metadata(),
138135
{
@@ -142,7 +139,7 @@ namespace winrt::Microsoft::Management::Configuration::implementation
142139

143140
WriteYamlParameters(emitter, configurationSet->Parameters());
144141
WriteYamlValueSetIfNotEmpty(emitter, ConfigurationField::Variables, configurationSet->Variables());
145-
WriteYamlConfigurationUnits(emitter, configurationSet->Units(), *commonEnvironment);
142+
WriteYamlConfigurationUnits(emitter, configurationSet->Units());
146143

147144
emitter << EndMap;
148145

@@ -220,8 +217,7 @@ namespace winrt::Microsoft::Management::Configuration::implementation
220217

221218
void ConfigurationSetSerializer_0_3::WriteYamlConfigurationUnits(
222219
AppInstaller::YAML::Emitter& emitter,
223-
const Windows::Foundation::Collections::IVector<Configuration::ConfigurationUnit>& values,
224-
const Configuration::ConfigurationEnvironment& commonEnvironment)
220+
const Windows::Foundation::Collections::IVector<Configuration::ConfigurationUnit>& values)
225221
{
226222
emitter << Key << GetConfigurationFieldName(ConfigurationField::Resources);
227223

@@ -242,7 +238,7 @@ namespace winrt::Microsoft::Management::Configuration::implementation
242238
// Prepare an override if necessary
243239
Collections::ValueSet wingetMetadataOverride = nullptr;
244240
Configuration::ConfigurationEnvironment unitEnvironment = unit.Environment();
245-
AddEnvironmentToMetadata(wingetMetadataOverride, unitEnvironment, commonEnvironment);
241+
AddEnvironmentToMetadata(wingetMetadataOverride, unitEnvironment);
246242

247243
WriteYamlValueSetIfNotEmpty(emitter, ConfigurationField::Metadata, unit.Metadata(),
248244
{ { ConfigurationField::WingetMetadataRoot, wingetMetadataOverride } });
@@ -272,7 +268,12 @@ namespace winrt::Microsoft::Management::Configuration::implementation
272268
emitter << Key << GetConfigurationFieldName(ConfigurationField::Properties);
273269
emitter << BeginMap;
274270

275-
WriteYamlConfigurationUnits(emitter, groupUnits, unitEnvironment);
271+
// Write everything but the resources
272+
WriteYamlValueSetValues(emitter, unit.Settings(),
273+
{ { ConfigurationField::Resources, nullptr } });
274+
275+
// Write the resources from the individual units
276+
WriteYamlConfigurationUnits(emitter, groupUnits);
276277

277278
emitter << EndMap;
278279
}

src/Microsoft.Management.Configuration/ConfigurationSetSerializer_0_3.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ namespace winrt::Microsoft::Management::Configuration::implementation
2424
void WriteYamlParameters(AppInstaller::YAML::Emitter& emitter, const Windows::Foundation::Collections::IVector<Configuration::ConfigurationParameter>& values);
2525
void WriteYamlConfigurationUnits(
2626
AppInstaller::YAML::Emitter& emitter,
27-
const Windows::Foundation::Collections::IVector<Configuration::ConfigurationUnit>& values,
28-
const Configuration::ConfigurationEnvironment& commonEnvironment);
27+
const Windows::Foundation::Collections::IVector<Configuration::ConfigurationUnit>& values);
2928
};
3029
}

0 commit comments

Comments
 (0)