From ff38dd5be978190e6c05831f6ee1b2dc2e39a535 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Tue, 22 Oct 2024 16:04:30 +0200 Subject: [PATCH 01/14] JENKINS-73941 - Option to hide "Use Groovy Sandbox" for users without Administer permission globally in the system --- plugin/pom.xml | 15 +++++++ .../workflow/cps/CpsFlowDefinition.java | 6 +-- .../workflow/cps/config/CPSConfiguration.java | 20 ++++++++- .../cps/config/CPSConfiguration/config.jelly | 5 --- .../CPSConfiguration/help-hideSandbox.html | 6 --- .../workflow/cps/CpsFlowDefinitionTest.java | 38 ++++++++++++++--- .../plugins/workflow/cps/JcascTest.java | 42 +++++++++++++++++++ .../plugins/workflow/cps/casc_test.yaml | 3 ++ .../workflow/cps/casc_test_expected.yaml | 1 + 9 files changed, 114 insertions(+), 22 deletions(-) delete mode 100644 plugin/src/main/resources/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration/help-hideSandbox.html create mode 100644 plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java create mode 100644 plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml create mode 100644 plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml diff --git a/plugin/pom.xml b/plugin/pom.xml index ef29baaea..87a02fbfc 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -54,6 +54,11 @@ import pom + + org.jenkins-ci.plugins + script-security + 1384.v4cb_f8321c66b_ + @@ -246,6 +251,16 @@ 4.2.2 test + + io.jenkins + configuration-as-code + test + + + io.jenkins.configuration-as-code + test-harness + test + diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java index 01f21b798..a4ca098ef 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java @@ -41,7 +41,6 @@ import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; -import org.jenkinsci.plugins.workflow.cps.config.CPSConfiguration; import org.jenkinsci.plugins.workflow.cps.persistence.PersistIn; import org.jenkinsci.plugins.workflow.flow.DurabilityHintProvider; import org.jenkinsci.plugins.workflow.flow.FlowDefinition; @@ -89,7 +88,7 @@ public CpsFlowDefinition(String script) throws Descriptor.FormException { @DataBoundConstructor public CpsFlowDefinition(String script, boolean sandbox) throws Descriptor.FormException { - if (CPSConfiguration.get().isHideSandbox() && !sandbox && !Jenkins.get().hasPermission(Jenkins.ADMINISTER)) { + if (!sandbox && ScriptApproval.get().forceSandboxForCurrentUser()) { // this will end up in the /oops page until https://github.com/jenkinsci/jenkins/pull/9495 is picked up throw new Descriptor.FormException("Sandbox cannot be disabled. This Jenkins instance has been configured to not " + "allow regular users to disable the sandbox in pipelines", "sandbox"); @@ -98,7 +97,6 @@ public CpsFlowDefinition(String script, boolean sandbox) throws Descriptor.FormE this.script = sandbox ? script : ScriptApproval.get().configuring(script, GroovyLanguage.get(), ApprovalContext.create().withCurrentUser().withItemAsKey(req != null ? req.findAncestorObject(Item.class) : null), req == null); this.sandbox = sandbox; - } private Object readResolve() { @@ -196,7 +194,7 @@ public JSON doCheckScriptCompile(@AncestorInPath Item job, @QueryParameter Strin public boolean shouldHideSandbox(@CheckForNull CpsFlowDefinition instance) { // sandbox checkbox is shown to admins even if the global configuration says otherwise // it's also shown when sandbox == false, so regular users can enable it - return CPSConfiguration.get().isHideSandbox() && !Jenkins.get().hasPermission(Jenkins.ADMINISTER) + return ScriptApproval.get().forceSandboxForCurrentUser() && (instance == null || instance.sandbox); } diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java index 9de7f59c6..3246c6e96 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java @@ -29,27 +29,43 @@ import hudson.ExtensionList; import jenkins.model.GlobalConfiguration; import jenkins.model.GlobalConfigurationCategory; +import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; import org.jenkinsci.Symbol; +/** +* @deprecated + * This class hs been deprecated and we don't recommend to use it. + * In order to force using the system sandbox for pipelines, please use the flag + * org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.get().isForceSandbox + * or + * org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.get().forceSandboxForCurrentUser + **/ @Symbol("cps") @Extension +@Deprecated public class CPSConfiguration extends GlobalConfiguration { /** * Whether to show the sandbox checkbox in jobs to users without Jenkins.ADMINISTER */ - private boolean hideSandbox; + private transient boolean hideSandbox; public CPSConfiguration() { + load(); + if (hideSandbox) { + ScriptApproval.get().setForceSandbox(hideSandbox); + } + } public boolean isHideSandbox() { - return hideSandbox; + return ScriptApproval.get().isForceSandbox(); } public void setHideSandbox(boolean hideSandbox) { this.hideSandbox = hideSandbox; + ScriptApproval.get().setForceSandbox(hideSandbox); save(); } diff --git a/plugin/src/main/resources/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration/config.jelly b/plugin/src/main/resources/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration/config.jelly index 0c7a1cebc..afd7376ad 100644 --- a/plugin/src/main/resources/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration/config.jelly +++ b/plugin/src/main/resources/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration/config.jelly @@ -25,9 +25,4 @@ THE SOFTWARE. - - - - - \ No newline at end of file diff --git a/plugin/src/main/resources/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration/help-hideSandbox.html b/plugin/src/main/resources/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration/help-hideSandbox.html deleted file mode 100644 index 158790b5f..000000000 --- a/plugin/src/main/resources/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration/help-hideSandbox.html +++ /dev/null @@ -1,6 +0,0 @@ -
-

Controls whether the "Use Groovy Sandbox" is shown in pipeline jobs configuration page to users without Overall/Administer permission.

-

This can be used to get a better UX in highly secured environments where all pipelines are required to run in the sandbox (ie. running arbitrary code is never approved)

-

Note that this does not prevent users to configure and run pipelines with sandbox disabled if they create or update jobs by other means (like CLI or HTTP API). - This option is only hiding the checkbox from the HTML UI

-
\ No newline at end of file diff --git a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java index 3ec930cc7..a335b17f1 100644 --- a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java +++ b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java @@ -24,6 +24,7 @@ package org.jenkinsci.plugins.workflow.cps; +import hudson.model.Result; import hudson.util.VersionNumber; import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.HttpMethod; @@ -45,6 +46,7 @@ import org.jenkinsci.plugins.scriptsecurity.scripts.languages.GroovyLanguage; import org.jenkinsci.plugins.workflow.cps.config.CPSConfiguration; import org.jenkinsci.plugins.workflow.job.WorkflowJob; +import org.jenkinsci.plugins.workflow.job.WorkflowRun; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.Issue; @@ -59,8 +61,6 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -316,7 +316,7 @@ public void cpsScriptSandboxHide() throws Exception { } // non-admins cannot see the sandbox checkbox in jobs if hideSandbox is On globally - CPSConfiguration.get().setHideSandbox(true); + ScriptApproval.get().setForceSandbox(true); { HtmlForm config = wcDevel.getPage(p, "configure").getFormByName("config"); assertThat(config.getVisibleText(), not(containsStringIgnoringCase("Use Groovy Sandbox"))); @@ -328,7 +328,7 @@ public void cpsScriptSandboxHide() throws Exception { } // admins can always see the sandbox checkbox - CPSConfiguration.get().setHideSandbox(false); + ScriptApproval.get().setForceSandbox(false); wcDevel.login("admin"); { HtmlForm config = wcDevel.getPage(p, "configure").getFormByName("config"); @@ -336,7 +336,7 @@ public void cpsScriptSandboxHide() throws Exception { } // even when set to hide globally - CPSConfiguration.get().setHideSandbox(true); + ScriptApproval.get().setForceSandbox(true); { HtmlForm config = wcDevel.getPage(p, "configure").getFormByName("config"); assertThat(config.getVisibleText(), containsStringIgnoringCase("Use Groovy Sandbox")); @@ -370,4 +370,32 @@ public void cpsScriptSandboxHide() throws Exception { } } + + @Test + public void cpsConfigurationSandboxToScriptApprovalSandbox() throws Exception{ + //Deprecated CPSConfiguration should update ScriptApproval forceSandbox logic to keep casc compatibility + ScriptApproval.get().setForceSandbox(false); + + CPSConfiguration.get().setHideSandbox(true); + assertTrue(ScriptApproval.get().isForceSandbox()); + + ScriptApproval.get().setForceSandbox(false); + assertFalse(CPSConfiguration.get().isHideSandbox()); + } + + @Test + public void cpsScriptSignatureException() throws Exception { + ScriptApproval.get().setForceSandbox(false); + WorkflowJob p = jenkins.createProject(WorkflowJob.class); + String script = "jenkins.model.Jenkins.instance"; + p.setDefinition(new CpsFlowDefinition(script, true)); + WorkflowRun b = jenkins.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); + jenkins.assertLogContains("Scripts not permitted to use staticMethod jenkins.model.Jenkins getInstance. " + + "Administrators can decide whether to approve or reject this signature.", b); + + ScriptApproval.get().setForceSandbox(true); + b = jenkins.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); + jenkins.assertLogContains("Scripts not permitted to use staticMethod jenkins.model.Jenkins getInstance. " + + "Script signature is not in the default whitelist.", b); + } } diff --git a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java new file mode 100644 index 000000000..aba7c9ae0 --- /dev/null +++ b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java @@ -0,0 +1,42 @@ +package org.jenkinsci.plugins.workflow.cps; + +import io.jenkins.plugins.casc.ConfigurationContext; +import io.jenkins.plugins.casc.ConfiguratorRegistry; +import io.jenkins.plugins.casc.misc.ConfiguredWithCode; +import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule; +import io.jenkins.plugins.casc.model.CNode; +import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; +import org.junit.ClassRule; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static io.jenkins.plugins.casc.misc.Util.getSecurityRoot; +import static io.jenkins.plugins.casc.misc.Util.toStringFromYamlFile; +import static io.jenkins.plugins.casc.misc.Util.toYamlString; + +public class JcascTest { + + @ClassRule(order = 1) + @ConfiguredWithCode("casc_test.yaml") + public static JenkinsConfiguredWithCodeRule j = new JenkinsConfiguredWithCodeRule(); + + /** + * Check that CASC for security.cps.hideSandbox is sending the value to ScriptApproval.get().isForceSandbox() + * @throws Exception + */ + @Test + public void cascHideSandBox() throws Exception { + assertTrue(ScriptApproval.get().isForceSandbox()); + } + + @Test + public void cascExport() throws Exception { + ConfiguratorRegistry registry = ConfiguratorRegistry.get(); + ConfigurationContext context = new ConfigurationContext(registry); + CNode yourAttribute = getSecurityRoot(context).get("cps"); + String exported = toYamlString(yourAttribute); + String expected = toStringFromYamlFile(this, "casc_test_expected.yaml"); + assertEquals(exported, expected); + } +} diff --git a/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml new file mode 100644 index 000000000..04fa77f0a --- /dev/null +++ b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml @@ -0,0 +1,3 @@ +security: + cps: + hideSandbox: true \ No newline at end of file diff --git a/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml new file mode 100644 index 000000000..1852e7be5 --- /dev/null +++ b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml @@ -0,0 +1 @@ +hideSandbox: true From b753a9773eb7f45fa06f89d219dfb9082b8e03d2 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Tue, 22 Oct 2024 17:47:27 +0200 Subject: [PATCH 02/14] JENKINS-73941 - New forceSandbox logic - Additional testing --- .../workflow/cps/CpsFlowDefinitionTest.java | 31 +++++++++++++++++++ ...s.workflow.cps.config.CPSConfiguration.xml | 4 +++ 2 files changed, 35 insertions(+) create mode 100644 plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest/cpsLoadConfiguration/org.jenkinsci.plugins.workflow.cps.config.CPSConfiguration.xml diff --git a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java index a335b17f1..9c59aeb34 100644 --- a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java +++ b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java @@ -52,6 +52,7 @@ import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockAuthorizationStrategy; +import org.jvnet.hudson.test.recipes.LocalData; import java.nio.charset.StandardCharsets; import java.util.List; @@ -398,4 +399,34 @@ public void cpsScriptSignatureException() throws Exception { jenkins.assertLogContains("Scripts not permitted to use staticMethod jenkins.model.Jenkins getInstance. " + "Script signature is not in the default whitelist.", b); } + + @Test + @LocalData + public void cpsLoadConfiguration() throws Exception { + //CPSConfiguration file containing true + // should be promoted to ScriptApproval.get().isForceSandbox() + assertTrue(ScriptApproval.get().isForceSandbox()); + } + + @Test + public void cpsRoundTrip() throws Exception { + jenkins.jenkins.setSecurityRealm(jenkins.createDummySecurityRealm()); + + MockAuthorizationStrategy mockStrategy = new MockAuthorizationStrategy(); + mockStrategy.grant(Jenkins.READ).everywhere().to("dev"); + for (Permission p : Item.PERMISSIONS.getPermissions()) { + mockStrategy.grant(p).everywhere().to("dev"); + } + + WorkflowJob p = jenkins.createProject(WorkflowJob.class); + p.setDefinition(new CpsFlowDefinition("echo 'Hello'", true)); + + WorkflowJob roundTrip = jenkins.configRoundtrip(p); + + assertEquals(((CpsFlowDefinition)p.getDefinition()).isSandbox(), + ((CpsFlowDefinition)roundTrip.getDefinition()).isSandbox()); + + assertEquals(((CpsFlowDefinition)p.getDefinition()).getScript(), + ((CpsFlowDefinition)roundTrip.getDefinition()).getScript()); + } } diff --git a/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest/cpsLoadConfiguration/org.jenkinsci.plugins.workflow.cps.config.CPSConfiguration.xml b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest/cpsLoadConfiguration/org.jenkinsci.plugins.workflow.cps.config.CPSConfiguration.xml new file mode 100644 index 000000000..12a4b3d33 --- /dev/null +++ b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest/cpsLoadConfiguration/org.jenkinsci.plugins.workflow.cps.config.CPSConfiguration.xml @@ -0,0 +1,4 @@ + + + true + \ No newline at end of file From b91350b7363872dc182010592d95485d55331942 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Wed, 23 Oct 2024 12:11:34 +0200 Subject: [PATCH 03/14] JENKINS-73941 - New forceSandbox logic - Improving the migration + tests --- .../plugins/workflow/cps/config/CPSConfiguration.java | 10 ++++++++++ .../plugins/workflow/cps/CpsFlowDefinitionTest.java | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java index 3246c6e96..c9dd97745 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java @@ -24,6 +24,9 @@ package org.jenkinsci.plugins.workflow.cps.config; +import java.io.IOException; +import java.io.UncheckedIOException; + import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.ExtensionList; @@ -57,6 +60,13 @@ public CPSConfiguration() { ScriptApproval.get().setForceSandbox(hideSandbox); } + //Data migration from this configuration to ScriptApproval should be done only once, + //so removing the config file after the previous migration + try { + this.getConfigFile().delete(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } public boolean isHideSandbox() { diff --git a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java index 9c59aeb34..cb68e9dbe 100644 --- a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java +++ b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java @@ -54,6 +54,7 @@ import org.jvnet.hudson.test.MockAuthorizationStrategy; import org.jvnet.hudson.test.recipes.LocalData; +import java.io.File; import java.nio.charset.StandardCharsets; import java.util.List; @@ -406,6 +407,11 @@ public void cpsLoadConfiguration() throws Exception { //CPSConfiguration file containing true // should be promoted to ScriptApproval.get().isForceSandbox() assertTrue(ScriptApproval.get().isForceSandbox()); + + //Once the info is promoted, we are removing the config file, so should no longer exist. + //We are checking the injected localData is removed + assertFalse(new File(jenkins.jenkins.getRootDir(), + "org.jenkinsci.plugins.workflow.cps.config.CPSConfiguration.xml").exists()); } @Test From 1061a190bdfd134a5ad20070c0c9889f5a1fcfc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Garc=C3=ADa?= <60674455+jgarciacloudbees@users.noreply.github.com> Date: Thu, 24 Oct 2024 09:48:55 +0200 Subject: [PATCH 04/14] JENKINS-73941 - Apply suggestions from code review Co-authored-by: Carroll Chiou --- plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/pom.xml b/plugin/pom.xml index 87a02fbfc..3522488fa 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -57,7 +57,7 @@ org.jenkins-ci.plugins script-security - 1384.v4cb_f8321c66b_ + 1384.v4cb_f8321c66b_ From 4a7b87c6e439209a1db7ac97f8184625c92aaa73 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Thu, 24 Oct 2024 09:50:52 +0200 Subject: [PATCH 05/14] JENKINS-73941 - Updated incremental versions --- plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/pom.xml b/plugin/pom.xml index 3522488fa..b1ca3db16 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -57,7 +57,7 @@ org.jenkins-ci.plugins script-security - 1384.v4cb_f8321c66b_ + 1385.va_f7eee148192 From e0dd3b1e7a184bdce8a0e088393c6f2e98c8edd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Garc=C3=ADa?= <60674455+jgarciacloudbees@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:13:01 +0200 Subject: [PATCH 06/14] JENKINS-73941 - Apply suggestions from code review Co-authored-by: Antonio Muniz --- .../plugins/workflow/cps/config/CPSConfiguration.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java index c9dd97745..93a9f906b 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java @@ -36,8 +36,8 @@ import org.jenkinsci.Symbol; /** -* @deprecated - * This class hs been deprecated and we don't recommend to use it. + * @deprecated + * This class has been deprecated and its only configuration value is ignored. Do not rely on it or use it in any way. * In order to force using the system sandbox for pipelines, please use the flag * org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.get().isForceSandbox * or @@ -60,8 +60,8 @@ public CPSConfiguration() { ScriptApproval.get().setForceSandbox(hideSandbox); } - //Data migration from this configuration to ScriptApproval should be done only once, - //so removing the config file after the previous migration + // Data migration from this configuration to ScriptApproval should be done only once, + // so removing the config file after the previous migration try { this.getConfigFile().delete(); } catch (IOException e) { From eeb813265b59f9648eae253dc35d64829bd20522 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Thu, 24 Oct 2024 14:36:25 +0200 Subject: [PATCH 07/14] JENKINS-73941 - Additional changes required from suggestions --- .../workflow/cps/config/CPSConfiguration.java | 10 ----- .../workflow/cps/CpsFlowDefinitionTest.java | 12 ------ .../plugins/workflow/cps/JcascTest.java | 42 ------------------- .../plugins/workflow/cps/casc_test.yaml | 3 -- .../workflow/cps/casc_test_expected.yaml | 1 - 5 files changed, 68 deletions(-) delete mode 100644 plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java delete mode 100644 plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml delete mode 100644 plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java index 93a9f906b..ad8eb83ea 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java @@ -69,16 +69,6 @@ public CPSConfiguration() { } } - public boolean isHideSandbox() { - return ScriptApproval.get().isForceSandbox(); - } - - public void setHideSandbox(boolean hideSandbox) { - this.hideSandbox = hideSandbox; - ScriptApproval.get().setForceSandbox(hideSandbox); - save(); - } - @NonNull @Override public GlobalConfigurationCategory getCategory() { diff --git a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java index cb68e9dbe..7ee02f154 100644 --- a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java +++ b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java @@ -373,18 +373,6 @@ public void cpsScriptSandboxHide() throws Exception { } } - @Test - public void cpsConfigurationSandboxToScriptApprovalSandbox() throws Exception{ - //Deprecated CPSConfiguration should update ScriptApproval forceSandbox logic to keep casc compatibility - ScriptApproval.get().setForceSandbox(false); - - CPSConfiguration.get().setHideSandbox(true); - assertTrue(ScriptApproval.get().isForceSandbox()); - - ScriptApproval.get().setForceSandbox(false); - assertFalse(CPSConfiguration.get().isHideSandbox()); - } - @Test public void cpsScriptSignatureException() throws Exception { ScriptApproval.get().setForceSandbox(false); diff --git a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java deleted file mode 100644 index aba7c9ae0..000000000 --- a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.jenkinsci.plugins.workflow.cps; - -import io.jenkins.plugins.casc.ConfigurationContext; -import io.jenkins.plugins.casc.ConfiguratorRegistry; -import io.jenkins.plugins.casc.misc.ConfiguredWithCode; -import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule; -import io.jenkins.plugins.casc.model.CNode; -import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; -import org.junit.ClassRule; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static io.jenkins.plugins.casc.misc.Util.getSecurityRoot; -import static io.jenkins.plugins.casc.misc.Util.toStringFromYamlFile; -import static io.jenkins.plugins.casc.misc.Util.toYamlString; - -public class JcascTest { - - @ClassRule(order = 1) - @ConfiguredWithCode("casc_test.yaml") - public static JenkinsConfiguredWithCodeRule j = new JenkinsConfiguredWithCodeRule(); - - /** - * Check that CASC for security.cps.hideSandbox is sending the value to ScriptApproval.get().isForceSandbox() - * @throws Exception - */ - @Test - public void cascHideSandBox() throws Exception { - assertTrue(ScriptApproval.get().isForceSandbox()); - } - - @Test - public void cascExport() throws Exception { - ConfiguratorRegistry registry = ConfiguratorRegistry.get(); - ConfigurationContext context = new ConfigurationContext(registry); - CNode yourAttribute = getSecurityRoot(context).get("cps"); - String exported = toYamlString(yourAttribute); - String expected = toStringFromYamlFile(this, "casc_test_expected.yaml"); - assertEquals(exported, expected); - } -} diff --git a/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml deleted file mode 100644 index 04fa77f0a..000000000 --- a/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml +++ /dev/null @@ -1,3 +0,0 @@ -security: - cps: - hideSandbox: true \ No newline at end of file diff --git a/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml deleted file mode 100644 index 1852e7be5..000000000 --- a/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml +++ /dev/null @@ -1 +0,0 @@ -hideSandbox: true From 55300cad42d9b8aa1854f8cc840e6dc1ac90fdde Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Thu, 24 Oct 2024 16:49:57 +0200 Subject: [PATCH 08/14] JENKINS-73941 - Updating pom.xml to use the latest script-security-plugin incremental version --- plugin/pom.xml | 2 +- .../org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java | 4 ++-- .../plugins/workflow/cps/config/CPSConfiguration.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/pom.xml b/plugin/pom.xml index b1ca3db16..e998a8f3f 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -57,7 +57,7 @@ org.jenkins-ci.plugins script-security - 1385.va_f7eee148192 + 1387.ve7d0edd705a_c diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java index a4ca098ef..d73cf4e5a 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java @@ -88,7 +88,7 @@ public CpsFlowDefinition(String script) throws Descriptor.FormException { @DataBoundConstructor public CpsFlowDefinition(String script, boolean sandbox) throws Descriptor.FormException { - if (!sandbox && ScriptApproval.get().forceSandboxForCurrentUser()) { + if (!sandbox && ScriptApproval.get().isForceSandboxForCurrentUser()) { // this will end up in the /oops page until https://github.com/jenkinsci/jenkins/pull/9495 is picked up throw new Descriptor.FormException("Sandbox cannot be disabled. This Jenkins instance has been configured to not " + "allow regular users to disable the sandbox in pipelines", "sandbox"); @@ -194,7 +194,7 @@ public JSON doCheckScriptCompile(@AncestorInPath Item job, @QueryParameter Strin public boolean shouldHideSandbox(@CheckForNull CpsFlowDefinition instance) { // sandbox checkbox is shown to admins even if the global configuration says otherwise // it's also shown when sandbox == false, so regular users can enable it - return ScriptApproval.get().forceSandboxForCurrentUser() + return ScriptApproval.get().isForceSandboxForCurrentUser() && (instance == null || instance.sandbox); } diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java index ad8eb83ea..789187e94 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java @@ -41,7 +41,7 @@ * In order to force using the system sandbox for pipelines, please use the flag * org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.get().isForceSandbox * or - * org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.get().forceSandboxForCurrentUser + * org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.get().isForceSandboxForCurrentUser **/ @Symbol("cps") @Extension From e538cece7f86eb86e176ba13269113a53ba50bd9 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Thu, 24 Oct 2024 17:43:38 +0200 Subject: [PATCH 09/14] JENKINS-73941 - Updating pom.xml to use the latest script-security-plugin incremental version --- plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/pom.xml b/plugin/pom.xml index e998a8f3f..45d463e33 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -57,7 +57,7 @@ org.jenkins-ci.plugins script-security - 1387.ve7d0edd705a_c + 1388.v9907110c2f80 From 8ffaefef24f82a242742a7f5b3a91c10154501e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Garc=C3=ADa?= <60674455+jgarciacloudbees@users.noreply.github.com> Date: Fri, 25 Oct 2024 16:44:23 +0200 Subject: [PATCH 10/14] JENKINS-73941 - Apply suggestions from code review Co-authored-by: Jesse Glick --- .../plugins/workflow/cps/config/CPSConfiguration.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java index 789187e94..1aed31cb7 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java @@ -38,10 +38,7 @@ /** * @deprecated * This class has been deprecated and its only configuration value is ignored. Do not rely on it or use it in any way. - * In order to force using the system sandbox for pipelines, please use the flag - * org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.get().isForceSandbox - * or - * org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.get().isForceSandboxForCurrentUser + * In order to force using the system sandbox for pipelines, please use {@link ScriptApproval#isForceSandbox} or {@link ScriptApproval#isForceSandboxForCurrentUser} **/ @Symbol("cps") @Extension From e0f823a8a69471f9b0762c1485e40b13a04ac76c Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Fri, 25 Oct 2024 17:02:08 +0200 Subject: [PATCH 11/14] JENKINS-73941 - reverting CASC compatibility --- plugin/pom.xml | 2 +- .../workflow/cps/config/CPSConfiguration.java | 10 +++++ .../workflow/cps/CpsFlowDefinitionTest.java | 12 ++++++ .../plugins/workflow/cps/JcascTest.java | 42 +++++++++++++++++++ .../plugins/workflow/cps/casc_test.yaml | 3 ++ .../workflow/cps/casc_test_expected.yaml | 1 + 6 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java create mode 100644 plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml create mode 100644 plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml diff --git a/plugin/pom.xml b/plugin/pom.xml index 45d463e33..19c2da6ef 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -57,7 +57,7 @@ org.jenkins-ci.plugins script-security - 1388.v9907110c2f80 + 1392.v64f458436d13 diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java index 1aed31cb7..300cc1ba6 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java @@ -66,6 +66,16 @@ public CPSConfiguration() { } } + public boolean isHideSandbox() { + return ScriptApproval.get().isForceSandbox(); + } + + public void setHideSandbox(boolean hideSandbox) { + this.hideSandbox = hideSandbox; + ScriptApproval.get().setForceSandbox(hideSandbox); + save(); + } + @NonNull @Override public GlobalConfigurationCategory getCategory() { diff --git a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java index 7ee02f154..cb68e9dbe 100644 --- a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java +++ b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java @@ -373,6 +373,18 @@ public void cpsScriptSandboxHide() throws Exception { } } + @Test + public void cpsConfigurationSandboxToScriptApprovalSandbox() throws Exception{ + //Deprecated CPSConfiguration should update ScriptApproval forceSandbox logic to keep casc compatibility + ScriptApproval.get().setForceSandbox(false); + + CPSConfiguration.get().setHideSandbox(true); + assertTrue(ScriptApproval.get().isForceSandbox()); + + ScriptApproval.get().setForceSandbox(false); + assertFalse(CPSConfiguration.get().isHideSandbox()); + } + @Test public void cpsScriptSignatureException() throws Exception { ScriptApproval.get().setForceSandbox(false); diff --git a/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java new file mode 100644 index 000000000..aba7c9ae0 --- /dev/null +++ b/plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/JcascTest.java @@ -0,0 +1,42 @@ +package org.jenkinsci.plugins.workflow.cps; + +import io.jenkins.plugins.casc.ConfigurationContext; +import io.jenkins.plugins.casc.ConfiguratorRegistry; +import io.jenkins.plugins.casc.misc.ConfiguredWithCode; +import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule; +import io.jenkins.plugins.casc.model.CNode; +import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; +import org.junit.ClassRule; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static io.jenkins.plugins.casc.misc.Util.getSecurityRoot; +import static io.jenkins.plugins.casc.misc.Util.toStringFromYamlFile; +import static io.jenkins.plugins.casc.misc.Util.toYamlString; + +public class JcascTest { + + @ClassRule(order = 1) + @ConfiguredWithCode("casc_test.yaml") + public static JenkinsConfiguredWithCodeRule j = new JenkinsConfiguredWithCodeRule(); + + /** + * Check that CASC for security.cps.hideSandbox is sending the value to ScriptApproval.get().isForceSandbox() + * @throws Exception + */ + @Test + public void cascHideSandBox() throws Exception { + assertTrue(ScriptApproval.get().isForceSandbox()); + } + + @Test + public void cascExport() throws Exception { + ConfiguratorRegistry registry = ConfiguratorRegistry.get(); + ConfigurationContext context = new ConfigurationContext(registry); + CNode yourAttribute = getSecurityRoot(context).get("cps"); + String exported = toYamlString(yourAttribute); + String expected = toStringFromYamlFile(this, "casc_test_expected.yaml"); + assertEquals(exported, expected); + } +} diff --git a/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml new file mode 100644 index 000000000..04fa77f0a --- /dev/null +++ b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test.yaml @@ -0,0 +1,3 @@ +security: + cps: + hideSandbox: true \ No newline at end of file diff --git a/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml new file mode 100644 index 000000000..1852e7be5 --- /dev/null +++ b/plugin/src/test/resources/org/jenkinsci/plugins/workflow/cps/casc_test_expected.yaml @@ -0,0 +1 @@ +hideSandbox: true From 9f5087da1bb8ba7b270f8ff8041d97660b615eba Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Fri, 25 Oct 2024 17:09:02 +0200 Subject: [PATCH 12/14] JENKINS-73941 - reverting back to CASC compatibility --- .../jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java index 300cc1ba6..206a131f7 100644 --- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java +++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java @@ -73,7 +73,6 @@ public boolean isHideSandbox() { public void setHideSandbox(boolean hideSandbox) { this.hideSandbox = hideSandbox; ScriptApproval.get().setForceSandbox(hideSandbox); - save(); } @NonNull From e9ec3dbb9e6b2c038a54a66a26bddbfcc29978d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Garc=C3=ADa?= <60674455+jgarciacloudbees@users.noreply.github.com> Date: Mon, 28 Oct 2024 08:59:58 +0100 Subject: [PATCH 13/14] JENKINS-73941 - Update to the latest Script-Security-Plugin release Co-authored-by: Jesse Glick --- plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/pom.xml b/plugin/pom.xml index 19c2da6ef..6a8f9335e 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -57,7 +57,7 @@ org.jenkins-ci.plugins script-security - 1392.v64f458436d13 + 1366.vd44b_49a_5c85c From 3d1ae21eb8a7da5d8c955ce07a4601c42807c027 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Tue, 29 Oct 2024 17:52:21 +0100 Subject: [PATCH 14/14] JENKINS-73941 - Update to the latest Script-Security-Plugin release --- plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/pom.xml b/plugin/pom.xml index 6a8f9335e..3c71061f7 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -57,7 +57,7 @@ org.jenkins-ci.plugins script-security - 1366.vd44b_49a_5c85c + 1367.vdf2fc45f229c