Giter Site home page Giter Site logo

meraki / dashboard-api-python Goto Github PK

View Code? Open in Web Editor NEW
285.0 67.0 148.0 1.97 MB

Official Dashboard API library (SDK) for Python

License: MIT License

Python 95.44% Jupyter Notebook 4.31% Jinja 0.25%
automation dashboard-api meraki meraki-api python

dashboard-api-python's Introduction

Meraki Dashboard API Python Library

The Meraki Dashboard API Python library provides all current Meraki dashboard API calls to interface with the Cisco Meraki cloud-managed platform. Meraki generates the library based on dashboard API's OpenAPI spec to keep it up to date with the latest API releases, and provides the full source code for the library including the tools used to generate the library, if you are participating in the Early Access program or would like to contribute to the development of the library. Meraki welcomes constructive pull requests that maintain backwards compatibility with prior versions. The library requires Python 3.10+, receives support from the community, and you can install it via PyPI:

pip install --upgrade meraki

If you participate in our Early Access program and would like to use early access features via the library, you'll find instructions in the generator readme.

Features

While you can make direct HTTP requests to dashboard API in any programming language or REST API client, using a client library can make it easier for you to focus on your specific use case, without the overhead of having to write functions to handle the dashboard API calls. The Python library can also take care of error handling, logging, retries, and other convenient processes and options for you automatically.

  • Support for all API endpoints, as it uses the OpenAPI specification to generate source code
  • Log all API requests made to a local file as well as on-screen console
  • Automatic retries upon 429 rate limit errors, using the Retry-After field within response headers
  • Get all (or a specified number of) pages of data with built-in pagination control
  • Tweak settings such as maximum retries, certificate path, suppress logging, and other options
  • Simulate POST/PUT/DELETE calls to preview first, so that network configuration does not get changed

Setup

  1. Enable API access in your Meraki dashboard organization and obtain an API key (instructions)

  2. Keep your API key safe and secure, as it is similar to a password for your dashboard. If publishing your Python code to a wider audience, please research secure handling of API keys.

  3. Install the latest version of Python 3

  4. Use pip (or an alternative such as easy_install) to install the library from the Python Package Index:

    • pip install meraki
    • If you have both Python3 and Python2 installed, you may need to use pip3 (so pip3 install meraki) along with python3 on your system
    • If meraki was previously installed, you can upgrade to the latest non-beta release with pip install --upgrade meraki
  5. The library supports Meraki dashboard API v1. You can also specify the version of the library when installing with pip:

    • See the full release history to pick the version you want, or use pip install meraki== without including a version number to display the list of available versions
    • Versions begin with 1 (1.0.0bz for beta)
    • Specify the version you want with the install command; for example: pip install meraki==1.34.0
    • You can also see the version currently installed with pip show meraki
    • End-of-life v0 versions of the Python library begin with 0 (0.x.y) and are not supported nor recommended.

Usage

  1. Export your API key as an environment variable, for example:

    export MERAKI_DASHBOARD_API_KEY=YOUR_KEY_HERE
  2. Alternatively, define your API key as a variable in your source code; this method is not recommended due to its inherent insecurity.

  3. Single line of code to import and use the library goes at the top of your script:

    import meraki
  4. Instantiate the client (API consumer class), optionally specifying any of the parameters available to set:

    dashboard = meraki.DashboardAPI()
  5. Make dashboard API calls in your source code, using the format client.scope.operation, where client is the name you defined in the previous step (dashboard above), scope is the corresponding scope that represents the first tag from the OpenAPI spec, and operation is the operation of the API endpoint. For example, to make a call to get the list of organizations accessible by the API key defined in step 1, use this function call:

    my_orgs = dashboard.organizations.getOrganizations()

Examples

You can find fully working example scripts in the examples folder.

Script Purpose
org_wide_clients.py That code collects the clients of all networks, in all orgs to which the key has access. No changes are made, since only GET endpoints are called, and the data is written to local CSV output files.

AsyncIO

asyncio is a library to write concurrent code using the async/await syntax. Special thanks to Heimo Stieg (@coreGreenberet) who has ported the API to asyncio.

Installation on macOS

If you use a Mac, then you may need to take additional Python installation steps that aren't required on other platforms. This is a limitation of macOS and not the library. This step is not required on Windows.

Usage

