Skip to content

Commit a67175e

Browse files
authored
fix: Properly support mTLS (#141)
1 parent 60d071e commit a67175e

3 files changed

Lines changed: 50 additions & 2 deletions

File tree

docs/user/authentication.rst

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,41 @@ mTLS - Mutual TLS Authentication (Certificate-Based Authentication)
6868

6969
The most ideal form of authentication for machine to machine communication. Follow `KB0993615 <https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0993615>`_ then:
7070

71-
>>> client = ServiceNowClient(instance, cert=('/path/to/client.cert', '/path/to/client.key'))
71+
72+
>>> client = ServiceNowClient(instance, cert=('/path/to/USER_x509.pem', '/path/to/USERPRIVATEKEY.key'))
73+
74+
75+
A quick example, using self-signed certificates:
76+
77+
1. Setup the CA (root) key
78+
79+
.. code-block:: bash
80+
81+
# generate a root private key, if for some reason you don't have one already
82+
openssl genrsa -aes256 -out ca.key 2048
83+
# generate the CA certificate
84+
openssl req -x509 -new -nodes -key ca.key -out cert.pem -sha512 -days 365 -out cacert.pem
85+
86+
2. Upload `cacert.pem` via `/sys_ca_certificate.do`
87+
88+
3. Setup the user key and CSR (we just generate them here for a POC example)
89+
90+
.. code-block:: bash
91+
92+
openssl req -nodes -newkey rsa:2048 -keyout USERPRIVATEKEY.key -out USERCSR.csr
93+
94+
.. important::
95+
96+
Python requests (the underlying http library) does not directly support keys with passwords! See `requests#2519 <https://github.com/psf/requests/issues/2519>`_ for details.
97+
98+
4. Sign the CSR with the root, creating a X.509 for the user
99+
100+
.. code-block:: bash
101+
102+
openssl x509 -req -days 365 -in USERCSR.csr -CA cacert.pem -CAkey ca.key -extfile <(printf "extendedKeyUsage=clientAuth") -out USER_x509.pem
103+
104+
5. Attach `USER_x509.pem` to a new `/sys_user_certificate.do` record
105+
72106

73107
Requests Authentication
74108
-----------------------

pysnc/client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class ServiceNowClient(object):
2929
:param bool verify: Verify the SSL/TLS certificate OR the certificate to use. Useful if you're using a self-signed HTTPS proxy.
3030
:param cert: if String, path to ssl client cert file (.pem). If Tuple, (‘cert’, ‘key’) pair.
3131
"""
32-
def __init__(self, instance, auth, proxy=None, verify=None, cert=None, auto_retry=True):
32+
def __init__(self, instance, auth=None, proxy=None, verify=None, cert=None, auto_retry=True):
3333
self._log = logging.getLogger(__name__)
3434
self.__instance = get_instance(instance)
3535

@@ -62,6 +62,7 @@ def __init__(self, instance, auth, proxy=None, verify=None, cert=None, auto_retr
6262
elif isinstance(auth, ServiceNowFlow):
6363
self.__session = auth.authenticate(self.__instance, proxies=self.__proxies, verify=verify)
6464
elif cert is not None:
65+
self.__session = requests.session()
6566
self.__session.cert = cert
6667
else:
6768
raise AuthenticationException('No valid authentication method provided')

test/test_snc_auth.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,19 @@ def nop_test_jwt(self):
124124
assert gr.get('6816f79cc0a8016401c5a33be04be441'), "did not jwt auth"
125125
'''
126126

127+
@skip("Requires keys and conf that makes automation hard")
128+
def test_mtls(self):
129+
# e.g. PYSNC_USER_KEY=x PYSNC_USER_CERT=y poetry run pytest test/test_snc_auth.py::TestAuth::test_mtls
130+
path_key = self.c.get_value('USER_KEY')
131+
assert path_key, 'Require user private key'
132+
path_cert = self.c.get_value('USER_CERT')
133+
assert path_cert, 'Require user x509 certificate'
134+
135+
client = ServiceNowClient(self.c.server, cert=(path_cert, path_key))
136+
gr = client.GlideRecord('sys_user')
137+
gr.fields = 'sys_id'
138+
self.assertTrue(gr.get('6816f79cc0a8016401c5a33be04be441'))
139+
127140

128141

129142

0 commit comments

Comments
 (0)