winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }