Skip to content

Commit

Permalink
Add Group Policy to control per-user installs in Enterprise.
Browse files Browse the repository at this point in the history
This CL implements a new InstallPerMachineOnly policy that controls whether User application installs are enabled via Google Update.
  • Loading branch information
sorinj committed Feb 27, 2020
1 parent bc00015 commit 8548179
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 36 deletions.
6 changes: 4 additions & 2 deletions omaha/common/config_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1339,11 +1339,13 @@ bool ConfigManager::AreUpdatesSuppressedNow() const {

return are_updates_suppressed;
}
bool ConfigManager::CanInstallApp(const GUID& app_guid) const {
bool ConfigManager::CanInstallApp(const GUID& app_guid, bool is_machine) const {
// Google Update should never be checking whether it can install itself.
ASSERT1(!::IsEqualGUID(kGoopdateGuid, app_guid));

return kPolicyDisabled != GetEffectivePolicyForAppInstalls(app_guid);
auto policy = GetEffectivePolicyForAppInstalls(app_guid);
return kPolicyDisabled != policy &&
(is_machine || kPolicyEnabledMachineOnly != policy);
}

// Self-updates cannot be disabled.
Expand Down
2 changes: 1 addition & 1 deletion omaha/common/config_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ class ConfigManager {
bool AreUpdatesSuppressedNow() const;

// Returns true if installation of the specified app is allowed.
bool CanInstallApp(const GUID& app_guid) const;
bool CanInstallApp(const GUID& app_guid, bool is_machine) const;

// Returns true if updates are allowed for the specified app. The 'is_manual'
// parameter is needed for context, because the update policy can be one of
Expand Down
42 changes: 26 additions & 16 deletions omaha/common/config_manager_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ class ConfigManagerNoOverrideTest : public testing::Test {
: cm_(ConfigManager::Instance()) {
}

bool CanInstallApp(const TCHAR* guid) {
return cm_->CanInstallApp(StringToGuid(guid));
bool CanInstallApp(const TCHAR* guid, bool is_machine) {
return cm_->CanInstallApp(StringToGuid(guid), is_machine);
}

bool CanUpdateApp(const TCHAR* guid, bool is_manual) {
Expand Down Expand Up @@ -1227,99 +1227,109 @@ TEST_P(ConfigManagerTest, IsWindowsInstalling_Installing_Vista_ValidStates) {
}

TEST_P(ConfigManagerTest, CanInstallApp_NoGroupPolicy) {
EXPECT_TRUE(CanInstallApp(kAppGuid1));
EXPECT_TRUE(CanInstallApp(kAppGuid1, true));
EXPECT_EQ(kPolicyEnabled, GetEffectivePolicyForAppInstalls(kAppGuid1));
}

TEST_P(ConfigManagerTest, CanInstallApp_DifferentAppDisabled) {
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp2, 0));
EXPECT_TRUE(CanInstallApp(kAppGuid1));
EXPECT_TRUE(CanInstallApp(kAppGuid1, true));
EXPECT_EQ(kPolicyEnabled, GetEffectivePolicyForAppInstalls(kAppGuid1));
}

TEST_P(ConfigManagerTest, CanInstallApp_NoDefaultValue_AppDisabled) {
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp1, 0));
ExpectFalseOnlyIfDomain(CanInstallApp(kAppGuid1));
ExpectFalseOnlyIfDomain(CanInstallApp(kAppGuid1, true));
ExpectTrueOnlyIfDomain(GetEffectivePolicyForAppInstalls(kAppGuid1) ==
kPolicyDisabled);
}

TEST_P(ConfigManagerTest, CanInstallApp_NoDefaultValue_AppEnabled) {
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp1, 1));
EXPECT_TRUE(CanInstallApp(kAppGuid1));
EXPECT_TRUE(CanInstallApp(kAppGuid1, true));
EXPECT_EQ(kPolicyEnabled, GetEffectivePolicyForAppInstalls(kAppGuid1));
}

TEST_P(ConfigManagerTest, CanInstallApp_NoDefaultValue_AppInvalid) {
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp1, 2));
EXPECT_TRUE(CanInstallApp(kAppGuid1));
EXPECT_TRUE(CanInstallApp(kAppGuid1, true));
ExpectTrueOnlyIfDomain(GetEffectivePolicyForAppInstalls(kAppGuid1) == 2);
}

