Skip to content
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-55710, #28 - Fix icon upload iframe in global config #36

Merged
merged 4 commits into from
Feb 17, 2022
Merged

JENKINS-55710, #28 - Fix icon upload iframe in global config #36

merged 4 commits into from
Feb 17, 2022

Conversation

KalleOlaviNiemitalo
Copy link
Contributor

@KalleOlaviNiemitalo KalleOlaviNiemitalo commented Feb 12, 2022

The icon upload feature of this plugin did not work, for several reasons:

  1. Maven resource filtering replaced ${url} with https://github.com/jenkinsci/sidebar-link-plugin in SidebarLinkPlugin/config.jelly at build time, so the iframe pointed to GitHub and not to the Jenkins controller, and was blocked by Web browsers.
    This was reported in Blocked iframe #28.
    ✅ Fix by disabling resource filtering.
  2. Jenkins no longer maps ${rootURL}/plugin/sidebar-link/startUpload to startUpload.jelly because [JENKINS-63149] - Adding JCasC support #25 made SidebarLinkPlugin extend GlobalConfiguration rather than Plugin.
    ✅ Fix by using ${rootURL}/descriptorByName/hudson.plugins.sidebar_link.SidebarLinkPlugin/startUpload instead.
  3. The upload POST failed with “HTTP ERROR 403 No valid crumb was included in the request”.
    This was reported in JENKINS-55710.
    ✅ Fix by replacing <l:ajax> with <l:layout>, which adds the anti-CSRF crumb values and scripts.
  4. startUpload.jelly had action="upload" but the method in SidebarLinkPlugin was renamed from doUpload to doUploadLinkImage in [JENKINS-63149] - Adding JCasC support #25.
    ✅ Fix by using action="uploadLinkImage".

Fix #28 and JENKINS-55710

  • Make sure you are opening from a topic/feature/bugfix branch (right side) and not your main branch!
  • Ensure that the pull request title represents the desired changelog entry
  • Please describe what you did
  • Link to relevant issues in GitHub or Jira
  • Link to relevant pull requests, esp. upstream and downstream changes
  • Ensure you have provided tests - that demonstrates feature works or fixes the issue

@KalleOlaviNiemitalo
Copy link
Contributor Author

KalleOlaviNiemitalo commented Feb 12, 2022

I did not build this locally. I intend to let https://ci.jenkins.io/job/Plugins/job/sidebar-link-plugin/job/PR-36/ build it, and then download the hpi artifact, compare to a previous version, and verify that nothing unexpected changed in the resources directory. Then test in a Jenkins instance.

@KalleOlaviNiemitalo
Copy link
Contributor Author

