-
Notifications
You must be signed in to change notification settings - Fork 29
/
main.py
84 lines (68 loc) · 3.81 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# ------------------------------------------------------------------------------
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
# -----------------------------------------
# Consuming sample, demonstrating how a device process would leverage the provisioning class.
# The handler makes use of the asycio library and therefore requires Python 3.7.
#
# Prereq's:
# 1) A provisioning claim certificate has been cut from AWSIoT.
# 2) A restrictive "birth" policy has been associated with the certificate.
# 3) A provisioning template was created to manage the activities to be performed during new certificate activation.
# 4) The claim certificate was placed securely on the device fleet and shipped to the field. (along with root/ca and private key)
#
# Execution:
# 1) The paths to the certificates, and names of IoTCore endpoint and provisioning template are set in config.ini (this project)
# 2) A device boots up and encounters it's "first run" experience and executes the process (main) below.
# 3) The process instatiates a handler that uses the bootstrap certificate to connect to IoTCore.
# 4) The connection only enables calls to the Foundry provisioning services, where a new certificate is requested.
# 5) The certificate is assembled from the response payload, and a foundry service call is made to activate the certificate.
# 6) The provisioning template executes the instructions provided and the process rotates to the new certificate.
# 7) Using the new certificate, a pub/sub call is demonstrated on a previously forbidden topic to test the new certificate.
# 8) New certificates are saved locally, and can be stored/consumed as the application deems necessary.
#
#
# Initial version - Raleigh Murch, AWS
# email: [email protected]
# ------------------------------------------------------------------------------
from provisioning_handler import ProvisioningHandler
from utils.config_loader import Config
from pyfiglet import Figlet
#Set Config path
CONFIG_PATH = 'config.ini'
config = Config(CONFIG_PATH)
config_parameters = config.get_section('SETTINGS')
secure_cert_path = config_parameters['SECURE_CERT_PATH']
bootstrap_cert = config_parameters['CLAIM_CERT']
# Demo Theater
f = Figlet(font='slant')
print(f.renderText(' F l e e t'))
print(f.renderText('Provisioning'))
print(f.renderText('----------'))
# Provided callback for provisioning method feedback.
def callback(payload):
print(payload)
# Used to kick off the provisioning lifecycle, exchanging the bootstrap cert for a
# production certificate after being validated by a provisioning hook lambda.
#
# isRotation = True is used to rotate from one production certificate to a new production certificate.
# Certificates signed by AWS IoT Root CA expire on 12/31/2049. Security best practices
# urge frequent rotation of x.509 certificates and this method (used in conjunction with
# a cloud cert management pattern) attempts to make cert exchange easy.
def run_provisioning(isRotation):
provisioner = ProvisioningHandler(CONFIG_PATH)
if isRotation:
provisioner.get_official_certs(callback, isRotation=True)
else:
#Check for availability of bootstrap cert
try:
with open("{}/{}".format(secure_cert_path, bootstrap_cert)) as f:
# Call super-method to perform aquisition/activation
# of certs, creation of thing, etc. Returns general
# purpose callback at this point.
# Instantiate provisioning handler, pass in path to config
provisioner.get_official_certs(callback)
except IOError:
print("### Bootstrap cert non-existent. Official cert may already be in place.")
if __name__ == "__main__":
run_provisioning(isRotation=False)