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

[core-http] Proxy - Basic authentication support for storage-blob #5009

Merged

Conversation

HarshaNalluru
Copy link
Member

@HarshaNalluru HarshaNalluru commented Sep 5, 2019

ProxySettings may have username & password, but getDefaultProxySettings doesn't parse them. Storage Explorer current proxy settings need them.

This PR updates the core-http's getDefaultProxySettings. With this, basic authentication with username/password works.

@HarshaNalluru HarshaNalluru changed the title [core-http] Proxy Basic authentication support for storage-blob [core-http] Proxy - Basic authentication support for storage-blob Sep 5, 2019
@HarshaNalluru HarshaNalluru self-assigned this Sep 5, 2019
@HarshaNalluru HarshaNalluru added Azure.Core Client This issue points to a problem in the data-plane of the library. Storage Storage Service (Queues, Blobs, Files) labels Sep 5, 2019
@HarshaNalluru HarshaNalluru requested review from bterlson, ramya-rao-a and sophiajt and removed request for vinjiang and jiacfan September 5, 2019 21:42
@jeremymeng
Copy link
Member

It would be ideal if URLBuilder support urls with username and password. The change won't be simple though. Could you please log an issue for the future consideration?

@HarshaNalluru
Copy link
Member Author

HarshaNalluru commented Sep 5, 2019

Ideally, the updates to core-http should be in the master branch.
Once this is reviewed,

  • I'll make a PR to master scoping the changes to core-http and
  • then merge the master branch into feature/storage and
  • then another PR to feature/storage branch for the rest of the changes in this PR related to storage SDKs.

@HarshaNalluru
Copy link
Member Author

It would be ideal if URLBuilder support urls with username and password. The change won't be simple though. Could you please log an issue for future consideration?

Created an issue - #5011

proxyUrl?: string,
username?: string,
password?: string
): ProxySettings | undefined {
if (!proxyUrl) {
proxyUrl = loadEnvironmentProxyValue();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work with environment proxies?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation of loadEnvironmentProxyValue()

function loadEnvironmentProxyValue(): string | undefined {
if (!process) {
return undefined;
}
if (process.env[Constants.HTTPS_PROXY]) {
return process.env[Constants.HTTPS_PROXY];
} else if (process.env[Constants.HTTPS_PROXY.toLowerCase()]) {
return process.env[Constants.HTTPS_PROXY.toLowerCase()];
} else if (process.env[Constants.HTTP_PROXY]) {
return process.env[Constants.HTTP_PROXY];
} else if (process.env[Constants.HTTP_PROXY.toLowerCase()]) {
return process.env[Constants.HTTP_PROXY.toLowerCase()];
}
return undefined;
}

It is not obvious on how(or why) someone would set username/password as environment variables to load them from the environment with loadEnvironmentProxyValue.

We can go for some syntax like http://username:password@ipaddress:port for the proxyUrl variable and parse it properly.

Or we can avoid using getDefaultProxySettings like mentioned below - #5009 (comment).

Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the .NET tests they do support urls with credentials.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Supporting parsing http://username:password@ipaddress:port into a ProxySettings object seems like the right approach here.

It is not obvious on how(or why) someone would set username/password as environment variables to load them from the environment with loadEnvironmentProxyValue.

username/password are simply part of the proxy URL. One scenario I've seen many times is the proxy settings aren't controlled by the app developer but instead by the ops folks who control the production/staging environment. Devs just send requests like normal, ops folks ensure the environment variable is set properly, and everything "just works (tm)".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @bterlson, but would keep parsing username/password from the url out of this PR and out of the current preview.

proxy: { url: "http://localhost:3128" }
proxy: {
// username and password can be passed as additional arguments
url: "http://localhost:3128"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to show actually passing a username and password

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basic authentication works fine with current state of core-http if we pass in the ProxySettings as follows:

  {
    host: "127.0.0.1",
    port: 3128,
    username: "xxx",
    password: "xxx"
  }

to the proxyPolicy() out of the box.

But if we wanted to load these values from the environment variables instead then we can have related changes in. Technically the loading can be done from SDK as well.

Copy link
Member Author

@HarshaNalluru HarshaNalluru Sep 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ramya0820 Good idea. I think host should also include http:// or https://.

And ProxyOptions from storage sdks can be removed in favour of ProxySettings from core-http.

We can directly pass proxySettings to the proxyPolicy() method and avoid using getDefaultProxySettings.

if (isNode) {
// ProxyPolicy is only avaiable in Node.js runtime, not in browsers
factories.push(
proxyPolicy(
getDefaultProxySettings(pipelineOptions.proxy ? pipelineOptions.proxy.url : undefined)
)
);

Thoughts, anybody ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the url to access is present on the request, believe core-http attempts to infer the protocol from it.
Came across something about username:password@host being deprecated eventually.
Overall, if ProxySettings is exposed to user to pass in, that should be sufficient I think.
cc: @bterlson @chradek @ramya-rao-a

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personal opinion here, I defer to @bterlson for the final call:

I would expect an sdk to use getDefaultProxySettings if the user has provided no details on the proxy and we are expected to infer from the environment.

If the user is indeed providing proxy details, then I would prefer them to pass in the ProxySettings instead of the proxy url (with host + port).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProxyOptions should not exist and be replaced with ProxySettings.

The maximally flexible signature would take either a ProxySettings or a string proxy URL which is parsed into a ProxySettings. Given the late hour, I'm ok with punting on parsing string proxy URLs for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest something like ramya-rao-a@7dfbce1

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option is removing the options, and solely relying on the environment variables? It's Node-only anyway.

export function getDefaultProxySettings(
proxyUrl?: string,
username?: string,
password?: string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HarshaNalluru With the new set of changes, we should revert the changes to this file

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In progress. Pushing the changes.

@@ -13,7 +13,7 @@ export { OperationArguments } from "./operationArguments";
export { OperationParameter, OperationQueryParameter, OperationURLParameter } from "./operationParameter";
export { OperationResponse } from "./operationResponse";
export { OperationSpec } from "./operationSpec";
export { ServiceClient, ServiceClientOptions, flattenResponse } from "./serviceClient";
export { ServiceClient, ServiceClientOptions, flattenResponse, ProxySettings } from "./serviceClient";
Copy link
Member Author

@HarshaNalluru HarshaNalluru Sep 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only change related to core-http in this PR.

Made a separate PR to master - #5043.

I will then merge the master branch into feature/storage(#5046) and then merge this PR(basic auth support for storage-blob).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Azure.Core Client This issue points to a problem in the data-plane of the library. Storage Storage Service (Queues, Blobs, Files)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants