{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Multi-Region IoT - Register PCA with IoT Core\n", "Register the private CA in the master and slave region in AWS IoT Core." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Libraries" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from OpenSSL import crypto, SSL\n", "from os.path import exists, join\n", "from os import makedirs\n", "from shutil import copy\n", "from time import time, gmtime, localtime, strftime\n", "import boto3\n", "import json\n", "import time" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Global Vars" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%store -r config\n", "print(\"config: {}\".format(json.dumps(config, indent=4, default=str)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Some Handy Functions" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def createCertRequest(pkey, subject, digest=\"sha256\"):\n", " print(\"subject: {}\".format(subject))\n", " req = crypto.X509Req()\n", " subj = req.get_subject()\n", " \n", " for i in ['C', 'ST', 'L', 'O', 'OU', 'CN']:\n", " if i in subject:\n", " setattr(subj, i, subject[i])\n", "\n", " req.set_pubkey(pkey)\n", " req.sign(pkey, digest)\n", " return req\n", "\n", "\n", "def create_priv_key_and_csr(cert_dir, csr_file, key_file, subject):\n", " if not exists(cert_dir):\n", " print(\"creating directory: {}\".format(cert_dir))\n", " makedirs(cert_dir)\n", " \n", " priv_key = crypto.PKey()\n", " priv_key.generate_key(crypto.TYPE_RSA, 2048)\n", " #print(crypto.dump_privatekey(crypto.FILETYPE_PEM, priv_key).decode('utf-8'))\n", "\n", " key_file = join(cert_dir, key_file)\n", " f = open(key_file,\"w\")\n", " f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, priv_key).decode('utf-8'))\n", " f.close()\n", " \n", " csr = createCertRequest(priv_key, subject)\n", "\n", " csr_file = join(cert_dir, csr_file)\n", " f= open(csr_file,\"w\")\n", " f.write(crypto.dump_certificate_request(crypto.FILETYPE_PEM, csr).decode('utf-8'))\n", " f.close()\n", " \n", " return crypto.dump_certificate_request(crypto.FILETYPE_PEM, csr)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Boto3 Client\n", "Create a boto3 client for the acm-pca service endpoint." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c_acm_pca = boto3.client('acm-pca', region_name = config['aws_region_pca'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## PCA Certificate and ARN\n", "Get the CA certificate for the private CA as well as it's arn. These values are required later to issue certificates and for the registration with AWS IoT Core." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "response = c_acm_pca.list_certificate_authorities(MaxResults=50)\n", "\n", "for ca in response['CertificateAuthorities']:\n", " if ca['CertificateAuthorityConfiguration']['Subject']['CommonName'] == config['Sub_CN']:\n", " pca_arn = ca['Arn']\n", " break\n", "\n", "print(\"pca_arn: {}\\n\".format(pca_arn))\n", "\n", "response = c_acm_pca.get_certificate_authority_certificate(\n", " CertificateAuthorityArn = pca_arn\n", ")\n", "print(\"response: {}\\n\".format(json.dumps(response, indent=4, default=str)))\n", "pca_certificate = response['Certificate']\n", "print(\"pca_certificate:\\n{}\".format(pca_certificate))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Register Private CA\n", "To register the private CA with AWS IoT Core you need to get a registration code, create a certificate containing where the value of the CN is the registration code and then use this certificate to register the CA with AWS IoT.\n", "\n", "The private CA will be registered with AWS IoT Core in the master and slave region." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for aws_region in [config['aws_region_master'], config['aws_region_slave']]: \n", " print(\"AWS REGION: {}\".format(aws_region))\n", " c_iot = boto3.client('iot', region_name = aws_region)\n", " time.sleep(2)\n", "\n", " response = c_iot.get_registration_code()\n", "\n", " print(\"response: {}\\n\".format(json.dumps(response, indent=4, default=str)))\n", " registration_code = response['registrationCode']\n", " print(\"registration_code: {}\\n\".format(registration_code))\n", "\n", " verification_csr = create_priv_key_and_csr(config['PCA_directory'], \n", " 'registration_csr_{}.pem'.format(aws_region), \n", " 'registration_key_{}.pem'.format(aws_region), \n", " {\"CN\": registration_code})\n", " print(\"verification_csr:\\n{}\\n\".format(verification_csr))\n", "\n", " idempotency_token = 'registration_cert'\n", " response = c_acm_pca.issue_certificate(\n", " CertificateAuthorityArn = pca_arn,\n", " Csr = verification_csr,\n", " SigningAlgorithm = 'SHA256WITHRSA',\n", " Validity= {\n", " 'Value': 365,\n", " 'Type': 'DAYS'\n", " },\n", " IdempotencyToken = idempotency_token\n", " )\n", "\n", " print(\"response: {}\\n\".format(json.dumps(response, indent=4, default=str)))\n", " certificate_arn = response['CertificateArn']\n", "\n", " print(\"certificate_arn: {}\\n\".format(certificate_arn))\n", "\n", " waiter = c_acm_pca.get_waiter('certificate_issued')\n", " try:\n", " waiter.wait(\n", " CertificateAuthorityArn=pca_arn,\n", " CertificateArn=certificate_arn\n", " )\n", " except botocore.exceptions.WaiterError as e:\n", " raise Exception(\"waiter: {}\".format(e))\n", " \n", " response = c_acm_pca.get_certificate(\n", " CertificateAuthorityArn = pca_arn,\n", " CertificateArn = certificate_arn\n", " )\n", " print(\"response: {}\".format(response))\n", " registration_certificate = response['Certificate']\n", "\n", " print(\"pca_certificate:\\n{}\\n\".format(pca_certificate))\n", " print(\"registration_certificate:\\n{}\\n\".format(registration_certificate))\n", " \n", " file_registration_crt = join(config['PCA_directory'], 'registration_cert_{}.pem'.format(aws_region))\n", " f = open(file_registration_crt,\"w\")\n", " f.write(registration_certificate)\n", " f.close()\n", "\n", " response = c_iot.register_ca_certificate(\n", " caCertificate = pca_certificate,\n", " verificationCertificate = registration_certificate,\n", " setAsActive = True,\n", " allowAutoRegistration = True\n", " )\n", "\n", " print(\"response: {}\\n\".format(json.dumps(response, indent=4, default=str)))\n", "\n", " certificate_id = response['certificateId']\n", " print(\"certificate_id: {}\\n\".format(certificate_id))\n", "\n", " response = c_iot.describe_ca_certificate(\n", " certificateId = certificate_id\n", " )\n", "\n", " print(\"response: {}\\n\".format(json.dumps(response, indent=4, default=str)))" ] } ], "metadata": { "kernelspec": { "display_name": "conda_python3", "language": "python", "name": "conda_python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.5" } }, "nbformat": 4, "nbformat_minor": 4 }