示例#1
0
    def __init__(self, file_path, template_name, thing_name, endpoint):
        """Initializes the provisioning handler
        
        Arguments:
            file_path {string} -- path to your configuration file
        """
        #Logging
        logging.basicConfig(level=logging.ERROR)
        self.logger = logging.getLogger(__name__)
        
        #Load configuration settings from config.ini
        config = Config(file_path)
        self.config_parameters = config.get_section('SETTINGS')
        self.secure_cert_path = self.config_parameters['SECURE_CERT_PATH']
        self.iot_endpoint = endpoint	
        self.template_name = template_name #self.config_parameters['PRODUCTION_TEMPLATE']
        self.rotation_template = self.config_parameters['CERT_ROTATION_TEMPLATE']
        self.claim_cert = self.config_parameters['CLAIM_CERT']
        self.secure_key = self.config_parameters['SECURE_KEY']
        self.root_cert = self.config_parameters['ROOT_CERT']
        self.root_cert_path = self.config_parameters['ROOT_CERT_PATH']
        self.topic_name = self.config_parameters['TOPIC_NAME']
        self.unique_id = thing_name

        self.primary_MQTTClient = None
        self.test_MQTTClient = None
        self.callback_returned = False
        self.message_payload = {}
        self.isRotation = False

        self.payloadhandler = payloadHandler(file_path)
