diff --git a/Jenkinsfile b/Jenkinsfile index 688a641ff..3765128a6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,4 +1,4 @@ buildPlugin(useAci: true, configurations: [ - [ platform: "windows", jdk: "8" ], + [ platform: "windows", jdk: "11" ], [ platform: "linux", jdk: "11" ] ]) diff --git a/pom.xml b/pom.xml index 30b43be52..783f0ea2d 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 4.40 + 4.47 @@ -16,7 +16,8 @@ https://github.com/jenkinsci/${project.artifactId}-plugin 999999-SNAPSHOT - 2.332.1 + + 2.366-rc32795.df5b_49c75b_0e jenkinsci/${project.artifactId}-plugin @@ -50,8 +51,8 @@ io.jenkins.tools.bom - bom-2.332.x - 1289.v5c4b_1c43511b_ + bom-2.361.x + 1607.va_c1576527071 import pom diff --git a/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SecureGroovyScript.java b/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SecureGroovyScript.java index 1c28e60d3..6a7ca1e72 100644 --- a/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SecureGroovyScript.java +++ b/src/main/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SecureGroovyScript.java @@ -33,6 +33,7 @@ import hudson.model.AbstractDescribableImpl; import hudson.model.Descriptor; import hudson.model.Item; +import hudson.model.Run; import hudson.model.TaskListener; import hudson.util.FormValidation; import io.jenkins.lib.versionnumber.JavaSpecificationVersion; @@ -437,7 +438,16 @@ public Object evaluate(ClassLoader loader, Binding binding, @CheckForNull TaskLi memoryProtectedLoader = new CleanGroovyClassLoader(loader); loaderF.set(sh, memoryProtectedLoader); } - return sh.evaluate(ScriptApproval.get().using(script, GroovyLanguage.get())); + String origin = "UNKNOWN"; + if (binding.hasVariable("build")) { + Run run = (Run) binding.getVariable("build"); + + origin = String.format("build '%s'", run.getExternalizableId()); + } else { + LOGGER.log(Level.INFO, "Could not determine origin of the groovy script - missing implementation. Please open an issue for this!"); + } + + return sh.evaluate(ScriptApproval.get().using(script, GroovyLanguage.get(), origin)); } } finally { diff --git a/src/main/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApproval.java b/src/main/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApproval.java index 9342ae1b4..8a0f2f1c5 100644 --- a/src/main/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApproval.java +++ b/src/main/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApproval.java @@ -27,6 +27,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import jenkins.model.GlobalConfiguration; import jenkins.model.GlobalConfigurationCategory; +import jenkins.model.ScriptListener; import jenkins.util.SystemProperties; import net.sf.json.JSONArray; import net.sf.json.JSONObject; @@ -475,12 +476,27 @@ public String configuring(@NonNull String script, @NonNull Language language, @N * @param script a possibly unapproved script * @param language the language in which it is written * @return {@code script}, for convenience - * @throws UnapprovedUsageException in case it has not yet been approved + * @throws UnapprovedUsageException in case it has not yet been approve + * @deprecated Use {@link #using(String, Language, String)}. */ + @Deprecated public synchronized String using(@NonNull String script, @NonNull Language language) throws UnapprovedUsageException { + return using(script, language, "N/A"); + } + /** + * Called when a script is about to be used (evaluated). + * @param script a possibly unapproved script + * @param language the language in which it is written + * @param origin A descriptive, trackable identifier of the entity running the script. + * @return {@code script}, for convenience + * @throws UnapprovedUsageException in case it has not yet been approved + */ + public synchronized String using(@NonNull String script, @NonNull Language language, String origin) throws UnapprovedUsageException { if (script.length() == 0) { // As a special case, always consider the empty script preapproved, as this is usually the default for new fields, // and in many cases there is some sensible behavior for an emoty script which we want to permit. + ScriptListener.fireScriptEvent(script, origin, null); + return script; } String hash = hash(script, language.getName()); @@ -488,9 +504,9 @@ public synchronized String using(@NonNull String script, @NonNull Language langu // Probably need not add to pendingScripts, since generally that would have happened already in configuring. throw new UnapprovedUsageException(hash); } + ScriptListener.fireScriptEvent(script, origin, null); return script; } - // Only for testing synchronized boolean isScriptHashApproved(String hash) { return approvedScriptHashes.contains(hash); diff --git a/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SecureGroovyScriptTest.java b/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SecureGroovyScriptTest.java index 31c30c5f0..76dd85257 100644 --- a/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SecureGroovyScriptTest.java +++ b/src/test/java/org/jenkinsci/plugins/scriptsecurity/sandbox/groovy/SecureGroovyScriptTest.java @@ -198,7 +198,7 @@ public class SecureGroovyScriptTest { assertEquals(0, pendingScripts.size()); // Test that the script is executable. If it's not, we will get an UnapprovedUsageException - assertEquals(groovy, ScriptApproval.get().using(groovy, GroovyLanguage.get())); + assertEquals(groovy, ScriptApproval.get().using(groovy, GroovyLanguage.get(), "Testing")); } /** @@ -243,7 +243,7 @@ public class SecureGroovyScriptTest { // We didn't add the approved classpath so ... final UnapprovedUsageException e = assertThrows(UnapprovedUsageException.class, - () -> ScriptApproval.get().using(groovy, GroovyLanguage.get())); + () -> ScriptApproval.get().using(groovy, GroovyLanguage.get(), "Testing")); assertEquals("script not yet approved for use", e.getMessage()); } diff --git a/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest.java b/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest.java index 35295973c..0f189d3cb 100644 --- a/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest.java +++ b/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest.java @@ -222,7 +222,7 @@ boolean findApproved() { @Override Script use() { - assertEquals(groovy, ScriptApproval.get().using(groovy, GroovyLanguage.get())); + assertEquals(groovy, ScriptApproval.get().using(groovy, GroovyLanguage.get(), "Testing")); return this; }