Initial Commit
This commit is contained in:
55
PatchProbe.Cli/Auth/DpapiCredentialStore.cs
Normal file
55
PatchProbe.Cli/Auth/DpapiCredentialStore.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace PatchProbe.Cli.Auth;
|
||||
|
||||
internal sealed class DpapiCredentialStore : IDeviceCredentialStore
|
||||
{
|
||||
// %ProgramData%\PatchProbe\device.cred — machine-scoped, survives user changes
|
||||
internal static readonly string StorePath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
|
||||
"PatchProbe", "device.cred");
|
||||
|
||||
public bool IsEnrolled => File.Exists(StorePath);
|
||||
|
||||
public DeviceCredentials Load()
|
||||
{
|
||||
var cipher = File.ReadAllBytes(StorePath);
|
||||
var plain = ProtectedData.Unprotect(cipher, null, DataProtectionScope.LocalMachine);
|
||||
return JsonSerializer.Deserialize<DeviceCredentials>(Encoding.UTF8.GetString(plain))
|
||||
?? throw new InvalidOperationException("Credential file is corrupt or empty.");
|
||||
}
|
||||
|
||||
public void Save(DeviceCredentials credentials)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(StorePath)!;
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
var plain = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(credentials));
|
||||
var cipher = ProtectedData.Protect(plain, null, DataProtectionScope.LocalMachine);
|
||||
|
||||
File.WriteAllBytes(StorePath, cipher);
|
||||
RestrictToAdmins(StorePath);
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
if (File.Exists(StorePath))
|
||||
File.Delete(StorePath);
|
||||
}
|
||||
|
||||
private static void RestrictToAdmins(string path)
|
||||
{
|
||||
var fi = new FileInfo(path);
|
||||
var acl = fi.GetAccessControl();
|
||||
// Break inheritance; grant only SYSTEM and Administrators full control
|
||||
acl.SetAccessRuleProtection(isProtected: true, preserveInheritance: false);
|
||||
acl.AddAccessRule(new FileSystemAccessRule(
|
||||
"SYSTEM", FileSystemRights.FullControl, AccessControlType.Allow));
|
||||
acl.AddAccessRule(new FileSystemAccessRule(
|
||||
"Administrators", FileSystemRights.FullControl, AccessControlType.Allow));
|
||||
fi.SetAccessControl(acl);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user