示例#2
0
    def __init__(self, file_path):
        """Initializes the provisioning handler

        Arguments:
                file_path {string} -- path to your configuration file
        """
        # Logging
        logging.basicConfig(level=logging.ERROR)
        self.logger = logging.getLogger(__name__)

        # Load configuration settings from config.ini
        config = Config(file_path)
        self.config_parameters = config.get_section('SETTINGS')
        self.secure_cert_path = self.config_parameters['SECURE_CERT_PATH']
        self.iot_endpoint = self.config_parameters['IOT_ENDPOINT']
        self.template_name = self.config_parameters[
            'PROVISIONING_TEMPLATE_NAME']
        self.claim_cert = self.certFullPath(
            self.config_parameters['CLAIM_CERT'])
        self.secure_key = self.certFullPath(
            self.config_parameters['SECURE_KEY'])
        self.root_cert = self.certFullPath(self.config_parameters['ROOT_CERT'])
        self.machine_config = self.config_parameters['MACHINE_CONFIG_PATH']
        self.error = ''

        with open(self.machine_config) as json_file:
            data = json.load(json_file)
            self.serial_num = data['serial_num']
            self.model_type = data['model_type']

        # ------------------------------------------------------------------------------
        #  -- PROVISIONING HOOKS EXAMPLE --
        # Provisioning Hooks are a powerful feature for fleet provisioning. Most of the
        # heavy lifting is performed within the cloud lambda. However, you can send
        # device attributes to be validated by the lambda. An example is show in the line
        # below (.hasValidAccount could be checked in the cloud against a database).
        # Alternatively, a serial number, geo-location, or any attribute could be sent.
        #
        # -- Note: This attribute is passed up as part of the register_thing method and
        # will be validated in your lambda's event data.
        # ------------------------------------------------------------------------------
        if not os.path.exists(self.claim_cert):
            self.error = '### Bootstrap cert non-existent. Official cert may already be in place.'
        else:
            self.hasValidAccount = True

            self.primary_MQTTClient = AWSIoTMQTTClient(
                "fleet_provisioning_demo")

            self.primary_MQTTClient.onMessage = self.on_message_callback
            self.callback_returned = False
            self.message_payload = {}
    def __init__(self, file_path):
        """Initializes the provisioning handler
		
		Arguments:
			file_path {string} -- path to your configuration file
		"""
        #Logging
        logging.basicConfig(level=logging.ERROR)
        self.logger = logging.getLogger(__name__)

        #Load configuration settings from config.ini
        config = Config(file_path)
        self.config_parameters = config.get_section('SETTINGS')
        self.secure_cert_path = self.config_parameters['SECURE_CERT_PATH']
        self.iot_endpoint = self.config_parameters['IOT_ENDPOINT']
        self.template_name = self.config_parameters[
            'PROVISIONING_TEMPLATE_NAME']
        self.claim_cert = self.config_parameters['CLAIM_CERT']
        self.secure_key = self.config_parameters['SECURE_KEY']
        self.root_cert = self.config_parameters['ROOT_CERT']
        self.device_info = {
            'certPath': self.secure_cert_path,
            'endpoint': self.iot_endpoint,
            'rootCert': self.root_cert
        }
        # Sample Provisioning Template requests a serial number as a
        # seed to generate Thing names in IoTCore. Simulating here.
        self.unique_id = str(int(round(time.time() * 1000)))

        # ------------------------------------------------------------------------------
        #  -- PROVISIONING HOOKS EXAMPLE --
        # Provisioning Hooks are a powerful feature for fleet provisioning. Most of the
        # heavy lifting is performed within the cloud lambda. However, you can send
        # device attributes to be validated by the lambda. An example is show in the line
        # below (.hasValidAccount could be checked in the cloud against a database).
        # Alternatively, a serial number, geo-location, or any attribute could be sent.
        #
        # -- Note: This attribute is passed up as part of the register_thing method and
        # will be validated in your lambda's event data.
        # ------------------------------------------------------------------------------
        self.hasValidAccount = False

        self.primary_MQTTClient = AWSIoTMQTTClient("fleet_provisioning_demo")
        self.test_MQTTClient = AWSIoTMQTTClient(
            "fleet_provisioning_demo_full_rights")
        self.primary_MQTTClient.onMessage = self.on_message_callback
        self.callback_returned = False
        self.message_payload = {}
 def __init__(self, profile, roleName, policyArn, file_path):
     
      #Logging
     logging.basicConfig(level=logging.ERROR)
     self.logger = logging.getLogger(__name__)
     
     config = Config(file_path)
     self.config_parameters = config.get_section('SETTINGS')
     self.secure_cert_path = self.config_parameters['SECURE_CERT_PATH']
     
     self.profile = profile
     self.session = boto3.Session(profile_name = profile)
     self.client = self.session.client('iot')
     #self.boto3.client('sts').get_caller_identity().get('Account')
     self.iam = IAM(profile)
     self.roleName = roleName
     self.policyArn = policyArn
     super().__init__()
    def __init__(self, file_path):
        super().__init__()

        logging.basicConfig(level=logging.ERROR)
        self.logger = logging.getLogger(__name__)

        #Load configuration settings from config.ini
        config = Config(file_path)
        self.config_parameters = config.get_section('SETTINGS')
        self.topic_name = self.config_parameters['TOPIC_NAME']
        self.trips_topic_name = self.config_parameters['TRIP_TOPIC_NAME']
        self.dtc_topic_name = self.config_parameters['DTC_TOPIC_NAME']
        self.csv_location = self.config_parameters['CSV_LOCATION']
        self.payload_location = self.config_parameters['PAYLOAD_LOCATION']
        self.trips_payload_location = self.config_parameters[
            'TRIP_PAYLOAD_LOCATION']
        self.dtc_payload_location = self.config_parameters[
            'DTC_PAYLOAD_LOCATION']
