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 filesRX
- 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.
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.
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.