The usage is similiar to the sequential version above. However it has has some differences.

  1. Export your API key as an environment variable, for example:

    export MERAKI_DASHBOARD_API_KEY=YOUR_KEY_HERE
  2. Alternatively, define your API key as a variable in your source code; this method is not recommended due to its inherent insecurity.

  3. Single line of code to import and use the library goes at the top of your script:

    import meraki.aio
  4. Instantiate the client (API consumer class), optionally specifying any of the parameters available to set:

    async with meraki.aio.AsyncDashboardAPI() as aiomeraki:

    The async with statement is important here to make sure, that the client sessions will be closed after using the api.

  5. Make dashboard API calls in your source code, using the format await client.section.operation, where client is the name you defined in the previous step (aiomeraki above), section is the corresponding group (or tag from the OpenAPI spec) from the API docs, and operation is the name (or operation ID from OpenAPI) of the API endpoint. For example, to make a call to get the list of organizations accessible by the API key defined in step 1, use this function call:

    my_orgs = await aiomeraki.organizations.getOrganizations()
  6. Run everything inside an event loop.

import asyncio

if __name__ == "__main__":
    # replace my_async_entry_point with the name of your entry point method
    asyncio.run(my_async_entry_point())

Examples

You can find fully working example scripts in the examples folder.

Script Purpose
aio_org_wide_clients.py That code is a asyncio port from org_wide_clients.py and collects the clients of all
networks, in all orgs to which the key has access. No changes are made, since only GET endpoints are called, and the
data is written to local CSV output files.
aio_ips2firewall.py That code will collect the source IP of security events and creates L7 firewall rules to
block them. usage: aio_ips2firewall.py [-h] -o ORGANIZATIONS [ORGANIZATIONS ...] [-f FILTER] [-s] [-d DAYS]

Note for application developers and ecosystem partners

We're so glad that you're leveraging our Python library. It's best practice to identify your application with every API request that you make. You can easily do this automatically just by following the format defined in config.py and passing the session kwarg:

MERAKI_PYTHON_SDK_CALLER

Unless you are an ecosystem partner, this identifier is optional.

  1. If you are an ecosystem partner and you have questions about this requirement, please reach out to your ecosystem rep.
  2. If you have any questions about the formatting, please ask your question by opening an issue in this repo.

dashboard-api-python's People

Contributors

andy-shady-org avatar camodunn avatar coregreenberet avatar danmanners avatar dependabot[bot] avatar dylanmtaylor avatar ez1mm avatar faho avatar gamemaster47 avatar grutz avatar jleatham avatar kennethwilke avatar longbeachhxc avatar nathanwiens avatar nerdguru avatar nofliesonyou avatar pocc avatar shiyuechengineer avatar sid137 avatar timway avatar tkipisalegacycipher avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dashboard-api-python's Issues

AP status?

Hello,

Is there an access point status query in the module anywhere? i.e a query that shows, up, repeater, down? I can't seem to find if it does exist? or could this be a feature request?

Thanks
Alex.

Else statement at the end of __returnhandler ignores suppressprint argument

I'd like to request that the catch-all else statement at the end of the returnhandler object respect the suppressprint argument.

I'm pulling the org name to test whether the org ID and API key are valid. The API key being invalid works, but if the org ID is invalid, then the results are returned to STDOUT.

Thanks for putting this library together!

Bug since 0.90

Hello,

I tried your new release which should have fixed #68, but I think the SDK is broken now... ;)

The thing is, I receive the correct logs from your application, such as :

09/03/2020 16:03:12 [ERROR] rest_session::request::160 - Networks, createOrganizationNetwork - 400 Bad Request, {'errors': ['Name has already been taken']}

The problem is the fact that the data returned by the calls is always None None, None (printed in str format as Networks, createOrganizationNetwork - None None, None)
For example, for the same call above I get this dict of values on the error:

09/03/2020 16:03:12 [WARNING] decorators::wrapper::74 - {'response': <Response [400]>, 'tag': 'Networks', 'operation': 'createOrganizationNetwork', 'status': None, 'reason': None, 'message': None}

Updating a client name

Hi,

The function for provisioning clients is missing one of the values, using the API you are able to update the name of the client as well as policy and policyID. This is the api-call;

POST/networks/[networkId]/clients/provision

And this is the function I'm referencing;
updateclientpolicy(apikey, networkid, clientmac, policy, policyid=None, suppressprint=False)

Is is it possible to add the name as an object here so this function could be used to rename clients in the dashboard?

Installation via PIP

I had some issues installing via pip as it didn't pull dependencies, and could not import properly after installation.

(tmp) โžœ  /tmp pip install meraki
Collecting meraki
Installing collected packages: meraki
Successfully installed meraki-0.34
(tmp) โžœ  /tmp python
Python 2.7.10 (default, Feb 22 2018, 22:42:27) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from meraki import meraki
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named meraki
>>> 

I added a setup.py and restructured slightly for what I think would be the required updates, feel free to PR if you like