示例#6
0
def main(vin, dtc):

   #Set Config path
   CONFIG_PATH = 'config.ini'
   payloadhandler = payloadHandler(CONFIG_PATH)
   #c = Cognito(profile)
   #m = ConnectedMobility(profile, stackname)
   config = Config(CONFIG_PATH)
   config_parameters = config.get_section('SETTINGS')
   ENDPOINT = config_parameters['IOT_ENDPOINT']
   
   CLIENT_ID = vin
   PATH_TO_CERT = "{}/{}".format(config_parameters['SECURE_CERT_PATH'].format(unique_id=CLIENT_ID), config_parameters['PROD_CERT'])
   PATH_TO_KEY = "{}/{}".format(config_parameters['SECURE_CERT_PATH'].format(unique_id=CLIENT_ID), config_parameters['PROD_KEY'])
   PATH_TO_ROOT = "{}/{}".format(config_parameters['ROOT_CERT_PATH'], config_parameters['ROOT_CERT'])

   event_loop_group = io.EventLoopGroup(1)
   host_resolver = io.DefaultHostResolver(event_loop_group)
   client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)

   test_MQTTClient = mqtt_connection_builder.mtls_from_path(
        endpoint=ENDPOINT,
        cert_filepath=PATH_TO_CERT,
        pri_key_filepath=PATH_TO_KEY,
        client_bootstrap=client_bootstrap,
        ca_filepath=PATH_TO_ROOT,
        client_id=CLIENT_ID,
        clean_session=False,
        on_connection_interrupted=on_connection_interrupted,
        on_connection_resumed=on_connection_resumed,
        keep_alive_secs=6)
   
   print("Connecting with Prod certs to {} with client ID '{}'...".format(ENDPOINT, CLIENT_ID))
   connect_future = test_MQTTClient.connect()
 
   connect_future.result()
   print("Connected with production certificates to the endpoint")
   
   payload = payloadhandler.getDTCPayload( dtc, CLIENT_ID)
   payloadhandler.publishDTCPayload(test_MQTTClient, payload, CLIENT_ID)
   print("Successfully published DTC: {}".format(dtc))
  
   exit()
示例#7
0
#      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)
示例#8
0
def main(profile, vin):

    #Set Config path
    CONFIG_PATH = 'config.ini'
    payloadhandler = payloadHandler(CONFIG_PATH)
    #c = Cognito(profile)
    #m = ConnectedMobility(profile, stackname)
    config = Config(CONFIG_PATH)
    config_parameters = config.get_section('SETTINGS')
    #ENDPOINT = config_parameters['IOT_ENDPOINT']
    i = IOT(profile, "", "", CONFIG_PATH)
    ENDPOINT = i.iotEndpoint

    CLIENT_ID = vin
    PATH_TO_CERT = "{}/{}".format(
        config_parameters['SECURE_CERT_PATH'].format(unique_id=CLIENT_ID),
        config_parameters['PROD_CERT'])
    PATH_TO_KEY = "{}/{}".format(
        config_parameters['SECURE_CERT_PATH'].format(unique_id=CLIENT_ID),
        config_parameters['PROD_KEY'])
    PATH_TO_ROOT = "{}/{}".format(config_parameters['ROOT_CERT_PATH'],
                                  config_parameters['ROOT_CERT'])

    event_loop_group = io.EventLoopGroup(1)
    host_resolver = io.DefaultHostResolver(event_loop_group)
    client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)

    test_MQTTClient = mqtt_connection_builder.mtls_from_path(
        endpoint=ENDPOINT,
        cert_filepath=PATH_TO_CERT,
        pri_key_filepath=PATH_TO_KEY,
        client_bootstrap=client_bootstrap,
        ca_filepath=PATH_TO_ROOT,
        client_id=CLIENT_ID,
        clean_session=False,
        on_connection_interrupted=on_connection_interrupted,
        on_connection_resumed=on_connection_resumed,
        keep_alive_secs=6)

    print("Connecting with Prod certs to {} with client ID '{}'...".format(
        ENDPOINT, CLIENT_ID))
    connect_future = test_MQTTClient.connect()

    connect_future.result()
    print("Connected with production certificates to the endpoint")

    tripId = uuid.uuid4().hex
    print("Generating Trip ID of {}".format(tripId))
    latLongDict = payloadhandler.generateLatLongFromCSV()
    print("Begin publishing trip data.  Will publish {} payloads".format(
        len(latLongDict)))
    startCoords = next(iter(latLongDict))
    endCoords = list(latLongDict)[-1]
    startTime = payloadhandler.getTimestampMS()
    for i in latLongDict:
        payload = payloadhandler.getPayload(i, tripId, CLIENT_ID)
        payloadhandler.publishPayload(test_MQTTClient, payload, CLIENT_ID)
        print("Successfully published coordinates {} of {}".format(
            i, len(latLongDict)))
        time.sleep(1)

    trippayload = payloadhandler.getTripPayload(startTime, startCoords,
                                                endCoords, tripId, CLIENT_ID)
    payloadhandler.publishTripPayload(test_MQTTClient, trippayload, CLIENT_ID)

    print("Trip data published sucessfully")
    exit()
