http_request succeeds but Groovy code gets 401 - jenkins

I was using the HTTP Request Plugin to make an API call to my Bitbucket server.
The following call returns the desired result:
def my-url = "http://my-username:my-password#my-bitbucket-server.com:7990/rest/api/1.0/my-project/pull-request-10"
def response = http_request my-url
However, I had an issue with the HTTP Request Plugin, because it prints my password in plain text in the logs.
Therefore, I tried doing the same call from a groovy script:
def response = new URL(my-url).getText()
But for this I am getting a 401 server response.
Any idea why this time, the call fails?

You're trying to apply Basic auth using almost plain Java. You have to generate your auth key and attach it to the request headers. Try:
String addr = 'my-bitbucket-server.com:7990/rest/api/1.0/my-project/pull-request-10'
String authString = 'my-username:my-password'.getBytes().encodeBase64().toString()
def conn = addr.toURL().openConnection()
conn.setRequestProperty( "Authorization", "Basic ${authString}" )
def feed = new XmlSlurper().parseText( conn.content.text )
Hope this would help!

Related

403 error HTTP GET request to Jenkins build /api/json

In Jenkins, I am trying to access the change set of a pipeline build by making a HTTP GET call. However I get a 403 error. Please note I am able to access this url in the browser so I know it exists and that the url is working.
The url I am trying to access is the "build url" and then appending "/api/json".
try {
def username = 'username'
def token = 'token'
def apiUrl = 'https://<jenkins-root>/job/<job-name>/<build-number>/api/json'
HttpURLConnection connection = (HttpURLConnection) new URL(apiUrl).openConnection()
def encoded = Base64.getEncoder().encodeToString((username+":"+token).getBytes("UTF-8"))
connection.setRequestProperty("Authorization", "Bearer " + token)
connection.setRequestProperty("Content-Type", "application/json")
def returnedData = connection.inputStream.text
} catch (Exception ex) {
println ex
}
When running the above code, I am getting the following error.
java.io.IOException: Server returned HTTP response code: 403 for URL: https://my-jenkins-build-url/api/json
Since it's 403 error, I can assume I am authenticated but somehow forbidden to access /api/json of the build? Does anyone have a working way of being able to access /api/json of a jenkins build using http call?

Issue making JWT token for use with Rails and rest-client gem

I'm new to Rails and I'm using rest-client to make outbound requests. It's easy to get successful results for a simple call like this:
#obj = RestClient.get 'https://jsonplaceholder.typicode.com/posts/1'
I need to hit a real endpoint and send a header with a jwt token (using ruby-jwt). According to the JWT readme, the content of the header should look like this:
Authorization: Bearer <token>
So I have some code to use a secret to make that token (and I confirmed the resulting token is valid) and put it into a headers variable, but I'm unsure about the syntax on that headers line, and whether it's right to use strings:
def build_headers (secret)
jwt_token = make_signed_JWT_token(secret)
headers = ("Authorization: Bearer "+ jwt_token)
return headers
end
Running it produces a 'headers' value like this:
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzIxMTc3MjF9.dP2k1oPwjna5HdrnFeSqiVfR0Fz6J1ZlupfXMsPtFKw
I include that in my rest-client invocation like so:
#obj = RestClient.get(path, headers)
I'm no longer get a 401 Unauthorized error, but no celebrating yet; we appear to jump out of the code block at that line, with this exception:
undefined method `delete_if' for #<String:0x007f9e4de410b8>
Looking in the rest-client code, there is exactly one block that uses delete_if, whose purpose is to find and extract/remove "params" key if the value is a Hash/ParamsArray:
headers.delete_if do |key, value|
if key.to_s.downcase == 'params' &&
(value.is_a?(Hash) || value.is_a?(RestClient::ParamsArray))
if url_params
raise ArgumentError.new("Multiple 'params' options passed")
end
url_params = value
true
else
false
end
So my error suggests that it found something in this forbidden format and is trying to delete it, but that delete method isn't defined to act on a String. My best hunch is that there's something the matter with that headers item I created, but reading around I'm not finding more clues. Has anyone seen this before, or know if my jwt/header should be different?
You are passing a string where a hash is expected. Try this:
def build_headers (secret)
jwt_token = make_signed_JWT_token(secret)
headers = { authorization: "Bearer "+ jwt_token }
return headers
end

Rest Assured basic auth issue

I have an endpoint which works perfectly fine when I use Postman with Basic Auth. However, when I tried it in Rest Assured it returns 401. I have tried both different auth methods in rest assured and none of them worked for me so far. Need help!
RequestSpecification requestSpec;
String baseURI = "http://qa3-phoenix.labcorp.com";
String basePath = "/phx-rest/healthcheck/ping";
RestAssured.useRelaxedHTTPSValidation();
RestAssured.baseURI = baseURI;
requestSpec = new RequestSpecBuilder()
.setContentType(ContentType.JSON)
.build();
Response response = RestAssured
.given()
.spec(requestSpec)
.auth().basic("username","password")
.when()
.get(basePath)
.then()
.extract().response();
One can use directly the Authorization header with base64 encoded username and password and omit the auth() part.
Code example:
String authBasic = Base64.encode(String.format("%s:%s", username, password));
rest()
.header("Authorization", String.format("Basic %s", authBasic))
useRelaxedHTTPSValidation() is a workaround when the server is not using a valid certificate or you bump into SSLPeerUnverifiedException. In most of the scenarios this does not happen.
So try removing useRelaxedHTTPSValidation().
Can you also try the below approach:
While creating your RequestSpecification, can you add an object of authentication scheme to your RequestSpecification and then use that to create http requests.
RequestSpecBuilder req = new RequestSpecBuilder();
PreemptiveBasicAuthScheme auth = new PreemptiveBasicAuthScheme();
auth.setUserName("");
auth.setPassword("");
req.setAuth(auth);
req.build();
May be you can think of creating your RequestSpec from a separate class or package for better re-use.
Let me know if this helps, or the stacktrace.

Send JSON data as post method from rails controller to a web service

I am trying to send some json data from my controller written in rails to a java webservice.
On form submission i take all the input fields data do some procession on it and convert it into json object using to_json.
But how can i send it to java webservice
http://localhost:8080/exim/jsonToMapService?jsonData={"key":"value"}
You can use net/http. (as #Pierre wrote, you should create a class in lib folder, and put there your function)
url = URI.parse(service_url)
headers = {"host" => URL }
req = Net::HTTP::Post.new(url.path)
req["Content-Type"] = "application/json"
req["Accept"] = "application/json"
req.body = JSON.generate(some_data)
con = Net::HTTP.new(url.host, url.port)
# ssl for https
if full_url.include?("https")
con.use_ssl = true
con.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
res = con.start {|http| http.request(req) }
To do things like this I suggest using either RestClient or Faraday. Howeve I strongly suggest not doing the HTTP call in your controller.
Using RestClient, it would look like this:
RestClient.get('http://localhost:8080/exim/jsonToMapService', { key: :value })
You should create a class to extract this logic in the lib folder for example.
As #eightbitraptor mentioned it, when performing HTTP request like above, you should avoid blocking by performing them in a background process like Delayed Job, Resque or Sideqik.

Mailgun, Groovy HTTPBuilder and problems with HTTP Basic authentication

Looks like HTTPBuilder's behavior goes wrong when the server / api endpoint does not give a proper response. Mailgun's API does not respond 401, but instead gives something else. (Correct me if I'm wrong!)
The fact that there are no "Authentication required" headers sent, HTTPBuilder will not even try to authenticate.
I think I got the problem solved by the help of this thread: http://groovy.329449.n5.nabble.com/HTTPBuilder-Strange-behaviour-of-auth-basic-td344479.html
They suggest, that writing the authentication header manually will force the authentication each time. Needed to modify that a bit so it looks like this:
def user = 'tom'
def pass = 'secret'
def http = new HTTPBuilder('http://myhost.com')
http.headers[ 'Authorization' ] = "Basic " + "$user:$pass".getBytes('iso-8859-1').encodeBase64()
Seems to work now. Any better ideas? This looks like and perhaps is a hack.
Try to use something like:
def authSite = new HTTPBuilder( 'https://some-protected-site.com/' )
authSite.auth.basic 'myUserName', 'myPassword'
Read more at: http://groovy.codehaus.org/modules/http-builder/doc/auth.html

Resources