如何以编程方式授予虚拟用户对文件夹(或文件)的权限
How to programatically grant a virtual user permission to a folder (or file)
我有一个我写的服务需要部署到一些(大约 1100 台)设备上。所有这些 设备都以普通用户而非管理员身份登录。
我可以使用我们的部署软件推出服务,该软件以管理员身份 运行。我们的安全团队不希望此服务在本地系统帐户上 运行(出于显而易见的原因)。我想出的是该服务将安装为本地系统,但随后会将其登录帐户更改为虚拟用户,然后需要访问中的文件夹Program Files (x86)
.
我发现如果我通过命令行安装服务(使用远程管理员访问),我可以安装服务,但是它不会启动.
当我查看事件日志时,我得到一个 UnauthorizedAccessException
错误。
我怀疑这是因为该服务已经 运行 正在虚拟用户 下运行,该用户无权启动该服务 。那么我该如何解决这个问题呢?
在主要的 class 服务中,我有这个方法,应该可以让用户访问必要的文件夹:
private void GiveDirectoryAccess(string dir, string user)
{
try
{
DirectoryInfo directoryInfo = new DirectoryInfo(dir);
DirectorySecurity ds = directoryInfo.GetAccessControl();
ds.AddAccessRule(new FileSystemAccessRule(user, FileSystemRights.FullControl,
InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
directoryInfo.SetAccessControl(ds);
}
catch (Exception e)
{
SimpleLog.Log(e);
throw;
}
}
服务初始化后立即调用:
public CheckRALVersionService()
{
InitializeComponent();
// Give directory access
string alhadminPath = System.IO.Path.Combine(pathToFolder, alhadmin);
GiveDirectoryAccess(alhadminPath, serviceUser);
string exeName = System.IO.Path.GetFileName(fullExeNameAndPath);
string tmppath = System.IO.Path.Combine(localdir, tmp);
SimpleLog.SetLogFile(logDir: tmppath, prefix: "debout." + exeName + "_", extension: "log");
watcher = new DirectoryWatcher(pathToFolder, alhadmin);
}
然后,在ProjectInstaller
class中,我在serviceInstaller1_Committed
方法中将用户更改为虚拟用户:
void serviceInstaller1_Committed(object sender, InstallEventArgs e)
{
using (ManagementObject service = new ManagementObject(new ManagementPath("Win32_Service.Name='RalConfigUpdate'")))
{
object[] wmiParams = new object[11];
wmiParams[6] = @"NT Service\RalConfigUpdate";
service.InvokeMethod("Change", wmiParams);
}
}
我需要帮助服务来授予访问权限吗?我想做的事都可以在这个服务里完成吗?
提前致谢。
一种选择是授予普通用户启动和停止服务的权限。
微软为此提供了一个小工具:SubInAcl!
Set Windows Service Permission!
应该也可以使用组策略来做到这一点。对于您的用例,这应该是更好的方法。另一方面,SubInAcl 方法更容易为您测试。我找到了一个较旧的描述 here!
严格回答你的问题:
你可以使用
System.Io.File.GetAccessControl to get a FileSecurity Class 可用于修改文件系统的权限。
这些链接显示了一些很好的例子。
但是仅当将运行该过程的用户有权更改Windows的权限时才有效,否则= ===> UnauthorizedAccessException
经过一段时间的思考,我找到了解决方案。它可能不是最优雅的,但它应该适合我的目的。我拥有所有“零件”,但只是按错误的顺序做事。
以前,我试图在安装过程中更改用户,但没有成功。我最终做的是允许该服务安装为 LOCAL SYSTEM
帐户,然后在实际程序的 OnStart
方法期间更改为虚拟帐户用户。
所以:
protected override void OnStart(string[] args)
{
string alhadminPath = System.IO.Path.Combine(pathToFolder, alohadmin);
try
{
// Update the service state to start pending
ServiceStatus serviceStatus = new ServiceStatus
{
dwCurrentState = ServiceState.SERVICE_START_PENDING,
dwWaitHint = 100000
};
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
// Update the logs
eventLog1.WriteEntry("Starting Service", EventLogEntryType.Information, eventId++);
SimpleLog.Info("RAL Config Update Service started");
serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
// Change the user to the virutal user
using (ManagementObject service = new ManagementObject(new ManagementPath("Win32_Service.Name='RalConfigUpdate'")))
{
object[] wmiParams = new object[11];
wmiParams[6] = serviceUser;
service.InvokeMethod("Change", wmiParams);
}
GiveDirectoryAccess(alhadminPath, serviceUser);
}
catch (Exception e)
{
eventLog1.WriteEntry("Service failed to start", EventLogEntryType.Error, eventId++);
SimpleLog.Log(e);
throw;
}
}
这是正常的工作方式,也应该满足安全程序。谢谢大家。
我有一个我写的服务需要部署到一些(大约 1100 台)设备上。所有这些 设备都以普通用户而非管理员身份登录。
我可以使用我们的部署软件推出服务,该软件以管理员身份 运行。我们的安全团队不希望此服务在本地系统帐户上 运行(出于显而易见的原因)。我想出的是该服务将安装为本地系统,但随后会将其登录帐户更改为虚拟用户,然后需要访问中的文件夹Program Files (x86)
.
我发现如果我通过命令行安装服务(使用远程管理员访问),我可以安装服务,但是它不会启动.
当我查看事件日志时,我得到一个 UnauthorizedAccessException
错误。
我怀疑这是因为该服务已经 运行 正在虚拟用户 下运行,该用户无权启动该服务 。那么我该如何解决这个问题呢?
在主要的 class 服务中,我有这个方法,应该可以让用户访问必要的文件夹:
private void GiveDirectoryAccess(string dir, string user)
{
try
{
DirectoryInfo directoryInfo = new DirectoryInfo(dir);
DirectorySecurity ds = directoryInfo.GetAccessControl();
ds.AddAccessRule(new FileSystemAccessRule(user, FileSystemRights.FullControl,
InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
directoryInfo.SetAccessControl(ds);
}
catch (Exception e)
{
SimpleLog.Log(e);
throw;
}
}
服务初始化后立即调用:
public CheckRALVersionService()
{
InitializeComponent();
// Give directory access
string alhadminPath = System.IO.Path.Combine(pathToFolder, alhadmin);
GiveDirectoryAccess(alhadminPath, serviceUser);
string exeName = System.IO.Path.GetFileName(fullExeNameAndPath);
string tmppath = System.IO.Path.Combine(localdir, tmp);
SimpleLog.SetLogFile(logDir: tmppath, prefix: "debout." + exeName + "_", extension: "log");
watcher = new DirectoryWatcher(pathToFolder, alhadmin);
}
然后,在ProjectInstaller
class中,我在serviceInstaller1_Committed
方法中将用户更改为虚拟用户:
void serviceInstaller1_Committed(object sender, InstallEventArgs e)
{
using (ManagementObject service = new ManagementObject(new ManagementPath("Win32_Service.Name='RalConfigUpdate'")))
{
object[] wmiParams = new object[11];
wmiParams[6] = @"NT Service\RalConfigUpdate";
service.InvokeMethod("Change", wmiParams);
}
}
我需要帮助服务来授予访问权限吗?我想做的事都可以在这个服务里完成吗?
提前致谢。
一种选择是授予普通用户启动和停止服务的权限。 微软为此提供了一个小工具:SubInAcl!
Set Windows Service Permission!
应该也可以使用组策略来做到这一点。对于您的用例,这应该是更好的方法。另一方面,SubInAcl 方法更容易为您测试。我找到了一个较旧的描述 here!
严格回答你的问题:
你可以使用 System.Io.File.GetAccessControl to get a FileSecurity Class 可用于修改文件系统的权限。 这些链接显示了一些很好的例子。
但是仅当将运行该过程的用户有权更改Windows的权限时才有效,否则= ===> UnauthorizedAccessException
经过一段时间的思考,我找到了解决方案。它可能不是最优雅的,但它应该适合我的目的。我拥有所有“零件”,但只是按错误的顺序做事。
以前,我试图在安装过程中更改用户,但没有成功。我最终做的是允许该服务安装为 LOCAL SYSTEM
帐户,然后在实际程序的 OnStart
方法期间更改为虚拟帐户用户。
所以:
protected override void OnStart(string[] args)
{
string alhadminPath = System.IO.Path.Combine(pathToFolder, alohadmin);
try
{
// Update the service state to start pending
ServiceStatus serviceStatus = new ServiceStatus
{
dwCurrentState = ServiceState.SERVICE_START_PENDING,
dwWaitHint = 100000
};
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
// Update the logs
eventLog1.WriteEntry("Starting Service", EventLogEntryType.Information, eventId++);
SimpleLog.Info("RAL Config Update Service started");
serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
// Change the user to the virutal user
using (ManagementObject service = new ManagementObject(new ManagementPath("Win32_Service.Name='RalConfigUpdate'")))
{
object[] wmiParams = new object[11];
wmiParams[6] = serviceUser;
service.InvokeMethod("Change", wmiParams);
}
GiveDirectoryAccess(alhadminPath, serviceUser);
}
catch (Exception e)
{
eventLog1.WriteEntry("Service failed to start", EventLogEntryType.Error, eventId++);
SimpleLog.Log(e);
throw;
}
}
这是正常的工作方式,也应该满足安全程序。谢谢大家。