TEST_P(ConfigManagerTest, CanInstallApp_DefaultDisabled_NoAppValue) {
EXPECT_SUCCEEDED(SetPolicy(_T("InstallDefault"), 0));
ExpectFalseOnlyIfDomain(CanInstallApp(kAppGuid1));
ExpectFalseOnlyIfDomain(CanInstallApp(kAppGuid1, true));
ExpectTrueOnlyIfDomain(GetEffectivePolicyForAppInstalls(kAppGuid1) ==
kPolicyDisabled);
}

TEST_P(ConfigManagerTest, CanInstallApp_DefaultDisabled_AppDisabled) {
EXPECT_SUCCEEDED(SetPolicy(_T("InstallDefault"), 0));
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp1, 0));
ExpectFalseOnlyIfDomain(CanInstallApp(kAppGuid1));
ExpectFalseOnlyIfDomain(CanInstallApp(kAppGuid1, true));
ExpectTrueOnlyIfDomain(GetEffectivePolicyForAppInstalls(kAppGuid1) ==
kPolicyDisabled);
}

TEST_P(ConfigManagerTest, CanInstallApp_DefaultDisabled_AppEnabled) {
EXPECT_SUCCEEDED(SetPolicy(_T("InstallDefault"), 0));
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp1, 1));
EXPECT_TRUE(CanInstallApp(kAppGuid1));
EXPECT_TRUE(CanInstallApp(kAppGuid1, true));
EXPECT_EQ(kPolicyEnabled, GetEffectivePolicyForAppInstalls(kAppGuid1));
}

// Invalid value defaulting to true overrides the InstallDefault disable.
TEST_P(ConfigManagerTest, CanInstallApp_DefaultDisabled_AppInvalid) {
EXPECT_SUCCEEDED(SetPolicy(_T("InstallDefault"), 0));
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp1, 2));
EXPECT_TRUE(CanInstallApp(kAppGuid1));
EXPECT_TRUE(CanInstallApp(kAppGuid1, true));
ExpectTrueOnlyIfDomain(GetEffectivePolicyForAppInstalls(kAppGuid1) == 2);
}

TEST_P(ConfigManagerTest, CanInstallApp_DefaultEnabled_NoAppValue) {
EXPECT_SUCCEEDED(SetPolicy(_T("InstallDefault"), 1));
EXPECT_TRUE(CanInstallApp(kAppGuid1));
EXPECT_TRUE(CanInstallApp(kAppGuid1, true));
EXPECT_EQ(kPolicyEnabled, GetEffectivePolicyForAppInstalls(kAppGuid1));
}

TEST_P(ConfigManagerTest, CanInstallApp_DefaultEnabled_AppDisabled) {
EXPECT_SUCCEEDED(SetPolicy(_T("InstallDefault"), 1));
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp1, 0));
ExpectFalseOnlyIfDomain(CanInstallApp(kAppGuid1));
ExpectFalseOnlyIfDomain(CanInstallApp(kAppGuid1, true));
ExpectTrueOnlyIfDomain(GetEffectivePolicyForAppInstalls(kAppGuid1) ==
kPolicyDisabled);
}

TEST_P(ConfigManagerTest, CanInstallApp_DefaultEnabled_AppEnabled) {
EXPECT_SUCCEEDED(SetPolicy(_T("InstallDefault"), 1));
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp1, 1));
EXPECT_TRUE(CanInstallApp(kAppGuid1));
EXPECT_TRUE(CanInstallApp(kAppGuid1, true));
EXPECT_TRUE(CanInstallApp(kAppGuid1, false));
EXPECT_EQ(kPolicyEnabled, GetEffectivePolicyForAppInstalls(kAppGuid1));
}

TEST_P(ConfigManagerTest, CanInstallApp_DefaultEnabled_AppInvalid) {
EXPECT_SUCCEEDED(SetPolicy(_T("InstallDefault"), 1));
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp1, 2));
EXPECT_TRUE(CanInstallApp(kAppGuid1));
EXPECT_TRUE(CanInstallApp(kAppGuid1, true));
ExpectTrueOnlyIfDomain(GetEffectivePolicyForAppInstalls(kAppGuid1) == 2);
}

TEST_P(ConfigManagerTest, CanInstallApp_DefaultEnabled_AppEnabledMachineOnly) {
EXPECT_SUCCEEDED(SetPolicy(_T("InstallDefault"), 1));
EXPECT_SUCCEEDED(SetPolicy(kInstallPolicyApp1, 4));
EXPECT_TRUE(CanInstallApp(kAppGuid1, true));
ExpectTrueOnlyIfDomain(!CanInstallApp(kAppGuid1, false));
ExpectTrueOnlyIfDomain(kPolicyEnabledMachineOnly ==
GetEffectivePolicyForAppInstalls(kAppGuid1));
}

