Skrypty Jenkins CI Pipeline nie mogą używać metody groovy.lang.GroovyObject

105

Używam Jenkinsa 2 do kompilowania projektów Java, chcę przeczytać wersję z pom.xml, postępowałem zgodnie z tym przykładem:

https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md

Przykład sugeruje:

Pełny potok Jenkinsa z problematyczną funkcją w kółku

Wygląda na to, że występuje problem z bezpieczeństwem dostępu do systemu plików, ale nie mogę dowiedzieć się, co powoduje (lub dlaczego) ten problem:

Robię trochę inaczej niż na przykładzie:

def version() {
    String path = pwd();
    def matcher = readFile("${path}/pom.xml") =~ '<version>(.+)</version>'
    return matcher ? matcher[0][1] : null
}

Błąd, który otrzymuję podczas uruchamiania metody „wersja”:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object (org.codehaus.groovy.runtime.GStringImpl call org.codehaus.groovy.runtime.GStringImpl)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.StaticWhitelist.rejectMethod(StaticWhitelist.java:165)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:117)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:103)
    at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:149)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:146)
    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:15)
    at WorkflowScript.run(WorkflowScript:71)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:55)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:106)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:79)
    at sun.reflect.GeneratedMethodAccessor408.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:100)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:79)
    at sun.reflect.GeneratedMethodAccessor408.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:106)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:79)
    at sun.reflect.GeneratedMethodAccessor408.invoke(Unknown Source)

Używam tych wersji: Plugin Pipeline 2.1 Jenkins 2.2

Daniel Hernández
źródło
Miałem podobny błąd co do Scripts not permitted to use method, ale stało się to dlatego, że scm 'checkout'zamiast napisałem checkou scm. Na wypadek gdyby ktoś na to wpadł, uważaj na złą składnię :). Postępowanie tak, jak powiedział Maarten Kieft, pozwoliło mi zobaczyć wyraźniejszy komunikat o błędzie dotyczący złego polecenia :)
GabLeRoux

Odpowiedzi:

263

Szybka naprawa

Miałem podobny problem i rozwiązałem go, wykonując następujące czynności

  1. Przejdź do jenkins> Manage jenkins> In-process Script Approval
  2. Było oczekujące polecenie, które musiałem zatwierdzić.

Link do zatwierdzenia procesu w Jenkins 2.61 Alternatywa 1: Wyłącz piaskownicę

Jak szczegółowo wyjaśniono w tym artykule , świetne skrypty są domyślnie uruchamiane w trybie piaskownicy. Oznacza to, że podzbiór groovy metod może działać bez zgody administratora. Możliwe jest również uruchamianie skryptów poza trybem piaskownicy, co oznacza, że ​​cały skrypt musi zostać od razu zatwierdzony przez administratora. Uniemożliwia to użytkownikom zatwierdzanie każdej linii w tym czasie.

Uruchamianie skryptów bez piaskownicy można wykonać, odznaczając to pole wyboru w konfiguracji projektu tuż pod skryptem: wprowadź opis obrazu tutaj

Alternatywa 2: Wyłącz zabezpieczenia skryptów

Jak wyjaśniono w tym artykule , możliwe jest również całkowite wyłączenie zabezpieczeń skryptów. Najpierw zainstaluj wtyczkę bezpieczeństwa skryptów permissive, a następnie zmień plik jenkins.xml, dodaj następujący argument:

-Dpermissive-script-security.enabled = true

Więc plik jenkins.xml będzie wyglądał mniej więcej tak:

<executable>..bin\java</executable>
<arguments>-Dpermissive-script-security.enabled=true -Xrs -Xmx4096m -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar "%BASE%\jenkins.war" --httpPort=80 --webroot="%BASE%\war"</arguments>

Upewnij się, że wiesz, co robisz, jeśli to wdrożysz!

