pypa / pip

The Python package installer
https://pip.pypa.io/
MIT License
9.52k stars 3.03k forks source link

usage of internal server with smarcard/passphrase #10778

Closed datamoc closed 2 years ago

datamoc commented 2 years ago

What's the problem this feature will solve?

Internal pip servers are mainly in quite secure networks. Strong authentication is required on all servers. Currently pip seems accept only login/password authentication.

Describe the solution you'd like

when using pip command chose the certificate to used in a menu (or use the only certificate on the smartcard if there is only one certificate) then ask for the passphrase

Alternative Solutions

login/password

Additional context

internal secured network without direct access to internet.

Code of Conduct

notatallshaw commented 2 years ago

I'm not a pip maintainer but I can tell you working in a company that uses smart card authentication for internal sites that currently pip uses requests for it's HTTP calls. And requests does not support any kind of smart card authentication mechanisms out of the box.

Your easiest option is to use "HTTP" only calls and add your internal repository to pip's trusted host list: https://pip.pypa.io/en/stable/cli/pip/?highlight=trusted-host#cmdoption-trusted-host

Internally within our company we have a script that attaches OpenSSL's CAPI engine to authentication calls in requests which automatically invokes smart card auth. However this involves many deprecated technologies and doesn't work in some scenarios with TLS 1.2+. Further you would need to patch pip in a way that isn't support and I can't directly share it ( though is it looks like this and only works with conda installed version of pyopenssl https://stackoverflow.com/a/60424608 ).

I've tried adapting oscrypto instead to call Microsoft's CNG API which should automatically invoke Smart Card authentication when required, but so far you can see my attempt here is yet to fully work: https://github.com/wbond/oscrypto/issues/10#issuecomment-953416175 . Again though even if this did work you would still need to patch Pip in an unsupported way to get it working.

I would recommend that if you need to host your internal repository on a server that must authenticate with smart card that you look at something like Fiddler to proxy your calls so pip/python does not have to provide the authentication itself.

Other than that your company provided significant enough funding to the underlying packages to support these authentication methods out of the box (probably start with urllib3?).

datamoc commented 2 years ago

Thanks for your comment. I have quickly tested your code but have got a 401 error. I was more focused on accessing using Python to the smartcard reader itself....

Sadly, currently the open innovation for my company is more related to work with fancy startup rather that to finance useful opensource projects.

notatallshaw commented 2 years ago

Thanks for your comment. I have quickly tested your code but have got a 401 error.

Unfortunately I never got oscrypto working that well in my environment never mind about other people's Internal environments.

I was more focused on accessing using Python to the smartcard reader itself....

Not sure how low level you want to go, if you're on Windows the smart card functions itself are managed via WinSCard.dll, you could Google around and read Microsoft docs https://docs.microsoft.com/en-us/windows/win32/api/winscard/nf-winscard-scardconnecta and then use either ctypes or cffi or pywin32 to access the APIs.

But it's probably too low level and cryptic to be useful for anything at Python level.

uranusjr commented 2 years ago

Someone needs to go through this with requests before pip can do anything meaningful about this.

notatallshaw commented 2 years ago

Someone needs to go through this with requests before pip can do anything meaningful about this.

What needs to happen here is urllib3 or some other popular Python HTTP back end needs to fully support Schannel.

Unfortunately oscrypto only has a partial implementation and does not support client authentication. So this particular use case will not be met even if urllib3 took oscryptos Schannel implementation like it took the Secure Transport implementation for MacOS.

Unfortunately I think Schannel is not well understood or documented enough outside Microsoft that I don't see a Python library providing a complete implementation unless Microsoft provides it. However I've not seen any commitment from Microsoft to provide such support for Python or any non-CLR languages beyond simple API bindings.

Side Note: One workaround would be to use Curl's Schannel implementation via PycURL, but the library requires compiled C code so is not compatible for urllib3. The only way I see Pip ever using it is if Pip provides a more modular architecture where the HTTP library Pip uses could be replaced by the user.

pradyunsg commented 2 years ago

Sounds like the thing that needs to happen is someone in an organisation that uses this technology needs to go talk to the relevant vendor to provide a solution that works for the Python community at large. I don't think pip's maintainers are going to be doing that work.

Given that there's limited interest and capacity to work this, I don't think there's much value in tracking this in pip's issue tracker, so I'm going to go ahead and close this out.

notatallshaw commented 2 years ago

Sounds like the thing that needs to happen is someone in an organisation that uses this technology needs to go talk to the relevant vendor to provide a solution that works for the Python community at large.

That's definitely one solution, I'm leaving these tidbits in the hopes that someone both has this problem and the capability to escalate it to a vendor that could do something about it.,

I don't think there's much value in tracking this in pip's issue tracker

Pip could provide is a more plug-able architecture to allow replacement of the HTTP library by the user. It's a use case I have highlighted to the conda team as they prepare to rearchitect conda to allow user plugins.

But given the extremely limited resources of pip in comparison to conda I also think people should think about implementing alternatives to Pip with this built in mind from the ground up.

Regardless I agree this particular issue can't be tracked by Pip.

potiuk commented 2 years ago

There likely is a way to provide card-based authentication that will be vendor neutral.

For many years I am using Yubico keys (I have 4 copies of those in case) for most authentication purposes. It supports multiple protocols but one of them is GPG authtentication and signing. And pretty much all smart cards I've seen and evaluated for myself, do.

It might be not easiest for casual user, but if we are talking about corporate environment, setting up GPG-smart-card compliant authentication for corporate environment is what admins do on a daily basis.

And possibly there is not much code for that in pip - many of other open-source tools I use (notably SSH and git) use existing authentication mechanism (specific for the platform) that perform the authentication using GPG smart card, very much like keyring. It nicely works with protocols that have public-key authentication implemented (SSH). It is a bit more difficult to HTTP based authentication as it requires U2F (renamed to FIDO2). Those are industry standards that are already implemented by all browsers, but we need more client-tool and libraries support for that.

And likely we should just wait a bit. There are some new developments recently on that front that might actually make it much easier without reinventing the wheel. I've heard very well founded rumours that very soon you will be able to authenticate git via https:// over HTTP to GitHub using your public key authentication that you use for SSH now. Which means likely implementing new protocol that will transplant SSH public key authentication over HTTP.

So it might be something to consider (and maybe contributing to requests) instead of going vendor-specific solution. I wish I had a bit more time to contribute that to requests - maybe some day :)

In any way - yeah, this is likely not pip "centered" issue.