API POST request to Proxmox with params using Groovy Script in Jenkins - api

I am trying to obtain an authentication ticket using a POST request with 3 parameters(user,pass,realm) to access Proxmox API Server to be parsed for further queries.
As I am writing the code in Groovy Script for a parameter in a Jenkins job, I am not getting much help in terms of errors. I have tried the POST request on insomnia and it has no problems.
I am still very new to GroovyScript any pointers in the right direction is much appreciated.
def url = new URL("https://$HOST/api2/json/access/ticket")
def connection = url.openConnection()
connection.setDoOutput(true)
connection.setRequestMethod("POST")
connection.setRequestProperty("Content-Type", "application/json")
connection.setRequestProperty('Username', '$USER')
connection.setRequestProperty('Password', '$PASS')
connection.setRequestProperty('Realm', '$REALM')
def requestCode = connection.getResponseCode

Not need connection.setRequestProperty('Realm', '$REALM'), using Username#realm
try this, write to API:
def url = new URL("https://$HOST/api2/json/access/ticket")
def connection = url.openConnection()
connection.setDoOutput(true)
connection.setRequestMethod("POST")
connection.setRequestProperty("Content-Type", "application/json")
connection.setRequestProperty('Password', '$PASS')
connection.setRequestProperty('Username', '$USER' + '#' + '$REALM')
def requestCode = connection.getResponseCode

Related

S3 presigned URL: Generate on server, use from client?

Is it possible to generate an S3 presigned URL in a Lambda function and return that URL to a client, so the client can use it to do an unauthenticated HTTP PUT?
I'm finding that S3 is unexpectedly closing my HTTPS connection when I try to PUT to the URL I get from the lambda function, and I don't know if it's because the server and client are different entities.
Can I do what I want to do? Is there a secret step I'm missing here?
EDIT: per Anon Coward's request, the server-side code is:
presigned_upload_parts = []
for part in range(num_parts):
resp = s3.generate_presigned_url(
ClientMethod = 'upload_part',
Params = {
'Bucket': os.environ['USER_UPLOADS_BUCKET'],
'Key': asset_id,
'UploadId': s3_upload_id,
'PartNumber': part
}
)
presigned_upload_parts.append({"part": part, "url": resp})
return custom_http_response_wrapper(presigned_upload_parts)
The client-side code is:
for idx, part in enumerate(urls):
startByte = idx * bytes_per_part
endByte = min(filesize, ((idx + 1) * bytes_per_part))
f.seek(startByte, 0)
bytesBuf = f.read(endByte - startByte)
print(f"Buffer is type {type(bytesBuf)} with length {len(bytesBuf):,}")
print(f"Part {str(idx)}: bytes {startByte:,} to {endByte:,} as {part['url']}")
#resp = requests.post(part['url'], data = bytesBuf, headers = self.get_standard_headers())
resp = requests.put(
url = part['url'],
data = bytesBuf
)
The error I'm getting is:
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
The presigned URL looks like:
https://my-bucket-name.s3.amazonaws.com/my/item/key?uploadId=yT2W....iuiggs-&partNumber=0&AWSAccessKeyId=ASIAR...MY&Signature=i6duc...Mmpc%3D&x-amz-security-token=IQoJ...%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F...SWHC&Expires=1657135314
There was a bug in my code somewhere. I ran the code under WSL as a test, and in the Linux environment got a more friendly error that helped me find and fix a minor bug, and now it's running as expected in the Windows environment. Whether that's because of the bugfix or some other environmental change I'll never know.

urequests only working on specific websites

I am using a nodemcu esp8266 and the plan is to make a spotify api request to automate playing some songs, and I have a fully functional python script that does exactly that, but when I tried to convert it to upython it failed. I have now spent hours on this and have figured out that the problem is that the urequest for some reason only works on specific websites, for example if I try:
import urequests as requests
x = requests.get('https://www.spotify.com')
print(x.status_code)
i get a 302
but when I try:
import urequests as requests
x = requests.get('https://www.google.com')
print(x.status_code)
I get a 200. That problem percists with a few websites and with no valid response my urequests.put command does not return the things I need... any ideas how to fix it?
thank you in advance.
this is the code I am trying to run:
import urequests as requests
import ujson as json
refresh_token = "xxxxx"
base_64 = "xxxxx"
class Refresh:
def __init__(self):
self.refresh_token = refresh_token
self.base_64 = base_64
def refresh(self):
query = "https://accounts.spotify.com/api/token"
payload={"grant_type": "refresh_token", "refresh_token": refresh_token}
headers={'Authorization': 'Basic %s' % base_64}
data = (json.dumps(payload)).encode()
response = requests.post(query,
data=data,
headers=headers)
print(response.status_code)
print(response.reason)
a = Refresh()
a.refresh()
There are several things going on here that are going to cause your problems.
First, you're trying to send JSON data to the /api/token endpoint:
data = (json.dumps(payload)).encode()
response = requests.post(query,
data=data,
headers=headers)
...but according to the documentation, this endpoint excepts application/x-www-form-urlencoded data.
Second, while the documentation suggests you need to send a basicAuthorization header, in my experiments this evening I wasn't able to get that to work...but I was able to successfully refresh a token if I included the client id and secret in the request body.
You can see my forum post with this question here.
With that in mind, the following code seems to work on my esp8266 running micropython 1.18:
import urequests as requests
refresh_token = "..."
client_id = "..."
client_secret = "..."
class Refresh:
def __init__(self, refresh_token, client_id, client_secret):
self.refresh_token = refresh_token
self.client_id = client_id
self.client_secret = client_secret
def refresh(self):
url = "https://accounts.spotify.com/api/token"
data = "&".join(
[
"grant_type=refresh_token",
f"refresh_token={self.refresh_token}",
f"client_id={self.client_id}",
f"client_secret={self.client_secret}",
]
)
headers = {
"content-type": "application/x-www-form-urlencoded",
}
response = requests.post(url, data=data, headers=headers)
print(data)
print(response.status_code)
print(response.reason)
print(response.text)
a = Refresh(refresh_token, client_id, client_secret)
a.refresh()