Maarten Kieft
źródło
1
To, czy zatwierdzenie całego scenariusza jest lepsze, zależy od struktury zespołu. Dla kilku programistów z pełnym dostępem jest to całkiem przyjemne. Ale konfiguracja z wieloma zespołami zmusiłaby administratorów do zatwierdzania każdej zmiany we wszystkich skryptach potoku.
Roger Lehmann
3
Alternatywą 3 (powinna być naprawdę pierwsza sugestia) jest zmiana problematycznego kodu spoza białej listy . W takim przypadku wystarczy proste użycie @NonCPSdo Matcherużycia. W tym przypadku nie ma potrzeby wyłączania zabezpieczeń dla całego rurociągu, a zwłaszcza całej instalacji Jenkins. Oceń każde zablokowane połączenie indywidualnie i zdecyduj, czy naprawdę musisz je zatwierdzić.
mkobit,
1
@mkobit nie działa dla mnie. @NonCPSnie pomaga.
warvariuc
@warvariuc hmm, może tak być, jeśli zwracasz Matchersię, ponieważ Matchernie implementuje Serializableinterfejsu. Warto zadać nowe pytanie. Chciałbym, aby dokumentacja, o której mowa w pierwotnym pytaniu, została zachowana i nie była błędna.
mkobit
2
@mkobit Udekorowałem NonCPS funkcją, która używa currentBuild.rawBuild.getCause(Cause.UserIdCause).getUserId(). NonCPS w ogóle nie pomaga w kwestiach bezpieczeństwa, z tego co przeczytałem.
warvariuc
12

Musisz wyłączyć piaskownicę dla Groovy w konfiguracji zadania.

Obecnie nie jest to możliwe w przypadku projektów wielobranżowych, w których groovy skrypt pochodzi ze scm. Więcej informacji można znaleźć pod adresem https://issues.jenkins-ci.org/browse/JENKINS-28178

Andre
źródło
6

Wpadłem na to, gdy zmniejszyłem liczbę parametrów wejściowych użytkownika w userInput z 3 do 1. To zmieniło typ wyjścia zmiennej userInput z tablicy na prymityw.

Przykład:

myvar1 = userInput['param1']
myvar2 = userInput['param2']

do:

myvar = userInput
znak
źródło
To jest dokładnie poprawka dla objawu, którego doświadczyłem. Komunikat o błędzie to org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object. Metoda oczekiwała 2 parametrów i otrzymywała 3.
Tyler W
4

Aby ominąć piaskownicę przechowywanych w SCM skryptów Groovy, polecam uruchomienie skryptu jako Groovy Command (zamiast pliku Groovy Script ):

import hudson.FilePath
final GROOVY_SCRIPT = "workspace/relative/path/to/the/checked/out/groovy/script.groovy"

evaluate(new FilePath(build.workspace, GROOVY_SCRIPT).read().text)

w takim przypadku groovy skrypt jest przenoszony z obszaru roboczego do Jenkins Master, gdzie można go wykonać jako plik system Groovy Script. Piaskownica jest pomijana, o ile opcja Użyj Groovy Sandbox nie jest zaznaczona .

Stepan Vavra
źródło
5
Wydaje się to niezgrabne, ryzykowne i na pewno wróci i cię ugryzie.
Simon Forsberg
4
Cóż, bezpieczeństwo jest ważne, zwłaszcza gdy chroni wrażliwe dane użytkownika, ale wiąże się również z kosztami, takimi jak komplikacje podczas procesu tworzenia. Gdy narzędzia bezpieczeństwa są zaimplementowane w połowie, sytuacja jest jeszcze gorsza. Piaskownica skryptów Jenkinsa jest dobrym przykładem w połowie zaimplementowanego narzędzia zabezpieczającego, w wyniku czego może być konieczne całkowite wyłączenie tej funkcji, ponieważ w przeciwnym razie oznacza to, że nie pójdziesz za tobą.
Stepan Vavra
3
W moim przypadku, po aktualizacji ze starszego Jenkinsa, mój skrypt Groovy przestał działać i jedynym sposobem, aby to zadziałało, byłoby uruchomienie skryptu 300 razy (tylko oszacowanie) i dla każdego uruchomienia kliknięcie w interfejsie użytkownika Jenkinsa, aby zezwolić wszystkie wywołania metody w skrypcie zawierającym 200 linii. Ponadto interfejs użytkownika nie pozwala na wklejenie pełnej listy wszystkich dozwolonych wywołań metod na wypadek, gdybyś był w stanie je w jakiś sposób wygenerować. Ponadto interfejs użytkownika przestał wyświetlać niektóre wywołania metod i po pewnym czasie nie mogłem kontynuować.
Stepan Vavra,