master...kecorbin:master

anyone having problems with switch autobind?

The bind to template function works fine, but the autobind=true doesnt seem to work. When the devices get added to the network i still have to manually go bind the switch to the profile. Just curious if anyone else has any experience with this.

Feature Request: Return MX HA state to 'getnetworkdetail'

I am able to pull MX devices for each given network but none of the network API calls return the MX appliance HA status ('Current Master', 'Passive;ready', etc.)

Are there any plans of adding this or any other ways to pull this information via the API? It would be very useful information.

Networks where the MX does not have a warm spare, the status could simply be Null or "Standalone"

dashboard-api-python issue

Hi
I am try copy your code to run , I copied and pasted to Pycharm , when I run it , I have get my organization code and get error message as below:

Analyzing organization other license.com:

  • iterating through 1 networks in organization 66934XXXXXXXXXXXXXX
    Finding clients in network API-Lab (1 of 1)
    Traceback (most recent call last):
    File "/Users/kitoorunoboru/PycharmProjects/dashboard-api-python-master/test.py", line 96, in
    main()
    File "/Users/kitoorunoboru/PycharmProjects/dashboard-api-python-master/test.py", line 77, in main
    field_names = list(field_names)
    UnboundLocalError: local variable 'field_names' referenced before assignment

can you help me ? thanks !

string indices must be integers

Hey guys,

This error is completely random.
I use the API to backup some parts of my organizations in meraki cloud.
Sometimes i get this error with backingup my switchports.
The problem is that it realy is not consistent when it happens.
Long story short, I build another PY file ready to restore the organization
Does anyone have an idea on this ?

Error:
***Backing up switchports
Traceback (most recent call last):
File "back-all-org.py", line 363, in
write_switchports(apikey,row['id'], suppressprint)
File "back-all-org.py", line 222, in write_switchports
if port['name'] is not "":
TypeError: string indices must be integers

Code:

def write_switchports(file, apikey, networkid, suppressprint):
switches = []

devices=meraki.getnetworkdevices(apikey, networkid, suppressprint)
file.write("\t# switchports\n")

for device in devices:
	if "MS" in str(device['model']):
		switches.append(device)

for switch in switches:
	file.write("\t# switch " + str(switch['name']) + "\n")
	file.write("\tprint(\"Restoring switchports\")")
	file.write("\t# https://dashboard.meraki.com/api_docs#switch-ports\n")
	portname = "None"
	porttags = "None"
	switchports = meraki.getswitchports(apikey, switch['serial'], suppressprint)
	for port in switchports:
		if port['name'] is not "":
			portname = "\""+str(port['name'])+"\""
		else: 
			portname = "None"

		if port['tags'] is not None:
			porttags = "\""+ port['tags']+"\""
		else:
			porttags= "None"

		file.write("\tmeraki.updateswitchport(apikey, \""+ str(switch['serial']) +"\", "+str(port['number'])+", "+ portname +", "+porttags+", "+str(port['enabled'])+", \""+str(port['type'])+"\", "+str(port['vlan'])+", "+str(port['voiceVlan'])+", \""+str(port['allowedVlans'])+"\", "+str(port['poeEnabled'])+", "+str(port['isolationEnabled'])+", "+str(port['rstpEnabled'])+', \"'+str(port['stpGuard'])+"\", "+str(port['accessPolicyNumber'])+", "+"suppressprint)\n")

	file.write("\n")

Alerts/HTTP Servers API calls

I'm doing some work with scripting setting up alerts using webhooks. Having the alerts and HTTP server calls being exposed as part of this library would be helpful in that regard. #

Mysterious error

Hello,

Following the debugging of the SDK from issues #68 & #72, I still get my mysterious error happening at random on any type of call made to Meraki, quite frequently.

Now, with your fix I get this sort of error: Organizations, getOrganizations - None None, None.
Do you know the origin of this error (timeout from Meraki, network problem, ...)?
Would you be able to send back a true error for it? I mean with an error message/code/etc., because None does not tell us what is the origin or why it happened in the first place.
I myself do not know where it comes from.

To resolve it without interrupting the user, I usually do a sleep(0.5) and then retry the call.
For each of our discussions in previous issues, I usually deploy a new network with devices etc. to test the error. It does not happen every time, but I usually only need a few calls (1-5) to get it again.

Updating device details requires move_map_marker value to be set

When trying to update device's details shown on dashboard, the update fails. After debugging, it seems that the Query builder is sending an API call to Meraki's dashboard with a "move_map_marker" value of None, while the only acceptable values are either True, or False.

Example code

