Christian Long's Blog

May 18, 2015

Twisted on Windows, 2015 Edition: Part 3

Recap

In Part 1, we set up Twisted. In Part 2, we configured Twisted to run as a Windows service. Now, we will assign the right permissions to the account that the service is using.

Windows file permissions

Windows implements file-level security through access control lists. Windows provides the icacls utility to query and set permissions at the command line.

For example

icacls C:\PythonEnvs\Example /grant "nt service\my_service":(OI)(CI)RX

Let’s break this down:

  • C:\PythonEnvs\Example - The folder you want to change permissions on
  • /grant - Grant rights additively
  • "nt service\my_service" - The name of the virtual service account
  • (OI)(CI) - Applies the grant recursively to this folder, subfolders, and files
  • RX - Grants Read and Execute access

Inheritance mode

Inherited folder permissions are specified as:

  • OI - Object inherit - This folder and files (no inheritance to subfolders)
  • CI - Container inherit - This folder and subfolders
  • IO - Inherit only - The ACE does not apply to the current file/directory

These can also be combined:

  • (OI)(CI) this folder, subfolders, and files
  • (OI)(CI)(IO) subfolders and files only
  • (CI)(IO) subfolders only
  • (OI) (IO) files only

So BUILTIN\Administrators:(OI)(CI)F means that both files and subfolders will inherit ‘F’ (Full Control)

Similarly (CI)R means folders will inherit ‘R’ (Read folders only = List permission)

SS64 has a good reference for the icacls options.

Troubleshooting permissions

Many Windows admin tasks require the wonderful Sysinternals tools, written by Mark Russinonvich. The first thing I do on a new Windows server is download the Sysinternals Suite and put it on the system path. For this troubleshooting section, I’ll be using the psexec tool.

Whenever a service is not working, it’s helpful to try running it by hand, in the same user account and environment that the service is trying to run in. As far as I know, there is no way to run commands manually as a virtual service account (NT SERVICE\my_service). Put another way, there is no equivalent of su - <user> that can be used for virtual service accounts. However, we can approximate it. We can use psexec to run commands as the LocalService account (NT AUTHORITY\LocalService). It’s far from perfect, but if we can get it working under the LocalService account, chances are we can then get it working under a virtual service account.

Let’s look at some steps we can take to investigate permissions problems. First, open a new admin command prompt. On Windows 8 and newer, “Win-x then a” is a quick way to open an admin command prompt.

Here’s how to execute a single command, under the LocalService account.

psexec -u "NT AUTHORITY\LocalService" C:\PythonEnvs\Example\Scripts\pip freeze

The -u option tells psexec what user to run as. The rest of the line is the command that you want psexec to run. Notice that we pass the full path to the pip inside the virtualenv. pip freeze prints a list of the packages that are installed.

If you get a “Couldn’t install PSEXESVC service” error, try running psexec as administrator.

Here’s another example. We’re telling Python to import the pyodbc module, and print “ok” if it succeeds.

psexec -u "NT AUTHORITY\LocalService" C:\PythonEnvs\Example\Scripts\python -c "import odbc; print 'ok'"

Here’s how to start a new interactive shell in a new window, running as the LocalService user.

psexec -u "NT AUTHORITY\LocalService" -i cmd /k

It should look something like this.

New interactive shell screenshot

In the screenshot above, I have used the whoami command to show that, in the new console window, we are running as NT AUTHORITY\LocalService.

If you want to start a new interactive session as a different user, but stay in your current command window, omit the -i argument to psexec.

psexec -u "NT AUTHORITY\LocalService" cmd /k

Since Windows does not print the username in the shell prompt, it can be hard to know what user you are running as. Use the whoami command to see the current user.

The whoami /all command shows a lot of useful information about the user, groups and privileges.

whoami all screenshot

Two things to keep in mind when using psexec to troubleshoot. One, it must be called from an admin command prompt (Win-x then a). Two, you can not use psexec to run commands as a virtual service account.

When I’m setting up Windows service, I configure it to run under the LocalService account at first, and I use psexec to track down any permissions problems. Then I switch the service over to a virtual service account. I grant the virtual service account the same privileges that I granted to the LocalService account.

Zip files

You may find that the virtual service accounts you’re using to run the services don’t have permission to handle zip files. This may be due to a policy restriction set by your network administrator. The LocalService account may have the same restriction.

This is why, when I’m installing pyodbc, I have to pass the --always-unzip option to easy_install. Otherwise, easy_install installs it as a zip file, and the virtual service account doesn’t have permission to read it.

Another example: on Windows, distutils packages source distributions as zip files. Let’s say for example you’re running python’s simpleHTTPServer as a Windows service (using nssm), running it as account nt service\package_server. You can visit http://localhost:8000 and you get a nice file listing. However, if you try to download one of the zip files, you get a 404. Assigning permissions for nt service\package_server doesn’t work - the permissions apply to folders and text files but they don’t apply to zip files through inheritance. It only works if you assign read permission specifically for the zip file itself.

Here’s a command to specifically assign permissions for a zip file

 icacls "C:\PackageServer\www\downloads\My_Package-0.0.1.zip" /grant "nt service\package_server":R

By your leave

We’ve come to the end of Part 3. The virtual service account under which the service is running has been assigned the permissions it needs.

Note that these commands can be used for any service you are running on Windows, not only those using Twisted or NSSM.

Thanks for following along, and find me on Twitter at @christianmlong if you have any suggestions or fixes.