From c8567457e852551caf863b26c69ea468a7fe9452 Mon Sep 17 00:00:00 2001 From: MarkRx Date: Mon, 17 Jan 2022 22:41:32 -0500 Subject: [PATCH] JENKINS-62708 add JCasC support for approved script hashes --- .../scripts/ScriptApproval.java | 22 +++++++++++++++++++ .../scriptsecurity/scripts/JcascTest.java | 3 +++ .../scripts/ScriptApprovalTest.java | 9 ++++++-- .../upgradeSmokes/scriptApproval.xml | 4 +++- .../scriptsecurity/scripts/smoke_test.yaml | 2 ++ .../scripts/smoke_test_expected.yaml | 2 ++ 6 files changed, 39 insertions(+), 3 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 fb2f3a933..acbb53f88 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 edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import jenkins.model.Jenkins; @@ -701,6 +702,27 @@ 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(); + Pattern sha1Pattern = Pattern.compile("[a-fA-F0-9]{40}"); + for (String scriptHash : scriptHashes) { + if (scriptHash != null && sha1Pattern.matcher(scriptHash).matches()) { + approvedScriptHashes.add(scriptHash); + } else { + LOG.warning(() -> "Ignoring malformed script hash: " + scriptHash); + } + } + 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..33856024f 100644 --- a/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest.java +++ b/src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest.java @@ -162,16 +162,21 @@ 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))); + p.getPublishersList().add(new TestGroovyRecorder( + new SecureGroovyScript("println(jenkins.model.Jenkins.instance.getLabels())", false, null))); r.assertLogNotContains("org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: " + "Scripts not permitted to use staticMethod jenkins.model.Jenkins getInstance", r.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0).get())); + r.assertLogNotContains("org.jenkinsci.plugins.scriptsecurity.scripts.UnapprovedUsageException: script not yet approved for use", + r.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0).get())); } private Script script(String groovy) { 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"