Infoblox WAPI: how to search for an IP - python

Our network team uses InfoBlox to store information about IP ranges (Location, Country, etc.)
There is an API available but Infoblox's documentation and examples are not very practical.
I would like to search via the API for details about an IP. To start with - I would be happy to get anything back from the server. I modified the only example I found
import requests
import json
url = "https://10.6.75.98/wapi/v1.0/"
object_type = "network"
search_string = {'network':'10.233.84.0/22'}
response = requests.get(url + object_type, verify=False,
data=json.dumps(search_string), auth=('adminname', 'adminpass'))
print "status code: ", response.status_code
print response.text
which returns an error 400
status code: 400
{ "Error": "AdmConProtoError: Invalid input: '{\"network\": \"10.233.84.0/22\"}'",
"code": "Client.Ibap.Proto",
"text": "Invalid input: '{\"network\": \"10.233.84.0/22\"}'"
}
I would appreciate any pointers from someone who managed to get this API to work with Python.
UPDATE: Following up on the solution, below is a piece of code (it works but it is not nice, streamlined, does not perfectly checks for errors, etc.) if someone one day would have a need to do the same as I did.
def ip2site(myip): # argument is an IP we want to know the localization of (in extensible_attributes)
baseurl = "https://the_infoblox_address/wapi/v1.0/"
# first we get the network this IP is in
r = requests.get(baseurl+"ipv4address?ip_address="+myip, auth=('youruser', 'yourpassword'), verify=False)
j = simplejson.loads(r.content)
# if the IP is not in any network an error message is dumped, including among others a key 'code'
if 'code' not in j:
mynetwork = j[0]['network']
# now we get the extended atributes for that network
r = requests.get(baseurl+"network?network="+mynetwork+"&_return_fields=extensible_attributes", auth=('youruser', 'youpassword'), verify=False)
j = simplejson.loads(r.content)
location = j[0]['extensible_attributes']['Location']
ipdict[myip] = location
return location
else:
return "ERROR_IP_NOT_MAPPED_TO_SITE"

By using requests.get and json.dumps, aren't you sending a GET request while adding JSON to the query string? Essentially, doing a
GET https://10.6.75.98/wapi/v1.0/network?{\"network\": \"10.233.84.0/22\"}
I've been using the WebAPI with Perl, not Python, but if that is the way your code is trying to do things, it will probably not work very well. To send JSON to the server, do a POST and add a '_method' argument with 'GET' as the value:
POST https://10.6.75.98/wapi/v1.0/network
Content: {
"_method": "GET",
"network": "10.233.84.0/22"
}
Content-Type: application/json
Or, don't send JSON to the server and send
GET https://10.6.75.98/wapi/v1.0/network?network=10.233.84.0/22
which I am guessing you will achieve by dropping the json.dumps from your code and handing search_string to requests.get directly.

Related

Python request to retrieve all requests from Postman collection

