Dashboard API via Python - unable to get local issuer certificate (passing through web gateway)

Solved
Meraki_Dave
Here to help

Dashboard API via Python - unable to get local issuer certificate (passing through web gateway)

 

Hello, 

 

I am using the Meraki Python module and having issues getting through our web gateway. 

 

My old scripts use a request.get where I can pass the certificate location in, but I am unable to see how to do this within the meraki python module

 

Code / Error:

 

 

 

import meraki

x_cisco_meraki_api_key = 'MyKey'

m = meraki.DashboardAPI(x_cisco_meraki_api_key)
orgs = m.organizations.getOrganizations()

print(orgs)

 

 

 

 

 

Organizations, getOrganizations - HTTPSConnectionPool(host='api.meraki.com', port=443): Max retries exceeded with url: /api/v0/organizations (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)'))), 

 

 

 

 

1 Accepted Solution
chengineer
Meraki Alumni (Retired)
Meraki Alumni (Retired)

Thanks @Meraki_Dave, this functionality has been pushed to a new 0.70.5 version so that you can specify the certificate path in the class instantiation, like this:

m = meraki.DashboardAPI(x_cisco_meraki_api_key, certificate_path='C:\\certfolder\\certfile.cer')

 

Also, this update contains newly-published endpoints for MV camera quality & retention settings, MX inbound firewall, and MS link aggregations.

Solutions Architect @ Cisco Meraki | API & Developer Ecosystem

View solution in original post

16 Replies 16
chengineer
Meraki Alumni (Retired)
Meraki Alumni (Retired)

Can you provide an example of what you did previously with requests.get to pass in the certificate information to make calls correctly with your corporate proxy please?

Solutions Architect @ Cisco Meraki | API & Developer Ecosystem
Meraki_Dave
Here to help

I am able to pass " verify='C:\location\of\my\cert.cer' to the requests.get, and it uses the certificate as expected, see below:

 

def list_networks(api_key, org_id):
    url = 'https://dashboard.meraki.com/api/v0/organizations/{}/networks'.format(org_id)
    try:
        response = requests.get(url=url, headers={'X-Cisco-Meraki-API-Key': api_key, 'Content-Type': 'application/json'}, verify='C:\\certfolder\\certfile.cer')
        return json.loads(response.text)
    except requests.exceptions.RequestException as e:
        print('Error calling list_networks: {}'.format(e))

 

 

chengineer
Meraki Alumni (Retired)
Meraki Alumni (Retired)

Thanks @Meraki_Dave, this functionality has been pushed to a new 0.70.5 version so that you can specify the certificate path in the class instantiation, like this:

m = meraki.DashboardAPI(x_cisco_meraki_api_key, certificate_path='C:\\certfolder\\certfile.cer')

 

Also, this update contains newly-published endpoints for MV camera quality & retention settings, MX inbound firewall, and MS link aggregations.

Solutions Architect @ Cisco Meraki | API & Developer Ecosystem
Meraki_Dave
Here to help

Thank you for that fast turnaround - everything is now working as expected. 

Paul_W
Here to help

Hi,

 

I'm getting a syntax error when trying to define certificate_path as below.  Any ideas on how to work around this?

 

def main():
    # Instantiate a Meraki dashboard API session
    dashboard = meraki.DashboardAPI(
        api_key='xxxx',
        base_url='https://api-mp.meraki.com/api/v0/',
        output_log=True,
        log_file_prefix=os.path.basename(__file__)[:-3],
        log_path='',
        print_console=True
        certificate_path='C:\\certfolder\\certfile.cer'      
    )
chengineer
Meraki Alumni (Retired)
Meraki Alumni (Retired)

looks like you're missing a comma there following the penultimate parameter

Solutions Architect @ Cisco Meraki | API & Developer Ecosystem
Paul_W
Here to help

Thanks for that, I knew it would have been something daft.  Do you know if the full key chain is required?  I'm still having problems, but it is a different challenge this time.

 

meraki: INFO > Meraki dashboard API session initialized with these parameters: {'version': '0.110.5', 'api_key': '************************************', 'base_url': 'https://api-mp.meraki.com/api/v0/', 'single_request_timeout': 60, 'certificate_path': 'C:\\certfolder\\certfile.cer', 'requests_proxy': '', 'wait_on_rate_limit': True, 'nginx_429_retry_wait_time': 60, 'action_batch_retry_wait_time': 60, 'retry_4xx_error': False, 'retry_4xx_error_wait_time': 60, 'maximum_retries': 2, 'simulate': False, 'be_geo_id': None, 'caller': None}


meraki: WARNING > Organizations, getOrganizations - HTTPSConnectionPool(host='api-mp.meraki.com', port=443): Max retries exceeded with url: /api/v0/organizations (Caused by SSLError(SSLError(136, '[X509: NO_CERTIFICATE_OR_CRL_FOUND] no certificate or crl found (_ssl.c:4263)'))), retrying in 1 second

 

I have checked the basics like is the certificate valid etc and ensured the path is correct and the case is correct.

abc2
New here

Hi, I am new to meraki module.

 

I developed the script using meraki module but i always get the below error 

 

(Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)')))

 

Even after using certificate_path="C:\certfolder\certificate.cer" am getting the same error.

 

Is there any solution for this ? 

Thanks in advance

 

 

Greenberet
Head in the Cloud

try double slashes in the path -> "C:\\certfolder\\certificate.cer"

abc2
New here

Thanks for the reply.

Yea i tried that too. Still getting the same error.

Is there any other way to download the certificate.cer and load them into "certificate_path"

 

 

PhilipDAth
Kind of a big deal
Kind of a big deal

Is this a transparent proxy?  Can you manually use whatever it is as a "normal" proxy?

Can you add *.meraki.com to a whitelist to bypass SSL inspection?

 

 

Some other thoughts; Python should trust what the underlying operating systems considers is trusted.  Can you web browse (from this machine running the script) to the below location and get no browser errors?

https://api.meraki.com/

 

If you do get a browser error, you will need to add the root certificate of your proxy server into the trusted root certificate store on the machine making the request.  I guess it is also possible the the root certicate of the device doing the SSL inspection has expired.  Need to see what that browser test says.

Adrian4
Head in the Cloud

I am sending the API calls via python script in pycharm ide on Windows 11.


I can reach the site with no errors but when I run the scripts I get

send
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='api.meraki.com', port=443): Max retries exceeded with url: /api/v1/organizations (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:992)')))

I am setting verify to false to get around it but Id like to fix it properly.

I have tried downloading the cisco umbrella root CA from the dashboard site and import it into my trusted root cert authorities but it hasn't worked.

PhilipDAth
Kind of a big deal
Kind of a big deal

It sounds like pycharm in your environment doesn't have the typical set of trusted root certificates loaded.  I would Google in that area.

Meraki_Dave
Here to help

in my specific situation it was that I had to trust our corporate web gateway root certificate. if you have a similar situation, you can store the cert locally, and use the following line in your python code to reference it:

 

dashboard = meraki.DashboardAPI(MERAKI_DASHBOARD_API_KEY, suppress_logging=True, certificate_path="C:\\certs\\your_cert.cer")

 

Adrian4
Head in the Cloud

cheers

PhilipDAth
Kind of a big deal
Kind of a big deal

What OS are you using this on?

 

Also, are you using a "recent" requests module?  Try something like:

pip install -U requests

 

 

Get notified when there are additional replies to this discussion.