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

Improve credentials handling when fetching repo resources #3057

Merged
merged 5 commits into from
Jun 30, 2021

Conversation

antgamdia
Copy link
Contributor

@antgamdia antgamdia commented Jun 29, 2021

Description of the change

This PR adds a similar change as the Helm folks did in helm/helm@179f901

Now, the credentials will be passed to an external URL if: 1) a user adds pass-credentials to the repo OR 2) the domain in the chart index.yaml file matches the icon/tarball domain.

Benefits

Not passing credentials to external domains (such as icons and tarballs)

Possible drawbacks

If users don't explicitly decide to allow passing the credentials, in scenarios when the index.yaml URL doesn't match the icon/tarball URL domain, the credentials won't be passed through anymore.

Applicable issues

Additional information

image

More testing is required, I feel the mock clients we use here are not enough to make sure we are doing it right.

@antgamdia antgamdia self-assigned this Jun 29, 2021
@antgamdia antgamdia added this to In progress in Kubeapps via automation Jun 29, 2021
@antgamdia antgamdia moved this from In progress to Waiting For Review in Kubeapps Jun 29, 2021
@antgamdia antgamdia removed this from Waiting For Review in Kubeapps Jun 29, 2021
Copy link
Contributor

@absoludity absoludity left a comment

Choose a reason for hiding this comment

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

Excellent neat change from CR through to UX :)

@@ -54,6 +54,8 @@ type AppRepositorySpec struct {
FilterRule FilterRuleSpec `json:"filterRule,omitempty"`
// (optional) description
Description string `json:"description,omitempty"`
// PassCredentials allows passing credentials to all domains
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// PassCredentials allows passing credentials to all domains
// PassCredentials allows passing credentials with requests to other domains linked from the repository

authorizationHeader := ""
chartTarballURL := chartTarballURL(r.RepoInternal, cv)

if (passCredentials || compareURLDomains(chartTarballURL, r.URL)) && len(r.AuthorizationHeader) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Tiny point, but I'd generally have the len(r.AuthorizationHeader) > 0 condition first so the rest is only evaluated if there's authorization?

@@ -783,7 +790,7 @@ func (f *fileImporter) fetchAndImportIcon(c models.Chart, r *models.RepoInternal
return err
}
req.Header.Set("User-Agent", userAgent())
if len(r.AuthorizationHeader) > 0 {
if (passCredentials || compareURLDomains(c.Icon, r.URL)) && len(r.AuthorizationHeader) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto here.

if err != nil {
log.WithFields(log.Fields{"name": c.Name}).WithError(err).Error("failed to encode icon")
return err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice catch for the missing error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't take the credit here :P the merit is on vscode and https://github.com/golangci/golangci-lint this time:

image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mmm I'm dropping a card in the next interaction discussion for considering addressing all linter issues at once and adding it as part of the build process of our go dockerfiles


// Check if two URL strings are in the same domain.
// Return true if so, and false otherwise or when an error occurs
func compareURLDomains(url1Str, url2Str string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Slight preference for a name that indicates the boolean nature of this, such as isURLDomainEqual or hostsEqual.


a := url1.Hostname()
b := url2.Hostname()
// return url1.Hostname() == url2.Hostname()
Copy link
Contributor

Choose a reason for hiding this comment

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

Guessing this is what you intended to return rather than using the a and b unnecessarily?

But related to this, I reckon we should also ensure that the proto is the same (ie. both https). If the index.yaml was listed as https://example.com/index.yaml but referred to an icon at http://example.com/icons/foo.png, I'd hope we wouldn't assume it's the same host (ie. same host name but different proto). Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, just a leftover when running the debugger :P
Good catch! We have to verify the URL scheme as well, of course!

By the way, there is an interesting go testing feature that will get released in 1.17: Fuzzing tests: https://blog.golang.org/fuzz-beta
Testing this method would be an interesting use case indeed.

assert.Err(t, fmt.Errorf("401 %s", charts[0].Icon), fImporter.fetchAndImportIcon(charts[0], repo))
})

// t.Run("valid icon (passing through if same domain)", func(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure why this is commented out?

Copy link
Contributor Author

@antgamdia antgamdia Jun 30, 2021

Choose a reason for hiding this comment

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

Sorry, I commented all of them out so that running the test suite was quicker. I forgot to enable this one again 😬
Thanks for pointing it out!

"https://charts.bitnami.com/bitnami/airflow-10.2.0.tgz",
"https://charts.bitnami.com/assets/stacks/airflow/img/airflow-stack-220x234.png",
true,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

possibly tests for different proto?

Comment on lines 1318 to 1329
{
"it returns false if they are different subdomains",
"https://charts.bitnami.com/bitnami/index.yaml",
"https://bitnami.com/assets/stacks/airflow/img/airflow-stack-220x234.png",
false,
},
{
"it returns false if they are under different subdomains",
"https://bitnami.com/bitnami/index.yaml",
"https://charts.bitnami.com/assets/stacks/airflow/img/airflow-stack-220x234.png",
false,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

These two tests appear to be testing the same thing? Also, this is interesting - the subdomain. Is this the same behaviour in the helm patch? Asking because it's much more likely that I'd have my assets on a subdomain of the repo... but fine either way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They are using the same approach (below), so I think we should stick close to it. If a user happens to really need to pass the credentials down to a different subdomain, we may consider adding a --allowed-pass-credentials-subdomains flag

(u1.Scheme == u2.Scheme && u1.Host == u2.Host)

Side note: we were using .Hostname(), which yields the Host value without ports. Having noticed they also compare the ports, I've changed the PR's code to match their appraoch.

@antgamdia antgamdia merged commit 918f0ff into vmware-tanzu:master Jun 30, 2021
@antgamdia antgamdia deleted the addPassCredentials branch June 30, 2021 18:05
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.

Avoid using given auth credentials when syncing charts outside index.yaml hostname
2 participants