class ConnectedMobility():
    #external constants
    cdfStackName = 'CDF'
    cmsStackName = 'CMS'
    authStackName = 'Authorizer'
    assetLibraryUrl = 'AssetLibraryApiGatewayUrl'
    facadeApiGatewayUrl = 'FacadeApiGatewayUrl'
    cfUuserPoolClientId = 'UserPoolClientId'
    cfCloudfrontDomain = 'CloudfrontDomain'
    cfUserPoolId = 'UserPoolId'
    cfCertficateId = 'CertificateId'
    CONFIG_PATH = 'config.ini'
    config = Config(CONFIG_PATH)
    config_parameters = config.get_section('SETTINGS')
    cAcceptHeader = config_parameters['ACCEPT_HEADER']
    cContentType = config_parameters['CONTENT_TYPE']
        
    #CF Constants
    cflogResourceId = 'LogicalResourceId'
    cfphyResourceId = 'PhysicalResourceId'
    cfStackResources = 'StackResources'
    cfStacks = 'Stacks'
    cfOutputs = 'Outputs'
    cfOutputKey = 'OutputKey'
    cfOutputValue = 'OutputValue'
    
    __cloudFrontDomainUrl = ''
    __assetLibraryBaseUrl = ''
    __cmscfResourcesArn = ''
    __cognitoId = ''
    __userPoolClientId = ''
    __userPoolId = ''
    __facadeEndpointUrl = ''
    __certificateId = ''
    __cdf_stackARN = ''
    __cdf_cf = {}
    __cdf_outputs = {}
    __cdfSubstackOutputs = {}
    __cf = None
    session = None
        
    def __init__(self, profile, stackname, cdfstackname):
        self.profile = profile
        self.stackname = stackname
        #in a prior version, we could derive the CDF stack name from the resources of the CMS, well that has changed, so now we need to pass in the CDF stack name to get asset library URL
        self.cdfstackname = cdfstackname
        self.session = boto3.Session(profile_name = profile)
        
        super().__init__()
    
    @property    
    def cf(self):
        if self.__cf == None: 
            self.__cf = self.session.client('cloudformation')
        return self.__cf
    @property
    def cdf_cf(self):
        if not self.__cdf_cf: 
            self.__cdf_cf = self.cf.describe_stacks(StackName=self.stackname)[self.cfStacks]
        return self.__cdf_cf
    @property
    def cdfOutputs(self):
        if not self.__cdf_outputs:
            self.__cdf_outputs = self.cdf_cf[0][self.cfOutputs]
        return self.__cdf_outputs
