-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Description
Feature Request
Please add support for SmartCard/PIV login using Windows certificate and cryptography APIs. The benefit is that federal agencies can login to Github securely, and to SSH bastions that require this capability.
Motivation
My federal institute has an ATO for use of AWS that we must only use our SmartCard/PIV login to access the Cloud, and many federal developers have only Windows, rather than a PowerBook. I'm looking to enhance their login process so that they can use ssh from a windows or bash command-line.
My federal institute is happy to use this with VanDyke SecureCRT on Windows and MacOS, but this displeases me as a developer/architect, because it always opens a window. I wish this feature were part of "Git for Windows".
Previous Issues
I did searches on SmartCard and PIV, and then looked through the related issues displayed when entering the title. Nothing seemed right.
Setup
- Which version of Git for Windows are you using?
2.2.0.windows.1
- Is it 32-bit or 64-bit?
64 bit
$ git --version --build-options
git version 2.22.0.windows.1
cpu: x86_64
built from commit: d003d728ffa6c0006da875ec6318d3f6b28a4ddb
sizeof-long: 4
sizeof-size_t: 8
- Which version of Windows are you running? Vista, 7, 8, 10? Is it 32-bit or 64-bit?
$ cmd.exe /c ver
Microsoft Windows [Version 10.0.17134.885]
- What options did you set as part of the installation? Or did you choose the
defaults?
# One of the following:
$ cat $HOME/Tools/Git/etc/install-options.txt
Editor Option: SublimeText
Custom Editor Path:
Path Option: Cmd
SSH Option: OpenSSH
CURL Option: OpenSSL
CRLF Option: LFOnly
Bash Terminal Option: ConHost
Performance Tweaks FSCache: Enabled
Use Credential Manager: Enabled
Enable Symlinks: Disabled
Enable Builtin Interactive Add: Disabled
*NOTE: * This implies it may work if I install OpenSC, and I will try it. However, half the advantages of PIV integration will be using the cached credentials that the Windows service already has.
Details
This is a feature request, rather than a big report, and so I will dispense with the questions about reproducing the issue to the extent possible.
There are workarounds for OpenSSH on MacOS that involve the use of OpenSC. These may or may not work with git for windows. If they do work, that is a work-around, but it will be most ideal to use the Windows Cryptography API or the New cryptography API to obtain the private key, because that will allow a password already authenticated recently to work out of the box.
I cannot advise on how to setup Windows 10 to require smart card authentication - I think NIST and SmartCard vendors provide a lot of that intelligence. I can provide wisdom on getting the public key from Active Directory or related tools.
Software that does it
- VanDyke SecureCRT supports SmartCard/PIV login, as does Chrome.
- Firefox supports PIV login only through OpenSC.
- Using VanDyke SecureCRT, I export my authentication certificate as an SSH public key,
and register it with Github.com under SSH keys.
PublicKey via Python from Active Directory
I can also export my public key from Active Directory. To maximize the likelihood this feature can be added, I provide some python for this:
import ldap3 as ldap
from ldap3.core.exceptions import LDAPExceptionError
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
from OpenSSL.crypto import load_certificate, FILETYPE_ASN1
## The following are assumed to be provided
# hostname
# bind_dn - equivalent of username
# password
# base-dn - where to start search from
# username - the user whose public key you wish to search on
server = ldap.Server(hostname, use_ssl=True)
connection = ldap.Connection(server, bind_dn, password, auto_bind=ldap.AUTO_BIND_TLS_BEFORE_BIND, read_only=True)
query = '(&(objectclass=user)(sAMAccountName=%s))' % username
connection.search(base_dn, query, attributes=['sAMAccountName', 'userCertificate'])
# now we assume it worked and we got a single response
certificate_bytes = connection.entries[0].userCertificate.values[0]
x509 = load_certificate(FILETYPE_ASN1, certificate_bytes)
public_key = x509.get_pubkey().to_cryptography_key()
public_key = public_key.public_bytes(Encoding.OpenSSH, PublicFormat.OpenSSH).decode('utf-8')
suffix = username + '@some-domain.com'
# now finally, the SSH public key
print(public_key+' '+suffix)