module PWN::Plugins::Jenkins
def self.add_job_to_nested_view(opts = {})
job_name: 'required view path attach to a view',
view_path: 'required view path associate job',
jenkins_obj: 'required jenkins_obj returned from #connect method',
PWN::Plugins::Jenkins.add_job_to_nested_view(
Supported Method Parameters::
def self.add_job_to_nested_view(opts = {}) jenkins_obj = opts[:jenkins_obj] view_path = opts[:view_path].to_s.scrub job_name = opts[:job_name].to_s.scrub jenkins_obj.api_post_request("#{view_path}/addJobToView?name=#{job_name}") rescue StandardError => e raise e end
def self.authors
def self.authors st.pentest@0dayinc.com>
def self.clear_build_queue(opts = {})
def self.clear_build_queue(opts = {}) [:jenkins_obj] list.each do |job_name| learing #{job_name} Build from Queue") stop_build(job_name) => e
def self.connect(opts = {})
def self.connect(opts = {}) .to_i ||= 8888 sername].to_s.scrub ri = "https://#{ip}/ase/services".to_s.scrub i_key].to_s.scrub ts[:identity_file].to_s.scrub opts[:ssl] ||= false [:proxy]) proxy.scheme .host xy.port ging into Jenkins Server: #{ip}") && api_key == '' == '' JenkinsApi::Client.new( p, port, ects: true, l, ol: proxy_protocol, oxy_ip, proxy_port JenkinsApi::Client.new( p, port, e: identity_file, ects: true, l, ol: proxy_protocol, oxy_ip, proxy_port lugins::AuthenticationHelper.mask_password if api_key == '' nkinsApi::Client.new( ort, name, key, ts: true, : proxy_protocol, y_ip, oxy_port .wait_for_ready => e
def self.copy_job_no_fail_on_exist(opts = {})
def self.copy_job_no_fail_on_exist(opts = {}) [:jenkins_obj] = opts[:existing_job_name] s[:new_job_name] nkins_obj.job.copy(existing_job_name, new_job_name) xceptions::JobAlreadyExists => e kins job: #{new_job_name} already exists") => e
def self.create_nested_view(opts = {})
def self.create_nested_view(opts = {}) [:jenkins_obj] view_name].to_s.scrub h = opts[:create_in_view_path].to_s.scrub eter for modes and use case statement to build dynamically post_body lugins.nested_view.NestedView' # Requires Jenkins Nested View Plugin to Work Properly el.ListView' ame, _name, r = [ _arr.include?(create_in_view_path) reating Nested View in /...') bj.api_post_request( reating Nested View in #{create_in_view_path}...") ath would be '/view/Projects/PROJECT_NAME/view/RELEASES' out of the Jenkins URI when residing in the view in which eate your view...simply drop the domain name. bj.api_post_request( iew_path}/createView", xceptions::ViewAlreadyExists => e kins view: #{view_name} already exists") => e
def self.create_ssh_credential(opts = {})
def self.create_ssh_credential(opts = {}) [:jenkins_obj] sername].to_s.scrub opts[:private_key_path].to_s.strip.chomp.scrub pts[:key_passphrase].to_s.scrub ts[:credential_id].to_s.scrub [:description].to_s.scrub o_s.strip.chomp.scrub == 'GLOBAL' || opts[:domain].nil? dentials/store/system/domain/_/createCredentials' omain].to_s.strip.chomp.scrub dentials/store/system/domain/#{domain}/createCredentials" _s.strip.chomp.scrub == 'SYSTEM' = '' ' => { scope, => username, ySource' => { -class' => 'com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource', Key' => File.read(private_key_path) e' => key_passphrase, on' => description, lass' => 'com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey' ' => { scope, => username, ySource' => { -class' => 'com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource', Key' => File.read(private_key_path) e' => key_passphrase, edential_id, on' => description, lass' => 'com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey' .api_post_request( => e
def self.create_user(opts = {})
def self.create_user(opts = {}) [:jenkins_obj] sername].to_s.scrub assword].to_s.scrub ugins::AuthenticationHelper.mask_password if password == '' ullname].to_s.scrub l].to_s.scrub ername, assword, assword, llname, , username, password, password, fullname, il ating #{username}...") .api_post_request( createAccountByAdmin', :Exceptions::UserAlreadyExists => e enkins view: #{view_name} already exists") => e
def self.delete_jobs_by_regex(opts = {})
def self.delete_jobs_by_regex(opts = {}) [:jenkins_obj] x].to_s.scrub st_all_with_details.each do |job| name'] h?(/#{regex}/) "Deleting #{job_name}") b.delete(job_name) => e
def self.disable_jobs_by_regex(opts = {})
def self.disable_jobs_by_regex(opts = {}) [:jenkins_obj] x].to_s.scrub st_all_with_details.each do |job| name'] h?(/#{regex}/) "Disabling #{job_name}") b.disable(job_name) => e
def self.disconnect(opts = {})
def self.disconnect(opts = {}) [:jenkins_obj] connecting from Jenkins...') => e
def self.get_all_job_git_repos(opts = {})
def self.get_all_job_git_repos(opts = {}) [:jenkins_obj] rieving a List of Git Repos from Every Job...') st_all_with_details.each do |job| kogiri::XML(jenkins_obj.job.get_config(job['name'])) this_config.xpath('//scm/userRemoteConfigs/hudson.plugins.git.UserRemoteConfig/url').text = this_config.xpath('//scm/branches/hudson.plugins.git.BranchSpec/name').text _repo == '' s' git repos } me] = job['name'] l] = job['url'] b_state] = job['color'] t_repo] = this_git_repo t_branch] = this_git_branch nfig_xml_response] = this_config h(job_git_repo) => e
def self.help
def self.help self}.connect( host/ip of Jenkins Server', l tcp port (defaults to 8080), ional username (functionality will be limited if ommitted)', onal api_key (functionality will be limited if ommitted)', 'optional ssh private key path to AuthN w/ Jenkins PREFERRED over username/api_key', connect over TLS (defaults to true), al debug proxy rest api requests to jenkins (e.g. "http://127.0.0.1:8080")'' .public_methods ser( required - jenkins_obj returned from #connect method', uired - user to create', ional - password for new user (will prompt if nil)' uired - full name of new user' ed - email address of new user' sh_credential( required - jenkins_obj returned from #connect method', uired - username for new credential' th: 'required - path of private ssh key for new credential' : 'optional - private key passphrase for new credential' 'optional but recommended - useful when creating userland jobs', optional - description of new credential' nal - defaults to GLOBAL', al - GLOBAL or SYSTEM (defaults to GLOBAL)' {self}.get_all_job_git_repos( required jenkins_obj returned from connect method' s = #{self}.get_all_git_repo_branches_by_commit_date( required jenkins_obj returned from #connect method', uired jenkins job name', ired git url for git_repo' = #{self}.list_nested_jobs( required jenkins_obj returned from #connect method', quired view path list jobs' = #{self}.list_nested_views( required jenkins_obj returned from #connect method', quired view path list sub-views' l = #{self}.create_nested_view( required jenkins_obj returned from #connect method', quired view path create', _path: 'optional creates nested view within an existing nested view, defaults to / views' d_view_resp = #{self}.add_job_to_nested_view( required jenkins_obj returned from #connect method', quired view path associate job', uired view path attach to a view', #{self}.copy_job_no_fail_on_exist( required jenkins_obj returned from #connect method', ame: 'required existing job to copt to new job', 'required name of new job' jobs_by_regex( required jenkins_obj returned from #connect method', ed regex pattern for matching jobs to disable e.g. :regex => "^M[0-9]"', ob_by_regex( required jenkins_obj returned from #connect method', ed regex pattern for matching jobs to disable e.g. :regex => "^M[0-9]"', ild_queue( required jenkins_obj returned from #connect method', ct( required jenkins_obj returned from connect method'
def self.list_nested_jobs(opts = {})
def self.list_nested_jobs(opts = {}) [:jenkins_obj] view_path].to_s.scrub jenkins_obj.api_get_request(view_path) jobs'] => e
def self.list_nested_views(opts = {})
def self.list_nested_views(opts = {}) [:jenkins_obj] view_path].to_s.scrub jenkins_obj.api_get_request(view_path) views'] => e