Force check with NagiosXI API using Python scripts - python

While trying to configure a script using python to write comments using the API i'm encounteringthe following error mesage:
{"error":"Unknown API endpoint."}
The code given by NagiosXI API System Reference, system/corecommand is the following:
curl -XPOST "http://192.168.1.239/nagiosxi/api/v1/system/corecommand?apikey=<API_Key>" -d "cmd=ADD_HOST_COMMENT;localhost;1;%user%;This is a test comment"
This translated to python should be something like this:
import requests
url = "http://192.168.1.239/nagiosxi/api/v1/system/corecommand"
api_key = "<API_Key>"
params = {
"cmd": "ADD_HOST_COMMENT",
"host_name": "localhost",
"entry_time": 1,
"author": "%user%",
"comment_data": "This is a test comment",
"apikey": api_key
}
response = requests.post(url, params=params)
if response.status_code == 200:
print("Comment added successfully")
else:
print("Error adding comment: ", response.text)
At the moment i'm getting a 200 response but with the error message previously mentioned: "{"error":"Unknown API endpoint."}"
Currently using NagiosXI version 5.9.3
Both systems are on the same network an "GET" request go through without any hiccups.
Many thanks in advance;

Related

Getting different responses from postman vs. python API call

I'm trying get the same data from an API call in Postman using Python.
The call is relatively simple. It uses Basic Authorization that only requires the API key being passes as the username, and a dynamic component: csv_key variable that is passed from earlier codes.
I was able to successfully made the request (status code 200), but the response from Python is different from the one in Postman. It's missing all key-value pairs except the firs two: id and description.
I'm getting this response from postman:
response from postman
{
"id": "63c9c0927885bf003ecd3a1b",
"description": "Streaming analytics",
"download_url": "https://storage.googleapis.com/***-static/***.csv?GoogleAccessId=888211540537-r3m40kms2upicdr07e5rl2q67feg9loh%40developer.gserviceaccount.com&Expires=4070908800&Signature=WvuuKdddCFKjSNpst5n8yKFNR5qtC1m1o1mQZFWLHmKomJtc7npa6PbwfRoTj9FhIIqbta98VPOYKMGW89XaqXtITh15V%2Bf9opAD3BnuLjTzWC6X24RC5kMCZATXpp9DWi1Our061%2FdKlpUozi1ir7b8AwBWWf%2Bs8u5J6VoelvtEyiZIO4l%2FQdeJ26GqDLRgWElEMAlBE3TJo7m3UuE8gOQPsYBCwBSfLI1bTIytNOHZMUlWuVtMQxEHzUOujAp%2Fgqn1Q8TGGzy5GoeEmzw%2FD80xs%2BALjhT%2BxdiN9riG6%2BEcObrhPoudxl32jUhVH0EmGJwjgiJFQpz%2FLfKr86LrCQ%3D%3D",
"error": "Cannot read property 'email' of undefined",
"completed_at": "2023-01-19T22:13:39.219Z"
}
But I'm only getting the first two key-value pairs using a Python script of the same API call:
response from Python
csv key: 63c9c0927885bf003ecd3a1b
api url: https://api.eventive.org/temporary_exports/63c9c0927885bf003ecd3a1b
<Response [200]>
response:[{'id': '63c9c0927885bf003ecd3a1b', 'description': 'Streaming analytics'}]
Process finished with exit code 0
My code for the Python script is:
import requests
import json
url_for_key = 'https://api.***.org/reports/streams?event_bucket=63279b48d8f8f1009209694f&start=1674111600000&end=1674198000000&tz=America%2FDenver'
api_key = '*************************'
header = {'content-type': 'application/json'}
r1 = requests.get(url=url_for_key, auth=(api_key, ''))
csv_obj = [r1.json()]
csv_key = csv_obj[0]['temporary_export']
#print(csv_obj)
print(f'csv key: {csv_key}')
url_for_link = 'https://api.***.org/temporary_exports/{}'.format(csv_key)
print(f'api url: {url_for_link}')
r2 = requests.get(url=url_for_link, headers=header, auth=(api_key, ''))
print(r2)
print(f'response:{[r2.json()]}')
csv_key is the same as id. Could anyone help me understand what's going on?
Many thanks,

