-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
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-31661] Check the root url (Admin monitor + Wizard) #3082
[JENKINS-31661] Check the root url (Admin monitor + Wizard) #3082
Conversation
This pull request originates from a CloudBees employee. At CloudBees, we require that all pull requests be reviewed by other CloudBees employees before we seek to have the change accepted. If you want to learn more about our process please see this explanation. |
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 error messages are inversed in the tests. It should be fixed. The rest is fine IMHO.
* Normally this root URL is set during SetupWizard phase, this monitor is there to ensure that behavior. | ||
* Potential exceptions are the dev environment, if someone disable the wizard or | ||
* the administrator put an empty string on the configuration page. | ||
*/ |
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.
@since
may be useful here though not strictly required
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.
added
@@ -1,3 +1,4 @@ | |||
CompletedInitializationMonitor.DisplayName=Jenkins Initialization Monitor | |||
SecurityIsOffMonitor.DisplayName=Disabled Security | |||
URICheckEncodingMonitor.DisplayName=Check URI Encoding | |||
RootUrlNotSetMonitor.DisplayName=Root URL configured Monitor |
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.
"not" is missing somewhere, I'd guess
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.
added
assertTrue(StringUtils.isNotBlank(JenkinsLocationConfiguration.get().getUrl())); | ||
|
||
RootUrlNotSetMonitor monitor = j.jenkins.getExtensionList(AdministrativeMonitor.class).get(RootUrlNotSetMonitor.class); | ||
assertFalse("Monitor must be activated", monitor.isActivated()); |
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.
"not be activated"
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.
corrected
JenkinsLocationConfiguration.get().setUrl(null); | ||
|
||
RootUrlNotSetMonitor monitor = j.jenkins.getExtensionList(AdministrativeMonitor.class).get(RootUrlNotSetMonitor.class); | ||
assertTrue("Monitor must not be activated", monitor.isActivated()); |
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.
"must be activated"
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.
corrected
@Test | ||
@Issue("JENKINS-31661") | ||
public void testWithRootUrl_configured() { | ||
assertTrue(StringUtils.isNotBlank(JenkinsLocationConfiguration.get().getUrl())); |
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 test relies on the default JTH behavior. Maybe it makes sense to mention 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.
good point :)
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.
🐝
@reviewbybees not do-ne edit: to show it in PR list to review |
I just tried with the PR build: Going through the setup wizard leaves Jenkins without a defined root URL. While I think this admin monitor is a good idea, Jenkins should not be showing warnings (other than "newer Jenkins is available") to someone who just went through the setup wizard. For that reason, I strongly disagree with merging this change as is. The setup wizard should be extended to allow defining a Jenkins URL (or could perhaps infer one from the URL used to access Jenkins in the setup wizard, similar to how the form field determines its default value?). Only then would this change make sense. |
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.
See previous comment; this does not make sense if the setup wizard leaves the root URL undefined.
@kzantow do you have time to review those modifications ? |
@Wadeck After "werk in progress" I rather expected to see a German translation :D |
I am a bit aware about the "Proceed as current admin" hyperlink. If I click this button, will the local URL change be applied? P.S: I would be happy to remove this button at all. It causes too many issues with unintended clicks |
@oleg-nenashev Yes, I put my "save action" for both the skip and save first user. And as it's a button and not a link, no risk to see anybody doing some ctrl+click or right-click open in a new tab, etc. So normally it should be called all the time. |
Predates major changes.
@Override | ||
public boolean isActivated() { | ||
JenkinsLocationConfiguration loc = JenkinsLocationConfiguration.get(); | ||
return loc == null || loc.getUrl() == 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.
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 for the information
Jenkins j = Jenkins.getInstance(); | ||
j.checkPermission(Jenkins.ADMINISTER); | ||
|
||
String rootUrl = req.getParameter("rootUrl"); |
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.
Just replace the current method parameters with
@QueryParameter String rootUrl
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.
nice feature 👍
@@ -44,6 +51,29 @@ | |||
<script> | |||
$('username').focus(); | |||
</script> | |||
</form> | |||
<form action="${rootURL}/setupWizard/configureRootUrl" class="root-url no-json" method="post"> |
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.
saveRootUrl
specifies the URL to post to, so I suspect action
and method
could just be deleted.
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.
removed
Create\ First\ Admin\ User=Create First Admin User | ||
Other\ Configuration=Other Configuration | ||
Jenkins\ URL=Jenkins URL |
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.
trailing newlines please
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.
corrected (also for FR translation)
@Test | ||
@Issue("JENKINS-31661") | ||
public void testWithRootUrl_notConfigured() { | ||
JenkinsLocationConfiguration.get().setUrl(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.
Could be merged into the preceding test, save a Jenkins startup.
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.
done
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 do not see any obvious issues in the code
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.
Small comments about some of the wording but looks fine to me in general.
I am somewhat against adding a new dependency but if new URL(input).toURI()
is totally inadequate then I am ok with it.
import java.net.URL; | ||
|
||
public class UrlHelper { | ||
public static boolean isValid(String url){ |
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 something basic like the following catches most potential errors then I would be inclined to use it instead of adding a new dependency. Either way I think this class should be @Restricted(NoExternalUse.class)
.
public static String isValidUrl(String url) {
try {
URL url = new URL(url);
url.toURI();
} catch (MalformedURLException | URISyntaxException e) {
return e.getMessage();
}
return null;
}
Since this is really just intended to help the admin so I would err on the side of allowing invalid URLs rather than disallowing valid URLs.
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.
Annotation added.
For the second point, actually only the Wizard and the admin monitors are asking for valid URL. But in case you have a very weird URL that is not considered valid for this helper, you can still use it in the configuration page, no check are done there. You will "just" have to disable the admin monitor.
* | ||
* @since TODO | ||
*/ | ||
public static HttpResponse errorJSON(@Nonnull String message, @Nonnull Map<?,?> data) { |
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.
nit: Since you are making this public I think it would make sense to go ahead and add methods for the other JSONObjectResponse
constructors (JSONObject
and JSONArray
) for consistency with okJSON
. Probably better to handle in another PR though.
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.
See #3379
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.
Needs corresponding proposed changelog entry.
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
# THE SOFTWARE. | ||
SetupWizard_ConfigureInstance_ValidationErrors=Some data are not valid, please look at the error messages close to the concerned fields |
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 might reword this from "Some data are not valid, please look at the error messages close the concerned fields" to "Some settings are invalid. See the error messages for details". Then I would get rid of the next message and just reuse this one.
SetupWizard_ConfigureInstance_ValidationErrors=Some data are not valid, please look at the error messages close to the concerned fields | ||
SetupWizard_ConfigureInstance_ProcessingErrors=Some data were not processed correctly, please look at the error messages close to the concerned fields | ||
SetupWizard_ConfigureInstance_RootUrl_Empty=The URL cannot be empty | ||
SetupWizard_ConfigureInstance_RootUrl_Invalid=The URL is invalid, please ensure you are using http:// or http:// with a valid domain. |
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 think you are missing an s in one of the http://
references.
core/pom.xml
Outdated
<dependency> | ||
<groupId>commons-validator</groupId> | ||
<artifactId>commons-validator</artifactId> | ||
<version>1.6</version> |
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.
Could we get this without adding a dependency that will be available to dependent plugins? E.g. integrate the relevant class into Jenkins with @Restricted
?
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.
To clarify, this really should be addressed.
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.
👍 addressed, 4 classes included with @Restricted
* | ||
* @since TODO | ||
*/ | ||
public static HttpResponse errorJSON(@Nonnull String message, @Nonnull Map<?,?> data) { |
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.
Needs corresponding proposed changelog entry.
* Please DO NOT ADD ITEM TO THIS LIST. <p> | ||
* If you add an item here, the deserialization process will break | ||
* because it is used for serialized state like "jenkins.install.InstallState$4" | ||
* before the change from anonymous class to named class. If you need to add a new InstallState, you can just add a new inner named class but nothing to change in this list. |
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.
CC @jglick for confirmation, looks good but to be sure.
<!-- | ||
The MIT License | ||
|
||
Copyright (c) 2018, CloudBees, Inc. |
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.
Not actually true?
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 think I added the header to the wrong file -.-
@@ -0,0 +1,101 @@ | |||
|
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.
Missing license header.
Manually tested behavior looks good. I'm on-holding this for another week though due to the upcoming core security update. I don't think the risk here is huge, but it's still a substantial 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.
LGTM
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.
Looks good to me. Maybe the imported classes could be moved into a different package since jenkins.org.blah
is a little weird but I don't feel strongly about it.
@dwnusbaum it was based on the same concept as used in hudson/org/apache/tools/tar/TarInputStream.java |
@daniel-beck are we good with this one ? |
To be merged later this week. |
@reviewbybees done |
$('root-url').focus(); | ||
(function setInitialRootUrlFieldValue(){ | ||
var iframeUrl = window.location.href; | ||
var iframeRelativeUrl = '/setupWizard/setupWizardConfigureInstance'; |
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.
Wrong! This strips the trailing slash, which is required. JENKINS-51660
@jglick a follow-up PR would be much appreciated |
Due to Jenkins:2247 for read and JenkinsLocationConfiguration:123 for write it does not seem to have a real impact. Related change: #3474 |
The problem is that the application has some little issues when there is no rootURL configured. Example: JENKINS-47426.
Normally with the Setup Wizard, this should not be the case. But there are some exceptions like development instance, administrator that disabled the wizard or if the administrator simply clear the root URL in the config.
There was already a PR (#1921) for the issue but as the PR went too far in the correction it was not merged (as I understand). This PR focuses only on the monitor part.
See JENKINS-31661.
Proposed changelog entries
HttpResponses
for sending an error.Submitter checklist
* Use the
Internal:
prefix if the change has no user-visible impact (API, test frameworks, etc.)Desired reviewers
@reviewbybees @oleg-nenashev @amuniz
Screenshot