-
Notifications
You must be signed in to change notification settings - Fork 196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[JENKINS-73470] Option to hide "Use Groovy Sandbox" #907
Conversation
See [JENKINS-73470](https://issues.jenkins.io/browse/JENKINS-73470) for details.
plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java
Outdated
Show resolved
Hide resolved
plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java
Show resolved
Hide resolved
<p>Note that this is not a security configuration, as it does not prevent users to configure and run | ||
pipelines in some other ways without using the sandbox.</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enhancements under discusssion:
- Throw
AbortException
if an attempt is made to run a non-sandboxed pipeline. - Throw something from the
@DataBoundConstructor
if!sandbox
.
The first option may not work though, because we allow an admin to define a non-sandboxed pipeline (maybe some special admin/diagnostic job), and we would not know when the build starts who edited it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throw something from the @DataBoundConstructor if !sandbox.
It should also check if the current user is an admin (as they are allowed to disable the sandbox), but jobs can be created by other means which do not necesasrily have a user context (job-dsl
for example, or CasC for items when using CloudBees CI). So this would not be a complete solution either. So given that there is not a complete solution, I decided to fix the minimum required to solve the UX issue that happens when using the UI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jobs can be created by other means which do not necessarily have a user context (
job-dsl
for example)
In this case the person configuring the DSL job (or approving changes to its source code) is effectively a Jenkins admin whom we trust to decide whether to allow the sandbox to be disabled. Checking hasPermission
would work uniformly, since SYSTEM
would pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been trying to block item creation/update by failing on the @DataBoundConstructor
of CpsFlowDefinition
. However UX is horrible, getting Angry Jenkins (no matter what exception type I use - tried with RuntimeException
and Failure
, same result).
An alternative solution would be to unconditionally set sandbox = true
when the right conditions are met (CPSConfiguration.get().isHideSandbox() && !sandbox && !Jenkins.get().hasPermission(Jenkins.ADMINISTER)
). But then the sandbox would be silently enabled when non-admin users save a job which had the sandbox disabled previously.
Given all that, I think we should not open that can of worms and just hide the checkbox (current state of the PR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Discussed out of band: core might have seen a regression in handling of Failure
as of jenkinsci/jenkins#4389. https://github.com/jenkinsci/jenkins/blob/cc97ad8f330aff43f412a95235a5386194803b14/core/src/main/java/hudson/model/Failure.java#L36-L41 is supposed to render https://github.com/jenkinsci/jenkins/blob/cc97ad8f330aff43f412a95235a5386194803b14/core/src/main/resources/hudson/model/AbstractModelObject/error.jelly#L33-L41; that is the whole purpose of this class.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
diff --git a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java
index aeae1865..153b2352 100644
--- a/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java
+++ b/plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition.java
@@ -91,6 +91,7 @@ public class CpsFlowDefinition extends FlowDefinition {
this.script = sandbox ? script : ScriptApproval.get().configuring(script, GroovyLanguage.get(),
ApprovalContext.create().withCurrentUser().withItemAsKey(req != null ? req.findAncestorObject(Item.class) : null), req == null);
this.sandbox = sandbox;
+ throw new Failure("Cannot save!!");
}
private Object readResolve() {
And try to save a pipeline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, because it is wrapped in Descriptor.newInstance
as you can see in the stack trace. I tried Descriptor.FormException
, which is supposed to be for this purpose. (In fact we could even revert the code to hide the checkbox, and instead use FormValidation.error
—this is arguably better UX.) Unfortunately right now it is getting wrapped by RequestImpl.invokeConstructor
then RequestImpl.TypePair.convertJSON
. Seems like a Stapler bug 👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Picked jenkinsci/stapler#571 + jenkinsci/jenkins#9495 up. It's working.
However, I just realized that we can't block the create-job
CLI as it's not going through the data-bound constructor (and I think the same will happen with the HTTP API).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, both of those would go through readResolve
as called by XStream. At least the CLI will treat certain exception types like IllegalArgumentException
specially for purposes of error handling, if it matters.
Build is failing with:
Coming from the incremental release of jenkinsci/jenkins#9495 - are incrementals building without JDK 11 release compatibility? |
Which requires Java 17, so to specify such a |
How do you usually handle this type of changes? Wait until the change is integrated in a weekly and bump to the weekly here? Or wait until the change is in an LTS? (regarless the required Java version, that's an aside). |
Neither. Revert the |
Ready for final review. |
plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java
Outdated
Show resolved
Hide resolved
Core PR merged. |
plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinitionTest.java
Outdated
Show resolved
Hide resolved
this(script, false); | ||
} | ||
|
||
@DataBoundConstructor | ||
public CpsFlowDefinition(String script, boolean sandbox) { | ||
public CpsFlowDefinition(String script, boolean sandbox) throws Descriptor.FormException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: source-incompatible but binary-compatible.
plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/config/CPSConfiguration.java
Outdated
Show resolved
Hide resolved
plugin/src/main/resources/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition/config.jelly
Outdated
Show resolved
Hide resolved
<div> | ||
<p>Controls whether the "Use Groovy Sandbox" is shown in pipeline jobs configuration page to users without Overall/Administer permission.</p> | ||
<p>This can be used to get a better UX in highly secured environments where all pipelines are required to run in the sandbox (ie. running arbitrary code is never approved)</p> | ||
<p>Note that this does not prevent users to configure and run pipelines with sandbox disabled if they create or update jobs by other means (like CLI or HTTP API). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So for now we are not touching readResolve
, deliberately?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I don't see how to differentiate from a regular call during start up and a call from a CLI/HTTP API call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deserialization during startup would run as SYSTEM
, which of course has ADMINISTER
; deserialization during a CLI/HTTP call would run as some user authentication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, we should leave this as is and revisit it separately if/when needed/requested.
StaplerRequest req = Stapler.getCurrentRequest(); | ||
this.script = sandbox ? script : ScriptApproval.get().configuring(script, GroovyLanguage.get(), | ||
ApprovalContext.create().withCurrentUser().withItemAsKey(req != null ? req.findAncestorObject(Item.class) : null), req == null); | ||
this.sandbox = sandbox; | ||
|
||
} | ||
|
||
private Object readResolve() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note 👇
plugin/src/main/resources/org/jenkinsci/plugins/workflow/cps/CpsFlowDefinition/config.jelly
Outdated
Show resolved
Hide resolved
Thanks @jglick for catching it during code review!
See JENKINS-73470 for details.
Testing done
Submitter checklist