#    @property
#    def cdfStackARN(self):
#        if not self.__cdf_stackARN:
#            self.__cdf_stackARN = self.getValuefromResourceDict(self.cf.describe_stack_resources(StackName=self.stackname)[self.cfStackResources], self.cdfStackName)
#        return self.__cdf_stackARN
#    @property
    @property
    def cdfSubstackOutputs(self):
        if not self.__cdfSubstackOutputs: 
            self.__cdfSubstackOutputs = self.cf.describe_stacks(StackName=self.cdfstackname)[self.cfStacks][0][self.cfOutputs]
        return self.__cdfSubstackOutputs
    @property
    def assetLibraryBaseUrl(self):
        if self.__assetLibraryBaseUrl == '':
            self.__assetLibraryBaseUrl = self.getValuefromDict(self.cdfSubstackOutputs, self.assetLibraryUrl)      
        return self.__assetLibraryBaseUrl
    @property
    def facadeEndpointUrl(self):
        if self.__facadeEndpointUrl == '':
            self.__facadeEndpointUrl = self.getValuefromDict(self.cdfOutputs, self.facadeApiGatewayUrl)
        return self.__facadeEndpointUrl
    @property
    def cloudFrontDomainUrl(self):
        if self.__cloudFrontDomainUrl == '':
            self.__cloudFrontDomainUrl = self.getValuefromDict(self.cdfOutputs, self.cfCloudfrontDomain)
        return self.__cloudFrontDomainUrl
    @property
    def certificateId(self):
        if self.__certificateId == '':
            self.__certificateId = self.getValuefromDict(self.cdfOutputs, self.cfCertficateId)
        return self.__certificateId
    def cognitoId(self):
        return self.__cognitoId
    @property
    def userPoolClientId(self):
        if not self.__userPoolClientId:
            self.__userPoolClientId = self.getValuefromDict(self.cdfOutputs, self.cfUuserPoolClientId)
        return self.__userPoolClientId
    @property
    def userPoolId(self):
        if self.__userPoolId == '':
            self.__userPoolId = self.getValuefromDict(self.cdfOutputs, self.cfUserPoolId)
        return self.__userPoolId
    
    def getValuefromDict(self, vals, keyValName):
        v = next(filter(lambda output: output[self.cfOutputKey] == keyValName, vals))
        return (v[self.cfOutputValue])
    
    def getValuefromResourceDict(self, vals, keyValName):
        v = next(filter(lambda output: output[self.cflogResourceId] == keyValName, vals))
        return (v[self.cfphyResourceId])   
             
    def getSupplier(self, deviceMaker, authorization) -> None:
        #TODO://create function to general the path
        url = self.assetLibraryBaseUrl + "/groups/%2Fauto%2Fsuppliers%2F{0}"
        url = url.format(deviceMaker)
        payload = {} # payload.format(deviceMaker, deviceMaker, GUID)
    
        headers = {
            'Authorization': authorization,
            'Accept': self.cAcceptHeader,
            'Content-Type': self.cContentType
        }
        
        response = requests.request("GET", url, headers=headers, data=payload)

        return response

    def createSupplier(self, deviceMaker, GUID, authorization) -> None:
        
        url = self.assetLibraryBaseUrl + "/groups"
        payload='{{\n    \"groupPath\" : \"/auto/suppliers/{0}\",\n    \"parentPath\" : \"/auto/suppliers\",\n    \"templateId\" : \"auto_supplier\",\n    \"name\" : \"{1}\",\n    \"attributes\" : {{\n        \"externalId\": \"{2}\"\n    }}\n}}'
        payload = payload.format(deviceMaker, deviceMaker, GUID)
        
        headers = {
            'Authorization': authorization,
            'Accept': self.cAcceptHeader,
            'Content-Type': self.cContentType
        }
        
        response = requests.request("POST", url, headers=headers, data=payload)

        return response

    def getCMSUser(self, firstName, lastName, username, authorization) -> None:
        url = self.facadeEndpointUrl + "/users"

        payload="{{\n    \"username\" : \"{0}\",\n    \"firstName\" : \"{1}\",\n    \"lastName\" : \"{2}\"\n}}"
        payload = payload.format(firstName, lastName, username)
        
        headers = {
            'Authorization': authorization,
            'Accept': self.cAcceptHeader,
            'Content-Type': self.cContentType
        }
        
        response = requests.request("POST", url, headers=headers, data=payload)

        return response

    def createCMSUser(self, firstName, lastName, username, authorization) -> None:
        url = self.facadeEndpointUrl + "/users"

        payload="{{\n    \"username\" : \"{0}\",\n    \"firstName\" : \"{1}\",\n    \"lastName\" : \"{2}\"\n}}"
        payload = payload.format(username, firstName, lastName)
        headers = {
            'Authorization': authorization,
            'Accept': self.cAcceptHeader,
            'Content-Type': self.cContentType
        }
        response = requests.request("POST", url, headers=headers, data=payload)

        return response

    def registerDevice(self, externalId, thingName, authorization) -> None:
        url = "{0}/suppliers/{1}/devices/{2}/register"
        url = url.format(self.facadeEndpointUrl, externalId, thingName)
        payload="{{\n    \"templateId\":\"auto_ecu\",\n    \"certificateId\": \"{0}\",\n    \"attributes\": {{\n        \"type\":\"tcu\",\n        \"model\":\"TCU-1\"\n    }}\n}}"
        payload = payload.format(self.certificateId)
        headers = {
            'Authorization': authorization,
            'Accept': self.cAcceptHeader,
            'Content-Type': self.cContentType
        }
        response = requests.request("POST", url, headers=headers, data=payload)

        return response
    
    def activateDevice(self, deviceMaker, externalId, thingName, vin, authorization) -> None:
        url = "{0}/suppliers/{1}/devices/{2}/activate"
        url = url.format(self.facadeEndpointUrl, externalId, thingName)
        payload = payload='{{\n    \"vehicle\": {{\n        \"make\": \"{0}\",\n        \"model\": \"DN\",\n        \"modelYear\": 2019,\n        \"marketCode\": \"NA\",\n        \"vin\": \"{1}\",\n        \"bodyType\": \"Saloon\",\n        \"fuelType\": \"Gas\",\n        \"transmissionType\": \"Auto\",\n        \"transmissionAutoType\": \"7-speed\",\n        \"colorCode\": \"B1B!\",\n        \"iviType\": \"Premium\",\n        \"ecus\": [{{\n            \"type\": \"tcu\",\n            \"id\": \"{2}\",\n            \"softwareVersion\": \"1.9.1\"\n        }}]\n    }}\n}}'
        payload = payload.format(deviceMaker, vin, thingName)
        headers = {
            'Authorization': authorization,
            'Accept': self.cAcceptHeader,
            'Content-Type': self.cContentType
        }
        
        response = requests.request("POST", url, headers=headers, data=payload)

        return response

    def associateDevice(self, username, vin, authorization) -> None: 
        url = "{0}/groups/{1}{2}/owns/groups/{3}{4}"
        url = url.format(self.assetLibraryBaseUrl,"%2Fauto%2Fusers%2F", username, '%2Fauto%2Fvehicles%2F', vin)
        payload={}
        headers = {
            'Authorization': authorization,
            'Accept': self.cAcceptHeader,
            'Content-Type': self.cContentType
        }  
        response = requests.request("PUT", url, headers=headers, data=payload)

        return response
