Jenkins Credentials Manager + Active Choices
Chcę uzyskać dostęp do poświadczeń Jenkins w celu uwierzytelnienia za pomocą Git przed skryptem potoku - w celu wypełnienia parametru Active Choices.
W przygotowaniu po prostu to robię withCredentials. Ale na etapie pre-pipeline (tj. Parametr Active Choices) rozszerzenia Hudson, takie jak withCredentialslub sshAgentnie są dostępne. Obecnie git ls-remote -h [email protected]:repo.gitwykonuję groovy z niezaszyfrowanym kluczem w katalogu jenkins_home (co nie jest dobrym pomysłem).
Wiem, że istnieje pewna możliwość importowania i konstruowania obiektów Javy poprzez czytanie kodu źródłowego Jenkina i jego wtyczek - ale wydaje się to nieskończone.
A więc: czy można w jakiś sposób łatwo zaimportować i zastosować rozszerzenia Hudson do obecnego skryptu Groovy, czy ktoś ma na to jakieś gotowe rozwiązanie (najwyraźniej nikt nie opublikował nic o takim przypadku)?
Odpowiedzi
Wydaje mi się, że już jesteś tego świadomy, ale jest na to kilka łatwych sposobów i kilka trudnych.
Proste sposoby:
- Udostępnij swoje repozytorium do płatności bez kluczy SSH lub danych uwierzytelniających.
- Ręcznie dodaj parę kluczy SSH do wyewidencjonowania repozytorium do użytkownika Jenkins w węźle głównym Jenkins (ponieważ skrypty Active Choice Groovy działają w węźle głównym) (tj. Nie używaj magazynu danych logowania).
Trudne sposoby:
- Użyj interfejsu API języka Java Jenkins w kodzie Active Choices, aby wyodrębnić poświadczenia z magazynu poświadczeń. Dokumentacja API jest dostępna dla magazynu poświadczeń i typu poświadczeń ssh . Nie ma dokumentacji na temat korzystania z klas Java dostępnych w tych wtyczkach, więc samodzielne ustalenie tego należy do Ciebie.
- Utwórz drugorzędne zadanie „meta”, aby zaktualizować parametry pierwotnego zadania Jenkinsa (w tym skrypty Active Choices) - opiszę to nieco poniżej.
Jeśli nie możesz zrobić żadnego z łatwych rozwiązań ze względów bezpieczeństwa, nie ma łatwego, prostego sposobu na aktualizację parametrów Active Choice w oparciu o zawartość repozytorium git. To dlatego, że:
- Jak powiedziałeś, „na etapie poprzedzającym potok (tj. Parametr Active Choices) rozszerzenia Hudson, takie jak withCredentials lub sshAgent, nie są dostępne”.
- Konfiguracja parametrów, w tym parametrów Active Choice, jest pobierana z poprzedniego uruchomienia tego potoku, a nie z bieżącego. Oznacza to, że aby zaktualizować parametry z poziomu kodu Pipeline, musisz uruchomić swój Pipeline, co jest sprzeczne z celem tego, co chcesz zrobić.
Istnieje rozwiązanie dla 1., które polega na użyciu skryptowych potoków zamiast deklaratywnych, ale to nie obejdzie problemu z 2.
Rozwiązaniem, które wymyśliłem, kiedy napotkałem ten problem, jest utworzenie drugiego zadania Jenkinsa (nazywam to zadaniem „meta”), które aktualizuje parametry pierwotnego zadania, w tym skrypty Active Choices. To drugie zadanie meta jest wyzwalane przez hak git w repozytorium, którego używam do wypełnienia opcji w moich parametrach Active Choices. Ma to tę zaletę, że nie trzeba uruchamiać potoku pierwotnego zadania w celu zaktualizowania jego parametrów, rozwiązując problemy w 2. Ponadto, ponieważ jest to nadal zadanie potoku, można używać normalnych kroków potoku, umożliwiając w ten sposób dostęp do magazyn poświadczeń.
Moja praca wygląda (z grubsza) tak - znacznie ją uprościłem, aby pasowała tutaj, więc będziesz musiał zrobić kilka poprawek, aby działała tak, jak chcesz. Prawdopodobnie jest w tym mnóstwo błędów i błędów, ponieważ rozerwałem istniejący skrypt, aby to zrobić. Kilka uwag:
- To powoduje duże wykorzystanie interfejsów API Jenkinsa, więc musisz albo wyłączyć piaskownicę skryptów, albo dodać do białej listy mnóstwo funkcji w menedżerze zabezpieczeń Jenkins, aby to uruchomić
- Technicznie rzecz biorąc jest to potok oparty na skryptach, mimo że wygląda bardziej jak zwykły skrypt Groovy niż plik potoku
- Ponieważ jest to potok, możesz użyć takich kroków, jak
withCredentialssprawdzanie repozytoriów przy użyciu magazynu poświadczeń.
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)