from meraki_sdk.meraki_sdk_client import MerakiSdkClient
from meraki_sdk.models.update_network_device_model import UpdateNetworkDeviceModel
from meraki_sdk.exceptions.api_exception import APIException

x_cisco_meraki_api_key = my_api_key

client = MerakiSdkClient(x_cisco_meraki_api_key)

devices_controller = client.devices
collect = {}
network_id = my_network_id
collect['network_id'] = network_id

serial = myDeviceSerial
collect['serial'] = serial

update_network_device = UpdateNetworkDeviceModel()
update_network_device.name = 'Testing'
update_network_device.tags = ' recently-added '
update_network_device.lat = 37.4180951010362
update_network_device.lng = -122.098531723022
collect['update_network_device'] = update_network_device

try:
    print (collect)
    devices_controller.update_network_device(collect)
except APIException as e:
    print(e)

Missing REST endpoints

Hello,

we have a problem with Cisco Meraki REST API (https://developer.cisco.com/meraki/api/#/rest/)

It seems that there doesn't exist REST endpoints for getting such basic information like ARP, MAC, routing tables etc. We can see that information in the Meraki app where those data received through the CometD web messaging service.

Is there any way how we can get those data in some kind of public API?

HTTP Servers not found

---------------------------------------------------------------------------
APIError                                  Traceback (most recent call last)
<ipython-input-2-f903ab53508d> in <module>
----> 1 meraki.dashboard.http_servers.getNetworkHttpServers('<network-id>')

/usr/local/lib/python3.6/dist-packages/meraki/api/http_servers.py in getNetworkHttpServers(self, networkId)
     18         resource = f'/networks/{networkId}/httpServers'
     19 
---> 20         return self._session.get(metadata, resource)
     21 
     22     def createNetworkHttpServer(self, networkId: str, name: str, url: str, **kwargs):

/usr/local/lib/python3.6/dist-packages/meraki/rest_session.py in get(self, metadata, url, params)
    190         metadata['url'] = url
    191         metadata['params'] = params
--> 192         response = self.request(metadata, 'GET', url, params=params)
    193         return response.json() if response and response.text.strip() else None
    194 

/usr/local/lib/python3.6/dist-packages/meraki/rest_session.py in request(self, metadata, method, url, **kwargs)
    184                     else:
    185                         self._logger.error(f'{tag}, {operation} - {status} {reason}, {message}')
--> 186                         raise APIError(metadata, response)
    187 
    188     def get(self, metadata, url, params=None):

APIError: HTTP servers, getNetworkHttpServers - 404 Not Found,  

JSON Decode Error

@shiyuechengineer, running into a minor issue that I think we fixed in the legacy meraki.py library. Or maybe I re-wrote it for a project, I can't remember.

Basically if someone mistypes an API key you get a series of errors but the most relevant is from the requests library. Because the dashboard still returns a web page you get a 200 HTTP response but invalid JSON from requests response.json() (basically the dashboard response is HTML but the requests library expects json)

File "/site-packages/meraki/rest_session.py", line 126, in request response.json()
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)

Can we trap for this error? I trap for it often to give a custom user message. I see it when people are using my tools based on your library but either use the wrong API key or mistype it.

