Hi Everyone,
I got a little frustrated by the lack of any official PowerShell module for Cisco's Meraki products and the existing independently developed modules only have a fraction of the available endpoints. So to remedy this issue I wrote my own. I've been working on it on and off for a few months and I've finally reached a point that I'm considering the 1.0 release. There are 644 commands in total and I've been able to test a majority of the Get commands. The others I've had less opportunity to verify, but I have tested and used a few of them in production ready scripts. I'm still working on more detailed documentation, but in its current form it's ready for other humans to start playing with it and providing feedback.
I've published it to GitHub and the official PowerShell Gallery repository so you can install manually or simply by running the install command from an elevated PowerShell window:
Install-Module Meraki
You'll need an API key from your Meraki dashboard to get started.
Check the GitHub page for more information and usage examples:
Meraki PowerShell Module on GitHub
If anyone from Cisco is watching this thread, please send me free gear to validate my module with.
I'm already using this heavily in my own environment, but I'm looking for more people to test and provide feedback.
P.S. I'm #notTheNetworkGuy, I'm an IT Operations engineer and my job is largely focused on automating our environment. Nothing I've done here couldn't also have been easily accomplished with the existing Python library, but everything else in my mostly Windows-centric world is using PowerShell, so I made this to be able to write everything in the same language.
Maybe it will help you.
https://www.powershellgallery.com/packages?q=Tags%3A%22Meraki%22
It was actually the existing lackluster options that caused me to create this.
Well done. What a great effort.
Thanks!
Good to see (and welcome to the community)!
Thanks for putting in the effort, it looks great.
The lack of a decent powershell module was something I noticed early on too but I'm nowhere near proficient enough to write my own.
@DocNougat I add this module and it looks extremely promising. I need to update a SSID across 170 networks and have been playing with the following commands but I keep getting error messages. I think there is a bug in the code or there is just not enough information to write the commands correctly on my part. Any help you can provide would be greatly appreciated.
$SSIDConfig = {"name":"TEST- Vendor 2" "enabled":"True" "authMode":"psk" "psk":"TestTest1" "encryptionMode":"wpa" "wpaEncryptionMode":"WPA3 Transition Mode" "ipAssignmentMode":"NAT Mode" "bandSelection":"Dual band operation" "lanIsolationEnabled":"False"}
$SSIDConfig = $SSIDConfig | ConvertTo-Json -Compress
Set-MerakiNetworkWirelessSSID -AuthToken "7xxxxxxxxxxxxxxxxxxxxxxx" -NetworkId "L_6xxxxxxxxxxxxxxxxxxx" -Number 2 -SSIDConfig $SSIDConfig
The first issue is that it does not like the {"name":"Test - Vendor 2" .... I have tired comas, spaces, semi-colons, as well as single quotes and double quotes, etc.
I have also tried @{"name":"TEST- Vendor 2" .....} in case it thinks it is an ARRAY. So far I cannot get past this.
Error:
At line:1 char:18
+ $SSIDConfig = {"name":"TEST - Vendor 2","enabled":"True","authMo ...
+ ~~~
Unexpected token ':"TEST - Vendor 2"' in expression or statement.
I tried the following which does not give me an error for the $SSIDConfig but does give me a message when I use the Set-MerakiNetworkWirelessSSID command.
$SSIDConfig = {name:TEST - Vendor 2,enabled:True,authMode:psk,psk:TestTest1,encryptionMode:wpa,wpaEncryptionMode:WPA3 Transition Mode,ipAssignmentMode:NAT Mode,bandSelection:Dual band operation,lanIsolationEnabled:False}
$SSIDConfig = $SSIDConfig | ConvertTo-Json -Compress
Set-MerakiNetworkWirelessSSID -AuthToken "7xxxxxxxxxxxxxxxxxxxxxxx" -NetworkId "L_6xxxxxxxxxxxxxxxxxxx" -Number 2 -SSIDConfig $SSIDConfig
Error:
The remote server returned an error: (400) Bad Request.
Any suggestions or help would be most helpful. Thanks.
What happens if you use a name of "Test" (an invalid SSID - does that resolve the "Unexpected token" error?).
Thanks for the idea, however same Error:
$SSIDConfig = {"name":"Test","enabled":"True","authMode":"psk","psk":"TestTest1","encryptionMode":"wpa","wpaEncryptionMode":"WPA3 Transition Mode","ipAssignmentMode":"NAT Mode","bandSelection":"Dual band operation","lanIsolationEnabled":"False"}
At line:1 char:23
+ $SSIDConfig = {"name":"Test","enabled":"True","authMode":"psk","psk" ...
+ ~~~~~~~
Unexpected token ':"Test"' in expression or statement.
At line:1 char:30
+ $SSIDConfig = {"name":"Test","enabled":"True","authMode":"psk","psk" ...
+ ~
Missing argument in parameter list.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
The syntax is incorrect. In PowerShell, hashtables are defined using @{} and key-value pairs are separated by = and semicolons ;
Thanks. I think I tried that and then you get prompted for more information from PS.
Yup tested it just now and I get the PS >> prompt requesting more information.
$SSIDConfig = @{"name":"Test";"enabled":"True";"authMode":"psk";"psk":"TestTest1";"encryptionMode":"wpa";"wpaEncryptionMode":"WPA3 Transition Mode";"ipAssignmentMode":"NAT Mode";"bandSelection":"Dual band operation";"lanIsolationEnabled":"False"}
>>
Sorry for the question, but what exactly are you trying to update? Are these networks in a template?
We have 170 Meraki Networks. I am trying to push out a standard SSID to all the sites {networks} We need all of them to have the exact same SSID. This test is just doing one network to test once I get it correct I will write the PowerShell to enumerate all the networks and update them.
I got It. I have an example of a script that I used for my clients, but I didn't find the latest version, but I have this other one that could help.
# Define the API key
$apiKey = "<Your-API-Key>"
# Define the new SSID name
$newSSIDName = "<New-SSID-Name>"
# Define the network IDs
$networkIDs = "<Your-Network-IDs>"
# Define the headers
$headers = @{
"X-Cisco-Meraki-API-Key" = $apiKey
"Content-Type" = "application/json"
}
# Loop through each network ID
foreach ($networkID in $networkIDs) {
# Define the API endpoint
$uri = "https://api.meraki.com/api/v1/networks/$networkID/wireless/ssids/0"
# Define the body
$body = @{
"name" = $newSSIDName
} | ConvertTo-Json
# Make the PUT request
$response = Invoke-RestMethod -Uri $uri -Method Put -Body $body -Headers $headers
# Print the response
Write-Output "Response for network $networkID:"
Write-Output $response
}
Opps forgot the = ... did that and it works but you get the error from PS
The remote server returned an error: (400) Bad Request.
I think the problem is that as a hashtable it is not in JSON format.
Here is what is stored for the variable but that is not the right format.
PS > $SSIDConfig
{"enabled":"True","ipAssignmentMode":"NAT Mode","encryptionMode":"wpa","wpaEncryptionMode":"WPA3 Transition Mode","name":"Test","authMode":"psk","psk":"TestTest1","lanIsolationEnabled":"False","bandSelection":"Dual band operation"}
Should look something like this:
{"Attributes":[],"File":null,"IsFilter":false,"IsConfiguration":false,"Module":null,"StartPosition":{"Content":"{name:Test,enabled:True,authMode:psk,psk:TestTest1,encryptionMode:wpa,wpaEncryptionMode:WPA3 Transition Mode,ipAssignmentMode:NAT Mode,bandSelection:Dual band operation,lanIsolationEnabled:False}","Type":19,"Start":14,"Length":205,"StartLine":1,"StartColumn":15,"EndLine":1,"EndColumn":220},"DebuggerHidden":false,"Id":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","Ast":{"Attributes":[],"UsingStatements":[],"ParamBlock":null,"BeginBlock":null,"ProcessBlock":null,"EndBlock":{"Unnamed":true,"BlockKind":130,"Statements":"name:Test,enabled:True,authMthMode:psk,psk:TestTest1,encryptionMode:wpa,wpaEncryptionMode:WPA3 Transition Mode,ipAssignmentMode:NAT Mode,bandSelection:Dual band operation,lanIsolationEnabled:False","Parent":"{name:Test,enabled:True,authMode:psk,psk:TestTest1,encryptionMode:wpa,wpaEncryptionMode:WPA3 Transition Mode,ipAssignmentMode:NAT Mode,bandSelection:Dual band operation,lanIsolationEnabled:False
but what exactly are you trying to update? Details please.
I am trying to use PowerShell to update 170 Meraki Network SSIDs.
Hi DarkStar! Thanks for trying out my module. It's still a bit of a work in progress and the thing I'm lacking the most is solid documentation with functional & tested examples. Keep in mind that depending on the device you may need to use Set-MerakiNetworkApplianceSSID instead.
Try using a PSCustomObject and converting it to compressed JSON. It just worked for me:
$SSIDConfig = [PSCustomObject]@{
name = "Test"
enabled = $true
authMode = "psk"
psk = "TestTest1"
encryptionMode = "wpa"
wpaEncryptionMode = "WPA3 Transition Mode"
ipAssignmentMode = "NAT Mode"
bandSelection = "Dual band operation"
lanIsolationEnabled = $false
}
$SSIDConfig = $SSIDConfig | ConvertTo-Json -Compress
Set-MerakiNetworkWirelessSSID -AuthToken $authtoken -NetworkId $NetID -Number 3 -SSIDConfig $SSIDConfig
I assumed the Set-MerakiNetworkApplianceSSID was for the Firewalls that have the WiFi built in?
I think you're correct about this one. I'm not the network guy in my org and i only have a z3 to test against
Tried the above code and I get:
The remote server returned an error: (400) Bad Request.
Here is the whole thing in case you see something wrong (Errors in RED):
PS > $SSIDConfig = [PSCustomObject]@{
>> name = "Test"
>> enabled = "True"
>> authMode = "psk"
>> psk = "TestTest1"
>> encryptionMode = "wpa"
>> wpaEncryptionMode = "WPA3 Transition Mode"
>> ipAssignmentMode = "NAT Mode"
>> bandSelection = "Dual band operation"
>> lanIsolationEnabled = "False"
>> }
PS > $SSIDConfig = $SSIDConfig | ConvertTo-Json -Compress
PS > Set-MerakiNetworkWirelessSSID -AuthToken "7xxxxxxxxxxxxxxxxxxx" -NetworkId "L_xxxxxxxxxxxxxxxxxxxxxx" -Number 2 -SSIDConfig $SSIDConfig
The remote server returned an error: (400) Bad Request.
PS > $SSIDConfig
{"name":"Test","enabled":"True","authMode":"psk","psk":"TestTest1","encryptionMode":"wpa","wpaEncryptionMode":"WPA3 Transition Mode","ipAssignmentMode":"NAT Mode","bandSelection":"Dual band operation","lanIsolationEnabled":"False"}
PS > Set-MerakiNetworkApplianceSSID -AuthToken "7xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -NetworkId "L_^xxxxxxxxxxxxxxxxxxx" -Number 2 -SSIDConfig $SSIDConfig
Set-MerakiNetworkApplianceSSID : A parameter cannot be found that matches parameter name 'Number'.
At line:1 char:120
+ ... xxxxxx" -NetworkId "L_6xxxxxxxxx" -Number 2 -SSID ...
+ ~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-MerakiNetworkApplianceSSID], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Set-MerakiNetworkApplianceSSID
Try this one:
$SSIDConfig = [PSCustomObject]@{
name = "Test"
enabled = $true
authMode = "psk"
psk = "TestTest1"
encryptionMode = "wpa"
wpaEncryptionMode = "WPA3 Transition Mode"
ipAssignmentMode = "NAT Mode"
bandSelection = "Dual band operation"
lanIsolationEnabled = $false
}
The values for enabled and lanIsolationEnabled should be boolean ($true or $false).
The Set-MerakiNetworkApplianceSSID cmdlet does not recognize the -Number parameter. It’s possible that this cmdlet does not require or accept a -Number parameter, or the parameter might be named differently.
Darn, same error message using the boolean.
The remote server returned an error: (400) Bad Request.
sorry, I think this was a mistake on my end that I'll have to correct in a future version. For whatever reason, I used SSIDNumber for the parameter on the Set-MerakiNetworkApplianceSSID command and just number on the other one.
Set-MerakiNetworkApplianceSSID -AuthToken "7xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -NetworkId "L_^xxxxxxxxxxxxxxxxxxx" -SSIDNumber 2 -SSIDConfig $SSIDConfig
also in the SSIDConfig, try replacing "true" & "false" with $true and $false and then let the convertto-json do the work. I should really start copy and pasting more carefully haha
Edit: I just updated my earlier reply with that correction
IMHO
Set-MerakiNetworkApplianceSSID would not need a number there is only one SSID. MX65W is an example of a firewall with built in WiFi
Set-MerakiNetworkWirelessSSID should have numbers because there are many.
We have 170 networks so I have many many different firewalls and many different WAPs on the network. I will be more happy to help you debug this module. Thanks
Did changing the true/false syntax fix the issue for you?
I've only been able to test Set-MerakiNetworkApplianceSSID with my Z3, but it's capable of broadcasting multiple SSIDs, so the number is required for that command. I would love the help in testing this module though. please kick the tires and let me know what's not working. Might be easier to track if you submit issues to the github repo instead of this forum:
https://github.com/DocNougat/Meraki-Powershell-Module
@DocNougat I don't have a GitHub account, but I could set one up. However I have an idea. I am willing to send you FREE a firewall and 2 WAPs that you can keep and use however you like if that will help with the development of this module. I see a huge value for us. We manage a lot of networks and PowerShell commands would make our lives a lot easier. Thoughts ??
This command prompts for the number ....
Set-MerakiNetworkApplianceSSID -AuthToken "7xxxxxxxxxxxxxx" -NetworkId "L_6xxxxxxxxxxxxxxxxxxx" -SSIDConfig $SSIDConfig
cmdlet Set-MerakiNetworkApplianceSSID at command pipeline position 1
Supply values for the following parameters:
SSIDNumber:
I entered 0, 1, 2, 3 and 4 it then returns error message below:
Set-MerakiNetworkApplianceSSID : The remote server returned an error: (400) Bad Request.
At line:1 char:1
+ Set-MerakiNetworkApplianceSSID -AuthToken "7xxxxxxxxxxxxx ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Set-MerakiNetworkApplianceSSID
same issue if you include it in the command instead of entering it when prompted?
also, do did you try same thing with Set-MerakiNetworkWirelessSSID?
Two different messages:
Entering the number at the prompt:
Set-MerakiNetworkApplianceSSID : The remote server returned an error: (400) Bad Request.
At line:1 char:1
+ Set-MerakiNetworkApplianceSSID -AuthToken "7xxxxxxxxxxxxxxxxxx ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Set-MerakiNetworkApplianceSSID
With the value in the commend string:
Set-MerakiNetworkApplianceSSID : A parameter cannot be found that matches parameter name 'Number'.
At line:1 char:120
+ ... xxxxxxxxxxxxxx" -NetworkId "L_xxxxxxxxxxxxx2" -Number 0 -SSID ...
+ ~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-MerakiNetworkApplianceSSID], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Set-MerakiNetworkApplianceSSID
If you're using Set-MerakiNetworkApplianceSSID you'll need to use -SSIDNumber
Set-MerakiNetworkApplianceSSID -AuthToken "7xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -NetworkId "L_^xxxxxxxxxxxxxxxxxxx" -SSIDNumber 2 -SSIDConfig $SSIDConfig
If you're using Set-MerakiNetworkWirelessSSID you'll need to use -number
Set-MerakiNetworkWirelessSSID -AuthToken "7xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -NetworkId "L_^xxxxxxxxxxxxxxxxxxx" -Number 2 -SSIDConfig $SSIDConfig
I'm going to publish an update to correct this soon (probably today or tomorrow)
Set-MerakiNetworkWirelessSSID
Gives the same error if prompted or in the comannd.
The remote server returned an error: (400) Bad Request.
What device are you testing this against?
We are using an MX65 Firewall with an MR57 WAP in the test enjoinment.
Actually I think I figured it out.
The Set-MerakiNetworkApplianceSSID endpoint doesn't support the following paremeters:
ipAssignmentMode
bandSelection
lanIsolationEnabled
https://developer.cisco.com/meraki/api-v1/update-network-appliance-ssid/
The Set-MerakiNetworkWirelessSSID works if I remove the following parameters.
ipAssignmentMode
bandSelection
lanIsolationEnabled
It supports them but removing them created the SSID on our network. So we are a lot closer.
Looks like LanIsolationEnabled is not in the Set-MerakiNetworkApplianceSSID creation list, and I have to have that command because these SSIDs cannot have access to the local LAN.
here is the return completed without error message:
number : 8
name : Test
enabled : True
splashPage : None
ssidAdminAccessible : False
authMode : psk
psk : TestTest1
dot11w : @{enabled=False; required=False}
dot11r : @{enabled=False; adaptive=False}
encryptionMode : wpa
wpaEncryptionMode : WPA3 Transition Mode
ipAssignmentMode : NAT mode
adultContentFilteringEnabled : False
dnsRewrite : @{enabled=False; dnsCustomNameservers=System.Object[]}
minBitrate : 11
bandSelection : Dual band operation
perClientBandwidthLimitUp : 0
perClientBandwidthLimitDown : 0
perSsidBandwidthLimitUp : 0
perSsidBandwidthLimitDown : 0
mandatoryDhcpEnabled : False
visible : True
availableOnAllAps : True
availabilityTags : {}
speedBurst : @{enabled=False}
I just published version 1.0.3 of the module. It corrects the examples in the help for each command to use the hashtable properly and also makes any command that requires a specified SSID take the parameter SSIDNumber instead of just number.
Also, if you're developing in visual studio code, try out my powershell module commander extension:
https://marketplace.visualstudio.com/items?itemName=DocNougat.powershell-commander
I tested this on and worked for me.
# Define the API endpoint
$uri = "https://api.meraki.com/api/v1/networks/NETWORK_ID/wireless/ssids/SSID_NUMBER"
# Define the headers
$headers = @{
"X-Cisco-Meraki-API-Key" = "API_KEY"
"Content-Type" = "application/json"
}
# Define the body
$body = @{
name = "My SSID"
enabled = $true
authMode = "psk"
encryptionMode = "wpa"
psk = "PASSWORD"
wpaEncryptionMode = "WPA2 only"
dot11w = @{
enabled = $true
required = $false
}
} | ConvertTo-Json
try {
# Try sending the POST request
# Try sending the PUT request
$response = Invoke-RestMethod -Uri $uri -Method Put -Body $body -Headers $headers
# Output the response
$response
}
catch {
# Catch any exceptions and output details
Write-Host "Error: $_"
if ($_.Exception -ne $null) {
Write-Host "Exception Type: $($_.Exception.GetType().FullName)"
Write-Host "Exception Message: $($_.Exception.Message)"
if ($_.Exception.Response -ne $null) {
$responseStream = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($responseStream)
$responseText = $reader.ReadToEnd()
Write-Host "Response from server: $responseText"
}
}
}
I think I actually found the issue you're having. I dug a bit deeper into the API docs and it looks like the lanIsolationEnabled setting is only available if you set your ipAssignmentMode to "Bridge mode"(this is also case sensitive because 🤷🏻♂️). Here is an example I was able to run successfully with Set-MerakiNetworkWirelessSsid: