Skip to content

Commit c83033c

Browse files
committed
JENKINS-62708 add JCasC support for approved script hashes
1 parent 717ba2e commit c83033c

File tree

6 files changed

+41
-5
lines changed

6 files changed

+41
-5
lines changed

src/main/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApproval.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@
6666
import java.util.function.Consumer;
6767
import java.util.logging.Level;
6868
import java.util.logging.Logger;
69-
import edu.umd.cs.findbugs.annotations.CheckForNull;
70-
import edu.umd.cs.findbugs.annotations.NonNull;
69+
import java.util.regex.Pattern;
70+
import javax.annotation.CheckForNull;
71+
import javax.annotation.Nonnull;
7172
import jenkins.model.Jenkins;
7273
import net.sf.json.JSON;
7374
import org.acegisecurity.context.SecurityContext;
@@ -701,6 +702,27 @@ public synchronized String[] getAclApprovedSignatures() {
701702
return aclApprovedSignatures.toArray(new String[aclApprovedSignatures.size()]);
702703
}
703704

705+
@DataBoundSetter
706+
public synchronized void setApprovedScriptHashes(String[] scriptHashes) throws IOException {
707+
Jenkins.getInstance().checkPermission(Jenkins.RUN_SCRIPTS);
708+
approvedScriptHashes.clear();
709+
Pattern sha1Pattern = Pattern.compile("[a-fA-F0-9]{40}");
710+
for (String scriptHash : scriptHashes) {
711+
if (scriptHash != null && sha1Pattern.matcher(scriptHash).matches()) {
712+
approvedScriptHashes.add(scriptHash);
713+
} else {
714+
LOG.warning(() -> "Ignoring malformed script hash: " + scriptHash);
715+
}
716+
}
717+
save();
718+
reconfigure();
719+
}
720+
721+
@Restricted(NoExternalUse.class) // Jelly, implementation
722+
public synchronized String[] getApprovedScriptHashes() {
723+
return approvedScriptHashes.toArray(new String[approvedScriptHashes.size()]);
724+
}
725+
704726
@Restricted(NoExternalUse.class) // implementation
705727
@Extension public static final class ApprovedWhitelist extends ProxyWhitelist {
706728
public ApprovedWhitelist() {

src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/JcascTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ public void smokeTestEntry() throws Exception {
2626
String[] approved = ScriptApproval.get().getApprovedSignatures();
2727
assertTrue(approved.length == 1);
2828
assertEquals(approved[0], "method java.net.URI getHost");
29+
String[] approvedScriptHashes = ScriptApproval.get().getApprovedScriptHashes();
30+
assertTrue(approvedScriptHashes.length == 1);
31+
assertEquals(approvedScriptHashes[0], "fccae58c5762bdd15daca97318e9d74333203106");
2932
}
3033

3134
@Test

src/test/java/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,21 @@ public void malformedScriptApproval() throws Exception {
162162
assertEquals(0, sa.getDangerousApprovedSignatures().length);
163163
}
164164

165-
@Issue("JENKINS-57563")
166-
@LocalData // Just a scriptApproval.xml that whitelists 'staticMethod jenkins.model.Jenkins getInstance'
165+
@Issue({"JENKINS-57563", "JENKINS-62708"})
166+
@LocalData // Just a scriptApproval.xml that whitelists 'staticMethod jenkins.model.Jenkins getInstance' and a script printing all labels
167167
@Test
168168
public void upgradeSmokes() throws Exception {
169+
configureSecurity();
169170
FreeStyleProject p = r.createFreeStyleProject();
170171
p.getPublishersList().add(new TestGroovyRecorder(
171172
new SecureGroovyScript("jenkins.model.Jenkins.instance", true, null)));
173+
p.getPublishersList().add(new TestGroovyRecorder(
174+
new SecureGroovyScript("println(jenkins.model.Jenkins.instance.getLabels())", false, null)));
172175
r.assertLogNotContains("org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: "
173176
+ "Scripts not permitted to use staticMethod jenkins.model.Jenkins getInstance",
174177
r.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0).get()));
178+
r.assertLogNotContains("org.jenkinsci.plugins.scriptsecurity.scripts.UnapprovedUsageException: script not yet approved for use",
179+
r.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0).get()));
175180
}
176181

177182
private Script script(String groovy) {

src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/ScriptApprovalTest/upgradeSmokes/scriptApproval.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<?xml version='1.0' encoding='UTF-8'?>
22
<scriptApproval plugin="script-security@1.24">
3-
<approvedScriptHashes/>
3+
<approvedScriptHashes>
4+
<string>fccae58c5762bdd15daca97318e9d74333203106</string>
5+
</approvedScriptHashes>
46
<approvedSignatures>
57
<string>staticMethod jenkins.model.Jenkins getInstance</string>
68
</approvedSignatures>

src/test/resources/org/jenkinsci/plugins/scriptsecurity/scripts/smoke_test.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ security:
22
scriptApproval:
33
approvedSignatures:
44
- method java.net.URI getHost
5+
approvedScriptHashes:
6+
- fccae58c5762bdd15daca97318e9d74333203106
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
approvedScriptHashes:
2+
- "fccae58c5762bdd15daca97318e9d74333203106"
13
approvedSignatures:
24
- "method java.net.URI getHost"

0 commit comments

Comments
 (0)