published

MerakiAutoRotatePSK

This python script is my first one i have done and doing it with Meraki API was a great experience. I took alot of the inspiration from this commmunity post Automatic rotating PSK for wireless
BrechtSchamp did an amazing job with the script and it was about as turn key a solution as you can get. Some main points on this script is that it assumes you know your organization ID and Network ID for your Meraki Environment. How i got my org ID was by accident on sandbox, here is the link i used Get-Oraganizations

  1. Create Meraki API key for your user in Meraki Dashboard Meraki API Overview
    Below is an example of the Always on Dev-Net Sandbox environment. As you can see this user already as 2 API keys.

Screen Shot 2022-09-09 at 4 17 35 PM

2. Get your Org ID if you dont know it [Get-Oraganizations](https://developer.cisco.com/meraki/api-v1/#!get-organizations). Here is another way of getting orgID https://documenter.getpostman.com/view/897512/SzYXYfmJ#5ac4bfa9-de2b-4fc9-b242-514914cd6a11

Postman get organizations

Run this in your browser after you logged into the dashBoard [link to API Call](https://api.meraki.com/api/v1/organizations)

API in Browser

3. Get the Network ID of the network you want to use, [Get Networks](https://developer.cisco.com/meraki/api-v1/#!get-organization-networks)

Screenshot of get Organizations networks API on dev-net

4. Copy and paste this code into Visual Studio. Here you can see i have my python virtual envionment setup in the project. i suggest to do the same, here is a link [Python Virtual Environments](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment)

Screenshot of users VSCODE

Snippet of code is below:

import requests
import random
import string
import smtplib
import ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
import qrcode 
#input path for QRcode image
#below "" equals to have the QR photo stores in the main directory of code base.
image_paths = [""]

api_key = "" # enter your meraki api key here
network_id = "" # enter the network id of the network you want to change here
ssid_number = 0 # enter the number of the ssid you want to change here 0 - 14
password_length = 15  # enter the desired length of the new PSK min 8 max 63
character_types = string.ascii_lowercase + string.ascii_uppercase + string.digits # remove or change according to needs
email_password = "" # enter a gmail app password here. (cannot use less secure access , use gmail app password process)
sender_email = "" # sending gmail address
receiver_email = "" # receiving address(es) use ["email1, email2, email3"] for multiple addresses

def random_string(stringlength=password_length):
   return ''.join(random.choice(character_types) for i in range(stringlength))

def set_new_psk(new_psk, ssid=ssid_number):
   url = "https://api.meraki.com/api/v0/networks/" + network_id + "/ssids/" + str(ssid)  #remove the spaces the I inserted to get around a community bug
   payload = "{\r\n    \"psk\": \""+str(new_psk)+"\"\r\n}"
   headers = {
       'Accept': "*/*",
       'Content-Type': "application/json",
       'cache-control': "no-cache",
       'X-Cisco-Meraki-API-Key': api_key
   }

   response = requests.request("PUT", url, data=payload, headers=headers)

   print(str(response.status_code) + " - " + response.text)
   return(response.status_code)

def send_password_email(new_psk_param):    
   message = MIMEMultipart("alternative")
   message["Subject"] = "Email Subject"
   message["From"] = sender_email
   message["To"] = ", ".join(receiver_email)
   #create QEcode Image for Email 
   #Formats:
   #Common format: WIFI:S:<SSID>;T:<WEP|WPA|blank>;P:<PASSWORD>;H:<true|false|blank>;;
   #sample : WIFI:S:MySSID;T:WPA;P:MyPassw0rd;;
   img = qrcode.make('WIFI:S:SSIDNAME;T:WPA;P:'+str(new_psk_param)+';;')
   type(img) # qrcode,image.pil.PilImage
   img.save("WIFI.png")
   
   # Create the plain-text and HTML version of your message
   text = """\
   Hi,
   We've changed the Wi-Fi password to: {new_psk}
   Kind regards,
   IT Team""".format(new_psk=new_psk_param)
   html = """\
   <html>
     <body>
     <img src="https://github.com/calcuttin/MerakiAutoRotatePSK/raw/main/<add branding here>">
       <div>Hi,<br>
          <br>
          We've changed the Wi-Fi password for SSID to: <br>
          <h1>{new_psk}</h1>
          <p> QRcode scan for mobile phones.</p> <br>
          <img src="https://github.com/calcuttin/MerakiAutoRotatePSK/raw/main/cid:image1"> </img> <br>
          Kind regards,<br>
          IT Team
       </div>
     </body>
   </html>
   """.format(new_psk=new_psk_param)

   # Turn these into plain/html MIMEText objects
   part1 = MIMEText(text, "plain")
   part2 = MIMEText(html, "html")
   
   #Attach Image 
   fp = open('WIFI.png', 'rb') #Read image 
   msgImage = MIMEImage(fp.read())
   fp.close()

   # Define the image's ID as referenced above
   msgImage.add_header('Content-ID', '<image1>')
   message.attach(msgImage)

   # Add HTML/plain-text parts to MIMEMultipart message
   # The email client will try to render the last part first
   message.attach(part1)
   message.attach(part2)

   # Create secure connection with server and send email
   context = ssl.create_default_context()
   with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
       server.login(sender_email, email_password)
       server.sendmail(
           sender_email, receiver_email, message.as_string()
       )

new_psk = random_string(password_length)
if set_new_psk(new_psk) == 200:
   send_password_email(new_psk)
  1. Import the Libraries needed on top.
    (See requirements.txt)

  2. Fill out the obejcts under the import section. Note SSIDs are number start with 0

  3. In the img on line 53 input the SSID for the QR code and Encryption. Reference QRcode info in Wikipedia

image

  1. Next look at the email bodies, there are email types plain text and HTML. I recommend editing as needed the HTML body to brand it to your needs.

  2. Line 100 you have the SMTP server, in this example i used gmail as a proof of concept for the project but change as needed.

   context = ssl.create_default_context()
    with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
        server.login(sender_email, email_password)
        server.sendmail(
            sender_email, receiver_email, message.as_string()
        )
  1. Office 365 Settings
  with smtplib.SMTP("smtp.office365.com", 587) as server:
        server.ehlo()
        server.starttls()
        server.ehlo()
        server.login(sender_email, email_password)
        server.sendmail(
            sender_email, receiver_email, message.as_string()
        )
        server.quit()

Here are some other links i used as well to research this.
Sending Emails with Python Great breakdown of the smtplib and ssl modules.

Random String Goes into more detail about the random string, take a look and customize as needed.

Sending Emails with images using python Shows how to attach the image in the email

Stack overflow how to embed picture in email Another great example.

QRcode generation option 1 I used this one but the one below is just as good.

QRcode generation option 2

I hope this code helps you solve a problem in your environment.

View code on GitHub
  • Owner

  • Contributors

    +1Github contributor
  • Categories

  • Products

    Meraki
  • Programming Languages

    Python
  • License

    MIT License

Code Exchange Community

Get help, share code, and collaborate with other developers in the Code Exchange community.View Community
Disclaimer:
Cisco provides Code Exchange for convenience and informational purposes only, with no support of any kind. This page contains information and links from third-party websites that are governed by their own separate terms. Reference to a project or contributor on this page does not imply any affiliation with or endorsement by Cisco.