> On Feb 16, 2016, at 6:12 PM, Glyph Lefkowitz <gl...@twistedmatrix.com> wrote:
> 
>> 
>> On Feb 16, 2016, at 5:00 PM, Noah Kantrowitz <n...@coderanger.net> wrote:
>> 
>> 
>>> On Feb 16, 2016, at 4:46 PM, Glyph Lefkowitz <gl...@twistedmatrix.com> 
>>> wrote:
>>> 
>>>> 
>>>> On Feb 16, 2016, at 4:33 PM, Noah Kantrowitz <n...@coderanger.net> wrote:
>>>> 
>>>> 
>>>>> On Feb 16, 2016, at 4:27 PM, Glyph Lefkowitz <gl...@twistedmatrix.com> 
>>>>> wrote:
>>>>> 
>>>>> 
>>>>>> On Feb 16, 2016, at 4:13 PM, Noah Kantrowitz <n...@coderanger.net> wrote:
>>>>>> 
>>>>>> As someone that handles the tooling side, I don't care how it works as 
>>>>>> long as there is an override for tooling a la Chef/Puppet. For stuff 
>>>>>> like Supervisord, it is usually the least broken path to install the 
>>>>>> code globally.
>>>>> 
>>>>> I don't know if this is the right venue for this discussion, but I do 
>>>>> think it would be super valuable to hash this out for good.
>>>>> 
>>>>> Why does supervisord need to be installed in the global Python 
>>>>> environment?
>>>> 
>>>> Where else would it go? I wouldn't want to assume virtualenv is installed 
>>>> unless absolutely needed.
>>> 
>>> This I can understand, but: in this case, it is needed ;).
>>> 
>>>> Virtualenv is a project-centric view of the world which breaks down for 
>>>> stuff that is actually global like system command line tools.
>>> 
>>> [citation needed].  In what way does it "break down"?  
>>> https://pypi.python.org/pypi/pipsi is a nice proof-of-concept that 
>>> dedicated virtualenvs are a better model for tooling than a big-ball-of-mud 
>>> integrated system environment that may have multiple conflicting 
>>> requirements.  Unfortunately it doesn't directly address this use-case 
>>> because it assumes that it is doing per-user installations and not a 
>>> system-global one, but the same principle holds: what version of 
>>> `ipaddress´ that supervisord wants to use is irrelevant to the tools that 
>>> came with your operating system, and similarly irrelevant to your 
>>> application.
>>> 
>>> To be clear, what I'm proposing here is not "shove supervisord into a venv 
>>> with the rest of your application", but rather, "each application should 
>>> have its own venv".  In supervisord's case, "python" is an implementation 
>>> detail, and therefore the public interface is /usr/bin/supervisord and 
>>> /usr/bin/supervisorctl, not 'import supervisord'; those should just be 
>>> symlinks into /usr/lib/supervisord/environment/bin/
>> 
>> That isn't a thing that exists currently, I would have to make it myself and 
>> I wouldn't expect users to assume that is how I made it work. Given the 
>> various flavors of user expectations and standards that exist for deploying 
>> Python code, global does the least harm right now.
> 
> I don't think users who install supervisord necessarily think they ought to 
> be able to import supervisord.  If they do expect that, they should probably 
> revise their expectations.
> 
> Here, I'll make it for you.  Assuming virtualenv is installed:
> 
> python -m virtualenv /usr/lib/supervisord/environment
> /usr/lib/supervisord/environment/bin/pip install supervisord
> ln -vs /usr/lib/supervisord/environment/bin/supervisor* /usr/bin
> 
> More tooling around this idiom would of course be nifty, but this is really 
> all it takes.
> 
>>> In fact, given that it is security-sensitive code that runs as root, it is 
>>> extra important to isolate supervisord from your system environment for 
>>> defense in depth, so that, for example, if, due to a bug, it can be coerced 
>>> into importing an arbitrarily-named module, it has a restricted set and 
>>> won't just load anything off the system.
>> 
>> Sounds cute but the threats that actually helps with seem really minor. If a 
>> user can install stuff as root, they can probably do whatever they want 
>> thanks to .pth files and other terrible things.
> 
> Once malicious code is installed in a root-executable location it's game 
> over; I didn't mean to imply otherwise.  I'm saying that since supervisord 
> might potentially import anything in its site-packages dir, this is just less 
> code for you to worry about that might have security bugs in it.
> 
> One specific example of how you might do this is by specifying a 
> protocol-defined codec; if you ever do .decode(user_data) on a string you're 
> doing an attacker-controlled dynamic import.  This is a bug, of course, but a 
> harmless one if you have a small set of modules with no surprises lurking in 
> store.  But, if the attacker can 'import qt' (whose default behavior was to 
> abort() if it couldn't open $DISPLAY for many years, not sure if it still is) 
> from the system, or anything like that, you have potential crashes on your 
> hands.
> 
>>>> Compare with `npm install -g grunt-cli`.
>>> 
>>> npm is different because npm doesn't create top-level script binaries 
>>> unless you pass the -g option, so you need to install global tooling stuff 
>>> with -g.  virtualenv is different (and, at least in this case, better).
>> 
>> Pip also doesn't generate binstubs in /usr/bin unless you install globally 
>> so pretty much same difference.
> 
> Pip always generates binstubs into whatever prefix you're installing into, 
> whereas npm sometimes doesn't generate binstubs at all; when it does generate 
> them, it puts them in a package-specific directory and not in a common 
> location.  (I don't fully understand the specifics; npm generates local 
> binstubs for coffeescript but not for grunt, for example.)  It's fine to 
> symlink pip's stubs.  Is making the symlink really the sticking point?
> 
> So far, in the "use virtualenv" column, I've got:
> 
>       • don't break tooling written in python in the host operating system by 
> installing a conflicting dependency by accident
>       • don't break the host operating system's package database by 
> potentially overwriting packages installed by the package manager
>       • don't break other pip-installed tools using the system or --user 
> environments
>       • don't let installing or upgrading any of those things accidentally 
> break the tool (supervisord in this case) later
>       • make provisioning possible by an unprivileged user, reducing the 
> amount of code that needs to run as root (you can make 
> /usr/lib/supervisord/environment writable by a dedicated user during the 
> install process, to ensure that it doesn't provision anything outside of that 
> directory). This is potentially useful because some setup.py scripts 
> "helpfully" end up doing other weird stuff besides installing the package - 
> there are a few who will remain nameless to protect the guilty which write a 
> bunch of files into root's home directory, for example.
>       • reduce the potential attack surface of any application with plugins 
> by reducing the number of things that can get imported.
> 
> and on the "use sudo pip install" side, I've got:
> 
>       • don't have to make a symlink
>       • users expect applications to install importable modules

I'm not concerned with if the module is importable specifically, but I am 
concerned with where the files will live overall. When building generic ops 
tooling, being unsurprising is almost always the right move and I would be 
surprised if supervisor installed to a custom virtualenv. It's a weird side 
effect of Python not having a great solution for "application packaging" I 
guess? We've got standards for web-ish applications, but not much for system 
services. I'm not saying I think creating an isolated "global-ish" environment 
would be worse, I'm saying nothing does that right now and I personally don't 
want to be the first because that bring a lot of pain with it :-)

--Noah


Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

_______________________________________________
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig

Reply via email to