24
24
25
25
package org .jenkinsci .plugins .scriptsecurity .sandbox .groovy ;
26
26
27
+
28
+ import com .gargoylesoftware .htmlunit .CollectingAlertHandler ;
27
29
import com .gargoylesoftware .htmlunit .html .HtmlCheckBoxInput ;
28
30
import com .gargoylesoftware .htmlunit .html .HtmlInput ;
29
31
import groovy .lang .Binding ;
61
63
import org .jenkinsci .plugins .scriptsecurity .scripts .UnapprovedUsageException ;
62
64
63
65
import static org .hamcrest .MatcherAssert .assertThat ;
66
+ import static org .hamcrest .Matchers .arrayWithSize ;
67
+ import static org .hamcrest .Matchers .contains ;
64
68
import static org .hamcrest .Matchers .containsString ;
69
+ import static org .hamcrest .Matchers .empty ;
70
+ import static org .hamcrest .Matchers .emptyArray ;
71
+ import static org .hamcrest .Matchers .is ;
65
72
import org .jenkinsci .plugins .scriptsecurity .sandbox .whitelists .Whitelisted ;
66
73
import static org .junit .Assert .assertEquals ;
67
74
import static org .junit .Assert .assertFalse ;
@@ -163,7 +170,7 @@ public class SecureGroovyScriptTest {
163
170
164
171
165
172
/**
166
- * Test where the user has ADMINISTER privs, default to non sandbox mode.
173
+ * Test where the user has ADMINISTER privs, default to non sandbox mode, but require approval
167
174
*/
168
175
@ Test public void testSandboxDefault_with_ADMINISTER_privs () throws Exception {
169
176
r .jenkins .setSecurityRealm (r .createDummySecurityRealm ());
@@ -198,12 +205,12 @@ public class SecureGroovyScriptTest {
198
205
// The user has ADMINISTER privs => should default to non sandboxed
199
206
assertFalse (publisher .getScript ().isSandbox ());
200
207
201
- // Because it has ADMINISTER privs, the script should not have ended up pending approval
208
+ // even though it has ADMINISTER privs, the script should still require approval
202
209
Set <ScriptApproval .PendingScript > pendingScripts = ScriptApproval .get ().getPendingScripts ();
203
- assertEquals (0 , pendingScripts .size ());
210
+ assertEquals (1 , pendingScripts .size ());
204
211
205
212
// Test that the script is executable. If it's not, we will get an UnapprovedUsageException
206
- assertEquals ( groovy , ScriptApproval .get ().using (groovy , GroovyLanguage .get ()));
213
+ assertThrows ( UnapprovedUsageException . class , () -> ScriptApproval .get ().using (groovy , GroovyLanguage .get ()));
207
214
}
208
215
209
216
/**
@@ -892,7 +899,7 @@ public void testScriptApproval() throws Exception {
892
899
893
900
JenkinsRule .WebClient wc = r .createWebClient ();
894
901
895
- // If configured by a user with ADMINISTER script is approved if edited by that user
902
+ // If configured by a user with ADMINISTER script is not approved and approval is requested
896
903
{
897
904
wc .login ("admin" );
898
905
HtmlForm config = wc .getPage (p , "configure" ).getFormByName ("config" );
@@ -903,8 +910,9 @@ public void testScriptApproval() throws Exception {
903
910
script .setText (groovy );
904
911
r .submit (config );
905
912
906
- assertTrue (ScriptApproval .get ().isScriptApproved (groovy , GroovyLanguage .get ()));
907
-
913
+ assertFalse (ScriptApproval .get ().isScriptApproved (groovy , GroovyLanguage .get ()));
914
+ assertEquals (1 , ScriptApproval .get ().getPendingScripts ().size ());
915
+
908
916
// clean up for next tests
909
917
ScriptApproval .get ().preapproveAll ();
910
918
ScriptApproval .get ().clearApprovedScripts ();
@@ -929,11 +937,14 @@ public void testScriptApproval() throws Exception {
929
937
ScriptApproval .get ().clearApprovedScripts ();
930
938
}
931
939
932
- // If configured by a user with ADMINISTER while escape hatch is on script is approved upon save
940
+ // If configured by a user with ADMINISTER while escape hatches are on script is approved upon save
933
941
{
934
942
wc .login ("admin" );
935
- boolean original = ScriptApproval .ADMIN_AUTO_APPROVAL_ENABLED ;
943
+ boolean originalAdminAutoApprove = ScriptApproval .ADMIN_AUTO_APPROVAL_ENABLED ;
936
944
ScriptApproval .ADMIN_AUTO_APPROVAL_ENABLED = true ;
945
+ boolean originalAllowAdminApproval = ScriptApproval .ALLOW_ADMIN_APPROVAL_ENABLED ;
946
+ ScriptApproval .ALLOW_ADMIN_APPROVAL_ENABLED = true ;
947
+
937
948
try {
938
949
HtmlForm config = wc .getPage (p , "configure" ).getFormByName ("config" );
939
950
List <HtmlTextArea > scripts = config .getTextAreasByName ("_.script" );
@@ -948,15 +959,18 @@ public void testScriptApproval() throws Exception {
948
959
ScriptApproval .get ().preapproveAll ();
949
960
ScriptApproval .get ().clearApprovedScripts ();
950
961
} finally {
951
- ScriptApproval .ADMIN_AUTO_APPROVAL_ENABLED = original ;
962
+ ScriptApproval .ADMIN_AUTO_APPROVAL_ENABLED = originalAdminAutoApprove ;
963
+ ScriptApproval .ALLOW_ADMIN_APPROVAL_ENABLED = originalAllowAdminApproval ;
952
964
}
953
965
}
954
966
955
967
// If configured by a user without ADMINISTER while escape hatch is on script is not approved
956
968
{
957
969
wc .login ("devel" );
958
- boolean original = ScriptApproval .ADMIN_AUTO_APPROVAL_ENABLED ;
970
+ boolean originalAdminAutoApprove = ScriptApproval .ADMIN_AUTO_APPROVAL_ENABLED ;
959
971
ScriptApproval .ADMIN_AUTO_APPROVAL_ENABLED = true ;
972
+ boolean originalAllowAdminApproval = ScriptApproval .ALLOW_ADMIN_APPROVAL_ENABLED ;
973
+ ScriptApproval .ALLOW_ADMIN_APPROVAL_ENABLED = true ;
960
974
try {
961
975
r .submit (wc .getPage (p , "configure" ).getFormByName ("config" ));
962
976
@@ -966,7 +980,8 @@ public void testScriptApproval() throws Exception {
966
980
ScriptApproval .get ().preapproveAll ();
967
981
ScriptApproval .get ().clearApprovedScripts ();
968
982
} finally {
969
- ScriptApproval .ADMIN_AUTO_APPROVAL_ENABLED = original ;
983
+ ScriptApproval .ADMIN_AUTO_APPROVAL_ENABLED = originalAdminAutoApprove ;
984
+ ScriptApproval .ALLOW_ADMIN_APPROVAL_ENABLED = originalAllowAdminApproval ;
970
985
}
971
986
}
972
987
}
@@ -1271,6 +1286,52 @@ public void testScriptAtFieldInitializers() throws Exception {
1271
1286
r .assertLogContains ("new java.io.File java.lang.String" , b );
1272
1287
}
1273
1288
1289
+ @ Test public void testApprovalFromFormValidation () throws Exception {
1290
+ r .jenkins .setSecurityRealm (r .createDummySecurityRealm ());
1291
+ MockAuthorizationStrategy mockStrategy = new MockAuthorizationStrategy ();
1292
+ mockStrategy .grant (Jenkins .ADMINISTER ).everywhere ().to ("admin" );
1293
+ for (Permission p : Item .PERMISSIONS .getPermissions ()) {
1294
+ mockStrategy .grant (p ).everywhere ().to ("admin" );
1295
+ }
1296
+ r .jenkins .setAuthorizationStrategy (mockStrategy );
1297
+
1298
+ FreeStyleProject p = r .createFreeStyleProject ("p" );
1299
+ try (JenkinsRule .WebClient wc = r .createWebClient ()) {
1300
+ CollectingAlertHandler altertHandler = new CollectingAlertHandler ();
1301
+ wc .setAlertHandler (altertHandler );
1302
+
1303
+ wc .login ("admin" );
1304
+ HtmlPage page = wc .getPage (p , "configure" );
1305
+ HtmlForm config = page .getFormByName ("config" );
1306
+ HtmlFormUtil .getButtonByCaption (config , "Add post-build action" ).click (); // lib/hudson/project/config-publishers2.jelly
1307
+ page .getAnchorByText (r .jenkins .getExtensionList (BuildStepDescriptor .class ).get (TestGroovyRecorder .DescriptorImpl .class ).getDisplayName ()).click ();
1308
+ wc .waitForBackgroundJavaScript (10000 );
1309
+ List <HtmlTextArea > scripts = config .getTextAreasByName ("_.script" );
1310
+ // Get the last one, because previous ones might be from Lockable Resources during PCT.
1311
+ HtmlTextArea script = scripts .get (scripts .size () - 1 );
1312
+ String groovy = "build.externalizableId" ;
1313
+ script .setText (groovy );
1314
+ // nothing is approved or pending (no save)
1315
+ assertThat (ScriptApproval .get ().getPendingScripts (), is (empty ()));
1316
+ assertThat (ScriptApproval .get ().getApprovedScriptHashes (), is (emptyArray ()));
1317
+
1318
+ wc .waitForBackgroundJavaScript (10_000 ); // FormValidation to display
1319
+
1320
+ page .getAnchorByText ("Approve script" ).click ();
1321
+
1322
+ wc .waitForBackgroundJavaScript (10_000 ); // wait for the ajax approval to complete
1323
+
1324
+ assertThat (altertHandler .getCollectedAlerts (), contains ("Script approved" ));
1325
+ // script is approved
1326
+ assertThat (ScriptApproval .get ().getPendingScripts (), is (empty ()));
1327
+ assertThat (ScriptApproval .get ().getApprovedScriptHashes (), is (arrayWithSize (1 )));
1328
+
1329
+ r .submit (config );
1330
+
1331
+ FreeStyleBuild b = r .assertBuildStatus (Result .SUCCESS , p .scheduleBuild2 (0 ));
1332
+ }
1333
+ }
1334
+
1274
1335
public static class HasMainMethod {
1275
1336
@ Whitelisted
1276
1337
public HasMainMethod () { }
0 commit comments