// deploys the generic worker as a windows service, running under the windows // user specified with username/password, such that the generic worker runs // with the given configuration file configFile. the http://nssm.cc/ executable // is required to install the service, specified as a file system path. The // serviceName is the service name given to the newly created service. if the // service already exists, it is simply updated. func deployService(user *runtime.OSUser, configFile, nssm, serviceName, exePath, dir string) error { return runtime.RunCommands( false, []string{nssm, "install", serviceName, exePath}, []string{nssm, "set", serviceName, "AppDirectory", dir}, []string{nssm, "set", serviceName, "AppParameters", "--config", configFile, "--configure-for-aws", "run"}, []string{nssm, "set", serviceName, "DisplayName", serviceName}, []string{nssm, "set", serviceName, "Description", "A taskcluster worker that runs on all mainstream platforms"}, []string{nssm, "set", serviceName, "Start", "SERVICE_AUTO_START"}, []string{nssm, "set", serviceName, "ObjectName", ".\\" + user.Name, user.Password}, []string{nssm, "set", serviceName, "Type", "SERVICE_WIN32_OWN_PROCESS"}, []string{nssm, "set", serviceName, "AppPriority", "NORMAL_PRIORITY_CLASS"}, []string{nssm, "set", serviceName, "AppNoConsole", "1"}, []string{nssm, "set", serviceName, "AppAffinity", "All"}, []string{nssm, "set", serviceName, "AppStopMethodSkip", "0"}, []string{nssm, "set", serviceName, "AppStopMethodConsole", "1500"}, []string{nssm, "set", serviceName, "AppStopMethodWindow", "1500"}, []string{nssm, "set", serviceName, "AppStopMethodThreads", "1500"}, []string{nssm, "set", serviceName, "AppThrottle", "1500"}, []string{nssm, "set", serviceName, "AppExit", "Default", "Restart"}, []string{nssm, "set", serviceName, "AppRestartDelay", "0"}, []string{nssm, "set", serviceName, "AppStdout", filepath.Join(dir, "generic-worker.log")}, []string{nssm, "set", serviceName, "AppStderr", filepath.Join(dir, "generic-worker.log")}, []string{nssm, "set", serviceName, "AppStdoutCreationDisposition", "4"}, []string{nssm, "set", serviceName, "AppStderrCreationDisposition", "4"}, []string{nssm, "set", serviceName, "AppRotateFiles", "1"}, []string{nssm, "set", serviceName, "AppRotateOnline", "1"}, []string{nssm, "set", serviceName, "AppRotateSeconds", "3600"}, []string{nssm, "set", serviceName, "AppRotateBytes", "0"}, ) }
func deleteTaskDir(path string, user string) error { if !config.CleanUpTaskDirs { log.Print("*NOT* Removing home directory '" + path + "' as 'cleanUpTaskDirs' is set to 'false' in generic worker config...") return nil } log.Print("Trying to remove directory '" + path + "' via os.RemoveAll(path) call as GenericWorker user...") err := os.RemoveAll(path) if err == nil { return nil } log.Print("WARNING: could not delete directory '" + path + "' with os.RemoveAll(path) method") log.Printf("%v", err) log.Print("Trying to remove directory '" + path + "' via del command as GenericWorker user...") err = runtime.RunCommands( false, []string{ "cmd", "/c", "del", "/s", "/q", "/f", path, }, ) if err != nil { log.Printf("%#v", err) } return err }
// see http://ss64.com/nt/icacls.html func makeDirUnreadable(dir string) error { if taskContext.DesktopSession == nil { return nil } return runtime.RunCommands( false, []string{"icacls", dir, "/remove:g", taskContext.DesktopSession.User.Name}, ) }
// see http://ss64.com/nt/icacls.html func makeDirReadable(dir string) error { if config.RunTasksAsCurrentUser { return nil } return runtime.RunCommands( false, []string{"icacls", dir, "/grant:r", taskContext.DesktopSession.User.Name + ":(OI)(CI)F"}, ) }
func (task *TaskRun) addGroupsToUser(groups []string) error { if len(groups) == 0 { return nil } commands := make([][]string, len(groups), len(groups)) for i, group := range groups { commands[i] = []string{"net", "localgroup", group, "/add", taskContext.DesktopSession.User.Name} } return runtime.RunCommands(false, commands...) }
func deleteOSUserAccount(line string) { if strings.HasPrefix(line, "task_") { user := line log.Print("Attempting to remove Windows user " + user + "...") err := runtime.RunCommands(false, []string{"net", "user", user, "/delete"}) if err != nil { log.Print("WARNING: Could not remove Windows user account " + user) log.Printf("%v", err) } } }
func deployStartup(user *runtime.OSUser, configFile string, exePath string) error { scheduledTaskUTF8 := []byte(strings.Replace(`<?xml version="1.0" encoding="UTF-16"?> <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <Date>2016-04-28T17:25:08.4654422</Date> <Author>GenericWorker</Author> <Description>Runs the generic worker.</Description> </RegistrationInfo> <Triggers> <LogonTrigger> <Enabled>true</Enabled> <UserId>GenericWorker</UserId> </LogonTrigger> </Triggers> <Principals> <Principal id="Author"> <UserId>GenericWorker</UserId> <LogonType>InteractiveToken</LogonType> <RunLevel>HighestAvailable</RunLevel> </Principal> </Principals> <Settings> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> <AllowHardTerminate>true</AllowHardTerminate> <StartWhenAvailable>false</StartWhenAvailable> <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> <IdleSettings> <StopOnIdleEnd>true</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <AllowStartOnDemand>true</AllowStartOnDemand> <Enabled>true</Enabled> <Hidden>false</Hidden> <RunOnlyIfIdle>false</RunOnlyIfIdle> <WakeToRun>false</WakeToRun> <ExecutionTimeLimit>PT0S</ExecutionTimeLimit> <Priority>3</Priority> </Settings> <Actions Context="Author"> <Exec> <Command>C:\generic-worker\run-generic-worker.bat</Command> </Exec> </Actions> </Task>`, "\n", "\r\n", -1)) utf16Encoder := unicode.UTF16(unicode.LittleEndian, unicode.UseBOM).NewEncoder() scheduledTaskUTF16, err := utf16Encoder.Bytes(scheduledTaskUTF8) if err != nil { return fmt.Errorf("INTERNAL ERROR: Could not UTF16-encode (static) scheduled task: %s\n\nError received: %s", scheduledTaskUTF8, err) } xmlFilePath := filepath.Join(filepath.Dir(exePath), "Run Generic Worker.xml") err = ioutil.WriteFile(xmlFilePath, scheduledTaskUTF16, 0644) if err != nil { return fmt.Errorf("I was not able to write the file \"Run Generic Worker.xml\" to file location %q with 0644 permissions, due to: %s", xmlFilePath, err) } err = runtime.RunCommands(false, []string{"schtasks", "/create", "/tn", "Run Generic Worker on login", "/xml", xmlFilePath}) if err != nil { return fmt.Errorf("Not able to schedule task \"Run Generic Worker on login\" using schtasks command, due to error: %s\n\nAlso see stderr/stdout logs for output of the command that failed.", err) } k, _, err := registry.CreateKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`, registry.WRITE) if err != nil { return fmt.Errorf(`Was not able to create registry key 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' due to %s`, err) } defer k.Close() err = k.SetDWordValue("AutoAdminLogon", 1) if err != nil { return fmt.Errorf(`Was not able to set registry entry 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon' to 1 due to %s`, err) } err = k.SetStringValue("DefaultUserName", user.Name) if err != nil { return fmt.Errorf(`Was not able to set registry entry 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName' to %q due to %s`, user.Name, err) } err = k.SetStringValue("DefaultPassword", user.Password) if err != nil { return fmt.Errorf(`Was not able to set registry entry 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword' to %q due to %s`, user.Password, err) } batScriptFilePath := filepath.Join(filepath.Dir(exePath), "run-generic-worker.bat") batScriptContents := []byte(strings.Join([]string{ `:: run the generic worker`, ``, `:: cd to folder containing this script`, `pushd %~dp0`, ``, `.\generic-worker.exe run --configure-for-aws > .\generic-worker.log 2>&1`, }, "\r\n")) err = ioutil.WriteFile(batScriptFilePath, batScriptContents, 0755) if err != nil { return fmt.Errorf("Was not able to create file %q with access permissions 0755 due to %s", batScriptFilePath, err) } return nil }