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