Skip to content

Commit a985d1e

Browse files
authored
Merge pull request #1206 from Gijsreyn/gh-1204/main/fix-registry-specialpermission
(MAINT) Improve permission handling in RegistryHelper
2 parents 3ae8105 + 726ce29 commit a985d1e

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

lib/dsc-lib-registry/src/lib.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,22 @@ impl RegistryHelper {
259259
///
260260
/// * `RegistryError` - The error that occurred.
261261
pub fn remove(&self) -> Result<Option<Registry>, RegistryError> {
262-
let (reg_key, _subkey) = match self.open(Security::AllAccess) {
262+
// For deleting a value, we need SetValue permission (KEY_SET_VALUE).
263+
// Try to open with the minimal required permission.
264+
// If that fails due to permission, try with AllAccess as a fallback.
265+
let (reg_key, _subkey) = match self.open(Security::SetValue) {
263266
Ok(reg_key) => reg_key,
264267
// handle NotFound error
265268
Err(RegistryError::RegistryKeyNotFound(_)) => {
266269
eprintln!("{}", t!("registry_helper.removeErrorKeyNotExist"));
267270
return Ok(None);
268271
},
272+
Err(RegistryError::RegistryKey(key::Error::PermissionDenied(_, _))) => {
273+
match self.open(Security::AllAccess) {
274+
Ok(reg_key) => reg_key,
275+
Err(e) => return self.handle_error_or_what_if(e),
276+
}
277+
},
269278
Err(e) => return self.handle_error_or_what_if(e),
270279
};
271280

@@ -289,10 +298,11 @@ impl RegistryHelper {
289298
Err(e) => return self.handle_error_or_what_if(RegistryError::RegistryValue(e)),
290299
}
291300
} else {
292-
// to delete the key, we need to open the parent key first
301+
// to delete the key, we need to open the parent key with CreateSubKey permission
302+
// which includes the ability to delete subkeys
293303
let parent_path = get_parent_key_path(&self.config.key_path);
294304
let (hive, parent_subkey) = get_hive_from_path(parent_path)?;
295-
let parent_reg_key = match hive.open(parent_subkey, Security::AllAccess) {
305+
let parent_reg_key = match hive.open(parent_subkey, Security::CreateSubKey) {
296306
Ok(k) => k,
297307
Err(e) => return self.handle_error_or_what_if(RegistryError::RegistryKey(e)),
298308
};

resources/registry/registry.dsc.resource.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"tags": [
66
"Windows"
77
],
8-
"version": "0.1.0",
8+
"version": "1.0.0",
99
"get": {
1010
"executable": "registry",
1111
"args": [

resources/registry/tests/registry.config.set.tests.ps1

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,55 @@ Describe 'registry config set tests' {
145145
$LASTEXITCODE | Should -Be 0
146146
$out.results[0].result.afterState._exist | Should -Be $false
147147
}
148+
149+
It 'Can delete value from system-protected key with minimal permissions' -Skip:(!$IsWindows) {
150+
$testKeyPath = 'HKLM:\Software\Policies\Microsoft\Windows\Appx'
151+
if (-not (Test-Path $testKeyPath)) {
152+
Set-ItResult -Skipped -Because "Test key path '$testKeyPath' does not exist"
153+
return
154+
}
155+
156+
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
157+
$isElevated = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
158+
159+
if (-not $isElevated) {
160+
Set-ItResult -Skipped -Because "Test requires elevated privileges"
161+
return
162+
}
163+
164+
$setJson = @'
165+
{
166+
"keyPath": "HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\Appx",
167+
"valueName": "DSCTestValue",
168+
"valueData": {
169+
"String": "TestData"
170+
}
171+
}
172+
'@
173+
$out = registry config set --input $setJson 2>$null
174+
$LASTEXITCODE | Should -Be 0
175+
176+
$getJson = @'
177+
{
178+
"keyPath": "HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\Appx",
179+
"valueName": "DSCTestValue"
180+
}
181+
'@
182+
$result = registry config get --input $getJson 2>$null | ConvertFrom-Json
183+
$result.valueName | Should -Be 'DSCTestValue'
184+
$result.valueData.String | Should -Be 'TestData'
185+
186+
$deleteJson = @'
187+
{
188+
"keyPath": "HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\Appx",
189+
"valueName": "DSCTestValue"
190+
}
191+
'@
192+
$out = registry config delete --input $deleteJson 2>$null
193+
$LASTEXITCODE | Should -Be 0
194+
195+
$result = registry config get --input $getJson 2>$null | ConvertFrom-Json
196+
$result._exist | Should -Be $false
197+
$result.valueData | Should -BeNullOrEmpty
198+
}
148199
}

0 commit comments

Comments
 (0)