How to handle invalid elements in the API

KarstenI
Kind of a big deal
Kind of a big deal

How to handle invalid elements in the API

I am still working on my script to copy an SSID between networks and change an SSID. But now I struggle with the implementation of the API.

 

Problem:

I use getNetworkWirelessSsid to read the SSID and write the SSID with updateNetworkWirelessSsid.

But the API call getNetworkWirelessSsid gives me the following result for my test-SSID:

 

{'authMode': '8021x-radius',
 'availabilityTags': [],
 'availableOnAllAps': True,
 'bandSelection': 'Dual band operation',
 'defaultVlanId': 999,
 'dot11r': {'adaptive': False, 'enabled': False},
 'dot11w': {'enabled': True, 'required': True},
 'enabled': True,
 'encryptionMode': 'wpa-eap',
...
 'wpaEncryptionMode': 'WPA2 only'}

 

 

The Schema Definition for updateNetworkWirelessSsid has some restrictions that make this invalid, and I can't write it back. For example, this SSID uses DOT1X authentication, but I get the element "encryptionMode" returned, which is only valid for PSK SSIDs. There are a couple of more restrictions where elements are dependent on each other.

 

How do I handle this (and I will never understand why this invalid element is returned)?

I can only think of having if-conditions where I match each restriction and remove the element if this element is not allowed on this SSID:

 

if source_ssid["authMode"] == '8021x-radius':
    source_ssid.pop('encryptionMode')

 

But this is an extremely dirty workaround, and I need an individual function for each object I want to copy. 

Or is there a "switch" or "parameter" to tell the system to ignore everything that is not valid? At least I didn't find anything like this.

 

Any idea or advice?

 

 

 

If you found this post helpful, please give it Kudos. If my answer solves your problem, please click Accept as Solution so others can benefit from it.
10 Replies 10
RaphaelL
Kind of a big deal
Kind of a big deal

You are describing the endpoint that I hate the most. 

 

You do a 'GET' of the SSID settings, you get bunch of nonsense , you try to 'PUT' the same exact data, you get bunch of errors 🙂 fun

KarstenI
Kind of a big deal
Kind of a big deal

Well, although this doesn't help, I am happy to see that I am not alone in my frustration ... 🤣

If you found this post helpful, please give it Kudos. If my answer solves your problem, please click Accept as Solution so others can benefit from it.
PhilipDAth
Kind of a big deal
Kind of a big deal

I must be lucky not to have run into this yet using my approach above.  🙂

 

If that happened - you test for the invalids and delete from my kwargs that I build.  Or maybe if I specify kwargs that are not used, they get ignored by updateNetworkWirelessSsid.  I guess they would have to be ignored.

DarrenOC
Kind of a big deal
Kind of a big deal

I applaud the effort and steadfastness @KarstenI but you could have done this manually by now 😉

Darren OConnor | doconnor@resalire.co.uk
https://www.linkedin.com/in/darrenoconnor/

I'm not an employee of Cisco/Meraki. My posts are based on Meraki best practice and what has worked for me in the field.
KarstenI
Kind of a big deal
Kind of a big deal

I think big and not only for the 15 branches where I need it now ... 😉

And I also see it as a preparation for the DEVASC certification that I want to do eventually.

If you found this post helpful, please give it Kudos. If my answer solves your problem, please click Accept as Solution so others can benefit from it.
PhilipDAth
Kind of a big deal
Kind of a big deal

Here is the jist of it, using Python, for MR based networks:

 

First grab the settings from the source network:

# Grab the current WiFi settings
ssidSettings=dashboard.wireless.getNetworkWirelessSsid(fromNetworkId,ssidNumber)

Then copy all of the settings to the new network:

# Build the SSID argument list
kwargs = {}
for setting in ssidSettings:
 kwargs[setting]=ssidSettings[setting]

dashboard.wireless.updateNetworkWirelessSsid(toNet['id'],**kwargs)

 

@sungod probably has a better approach ...

RaphaelL
Kind of a big deal
Kind of a big deal

And this is working for you Phil ? I don't have the same luck 😞

 

Recently I can't copy my WPA2-Enterprise SSID settings. When I do the push It pukes couple errors about RadSecTLS timeouts ( which are not visible on the dashboard ). Opened a case , waiting ...

PhilipDAth
Kind of a big deal
Kind of a big deal

Yes, I've used it maybe 10 to 20 times to copy WiFi settings.

sungod
Kind of a big deal

@PhilipDAth 

 

I tend to follow old-school defensive programming practices...

 

There are API calls that return elements with a None value when they really shouldn't, or that change behaviour without notice, or that give the same data with different element names for no apparent reason.

 

Anything I need to rely on, I code to validate each element and then follow the rules to build the parameter list for the write operation. It's more effort, but still a lot easier than paper coding pads and opcode tables.

 

I know if I trust what an API response provides, there is a higher likelihood something will break, probably at 0200 on a Saturday.

 

RaphaelL
Kind of a big deal
Kind of a big deal

My favorite example 🙂 

 

get /networks/{networkId}/wireless/ssids 

{'authMode': '8021x-radius',
 'availabilityTags': [],
 'availableOnAllAps': True,
 'bandSelection': 'Dual band operation',
 'dot11r': {'adaptive': False, 'enabled': True},
 'dot11w': {'enabled': False, 'required': False},
 'enabled': True,
 'encryptionMode': 'wpa-eap',
 'ipAssignmentMode': 'Bridge mode',
 'lanIsolationEnabled': False,
 'mandatoryDhcpEnabled': False,
 'minBitrate': 11,
 'name': 'XXXXXX',
 'number': 0,
 'perClientBandwidthLimitDown': 0,
 'perClientBandwidthLimitUp': 0,
 'perSsidBandwidthLimitDown': 0,
 'perSsidBandwidthLimitUp': 0,
 'radiusAccountingEnabled': True,
 'radiusAccountingInterimInterval': 1200,
 'radiusAccountingServers': [{'caCertificate': None,
                              'host': 'XXXXX',
                              'id': 'XXXXXXX',
                              'openRoamingCertificateId': None,
                              'port': 1813},
                             {'caCertificate': None,
                              'host': 'XXXXXX',
                              'id': 'XXXXXX',
                              'openRoamingCertificateId': None,
                              'port': 1813}],
 'radiusAttributeForGroupPolicies': 'Airespace-ACL-Name',
 'radiusAuthenticationNasId': '$NODE_MAC$:$VAP_NUM$',
 'radiusCalledStationId': '$NODE_MAC$:$VAP_NAME$',
 'radiusCoaEnabled': True,
 'radiusFailoverPolicy': None,
 'radiusFallbackEnabled': False,
 'radiusLoadBalancingPolicy': None,
 'radiusOverride': True,
 'radiusProxyEnabled': False,
 'radiusRadsecTlsIdleTimeout': 900,
 'radiusServerAttemptsLimit': 3,
 'radiusServerTimeout': 1,
 'radiusServers': [{'caCertificate': None,
                    'host': 'XXXX',
                    'id': 'XXXXXX',
                    'openRoamingCertificateId': None,
                    'port': 1812},
                   {'caCertificate': None,
                    'host': 'XXXXXX',
                    'id': 'XXXXX',
                    'openRoamingCertificateId': None,
                    'port': 1812}],
 'radiusTestingEnabled': False,
 'speedBurst': {'enabled': False},
 'splashPage': 'None',
 'ssidAdminAccessible': False,
 'useVlanTagging': False,
 'visible': False,
 'wpaEncryptionMode': 'WPA2 only'}

 you try to push to a new network : 

 

"RADIUS RADSec TLS idle timeout interval must be greater than RADIUS accounting interim interval"

 

remove "radiusRadsecTlsIdleTimeout" ( because where did that come from ? not present on the dashboard . I know 1200 > 900)

you get : 'encryptionMode' must be one of: 'wep' or 'wpa'

 

remove encryptionMod. It works.... 

 

How hard is it to push the same payload that you got.... 

Get notified when there are additional replies to this discussion.