-
Notifications
You must be signed in to change notification settings - Fork 357
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
Improving hostname validation #2455
Conversation
@miq-bot assign @dclarizio |
@douglasgabriel definitely need to take a look at the codeclimate issues. |
b57635b
to
b92a53f
Compare
Hey @AparnaKarve @douglasgabriel fixed the code climate issues, can you take a look? |
miq-bot add_label gaprindashvili/yes |
@douglasgabriel In the screenshot above, why is the hostname format incorrect? If that's the case, it's probably not applicable across the board for all hostnames. |
@AparnaKarve this is based on discussion in this PR, only extend the validation to front-end. Can you mention some case that this validation is not applicable? |
@douglasgabriel I don't know off-hand. What I do know is that my Lenovo XClarity EMS was created using the Although I just verified that it does work even without @h-kataria Would you have an idea if we allow using the protocol (http/https) in the hostname in other areas of the app? |
In this validation occurs what I believe that is an inconsistency: the user provides some data (with the protocol, for example) and the system validates only a part of this input (without protocol), after this the system store all data provided by user (with protocol). So, if the user be allowed to provide the protocol, so I believe that the validation strategy must be revised, don't you think? |
I believe that the validation in this PR should be the same considered here in the ruby code. Also I think that the behavior considered for the hostname should be the same considered for the IP. Imagine that the hostname See examples of the current PR:
According to the previous explanation, 1 and 4 are equivalent. Thus, 4 should not be invalid (or both 2 and 4 should be invalid). The first question then: what option should we choose? In order to contribute with the discussion, I think we should accept the path in the URLs. Let me prove my point with an example: imagine that, for some reason (security, for example) I just have one public IP, but I have several hosts I want to put in my MiQ instance. I can install something in that public IP (Zuul, for example, or any other technology I want) that transparently redirect subdomains to my internal hosts. Something like:
Considering that @agrare, @rodneyhbrown7 could you confirm the information and decide about what should be done in these PRs? |
return /\b:\/\/\b/.test(hostname); | ||
}; | ||
var isIpAddressWithPath = function(hostname) { | ||
var isIpAddress = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/.test(hostname); |
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 the following cases should be invalid: 100.100.100.100invalid
, invalid100.100.100.100invalid
. Could you confirm that?
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.
In addition, this does not support IPV6 format, pointed out in the UI. The following expression can handle ipv4 and ipv6:
return /((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))/.test(hostname);
This won't work across the board because most on-premise providers add a path after the hostname/ipaddr for the API endpoint so you wouldn't be able to tell what component of the path is meant to point to another host and what part is for the API endpoint. |
Ok. In addition, strictly speaking, host and path are different concepts, and the port has a specific field for it. So, after thinking a little about it, I agree with you. So, can we continue these PRs by removing the path from the host field? |
}; | ||
} | ||
} | ||
})(); |
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 we consider removing the path (see current discussion), here is my suggestion for this code (needs testing):
(function() {
angular.module('ManageIQ').directive('hostnameValidation', directive);
function directive() {
return {
require: 'ngModel',
restrict: 'A',
link: link,
};
function link(_scope, _elem, _attrs, ctrl) {
ctrl.$validators.hostnameValidation = function(_modelValue, viewValue) {
return isHostname(viewValue) || isIpAddress(viewValue);
};
/**
* Verifies if the informed value is a valid hostname.
*
* @param {string} value - Value to be validated
* @returns {boolean} True if the value is a valid hostname
*/
var isHostname = function(value) {
return /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$/.test(value);
};
/**
* Verifies if the informed value is a valid IP (IPV4 or IPV6).
*
* @param {string} value - Value to be validated
* @returns {boolean} True if the value is a valid IP address (IPV4 or IPV6)
*/
var isIpAddress = function(value) {
return /((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))/.test(value);
};
}
}
})();
My lack of regex skill precludes me from reviewing the code changes :) @douglasgabriel IDK the ui tests very well but I highly recommend adding some tests for this validation. |
b92a53f
to
6205167
Compare
Well, it's done guys. I've add the Saulo's solution on the validation and add some tests to it. Now it avoid the user to put protocol, path and port on the hostname field. What do you think @agrare @saulotoledo @AparnaKarve ? |
Nice tests @douglasgabriel ! |
LGTM @douglasgabriel |
@douglasgabriel Based on the benchmark that @agrare mentioned above, your hostname validation directive works. I did find something in my testing, though. The regex does satisfy the "No protocol, no paths, no ports" condition, hence I would say - |
6205167
to
af4cd88
Compare
Checked commit douglasgabriel@af4cd88 with ruby 2.3.3, rubocop 0.47.1, haml-lint 0.20.0, and yamllint 1.10.0 |
Improving hostname validation (cherry picked from commit a26d124)
Gaprindashvili backport details:
|
PR based on this discussion:
ManageIQ/manageiq#16220
This PR is able to: