I want to create container in splunk phantom using phantom rest api. I am using splunk phantom community version. This is the body I am passing using python post method
payload={
"description": "this is Useful description of this container.",
"label":"events",
"name":"xOkta event 110",
"sensitivity": "red",
"severity":"medium",
"source_data_identifier": "4",
"status": "new",
"container_type": "default",
"run_automation": "False",
"due_time": "2020-06-10T19:29:23.759Z",
}
and this is the code :
requests.post(url, auth=(username, password),json=payload, verify=False)
GET method is working. I am just unable to create container using phantom rest api(I am getting http status code 400 when post called). Any help will be appreciated.
That's an aged question, but to help others, you never told what is the URL endpoint you are trying, but assuming it was right (/rest/container), then the 400 returned means that the endpoint rejected your payload for some reason, but when it does, it outputs the error message in a JSON response (message key).
I would suggest to enable debug mode OR to try the same call via cURL or Postman to validate.
So, in a nutshell:
Make sure you are using the right protocol (HTTP/HTTPS).
Make sure you are sending the POST to /rest/container endpoint with the payload in JSON format.
Make sure the payload has the label, which is mandatory, and it does exist.
Related
I want to send API requests to create or update commands in a ,Powershell script, .ps1 file.
I'm using Python requests library.
I followed the microsoft document HERE to construct the api to be send PUT request.
The format of the .ps1 file that I want to link with the request is something like;
$Comp = $env:computername
$Timezone = (Get-Timezone).Id
If ($Timezone -ne "UTC-04:00")
{write-host "Timezone: Problem Occured!" $timezone -backgroundcolor red}89
else {write-host "TimeZone: OK" $timezone}
and allowed to contain other commands. New commands should be created with sent api request.
The function, takes rgName,vmName,CommandName as parameter and forms an API
to send request with
requests.put(url:"",data:{},params:{}) in python.
The function template as follows;
`subscription_id =os.environ['AZURE_SUBSCRIPTION_ID']
source="https://management.azure.com"
token_context=access_token()
tokens=json.loads(token_context.text)
token=tokens['access_token']
url=" {}/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}/
runCommands/{}?api-version==2021-04-01".format(source,subscription_id,vmRG,vmName,command)
data={"location": "West US","commandId":
"RunShellScript","script": "<urlAdress_toScriptFileinBlobStorage>","asyncExecution":
False,"timeoutInSeconds": 3600}
headers = {'Authorization': 'Bearer ' +token,
'Content-Type': 'application/json'}
response = requests.put(url,data=data,headers=headers)
return response`
But I cannnot get a response body.
The error message I got "
"error": {
"code": "InvalidRequestContent",
"message": "The request content was invalid and could not be deserialized:
'Unexpected character encountered while parsing value: l. Path '', line 0, position 0.'."
"
How can I achieve this task? Is it possible to do with an another method?
What're your opinions about source of the error and how could I fix it?
Any suggestions and solution methods would be appreciated. Thanks in Advance,
Hi Stack Overflow community, thanks in advance for your help:
Question for Community:
Instead of reinventing the oauth wheel, are there any tips / best practices for creating my own oauth signature/nonce within my python GET requests for Netsuite's new API (REST Web Services; see below for context of question)? It seems that other folks who have been successful at this have done it through trial and error which is my plan as well, but ideally I'd like to have fewer errors and again, not reinvent the wheel. Any tips, tricks, ideas are greatly welcome. See context below
What:
Attempting to make a GET request using Netsuite's brand new REST API (REST Web Services). This is a different API than their SOAP/ RESTlets.
How:
Through writing Python script in Visual Studio Code. I am successful at making the request in Postman. I copied the code into Visual Studio Code that Postman used to make the successful GET request and received a 401 response (see below).
Problem Encountered:
I receive a 401 response, invalid login. There is no official Netsuite documentation on how make a successful interaction with this new REST API outside of Postman, so after reading through StackOverflow and other blogs/publications it seems that I need to create my own oauth_signature, oauth_timestamp, and oauth_nonce.
Postman GET Request Code:
import requests
url = "https://123456-sb1.suitetalk.api.netsuite.com/services/rest/query/v1/workbook/custworkbook12345/result"
payload = {}
headers = {
'Authorization': 'OAuth realm="123456_SB1",oauth_consumer_key="123456789101112131415",oauth_token="123456789101112131415",oauth_signature_method="HMAC-SHA256",oauth_timestamp="123456789",oauth_nonce="123456789",oauth_version="1.0",oauth_signature="123456789101112131415"',
'Cookie': 'NS_ROUTING_VERSION=LAGGING'
}
response = requests.request("GET", url, headers=headers, data = payload)
print(response.text.encode('utf8'))
Thanks in advance!
Thanks to Josh's recommendation (see comments to my original question) I successfully used oauthlib's oauth1 client to send a request in Visual Studio Code. The nonce and signature look a little different than what Postman shows in their code snippet, but it did work. For anyone attempting the same thing with Netsuite's REST Web Services I suggest going this route.
My code that sent a successful GET request:
import requests
import oauthlib.oauth1
import json
url = "https://12345-sb1.suitetalk.api.netsuite.com/services/rest/query/v1/dataset/custdataset1/result"
payload = {}
client = oauthlib.oauth1.Client('consumer key', client_secret='12345',
resource_owner_key='12345', resource_owner_secret='12345', realm='12345_SB1',signature_method="HMAC-SHA256")
url, headers, body = client.sign('https://4635201-sb4.suitetalk.api.netsuite.com/services/rest/query/v1/dataset/custdataset1/result')
response = requests.request("GET", url, headers=headers, data = payload)
print(response.text.encode('utf8'))
A Few Additional Helpful Notes -
I'm testing this in Netsuite Sandbox, hence the realm "12345_SB1". If
you aren't in sandbox you shouldn't need the underscore SB. Just use your account ID.
I'm pulling Netsuite Analytics Report, which at this time is still in
beta for the new API (REST Web Services).
I used the Python oauthlib that Josh recommended and I recommend you do the same, link here
I am trying to use AWS DynamoDB in a Flutter app, and given the lack of an official AWS SDK for Dart I am forced to use the low level HTTP REST API.
The method for signing an AWS HTTP request is quite tedious, but using an AWS supplied sample as a guide, I was able to convert the Python to Dart pretty much line-for-line relatively easily. The end result was both sets of code producing the same auth signatures.
My issue came when I actually went to sent the request. The Python works as expected but sending a POST with Dart's HTTP package gives the error
The request signature we calculated does not match the signature you
provided. Check your AWS Secret Access Key and signing method. Consult
the service documentation for details.
I'll spare you the actual code for generating the auth signature, as the issue can be replicated simply by sending the same request hard-coded. See the Python and Dart code below.
Note: A valid response will return
Signature expired: 20190307T214900Z is now earlier than
20190307T215809Z (20190307T221309Z - 15 min.)
as the request signature uses current date and is only valid for 15 mins.
*****PYTHON CODE*****
import requests
headers = {'Content-Type':'application/json',
'X-Amz-Date':'20190307T214900Z',
'X-Amz-Target':'DynamoDB_20120810.GetItem',
'Authorization':'AWS4-HMAC-SHA256 Credential=AKIAJFZWA7QQAQT474EQ/20190307/ap-southeast-2/dynamodb/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-target, Signature=297c5a03c59db6da45bfe2fda6017f89a0a1b2ab6da2bb6e0d838ca40be84320'}
endpoint = 'https://dynamodb.ap-southeast-2.amazonaws.com/'
request_parameters = '{"TableName": "player-exports","Key": {"exportId": {"S": "HG1T"}}}'
r = requests.post(endpoint, data=request_parameters, headers=headers)
print('Response status: %d\n' % r.status_code)
print('Response body: %s\n' % r.text)
*****DART CODE*****
import 'package:http/http.dart' as http;
void main(List<String> arguments) async {
var headers = {'Content-Type':'application/json',
'X-Amz-Date':'20190307T214900Z',
'X-Amz-Target':'DynamoDB_20120810.GetItem',
'Authorization':'AWS4-HMAC-SHA256 Credential=AKIAJFZWA7QQAQT474EQ/20190307/ap-southeast-2/dynamodb/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-target, Signature=297c5a03c59db6da45bfe2fda6017f89a0a1b2ab6da2bb6e0d838ca40be84320'};
var endpoint = 'https://dynamodb.ap-southeast-2.amazonaws.com/';
var request_parameters = '{"TableName": "player-exports","Key": {"exportId": {"S": "HG1T"}}}';
http.post(endpoint, body: request_parameters, headers: headers).then((response) {
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
});
}
The endpoint, headers and body are literally copy and pasted between the two sets of code.
Is there some nuance to how Dart HTTP works that I am missing here? Is there some map/string/json conversion of the headers or request_paramaters happening?
One thing I did note is that in the AWS provided example it states
For DynamoDB, the request can include any headers, but MUST include
"host", "x-amz-date", "x-amz-target", "content-type", and
"Authorization". Except for the authorization header, the headers must
be included in the canonical_headers and signed_headers values, as
noted earlier. Order here is not significant. Python note: The 'host'
header is added automatically by the Python 'requests' library.
But
a) When I add 'Host':'dynamodb.ap-southeast-2.amazonaws.com' to the headers in the Dart code I get the same result
and
b) If I look at r.request.headers after the Python requests returns, I can see that it has added a few new headers (Content-Length etc) automatically, but "Host" isn't one of them.
Any ideas why the seemingly same HTTP request works for Python Requests but not Dart HTTP?
Ok this is resolved now. My issue was in part a massive user-error. I was using a new IDE and when I generated the hardcoded example I provided I was actually still executing the previous file. Stupid, stupid, stupid.
But...
I was able to sort out the actual issue that caused me raise the question in the first place. I found that if you set the content type to "application/json" in the headers, the dart HTTP package automatically appends "; charset=utf-8". Because this value is part of the auth signature, when AWS encodes the values from the header to compare to the user-generated signature, they don't match.
The fix is simply to ensure that when you are setting the header content-type, make sure that you manually set it to "application/json; charset=utf-8" and not "application/json".
Found a bit more discussion about this "bug" after the fact here.
tl;dr:
I am trying to set headers in a Python HTTP request for the first time and am getting a 404. I would appreciate any help (see bottom).
I have been experimenting with the Twitter API and have not been having much luck. Eventually I am trying to get all of the media (photos) a user has posted (20 or 50 or whatever per fetch)
In my experience with other APIs, this process would go as follows: Get The userID, Make a get request to some endpoint using that userId, get a JSON feed response.
It seems to be much more complicated in Twitter.
For instance, I do not see any URLs where I can attach an access token or client ID. Instead, in their documentation they show a place where I can retrieve my
Comsumer Key, Consumer Secret, Access Token, and, Access Token Secret
If I enter my request URI and "query", it generates an oAuth Signature, which in this case consists of a
Signature base string, Authorization header and cURL command
This is where things get confusing. It says
Important: This will only be valid for a few minutes. Also remember the cURL command will actually execute the request.
So:
Question 1: right away I am wondering how I can use these credentials to retrieve media over an entire day or a weekend if they become invalid only a few minutes later?
Question 2: Using their "exploring API" console, I can test this query (where I am trying to get the user ID for the Ford" twitter account I use GET https://api.twitter.com/1.1/users/lookup.json?screen_name=hyundai
Typing that into the browser alone returns a 404
{"errors": [{"message": "Bad Authentication data","code": 215}]}
But using their little console APP I can pick "O Auth 1 authentication" (using a twitter app I made) and I get the JSON response I want. Examining the request object in the console shows:
GET /1.1/users/lookup.json?screen_name=hyundai HTTP/1.1
Authorization:
OAuth oauth_consumer_key="555SECRET555",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1421370510",oauth_nonce="1869828628",oauth_version="1.0",oauth_token="333DONTHACKMEPLEASE333",oauth_signature="444SECRET444"
Host:
api.twitter.com
X-Target-URI:
https://api.twitter.com
Connection:
Keep-Alive
tl;dr Version:
So, I thought this was the headers object I would need to send from Python (3) to make the identical request. So here is that code:
import urllib.request
header = {
"Authorization" : "OAuth",
"oauth_consumer_key" :"555SECRET555",
"oauth_signature_method": "HMAC-SHA1",
"oauth_timestamp" : "1421362844",
"oauth_nonce":"1201915763",
"oauth_version": "1.0",
"oauth_token":"333CHANGINGTHIS33333",
"oauth_signature":"222CHANGEDTHIS222",
"Host": "api.twitter.com",
"X-Target-URI": "https://api.twitter.com",
"Connection": "Keep-Alive"
}
endpoint = 'https://api.twitter.com/1.1/users/lookup.json?screen_name=hyundai'
q = urllib.request.Request(endpoint, headers=header)
a = urllib.request.urlopen(q)
print(a.read().decode('utf-8'))
But I get a bad, 404 response.
Have I formatted my headers wrong here or is there another way to do this?
If you capture the network traffic from your request (use http not https), you will see that the headers you send are not the same as the header that are expected. This is why you are getting a 404 response.
What you want is something like
header = {
"Authorization": 'OAuth oauth_consumer_key="555SECRET555",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1421362844",oauth_nonce="1201915763",oauth_version="1.0",oauth_token="333CHANGINGTHIS33333",oauth_signature="222CHANGEDTHIS222"',
"Host": "api.twitter.com",
"X-Target-URI": "https://api.twitter.com",
"Connection": "Keep-Alive"
}
Of course, you could always use an OAuth library, such as RAuth or similar, see
Python: OAuth Library for a discussion
I have successfully inserted a moment with this procedure before and am trying to figure out if the API is currently broken or i'm making a mistake.
I have obtained a valid access_token with request_visible_actions=http://schema.org/AddAction as seen in the partial url below from the auth stage as well as plus.login scope:
https://accounts.google.com/o/oauth2/auth?access_type=offline&request_visible_actions=http%3A%2F%2Fschema.org%2FAddAction&
the request code:
import requests
import json
moment = {"type":"http://schema.org/AddAction",
"object": {"id": "object-id-1",
"type":"http://schema.org/AddAction",
"name": "The Google+ Platform",
"description": "A page that describes just how awesome Google+ is!",
"image": "https://developers.google.com/+/plugins/snippet/examples/thing.png"}}
url ='https://www.googleapis.com/plus/v1/people/me/moments/vault'
params = {'access_token': 'MY_VALID_ACCESS_TOKEN'}
r = requests.request("POST",url=url, params=params, json=moment, headers=headers)
print r.url
print r.json()
and the result:
https://www.googleapis.com/plus/v1/people/me/moments/vault?access_token=MY_ACCESS_TOKEN
{u'error': {u'code': 401,
u'message':
u'Unauthorized',
u'errors': [{u'domain': u'global', u'message': u'Unauthorized', u'reason': u'unauthorized'}]}}
I tried to verify with the tokeninfo endpoint that request_visible_actions are present, but it's not listed there.
confirmed granted scopes:
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.profile.emails.read',
'https://www.googleapis.com/auth/plus.moments.write',
'https://www.googleapis.com/auth/plus.me',
'https://www.googleapis.com/auth/plus.profile.agerange.read',
'https://www.googleapis.com/auth/plus.profile.language.read',
'https://www.googleapis.com/auth/plus.circles.members.read'
I am able to get moments/vault with the same token so i know it's valid.
Any ideas here?
The procedure shown in the question does in fact work as long as request_visible_actions=space separated list of app activity types was included when the user makes the first connection to your app and the app activity type you are trying to post was included. If you want to update the list or add the moment.insert permission after initial authentication, the user must first disconnect the app from their google+ settings and reconnect.
It seems this is a bug with google's implementation of request_visible_actions and an incremental authorization strategy.
request_visible_actions seems to only be accepted during initial authorization and disregarded after that. This makes incrementally adding this parameter impossible.
Further more, request_visible_actions is not available when calling the tokeninfo endpoint, which leads me to believe that request_visible_actions is somehow dissociated from token auth and merely an attribute assigned to the user's app connection on instantiation.
Posted to exising moments.instert 401 issue: