Wie initialisiere ich ein neues lokales Konto für einen Windows-Dienst?

Wie initialisiere ich ein neues lokales Konto für einen Windows-Dienst?

Ich verwende Terraform mit Google Cloud, um Windows Server Core 2019-Hosts für die Verwendung mit Jenkins zu erstellen. Ich möchte einige Software wie Git, OpenJDK und andere installieren, indem ichScoopund starten Sie denJenkins Agent JARals Systemdienst, der unter einem lokalen jenkinsBenutzer ausgeführt wird.

Ich richte sie mithilfe von PowerShell-Skripts ein, die über metadataSchlüssel wie sysprep-specialize-script-ps1und bereitgestellt werden windows-startup-script-ps1:

https://cloud.google.com/compute/docs/startupscript#providing_a_startup_script_for_windows_instances

Mein Problem besteht darin, dass ich lokale Benutzer mit Powershell wie folgt erstelle:

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

Und ich erstelle einen Jenkins-Agent-Dienst mit Windows Service Wrapper: https://github.com/winsw/winsw

Aber wenn ich versuche, es auszuführen, ohne mich zuerst als Jenkins-Benutzer anzumelden, erhalte ich Folgendes:

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)

Dieses Problem tritt nicht auf, wenn ich mich zuerst jenkinsüber RDP beim Benutzer anmelde, wodurch das Benutzerprofil bei der ersten Anmeldung erstellt wird. Ich gehe davon aus, dass dies den korrekten Start des Dienstes ermöglicht.

Ich versuche herauszufinden, wie ich einen Benutzer und sein Profil erstellen kann, ohne mich manuell als Benutzer anmelden zu müssen, damit der Dienst korrekt gestartet werden kann. Die Setup- und Start-PS-Skripte werden als SYSTEMBenutzer ausgeführt. Dies könnte der Grund sein, warum die Verwendung von etwas wie Start-Process, Invoke-Commandoder Start-Jobmit -CredentialFlag zum Ausführen eines Befehls als jenkinsBenutzer zum Erstellen seines Profils fehlschlägt.

Ich hatte Probleme beim Ausführen eines Befehls oder einfach exitals jenkinsBenutzer wie folgt:

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

Was mache ich falsch?

Gibt es eine bessere Möglichkeit, mein Ziel zu erreichen?

Wie kann ich einen lokalen Benutzer erstellenmitsein Profil, damit der von mir erstellte Dienst startet?

Antwort1

Basierend auf Antworten auf eine verknüpfte FrageEs gibt drei Möglichkeiten (die am vielversprechendsten erscheinen):

  1. VerwendenCreateProfile-API

  2. Verwenden Sie Powershell alsin dieser Antwort beschrieben- du wirst findenBeispiel auf GitHub- in diesem Fall können Sie den Home-Verzeichnispfad definieren. Teil des Codes, der den Profilpfad definiert:

    $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. psexecDienstprogramm verwenden Das sieht nach einer unkomplizierten Methode aus, aber ich bin mir nicht sicher, ob es Ansible ist. psexec.exe -u foobar -p Abcd123! cmd.exe /c exit Hier istmehr Infos überpsexecWerkzeug.

verwandte Informationen