Как инициализировать новую локальную учетную запись для службы Windows?

Как инициализировать новую локальную учетную запись для службы Windows?

Я использую Terraform с Google Cloud для создания хостов Windows Server Core 2019 для использования с Jenkins. Я хочу установить некоторое программное обеспечение, например Git, OpenJDK и другие, используяСовок, и начатьJAR агента Дженкинсакак системная служба, работающая под локальным jenkinsпользователем.

Я настраиваю их с помощью скриптов PowerShell, предоставляемых с помощью metadataключей типа sysprep-specialize-script-ps1и windows-startup-script-ps1:

https://cloud.google.com/compute/docs/startupscript#предоставление_стартового_скрипта_для_экземпляров_windows

Моя проблема в том, что я создаю локальных пользователей с помощью Powershell следующим образом:

New-LocalUser -Name $Username `
    -Description $Description `
    -Password $Password `
    -PasswordNeverExpires `
    -AccountNeverExpires

И я создаю службу агента Jenkins с помощью Windows Service Wrapper: https://github.com/winsw/winsw

Но когда я пытаюсь запустить его без предварительного входа в систему под учетной записью Jenkins, я получаю:

2020-08-26 14:49:57,760 INFO  - Starting the service with id 'JenkinsAgent'
2020-08-26 14:49:57,823 FATAL - WMI Operation failure: ServiceLogonFailure
WMI.WmiException: ServiceLogonFailure
   at WMI.WmiRoot.BaseHandler.CheckError(ManagementBaseObject result)
   at WMI.WmiRoot.InstanceHandler.Invoke(Object proxy, MethodInfo method, Object[] arguments)
   at WinSW.Program.<Run>g__Start|2_2(<>c__DisplayClass2_0& )
   at WinSW.Program.Run(String[] argsArray, IWinSWConfiguration descriptor)
   at WinSW.Program.Main(String[] args)

Эта проблема не возникает, если я сначала вхожу в jenkinsсистему пользователя с помощью RDP, который создает профиль пользователя при первом входе. Я предполагаю, что это позволяет службе запускаться правильно.

Я пытаюсь понять, как создать пользователя и его профиль без необходимости вручную входить в систему, чтобы служба могла правильно запуститься. Скрипты настройки и запуска PS выполняются от имени SYSTEMпользователя, что может быть причиной того, что использование чего-то вроде Start-Process, Invoke-Commandили Start-Jobс -Credentialфлагом для запуска команды от имени jenkinsпользователя, чтобы создать его профиль, не удается.

У меня возникли проблемы при попытке выполнить команду или просто exitкак jenkinsпользователь, например:

[localhost] The background process reported an error with the following message: .
    + CategoryInfo          : OpenError: (localhost:String) [], PSRemotingTransportException
    + FullyQualifiedErrorId : 2100,PSSessionStateBroken

Что я делаю не так?

Есть ли лучший способ достичь того, чего я пытаюсь добиться?

Как создать локального пользователя?сего профиль, чтобы созданная мной служба запустилась?

решение1

На основе ответов на связанный вопросесть три способа (которые выглядят наиболее многообещающими):

  1. ИспользоватьAPI CreateProfile

  2. Использовать Powershell какописано в этом ответе- ты найдешьпример на GitHub- в этом случае вы сможете определить путь к домашнему каталогу. Часть кода, которая определяет путь к профилю:

    $methodName = 'UserEnvCP'
    $script:nativeMethods = @();

    Register-NativeMethod "userenv.dll" "int CreateProfile([MarshalAs(UnmanagedType.LPWStr)] string pszUserSid,`
      [MarshalAs(UnmanagedType.LPWStr)] string pszUserName,`
      [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszProfilePath, uint cchProfilePath)";

    Add-NativeMethods -typeName $MethodName;

    $localUser = New-Object System.Security.Principal.NTAccount("$UserName");
    $userSID = $localUser.Translate([System.Security.Principal.SecurityIdentifier]);
    $sb = new-object System.Text.StringBuilder(260);
    $pathLen = $sb.Capacity;
 
    Write-Verbose "Creating user profile for $Username";
    try
    {
        [UserEnvCP]::CreateProfile($userSID.Value, $Username, $sb, $pathLen) | Out-Null;
    }
    catch
    {
        Write-Error $_.Exception.Message;
        break;
    }
  1. Использовать psexecутилиту Это выглядит как простой метод, но я не уверен, будет ли он работать в Ansible. psexec.exe -u foobar -p Abcd123! cmd.exe /c exit Вотбольше информации оpsexecинструмент.

Связанный контент