概述
最近工作上遇到了和GMSA有关的需求,记录一下实现过程和感悟。
需求
工作上存在一些以域管理员来运行的定时任务,需要替换运行账号,并且对域管理员做安全加固,如不能以域管理员运行批处理脚本和启动服务。同时,我想绕开域账号的密码策略,避免每过一段时间修改账号密码和重新配置任务。所以决定使用GMSA。接下来替换面临几个问题。 - 搞清楚任务执行具体需要什么权限。 - 无法使用GUI界面建立以GMSA为运行账号的定时任务,需要用命令行。 - 对于主机层面,怎么授权其取得对应GMSA的密码,来顺利执行任务。
权限问题
对于我本次修改的任务,脚本主要调用Zoom API,下载日志文件,并存放至本地,最后以邮件通知我自己。权限涉及,1. 文件存放路径赋权。 2. 如何处理GMSA账号发邮件的问题。 对于问题1. 直接对路径赋权,简单。对于问题2. 脚本内使用Send-MailMessage来执行发送邮件,将新的以GMSA账号运行的定时任务建好以后(如何建,后面再提),发现邮件没有发出来。去邮件服务器检查MessageTrackingLog,发现发送失败。在确认已添加匿名中继后,检查前端连接器日志。发现触发了NTLM认证。因为GMSA没有邮件账号,一定会认证失败。Send-MailMessage命令从结果来看,触发认证的优先级要高于匿名发送,所以需要使用其他实现方式来做发邮件。我用C#重构了发邮件功能,并将这个类用Add-Type命令导入到powershell,在powershell内调用类里的方法。此处为代码。
用命令行建定时任务
原本打算用powershell提供的命令行建定时任务,但是面临了新问题,任务需要每个月1号执行一次,powershell原生没有每月一次频率的参数定义。后来用scheduled task api来实现每月一次的定时任务创建,代码在此处。
$arg ="-ExecutionPolicy Bypass -NoProfile -File c:\temp\test.ps1"
$taction = New-ScheduledTaskAction -Execute C:\Windons\System32\Windowsrowershell\vl.0\powershell.exe -Argument $arg
$ttime = New-ScheduledTaskTrigger -At "15:33" -Once
$tprinc = New-ScheduledTaskPrincipal -UserID <domain_name>\gmsaaccount$ -LogonType Password
Register-Scheduledtask taskname -Action $taction -Trigger $ttime -Principal $tprinc
授权主机取得GMSA密码的权限
在新建GMSA的时候,定义PrincipalsAllowedToRetrieveManagedPassword
New-ADServiceAccount -Name gmsaaccount -DNSHostName gmsaaccount.contoso.com -PrincipalsAllowedToRetrieveManagedPassword "<computerobject>"
在执行定时任务所在的主机,添加gmsa到log on as a batch job和log on as a service权限,可以通过组策略或者本地策略来做,推荐用组策略,比较好管理。策略路径Computer Configuration->Windows Settings->Security Settings->Local Policies->User Rights Assign
感悟
当我们用上层方法无法实现需求的时候,应该用底层方法去尝试。