Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task Fails to run under different user account #976

Open
fritznkitz opened this issue Oct 16, 2023 · 5 comments
Open

Task Fails to run under different user account #976

fritznkitz opened this issue Oct 16, 2023 · 5 comments

Comments

@fritznkitz
Copy link

Describe the bug
After creating a task to run for one user (with highest privileges), it will run for that user. But if you log in as another user, it will not run, saying the user does not have permission.

To Reproduce
Steps to reproduce the behavior:

  1. Create Task using RegisterTaskDefinition("TaskName", def, TaskCreation.CreateOrUpdate, runnerUserName, runnerUserPwd, TaskLogonType.Password);
  2. Log on to the server using a different account
  3. Open Task Scheduler and try to run the task created in step 1

Expected behavior
I expect the task to run, however it gives a permissions error.

Environment (please complete the following information):

  • Windows Server 2019

Additional context
As per https://learn.microsoft.com/en-us/answers/questions/707600/task-scheduler-the-user-account-does-not-have-perm
if one exports the task to xml, deletes the task and then imports it, it will then work for all uses. Or if I run the powershell script (there's a link to it from that page) on the task, it will work. It has to do with some permissions being now stored in the registry.

I have done done some searching but can't find a similar posting to this, but apologize if this is a duplicate or if it is handled by code somehow already.

@CWIWC
Copy link

CWIWC commented Oct 17, 2023

I do this all the time, but I don't do it like you are,
there are issues with this method when dealing with azure users so this will not work for that.

//create my task instance
TaskDefinition td = TaskService.Instance.NewTask();
//create the name of your task
td.RegistrationInfo.Description = "YOURTASKNAME";
//set the elevation level 
td.Principal.RunLevel = TaskRunLevel.Highest;
//set your username
td.Principal.UserId = userName;
//dont start on battery set to false
td.Settings.DisallowStartIfOnBatteries = false;
//stop if on battery set to false
td.Settings.StopIfGoingOnBatteries = false;

//you would also use the td object to add triggers like on boot or on logon triggers, they would be added like the fallowing

//td.Settings.RunOnlyIfLoggedOn = true;
//BootTrigger bt = new BootTrigger();
//LogonTrigger lot = new LogonTrigger();
//lot.Delay = TimeSpan.FromMinutes(1);
//bt.Delay = TimeSpan.FromMinutes(1);
//td.Triggers.Add(bt);
//td.Triggers.Add(lot);

//add our actions here, in my case the app i want to launch and its args
 td.Actions.Add(cmdPath, cmdArgs);
 //set your password, this is NOT needed if your running as system or "nt authority/system" (you can test with psexec reflecting)
 //this is the one i use and know is working. like 1000+ machines working.
 TaskService.Instance.RootFolder.RegisterTaskDefinition($"{taskName}", td);
 //OR
//this is not tested but should work, but i dont use passwords to make tasks, as i dont know the passwords for my clients login and should not know them.
TaskService.Instance.RootFolder.RegisterTaskDefinition($"{taskName}", td, TaskCreation.CreateOrUpdate, userName, PASSWORD);
  try
 {
		TaskService.Instance.FindTask($"LaunchAsUser-{userTag}").Run();
	}
 catch (Exception ex)
 {
		Console.WriteLine($"{ex.Message}")
		if (ex.InnerException != null)
		{
        Console.WriteLine($"{ex.InnerException.Message}")
     }
 }

It should also let you create a task for yourself without a password but if you want to be your user, and to make a task for any other user as a user, even as admin, you will need the password.

This may not help you, but I hope it solves your issue or at least gives you a path to what you want.

@CWIWC
Copy link

CWIWC commented Oct 17, 2023

with azure users, the user can make the task for himself,
the system can not make tasks for the azure user.

I have not tried to get an azure user to make a task for an azure user.

@fritznkitz
Copy link
Author

fritznkitz commented Oct 18, 2023

Thank you for your response. The only significant differences in our approaches were that you set
td.Principal.UserId = userName;
and that you don't set the username & password explicitly. We see it it as security issue and need to set the username & password. We have been using this library for over 10 years on regular Windows Domain accounts (not Azure) and on Windows Server 2008 up to 2019 now. It is as we are changing some of our other practices that this issue has become illuminated. The case is that we wish to create tasks to run on a schedule under a particular account, and yet allow another user admin account to run the task on from the task scheduler ad hoc.

I have changed it to set the td.Principal.UserId, as well as the option to set the username & password in the RegisterTaskDefinition (as we were doing before), and it still does not work to try to run the task from the task scheduler when logged in as another admin user. However, if we do as that link I provided in my original post suggests and and export, delete and reimport the task, then it will run as desired.

if it helps, here's a massaged version of the my code that creates the task:

using (TaskService ts = new TaskService())
{
    if (ts.FindTask(Name) != null)
    {
       // handle task already existing
        return ;
    }
    TaskDefinition def = ts.NewTask();
    def.RegistrationInfo.Description = Name;  // Name defined elsewhere
    def.Actions.Add(new ExecAction(Program, Parameters)); // Program and Parameters defined elsewhere
    def.Triggers.Add(OneTrigger); // OneTrigger defined elsewhere
    def.Settings.IdleSettings.IdleDuration = new TimeSpan(0, IdleWaitMinutes, 0);
    def.Settings.Priority = System.Diagnostics.ProcessPriorityClass.Normal;
    if (OneTrigger.EndBoundary != DateTime.MaxValue)
        def.Settings.DeleteExpiredTaskAfter = new TimeSpan(7, 0, 0, 0);

    def.Principal.RunLevel = TaskRunLevel.Highest;
    def.Principal.UserId = RunnerUser;

    try
    {
        ts.RootFolder.RegisterTaskDefinition(Name, def, TaskCreation.CreateOrUpdate, RunnerUser, RunnerPwd, TaskLogonType.Password);
    }
    catch (Exception ex)
    {
        ts.RootFolder.DeleteTask(Name); // so that there's not some 'bad' task hanging out there...
        // handle exception 
    }
}

Thank you for your comments and suggestions.

@CWIWC
Copy link

CWIWC commented Oct 31, 2023

I would argue that having access to passwords is less secure then having access to system if you already have system, but that is irrelevant.

I took your code and made some slight changes
The fallowing is tested and WORKS for me.
The user was an administrator.

First I created a project and added the app manifest file and set the project to "requireAdministrator"
image

This will prevent the unauthorized action error.

Here is my working code, TESTED, where I use a logon trigger for my test, this does launch notepad under the "TestUser" i created for this process and logged into 1 time before hand.


public void Run()
        {

            string Name = "ExampleTaskPerUser";
            string username = "TestUser";
            string password = "TestUser";
            TimeTrigger trigger = new TimeTrigger();
            //for my testing to verify this works
            LogonTrigger bootTrigger = new LogonTrigger();
            bootTrigger.Enabled = true;
            // example of getting a parameter. will return "FAIL" if not present. remove if not needed.
            using (TaskService ts = new TaskService())
            {
                if (ts.FindTask(Name) != null)
                {
                    // handle task already existing
                    return;
                }
                TaskDefinition def = ts.NewTask();
                def.RegistrationInfo.Description = Name;  // Name defined elsewhere
                def.Actions.Add(new ExecAction("C:\\Windows\\System32\\notepad.exe")); // Program and Parameters defined elsewhere
                def.Settings.Priority = System.Diagnostics.ProcessPriorityClass.Normal;
                //changed by me
                if (trigger.EndBoundary != DateTime.MaxValue)
                    def.Settings.DeleteExpiredTaskAfter = new TimeSpan(7, 0, 0, 0);
                //============

                //added by me
                def.Triggers.Add(trigger);
                def.Triggers.Add(bootTrigger);
                //===========


                def.Principal.RunLevel = TaskRunLevel.Highest;
                def.Principal.UserId = username;


                try
                {
                    ts.RootFolder.RegisterTaskDefinition(Name, def, TaskCreation.CreateOrUpdate, username, password, TaskLogonType.InteractiveTokenOrPassword);
                }
                catch (Exception ex)
                {       
                    Console.WriteLine(ex.Message);// handle exception 
                    if (ex.InnerException != null)
                    {
                        Console.WriteLine(ex.InnerException.Message);
                    }
                    ts.RootFolder.DeleteTask(Name);
                }
            }
        }
        

I hope the above helps out and that I did not respond to late.

@CWIWC
Copy link

CWIWC commented Oct 31, 2023

We see it it as security issue and need to set the username & password. We have been using this library for over 10 years on regular Windows Domain accounts (not Azure) and on Windows Server 2008 up to 2019 now. It is as we are changing some of our other practices that this issue has become illuminated. The case is that we wish to create tasks to run on a schedule under a particular account, and yet allow another user admin account to run the task on from the task scheduler ad hoc.

I'm semi confused by the ad hoc run part of your requirement, but if the task exists for the the user in question without a trigger they could run the task from task scheduler at any time.

But i may just not understand exactly what you meant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants