From ee148dd15943cf48aa327e44457739cc41eacacb Mon Sep 17 00:00:00 2001 From: MarkRx Date: Mon, 15 Feb 2021 12:13:21 -0500 Subject: [PATCH] JENKINS-62708 add JCasC support for approved script hashes --- .../scripts/ScriptApproval.java | 24 +++++++++++++++++++ .../scriptsecurity/scripts/JcascTest.java | 3 +++ .../scripts/ScriptApprovalTest.java | 10 ++++---- .../upgradeSmokes/scriptApproval.xml | 4 +++- .../scriptsecurity/scripts/smoke_test.yaml | 2 ++ .../scripts/smoke_test_expected.yaml | 2 ++ 6 files changed, 40 insertions(+), 5 deletions(-) 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 cfda3ff3e..1b0ba2fe0 100644 --- a/src/main/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApproval.java +++ b/src/main/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApproval.java @@ -66,6 +66,7 @@ import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Pattern; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import jenkins.model.Jenkins; @@ -701,6 +702,29 @@ public synchronized String[] getAclApprovedSignatures() { return aclApprovedSignatures.toArray(new String[aclApprovedSignatures.size()]); } + @DataBoundSetter + public synchronized void setApprovedScriptHashes(String[] scriptHashes) throws IOException { + Jenkins.getInstance().checkPermission(Jenkins.RUN_SCRIPTS); + approvedScriptHashes.clear(); + List goodScriptHashes = new ArrayList<>(scriptHashes.length); + Pattern sha1Pattern = Pattern.compile("^[a-fA-F0-9]{40}$"); + for (String scriptHash : scriptHashes) { + if (scriptHash != null && sha1Pattern.matcher(scriptHash).matches()) { + goodScriptHashes.add(scriptHash); + } else { + LOG.warning("Ignoring malformed script hash: " + scriptHash); + } + } + approvedScriptHashes.addAll(goodScriptHashes); + save(); + reconfigure(); + } + + @Restricted(NoExternalUse.class) // Jelly, implementation + public synchronized String[] getApprovedScriptHashes() { + return approvedScriptHashes.toArray(new String[approvedScriptHashes.size()]); + } + @Restricted(NoExternalUse.class) // implementation @Extension public static final class ApprovedWhitelist extends ProxyWhitelist { public ApprovedWhitelist() { diff --git a/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/JcascTest.java b/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/JcascTest.java index 8a825b274..b562f911f 100644 --- a/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/JcascTest.java +++ b/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/JcascTest.java @@ -26,6 +26,9 @@ public void smokeTestEntry() throws Exception { String[] approved = ScriptApproval.get().getApprovedSignatures(); assertTrue(approved.length == 1); assertEquals(approved[0], "method java.net.URI getHost"); + String[] approvedScriptHashes = ScriptApproval.get().getApprovedScriptHashes(); + assertTrue(approvedScriptHashes.length == 1); + assertEquals(approvedScriptHashes[0], "fccae58c5762bdd15daca97318e9d74333203106"); } @Test 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 e92afda99..a5779714e 100644 --- a/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest.java +++ b/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest.java @@ -162,15 +162,17 @@ public void malformedScriptApproval() throws Exception { assertEquals(0, sa.getDangerousApprovedSignatures().length); } - @Issue("JENKINS-57563") - @LocalData // Just a scriptApproval.xml that whitelists 'staticMethod jenkins.model.Jenkins getInstance' + @Issue({"JENKINS-57563", "JENKINS-62708"}) + @LocalData // Just a scriptApproval.xml that whitelists 'staticMethod jenkins.model.Jenkins getInstance' and a script printing all labels @Test public void upgradeSmokes() throws Exception { + configureSecurity(); FreeStyleProject p = r.createFreeStyleProject(); p.getPublishersList().add(new TestGroovyRecorder( new SecureGroovyScript("jenkins.model.Jenkins.instance", true, null))); - r.assertLogNotContains("org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: " - + "Scripts not permitted to use staticMethod jenkins.model.Jenkins getInstance", + p.getPublishersList().add(new TestGroovyRecorder( + new SecureGroovyScript("println(jenkins.model.Jenkins.instance.getLabels())", false, null))); + r.assertLogNotContains("org.jenkinsci.plugins.scriptsecurity.scripts.UnapprovedUsageException: script not yet approved for use", r.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0).get())); } diff --git a/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest/upgradeSmokes/scriptApproval.xml b/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest/upgradeSmokes/scriptApproval.xml index 753c1b0e6..b15a50a3d 100644 --- a/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest/upgradeSmokes/scriptApproval.xml +++ b/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest/upgradeSmokes/scriptApproval.xml @@ -1,6 +1,8 @@ - + + fccae58c5762bdd15daca97318e9d74333203106 + staticMethod jenkins.model.Jenkins getInstance diff --git a/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/smoke_test.yaml b/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/smoke_test.yaml index 5225d1885..366aa49de 100644 --- a/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/smoke_test.yaml +++ b/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/smoke_test.yaml @@ -2,3 +2,5 @@ security: scriptApproval: approvedSignatures: - method java.net.URI getHost + approvedScriptHashes: + - fccae58c5762bdd15daca97318e9d74333203106 diff --git a/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/smoke_test_expected.yaml b/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/smoke_test_expected.yaml index 2e73906fc..73bc4b2da 100644 --- a/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/smoke_test_expected.yaml +++ b/src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/smoke_test_expected.yaml @@ -1,2 +1,4 @@ +approvedScriptHashes: +- "fccae58c5762bdd15daca97318e9d74333203106" approvedSignatures: - "method java.net.URI getHost"