mirror of https://github.com/portainer/portainer
fix(helm) tighten up helm requests [EE-6722] (#11711)
Co-authored-by: testa113 <testa113>pull/11715/head
parent
02302f0959
commit
ba2bf365e6
|
@ -37,24 +37,25 @@ func NewHandler(bouncer security.BouncerService, dataStore dataservices.DataStor
|
||||||
kubeClusterAccessService: kubeClusterAccessService,
|
kubeClusterAccessService: kubeClusterAccessService,
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Use(middlewares.WithEndpoint(dataStore.Endpoint(), "id"))
|
h.Use(middlewares.WithEndpoint(dataStore.Endpoint(), "id"),
|
||||||
|
bouncer.AuthenticatedAccess)
|
||||||
|
|
||||||
// `helm list -o json`
|
// `helm list -o json`
|
||||||
h.Handle("/{id}/kubernetes/helm",
|
h.Handle("/{id}/kubernetes/helm",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.helmList))).Methods(http.MethodGet)
|
httperror.LoggerHandler(h.helmList)).Methods(http.MethodGet)
|
||||||
|
|
||||||
// `helm delete RELEASE_NAME`
|
// `helm delete RELEASE_NAME`
|
||||||
h.Handle("/{id}/kubernetes/helm/{release}",
|
h.Handle("/{id}/kubernetes/helm/{release}",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.helmDelete))).Methods(http.MethodDelete)
|
httperror.LoggerHandler(h.helmDelete)).Methods(http.MethodDelete)
|
||||||
|
|
||||||
// `helm install [NAME] [CHART] flags`
|
// `helm install [NAME] [CHART] flags`
|
||||||
h.Handle("/{id}/kubernetes/helm",
|
h.Handle("/{id}/kubernetes/helm",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.helmInstall))).Methods(http.MethodPost)
|
httperror.LoggerHandler(h.helmInstall)).Methods(http.MethodPost)
|
||||||
|
|
||||||
h.Handle("/{id}/kubernetes/helm/repositories",
|
h.Handle("/{id}/kubernetes/helm/repositories",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.userGetHelmRepos))).Methods(http.MethodGet)
|
httperror.LoggerHandler(h.userGetHelmRepos)).Methods(http.MethodGet)
|
||||||
h.Handle("/{id}/kubernetes/helm/repositories",
|
h.Handle("/{id}/kubernetes/helm/repositories",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.userCreateHelmRepo))).Methods(http.MethodPost)
|
httperror.LoggerHandler(h.userCreateHelmRepo)).Methods(http.MethodPost)
|
||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
@ -67,12 +68,14 @@ func NewTemplateHandler(bouncer security.BouncerService, helmPackageManager libh
|
||||||
requestBouncer: bouncer,
|
requestBouncer: bouncer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.Use(bouncer.AuthenticatedAccess)
|
||||||
|
|
||||||
h.Handle("/templates/helm",
|
h.Handle("/templates/helm",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.helmRepoSearch))).Methods(http.MethodGet)
|
httperror.LoggerHandler(h.helmRepoSearch)).Methods(http.MethodGet)
|
||||||
|
|
||||||
// helm show [COMMAND] [CHART] [REPO] flags
|
// helm show [COMMAND] [CHART] [REPO] flags
|
||||||
h.Handle("/templates/helm/{command:chart|values|readme}",
|
h.Handle("/templates/helm/{command:chart|values|readme}",
|
||||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.helmShow))).Methods(http.MethodGet)
|
httperror.LoggerHandler(h.helmShow)).Methods(http.MethodGet)
|
||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var errRequiredSearchOptions = errors.New("repo is required")
|
var errRequiredSearchOptions = errors.New("repo is required")
|
||||||
|
var errInvalidRepoURL = errors.New("the request failed since either the Helm repository was not found or the index.yaml is not valid")
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
APIVersion string `yaml:"apiVersion" json:"apiVersion"`
|
APIVersion string `yaml:"apiVersion" json:"apiVersion"`
|
||||||
|
@ -62,6 +63,11 @@ func (hbpm *helmBinaryPackageManager) SearchRepo(searchRepoOpts options.SearchRe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow redirect behavior to be overriden if specified.
|
||||||
|
if client.CheckRedirect == nil {
|
||||||
|
client.CheckRedirect = defaultCheckRedirect
|
||||||
|
}
|
||||||
|
|
||||||
url, err := url.ParseRequestURI(searchRepoOpts.Repo)
|
url, err := url.ParseRequestURI(searchRepoOpts.Repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, fmt.Sprintf("invalid helm chart URL: %s", searchRepoOpts.Repo))
|
return nil, errors.Wrap(err, fmt.Sprintf("invalid helm chart URL: %s", searchRepoOpts.Repo))
|
||||||
|
@ -70,20 +76,42 @@ func (hbpm *helmBinaryPackageManager) SearchRepo(searchRepoOpts options.SearchRe
|
||||||
url.Path = path.Join(url.Path, "index.yaml")
|
url.Path = path.Join(url.Path, "index.yaml")
|
||||||
resp, err := client.Get(url.String())
|
resp, err := client.Get(url.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to get index file")
|
return nil, errInvalidRepoURL
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var file File
|
var file File
|
||||||
err = yaml.NewDecoder(resp.Body).Decode(&file)
|
err = yaml.NewDecoder(resp.Body).Decode(&file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to decode index file")
|
return nil, errInvalidRepoURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate index.yaml
|
||||||
|
if file.APIVersion == "" || file.Entries == nil {
|
||||||
|
return nil, errInvalidRepoURL
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := json.Marshal(file)
|
result, err := json.Marshal(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to marshal index file")
|
return nil, errInvalidRepoURL
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// defaultCheckRedirect is a default CheckRedirect for helm
|
||||||
|
// We don't allow redirects to URLs not ending in index.yaml
|
||||||
|
// After that we follow the go http client behavior which is to stop
|
||||||
|
// after a maximum of 10 redirects
|
||||||
|
func defaultCheckRedirect(req *http.Request, via []*http.Request) error {
|
||||||
|
// The request url must end in index.yaml
|
||||||
|
if path.Base(req.URL.Path) != "index.yaml" {
|
||||||
|
return errors.New("the request URL must end in index.yaml")
|
||||||
|
}
|
||||||
|
|
||||||
|
// default behavior below
|
||||||
|
if len(via) >= 10 {
|
||||||
|
return errors.New("stopped after 10 redirects")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ func (hbpm *helmBinaryPackageManager) Show(showOpts options.ShowOptions) ([]byte
|
||||||
|
|
||||||
result, err := hbpm.run("show", args, showOpts.Env)
|
result, err := hbpm.run("show", args, showOpts.Env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to run helm show on specified args")
|
return nil, errors.New("the request failed since either the Helm repository was not found or the chart does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|
Loading…
Reference in New Issue