1

I have this curl command I use a shell script:

curl -X POST -H 'Content-Type: application/json' \
--cert /etc/puppetlabs/puppet/ssl/certs/${PEFQDN}.pem \
--key /etc/puppetlabs/puppet/ssl/private_keys/${PEFQDN}.pem \
--cacert /etc/puppetlabs/puppet/ssl/certs/ca.pem \
--data "{ \"name\": \"$GROUP\", \"parent\": \"00000000-0000-4000-8000-000000000000\", \"environment\": \"production\", \"classes\": { \"$CLASS\": {}} }" \
https://${PEFQDN}:4433/classifier-api/v1/groups | python -m json.tool

I want to get away from my shell script as I need to be able to process some complex json that comes back from the REST API. I figure I'd use python and the requests package. I was looking at this documentation:

http://docs.python-requests.org/en/latest/user/quickstart/

But I do not see where I can specify my certificate info. In my shell script I can pass curl these options: --cert, --key, --cacert. I do not know how to accomplish the same with python's requests API. Does anyone out know how I can accomplish this?

UPDATE: Thanks Joran. Here is my attempt to write a python script to do this:

#!/usr/bin/env python

import requests

# curl https://${PEFQDN}:4433/classifier-api/v1/groups \
# -H "Content-Type: application/json" \
# --cert /etc/puppetlabs/puppet/ssl/certs/${PEFQDN}.pem \
# --key /etc/puppetlabs/puppet/ssl/private_keys/${PEFQDN}.pem \
# --cacert /etc/puppetlabs/puppet/ssl/certs/ca.pem | python -m json.tool

url='https://my-pm.example.com:4433/classifier-api/v1/groups'
headers = {"Content-Type: application/json"}
data={}
cacert='/etc/puppetlabs/puppet/ssl/certs/ca.pem'
key='/etc/puppetlabs/puppet/ssl/private_keys/my-pm.example.com.pem'
cert='/etc/puppetlabs/puppet/ssl/certs/my-pm.example.com.pem'
result = requests.get(url,
        data=data, #whatever data
        headers=headers, #dict {"Content-Type":"application/json"}
        verify=cert,
        cert=(cacert,key) #key/cert pair 
        )
print result.json()

And I must be doing something wrong because this is the output I get ...

# ./add-group.py 
Traceback (most recent call last):
  File "./add-group.py", line 21, in <module>
    cert=(cacert,key) #key/cert pair 
  File "/usr/lib/python2.7/site-packages/requests-2.7.0-py2.7.egg/requests/api.py", line 69, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests-2.7.0-py2.7.egg/requests/api.py", line 50, in request
    response = session.request(method=method, url=url, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests-2.7.0-py2.7.egg/requests/sessions.py", line 451, in request
    prep = self.prepare_request(req)
  File "/usr/lib/python2.7/site-packages/requests-2.7.0-py2.7.egg/requests/sessions.py", line 382, in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "/usr/lib/python2.7/site-packages/requests-2.7.0-py2.7.egg/requests/models.py", line 293, in prepare
    self.prepare_headers(headers)
  File "/usr/lib/python2.7/site-packages/requests-2.7.0-py2.7.egg/requests/models.py", line 401, in prepare_headers
    self.headers = CaseInsensitiveDict((to_native_string(name), value) for name, value in headers.items())
AttributeError: 'set' object has no attribute 'items'

What I am doing wrong here?

Thanks

2 Answers 2

3
headers = {"Content-Type: application/json"}

should be changed to

headers = {"Content-Type": "application/json"}

Looks like the requests API is expecting a dictionary, and {"Content-Type: application/json"} is apparently a Python set.

Sign up to request clarification or add additional context in comments.

Comments

2
result = requests.get(url,
        data=data, #whatever data
        headers=headers, #dict {"Content-Type":"application/json"}
        cert=(cacert,key),#key/cert pair 
        verify="cert_chain.pem" 
        )
print result.json() #depending on version of requests, json may be a function or a property

this link will be helpful

http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification

4 Comments

Maybe this is obvious enough that it doesn't need to be pointed out, but it should be post() instead of get().
it should work identically regardless of post/get/push
Thanks Joran, but I still don't get what I am doing wrong in my python script. I have updated my question with my attempt to write this in python. Please take a look. Thank you
headers = {"Content-Type: application/json"} is not the same as headers = {"Content-Type": "application/json"} one is a dictionary with one key/value pair, the other is a set with a single string element ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.