-
Notifications
You must be signed in to change notification settings - Fork 900
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
Add proxy URI schema #17318
Add proxy URI schema #17318
Conversation
@moolitayer @blomquisg please review. I know that this kind of change is unlikely to be merged. The alternative is to add to the UI new fields for the proxy user name and password, modify the backend to support that, modify the |
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 Ruby URI parser doesn't decode the percent encoded characters in the userinfo part of URIs
AFAICT, the Ruby parser doesn't decode any characters in any part of the URI - that's left up to the client.
But according to RFC 3986 it should decode the percent encoded characters, and produce the following output:
Again, AFAICT, RFC 3986 doesn't make any pronouncements about how a URI parser should be implemented, it mere talks about the form/syntax of URIs.
As such, I think this patch results in surprising behavior, and I'd recommend looking into another approach.
Yes, I agree this isn't the right solution. May be good for an emergency, but not as the definitive solution. I wanted to share it anyhow. I am marking it as WIP to make sure it isn't merged. |
@imtayadeway I have updated the pull request to use a less intrusive mechanism: it adds a new |
@miq-bot add_label gaprindashvili/yes |
@moolitayer @blomquisg @imtayadeway can you please review again? |
config/initializers/proxy_uri.rb
Outdated
module URI | ||
class PROXY < HTTP | ||
def password | ||
CGI.unescape(super()) |
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 we need to handle gracefully this case:
uri = URI('http://192.168.122.40:3128') # uri.password is nil
uri = URI('proxy://192.168.122.40:3128') # uri.password raises exception
even though we don't expect the users to input no password when using the proxy protocol.
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.
@jhernand isn't the problem that the client is using a field of a URI without unescaping it? Could we either fix the clients or unescape the password before passing it to the client? |
@agrare the client (the The right solution would require all this:
|
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 👍
Seems like a reasonable solution given this is targeted to Gaprindashvili
IDK this still seems like the wrong place to be doing this. If rest-client is calling URI.parse, then uses a field in the URI without unescaping it that sounds like a bug in rest-client. Did you try opening an issue on rest-client? I'm going to assign this over to @Fryguy for review |
Here is the If you think that the fix should go in those gems, please close this pull request. |
|
||
module URI | ||
class PROXY < HTTP | ||
def password |
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.
we might also want to handle percent-encoded username
(RFC just says whole userinfo field may contain pct-encoded
chars; username encoding does happen in the wild for example when using email as username https://stackoverflow.com/questions/10050877/url-username-with)
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, that makes sense. Can you comment that also in the rest-client
and kubeclient
issues?
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.
Are you monkey patching an existing class? If so I am against this approach. This is a known thing about the URI class, and it's the callers responsibility to do the CGI escape/unescape thing.
I would not mind if you created a subclass, though not sure what it would be named. Id also argue that new subclass should live in a utility library like more_core_extensions or manageiq_gems_pending.
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'm not a fan of the name PROXY
, but I like the idea.
Id also argue that new subclass should live in a utility library like
more_core_extensions
👍
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 agree, PROXY
is confusing to me.
There's already find_proxy
and use_proxy
methods that leverage environment variables HTTP_PROXY, FTP_PROXY, NO_PROXY, which are completely different things than this. See here.
We can certainly change kubeclient.
If we can't get a PR into rest-client (and see it released), I'd feel fine about somehow monkey-patching rest-client itself to handle Also, there might be a bug in ruby stdlib. When one doesn't specify any proxy, it's autodected from environment variables (by |
My concerns about fixing this in
|
The Ruby URI parser doesn't decode the percent encoded characters in the URI, in particular it doesn't decode the password which is frequently used when specifying proxy addresses and authentication. For example, the following code: ```ruby require 'uri' proxy = URI.parse('http://myuser:%24%[email protected]:3128') puts proxy.password ``` Produces the following output: ``` %24%3fxxxx ``` But some gems, in particular `rest-client` and `kubeclient`, expect it to decode those characters, as they use the value returned by the `password` method directly, and thus they fail to authenticate against the proxy server when the password contains percent encoded characters. To address this issue this patch adds a new `proxy` URI schema that almost identical to the `http` schema, but that decodes the password before returning it. Users can use this schema instead of `http` when they need to use percent encoded characters in the password. For example, the user can type in the UI the following proxy URL: proxy://myuser:%24%[email protected]:3128 And the new schema will automatically translate `%24%3fxxxx` into `$?xxxx`. Signed-off-by: Juan Hernandez <[email protected]>
Some comments on commit https://github.com/jhernand/manageiq/commit/73102d7e7ec1921c4c8658183408767ece7be198 config/initializers/proxy_uri.rb
|
Checked commit https://github.com/jhernand/manageiq/commit/73102d7e7ec1921c4c8658183408767ece7be198 with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 |
@miq-bot add_label blocker |
@jhernand is there anything else needed for this PR? |
@JPrause it needs to be reviewed and either merged or rejected. |
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 don't see any other direction we can realistically ship.
(IMHO it'd be OK to change behavior of http: scheme, but implementation would be more invasive and riskier to backport. This is good balance.)
@Fryguy it appears this is ready to be merged. This is for a blocker issue. |
I'm sorry, but I had never seen this issue for some reason, so I apologise for the extremely delayed response. It only came onto my radar again because it was marked as a blocker. I would love to get input from @bdunne and @jrafanie. It's hard to tell from the history here if this is a new URI class or monkey patching an existing one. I'm not a fan of either to be honest, and feel like this is more simply handled by just changing the callers. |
We can't assume that the This sounds very familiar.... If I'm understanding this correctly, it seems very similar to how IPv6 addresses need to be wrapped in # parse only valid URIs (IPv6 address is wrapped with []
# INVALID
irb(main):028:0> URI.parse("https://::1/blah")
URI::InvalidURIError: bad URI(is not URI?): https://::1/blah
...
#VALID
irb(main):011:0> u = URI.parse("https://[::1]/blah")
=> #<URI::HTTPS https://[::1]/blah>
# hostname reader unwraps ipv6 address for use in socket connections:
irb(main):012:0> u.hostname
=> "::1"
# host reader wraps ipv6 address for use in URI building
irb(main):013:0> u.host
=> "[::1]"
# host setter raises on invalid unwrapped ipv6 addresses
irb(main):027:0> u.host = "::1"
URI::InvalidComponentError: bad component(expected host component): ::1
# host setter only works if the ipv6 address is wrapped
irb(main):016:0> u.host = "[::2]"
=> "[::2]"
# hostname setter will wrap ipv6 addresses whether it's wrapped or not
irb(main):021:0> u.hostname = "::1"
=> "::1"
irb(main):022:0> u.host
=> "[::1]"
irb(main):023:0> u.hostname
=> "::1"
irb(main):024:0> u.hostname = "[::2]"
=> "[::2]"
irb(main):025:0> u.host
=> "[::2]"
irb(main):026:0> u.hostname
=> "::2"
... The only way to fix this was to have a "encoded/decoded getter/setter" in the URI/addressable libraries, ensure the This is not easy. Feel free to look at the various PRs that were required to get this working for IPv6: Of note: As a temporary measure, I added a monkey patch prepended module to get the ruby fix above so all of my manageiq client code can use the correct syntax (while I waited for that fix to be merged and released) Either way, clients needed to know when to use excon There were many others. |
what I mean by this is this
|
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 my comments, I don't think this is going to work.
@jhernand can you review the comments above. |
@Fryguy @jrafanie if adding the new @cben what do you think it will cost (in time) to replace |
@jhernand rest-client may in fact not be actively maintained anymore but from the looks of the issue that was opened, it might just be a single line that needs CGI.unescape. It seems far easier to verify this is the only place that needs it, make the change, add a test and open a PR, than to change the underlying http library in all of kubeclient. I have reached out to |
I opened a PR to rest-client, let's see if we can get it merged and released: rest-client/rest-client#665 |
@miq-bot add_label hammer/yes |
rest-client alongside URIs parse method introduces a bug where by usernames or passwords cannot have symbols in them. More Information: rest-client/rest-client#661 ManageIQ/manageiq#17318
rest-client alongside URIs parse method introduces a bug where by usernames or passwords cannot have symbols in them. More Information: rest-client/rest-client#661 ManageIQ/manageiq#17318
@jhernand can this be closed? I opened rest-client/rest-client#665 on rest-client... they haven't reviewed/merged/commented on it, so we monkey patched it here: #18105 I think that monkey patch makes this PR no longer needed. |
Not needed, I am closing it. |
The Ruby URI parser doesn't decode the percent encoded characters in the URI, in particular it doesn't decode the password which is frequently used when specifying proxy addresses and authentication. For example, the following code:
Produces the following output:
But some gems, in particular
rest-client
andkubeclient
, expect it to decode those characters, as they use the value returned by thepassword
method directly, and thus they fail to authenticate against the proxy server when the password contains percent encoded characters.To address this issue this patch adds a new
proxy
URI schema that almost identical to thehttp
schema, but that decodes the password before returning it. Users can use this schema instead ofhttp
whenthey need to use percent encoded characters in the password. For example, the user can type in the UI the following proxy URL:
And the new schema will automatically translate
%24%3fxxxx
into$?xxxx
.Fixes https://bugzilla.redhat.com/1566615.