Jenkins Credentials Manager + Active Choices
Saya ingin mengakses Kredensial Jenkins untuk mengautentikasi dengan Git sebelum skrip pipeline - untuk mengisi parameter Active Choices.
Dalam pipeline saya hanya melakukannya dengan withCredentials. Tetapi selama tahap pra-pipa (yaitu parameter Pilihan Aktif) ekstensi Hudson seperti withCredentialsatau sshAgenttidak dapat diakses. Saat ini saya menjalankan groovy git ls-remote -h [email protected]:repo.gitdengan kunci yang tidak terenkripsi di direktori jenkins_home (yang bukan ide yang bagus).
Saya tahu bahwa ada kemungkinan untuk mengimpor dan membuat objek Java dengan membaca kode sumber Jenkin dan pluginnya - tetapi ini sepertinya tidak ada habisnya.
Jadi: apakah mungkin untuk dengan mudah mengimpor dan menerapkan ekstensi Hudson ke skrip Groovy saat ini atau apakah ada yang memiliki solusi siap untuk ini (tampaknya tidak ada yang menerbitkan sesuatu tentang kasus seperti itu)?
Jawaban
Bagi saya kedengarannya Anda sudah menyadarinya, tetapi ada beberapa cara mudah untuk melakukan ini, dan beberapa cara sulit untuk melakukan ini.
Cara mudahnya:
- Buat repo Anda tersedia untuk pembayaran tanpa kunci SSH atau kredensial autentikasi.
- Tambahkan secara manual pasangan kunci SSH untuk checkout repo ke pengguna Jenkins pada node master Jenkins Anda (karena skrip Active Choice Groovy berjalan pada node master) (yaitu, jangan gunakan penyimpanan Kredensial).
Cara yang sulit:
- Gunakan Jenkins Java API di kode Active Choices Anda untuk mengekstrak kredensial dari penyimpanan kredensial. Dokumen API tersedia untuk penyimpanan kredensial dan jenis kredensial ssh . Tidak ada dokumentasi tentang cara menggunakan kelas Java yang tersedia di plugin ini, jadi terserah Anda untuk mencari tahu sendiri.
- Buat pekerjaan "meta" sekunder untuk memperbarui parameter dalam pekerjaan Jenkins asli (termasuk skrip Pilihan Aktif) - Saya menjelaskannya sedikit di bawah.
Jika Anda tidak dapat melakukan solusi mudah apa pun karena alasan keamanan, tidak ada cara yang mudah dan langsung untuk memperbarui parameter Pilihan Aktif berdasarkan konten repo git. Hal ini karena:
- Seperti yang Anda katakan, "selama tahap pra-jalur (yaitu parameter Pilihan Aktif) ekstensi Hudson seperti withCredentials atau sshAgent tidak dapat diakses".
- Konfigurasi untuk parameter, termasuk parameter Choice Aktif, diambil dari sebelumnya menjalankan yang Pipeline, tidak satu saat ini. Artinya, untuk memperbarui parameter Anda dari dalam kode Pipeline, Anda harus menjalankan Pipeline Anda, yang mengalahkan poin dari apa yang ingin Anda lakukan.
Ada solusi untuk 1., yaitu menggunakan Scripted Pipelines dan bukan Declarative, tetapi itu tidak akan mengatasi masalah 2.
Solusi yang saya dapatkan saat mengalami masalah ini adalah membuat pekerjaan Jenkins kedua (saya menyebutnya pekerjaan "meta") yang memperbarui parameter pekerjaan asli, termasuk skrip Pilihan Aktif. Pekerjaan meta kedua ini dipicu oleh git hook di repositori yang saya gunakan untuk mengisi opsi di parameter Active Choices saya. Keuntungannya adalah Anda tidak perlu menjalankan Pipeline tugas asli untuk memperbarui parameternya, menyelesaikan masalah di 2. Selain itu, karena ini masih merupakan tugas Pipeline, Anda dapat menggunakan langkah Pipeline normal, sehingga memungkinkan Anda untuk mengakses penyimpanan kredensial.
Pekerjaan saya terlihat (kira-kira) seperti ini - Saya banyak menyederhanakannya agar pas di sini, jadi Anda perlu melakukan banyak penyesuaian agar berfungsi sesuai keinginan Anda. Mungkin ada banyak kesalahan dan bug dalam hal ini karena saya merobek skrip yang ada untuk membuat ini. Beberapa hal yang perlu diperhatikan:
- Hal ini membuat banyak penggunaan Jenkins API, jadi Anda harus menonaktifkan kotak pasir skrip atau mengizinkan banyak fungsi di manajer keamanan Jenkins untuk menjalankannya
- Secara teknis ini masih merupakan Scripted Pipeline meskipun lebih terlihat seperti script Groovy normal daripada file Pipeline
- Karena ini adalah Pipeline, Anda dapat menggunakan langkah-langkah seperti
withCredentialsmemeriksa repositori menggunakan penyimpanan kredensial.
import groovy.json.JsonOutput
import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript
import org.biouno.unochoice.*
import org.biouno.unochoice.model.*
def metadataUrl = 'ssh://git@**************/metadata.git'
def metadataBranch = 'master'
def metadata = [:]
node('master') {
git(
url: metadataUrl,
branch: metadataBranch,
credentialsId: 'jenkins',
changelog: false,
)
def dataDir = "${pwd()}/myJsonFiles" // can't use File.eachFileMatch() due to: // https://wiki.jenkins.io/display/JENKINS/Pipeline+CPS+method+mismatches def files = new File(dataDir).list().findAll() { f-> FilenameUtils.getExtension(f) == 'json' } files.each() { f-> // TODO: nice error messages if files are misformatted def name = FilenameUtils.removeExtension(f) def data = readJson(file: "${dataDir}/${f}") metadata[name] = data } } // ChoiceParameterDefinition is the class name for the built-in static choice parameter. // CascadeChoiceParameter is the class name for the Active Choices dynamic choice parameter. // begin first parameter def fileParam = new ChoiceParameterDefinition( 'file', 'The JSON file to use', ) fileParam.setChoices(metadata.keySet()) // end first parameter // begin second parameter def metadataJson = JsonOutput.toJson(metadata) def scriptText = """ import groovy.json.JsonSlurper def slurper = new JsonSlurper() def metadata = slurper.parseText('${metadataJson}')
return metadata[file]['versions']
"""
def mainScript = new SecureGroovyScript(scriptText, true)
def fallbackScript = new SecureGroovyScript('return ["Error encountered - see logs"]', true)
def activeChoiceScript = new GroovyScript(mainScript, fallbackScript)
def versionParam = new CascadeChoiceParameter(
'version',
'The version to use',
activeChoiceScript,
'PT_SINGLE_SELECT',
'file',
false,
)
// end second parameter
def paramProp = new ParametersDefinitionProperty(fileParam, versionParam)
// this is the full name of the actual job which needs dynamic parameters
def job = Jenkins.instance.getItemByFullName('UNIX/deploy_to_environment/master')
// There is no "setProperty" - we need to remove and replace.
// removeProperty is safe to run even if no matching properties are set on the job.
// However, this method only removes one property per method call.
// Theoretically, this means the job could accumulate multiple conflicting
// ParametersDefinitionProperty properties.
// TODO: run removeProperty in a while loop to eliminate all matching properties for extra safety.
job.removeProperty(ParametersDefinitionProperty)
job.addProperty(paramProp)