Karate Test Framework -Storing credentials outside of github

I have Karate Tests for the APIs which are on Amazon API Gateway. As such, in my Karate Tests I have to provide client_id and client_secret for authentication. I was wondering if there is a way I could store the credentials outside my github repository and use it at run time. Is it possible to do that in Karate ?
Here is how my tests look like:
Feature: API Test all endpoints using Karate
Background:
* configure ssl = true
* url baseUrl
* def res = (env == 'qa'? 'classpath:endpoints/user-login.feature' : 'classpath:endpoints/user-login-dev.feature')
* def token = call read(res)
* def headerData = {Authorization: #(token.nextGen),Accept: 'application/json;v=1'}
* headers headerData
Here is the user-login.feature file
Feature: API Test using Karate
Background:
* configure ssl = true
Scenario: Get authorization header
Given url 'https://api.cloud.xyz.com/oauth2/token?client_id=****&client_secret=****&grant_type=client_credentials'
When method get
Then status 200
And def tokenType = response.token_type
And def accessToken = response.access_token
* def nextGen = tokenType + ' '+ accessToken
* def headerData = {Authorization: nextGen,Accept: 'application/json;v=1'}
Any pointers on how I can have the client_id and client_secret passed to the tests at run time and not stored in github.
Thanks in advance!
The easiest way would be to pass them as Java system properties via the command-line, which you can very easily do from a test or from a CI triggered run.
Refer to the documentation here: https://github.com/intuit/karate#dynamic-port-numbers
An example of how it could look like in your case:
Given url 'https://api.cloud.xyz.com/oauth2/token'
And param client_id = karate.properties['client.id']
And param client_secret = karate.properties['client.secret']
And param grant_type = 'client_credentials'
And on the command-line:
mvn test -DargLine="-Dclient.id=**** -Dclient.secret=**** -Dkarate.env=qa"

Why does this Python Reddit API call fail?

If someone could point me in the right direction I would be very grateful. I am trying to use the requests module to interact with Reddit's APIs, but for some reason I am getting HTTP status 403 codes. I am able to successfully log in I believe (since I get HTTP 200), but I cannot perform a successful API request. I am very new to this so please use small words. Thanks.
import requests
import json
from pprint import pprint
# URLs
url_base = r'https://www.reddit.com'
url_login = '/api/login'
url_me = '/api/v1/me'
# Credentials
user = '__kitten_mittens__'
passwd = 'password'
params = {'user': user,
'passwd': passwd,
'api_type': 'json',}
headers = {'user-agent': '/u/__kitten_mittens__ practice api bot'}
# Set up the session/headers
client = requests.session()
client.headers = headers
response = client.post(url_base + url_login, data = params)
j = json.loads(response.content.decode('utf-8'))
mh = j['json']['data']['modhash']
print("The modhash for {USER} is {mh}".format(USER=user, mh=mh))
# THIS CODE GIVES HTTP STATUS CODE 403
response = client.get(url_base + url_me)
me_json = json.loads(r.content.decode('utf-8'))
pprint(me_json)
EDIT: I fixed the missing single quote from the password field. That was not part of the problem.

how to use get method in groovyx.net.http.RESTClient properly

I'm trying to get JSON file via get method in RESTClient.
Right now I'm trying
def url = 'http://urlurlurl'
def username = 'username'
def password = 'password'
def restClient = new RESTClient(url)
restClient.auth.basic(username, password)
render restClient
When I see what I get from restClient, is just prints
'groovyx.net.http.RESTClient#65333e2e'
Which is hard to understand.
Given that the url is a endpoint of a API get method, and contains JSON file, how can I retrieve JSON file so I can parse it and use that JSON file?
Also I'm trying this too
def url = 'http://urlurlurl'
def username = 'username'
def password = 'password'
def restClient = new RESTClient(url)
restClient.auth.basic(username, password)
//Adding get method
def jsonData = restClient.get(/* what value should I put in here?? */)
This gives me a forbbiden error that says:
Error 500: Internal Server Error
URI: JsonRender
Class: groovyx.net.http.HttpResponseException
Message: Forbidden
Any suggestions? Examples that uses get method in RESTClient will be nice.
The url should be the base url for your api. For example if we want to search some data from an api which complete url is http://localhost:9200/user/app/_search. So, we have base url as http://localhost:9200/ and the path to api is user/app/_search. Now the request looks like this
def client = new RESTClient( 'http://localhost:9200/' )
def resp = client.get( path : 'user/app/_search')
log.debug (resp.getContentAsString())
Hope this will work out.
Thanks,