Fetch client certificate from Windows cert store using arcpy

3065
5
11-09-2021 10:03 AM
Status: Closed
EricEagle
Occasional Contributor III

I would like a way to fetch a user's client certificate from the Windows cert store, for authenticating to protected web services within geoprocessing tools.

Previously I had done this using pythonnet but pythonnet is [still? lately? unreliably?] unsupported in python scripts when used as geoprocessing tools.

For those of us working in "extremely security conscious" environments, being able to extend ArcGIS Pro to integrate protected web services, without interfering with a user's workflow, and without having to use the .NET SDK, is a critical need.

5 Comments
Luke_Pinner

Looks like you can use ssl.enum_certificates  to fetch certs.  Here's an example using ArcGIS Pro 2.8 arcgispro-py3 env (which includes the cryptography package v 2.8):

 

import ssl
from cryptography import x509
from cryptography.hazmat.backends import default_backend  # cryptography < 3.1 https://cryptography.io/en/latest/faq/?highlight=backend#what-happened-to-the-backend-argument

for store in ["CA", "ROOT", "MY"]:
    for cert, encoding, trust in ssl.enum_certificates(store):
        certificate = x509.load_der_x509_certificate(cert, backend=default_backend())   # cryptography < 3.1 
        # certificate = x509.load_der_x509_certificate(cert)   # cryptography >= 3.1 
        print(certificate.issuer, certificate.not_valid_after)

 

EricEagle

Hey @Luke_Pinner thanks, however this does not give me the user's personal digital signing certificate, only the cert authorities.... I feel like this moves me closer, but basically I'd need to know how to go from getting that personal signing certificate object, and then sending it via a library like requests or requests_pkcs12 to authenticate/authorize a session.

ShaunWalbridge

@EricEagle I believe from the "MY" store in Luke's example you should be able to get down to the users' provided certificates. For a more fully worked example, see for example this post. I'm not aware of any direct core functionality in our software that provides this, so I don't think there is something internal for us to expose via ArcPy, is that consistent with your understanding? If so, I think probably trying to get our collection of certificate interacting packages (ssl, wincertstore, keyring) to do what you want is best. Alternatively, we do include a stripped-down version of PyWin32 which includes just the security APIs (ntsecuritycon, sspi, and win32security) that can be imported with `import pywin32security` as a starting point. Those are API wrappers around the underlying Win32 APIs that should provide what you need, though it may be somewhat challenging to work with them since they are low level.

Luke_Pinner

Yep personal certs from "MY", e.g. to search for cert by subject or issuer CN

import ssl
from cryptography.hazmat.backends import default_backend  # cryptography < 3.1 https://cryptography.io/en/latest/faq/?highlight=backend#what-happened-to-the-backend-argument
from cryptography.x509.oid import NameOID
from cryptography import x509

def get_cert(subject=None, issuer=None, store="MY"):
    for cert, encoding, trust in ssl.enum_certificates(store):
        certificate = x509.load_der_x509_certificate(cert, backend=default_backend())   # cryptography < 3.1 
        # certificate = x509.load_der_x509_certificate(cert)   # cryptography >= 3.1 

        if subject is not None and subject == certificate.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value:
            return certificate

        elif issuer is not None and issuer == certificate.issuer.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value:
            return certificate

  

ShaunWalbridge
Status changed to: Closed

@EricEagle thanks for your idea on this. I believe that the solution proposed by @Luke_Pinner is a good one, and relies on existing components we provide in our stack without Esri trying to maintain something that we don't directly use nor expect to deliver to customers at this time. If certificate handling becomes part of the product, exposing this through Python would definitely be a valuable addition.

Cheers,
Shaun