From a89622cf98de88c547bb2a93872e3bd82322c301 Mon Sep 17 00:00:00 2001 From: kireto Date: Thu, 15 Oct 2020 00:24:10 +0300 Subject: [PATCH 1/3] Preserving the cookie when requesting a crumb from crumbIssuer and then sending a post for a build. The post will include the same cookie --- lib/jenkins_api_client/client.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/jenkins_api_client/client.rb b/lib/jenkins_api_client/client.rb index cee4c2cb..054f9c28 100644 --- a/lib/jenkins_api_client/client.rb +++ b/lib/jenkins_api_client/client.rb @@ -369,6 +369,7 @@ def make_http_request(request, follow_redirect = @follow_redirects) http.read_timeout = @http_read_timeout response = http.request(request) + @cookies = response["set-cookie"] case response when Net::HTTPRedirection then # If we got a redirect request, follow it (if flag set), but don't From d585b497a94059899762925bc34038ada98e5d8b Mon Sep 17 00:00:00 2001 From: kireto Date: Thu, 15 Oct 2020 08:32:27 +0300 Subject: [PATCH 2/3] Crt, Key and get_artifact_by_path 1. Crk and Key In a jenkins instance that is behind an https proxy the certificate might be restricted only to peers that have a certificate issued by the authority. The jenkins_api_client should send the certificate issued by the authority with the call. The perpose of the :crt and :key file arguments is to allow for the client to include its crt and key file when making the request and in this way authorizing to the https service. 2. Verify model The certificate of the https service might be self-signed so I have added an option of ":verify_mode" that allows you to override the default verify_mode used to make the connections In this way existing clients will not get a different behaviour while new clients could specify their verify_mode Example for calling with crt, key and verify_mode ``` # This crt and key files could be generated with # openssl pkcs12 -in path.p12 -out newfile.crt.pem -clcerts -nokeys # openssl pkcs12 -in path.p12 -out newfile.key.pem -nocerts -nodes # This of course is only if you have p12 file. JenkinsApi::Client.new(:server_url=>the_url, crt: the_crt, key: the_key, ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE, :username=>ENV["JENKINS_USERNAME"], :password=>ENV["JENKINS_PASSWORD"]) ``` 3. get_artifcat_by_path Sometime you need to get not all the artifacts but a specific artifact. This new method allows you to. This is need when the build produces to many artifacts and you only want to download one of them as you only need one of them. --- lib/jenkins_api_client/client.rb | 37 +++++++++++++++++++++++++++++--- lib/jenkins_api_client/job.rb | 4 ++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/lib/jenkins_api_client/client.rb b/lib/jenkins_api_client/client.rb index 054f9c28..350e36c6 100644 --- a/lib/jenkins_api_client/client.rb +++ b/lib/jenkins_api_client/client.rb @@ -67,6 +67,9 @@ class Client "http_open_timeout", "http_read_timeout", "ssl", + "crt", + "key", + "verify_mode", "pkcs_file_path", "pass_phrase", "ca_file", @@ -95,6 +98,10 @@ class Client # @option args [String] :proxy_protocol the proxy protocol ('socks' or 'http' (defaults to HTTP) # @option args [String] :jenkins_path ("/") the optional context path for Jenkins # @option args [Boolean] :ssl (false) indicates if Jenkins is accessible over HTTPS + # @option args [String] :crt path to the crt pem for authenticating with Jenkins. See :key options + # @option args [String] :key path to the key pem for authenticating with Jenkins. The Crt and Key files are usefull for authenticating with untrusted host + # and would be set to http.key and http.crt + # @option args [String] :verify_mode one of OpenSSL::SSL::VERIFY_* or nil to leave for default values # @option args [String] :pkcs_file_path ("/") the optional context path for pfx or p12 binary certificate file # @option args [String] :pass_phrase password for pkcs_file_path certificate file # @option args [String] :ca_file the path to a PEM encoded file containing trusted certificates used to verify peer certificate @@ -293,6 +300,26 @@ def get_artifact(job_name,filename) end end + # Connects to the server and downloads artifacts with a given path to a specified location + # + # @param [String] job_name + # @param [String] build_number + # @param [String] artifact_path + # @param [String] filename location to save artifact + # + def get_artifact_by_path(job_name,build_number,artifact_path,filename) + build_path = job.build_path(job_name, build_number) + uri= "#{@jenkins_path}/#{build_path}/#{artifact_path}" + response = make_http_request(Net::HTTP::Get.new(uri)) + if response.code == "200" + File.open(File.expand_path(filename),"wb") do |file| + file.write(response.body) + end + else + raise "Couldn't get the artifact" + end + end + # Connects to the server and download all artifacts of a build to a specified location # # @param [String] job_name @@ -306,7 +333,7 @@ def get_artifacts(job_name, dldir, build_number = nil) @artifacts.each do |artifact| uri = URI.parse(artifact) http = Net::HTTP.new(uri.host, uri.port) - http.verify_mode = OpenSSL::SSL::VERIFY_NONE + http.verify_mode = @verify_mode || OpenSSL::SSL::VERIFY_NONE http.use_ssl = @ssl request = Net::HTTP::Get.new(uri.request_uri) request.basic_auth(@username, @password) @@ -358,11 +385,15 @@ def make_http_request(request, follow_redirect = @follow_redirects) pkcs12 =OpenSSL::PKCS12.new(File.binread(@pkcs_file_path), @pass_phrase!=nil ? @pass_phrase : "") http.cert = pkcs12.certificate http.key = pkcs12.key - http.verify_mode = OpenSSL::SSL::VERIFY_NONE + http.verify_mode = @verify_mode || OpenSSL::SSL::VERIFY_NONE elsif @ssl http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_PEER + http.cert = OpenSSL::X509::Certificate.new(@crt) if @crt + http.key = OpenSSL::PKey::RSA.new(@key) if @key + + # Why is this here a VERIFY_PEER and the rest are VERIFY_NONE? + http.verify_mode = @verify_mode || OpenSSL::SSL::VERIFY_PEER http.ca_file = @ca_file if @ca_file end http.open_timeout = @http_open_timeout diff --git a/lib/jenkins_api_client/job.rb b/lib/jenkins_api_client/job.rb index 30d7dc9c..c9289eb1 100644 --- a/lib/jenkins_api_client/job.rb +++ b/lib/jenkins_api_client/job.rb @@ -1662,6 +1662,10 @@ def find_artifact(job_name, build_number = 0) find_artifacts(job_name, build_number).first end + def build_path(job_name, build_number = 0) + "job/#{path_encode job_name}/#{build_number}" + end + #A Method to check artifact exists path from the Current Build # # @param [String] job_name From aeb2a6268d334e7d729a9ddc07c4b8643765634a Mon Sep 17 00:00:00 2001 From: Kiril Mitov Date: Sat, 10 May 2025 13:35:12 +0300 Subject: [PATCH 3/3] Moving to ruby 3 --- jenkins_api_client.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jenkins_api_client.gemspec b/jenkins_api_client.gemspec index 37061a61..f335b0bc 100644 --- a/jenkins_api_client.gemspec +++ b/jenkins_api_client.gemspec @@ -15,7 +15,7 @@ Gem::Specification.new do |s| s.files = `git ls-files -z`.split("\x0").select { |f| f.match(%r{lib/|bin/|java_deps/|gemspec}) } s.require_paths = ['lib'] s.homepage = 'https://github.com/arangamani/jenkins_api_client' - s.required_ruby_version = ::Gem::Requirement.new('~> 2.1') + s.required_ruby_version = ::Gem::Requirement.new(['>= 2.1', '< 4.0']) s.rubygems_version = "2.4.5.1" s.summary = "Jenkins JSON API Client" s.licenses = ["MIT"]