25
25
package org .jenkinsci .plugins .scriptsecurity .scripts ;
26
26
27
27
import edu .umd .cs .findbugs .annotations .SuppressFBWarnings ;
28
+ import hudson .init .InitMilestone ;
28
29
import hudson .model .BallColor ;
29
30
import hudson .model .PageDecorator ;
30
31
import hudson .security .ACLContext ;
@@ -268,7 +269,7 @@ String hashClasspathEntry(URL entry) throws IOException {
268
269
/** All external classpath entries allowed used for scripts. */
269
270
private /*final*/ TreeSet <ApprovedClasspathEntry > approvedClasspathEntries ;
270
271
271
- /* for test */ void addApprovedClasspathEntry (ApprovedClasspathEntry acp ) {
272
+ /* for test */ synchronized void addApprovedClasspathEntry (ApprovedClasspathEntry acp ) {
272
273
approvedClasspathEntries .add (acp );
273
274
}
274
275
@@ -503,16 +504,12 @@ private PendingClasspathEntry getPendingClasspathEntry(@NonNull String hash) {
503
504
@ DataBoundConstructor
504
505
public ScriptApproval () {
505
506
load ();
506
- /* can be null when upgraded from old versions.*/
507
- if (aclApprovedSignatures == null ) {
508
- aclApprovedSignatures = new TreeSet <>();
509
- }
510
- if (approvedClasspathEntries == null ) {
511
- approvedClasspathEntries = new TreeSet <>();
512
- }
513
- if (pendingClasspathEntries == null ) {
514
- pendingClasspathEntries = new TreeSet <>();
515
- }
507
+ }
508
+
509
+ @ Override
510
+ public synchronized void load () {
511
+ clear ();
512
+ super .load ();
516
513
// Check for loaded class directories
517
514
boolean changed = false ;
518
515
int dcp = 0 ;
@@ -536,6 +533,40 @@ public ScriptApproval() {
536
533
if (changed ) {
537
534
save ();
538
535
}
536
+ // only call on subsequent load to avoid cycle
537
+ if (Jenkins .get ().getInitLevel () == InitMilestone .COMPLETED ) {
538
+ try {
539
+ LOG .log (Level .FINE , "Reconfiguring ScriptApproval after loading configuration from disk" );
540
+ reconfigure ();
541
+ } catch (IOException e ) {
542
+ LOG .log (Level .WARNING , e , () -> "Failed to reconfigure ScriptApproval" );
543
+ }
544
+ } else {
545
+ LOG .log (Level .FINE , "Skipping reconfiguration of ScriptApproval during Jenkins startup sequence" );
546
+ }
547
+ }
548
+
549
+ private void clear () {
550
+ approvedScriptHashes .clear ();
551
+ approvedSignatures .clear ();
552
+ pendingScripts .clear ();
553
+ pendingSignatures .clear ();
554
+ /* can be null when upgraded from old versions.*/
555
+ if (aclApprovedSignatures == null ) {
556
+ aclApprovedSignatures = new TreeSet <>();
557
+ } else {
558
+ aclApprovedSignatures .clear ();
559
+ }
560
+ if (approvedClasspathEntries == null ) {
561
+ approvedClasspathEntries = new TreeSet <>();
562
+ } else {
563
+ approvedClasspathEntries .clear ();
564
+ }
565
+ if (pendingClasspathEntries == null ) {
566
+ pendingClasspathEntries = new TreeSet <>();
567
+ } else {
568
+ pendingClasspathEntries .clear ();
569
+ }
539
570
}
540
571
541
572
@ Restricted (NoExternalUse .class )
@@ -571,7 +602,7 @@ public synchronized boolean hasDeprecatedApprovedClasspathHashes() {
571
602
}
572
603
573
604
/** Nothing has ever been approved or is pending. */
574
- boolean isEmpty () {
605
+ synchronized boolean isEmpty () {
575
606
return approvedScriptHashes .isEmpty () &&
576
607
approvedSignatures .isEmpty () &&
577
608
aclApprovedSignatures .isEmpty () &&
@@ -1201,7 +1232,7 @@ public JSON getClasspathRenderInfo() {
1201
1232
1202
1233
@ Restricted (NoExternalUse .class ) // for use from AJAX
1203
1234
@ JavaScriptMethod
1204
- public JSON approveClasspathEntry (String hash ) throws IOException {
1235
+ public synchronized JSON approveClasspathEntry (String hash ) throws IOException {
1205
1236
Jenkins .get ().checkPermission (Jenkins .ADMINISTER );
1206
1237
URL url = null ;
1207
1238
synchronized (this ) {
@@ -1225,7 +1256,7 @@ public JSON approveClasspathEntry(String hash) throws IOException {
1225
1256
1226
1257
@ Restricted (NoExternalUse .class ) // for use from AJAX
1227
1258
@ JavaScriptMethod
1228
- public JSON denyClasspathEntry (String hash ) throws IOException {
1259
+ public synchronized JSON denyClasspathEntry (String hash ) throws IOException {
1229
1260
Jenkins .get ().checkPermission (Jenkins .ADMINISTER );
1230
1261
PendingClasspathEntry cp = getPendingClasspathEntry (hash );
1231
1262
if (cp != null ) {
@@ -1237,7 +1268,7 @@ public JSON denyClasspathEntry(String hash) throws IOException {
1237
1268
1238
1269
@ Restricted (NoExternalUse .class ) // for use from AJAX
1239
1270
@ JavaScriptMethod
1240
- public JSON denyApprovedClasspathEntry (String hash ) throws IOException {
1271
+ public synchronized JSON denyApprovedClasspathEntry (String hash ) throws IOException {
1241
1272
Jenkins .get ().checkPermission (Jenkins .ADMINISTER );
1242
1273
if (approvedClasspathEntries .remove (new ApprovedClasspathEntry (hash , null ))) {
1243
1274
save ();
0 commit comments