GroupPolicy.h (8488B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #pragma once 4 #include <AppInstallerLanguageUtilities.h> 5 #include <winget/Certificates.h> 6 #include <winget/Registry.h> 7 #include <winget/Resources.h> 8 9 #include <string_view> 10 11 using namespace std::string_view_literals; 12 13 namespace AppInstaller::Settings 14 { 15 16 // A policy that sets a value for some setting. 17 // The value of the policy is a value in the registry key, or is 18 // made up of sub-keys for settings that are lists. 19 enum class ValuePolicy 20 { 21 None, 22 SourceAutoUpdateIntervalInMinutes, 23 AdditionalSources, 24 AllowedSources, 25 DefaultProxy, 26 Max, 27 }; 28 29 // A policy that acts as a toggle to enable or disable a feature. 30 // They are backed by a DWORD value with values 0 and 1. 31 struct TogglePolicy 32 { 33 enum class Policy 34 { 35 None = 0, 36 WinGet, 37 Settings, 38 ExperimentalFeatures, 39 LocalManifestFiles, 40 HashOverride, 41 LocalArchiveMalwareScanOverride, 42 DefaultSource, 43 MSStoreSource, 44 AdditionalSources, 45 AllowedSources, 46 BypassCertificatePinningForMicrosoftStore, 47 WinGetCommandLineInterfaces, 48 Configuration, 49 ProxyCommandLineOptions, 50 McpServer, 51 Max, 52 }; 53 54 TogglePolicy(Policy policy, std::string_view regValueName, StringResource::StringId policyName, bool defaultIsEnabled = true) : 55 m_policy(policy), m_regValueName(regValueName), m_policyName(policyName), m_defaultIsEnabled(defaultIsEnabled) {} 56 57 static TogglePolicy GetPolicy(Policy policy); 58 static std::vector<TogglePolicy> GetAllPolicies(); 59 60 Policy GetPolicy() const { return m_policy; } 61 std::string_view RegValueName() const { return m_regValueName; } 62 StringResource::StringId PolicyName() const { return m_policyName; } 63 bool DefaultIsEnabled() const { return m_defaultIsEnabled; } 64 65 private: 66 Policy m_policy; 67 std::string_view m_regValueName; 68 StringResource::StringId m_policyName; 69 bool m_defaultIsEnabled; 70 }; 71 72 // Possible configuration states for a policy. 73 enum class PolicyState 74 { 75 NotConfigured, 76 Disabled, 77 Enabled, 78 }; 79 80 // A source defined by Group Policy to be added or allowed 81 struct SourceFromPolicy 82 { 83 std::string Name; 84 std::string Arg; 85 std::string Type; 86 std::string Data; 87 std::string Identifier; 88 std::vector<std::string> TrustLevel; 89 bool Explicit = false; 90 91 #ifndef AICLI_DISABLE_TEST_HOOKS 92 Certificates::PinningConfiguration PinningConfiguration; 93 #endif 94 95 std::string ToJsonString() const; 96 }; 97 98 99 namespace details 100 { 101 102 template <ValuePolicy P> 103 struct ValuePolicyMapping 104 { 105 // value_t - type of the policy 106 // ReadAndValidate() - Function that reads the value and does semantic validation. 107 108 // For simple values: 109 // ValueName - Name of the registry value 110 // ValueType - Type of the registry value 111 // reg_value_t - Type returned by the registry when reading the value 112 113 // For lists: 114 // item_t - Type of each item 115 // KeyName -- Name of the sub-key containing the list 116 // ReadAndValidateItem() - Function that reads a single item from a subkey 117 }; 118 119 template<> 120 struct ValuePolicyMapping<ValuePolicy::None> 121 { 122 using value_t = std::monostate; 123 using opt_value_t = std::nullopt_t; 124 using opt_ref_value_t = std::nullopt_t; 125 static std::nullopt_t ReadAndValidate(const Registry::Key& policiesKey); 126 }; 127 128 #define POLICY_MAPPING_SPECIALIZATION(_policy_, _type_, _extra_) \ 129 template <> \ 130 struct ValuePolicyMapping<_policy_> \ 131 { \ 132 using value_t = _type_; \ 133 using opt_value_t = std::optional<value_t>; \ 134 using opt_ref_value_t = std::optional<std::reference_wrapper<const value_t>>; \ 135 static std::optional<value_t> ReadAndValidate(const Registry::Key& policiesKey); \ 136 _extra_ \ 137 } 138 139 #define POLICY_MAPPING_VALUE_SPECIALIZATION(_policy_, _type_, _valueName_, _valueType_) \ 140 POLICY_MAPPING_SPECIALIZATION(_policy_, _type_, \ 141 static constexpr std::string_view ValueName = _valueName_; \ 142 static constexpr Registry::Value::Type ValueType = _valueType_; \ 143 using reg_value_t = decltype(std::declval<Registry::Value>().GetValue<ValueType>()); \ 144 ) 145 146 #define POLICY_MAPPING_LIST_SPECIALIZATION(_policy_, _type_, _keyName_) \ 147 POLICY_MAPPING_SPECIALIZATION(_policy_, std::vector<_type_>, \ 148 static constexpr std::string_view KeyName = _keyName_; \ 149 using item_t = _type_; \ 150 static std::optional<item_t> ReadAndValidateItem(const Registry::Value& item); \ 151 ) 152 153 POLICY_MAPPING_VALUE_SPECIALIZATION(ValuePolicy::SourceAutoUpdateIntervalInMinutes, uint32_t, "SourceAutoUpdateInterval"sv, Registry::Value::Type::DWord); 154 POLICY_MAPPING_VALUE_SPECIALIZATION(ValuePolicy::DefaultProxy, std::string, "DefaultProxy"sv, Registry::Value::Type::String); 155 156 POLICY_MAPPING_LIST_SPECIALIZATION(ValuePolicy::AdditionalSources, SourceFromPolicy, "AdditionalSources"sv); 157 POLICY_MAPPING_LIST_SPECIALIZATION(ValuePolicy::AllowedSources, SourceFromPolicy, "AllowedSources"sv); 158 } 159 160 // Representation of the policies read from the registry. 161 struct GroupPolicy 162 { 163 using ValuePoliciesMap = EnumBasedVariantMap<ValuePolicy, details::ValuePolicyMapping>; 164 165 static GroupPolicy const& Instance(); 166 167 GroupPolicy(const Registry::Key& key); 168 ~GroupPolicy() = default; 169 170 GroupPolicy() = delete; 171 172 GroupPolicy(const GroupPolicy&) = delete; 173 GroupPolicy& operator=(const GroupPolicy&) = delete; 174 175 GroupPolicy(GroupPolicy&&) = delete; 176 GroupPolicy& operator=(GroupPolicy&&) = delete; 177 178 template<ValuePolicy P> 179 using ValueType = typename details::ValuePolicyMapping<P>::value_t; 180 181 // Gets the policy value if it is present 182 template<ValuePolicy P> 183 typename details::ValuePolicyMapping<P>::opt_value_t GetValue() const 184 { 185 if (m_values.Contains(P)) 186 { 187 return m_values.Get<P>(); 188 } 189 else 190 { 191 return std::nullopt; 192 } 193 } 194 195 template<ValuePolicy P> 196 typename details::ValuePolicyMapping<P>::opt_ref_value_t GetValueRef() const 197 { 198 if (m_values.Contains(P)) 199 { 200 return std::cref(m_values.Get<P>()); 201 } 202 else 203 { 204 return std::nullopt; 205 } 206 } 207 208 template<> 209 std::nullopt_t GetValue<ValuePolicy::None>() const 210 { 211 return std::nullopt; 212 } 213 214 template<> 215 std::nullopt_t GetValueRef<ValuePolicy::None>() const 216 { 217 return std::nullopt; 218 } 219 220 PolicyState GetState(TogglePolicy::Policy policy) const; 221 222 // Checks whether a policy is enabled, using an appropriate default when not configured. 223 // Should not be used when not configured means something different than enabled/disabled. 224 bool IsEnabled(TogglePolicy::Policy policy) const; 225 226 #ifndef AICLI_DISABLE_TEST_HOOKS 227 protected: 228 static void OverrideInstance(GroupPolicy* gp); 229 static void ResetInstance(); 230 #else 231 private: 232 #endif 233 std::map<TogglePolicy::Policy, PolicyState> m_toggles; 234 ValuePoliciesMap m_values; 235 }; 236 237 inline const GroupPolicy& GroupPolicies() 238 { 239 return GroupPolicy::Instance(); 240 } 241 242 struct GroupPolicyException 243 { 244 GroupPolicyException(TogglePolicy::Policy policy) : m_policy(policy) {} 245 246 const TogglePolicy::Policy& Policy() const { return m_policy; } 247 248 private: 249 TogglePolicy::Policy m_policy; 250 }; 251 252 }