How do you push files to a github repo in python

This bounty has ended. Answers to this question are eligible for a +50 reputation bounty. Bounty grace period ends in 19 hours.
user19926715 is looking for an up-to-date answer to this question:
I would like an example that shows the before and after of the packet before it gets sent and the response after and showing proof of it going into a repository and explain what was different from the code given by me.
I have a file called w.txt that holds 4 random numbers
I am trying to push it to a git repo and I have the following code:
aa=open(fileName,'r').read()
print(aa)
text= base64.b64encode(aa.encode("utf-8"))
api="https://api.github.com/repos/Ixonblitz-MatOS/Worm/contents/w.txt"
headers = {
"Authorization": f'''Bearer {token}''',
"Content-type": "application/vnd.github+json"
}
data = {
"message": msg, # Put your commit message here.
"content": text.decode("utf-8")
}
r = requests.put(api, headers=headers, json=data)
print(r.text)
In this case fileName is "w.txt" and the api is the api for my repo and the correct token is being used. What am I missing? It is leaving the file on my repo empty instead of putting the numbers there.
You need to provide the SHA of the file as the error message says.
To get the SHA, you can get the file like this:
import requests
url = "https://api.github.com/repos/Ixonblitz-MatOS/Worm/contents/w.txt"
headers = {
'Accept': 'application/vnd.github+json',
'Authorization': 'Bearer <token>',
}
response = requests.request("GET", url, headers=headers)
data = response.json()
The SHA will be at data['sha'].
Then you need to modify your request to include the SHA:
data = {
"message": msg, # Put your commit message here.
"content": text.decode("utf-8"),
"sha": data['sha']
}
The /repos/{owner}/{repo}/contents/{path} API route to fetch files has some size limits. See below:
If the requested file's size is:
1 MB or smaller: All features of this endpoint are supported.
Between
1-100 MB: Only the raw or object custom media types are supported.
Both will work as normal, except that when using the object media
type, the content field will be an empty string and the encoding field
will be "none". To get the contents of these larger files, use the raw
media type.
Greater than 100 MB: This endpoint is not supported.
For larger files, you will have to clone the repository and then calculate the SHA locally.
Why don't you do it this way.
from git import Repo
PATH_OF_GIT_REPO = r'path\to\your\project\folder\.git' # make sure .git folder is properly configured
COMMIT_MESSAGE = 'comment from python script'
def git_push():
try:
repo = Repo(PATH_OF_GIT_REPO)
repo.git.add(update=True)
repo.index.commit(COMMIT_MESSAGE)
origin = repo.remote(name='origin')
origin.push()
except:
print('Some error occured while pushing the code')
git_push()
Based on the code you've provided, it seems that you are encoding the content of the file as base64 before pushing it to your Git repository. While this is a valid approach, you need to make sure that you are decoding the content before writing it to the file on the Git repository. Here's a modified version of your code that should work:
import base64
import requests
fileName = "w.txt"
msg = "Updated w.txt with new numbers"
token = "<your GitHub access token>"
with open(fileName, 'r') as f:
content = f.read()
encoded_content = base64.b64encode(content.encode("utf- 8")).decode("utf-8")
api_url = "https://api.github.com/repos/Ixonblitz-MatOS/Worm/contents/w.txt"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/vnd.github+json"
}
data = {
"message": msg,
"content": encoded_content
}
response = requests.put(api_url, headers=headers, json=data)
if response.status_code == 200:
print("Successfully pushed the file to Git repository.")
else:
print(f"Error pushing file to Git repository. Response status code: {response.status_code}")
The above code reads the content of the file into the content variable and then encodes it as base64 using the base64.b64encode method. It then sends a PUT request to the GitHub API to create or update the file in your Git repository. The data payload contains the encoded content of the file along with a commit message. The response status code is then checked to verify whether the operation was successful.
Note that you may also want to make sure that the headers dictionary contains the correct User-Agent field as per GitHub API requirements.

Ebay Token and GetDealItems API Call Issue

I'm trying to access GetDealItems API and i have a nightmare to get this working. Even though I use the valid client_id','client_secret','ruName' i keep getting
{'error': 'invalid_client', 'error_description': 'client authentication failed'}
below is the ebay doc
https://developer.ebay.com/api-docs/buy/deal/resources/deal_item/methods/getDealItems
I guess i need to use this scope and url in my request
scopes:'https://api.ebay.com/oauth/api_scope/buy.deal' and the
url='https://api.ebay.com/buy/deal/v1/deal_item?limit=1000'
Please see below my Python code.
import requests, urllib, base64
def getAuthToken():
AppSettings = {
'client_id':'xxxx7c8ec878c-c80c4c69',
'client_secret':'xxxx56db-4b4a-97b4-fad2',
'ruName':'xxxxx-gscrcsrtj'}
authHeaderData = AppSettings['client_id'] + ':' + AppSettings['client_secret']
encodedAuthHeader = base64.b64encode(str.encode(authHeaderData))
headers = {
"Content-Type" : "application/x-www-form-urlencoded",
"Authorization" : "Bearer " + str(encodedAuthHeader)
}
body= {
"grant_type" : "client_credentials",
"redirect_uri" : AppSettings['ruName'],
"scope" : "https://api.ebay.com/oauth/api_scope/buy.deal"
}
data = urllib.parse.urlencode(body)
tokenURL = "https://api.ebay.com/identity/v1/oauth2/token"
response = requests.post(tokenURL, headers=headers, data=data)
return response.json()
response = getAuthToken()
print(response)
response['access_token'] #access keys as required
response['error_description'] #if errors
The most obvious problem I see is that you are using Bearer when you should be using Basic in your Authorization header.
Also, You are urlencoding your redirect_url when you pass the entire dictionary into urlencode. The docs say you are supposed to urlencode the scope parameter, but honestly, I never encode the scope and it still works for me.
Here is your modified code, with a few formatting changes:
import requests, urllib, base64
client_id='xxxx7c8ec878c-c80c4c69'
client_secret='xxxx56db-4b4a-97b4-fad2'
ruName='xxxxx-gscrcsrtj'
scope = urllib.parse.quote('https://api.ebay.com/oauth/api_scope/buy.deal')
def basic_token(key, secret):
return 'Basic ' + base64.b64encode((key + ':' + secret).encode()).decode()
def getAuthToken():
headers = {
"Content-Type" : "application/x-www-form-urlencoded",
"Authorization" : basic_token(client_id, client_secret)
}
data = (
'grant_type=client_credentials&'
f'redirect_uri={ruName}&'
f'scope={scope}'
)
tokenURL = "https://api.ebay.com/identity/v1/oauth2/token"
response = requests.post(tokenURL, headers=headers, data=data)
return response.json()
Update:
I think you need to use the authorization_code grant instead of client_credentials.
To use the authorization_code grant, modify your body to look like this:
data = (
'grant_type=authorization_code&'
f'code={authorization_code}&'
f'redirect_uri={ruName}&'
f'scope={scope}'
)
Also, you will need to follow your "redirect url" to get the actual authorization code. Execute the following:
redirect_url = (
'https://auth.ebay.com/oauth2/authorize?'
f'client_id={client_id}&'
f'response_type=code&'
f'redirect_uri={ruName}&'
f'scope={scope}'
)
print(redirect_url)
Copy/paste the url from stdout, follow the link, and click "accept", then you will be redirected to a url that looks like this:
https://signin.ebay.com/ws/eBayISAPI.dll?ThirdPartyAuthSucessFailure&isAuthSuccessful=true&code=<authorization code here>&expires_in=299
Copy/paste the authorization code into your code, then see if it works.
Realistically, eBay expects you to automate this within your application using a server, but it doesn't make sense for you to go through the trouble if you are building an app for personal use.
GetDealItems API uses client_credentials grant as evident from the docs
The authorization should be using client_id and secret as described in getting access tokens
curl -X POST 'https://api.ebay.com/identity/v1/oauth2/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Authorization: Basic UkVTVFRlc3...wZi1hOGZhLTI4MmY=' \
-d 'grant_type=client_credentials&scope=https%3A%2F%2Fapi.ebay.com%2Foauth%2Fapi_scope%2Fbuy.deal'
Note: if the error is client_authorization_failed, ensure that the correct Keyset for production is used for production. Also ensure that the keyset is also enabled for Oauth
Finally, you can use/refer to the official python SDK as well here
A simple way to check if the particular scope, in this case https://api.ebay.com/oauth/api_scope/buy.deal is even allowed for this app, is to navigate to the keyset page under Keys link and click on "Oauth scopes" under the keyset which details the scopes allowed and their purpose. If the application is once authorized for buy.deal, then the scope will appear there.
UPDATE
GetDeals API is restricted in Production for authorized applications only. Please reach out to the eBay developer program as provided in the link on the page below.
https://developer.ebay.com/api-docs/buy/deal/overview.html#API

webAPI communication in python: Requested route has not been mapped in spark

I'm trying to communicate with a server (program controlling robots) via webAPI which expects JSON Files. I tried to realize this with the following Python Code, but I always get the Error:
The requested route [/v1/TransportOrders/Order-0001] has not been mapped in Spark for Accept: [/]
Does anybody know what causes the error or how to fix it?
Let me know if you need any further details.
Thanks
CODE:
#!/usr/bin/env python
import requests
import json
url = 'http://localhost:55200/v1/TransportOrders/Order-0001'
# headers= {'Content-type': 'application/json'}
transportOrders = {
"deadline": "2019-03-07T06:42:40.396Z",
"intendedVehicle": "Vehicle-0001",
"destinations": [
{
"locationName": "Location-0001",
"operation": "NOTHING",
}
]
}
resp = requests.post(url, data=json.dumps(transportOrders))
print 'data sent'
if resp.status_code != 200:
print 'error accured transmitting data'
print resp.status_code
The requested route [/v1/TransportOrders/Order-0001] has not been mapped in Spark for Accept: [/]
This is the default "404" message from SparkJava. You should double-check in the server API documentation that you are calling the right end point, at the right path with the right parameters and headers - and the right server, for that matter.

400 (Bad Request) error when using Pushbullet Ephemerals

I'm working on a simple command-line Pushbullet Python project, and have the following code:
from settings import *
import urllib
import urllib2
def pushSms(number, message):
url = 'https://api.pushbullet.com/v2/ephemerals'
values = {
"type": "push",
"push": {
"type": "messaging_extension_reply",
"package_name": "com.pushbullet.android",
"source_user_iden": settings["PUSHBULLET_USER_IDEN"],
"target_device_iden": settings["PUSHBULLET_SMS_IDEN"],
"conversation_iden": number,
"message": message
}
}
headers = {"Authorization" : "Bearer " + settings["PUSHBULLET_API_KEY"]}
data = urllib.urlencode(values)
req = urllib2.Request(url, data, headers)
response = urllib2.urlopen(req)
return response
Example usage might be pushSms("555 555 5555", "Hi there!").
This takes advantage of the Pushbullet android app access to SMS, as documented here. I've checked my settings variables and they're all valid (in fact, they're currently in use in a JavaScript version of nearly this exact code in another project of mine.
My suspicion is that this is a basic Python syntax/urllib2 misuse or error, but I've been staring/Googling for hours and can't see my error. Thoughts?
I can't tell for certain (the response from the server may contain more information), but because we accept both form encoded and json requests, you probably need to set the header "Content-Type: application/json" on the request.
If that's not the case, could you post the body of the 400 response?

Categories

Resources