-
Notifications
You must be signed in to change notification settings - Fork 168
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-49486] Enable variable expansion for ManualCondition.users (approvers) #114
base: master
Are you sure you want to change the base?
Conversation
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.
Thanks for your PR! There are some issues in your current approach, but with some changes a feature like this might be able to work.
I am not exactly sure the best way to go about implementing this feature, but maybe one way to approach it would be to edit the methods in PromotionPermissionHelper.java
to take an extra AbstractBuild<?,?> build
parameter and use that to expand the values when checking for permissions. You'd also have to do something about ManualCondition#isInUsersList
and ManualCondition#isInGroupList
so that they would be able to handle variables in the users list correctly.
@@ -52,8 +59,9 @@ | |||
* @author Peter Hayes | |||
*/ | |||
public class ManualCondition extends PromotionCondition { | |||
private String users; | |||
private static String users; |
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.
By making this static
, you have forced all ManualCondition
s to use the same list of users, which is causing the issue noted in your email to jenkinsci-dev.
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.
thank you very much for the direction!
I'll give it a try.
748f171
to
e73582d
Compare
Hi @dwnusbaum, I updated my pull-request based on your suggestion. But I still miss one thing. How can I update the promotion page to show approvers |
e73582d
to
fbddb91
Compare
I updated Since getUsersAsSet is set, I tried to use How can I properly call Java function in Stapler? I think once I got this issue resolved, |
fbddb91
to
163f07c
Compare
@totoroliu I'll try to take a look at the new changes sometime this week, thanks! |
163f07c
to
5394488
Compare
any update on this 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.
HI @totoroliu! I am sorry that I was not able to review this sooner. It looks ok in general to me, but I have a few comments.
The only big thing I think the PR still needs is a few tests for the new behavior to confirm that it works as expected and so that it doesn't regress in the future. You should be able to add new tests to ManualConditionTest.java that are very similar to the tests already in that file.
CC @oleg-nenashev: It would be great if you could take a look and confirm whether the feature/implementation make sense to you.
LOGGER.log(Level.FINER, "ManualCondition.getUsersAsSet(): user={0}", user); | ||
if (user.startsWith("$")){ | ||
user = user.substring(1); | ||
if (user.startsWith("{") && user.endsWith("}")) |
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 would prefer to allow either $NAME
or ${NAME}
, but not both. What happens if there is a user named $NAME
? I don't think users can have $
in their name after a recent security fix, but I am not 100% sure.
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.
the reason I allow both
Email-ext plugin and token-macro plugin support these 2 syntax.
But if you insist,
I could allow only one of the case,
and which form do you prefert to support?
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.
If email-ext and token-macro support both, then it probably makes sense to support both here as well. I'd leave it the way you have it for now.
// TODO: Give a more accurate error message if the user has Promotion.PROMOTE but is not in the list of approvers. | ||
throw new AccessDeniedException2(Jenkins.getAuthentication(), Promotion.PROMOTE); | ||
} | ||
} | ||
|
||
public static boolean hasPermission(@Nonnull AbstractProject<?,?> target, @CheckForNull ManualCondition associatedCondition) { | ||
public static boolean hasPermission(@Nonnull AbstractProject<?,?> target, AbstractBuild<?,?> build, @CheckForNull ManualCondition associatedCondition) { |
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.
It would be good to add either @CheckForNull
or @Nonnull
to the parameter for clarity (same for the other places where a parameter is added).
@@ -95,18 +98,28 @@ public ParameterDefinition getParameterDefinition(String name) { | |||
return null; | |||
} | |||
|
|||
public Set<String> getUsersAsSet() { | |||
public Set<String> getUsersAsSet(AbstractBuild<?,?> build) { |
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.
Breaks binary compatibility, although I don't see any other callers based on a GitHub search of the jenkinsci organization, so it might not matter. We could always be safe and keep the previous method around as well, and have it call the new method passing null
for the new parameter.
Same issue with isInUsersList
and isInGroupList
.
will try to review it this week, ping me if I don't |
Also just a note: For any job with a parameterized approver for its manual promotion condition, all Job/Build users would be able to allow anyone to promote the job. Previously, only Job/Configure users were able to edit the list and allow anyone to promote the job, so this feature definitely needs to be used carefully. @totoroliu In your environment, which users would be configuring/building/promoting, and what permissions would they have? It would be good to make sure we are all on the same page and that the permission model makes sense for real use-cases. |
52a1215
to
ba93574
Compare
I'm using LDAP authentication with Role-based permission control. |
ba93574
to
a3e8f84
Compare
Please don't force-push, it makes it difficult to review the PR since we cannot tell what changed each time and have to review everything from scratch. It's ok to have a ton of commits here, we can always squash-merge the PR if it gets messy. |
Enable variable expansion for ManualCondition.users (approvers) by adding parameters 'AbstractBuild<?,?> build' to methods in PromotionPermissionHelper.java and ManualCondition.getUsersAsSet()
a3e8f84
to
40964fd
Compare
i'm sorry for the trouble. |
In ManualConditionTest.java, My plan is: |
I think that you would replace a line like the following:
with the following (although I have not tested it):
|
…n.users (approvers)
} | ||
assertThat(waitForBuildByNumber(pp, 4).getResult(), equalTo(Result.SUCCESS)); | ||
} | ||
|
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.
@dwnusbaum
Do you know why this webclient test fail?
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.
At a glance, no, but you could use a debugger and step through the test/plugin code to figure out why it is failing before removing 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.
AFAICT there is a bug in the current logic implementation. Regarding the use-case itself, it looks reasonable though it makes the job developer responsible for all possible security concerns related to the variable resolution.
Before merging the PR, you need to ensure that the patch does not allow exposing sensitive environment variable values to the system log or web UI. From what I see, it does it in the current implementation
} | ||
|
||
public Set<String> getUsersAsSet(AbstractBuild<?,?> build) { | ||
if (users == null || users.equals("") || build == null) |
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.
This condition is not correct from what I see.
When build
is null, the result will be always empty.
E.g. getUsersAsSet()
will be always returning empty list after the change
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.
What sensitive environment variable is exposing right now?
Could you give me some examples?
if (users == null || users.equals("")) | ||
return Collections.emptySet(); | ||
|
||
Set<String> set = new HashSet<String>(); | ||
for (String user : users.split(",")) { | ||
user = user.trim(); | ||
|
||
if (user.trim().length() > 0) | ||
LOGGER.log(Level.FINER, "ManualCondition.getUsersAsSet(): user={0}", user); | ||
if (user.startsWith("$")){ |
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.
You still need to null-check build somewhere before using it below. I think it makes sense to do it here: if (build != null && user.startsWith("$"))
. That way if the the build is null, we don't try to substitute parameterized names, and just treat them as actual usernames.
user = user.substring(1); | ||
if (user.startsWith("{") && user.endsWith("}")) | ||
user = user.substring(1, user.length() -1); | ||
LOGGER.log(Level.INFO, "ManualCondition.getUsersAsSet(): build.getBuildVariableResolver().resolve(user=${0})={1}", |
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.
Level.INFO
is visible by default in Jenkins, so I would move this and the other call to LOGGER.log
to Level.FINER
or similar.
Hi,
I'm trying to develop for Jenkins-49486,
but this is my first time implementing a feature for a Jenkins plugin.
My plan is to update Approver field for each build
by doing TokenMacro.expandAll() for each of comma delimited user
from String ManualCondition.users at the end of each build.
After bring in RunListenerImpl.onCompleted(),
I'm able to expand Approver field when a build is copmleted.
However, now it's not only updating the build's Approver,
but also update the Jenkins job's configurations.
Hence, at the end of a build,
the job configuration's Approver variable
would be expanded to be hardcoded Approver accroding to my last build result.
I'm just wondering if any one could point out some direction for me.
Thanks!