Search code examples
powershellscheduled-taskspowershell-2.0powershell-remoting

Minimum privilege for Powershell Remoting user to create a Task on Task Schedular


I want to enable running few jobs remotely on various Windows Nodes on some random interval. I can use PS remoting to logon to a remote computer and create a task there to run it under some specific user account.

In order for PS Remoting to work, I understand that I don't need to be an admin from the following article however I am unable to understand what is the minimum privilege needed to schedule a task on that remote machine for this script user.

I don't want to use an Admin account as this can be a security risk that I open up on those machines.

Can some one please help me out. I am using a C# application to initiate the remote powershell connection to that computer as below.

private void StartCollection(string triggerId, ActivationData parameters)
        {
            string scriptUserName = parameters.Params["PSUser"];
            string scriptUserPassword = parameters.Params["PSUserPassword"];
            string remotecomputerName = parameters.Params["ComputerName"];
            string scheme = parameters.Params["PSScheme"];
            string port = parameters.Params["PSPort"];
            var agentFile = Path.Combine(parameters.AssemblyPath, parameters.FileName);

            List<string> allParams = new List<string>();

            allParams.Add(String.Format("-trigger {0} -collector {1} ", triggerId, parameters.CollectorId));
            allParams.Add(String.Format("-monitored_by {0} -monitored_at {1}", parameters.Monitoring.Name, parameters.Monitoring.InterfacePoint));

            foreach (var param in parameters.Params)
            {
                if (!ConfigurationKeys.Contains(param.Key))
                {
                    allParams.Add(string.Format("-{0} {1}", param.Key, param.Value));
                }
            }

            var cmdLineParams = string.Join(" ", allParams.ToArray());

            // Cred to execute PS on the remote computer.
            SecureString securePassword = scriptUserPassword.ToSecureString();
            PSCredential scriptCred = new PSCredential(scriptUserName, securePassword);

            var remoteUriStr = String.Format("{0}://{1}:{2}/wsman", scheme, remotecomputerName, port);
            var remoteComputer = new Uri(remoteUriStr);

            var connection = String.IsNullOrEmpty(scriptUserName) ? new WSManConnectionInfo(remoteComputer) : new WSManConnectionInfo(remoteComputer, null, scriptCred);
            //connection.AuthenticationMechanism = AuthenticationMechanism.Credssp;

            var runspace = RunspaceFactory.CreateRunspace(connection);
            runspace.Open();

            using (var powershell = PowerShell.Create())
            {
                powershell.Runspace = runspace;

                //Cred to run the agent under: Job credential.
                SecureString jobPass = parameters.UserCred.Item2.ToSecureString();
                string jonUser = parameters.UserCred.Item1;
                PSCredential jobCred = new PSCredential(jonUser, jobPass);

                var scriptfile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Start-Program.ps1");
                Command command = new Command(scriptfile);
                command.Parameters.Add("ComputerName", remotecomputerName);
                command.Parameters.Add("StartTime", "22:50");
                command.Parameters.Add("Program", agentFile);
                command.Parameters.Add("Parameters", cmdLineParams);
                command.Parameters.Add("TaskCredential", jobCred);

                powershell.Commands.AddCommand(command);

                var results = powershell.Invoke();

                runspace.Close();

                Console.WriteLine("Outputing the PS1 Result: {0}: " ,parameters.CollectorId);
                foreach (var obj in results.Where(o => o != null))
                {
                    Console.WriteLine("\t" + obj);
                }
                if (powershell.Streams.Error.Count > 0)
                {

                    var errors = from err in powershell.Streams.Error select err.ErrorDetails.Message;
                    throw new Exception(String.Join(Environment.NewLine, errors.ToArray()));
                }
            }
        } 

Solution

  • Once you set the PS Remoting permissions, the simple way to give them Task Scheduling access would be to make your remote users a member of the local "Backup Operators" group on the target server. This would give them the necessary permissions to schedule and manage tasks on the server but would also give them indirect read access to files on that server.

    If that's still too much access, then I've seen references to granting control of the C:\Windows\Tasks folder on the target server through ACLs but I've never tried that myself.