Hi all, Has anyone implemented or know a way to automate a password on weekly basis for a Meraki guest user account?
Solved! Go to solution.
You could also use the dashboard API to change the password weekly with a timed script.
PUT /networks/[networkId]/ssids/[number]
name | The name of an SSID |
enabled | Whether or not an SSID is enabled |
authMode | The association control method for the SSID ('open', 'psk', 'open-with-radius', '8021x-meraki' or '8021x-radius') |
encryptionMode | The psk encryption mode for the SSID ('wpa', 'wep' or 'wpa-eap') |
psk | The passkey for the SSID. This param is only valid if the authMode is 'psk' |
wpaEncryptionMode | The types of WPA encryption. ('WPA1 and WPA2' or 'WPA2 only') |
splashPage | The type of splash page for the SSID ('None', 'Click-through splash page', 'Billing', 'Password-protected with Meraki RADIUS', 'Password-protected with custom RADIUS', 'Password-protected with Active Directory', 'Password-protected with LDAP', 'SMS authentication', 'Systems Manager Sentry', 'Facebook Wi-Fi', 'Google OAuth' or 'Sponsored guest'). This attribute is not supported for template children. |
radiusServers | The RADIUS 802.1x servers to be used for authentication. This param is only valid if the authMode is 'open-with-radius' or '8021x-radius' |
host | IP address of your RADIUS server |
port | UDP port the RADIUS server listens on for Access-requests |
secret | RADIUS client shared secret |
radiusCoaEnabled | If true, Meraki devices will act as a RADIUS Dynamic Authorization Server and will respond to RADIUS Change-of-Authorization and Disconnect messages sent by the RADIUS server. |
radiusFailoverPolicy | This policy determines how authentication requests should be handled in the event that all of the configured RADIUS servers are unreachable ('Deny access' or 'Allow access') |
radiusLoadBalancingPolicy | This policy determines which RADIUS server will be contacted first in an authentication attempt and the ordering of any necessary retry attempts ('Strict priority order' or 'Round robin') |
radiusAccountingEnabled | Whether or not RADIUS accounting is enabled. This param is only valid if the authMode is 'open-with-radius' or '8021x-radius' |
radiusAccountingServers | The RADIUS accounting 802.1x servers to be used for authentication. This param is only valid if the authMode is 'open-with-radius' or '8021x-radius' and radiusAccountingEnabled is 'true' |
host | IP address to which the APs will send RADIUS accounting messages |
port | Port on the RADIUS server that is listening for accounting messages |
secret | Shared key used to authenticate messages between the APs and RADIUS server |
ipAssignmentMode | The client IP assignment mode ('NAT mode', 'Bridge mode', 'Layer 3 roaming', 'Layer 3 roaming with a concentrator' or 'VPN') |
useVlanTagging | Direct trafic to use specific VLANs. This param is only valid with 'Bridge mode' and 'Layer 3 roaming' |
concentratorNetworkId | The concentrator to use for 'Layer 3 roaming with a concentrator' or 'VPN'. |
vlanId | The VLAN ID used for VLAN tagging. This param is only valid with 'Layer 3 roaming with a concentrator' and 'VPN' |
defaultVlanId | The default VLAN ID used for 'all other APs'. This param is only valid with 'Bridge mode' and 'Layer 3 roaming' |
apTagsAndVlanIds | The list of tags and VLAN IDs used for VLAN tagging. This param is only valid with 'Bridge mode', 'Layer 3 roaming' |
tags | Comma-separated list of AP tags |
vlanId | Numerical identifier that is assigned to the VLAN |
walledGardenEnabled | Allow access to a configurable list of IP ranges, which users may access prior to sign-on. |
walledGardenRanges | Specify your walled garden by entering space-separated addresses, ranges using CIDR notation, domain names, and domain wildcards (e.g. 192.168.1.1/24 192.168.37.10/32 www.yahoo.com *.google.com). Meraki's splash page is automatically included in your walled garden. |
minBitrate | The minimum bitrate in Mbps. ('1', '2', '5.5', '6', '9', '11', '12', '18', '24', '36', '48' or '54') |
bandSelection | The client-serving radio frequencies. ('Dual band operation', '5 GHz band only' or 'Dual band operation with Band Steering') |
perClientBandwidthLimitUp | The upload bandwidth limit in Kbps. (0 represents no limit.) |
perClientBandwidthLimitDown | The download bandwidth limit in Kbps. (0 represents no limit.) |
{ "name": "viaPostman935", "enabled": false, "splashPage": "None", "perClientBandwidthLimitUp": 0, "perClientBandwidthLimitDown": 0, "ssidAdminAccessible": false, "ipAssignmentMode": "NAT mode", "authMode": "open" }
Here are the docs for that endpoint:
Splash Access do a rotating WPA2-PSK option with a QR code for configuring guest WiFi devices.
You could also use the dashboard API to change the password weekly with a timed script.
PUT /networks/[networkId]/ssids/[number]
name | The name of an SSID |
enabled | Whether or not an SSID is enabled |
authMode | The association control method for the SSID ('open', 'psk', 'open-with-radius', '8021x-meraki' or '8021x-radius') |
encryptionMode | The psk encryption mode for the SSID ('wpa', 'wep' or 'wpa-eap') |
psk | The passkey for the SSID. This param is only valid if the authMode is 'psk' |
wpaEncryptionMode | The types of WPA encryption. ('WPA1 and WPA2' or 'WPA2 only') |
splashPage | The type of splash page for the SSID ('None', 'Click-through splash page', 'Billing', 'Password-protected with Meraki RADIUS', 'Password-protected with custom RADIUS', 'Password-protected with Active Directory', 'Password-protected with LDAP', 'SMS authentication', 'Systems Manager Sentry', 'Facebook Wi-Fi', 'Google OAuth' or 'Sponsored guest'). This attribute is not supported for template children. |
radiusServers | The RADIUS 802.1x servers to be used for authentication. This param is only valid if the authMode is 'open-with-radius' or '8021x-radius' |
host | IP address of your RADIUS server |
port | UDP port the RADIUS server listens on for Access-requests |
secret | RADIUS client shared secret |
radiusCoaEnabled | If true, Meraki devices will act as a RADIUS Dynamic Authorization Server and will respond to RADIUS Change-of-Authorization and Disconnect messages sent by the RADIUS server. |
radiusFailoverPolicy | This policy determines how authentication requests should be handled in the event that all of the configured RADIUS servers are unreachable ('Deny access' or 'Allow access') |
radiusLoadBalancingPolicy | This policy determines which RADIUS server will be contacted first in an authentication attempt and the ordering of any necessary retry attempts ('Strict priority order' or 'Round robin') |
radiusAccountingEnabled | Whether or not RADIUS accounting is enabled. This param is only valid if the authMode is 'open-with-radius' or '8021x-radius' |
radiusAccountingServers | The RADIUS accounting 802.1x servers to be used for authentication. This param is only valid if the authMode is 'open-with-radius' or '8021x-radius' and radiusAccountingEnabled is 'true' |
host | IP address to which the APs will send RADIUS accounting messages |
port | Port on the RADIUS server that is listening for accounting messages |
secret | Shared key used to authenticate messages between the APs and RADIUS server |
ipAssignmentMode | The client IP assignment mode ('NAT mode', 'Bridge mode', 'Layer 3 roaming', 'Layer 3 roaming with a concentrator' or 'VPN') |
useVlanTagging | Direct trafic to use specific VLANs. This param is only valid with 'Bridge mode' and 'Layer 3 roaming' |
concentratorNetworkId | The concentrator to use for 'Layer 3 roaming with a concentrator' or 'VPN'. |
vlanId | The VLAN ID used for VLAN tagging. This param is only valid with 'Layer 3 roaming with a concentrator' and 'VPN' |
defaultVlanId | The default VLAN ID used for 'all other APs'. This param is only valid with 'Bridge mode' and 'Layer 3 roaming' |
apTagsAndVlanIds | The list of tags and VLAN IDs used for VLAN tagging. This param is only valid with 'Bridge mode', 'Layer 3 roaming' |
tags | Comma-separated list of AP tags |
vlanId | Numerical identifier that is assigned to the VLAN |
walledGardenEnabled | Allow access to a configurable list of IP ranges, which users may access prior to sign-on. |
walledGardenRanges | Specify your walled garden by entering space-separated addresses, ranges using CIDR notation, domain names, and domain wildcards (e.g. 192.168.1.1/24 192.168.37.10/32 www.yahoo.com *.google.com). Meraki's splash page is automatically included in your walled garden. |
minBitrate | The minimum bitrate in Mbps. ('1', '2', '5.5', '6', '9', '11', '12', '18', '24', '36', '48' or '54') |
bandSelection | The client-serving radio frequencies. ('Dual band operation', '5 GHz band only' or 'Dual band operation with Band Steering') |
perClientBandwidthLimitUp | The upload bandwidth limit in Kbps. (0 represents no limit.) |
perClientBandwidthLimitDown | The download bandwidth limit in Kbps. (0 represents no limit.) |
{ "name": "viaPostman935", "enabled": false, "splashPage": "None", "perClientBandwidthLimitUp": 0, "perClientBandwidthLimitDown": 0, "ssidAdminAccessible": false, "ipAssignmentMode": "NAT mode", "authMode": "open" }
Here are the docs for that endpoint:
You're welcome.
a bit late to the camp but I recently just finished a powershell script and implemented it last week:
It generates a random password (length and complexity can be changed in the script), it then updates the relevant SSID in the required site and emails the password to the reception mailbox.
Site name and SSID name are passed as parameters to the script. Its currently used for just the guest wifi, but can obviously be used for any that uses a PSK.
It's scheduled to run at 4pm Fridays (this gives reception time to print out the new password ready for the nights and weekend security teams.
e.g.:
MerakiPSKTool.ps1 -site <sitename> -ssid <ssidname>
rgds
Gary
This is exactly what I'm looking for. SSID's psk must be changed once a month and the password emailed to a distro list.
Can you share your script? I'm no good with power shell, but some folks here are. I'm sure I could get them to help me implement.
thanks!
Gary,
Is your script available to share? I am looking for something like this as well. I am trying Splash Access now but I only want just that feature from them and not the whole package. I don't think they price it separately. There's automates the rotating of the PSK, but I believe I can only do one SSID.
Thanks,
Steve
For those still looking to do this. I just wrote a script to do it. You can find it here:
Thanks BrechtSchamp!
I've just gotten started with Python, so this is a great script to use and learn!
I'm working on one that will run multiple remote commands on multiple Cisco wireless controllers. So far, it's very promising.
Hi Steve,
Below is the powershell script - As it stands, it is hard coded for a single organisation as the base URI contains the Org ID
You will just need to populate the necessary areas with your particular details etc.
I.E. smpt server and recipient info in function sendMail
API key in function Get-WifiSSID
base_uri & api_key in #setup some global static stuff section
email message body in section # build email message body and send it
You can change password length (currently 10 chars) and complexity by changing the code in function createPassword
param([string]$site="",[string]$ssid="",[string]$action="")
function sendMail([string]$txtbody)
{
#SMTP server name
$smtpServer = "<InsertYourSMTPMailServerInfoHere>"
#Creating a Mail object
$msg = new-object Net.Mail.MailMessage
#Creating SMTP server object
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
#Email structure
$msg.From = "merakiapi@<YourMailDomainHere>"
$msg.To.Add("<RecipientMailAddressHere>")
#$msg.To.Add("<OtherRecipientAddressHere")
$msg.subject = "New password for guest Wifi"
$msg.body = $txtbody
$msg.IsBodyHTML=$true
#Sending email
$smtp.Send($msg)
}
function Get-RandomCharacters($length, $characters)
{
$random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
$private:ofs=""
return [String]$characters[$random]
}
function Scramble-String([string]$inputString)
{
$characterArray = $inputString.ToCharArray()
$scrambledStringArray = $characterArray | Get-Random -Count $characterArray.Length
$outputString = -join $scrambledStringArray
return $outputString
}
function updateWiFiPSK ([string]$s_id, [string]$w_id, [string]$newpassword)
{
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# PSK = New password
$data = @{
"psk" = $newpassword
}
#Convert data to Json format
$jbody = ConvertTo-Json -InputObject $data
#Combine base URL and ssid
$request_uri = $base_uri + $networks_uri + $s_id + "/ssids/" + $w_id
$r = Invoke-WebRequest $request_uri -Method:Put -Headers $header_org -Body $jbody
return $r
}
function Get-SiteID
{
#get site id
$request_uri = $base_uri + $networks_uri
$r = Invoke-WebRequest $request_uri -Method:Get -Headers $header_org
$json = $r | ConvertFrom-Json
for($i=0;$i -lt $json.count;$i++)
{
if ($site -eq $json[$i].name)
{
Write-host "Network Name : " $json[$i].name
Write-host "id : " $json[$i].id
Write-host "Type : " $json[$i].type
$s_id = $json[$i].id
}
}
return $s_id
}
function Get-WiFiSSID ([string]$s_id)
{
#get wifi network ID from site requested
if ($s_id -ne "")
{
$request_uri = $base_uri + $networks_uri + $s_id + "/ssids/"
$r = Invoke-WebRequest $request_uri -Method:Get -Headers @{"X-Cisco-Meraki-API-Key"="<ReplaceWithYouAPIKeyHere>"} -ContentType "application/json"
$z = $r | ConvertFrom-Json
for($i=0;$i -lt $z.count;$i++)
{
If ($z[$i].name -eq $ssid)
{
Write-host "SSID Name : " $z[$i].name
Write-host "SSID# : " $z[$i].number
Write-host "Current PSK : " $z[$i].psk
$w_id = $z[$i].number
}
}
}
return $w_id
}
function createPassword
{
$password = Get-RandomCharacters -length 4 -characters 'abcdefghiklmnoprstuvwxyz'
$password += Get-RandomCharacters -length 2 -characters 'ABCDEFGHKLMNOPRSTUVWXYZ'
$password += Get-RandomCharacters -length 2 -characters '1234567890'
$password += Get-RandomCharacters -length 2 -characters '!$%&()?}][{@#+'
#Write-Host $password
return Scramble-String $password
}
# setup some global static stuff
$base_uri = "https://<InsertYourMerakiAPIBaseURLHere>"
## E.G. n34.meraki.com/api/v0/organizations/<OrgID>/
$networks_uri = "networks/"
#Meraki API KEY
$api_key = "<InsertYourAPIKeyHere>"
$header_org = @{"X-Cisco-Meraki-API-KEY" = $api_key;"Content-Type" = 'application/json'}
$s_id = ""
$w_id = ""
$mode = ""
If ($site -eq "" -or $ssid -eq "")
{
Write-Host "MerakiPSKTool - (c) 2019"
Write-Host ""
Write-Host "Site/SSID parameter is missing"
Write-Host "Usage: MerakiPSKTool.ps1 -site <sitename> -ssid <ssidName> -action [Change | Display]"
Write-Host ""
exit
}
# if action not passed or is blank, set default mode to Display
if ($action -eq "")
{
$action = "Display"
}
switch ($action)
{
{@("Display", "display") -contains $_ }
{
"Displaying Wifi details"
$mode = "display"
}
{@("Change", "change") -contains $_ }
{
"Change Wifi password"
$mode = "change"
}
default { "MerakiPSKTool.ps1" }
}
# get ID of the site passed in params (set a default value if no site passed)
$s_id = Get-SiteID
If ($s_id -ne "")
{
# get id of Wifi network that password is to be changed for
$w_id = Get-WifiSSID($s_id)
#Write-Host "Site ID : " $s_id " | Wifi #: " $w_id
}
if ($mode -eq "change")
{
# generate a new complex password
$newpassword = createPassword
$result = updateWiFiPSK $s_id $w_id $newpassword
#Write-Host $result
# build email message body and send it
if ($result.StatusCode -eq 200)
{
Write-Host "Sending Email"
$txtbody = "<html><body>"
$txtbody = $txtbody + "The new password for " + $ssid + " at " + $site + " is<br><br><b><font size=30 color=green>"
$txtbody = $txtbody + $newpassword + "</font></b>"
$txtbody = $txtbody + "<br><br>If you have any problems please contact <SomeContactDetailsHere>"
$txtbody = $txtbody + "<br><br>regards<br>SignoffInfo"
$txtbody = $txtbody + "</body></html>"
#Write-Host $txtbody
# send the email
sendMail $txtbody
}
else
{
Write-Host "Password change failed for " + $ssid + " at " + $site
}
}
Copy and paste the above into text editor, make the necessary changes and save as MerakiPSKTool.ps1
to display current PSK for site, use
MerakiPSKTool.ps1 -site <sitename> -ssid <SSIDName> -action Display
to change psk for site use
MerakiPSKTool.ps1 -site <sitename> -ssid <SSIDName> -action Change
if no Action value provided it will default to Display
Current email body looks like this:
The new password for [ssidName] at [SiteName] is
z$ys$63mPX
If you have any problems please contact [ContactName] on [ContactTel] or [ContactEmail]
regards
[Contact]
Subject line is New password for guest Wifi
I'm not a pro programmer so use at own risk, i've had it running now for a good couple or months or so now and it's worked fine since.
rgds
Gary
nealgs,
THANK YOU for the reply. I am getting an error that I think may be related to the base URL. I am not sure where I find the orgid? Can you give me a pointer on that please?
Thanks,
Steve
hi Steve,
from your Meraki dashboard, type this url into address bar
https://dashboard.meraki.com/api/v0/organizations
or even just append your dashboard address to be
https://<yourdashboardurl>/api/v0/organizations
and press Enter - it should then return some json info:
[{"id":"<yourOrgID>".......
use the value in there for orgid - think it's a 6 digit number, at least ours is
Once the SSID password is changed, is there an easy way to tell it to sync across to other networks?
Hi JoshMikow,
As the code stands, no - it's per SSID in a named Network. You'd have to run it once for each SSID in each network. It would require a fair bit of change to do what you want.
I do have plans in the near future to amend it so that you can change the password for a named SSID across all networks - this is because we have a corporate wifi that we want to be able to sync passwords with to allow cross site visitors to be able to automatically access the Corporate Wifi once onsite - just waiting for the relevant infrastructure to be installed and setup to allow this (e.g. MR devices at those sites without)
I don't think there is a Meraki API call or anything in the Meraki Dashboard that will do what you need either.
rgds
Gary
Thanks Gary. I'm also looking into using Configuration Templates to see if that would be a way to sync the settings. New to the API so I'm trying to make it as simple but secure as possible.
Hello,
Thank you for the awesome script. I am just trying to run the script in display mode and all I see is 'Displaying Wifi details' but nothing after that, any ideas?
Thanks,
Davis
Hi Davis,
Make sure you have the correct specific info in place - e.g. network id, API key etc
rgds
Gary
Hi Gary,
Thank you for your quick response - where in your code should I include the network ID? Sorry, I tried to find it but I couldn't.
I have updated the API key.
Thanks,
Davis
Hi Davis,
In the original posting the changes you need to make are
smpt server and recipient info in function sendMail
API key in function Get-WifiSSID
base_uri & api_key in #setup some global static stuff section
email message body in section # build email message body and send it
If you search for the text bolded above, that will take you to the relevant areas you need to modify with your info
in the code
give me a shout if any more help needed 🙂
Yes, I have done those (above mentioned) changes already except for updating the 'network ID' and I couldn't tell where to include this info. What am I missing?
Thank you,
Davis
My bad, I was missing the '/' at the end of $base_uri and I can get the output finally using the 'Display'.
I will try to use the 'Change' as well as do further testing and get back if I need any help.
Thank you for your assistance, much appreciated.
Good to hear you got it sorted 🙂
No problem - drop a post in here if any more issues.
HI Nealgs
I am not getting clear about update Get-WifiSSID value in script, please help on this
Hi Taslim,
You need to apply for an API access code the value of which goes into the Get-WifiSSID function
Go to Organisation/Settings and scroll down to bottom. You should see a section called
Dashboard API Access
tick Enable access too ..... and following instructions to get you API key
This key then goes into the code sections Get-WifiSSID function and the setup some globals section
rgds
Gary
Hi Neagls,
First of all thanks to your all help.
I have set the API key and i am able to communicate the API, i tested through https://developer.cisco.com/meraki/api-v1/#!update-network-wireless-ssid.
Hi Taslim,
The first error message (red text on blue) usually occurs if you don't provide the full path to a Ps1 script.
So for example, my merakipsktool.ps1 file resides in
C:\tst\powershell
if i'm in Powershell ISE, then i'd CD to c:\tst\powershell
and to run the script, i'd type
.\merakipsktool.ps1
this displays the the copyright sign and a message that the site/ssid parameter was missed
The 2nd screen where yours appears to show nothing i'd say is due to something not being entered correctly in the areas of the script that need to be changed to have your Meraki specific details.
Can you double check them again, and make sure you include a '/' at the end of $base_uri variable - (see DavisJ post earlier)
rgds
Gary
Hi Nealgs,
Yaa i was missing / at the end of Base Uri, Now Display action working perfectly, however change action not working getting below error.
param([string]$site=" changed according to us ",[string]$ssid="changed according to us",[string]$action="Display")
function sendMail([string]$txtbody)
{
#SMTP server name
$smtpServer = " changed according to us "
#Creating a Mail object
$msg = new-object Net.Mail.MailMessage
#Creating SMTP server object
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
#Email structure
$msg.From = "merakiapi@ changed according to us "
$msg.To.Add("changed according to us ")
$msg.subject = "New password for guest Wifi"
$msg.body = $txtbody
$msg.IsBodyHTML=$true
#Sending email
$smtp.Send($msg)
}
function Get-RandomCharacters($length, $characters)
{
$random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
$private:ofs=""
return [String]$characters[$random]
}
function Scramble-String([string]$inputString)
{
$characterArray = $inputString.ToCharArray()
$scrambledStringArray = $characterArray | Get-Random -Count $characterArray.Length
$outputString = -join $scrambledStringArray
return $outputString
}
function updateWiFiPSK ([string]$s_id, [string]$w_id, [string]$newpassword)
{
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# PSK = New password
$data = @{
"psk" = $newpassword
}
#Convert data to Json format
$jbody = ConvertTo-Json -InputObject $data
#Combine base URL and ssid
$request_uri = $base_uri + $networks_uri + $s_id + "/ssids/" + $w_id
$r = Invoke-WebRequest $request_uri -Method:Put -Headers $header_org -Body $jbody
return $r
}
function Get-SiteID
{
#get site id
$request_uri = $base_uri + $networks_uri
$r = Invoke-WebRequest $request_uri -Method:Get -Headers $header_org
$json = $r | ConvertFrom-Json
for($i=0;$i -lt $json.count;$i++)
{
if ($site -eq $json[$i].name)
{
Write-host "Network Name : " $json[$i].name
Write-host "id : " $json[$i].id
Write-host "Type : " $json[$i].type
$s_id = $json[$i].id
}
}
return $s_id
}
function Get-WiFiSSID ([string]$s_id)
{
#get wifi network ID from site requested
if ($s_id -ne "")
{
$request_uri = $base_uri + $networks_uri + $s_id + "/ssids/"
$r = Invoke-WebRequest $request_uri -Method:Get -Headers @{"X-Cisco-Meraki-API-Key"=" changed according to us "} -ContentType "application/json"
$z = $r | ConvertFrom-Json
for($i=0;$i -lt $z.count;$i++)
{
If ($z[$i].name -eq $ssid)
{
Write-host "SSID Name : " $z[$i].name
Write-host "SSID# : " $z[$i].number
Write-host "Current PSK : " $z[$i].psk
$w_id = $z[$i].number
}
}
}
return $w_id
}
function createPassword
{
$password = Get-RandomCharacters -length 4 -characters 'abcdefghiklmnoprstuvwxyz'
$password += Get-RandomCharacters -length 2 -characters 'ABCDEFGHKLMNOPRSTUVWXYZ'
$password += Get-RandomCharacters -length 2 -characters '1234567890'
$password += Get-RandomCharacters -length 2 -characters '!$%&()?}][{@#+'
#Write-Host $password
return Scramble-String $password
}
# setup some global static stuff
$base_uri = "https://nXX.meraki.com/api/v0/organizations/ changed according to us/ "
## E.G. n34.meraki.com/api/v0/organizations/<OrgID>/
$networks_uri = "networks/"
#Meraki API KEY
$api_key = " changed according to us "
$header_org = @{"X-Cisco-Meraki-API-KEY" = $api_key;"Content-Type" = 'application/json'}
$s_id = ""
$w_id = ""
$mode = ""
If ($site -eq "" -or $ssid -eq "")
{
Write-Host "MerakiPSKTool - (c) 2019"
Write-Host ""
Write-Host "Site/SSID parameter is missing"
Write-Host "Usage: MerakiPSKTool.ps1 -site changed according to us -ssid changed according to us -action [Change | Display]"
Write-Host ""
exit
}
# if action not passed or is blank, set default mode to Display
if ($action -eq "")
{
$action = "Display"
}
switch ($action)
{
{@("Display", "display") -contains $_ }
{
"Displaying Wifi details"
$mode = "display"
}
{@("Change", "change") -contains $_ }
{
"Change Wifi password"
$mode = "change"
}
default { "MerakiPSKTool.ps1" }
}
# get ID of the site passed in params (set a default value if no site passed)
$s_id = Get-SiteID
If ($s_id -ne "")
{
# get id of Wifi network that password is to be changed for
$w_id = Get-WifiSSID($s_id)
#Write-Host "Site ID : " $s_id " | Wifi #: " $w_id
}
if ($mode -eq "change")
{
# generate a new complex password
$newpassword = createPassword
$result = updateWiFiPSK $s_id $w_id $newpassword
#Write-Host $result
# build email message body and send it
if ($result.StatusCode -eq 200)
{
Write-Host "Sending Email"
$txtbody = "<html><body>"
$txtbody = $txtbody + "The new password for " + $ssid + " at " + $site + " is<br><br><b><font size=30 color=green>"
$txtbody = $txtbody + $newpassword + "</font></b>"
$txtbody = $txtbody + "<br><br>If you have any problems please contact <SomeContactDetailsHere>"
$txtbody = $txtbody + "<br><br>regards<br>SignoffInfo"
$txtbody = $txtbody + "</body></html>"
#Write-Host $txtbody
# send the email
sendMail $txtbody
}
else
{
Write-Host "Password change failed for " + $ssid + " at " + $site
}
}
Hi Gary,
All good now its working as expected.
Thanks lots
Hi Gary,
Is there any script available to change the PSK if site network managed by configuration template, i tried with couple of change but not working.
Hi Taslim
Sorry can't help on that one im afraid - not really used config templates, so not sure how they differ with regards to directly changing a SSID psk.
rgds
Gary
Hi Taslim,
Good to hear 🙂
What was the problem in the end - would be good to know in case someone else has similar issues.
rgds
Gary
Getting Below error, Please help.
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (MerakiPSKTool.ps1:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Hi Taslim
Can you provide a screenshot of how you are attempting to run the script - the error seems to be incomplete as it's not saying which Command isn't found.
I've not seen that error during my testing and final implementation of the script.
rgds
Gary
Great script, thanks.
Using the script as is I got the below error due to TLS issues.
The underlying connection was closed: An unexpected error occurred on a send.
Adding the below line before invoking the web request did the trick.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Hi Jason7,
I've never seen that error before 🙂 very strange. I've had the script running for over a year now. Executes a scheduled task at 4pm every Friday to change the guest wifi password and sends out and email to a couple of recipients with the new one.
The line you entered already exists in the function updateWiFiPSK
rgds
Gary
I added the line prior to the web request in the Get-SiteID function. It may be something specific in relation to my host. Either way it is working well now and running as a scheduled task. Thanks for sharing, saved me hours 🙂
Hi Nealgs,
For the life of me I can't get the script to work. I have made sure everything is good and even tested my URL links outside of the script and can get to them, but I keep getting a blank readout when trying to display and when I try to run change I get a 404 error
I have got following error message when I try with "Change" option. "Display" option is okay. Can help me check this error?
Invoke-WebRequest : The remote server returned an error: (400) Bad Request.
At C:\Users\sithu\Dropbox\AMNET\Meraki WiFi PSK Auto Generate\MerakiPSKTool.ps1:56 char:7
+ $r = Invoke-WebRequest $request_uri -Method:Put -Headers $header_ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Hi STM,
Can you confirm you have made all of the necessary changes in the script to contain your meraki details
i.e the values for $request_uri, $header_org and $jbody etc have been set correctly
Gary
Hi Nealgs,
Yes, I made necessary changes in script. I can see the SSID PSK with "Display" switch. But I cannot change the PSK. If I run with "Change" switch, this error occurs.
Following is my Script that I add required parameters.
I've never tried the code changing or adding anything more than just the password value.
Can you try it but remove the entries in the $data section so it looks like this:
I'd suggest installing Postman app and getting the Meraki API collection - it allows you to mess around with calls etc and see the results.
for multiple values in $data i think they need to be separated by commas
Hi STM,
Ok, i've just tried the script out changing multiple values
$data = @{
"authMode" = "psk"
"encryptionMode" = "wpa"
"psk" = $newpassword"
}
I tried with commas and it generated the errors - remove commas and it runs and changes the password ok.
Not sure why you want to include/change authmode and encryptionmode as i'd thought they would stay the same each time?
Gary
Hi nealgs,
I also tried and get the new PSK from email. But when I check the SSID PSK on Meraki dashboard, it display old PSK.
It should display the updated PSK, right?
Regards,
Add the following line in green (code is around line 184) into the script - this will display the new password as well
it'll can take a couple of mins for the Meraki portal to show the changed password - but if you run the script again in display mode, it should show the new password as the Current password.
run script in display mode gets this output:
Network Name : <nameofnetwork>
id : <blahblah>
Type : combined
SSID Name : APITest
SSID# : 5
Current PSK : TkGl55[&51
run in change mode should show the output below after you put in the extra line in the script:
Change Wifi password
Network Name : <nameofnetwork>
id : <blahblah>
Type : combined
SSID Name : APITest
SSID# : 5
Current PSK : TkGl55[&51
New Password : 8$1vA9p4T[
Sending Email
Paste your results in here once run
Gary
Hi nealgs,
This is output of "change".
Change Wifi password
Network Name : STM-HQ
id : N_739153288842186759
Type : wireless
SSID Name : GUEST_WIFI
SSID# : 1
Current PSK : 73gbL#!Bym
New PSK : pWD%3hc4a$
Sending Email
This is output of "display". It shows updated password.
Displaying Wifi details
Network Name : STM-HQ
id : N_739153288842186759
Type : wireless
SSID Name : GUEST_WIFI
SSID# : 1
Current PSK : pWD%3hc4a$
For SSID PSK in Meraki dashboard, it still shows very old one.
But we don't need to take note that PSK right?
looking at the output, the psk is being changed correctly
the display mode lists the current psk password it get it's from the ssid you provide so it is reading correct one and looks to be working ok.
I don't quite understand your line:
For SSID PSK in Meraki dashboard, it still shows very old one.
for the display mode to show the correct value, then the value in the Meraki Dashboard must also be correct as they both read the value from the same location (i assume).
Gary
Having an issue I am not sure how to resolve. This is the error
PS C:\Meraki Scripts> .\MerakiPSKTool.ps1 -site Wireless -ssid Guest
Displaying Wifi details
Network Name : Wireless
id : N_616000344304523008
Type :
Invoke-WebRequest : Page not found
The page you are looking for may have been moved or does not exist.
To log in to the Cisco Meraki Dashboard, go to https://dashboard.meraki.com.© 2021 Cisco Systems, Inc.
At C:\Meraki Scripts\MerakiPSKTool.ps1:138 char:14
+ ... $r = Invoke-WebRequest $request_uri -Method:Get -Headers @{"X- ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
ConvertFrom-Json : Cannot bind argument to parameter 'InputObject' because it is null.
At C:\Meraki Scripts\MerakiPSKTool.ps1:140 char:19
+ $z = $r | ConvertFrom-Json
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertFrom-Json], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
Hi Paul1226,
Hmm, strange one is this.
It looks to of failed in the Get-WifiSSID function which is called once it gets the site ID ($s_id) from the Get-SiteID function.
Are you sure that the Network you are querying has any wireless devices on it?
If i run the scripts against a site without any wifi devices i get an Invoke-WebRequest error at the same point.
discovered this issue in my base uri was using v1 and v0
failed with this code
# setup some global static stuff
$base_uri = "https://api.meraki.com/api/v1/organizations/<OrgID>/"
functioned properly using this code
# setup some global static stuff
$base_uri = "https://api.meraki.com/api/v0/organizations/<OrgID>/"
Great news 🙂
The original post with the script code does mention to make sure the Base URI is correct for your site. It would appear the there are other possibilities for the vX value based on this v0 and v1.
i'll add a note into original post for this.
rgds
Gary
Hi,
I am running the change command with your script and am getting:
Invoke-WebRequest : The remote server returned an error: (404) Not Found.
At C:\MerakiPSKTool.ps1:56 char:7
+ $r = Invoke-WebRequest $request_uri -Method:Put -Headers $header_ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
eption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
I am pretty sure everything is correct. Any ideas why I might be seeing this?
Thanks!
Can you someone help me, how to change the authentication : " enabled" : false "for view the password XXXX and modify
Looking at that code, it should be:
$base_uri = "https://api.meraki.com/api/v1/organizations/ORG_ID/"
I have already tried the below and still the error is same. The URL's I have tried are
"https://api.meraki.com/api/v0/organizations/ORG_ID/"
"https://api.meraki.com/api/v1/organizations/ORG_ID/"
"https://n290.meraki.com/api/v0/organizations/ORG_ID/>"
"https://n290.meraki.com/api/v1/organizations/ORG_ID/>"
"https://dashboard.meraki.com/api/v0/organizations/ORG_ID/"
"https://dashboard.meraki.com/api/v1/organizations/ORG_ID/"
All of them fail with the same error, I have made double confirmation that API_Key works. Also replaced the ORG_ID with the ORG_ID displayed in most of the web_pages at the bottom "Data for XYZ (organization ID: 123456) is hosted in Asia-Pacific"
Try:
"https://api.meraki.com/api/v1/organizations/ORG_ID/"
And then give us the new error. It will be a different error.
With the $base_uri = "https://api.meraki.com/api/v1/organizations/12345/" - 12345 being the org_id displayed at the bottom of my meraki dashboard page in Web_UI , I run the command as
.\MerakiPSKTool.ps1 -site <sitename> -ssid <ssidName> -action Display
The errors are :
===
Displaying Wifi details
Network Name : NetworkName
id : Network_Id
Type :
Invoke-WebRequest : Page not found
The page you are looking for may have been moved or does not exist.
To log in to the Cisco Meraki Dashboard, go to https://dashboard.meraki.com.© 2024 Cisco Systems, Inc.
At D:\scripts\amagi\MerakiPSKTool.ps1:90 char:14
+ ... $r = Invoke-WebRequest $request_uri -Method:Get -Headers @{"X- ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
ConvertFrom-Json : Cannot bind argument to parameter 'InputObject' because it is null.
At D:\scripts\amagi\MerakiPSKTool.ps1:92 char:19
+ $z = $r | ConvertFrom-Json
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertFrom-Json], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
===