Diff from https://ci.jenkins.io/job/Plugins/job/sidebar-link-plugin/job/master/28/ shows:

  • hpi, jar: META-INF/MANIFEST.MF
    • Built-By: administrator rather than Built-By: Jenkins. I guess a different agent was used.
    • Plugin-Version differs obviously
  • hpi, jar: META-INF/maven/org.jenkins-ci.plugins/sidebar-link/pom.properties
    • different time stamp in a comment
    • the PR build uses CRLF newlines and the master build uses LF; different agent?
  • hpi, jar: META-INF/maven/org.jenkins-ci.plugins/sidebar-link/pom.xml
    • includes the comment that I added
  • jar: various *.stapler files
    • different time stamp in a comment
    • the PR build uses CRLF newlines and the master build uses LF
  • jar: META-INF/annotations/*
    • the PR build uses CRLF newlines and the master build uses LF
  • jar: hudson/plugins/sidebar_link/SidebarLinkPlugin/config.jelly
    • as expected, ${url} is no longer replaced
  • jar: hudson/plugins/sidebar_link/Messages.class
    • there are eight one-byte differences, I don't know why. I guess these are OK, as the message strings themselves are not in this file, and the resource filtering setting could only have affected them.

Looking good enough so far.

@KalleOlaviNiemitalo
Copy link
Contributor Author

KalleOlaviNiemitalo commented Feb 12, 2022

I installed this, and the generated HTML now has <iframe src="/jenkins/plugin/sidebar-link/startUpload" style="width:100%;height:4em;margin-top:2em" frameborder="0"><a href="/jenkins/plugin/sidebar-link/startUpload" target="_blank">, which results in HTTP ERROR 404 Not Found. So it's not really better than the github link… I wonder what went wrong.

@KalleOlaviNiemitalo
Copy link
Contributor Author

Judging from https://github.com/jenkinsci/jenkins/blob/8a29e8858b49da45c0071f690d4ceebe8db2f18f/core/src/main/java/hudson/Plugin.java#L68-L71, the generated src="/jenkins/plugin/sidebar-link/startUpload" should be correct, given that this Jenkins instance is at /jenkins.

@KalleOlaviNiemitalo
Copy link
Contributor Author

KalleOlaviNiemitalo commented Feb 12, 2022

The Promoted Builds (Simple) plugin has a similar iframe, and that one loads fine.

@KalleOlaviNiemitalo
Copy link
Contributor Author

KalleOlaviNiemitalo commented Feb 12, 2022

PromotedBuildsSimplePlugin extends Plugin, but SidebarLinkPlugin extends GlobalConfiguration:

@Extension
@Symbol("sidebarGlobalLink")
public class SidebarLinkPlugin extends GlobalConfiguration {

That was changed in #25. Perhaps that causes the ${rootURL}/plugin/sidebar-link/startUpload page not to be available.

@KalleOlaviNiemitalo
Copy link
Contributor Author

I looked at several plugins that support CasC. In them, the classes that have configurable properties typically extend GlobalConfiguration. None of them extends Plugin. I don't know whether CasC supports configuring actual plugin classes.

The Plugin() constructor is deprecated. The comment there claims that DummyImpl "will still route the URL space", but this is apparently implemented in Plugin.doDynamic, which seems to support only static (possibly localized) files, rather than Jelly views like startUpload.jelly. Also, I don't see how methods like SidebarLinkPlugin.doUploadLinkImage can ever be called.

Perhaps the file upload feature has to be moved from SidebarLinkPlugin to a new class that implements RootAction (javadoc).

@KalleOlaviNiemitalo
Copy link
Contributor Author

KalleOlaviNiemitalo commented Feb 12, 2022

Ohh, actually ${rootURL}/descriptorByName/hudson.plugins.sidebar_link.SidebarLinkPlugin/startUpload does render startUpload.jelly. Perhaps I can point the iframe to that instead.

…no, that doesn't work. the HTML form appears all right, but the upload POST fails with "HTTP ERROR 403 No valid crumb was included in the request".

@KalleOlaviNiemitalo
Copy link
Contributor Author

Can someone test whether the Promoted Builds (Simple) plugin has the same problem with the anti-CSRF crumb? It's too late for me to continue on this tonight.

@damianszczepanik
Copy link
Member

Did you try to change parent class and test result?

@KalleOlaviNiemitalo
Copy link
Contributor Author

The CSRF crumb error is JENKINS-55710.

Did you try to change parent class and test result?

Not going to try because it would require using the deprecated Plugin() constructor.

@KalleOlaviNiemitalo
Copy link
Contributor Author

KalleOlaviNiemitalo commented Feb 12, 2022

I wonder if it would be better to delete the file upload feature altogether. Jenkins administrators presumably have other ways to copy files to the userContent directory. The plugin does not offer a full-featured file manager anyway; you cannot even list or delete files.

After all, #28 is a complaint about a blocked iframe, not about the inability to upload icons.

Even so, I think the resource filtering should still be disabled. None of the existing resources benefits from the filtering, and it seems pretty risky to use on jelly files.

Because SidebarLinkPlugin nowadays extends GlobalConfiguration
rather than Plugin, Jenkins maps ${rootURL}/plugin/sidebar-link/*
only to static resources and not to Jelly views like startUpload.jelly.
Form validation generates URLs that use "descriptorByName",
so let's use that for the upload iframe as well.

(Descriptor.getDescriptorUrl would return that string,
but the risk of bugs seems lower if I just hardcode it.)
layout.jelly will add data-crumb-header and data-crumb-value
attributes to the head element, and include behavior.js,
which should then add the anti-CSRF crumb as a hidden field
to the HTML form.

Fix JENKINS-55710
@KalleOlaviNiemitalo
Copy link
Contributor Author

KalleOlaviNiemitalo commented Feb 13, 2022

No, it still doesn't work. The upload POST now fails with status 404. The POST request has four copies of Jenkins-Crumb, all with the same value:

  • Two in the request URL. One of them is added to the action attribute of the form element before I select a file. Another is added there when I submit the form.
  • One in a hidden input field, added before I select a file.
  • One in a hidden 'json' input field, added when I submit the form. https://www.jenkins.io/doc/developer/forms/structured-form-submission/

@KalleOlaviNiemitalo
Copy link
Contributor Author

When I upload a plugin hpi file to the Plugin Manager, the POST request to ${rootURL}/pluginManager/uploadPlugin likewise has two Jenkins-Crumb parameters in the request URI and two more in the request body. Those shouldn't be the problem, then.

Aha! startUpload.jelly has action="upload" but the method in SidebarLinkPlugin was renamed from doUpload to doUploadLinkImage in #25.

action="upload" in startUpload.jelly attempted to call the
SidebarLinkPlugin.doUpload method, but that was renamed to
doUploadLinkImage in commit 3ef9756
during the CasC work, so we need to use action="uploadLinkImage".
@KalleOlaviNiemitalo KalleOlaviNiemitalo changed the title Fix URL of iframe used for uploading icons JENKINS-55710 - Make the icon upload feature work again Feb 13, 2022
@KalleOlaviNiemitalo KalleOlaviNiemitalo changed the title JENKINS-55710 - Make the icon upload feature work again JENKINS-55710, #28 - Make the icon upload feature work again Feb 13, 2022
@KalleOlaviNiemitalo KalleOlaviNiemitalo changed the title JENKINS-55710, #28 - Make the icon upload feature work again JENKINS-55710, #28 - Fix icon uploading in global config Feb 13, 2022
@KalleOlaviNiemitalo KalleOlaviNiemitalo changed the title JENKINS-55710, #28 - Fix icon uploading in global config JENKINS-55710, #28 - Fix icon upload iframe in global config Feb 13, 2022
@KalleOlaviNiemitalo
Copy link
Contributor Author

KalleOlaviNiemitalo commented Feb 13, 2022

I tested that the file upload in the global configuration now works; the uploaded file is created in the userContent directory and has the correct content. After the upload, the "back" link works too, and I can upload another file.

@KalleOlaviNiemitalo KalleOlaviNiemitalo marked this pull request as ready for review February 13, 2022 12:34
@KalleOlaviNiemitalo
Copy link
Contributor Author

@damianszczepanik do you need anything else from me here?

@damianszczepanik
Copy link
Member

How about compatibility with last release ? Does it break configuration when users upgrade plugin after releasing this change?

@KalleOlaviNiemitalo
Copy link
Contributor Author

No, this does not break compatibility. This does not change any Java code, so the settings saved using this version can be loaded using Sidebar Link 2.0.0 and vice versa.

Commits b0fac40 and 2df9a3c together make the iframe point to ${rootURL}/descriptorByName/hudson.plugins.sidebar_link.SidebarLinkPlugin/startUpload. Now here's some history:

  • Sidebar Link 1.0 to 1.4 did not have the icon upload feature.
  • Sidebar Link 1.5 to 1.10 pointed the iframe to ${rootURL}/plugin/sidebar-link/startUpload. If somebody bookmarked that URL, it stopped working in Sidebar Link 2.0.0 and this PR does not make it work again.
  • Sidebar Link 1.11.0 to 1.12.0 pointed the iframe to http://wiki.jenkins-ci.org/display/JENKINS/Sidebar-Link+Plugin, which did not allow people to upload icons. The ${rootURL}/plugin/sidebar-link/startUpload page would still have worked if there had been a link to it.
  • Sidebar Link 1.12.1 pointed the iframe to https://github.com/jenkinsci/sidebar-link-plugin, which did not allow people to upload icons. A ${rootURL}/plugin/sidebar-link/startUpload bookmark would still have worked.
  • Sidebar Link 2.0.0 to 2.0.2 pointed the iframe to https://github.com/jenkinsci/sidebar-link-plugin. Any ${rootURL}/plugin/sidebar-link/startUpload bookmark was broken. ${rootURL}/descriptorByName/hudson.plugins.sidebar_link.SidebarLinkPlugin/startUpload would have rendered the icon upload page (tested in 2.0.0), but there was no link to it, and the icon upload page itself did not work.

Commit e92770a makes the icon upload HTML page reference the usual JavaScript files of Jenkins. This change depends on JENKINS-34670 and thus requires Jenkins 2.53 or later; that's OK because pom.xml already declares Jenkins 2.263.4. The commit also adds an HTML title element that is localizable but does not have any translations yet.

Commit 4f35c1a changes the URL to which the icon upload HTML page posts the form data. I believe the new URL would have worked in Sidebar Link 2.0.0 and later if there had been a link to it, and I don't expect people to bookmark this URL anyway.

@damianszczepanik damianszczepanik merged commit 8ab8e97 into jenkinsci:master Feb 17, 2022
@damianszczepanik
Copy link
Member

Thanks @KalleOlaviNiemitalo for supporting this change!

@KalleOlaviNiemitalo KalleOlaviNiemitalo deleted the disable-resource-filtering branch February 17, 2022 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Blocked iframe
2 participants