If you can think of a work around without monkey patching (which I don't want to do), please let me know. It's easy to re-create, just use any invalid API key.

incompatible error when install meraki package

C:\Users\martlee2\Documents>pip install --upgrade requests
Requirement already up-to-date: requests in c:\python27\lib\site-packages (2.18.4)
Requirement not upgraded as not directly required: chardet<3.1.0,>=3.0.2 in c:\python27\lib\site-packages (from requests) (3.0.4)
Requirement not upgraded as not directly required: certifi>=2017.4.17 in c:\python27\lib\site-packages (from requests) (2018.4.16)
Requirement not upgraded as not directly required: urllib3<1.23,>=1.21.1 in c:\python27\lib\site-packages (from requests) (1.22)
Requirement not upgraded as not directly required: idna<2.7,>=2.5 in c:\python27\lib\site-packages (from requests) (2.6)
dhclientlist 0.0.6 has requirement requests==1.2.3, but you'll have requests 2.18.4 which is incompatible.
pyem7 0.0.dev1 has requirement requests==2.7.0, but you'll have requests 2.18.4 which is incompatible.

C:\Users\martlee2\Documents>pip install meraki
Requirement already satisfied: meraki in c:\python27\lib\site-packages (0.30)
dhclientlist 0.0.6 has requirement requests==1.2.3, but you'll have requests 2.18.4 which is incompatible.
pyem7 0.0.dev1 has requirement requests==2.7.0, but you'll have requests 2.18.4 which is incompatible.

and how to download csv with the api
for
manage/usage/list

Enhanced User-Agent

Per the email exchange we had internally, the idea here is to enhance the information placed in the User-Agent HTTP Request header to be more like what pip does as can be seen here:

https://github.com/pypa/pip/blob/master/src/pip/_internal/network/session.py

In addition to the SDK version string, pip appends a URL encoded JSON string that includes things like OS version of the caller and Python version. It would be nice to also have a field in that string that partners could set that would identify API calls made by them. I just forked the repo and am working on a patch for this exact scenario.

Logs are printing and log files generated without setting logging

This looks to be newer behavior at the moment. But logs are now being printed to the output, and also a file is being created in the project directory without having logs setup. I see creating files and printing output to the screen as something that the application developer should choose to do, not the SDK.

sdk unhandled exception on request timeout

The following unhandled exception is raised when a request timeout occurs (and all retires are done):

UnboundLocalError: local variable 'response' referenced before assignment

This happens on this line on rest_session.py file

448 PEP8 errors

Problem

Pasting the main program file into http://pep8online.com, we get 447 PEP8 errors and 1 PEP8 warning.

Details

Count PEP8 Code Error Text
1 E127 continuation line over-indented for visual indent
1 E225 missing whitespace around operator
1 E265 block comment should start with '# '
21 E266 too many leading '#' for block comment
1 E302 expected 2 blank lines, found 3
3 E303 too many blank lines (3)
377 E501 line too long ( > 79 characters)
41 E711 comparison to None should be 'if cond is None:'
1 E713 test for membership should be 'not in'
1 W292 no newline at end of file

Solution

I am working on a pull request to resolve this issue. I am using PyCharm's built-in PEP8 inspections.

how to get the columns like these?

myNetworks = meraki.getnetworklist(apikey, orgid)
result = ""
for networkdevicelist in myNetworks:
    networkid = networkdevicelist["id"]
    deviceList = meraki.getnetworkdevices(apikey, networkid)
    for devices in deviceList:
        serialnum = devices["serial"]
        clientList = meraki.getclients(apikey,serialnum)
        for clients in clientList:
            d = clients.copy()
            d.update(devices)
            d.update(networkdevicelist)
            result = result + str(d) + ","

i can get

w.writerow([row['usage'], row['id'], row['description'], row['mdnsName'], row['dhcpHostname'], row['mac'], row['ip'], row['vlan'], row['switchport'], row['lanIp'], row['serial'], row['lat'], row['lng'], row['address'], row['name'], row['model'], row['networkId'], row['organizationId'], row['timeZone'], row['tags'], row['type']])
how to get columns below?
there are first seen and last seen date time

image

aio exception problem

Hello,

I think there is a problem with the exception AsyncAPIError(Exception):

When an exception occur, the exception try to call self.response.json()
Or it should be awaited.

The exception :

PS C:\Users\ttr\Documents\dev\meraki-winmonitor> python.exe .\win-meraki-provide.py -c .\config.ini -m Y C:\Users\ttr\AppData\Local\Programs\Python\Python38-32\lib\site-packages\meraki\exceptions.py:37: RuntimeWarning: coroutine 'ClientResponse.json' was never awaited self.message = self.response.json() if self.response.json() else None RuntimeWarning: Enable tracemalloc to get the object allocation traceback Test 1 : ****** .\win-meraki-provide.py:311: RuntimeWarning: coroutine 'ClientResponse.json' was never awaited print('Test 1 : {}'.format(org['name'])) RuntimeWarning: Enable tracemalloc to get the object allocation traceback

The code used :

` try:

    results = await aiomeraki.organizations.getOrganizationInventory(org["id"],includeLicenseInfo ='True')

except:

    print('Test 1 : {}'.format(org['name']))`

It happen if the organisation is not licensed by device.

Thanks

Bug in Dashboard API code - __init__() missing 1 required positional argument: 'response'

Hello,

I often encounter this bug:

File "./app/lib/meraki_api.py", line 95, in _get_organization
dev_1         |     organizations = self.organizations.getOrganizations()
dev_1         |   File "/usr/local/lib/python3.7/site-packages/meraki/api/organizations.py", line 19, in getOrganizations
dev_1         |     return self._session.get(metadata, resource)
dev_1         |   File "/usr/local/lib/python3.7/site-packages/meraki/rest_session.py", line 142, in get
dev_1         |     response = self.request(metadata, 'GET', url, params=params)
dev_1         |   File "/usr/local/lib/python3.7/site-packages/meraki/rest_session.py", line 81, in request
dev_1         |     raise APIError(metadata)
dev_1         | TypeError: __init__() missing 1 required positional argument: 'response'

Which results from when I get this error (quite often too):

Organizations, getOrganizations - HTTPSConnectionPool(host='api.meraki.com', port=443): Max retries exceeded with url: /api/v0/organizations (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7f37bd3e4390>: Failed to establish a new connection: [Errno -2] Name or service not known')), retrying in 1 second

moveMapMarker Not Working When Updating A Device

When I call the updateNetworkDevice function from devices and an address is specified and moveMapMarker is set to True, the map marker does not move in the dashboard. I can also specify the lat and lng when calling the same function, excluding the moveMapMarker parameter, and the map marker will still not move in the dashboard. If I login to the dashboard and open the address properties of the device and click save without modifying the address, it will move it to where it's supposed to be.

`__hasorgaccess` problematic when organization employs whitelisting

Many of the functions utilise the __hasorgaccess function in order to test access prior to proceeding.

This sounds fine, however currently it appears that the /api/v0/organizations call will fail if one of the organizations which an API key's owner has access to is employing "IP address whitelisting" (Organization -> Settings -> Security -> Login IP Ranges), and the requestor's IP address is not included in the configured ranges.

E.g.

  • User has 2 organizations which they are a member of
    • OrgA
    • OrgB
  • OrgA has "whitelisting" configured, allowing only 1.2.3.4
  • OrgB does not have "whitelisting" configured
  • User attempts to call /api/v0/organizations from 5.6.7.8 to find out which orgs they have access to - response:

403 - You are trying to access Dashboard from an unauthorized IP address (5.6.7.8). Contact your network administrator for more information.

Because of this error, __hasorgaccess will fail, whether the org involved is using "whitelisting" or not, and then the original call will also fail.

E.g.

----> 1 meraki.getnetworklist(api,org)

~/meraki/meraki.py in getnetworklist(apikey, orgid, templateid, suppressprint)
   1775     # Confirm API Key has Admin Access Otherwise Raise Error
   1776     #
-> 1777     __hasorgaccess(apikey, orgid)
   1778     calltype = 'Network'
   1779

~/meraki/meraki.py in __hasorgaccess(apikey, targetorg)
    806     if validjson is True:
    807         for org in currentorgs:
--> 808             if int(org['id']) == int(targetorg):
    809                 orgs.append(org['id'])
    810                 return None

TypeError: string indices must be integers

I believe the API endpoint /api/v0/organizations is not behaving as expected.
I would expect that it should either:

  • provide a list of organizations which the API key is allowed to access from the current IP (excluding OrgA in the above case), or
  • provide a list of organizations which the API key's owner is an administrator of (regardless of IP restrictions), and return an error when attempting to access an organization (using any call which would provide information about, or modify the target organization) which has excluded the requestor's IP address.

Regardless, it's current behaviour is breaking this module is operating if any org that the user is a member of is employing "whitelisting".

If this is the correct behaviour of /api/v0/organizations, perhaps this module can be modified to use another call to test access to an org.

I'm going to "make a wish" containing the following content, in order to try and get /api/v0/organizations fixed:

# Fix `/api/v0/organizations` API endpoint

It appears that the `/api/v0/organizations` call will fail if one of the organizations which an API key's owner has access to is employing "IP address whitelisting" (Organization -> Settings -> Security -> Login IP Ranges), and the requestor's IP address is not included in the configured ranges.

E.g. 
* User has 2 organizations which they are a member of
  * OrgA
  * OrgB
* OrgA has "whitelisting" configured, allowing only `1.2.3.4`
* OrgB does not have "whitelisting" configured
* User attempts to call `/api/v0/organizations` from `5.6.7.8` to find out which orgs they have access to - response:
> 403 - You are trying to access Dashboard from an unauthorized IP address (5.6.7.8). Contact your network administrator for more information.

I believe the API endpoint `/api/v0/organizations` is not behaving as expected.
I would expect that it should either:
* provide a list of organizations which the API key is allowed to access from the current IP (excluding OrgA in the above case), or
* provide a list of organizations which the API key's owner is an administrator of (regardless of IP restrictions), and return an error when attempting to access an organization (using any call which would provide information about, or modify the target organization) which has excluded the requestor's IP address.

This also affects the meraki.py python module's operation, due to the way it relies on `/api/v0/organizations` - more information here: https://github.com/meraki/dashboard-api-python/issues/28

Please modify `/api/v0/organizations` so that it operates more in line with user expectation (as one of the above expectations, if possible).

Thank you!
๐Ÿ™‚

APIError PicklingError

Hi,
Im running meraki==0.100.1.

Im using it together with Celery Tasks.

I tested to see how it behaves without any connection to Meraki Cloud and it seems like the errors meraki python library is producing are not pickable.

Task handler raised error: <MaybeEncodingError: Error sending result: '"(1, <ExceptionInfo: APIError('Organizations, getOrganization - None None, None')>, None)"'. Reason: ''PicklingError("Can't pickle <class 'meraki.exceptions.APIError'>: it's not the same object as meraki.exceptions.APIError")''.>

billiard.pool.MaybeEncodingError: Error sending result: '"(1, <ExceptionInfo: APIError('Organizations, getOrganization - None None, None')>, None)"'. Reason: ''PicklingError("Can't pickle <class 'meraki.exceptions.APIError'>: it's not the same object as meraki.exceptions.APIError")''.

Those two are the error messages i see.

apiData2CSV_vX.py can't handle Windows data in the User-Agent extension

While teaching someone else to do the extended User-Agent demo, I discovered that the sample scripts that pull that data and create a CSV out of it can't handle the structure Windows client data because of a missing "distro" element. The code for apiData2CSV_v0.py and apiData2CSV_v1.py needs to be altered with conditionals for missing elements.

getnetworklist 'tags' = None causing JSON output failed to be parsed correctly

Sample of current output as follows.

`meraki.getnetworklist(โ€˜api_keyโ€™,organizationId)

Network Operation Successful - See returned data for results

[{'id': 'L_602356450160805778', 'organizationId': '596171', 'name': 'Heathcote Nth 28923', 'timeZone': 'Australia/NSW', 'tags': None, 'type': 'combined'}]`

This causes error when I try to convert the output from JSON to CSV as it couldn't recognise the word None

Can I request the output to be changed to:

[{'id': 'L_602356450160805778', 'organizationId': '596171', 'name': 'Heathcote Nth 28923', 'timeZone': 'Australia/NSW', 'tags': 'None', 'type': 'combined'}]`

newssid: SSID error

Traceback (most recent call last):
File "myNetworks.py", line 1, in
from meraki import meraki
File "/root/dashboard-api-python/meraki.py", line 3267
def updatessidobject(apikey, networkid, newssid: SSID, suppressprint=False):
^
SyntaxError: invalid syntax

When updating device's details, the query builder is sending a "switchProfileId" value regardless of device type causing the update to fail

It seems that the Query builder is sending a "switchProfileId" value of "None" when this value is omitted by the UpdateNetworkDeviceModel() object used to build the query, and regardless of the device type. This is causing the update to fail as Meraki's dashboard is expecting the API call to either have a valid switchProfileId value or no switchProfileId value

Example code

from meraki_sdk.meraki_sdk_client import MerakiSdkClient
from meraki_sdk.models.update_network_device_model import UpdateNetworkDeviceModel
from meraki_sdk.exceptions.api_exception import APIException

x_cisco_meraki_api_key = my_api_key

client = MerakiSdkClient(x_cisco_meraki_api_key)

devices_controller = client.devices
collect = {}
network_id = my_network_id
collect['network_id'] = network_id

serial = myDeviceSerial
collect['serial'] = serial

update_network_device = UpdateNetworkDeviceModel()
update_network_device.name = 'Testing'
update_network_device.tags = ' recently-added '
update_network_device.lat = 37.4180951010362
update_network_device.lng = -122.098531723022
update_network_device.move_map_marker = False

collect['update_network_device'] = update_network_device

try:
    print (collect)
    devices_controller.update_network_device(collect)
except APIException as e:
    print(e)

tags not entering correctly

When tags are entered for update device I am getting each letter as a separate tag instead of each word as a tag

Functions missing

Please add functions for content filtering and Intrusion prevention

Method returning HTTP Status Code: 404 - No returned data

I've run into a few methods that return HTTP Status Code: 404 - No returned data, even though I can see data in the Dashboard that I would expect to be returned.

For instance,

meraki.getnetworklist(apikey, orgid)
HTTP Status Code: 404 - No returned data

meraki.getorginventory(apikey, orgid)
HTTP Status Code: 404 - No returned data

This orgid definitely has networks with devices in it that I can view from Dashboard. Using different orgid's and the same call may give me data, or may give me the 404.

Any ideas?

updatevlan no DHCP option change

Update a VLAN

https://api.meraki.com/api_docs#update-a-vlan

def updatevlan

does not include the change of he DHCP option like

dhcpHandling - The appliance's handling of DHCP requests on this VLAN. One of: "Run a DHCP server", "Relay DHCP to another server", or "Do not respond to DHCP requests"
dhcpRelayServerIps - The IPs of the DHCP servers that DHCP requests should be relayed to

meraki.getgrouppolicies() groupPolicyId is a string. in meraki.getclientpolicy() its a int

meraki.getgrouppolicies() "groupPolicyId" is a string. In meraki.getclientpolicy() its an int. I believe these should be, and were at some point previously, the same. Workaround is to cast one to the type of the other.

I use getgrouppolicies() to collect the name and ID of the policies and allow the user to select the interesting one, and then later getclientpolicy() to grab the clients with a certain policy, and move them to a different policy.

an example:

meraki_group_policies=meraki.getgrouppolicies(meraki_keys['apikey'],meraki_keys['networkid'], suppressprint=True)
policy_IDs={}
for policy in meraki_group_policies:
#notice the cast to int here as the workaround
policy_IDs[int(policy['groupPolicyId'])]=policy['name']

meraki_clients=meraki.getclients(meraki_keys['apikey'],meraki_keys['device_serial'], suppressprint=True)
for client in meraki_clients:
client_policy=meraki.getclientpolicy(meraki_keys['apikey'], clientmac=client['mac'], networkid=meraki_keys['networkid'], suppressprint=True)
if client_policy:
if 'groupPolicyId' in client_policy.keys():
# the below test fails as they are different types
if client_policy['groupPolicyId'] in policy_IDs and client_policy['groupPolicyId'] in policy_ID_selected :
print("found the selected policy")

Missing API Function - All Org MX Device Uplink Loss

Hi Team,
Firstly, love the API and Python class, thank you for all your hardwork.

I wanted to use the API (link below) via the Meraki Python class however it doesn't appear to be added yet. I suspect the API documentation on Meraki's side talks about timespan arguments yet the example has none.

Any ideas when this will be added? Again really appreciate the work.

https://dashboard.meraki.com/api_docs#return-the-uplink-loss-and-latency-for-every-mx-in-the-organization-from-at-latest-2-minutes-ago

Thanks in advance,
Chris (Melbourne, Australia)

String limit for destCidr

I'm sorry to ask you this here, but only you can help me. What's the "destCidr" limit? How many IP addresses can there be in one rule (or string length limit) ? I'm working on automation right now and I want to have one Black list for each brunch.

Thank you for your job and for API.

SM Wipe Device API Issue

Upfront Context Disclosure: I lack context on how to determine if the API changed or if this "wrapper" has it wrong, so full disclosure there. As far as I understood, all API endpoints were to be backwards compatible, but maybe the API we have access to isn't the same as the version this library targets.

It seems there's a bit of a mismatch around the API for wiping devices and the function enclosed in this wrapper to invoke that endpoint. The specific endpoint is documented here: https://api.meraki.com/api_docs#wipe-a-device

Looking at the url, it targets a specific device. Comparing to the python variant, it tries to invoke a plural variant (devices instead of device - so https://api.meraki.com/api/v0/networks/[network_id]/sm/devices/wipe rather than the documented endpoint of https://api.meraki.com/api/v0/networks/[network_id]/sm/device/wipe) which takes lists of params rather than a single param (eg. 'ids' rather than 'id'). This is a fairly easy change, but again, I cannot tell if it supposed to be plural or not.

Can't set perclientbandwidthlimit

If I do anything for as a none 0 value for 'perClientBandwidthLimitDown' or 'perClientBandwidthLimitUp' i get the error 'Download bandwidth is too small (minimum: 20Kbps)'.

The value that I am sending, 10240, should work, and does work if I manually set it through the dashboard.

dashboard.ssids.updateNetworkSsid(networkid, ssidnum, **ssid)
Bad Request, {'errors': ['Download bandwidth is too small (minimum: 20Kbps)']}]
[[{'adminSplashUrl': None,
'authMode': 'psk',
'bandSelection': 'Dual band operation',
'enabled': True,
'encryptionMode': 'wpa',
'ipAssignmentMode': 'NAT mode',
'minBitrate': 11,
'name': 'My Home Lab',
'number': 0,
'perClientBandwidthLimitDown': 10240,
'perClientBandwidthLimitUp': 10240,
'psk': 'SonderGuest',
'splashPage': 'Click-through splash page',
'splashTimeout': '1440 minutes',
'ssidAdminAccessible': False,
'walledGardenEnabled': False,
'wpaEncryptionMode': 'WPA2 only'},
SSIDs, updateNetworkSsid - 400 Bad Request, {'errors': ['Download bandwidth is too small (minimum: 20Kbps)']},
SSIDs, updateNetworkSsid - 400 Bad Request, {'errors': ['Download bandwidth is too small (minimum: 20Kbps)']}]]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.