Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9375677

Browse files
authored
X509 cert auth (#23)
* Added x509keyPair param to Device constructor * New def authorize_x509(...) * Modified def post for x509keyPair * Added mTLS auth info. to README * Significantly simplified mTLS auth block
1 parent c6bfe5d commit 9375677

File tree

4 files changed

+46
-13
lines changed

4 files changed

+46
-13
lines changed

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,22 @@ service_user = mySystem.ServiceUser(email, token)
208208
---
209209
### Devices
210210
Another common entity that may interact with your system is a **device**.
211-
Similar to users, devices must be authenticated before you can use them.
212-
To authenticate a device, you need its _active key_.
211+
Similar to users, devices must be authenticated before you can use them.
212+
213+
One way to authenticate a device is using its _active key_.
213214

214215
> Definition: `System.Device(name, key)`
215216
> Returns: Device object.
216217
217218

219+
Another way to authenticate a device is using mTLS authentication which requires passing an _x509keyPair_ when creating the Device object.
220+
221+
> Definition: `System.Device(name, x509keyPair={"certfile": "/path/to/your/cert.pem", "keyfile": "/path/to/your.key"})`
222+
> Returns: Device object.
223+
224+
mTLS authentication is achieved by a POST request being sent to API `{platformURL}:444/api/v/4/devices/mtls/auth` with the provided x509keyPair being loaded into the SSL context's cert chain. This is handled by the SDK.
225+
226+
218227
Previously authenticated devices can also connected to your system without being re-authenticated as long as they provide a valid authToken:
219228

220229
> Definition: `System.Device(name, authToken="<valid authToken>")`

clearblade/ClearBladeCore.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ def getDevice(self, authenticatedUser, name):
7777
dev = Devices.getDevice(self, authenticatedUser, name)
7878
return dev
7979

80-
def Device(self, name, key="", authToken=""):
81-
dev = Devices.Device(system=self, name=name, key=key, authToken=authToken)
80+
def Device(self, name, key="", authToken="", x509keyPair=None):
81+
dev = Devices.Device(system=self, name=name, key=key, authToken=authToken, x509keyPair=x509keyPair)
8282
# check if dev in self.devices?
8383
return dev
8484

clearblade/Devices.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ def getDevice(system, authenticatedUser, name):
2424

2525

2626
class Device:
27-
def __init__(self, system, name, key="", authToken=""):
27+
def __init__(self, system, name, key="", authToken="", x509keyPair=None):
2828
self.name = name
2929
self.systemKey = system.systemKey
3030
self.url = system.url + "/api/v/2/devices/" + self.systemKey
31+
self.mtls_auth_url = system.url + ":444/api/v/4/devices/mtls/auth"
3132
self.headers = {
3233
"Content-Type": "application/json",
3334
"Accept": "application/json"
@@ -41,8 +42,10 @@ def __init__(self, system, name, key="", authToken=""):
4142
self.token = authToken
4243
self.headers["ClearBlade-DeviceToken"] = self.token
4344
cbLogs.info("Successfully set!")
45+
elif x509keyPair != None:
46+
self.authorize_x509(x509keyPair)
4447
else:
45-
cbLogs.error("You must provide an active key or auth token when creating the device", name)
48+
cbLogs.error("You must provide an active key, auth token or x509 key pair when creating or accessing the device", name)
4649
exit(-1)
4750

4851
def authorize(self, key):
@@ -56,6 +59,17 @@ def authorize(self, key):
5659
self.headers["ClearBlade-DeviceToken"] = self.token
5760
cbLogs.info("Successfully authenticated!")
5861

62+
def authorize_x509(self, x509keyPair):
63+
cbLogs.info("Authenticating", self.name, "as a device using x509 key pair...")
64+
credentials = {
65+
"system_key": self.systemKey,
66+
"name": self.name
67+
}
68+
resp = restcall.post(self.mtls_auth_url, headers=self.headers, data=credentials, sslVerify=self.system.sslVerify, x509keyPair=x509keyPair)
69+
self.token = str(resp["deviceToken"])
70+
self.headers["ClearBlade-DeviceToken"] = self.token
71+
cbLogs.info("Successfully authenticated!")
72+
5973
def update(self, info):
6074
payload = info
6175
try:

clearblade/restcall.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import print_function, absolute_import
22
import json
3+
import ssl
34
import requests
45
from requests.exceptions import *
56
from . import cbLogs
@@ -46,19 +47,28 @@ def get(url, headers={}, params={}, silent=False, sslVerify=True):
4647
return resp
4748

4849

49-
def post(url, headers={}, data={}, silent=False, sslVerify=True):
50+
def post(url, headers={}, data={}, silent=False, sslVerify=True, x509keyPair=None):
5051
# make sure our data is valid json
5152
try:
5253
json.loads(data)
5354
except TypeError:
5455
data = json.dumps(data)
5556

56-
# try our request
57-
try:
58-
resp = requests.post(url, headers=headers, data=data, verify=sslVerify)
59-
except ConnectionError:
60-
cbLogs.error("Connection error. Check that", url, "is up and accepting requests.")
61-
exit(-1)
57+
if x509keyPair == None:
58+
# try our request
59+
try:
60+
resp = requests.post(url, headers=headers, data=data, verify=sslVerify)
61+
except ConnectionError:
62+
cbLogs.error("Connection error. Check that", url, "is up and accepting requests.")
63+
exit(-1)
64+
else:
65+
try:
66+
# mTLS auth so load cert
67+
resp = requests.post(url, headers=headers, data=data, verify=sslVerify, cert=(x509keyPair["certfile"], x509keyPair["keyfile"]))
68+
except ConnectionError:
69+
cbLogs.error("Connection error. Check that", url, "is up and accepting requests.")
70+
exit(-1)
71+
6272

6373
# check for errors
6474
if resp.status_code == 200:

0 commit comments

Comments
 (0)