I need to print all requests from specific Postman collection. I have this code:
import requests
# Set up Postman API endpoint and authorization
postman_api_endpoint = "https://api.getpostman.com/collections"
postman_api_key = "PMAK-63b6bf724ebf902ad13d4bf2-e683c12d426716552861acda**********"
headers = {"X-Api-Key": postman_api_key}
# Get all requests from Postman collection
collection_id = "25184041-c1537769-f598-4c0e-b8ae-8cd185a79c03"
response = requests.get(f"{postman_api_endpoint}/{collection_id}/items", headers)
if response.status_code != 200:
print("Error retrieving collection:", response.text)
else:
# Print all requests
requests_data = response.json()["items"]
for request_data in requests_data:
request_method = request_data["request"]["method"]
request_url = request_data["request"]["url"]
request_headers = request_data["request"]["header"]
request_body = request_data["request"]["body"]["raw"] \
if request_data["request"]["body"]["mode"] == "raw" else ""
print(f"{request_method} {request_url}")
print("Headers:")
for header in request_headers:
print(f"{header['key']}: {header['value']}")
print("Body:")
print(request_body)
I received an error while I try to call response.text and have such massage:
Error retrieving collection: {"error":{"name":"notFound","message":"Requested resource not found"}}
Which means that I have 404 error. I have several assumptions what I did wrong:
I entered incorrect api key(But I checked several times and regenerated it twice)
I entered incorrect collection id, but in the screen below you can see where I took it and it is correct
And as I think the most likely variant I wrote incorrect request where I put my key and my collection id(I din't find any example how such requests should be like)
And of course I have requests in my collection, so error can not be because the collection is empty
Please give me some advice how I can fix this error. Thank you!
The answer is actually is really simple. I didn't know that I need to push button save request in Postman. I think if I create request in collection it will automatically save it. But I didn't, so I just saved all requests manually and finally receive correct response.

Python HTTP Requests

The following figure shows the TMDb endpoint documentation by which a client can request a movie or TV show be added to a user's watchlist, where the user has previously established a session_id.
Based on the developer documentation, and using the (fictional) values of the various pieces that need to be part of the request and that are presented in the following table:
Question !!
Can you please provide the HTTP for this request? You can present the request in a line-oriented fashion, and without needing to note linefeeds or carriage returns.
If you are asking about writing code, the following lines could be useful for you:
import requests
account_id = 12345
url = 'https://YOUR_URL.com/accout/' + account_id + '/watchlist'
payload = {'media_type': 'movie', 'media_id': 777, 'watchlist': 'true'}
x = requests.post(url, data = payload)
print(x.text)
Where is:
requests.post(url, data={key: value}, json={key: value} -> string, args)

how to parametrize url in put requests using python

I am trying to send parameterized url in put request using python.
One of my function "getipaddress()" is returning the device ip address as 192.168.72.31
Code:
import requests
ips= getipaddress()
URL = "https://%s/UDW/Command?entry=eprint.register" % ips
r = requests.put(url=URL,data=data, verify=False)
print r.status_code
Getting error : 405 error (Method Not Allowed response status code).
As per inputs from #Ami Hollander and #DeepSpace I have figured out that put request is not supported. Trying with get request, I am able to get the response
Code :
ips = getipaddress() # returns device ip:192.168.72.31
url = "https://%s/UDW/Command?entry=eprint.register" % ips
requests.get(url=URL,verify=False)
Output :
{
"state": 200,
"eprint_reg_state": "registering"
}
I guess your server doesn't accept PUT requests
in Flask : #app.route('/your_route', methods=['PUT'])
in Django : doesn't support PUT requests, you'll need to use http://www.django-rest-framework.org/

How can i post using Python urllib in html input type submit [duplicate]

I'm trying to create a super-simplistic Virtual In / Out Board using wx/Python. I've got the following code in place for one of my requests to the server where I'll be storing the data:
data = urllib.urlencode({'q': 'Status'})
u = urllib2.urlopen('http://myserver/inout-tracker', data)
for line in u.readlines():
print line
Nothing special going on there. The problem I'm having is that, based on how I read the docs, this should perform a Post Request because I've provided the data parameter and that's not happening. I have this code in the index for that url:
if (!isset($_POST['q'])) { die ('No action specified'); }
echo $_POST['q'];
And every time I run my Python App I get the 'No action specified' text printed to my console. I'm going to try to implement it using the Request Objects as I've seen a few demos that include those, but I'm wondering if anyone can help me explain why I don't get a Post Request with this code. Thanks!
-- EDITED --
This code does work and Posts to my web page properly:
data = urllib.urlencode({'q': 'Status'})
h = httplib.HTTPConnection('myserver:8080')
headers = {"Content-type": "application/x-www-form-urlencoded",
"Accept": "text/plain"}
h.request('POST', '/inout-tracker/index.php', data, headers)
r = h.getresponse()
print r.read()
I am still unsure why the urllib2 library doesn't Post when I provide the data parameter - to me the docs indicate that it should.
u = urllib2.urlopen('http://myserver/inout-tracker', data)
h.request('POST', '/inout-tracker/index.php', data, headers)
Using the path /inout-tracker without a trailing / doesn't fetch index.php. Instead the server will issue a 302 redirect to the version with the trailing /.
Doing a 302 will typically cause clients to convert a POST to a GET request.

How do I insert a row in my google fusion table using Python

I am working on a project and part of it involves inserting rows in to a Google Fusion Table for the Project from a python script. I have spent the last couple days trying to figure out just how to do that and I am officially confused.
My research seems to indicate that I need to use Oauth 2.0 to access the API. In doing so I can successfully get an access token but I can't seem to successfully get a refresh token. I'm not sure if this is going to hamper my ability to successfully integrate access to my Fusion Table with my Python code.
The second problem I am having is that I don't really understand how exactly to code inserting a row in my table. Most of the material I have found on it is from the deprecated Fusion Tables SQL API and I don't fully understand the new way of doing it.
I'm a beginner at this sort of thing and any direction to help me is very much appreciated!
Edit:
So the code I have working so far looks like this:
client_id = "<client_i>"
client_secret = "<client_secret>"
table_id = "<table_id>"
access_token = ""
refresh_token = "<refresh_token>"
# the refresh token is used to request a new access token
data = urllib.urlencode({
'client_id': client_id,
'client_secret': client_secret,
'refresh_token': refresh_token,
'grant_type': 'refresh_token'})
request = urllib2.Request(
url='https://accounts.google.com/o/oauth2/token',
data=data)
request_open = urllib2.urlopen(request)
response = request_open.read()
request_open.close()
tokens = json.loads(response)
access_token = tokens['access_token']
# Read the table
request_read = urllib2.Request(
url='https://www.google.com/fusiontables/api/query?%s' % \
(urllib.urlencode({'access_token': access_token,
'sql': 'SELECT * FROM table_id'})))
request_open = urllib2.urlopen(request_read)
response = request_open.read()
request_open.close()
print response
And my code for trying to insert a new row into my table:
date = str(datetime.now().date())
time = str(datetime.now().time())
query = 'INSERT INTO table_id (Date,Time,Saskatoon,Regina,MeadowLake)VALUES(date,time,60.01,60.02,59.99)'
data = urllib2.Request(
url='https://www.google.com/fusiontables/api/query?%s' % \
(urllib.urlencode({'access_token': access_token,
'sql': query})))
request_open = urllib2.urlopen(data)
When I run this i get
HTTP Error 400: HTTP GET can only be used for select queries.
I am know I'm supposed to be making a POST not a GET for the INSERT, I'm just not sure what needs to change in my code for that to happen.
Sorry for being a noob.
2ND EDIT:
Sorry for making this longer but I feel it is pertinent to show where I've gotten so far. I switched to the library requests and things have gotten somewhat easier however I still haven't successfully made a POST. My new code for importing rows is as follows:
def importRows(self):
print 'IMPORT ROWS'
date = str(datetime.now().date())
time = str(datetime.now().time())
data = {'Date': date,
'Time': time,
'Saskatoon': '60.01',
'Regina': '59.95'}
url = 'https://www.googleapis.com/upload/fusiontables/v1/tables/%s/import/%s' % \
(tableid, self.params) # self.params is access token
importRow = requests.post(url, params=data)
print importRow.status_code
print importRow.text
Which gives me
400
{
"error": {
"errors": [
{
"domain": "fusiontables",
"reason": "badImportInputEmpty",
"message": "Content is empty."
}
],
"code": 400,
"message": "Content is empty."
}
}
If your application needs offline access to a Google API, then the request for an authorization code should include the access_type parameter, where the value of that parameter is offline.
https://developers.google.com/accounts/docs/OAuth2WebServer#offline
Then, to obtain an access token using the refresh token you send a POST request including grant_type with value refresh_token.
Basically, the way SQL works is you send POST requests using a subset of SQL statements https://www.googleapis.com/fusiontables/v1/query?sql=STATEMENT_HERE
Refer to
https://developers.google.com/fusiontables/docs/v1/reference/query
https://developers.google.com/fusiontables/docs/v1/sql-reference
Edit:
Since you are using urllib2 without a data parameter, it defaults to GET. To fix this you should either use another HTTP library that allows for explicitly specifying method (like requests or httplib) or do something like this:
query = "INSERT INTO %s(EXAMPLE_COL1,EXAMPLE_COL2) VALUES"\
"('EXAMPLE_INFO1','EXAMPLE_INFO2')" % table_id # Single quotes
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request('https://www.google.com/fusiontables/api/query?%s' % \
(urllib.urlencode({'access_token': access_token,
'sql': query})),
headers={'Content-Length':0}) # Manually set length to avoid 411 error
request.get_method = lambda: 'POST' # Change HTTP request method
response = opener.open(request).read()
print response
Important to notice:
Monkey patch the method to do what we want (POST with an empty body) otherwise we would receive HTTP Error 400: HTTP GET can only be used for SELECT queries.
Manually specify that we do not have a body (Content-Length is 0) otherwise we would receive HTTP Error 411: Length Required.
Must use double quotes with single quotes inside or escape the inner quotes to submit strings via the query. In other words, "INSERT INTO %s(EXAMPLE_COL1,EXAMPLE_COL2) VALUES(EXAMPLE_INFO1,EXAMPLE_INFO2)" % table_id does not work.
If we tried to use the previous line we would get something like HTTP Error 400: Parse error near 'SOME_STRING' (line X, position Y)
See for info on changing method with urllib2:
Is there any way to do HTTP PUT in python

Categories