def main(profile, stackname, cdfstackname, vin, firstname, lastname, username, password):
    
   #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']
   root_cert_url = config_parameters['AWS_ROOT_CERT_URL']
   root_cert = config_parameters['ROOT_CERT']
   root_cert_path = config_parameters['ROOT_CERT_PATH']
   default_role_name = config_parameters['DEFAULT_ROLE_NAME']
   default_role_arn = config_parameters['POLICY_ARN_IOT']
   deviceMaker = config_parameters['DEVICE_MAKER']
   provisioning_template_name = config_parameters['PROVISIONING_TEMPLATE_NAME']
   provisioning_template_description = config_parameters['PROVISIONING_TEMPLATE_DESCRIPTION']
   provisioning_policy_file_name = config_parameters['POLICY_JSON']
   provisioning_template_file_name = config_parameters['TEMPLATE_JSON']
   provisioning_policy_name = config_parameters['PROVISIONING_POLICY_NAME']
   
   externalId = uuid.uuid4().hex
   thingName = vin

   c = Cognito(profile)
   m = ConnectedMobility(profile, stackname, cdfstackname)
   i = IOT(profile, default_role_name, default_role_arn, CONFIG_PATH)   
   provisioner = ProvisioningHandler(CONFIG_PATH, provisioning_template_name, thingName, i.iotEndpoint)
   
   if not c.checkCognitoUser(username,m.userPoolId):
     print("Creating user ...")
     c.createCognitoUser(username, password, m.userPoolId, m.userPoolClientId)
     
   print("Logging in user ...")
   authorization = c.authenticateCognitoUser(username, password, m.userPoolId, m.userPoolClientId)
 
   #check to see if supplier exists, otherwise create a new one.
   response = m.getSupplier(deviceMaker, authorization)
   
   if response.status_code != 200:   
       print("Creating supplier ...")
       response = m.createSupplier(deviceMaker = deviceMaker, GUID = externalId, authorization = authorization)
       if response.status_code == 204:
           print("Vehicle Supplier created successfully...")
       else:
           print("Error creating vehicle supplier.  Exiting. Error: %s", response)
           exit()
   else: 
       #get externalId from existing supplier
       data = json.loads(response.text)  
       externalId = data["attributes"]["externalId"]
   
   print("Creating CMS User ...") 
   response = m.createCMSUser(firstName = firstname, lastName = lastname, username = username, authorization = authorization)
   
   if response.status_code == 201 or response.status_code == 204:
       print("CMS User created successfully...")
   else:
       print("Error creating CMS User.  May currently exist, who knows, there's no method to check.")
       
   print("Registering Device ...")          
   response = m.registerDevice(externalId, thingName, authorization)
   
   if response.status_code == 200 or response.status_code == 204 or response.status_code == 201:
       print("Device registered successfully...")
   elif response.status_code == 409:
       print("Device already registered.  Will attempt to activate the device...")
   else:
       print(response)
       print("Error registering the device.  Exiting.")
       exit()
      
   response = m.activateDevice(deviceMaker = deviceMaker, externalId = externalId, thingName = thingName, vin = vin, authorization = authorization)
   
   if response.status_code == 204:
       print("Device activated successfully...")
   else:
       print("Error activating device.  Exiting.")
       exit()
   
   response = m.associateDevice(username = username, vin = vin, authorization = authorization) 
   
   if response.status_code == 204 or response.status_code == 200:
       print("Device associated successfully...")
       print("External ID: {}".format(externalId))
       print("Thing Name: {}".format(thingName))
   else:
       print("Error associating device to user.  Exiting.")
       exit()    

   #begin setting up device certificates for this thing
   #We will use fleet provisioning to take a bootstrap certificate, this bootstrap certificate is allowed to connect to specific topics that will allow for the creation
   #of the permananet certificate.  The permanent certificate is then downloaded to the /certs folder and used to connect to the telemetry topics 
   print("Begin setting up provisioning templates and certificates...")
   v = i.setupProvisioningTemplate(
       provisioning_template_name,
       provisioning_template_description, 
       provisioning_template_file_name, 
       provisioning_policy_name, 
       provisioning_policy_file_name,
       vin)

   if v == True:
    try: #to get root cert if it does not exist    
        print("Check that the provisioning template has been created")
        template = i.describeProvisioningTemplate(provisioning_template_name)
        print(template)
        print("Getting root certificate")
        root_path = "{}/{}".format( root_cert_path, root_cert)
        if not os.path.exists( root_path):
            response = urlopen(root_cert_url)
            content = response.read().decode('utf-8')
            with open(root_path, "w" ) as f:
                f.write( content )
                f.close()
    except Exception as e:
            print(e)
            exit()
    print("Root certificate downloaded to certificates directory.")
    try:
            print("{}/{}".format(secure_cert_path.format(unique_id=vin), bootstrap_cert))
            with open("{}/{}".format(secure_cert_path.format(unique_id=vin), bootstrap_cert), 'r') as f:
            # Call super-method to perform aquisition/activation
            # of certs, association 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.")          
    
    print("Vehicle setup sucessfully, please visit http://{} to login with your user and see your vehicle".format(m.cloudFrontDomainUrl))