TEST_P(ConfigManagerTest, CanInstallApp_DMPolicy) {
if (IsDomainPredominant()) {
return;
}

EXPECT_EQ(!IsDM(), CanInstallApp(kChromeAppId));
EXPECT_EQ(!IsDM(), CanInstallApp(kChromeAppId, true));
EXPECT_EQ(IsDM() ? kPolicyDisabled : kPolicyEnabled,
GetEffectivePolicyForAppInstalls(kChromeAppId));
}
Expand Down
1 change: 1 addition & 0 deletions omaha/common/const_group_policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ const TCHAR* const kRegValueRollbackToTargetVersion

const int kPolicyDisabled = 0;
const int kPolicyEnabled = 1;
const int kPolicyEnabledMachineOnly = 4;
const int kPolicyManualUpdatesOnly = 2;
const int kPolicyAutomaticUpdatesOnly = 3;

Expand Down
32 changes: 26 additions & 6 deletions omaha/enterprise/generate_group_policy_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@
EXPLAIN !!Explain_Applications
"""

INSTALL_POLICY_ITEMLIST = """\
ITEMLIST
NAME !!Name_InstallsEnabled
VALUE NUMERIC 1
NAME !!Name_InstallsEnabledMachineOnly
VALUE NUMERIC 4
NAME !!Name_InstallsDisabled
VALUE NUMERIC 0
END ITEMLIST
REQUIRED"""

UPDATE_POLICY_ITEMLIST = """\
ITEMLIST
NAME !!Name_UpdatesEnabled
Expand All @@ -186,9 +197,11 @@
SUPPORTED !!Sup_GoogleUpdate1_2_145_5
#endif
EXPLAIN !!Explain_DefaultAllowInstallation
VALUENAME InstallDefault
VALUEOFF NUMERIC 0
VALUEON NUMERIC 1
PART !!Part_InstallPolicy DROPDOWNLIST
VALUENAME InstallDefault
""" +
INSTALL_POLICY_ITEMLIST + """
END PART
END POLICY
POLICY !!Pol_DefaultUpdatePolicy
Expand All @@ -213,9 +226,11 @@
SUPPORTED !!Sup_GoogleUpdate1_2_145_5
#endif
EXPLAIN !!Explain_Install$AppLegalId$
VALUENAME Install$AppGuid$
VALUEOFF NUMERIC 0
VALUEON NUMERIC 1
PART !!Part_InstallPolicy DROPDOWNLIST
VALUENAME Install$AppGuid$
""" +
INSTALL_POLICY_ITEMLIST.replace(' ', ' ') + """
END PART
END POLICY
POLICY !!Pol_UpdatePolicy
Expand Down Expand Up @@ -321,9 +336,14 @@
Part_ProxyMode=Choose how to specify proxy server settings
Part_ProxyServer=Address or URL of proxy server
Part_ProxyPacUrl=URL to a proxy .pac file
Part_InstallPolicy=Policy
Part_UpdatePolicy=Policy
Part_TargetVersionPrefix=Target version prefix
Name_InstallsEnabled=Always allow Installs (recommended)
Name_InstallsEnabledMachineOnly=Always allow Machine-Wide Installs, but not Per-User Installs
Name_InstallsDisabled=Installs disabled
Name_UpdatesEnabled=""" + UPDATES_ENABLED + """ (recommended)
Name_ManualUpdatesOnly=""" + MANUAL_UPDATES_ONLY + """
Name_AutomaticUpdatesOnly=""" + AUTOMATIC_UPDATES_ONLY + """
Expand Down
66 changes: 56 additions & 10 deletions omaha/enterprise/generate_group_policy_template_admx.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,29 @@
displayName="$(string.Pol_DefaultAllowInstallation)"
explainText="$(string.Explain_DefaultAllowInstallation)"
presentation="$(presentation.Pol_DefaultAllowInstallation)"
key="%(RootPolicyKey)s" valueName="InstallDefault">
key="%(RootPolicyKey)s">
<parentCategory ref="Cat_Applications" />
<supportedOn ref="Sup_GoogleUpdate1_2_145_5" />
<enabledValue><decimal value="1" /></enabledValue>
<disabledValue><decimal value="0" /></disabledValue>
<elements>
<enum id="Part_InstallPolicy" key="%(RootPolicyKey)s"
valueName="InstallDefault" required="true">
<item displayName="$(string.Name_InstallsEnabled)">
<value>
<decimal value="1" />
</value>
</item>
<item displayName="$(string.Name_InstallsEnabledMachineOnly)">
<value>
<decimal value="4" />
</value>
</item>
<item displayName="$(string.Name_InstallsDisabled)">
<value>
<decimal value="0" />
</value>
</item>
</enum>
</elements>
</policy>
<policy name="Pol_DefaultUpdatePolicy" class="Machine"
displayName="$(string.Pol_DefaultUpdatePolicy)"
Expand Down Expand Up @@ -246,12 +264,29 @@
displayName="$(string.Pol_AllowInstallation)"
explainText="$(string.Explain_Install%(AppLegalId)s)"
presentation="$(presentation.Pol_AllowInstallation)"
key="%(RootPolicyKey)s"
valueName="Install%(AppGuid)s">
key="%(RootPolicyKey)s">
<parentCategory ref="Cat_%(AppLegalId)s" />
<supportedOn ref="Sup_GoogleUpdate1_2_145_5" />
<enabledValue><decimal value="1" /></enabledValue>
<disabledValue><decimal value="0" /></disabledValue>
<elements>
<enum id="Part_InstallPolicy"
valueName="Install%(AppGuid)s" required="true">
<item displayName="$(string.Name_InstallsEnabled)">
<value>
<decimal value="1" />
</value>
</item>
<item displayName="$(string.Name_InstallsEnabledMachineOnly)">
<value>
<decimal value="4" />
</value>
</item>
<item displayName="$(string.Name_InstallsDisabled)">
<value>
<decimal value="0" />
</value>
</item>
</enum>
</elements>
</policy>
<policy name="Pol_UpdatePolicy%(AppLegalId)s" class="Machine"
displayName="$(string.Pol_UpdatePolicy)"
Expand Down Expand Up @@ -465,6 +500,11 @@ def _GeneratePolicies(apps):
('Part_ProxyMode', 'Choose how to specify proxy server settings'),
('Part_ProxyServer', 'Address or URL of proxy server'),
('Part_ProxyPacUrl', 'URL to a proxy .pac file'),
('Part_InstallPolicy', 'Policy'),
('Name_InstallsEnabled', 'Always allow Installs (recommended)'),
('Name_InstallsEnabledMachineOnly',
'Always allow Machine-Wide Installs, but not Per-User Installs.'),
('Name_InstallsDisabled', 'Installs disabled'),
('Part_UpdatePolicy', 'Policy'),
('Part_TargetVersionPrefix', 'Target version prefix'),
('Name_UpdatesEnabled', 'Always allow updates (recommended)'),
Expand Down Expand Up @@ -592,16 +632,22 @@ def _GeneratePolicies(apps):
<defaultValue></defaultValue>
</textBox>
</presentation>
<presentation id="Pol_DefaultAllowInstallation" />
<presentation id="Pol_DefaultAllowInstallation">
<dropdownList refId="Part_InstallPolicy"
defaultItem="0">Policy</dropdownList>
</presentation>
<presentation id="Pol_DefaultUpdatePolicy">
<dropdownList refId="Part_UpdatePolicy"
defaultItem="0">Policy</dropdownList>
</presentation>
<presentation id="Pol_AllowInstallation" />
<presentation id="Pol_AllowInstallation">
<dropdownList refId="Part_InstallPolicy"
defaultItem="0">Policy</dropdownList>
</presentation>
<presentation id="Pol_UpdatePolicy">
<dropdownList refId="Part_UpdatePolicy"
defaultItem="0">Policy</dropdownList>
</presentation>\
</presentation>
<presentation id="Pol_TargetVersionPrefix">
<textBox refId="Part_TargetVersionPrefix">
<label>Target version prefix</label>
Expand Down
3 changes: 2 additions & 1 deletion omaha/goopdate/app.cc
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,8 @@ HRESULT App::CheckGroupPolicy() const {
return GOOPDATE_E_APP_UPDATE_DISABLED_BY_POLICY;
}
} else {
if (!ConfigManager::Instance()->CanInstallApp(app_guid_)) {
if (!ConfigManager::Instance()->CanInstallApp(app_guid_,
app_bundle_->is_machine())) {
return GOOPDATE_E_APP_INSTALL_DISABLED_BY_POLICY;
}
}
Expand Down

0 comments on commit 8548179

Please sign in to comment.