From 5d623a01ed20913e8b6ee212eda3162d494f8461 Mon Sep 17 00:00:00 2001 From: Blake Pettersson Date: Mon, 26 Jun 2023 16:23:50 +0200 Subject: [PATCH 1/7] fix: loosen source not permitted helm errors With #12255, we check if a source is first permitted before running `helm template`. This works a bit too well, since this may break previously working manifests. If an `AppProject` has a set of `sourceRepos` which are more restrictive than `*`, and it also has Helm public dependencies (repos with credentials would not work with 2.7x due to the fact they get filtered out before ending up on the repo server). Whereas before this would work, this currently fails on `HEAD` but not in `2.7x`. What we instead do here is that we only run this check if the chart failed to download - if it does then we run a check to see if the repo is in the allowed repos list. If the repo is not in the allowed repos list, we return the same error as in #12555, otherwise we bubble up the error. Should fix #13833. Signed-off-by: Blake Pettersson --- reposerver/repository/repository.go | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go index 25a5a0f937e3b..ed041666cfe10 100644 --- a/reposerver/repository/repository.go +++ b/reposerver/repository/repository.go @@ -1048,9 +1048,9 @@ func runHelmBuild(appPath string, h helm.Helm) error { manifestGenerateLock.Lock(appPath) defer manifestGenerateLock.Unlock(appPath) - // the `helm dependency build` is potentially time consuming 1~2 seconds - // marker file is used to check if command already run to avoid running it again unnecessary - // file is removed when repository re-initialized (e.g. when another commit is processed) + // the `helm dependency build` is potentially a time-consuming 1~2 seconds, + // a marker file is used to check if command already run to avoid running it again unnecessarily + // the file is removed when repository is re-initialized (e.g. when another commit is processed) markerFile := path.Join(appPath, helmDepUpMarkerFile) _, err := os.Stat(markerFile) if err == nil { @@ -1066,6 +1066,11 @@ func runHelmBuild(appPath string, h helm.Helm) error { return os.WriteFile(markerFile, []byte("marker"), 0644) } +func isSourcePermitted(url string, repos []string) bool { + p := v1alpha1.AppProject{Spec: v1alpha1.AppProjectSpec{SourceRepos: repos}} + return p.IsSourcePermitted(v1alpha1.ApplicationSource{RepoURL: url}) +} + func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclient.ManifestRequest, isLocal bool, gitRepoPaths io.TempPaths) ([]*unstructured.Unstructured, error) { concurrencyAllowed := isConcurrencyAllowed(appPath) if !concurrencyAllowed { @@ -1186,6 +1191,20 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie } if err != nil { + var reposNotPermitted []string + // We do a sanity check here to give a nicer error message in case any of the Helm repositories are not permitted by + // the AppProject which the application is a part of + for _, repo := range helmRepos { + match := regexp.MustCompile(fmt.Sprintf("could not download (oci|https?)://%s", repo.Repo)) + if match.MatchString(err.Error()) && !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { + reposNotPermitted = append(reposNotPermitted, repo.Repo) + } + } + + if len(reposNotPermitted) > 0 { + return nil, status.Errorf(codes.PermissionDenied, "helm repos %s are not permitted in project '%s'", strings.Join(reposNotPermitted, ", "), q.ProjectName) + } + return nil, err } From 85834f54128ae83f83dd1688948d6e9befba371c Mon Sep 17 00:00:00 2001 From: Blake Pettersson Date: Sat, 15 Jul 2023 16:28:43 +0200 Subject: [PATCH 2/7] fix: check for 401 unauthorized in error The regex check works fine for OCI artifacts, but the flow is slightly different for standard Helm charts (specifically when running `helm repo add`). To get around that, we also check the error for `401 Unauthorized`. Signed-off-by: Blake Pettersson --- reposerver/repository/repository.go | 2 +- test/e2e/helm_test.go | 40 +++++++++++++++++++ .../Chart.yaml | 8 +++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go index ed041666cfe10..3faff1b5f3ce6 100644 --- a/reposerver/repository/repository.go +++ b/reposerver/repository/repository.go @@ -1196,7 +1196,7 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie // the AppProject which the application is a part of for _, repo := range helmRepos { match := regexp.MustCompile(fmt.Sprintf("could not download (oci|https?)://%s", repo.Repo)) - if match.MatchString(err.Error()) && !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { + if (strings.Contains(err.Error(), "401 Unauthorized") || match.MatchString(err.Error())) && !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { reposNotPermitted = append(reposNotPermitted, repo.Repo) } } diff --git a/test/e2e/helm_test.go b/test/e2e/helm_test.go index 2aed6a6973b8f..23be345725d1d 100644 --- a/test/e2e/helm_test.go +++ b/test/e2e/helm_test.go @@ -20,6 +20,7 @@ import ( "github.com/argoproj/argo-cd/v2/test/e2e/fixture" . "github.com/argoproj/argo-cd/v2/test/e2e/fixture" . "github.com/argoproj/argo-cd/v2/test/e2e/fixture/app" + projectFixture "github.com/argoproj/argo-cd/v2/test/e2e/fixture/project" "github.com/argoproj/argo-cd/v2/test/e2e/fixture/repos" . "github.com/argoproj/argo-cd/v2/util/errors" "github.com/argoproj/argo-cd/v2/util/settings" @@ -400,6 +401,45 @@ func TestHelmWithMultipleDependencies(t *testing.T) { Expect(SyncStatusIs(SyncStatusCodeSynced)) } +func TestHelmWithMultipleDependenciesPermissionDenied(t *testing.T) { + SkipOnEnv(t, "HELM") + + projName := "argo-helm-project-denied" + projectFixture. + Given(t). + Name(projName). + Destination("*,*"). + When(). + Create(). + AddSource(RepoURL(RepoURLTypeFile)) + + expectedErr := fmt.Sprintf("helm repos localhost:5000/myrepo are not permitted in project '%s'", projName) + GivenWithSameState(t). + Project(projName). + Path("helm-oci-with-dependencies"). + CustomCACertAdded(). + HelmHTTPSCredentialsUserPassAdded(). + HelmPassCredentials(). + When(). + IgnoreErrors(). + CreateApp(). + Then(). + Expect(Error("", expectedErr)) + + expectedErr = fmt.Sprintf("helm repos https://localhost:9443/argo-e2e/testdata.git/helm-repo/local, https://localhost:9443/argo-e2e/testdata.git/helm-repo/local2 are not permitted in project '%s'", projName) + GivenWithSameState(t). + Project(projName). + Path("helm-with-multiple-dependencies"). + CustomCACertAdded(). + HelmHTTPSCredentialsUserPassAdded(). + HelmPassCredentials(). + When(). + IgnoreErrors(). + CreateApp(). + Then(). + Expect(Error("", expectedErr)) +} + func TestHelmWithDependenciesLegacyRepo(t *testing.T) { SkipOnEnv(t, "HELM") testHelmWithDependencies(t, "helm-with-dependencies", true) diff --git a/test/e2e/testdata/helm-with-multiple-dependencies/Chart.yaml b/test/e2e/testdata/helm-with-multiple-dependencies/Chart.yaml index fc1982761746c..97f351834ff68 100644 --- a/test/e2e/testdata/helm-with-multiple-dependencies/Chart.yaml +++ b/test/e2e/testdata/helm-with-multiple-dependencies/Chart.yaml @@ -1,7 +1,11 @@ apiVersion: v2 -name: helm-with-dependencies +name: helm-with-multiple-dependencies version: v1.0.0 dependencies: - name: helm - repository: "https://localhost:9444/argo-e2e/testdata.git/helm-repo/local" + repository: "https://localhost:9443/argo-e2e/testdata.git/helm-repo/local" version: v1.0.0 + - name: helm + repository: "https://localhost:9443/argo-e2e/testdata.git/helm-repo/local2" + version: v1.0.0 + alias: helm2 \ No newline at end of file From 213421c0017fb8aa6112fc3f8b2c864250472d59 Mon Sep 17 00:00:00 2001 From: Blake Pettersson Date: Sun, 16 Jul 2023 15:38:02 +0200 Subject: [PATCH 3/7] fix: loosen string check Signed-off-by: Blake Pettersson --- reposerver/repository/repository.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go index 3faff1b5f3ce6..3a6ad0fb8d096 100644 --- a/reposerver/repository/repository.go +++ b/reposerver/repository/repository.go @@ -1195,8 +1195,12 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie // We do a sanity check here to give a nicer error message in case any of the Helm repositories are not permitted by // the AppProject which the application is a part of for _, repo := range helmRepos { - match := regexp.MustCompile(fmt.Sprintf("could not download (oci|https?)://%s", repo.Repo)) - if (strings.Contains(err.Error(), "401 Unauthorized") || match.MatchString(err.Error())) && !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { + msg := err.Error() + + chartCannotBeReached := strings.Contains(msg, "is not a valid chart repository or cannot be reached") + couldNotDownloadChart := strings.Contains(msg, "could not download") + + if (chartCannotBeReached || couldNotDownloadChart) && !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { reposNotPermitted = append(reposNotPermitted, repo.Repo) } } From a41aa764fd3d737d326583da9ca05f66c5b68636 Mon Sep 17 00:00:00 2001 From: Blake Pettersson Date: Wed, 9 Aug 2023 17:47:10 +0200 Subject: [PATCH 4/7] Revert "chore: revert #12255 (#14858)" This reverts commit c8ae5bc3e79fa985632861f75669c07523f5ded6. Signed-off-by: Blake Pettersson --- cmd/argocd/commands/app.go | 42 ++- cmd/argocd/commands/project.go | 14 +- controller/state.go | 2 + reposerver/apiclient/repository.pb.go | 400 +++++++++++++++-------- reposerver/repository/repository.go | 14 + reposerver/repository/repository.proto | 4 + reposerver/repository/repository_test.go | 170 +++++++--- server/application/application.go | 16 + util/argo/argo.go | 4 + 9 files changed, 455 insertions(+), 211 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index cf927b1edfece..82af6f7e3b004 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -846,9 +846,9 @@ func targetObjects(resources []*argoappv1.ResourceDiff) ([]*unstructured.Unstruc return objs, nil } -func getLocalObjects(ctx context.Context, app *argoappv1.Application, local, localRepoRoot, appLabelKey, kubeVersion string, apiVersions []string, kustomizeOptions *argoappv1.KustomizeOptions, +func getLocalObjects(ctx context.Context, app *argoappv1.Application, proj *argoappv1.AppProject, local, localRepoRoot, appLabelKey, kubeVersion string, apiVersions []string, kustomizeOptions *argoappv1.KustomizeOptions, trackingMethod string) []*unstructured.Unstructured { - manifestStrings := getLocalObjectsString(ctx, app, local, localRepoRoot, appLabelKey, kubeVersion, apiVersions, kustomizeOptions, trackingMethod) + manifestStrings := getLocalObjectsString(ctx, app, proj, local, localRepoRoot, appLabelKey, kubeVersion, apiVersions, kustomizeOptions, trackingMethod) objs := make([]*unstructured.Unstructured, len(manifestStrings)) for i := range manifestStrings { obj := unstructured.Unstructured{} @@ -859,19 +859,21 @@ func getLocalObjects(ctx context.Context, app *argoappv1.Application, local, loc return objs } -func getLocalObjectsString(ctx context.Context, app *argoappv1.Application, local, localRepoRoot, appLabelKey, kubeVersion string, apiVersions []string, kustomizeOptions *argoappv1.KustomizeOptions, +func getLocalObjectsString(ctx context.Context, app *argoappv1.Application, proj *argoappv1.AppProject, local, localRepoRoot, appLabelKey, kubeVersion string, apiVersions []string, kustomizeOptions *argoappv1.KustomizeOptions, trackingMethod string) []string { source := app.Spec.GetSource() res, err := repository.GenerateManifests(ctx, local, localRepoRoot, source.TargetRevision, &repoapiclient.ManifestRequest{ - Repo: &argoappv1.Repository{Repo: source.RepoURL}, - AppLabelKey: appLabelKey, - AppName: app.Name, - Namespace: app.Spec.Destination.Namespace, - ApplicationSource: &source, - KustomizeOptions: kustomizeOptions, - KubeVersion: kubeVersion, - ApiVersions: apiVersions, - TrackingMethod: trackingMethod, + Repo: &argoappv1.Repository{Repo: source.RepoURL}, + AppLabelKey: appLabelKey, + AppName: app.Name, + Namespace: app.Spec.Destination.Namespace, + ApplicationSource: &source, + KustomizeOptions: kustomizeOptions, + KubeVersion: kubeVersion, + ApiVersions: apiVersions, + TrackingMethod: trackingMethod, + ProjectName: proj.Name, + ProjectSourceRepos: proj.Spec.SourceRepos, }, true, &git.NoopCredsStore{}, resource.MustParse("0"), nil) errors.CheckError(err) @@ -989,7 +991,8 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co diffOption.cluster = cluster } } - foundDiffs := findandPrintDiff(ctx, app, resources, argoSettings, diffOption) + proj := getProject(c, clientOpts, ctx, app.Spec.Project) + foundDiffs := findandPrintDiff(ctx, app, proj.Project, resources, argoSettings, diffOption) if foundDiffs && exitCode { os.Exit(1) } @@ -1017,13 +1020,13 @@ type DifferenceOption struct { } // findandPrintDiff ... Prints difference between application current state and state stored in git or locally, returns boolean as true if difference is found else returns false -func findandPrintDiff(ctx context.Context, app *argoappv1.Application, resources *application.ManagedResourcesResponse, argoSettings *settings.Settings, diffOptions *DifferenceOption) bool { +func findandPrintDiff(ctx context.Context, app *argoappv1.Application, proj *argoappv1.AppProject, resources *application.ManagedResourcesResponse, argoSettings *settings.Settings, diffOptions *DifferenceOption) bool { var foundDiffs bool liveObjs, err := cmdutil.LiveObjects(resources.Items) errors.CheckError(err) items := make([]objKeyLiveTarget, 0) if diffOptions.local != "" { - localObjs := groupObjsByKey(getLocalObjects(ctx, app, diffOptions.local, diffOptions.localRepoRoot, argoSettings.AppLabelKey, diffOptions.cluster.Info.ServerVersion, diffOptions.cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.TrackingMethod), liveObjs, app.Spec.Destination.Namespace) + localObjs := groupObjsByKey(getLocalObjects(ctx, app, proj, diffOptions.local, diffOptions.localRepoRoot, argoSettings.AppLabelKey, diffOptions.cluster.Info.ServerVersion, diffOptions.cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.TrackingMethod), liveObjs, app.Spec.Destination.Namespace) items = groupObjsForDiff(resources, localObjs, items, argoSettings, app.InstanceName(argoSettings.ControllerNamespace), app.Spec.Destination.Namespace) } else if diffOptions.revision != "" { var unstructureds []*unstructured.Unstructured @@ -1694,7 +1697,8 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co errors.CheckError(err) argoio.Close(conn) - localObjsStrings = getLocalObjectsString(ctx, app, local, localRepoRoot, argoSettings.AppLabelKey, cluster.Info.ServerVersion, cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.TrackingMethod) + proj := getProject(c, clientOpts, ctx, app.Spec.Project) + localObjsStrings = getLocalObjectsString(ctx, app, proj.Project, local, localRepoRoot, argoSettings.AppLabelKey, cluster.Info.ServerVersion, cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.TrackingMethod) errors.CheckError(err) diffOption.local = local diffOption.localRepoRoot = localRepoRoot @@ -1764,7 +1768,8 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co foundDiffs := false fmt.Printf("====== Previewing differences between live and desired state of application %s ======\n", appQualifiedName) - foundDiffs = findandPrintDiff(ctx, app, resources, argoSettings, diffOption) + proj := getProject(c, clientOpts, ctx, app.Spec.Project) + foundDiffs = findandPrintDiff(ctx, app, proj.Project, resources, argoSettings, diffOption) if foundDiffs { if !diffChangesConfirm { yesno := cli.AskToProceed(fmt.Sprintf("Please review changes to application %s shown above. Do you want to continue the sync process? (y/n): ", appQualifiedName)) @@ -2376,7 +2381,8 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob cluster, err := clusterIf.Get(context.Background(), &clusterpkg.ClusterQuery{Name: app.Spec.Destination.Name, Server: app.Spec.Destination.Server}) errors.CheckError(err) - unstructureds = getLocalObjects(context.Background(), app, local, localRepoRoot, argoSettings.AppLabelKey, cluster.ServerVersion, cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.TrackingMethod) + proj := getProject(c, clientOpts, ctx, app.Spec.Project) + unstructureds = getLocalObjects(context.Background(), app, proj.Project, local, localRepoRoot, argoSettings.AppLabelKey, cluster.ServerVersion, cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.TrackingMethod) } else if revision != "" { q := application.ApplicationManifestQuery{ Name: &appName, diff --git a/cmd/argocd/commands/project.go b/cmd/argocd/commands/project.go index fc7b6617c13b9..4f08665eb437b 100644 --- a/cmd/argocd/commands/project.go +++ b/cmd/argocd/commands/project.go @@ -1,6 +1,7 @@ package commands import ( + "context" "encoding/json" "fmt" "io" @@ -818,10 +819,7 @@ func NewProjectGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command os.Exit(1) } projName := args[0] - conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() - defer argoio.Close(conn) - detailedProject, err := projIf.GetDetailedProject(ctx, &projectpkg.ProjectQuery{Name: projName}) - errors.CheckError(err) + detailedProject := getProject(c, clientOpts, ctx, projName) switch output { case "yaml", "json": @@ -838,6 +836,14 @@ func NewProjectGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command return command } +func getProject(c *cobra.Command, clientOpts *argocdclient.ClientOptions, ctx context.Context, projName string) *projectpkg.DetailedProjectsResponse { + conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() + defer argoio.Close(conn) + detailedProject, err := projIf.GetDetailedProject(ctx, &projectpkg.ProjectQuery{Name: projName}) + errors.CheckError(err) + return detailedProject +} + func NewProjectEditCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { var command = &cobra.Command{ Use: "edit PROJECT", diff --git a/controller/state.go b/controller/state.go index a2765f249bc82..8b9842d91b249 100644 --- a/controller/state.go +++ b/controller/state.go @@ -200,6 +200,8 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, sources []v1alp HelmOptions: helmOptions, HasMultipleSources: app.Spec.HasMultipleSources(), RefSources: refSources, + ProjectName: proj.Name, + ProjectSourceRepos: proj.Spec.SourceRepos, }) if err != nil { return nil, nil, fmt.Errorf("failed to generate manifest for source %d of %d: %w", i+1, len(sources), err) diff --git a/reposerver/apiclient/repository.pb.go b/reposerver/apiclient/repository.pb.go index 3dcacedd00933..4c05248b87e16 100644 --- a/reposerver/apiclient/repository.pb.go +++ b/reposerver/apiclient/repository.pb.go @@ -46,17 +46,21 @@ type ManifestRequest struct { KubeVersion string `protobuf:"bytes,14,opt,name=kubeVersion,proto3" json:"kubeVersion,omitempty"` ApiVersions []string `protobuf:"bytes,15,rep,name=apiVersions,proto3" json:"apiVersions,omitempty"` // Request to verify the signature when generating the manifests (only for Git repositories) - VerifySignature bool `protobuf:"varint,16,opt,name=verifySignature,proto3" json:"verifySignature,omitempty"` - HelmRepoCreds []*v1alpha1.RepoCreds `protobuf:"bytes,17,rep,name=helmRepoCreds,proto3" json:"helmRepoCreds,omitempty"` - NoRevisionCache bool `protobuf:"varint,18,opt,name=noRevisionCache,proto3" json:"noRevisionCache,omitempty"` - TrackingMethod string `protobuf:"bytes,19,opt,name=trackingMethod,proto3" json:"trackingMethod,omitempty"` - EnabledSourceTypes map[string]bool `protobuf:"bytes,20,rep,name=enabledSourceTypes,proto3" json:"enabledSourceTypes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` - HelmOptions *v1alpha1.HelmOptions `protobuf:"bytes,21,opt,name=helmOptions,proto3" json:"helmOptions,omitempty"` - HasMultipleSources bool `protobuf:"varint,22,opt,name=hasMultipleSources,proto3" json:"hasMultipleSources,omitempty"` - RefSources map[string]*v1alpha1.RefTarget `protobuf:"bytes,23,rep,name=refSources,proto3" json:"refSources,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + VerifySignature bool `protobuf:"varint,16,opt,name=verifySignature,proto3" json:"verifySignature,omitempty"` + HelmRepoCreds []*v1alpha1.RepoCreds `protobuf:"bytes,17,rep,name=helmRepoCreds,proto3" json:"helmRepoCreds,omitempty"` + NoRevisionCache bool `protobuf:"varint,18,opt,name=noRevisionCache,proto3" json:"noRevisionCache,omitempty"` + TrackingMethod string `protobuf:"bytes,19,opt,name=trackingMethod,proto3" json:"trackingMethod,omitempty"` + EnabledSourceTypes map[string]bool `protobuf:"bytes,20,rep,name=enabledSourceTypes,proto3" json:"enabledSourceTypes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + HelmOptions *v1alpha1.HelmOptions `protobuf:"bytes,21,opt,name=helmOptions,proto3" json:"helmOptions,omitempty"` + HasMultipleSources bool `protobuf:"varint,22,opt,name=hasMultipleSources,proto3" json:"hasMultipleSources,omitempty"` + RefSources map[string]*v1alpha1.RefTarget `protobuf:"bytes,23,rep,name=refSources,proto3" json:"refSources,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // This is used to surface "source not permitted" errors for Helm repositories + ProjectSourceRepos []string `protobuf:"bytes,24,rep,name=projectSourceRepos,proto3" json:"projectSourceRepos,omitempty"` + // This is used to surface "source not permitted" errors for Helm repositories + ProjectName string `protobuf:"bytes,25,opt,name=projectName,proto3" json:"projectName,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ManifestRequest) Reset() { *m = ManifestRequest{} } @@ -232,6 +236,20 @@ func (m *ManifestRequest) GetRefSources() map[string]*v1alpha1.RefTarget { return nil } +func (m *ManifestRequest) GetProjectSourceRepos() []string { + if m != nil { + return m.ProjectSourceRepos + } + return nil +} + +func (m *ManifestRequest) GetProjectName() string { + if m != nil { + return m.ProjectName + } + return "" +} + type ManifestRequestWithFiles struct { // Types that are valid to be assigned to Part: // *ManifestRequestWithFiles_Request @@ -2171,138 +2189,140 @@ func init() { } var fileDescriptor_dd8723cfcc820480 = []byte{ - // 2085 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x5b, 0x6f, 0x1b, 0xc7, - 0xf5, 0xe7, 0x92, 0xba, 0x90, 0x47, 0xb6, 0x45, 0x8d, 0x75, 0x59, 0x33, 0x8e, 0xa0, 0xec, 0xff, - 0x6f, 0x43, 0xb5, 0x13, 0x12, 0x92, 0x91, 0xb8, 0x70, 0xd2, 0x14, 0x8a, 0x62, 0x4b, 0x8e, 0x2d, - 0x5b, 0x5d, 0xbb, 0x2d, 0xd2, 0xba, 0x2d, 0x86, 0xcb, 0xe1, 0x72, 0xc2, 0xbd, 0x8c, 0x77, 0x67, - 0x15, 0xc8, 0x40, 0x1f, 0x8a, 0x16, 0x05, 0xfa, 0x05, 0x8a, 0xa2, 0xdf, 0xa3, 0xe8, 0x53, 0xd1, - 0xa7, 0x5e, 0x1e, 0x83, 0x7e, 0x81, 0x16, 0xfe, 0x24, 0xc5, 0xcc, 0xce, 0x5e, 0xb9, 0x92, 0x9d, - 0x52, 0x56, 0x50, 0xf4, 0xc5, 0xde, 0x99, 0x39, 0xb7, 0x39, 0x73, 0xe6, 0x9c, 0xdf, 0x19, 0x0a, - 0xae, 0x07, 0x84, 0xf9, 0x21, 0x09, 0x8e, 0x48, 0xd0, 0x93, 0x9f, 0x94, 0xfb, 0xc1, 0x71, 0xee, - 0xb3, 0xcb, 0x02, 0x9f, 0xfb, 0x08, 0xb2, 0x99, 0xce, 0x43, 0x9b, 0xf2, 0x51, 0xd4, 0xef, 0x5a, - 0xbe, 0xdb, 0xc3, 0x81, 0xed, 0xb3, 0xc0, 0xff, 0x42, 0x7e, 0xbc, 0x67, 0x0d, 0x7a, 0x47, 0xdb, - 0x3d, 0x36, 0xb6, 0x7b, 0x98, 0xd1, 0xb0, 0x87, 0x19, 0x73, 0xa8, 0x85, 0x39, 0xf5, 0xbd, 0xde, - 0xd1, 0x16, 0x76, 0xd8, 0x08, 0x6f, 0xf5, 0x6c, 0xe2, 0x91, 0x00, 0x73, 0x32, 0x88, 0x25, 0x77, - 0xde, 0xb2, 0x7d, 0xdf, 0x76, 0x48, 0x4f, 0x8e, 0xfa, 0xd1, 0xb0, 0x47, 0x5c, 0xc6, 0x95, 0x5a, - 0xe3, 0x77, 0x17, 0x60, 0xf1, 0x00, 0x7b, 0x74, 0x48, 0x42, 0x6e, 0x92, 0xe7, 0x11, 0x09, 0x39, - 0x7a, 0x06, 0x33, 0xc2, 0x18, 0x5d, 0xdb, 0xd0, 0x36, 0x17, 0xb6, 0xf7, 0xbb, 0x99, 0x35, 0xdd, - 0xc4, 0x1a, 0xf9, 0xf1, 0x33, 0x6b, 0xd0, 0x3d, 0xda, 0xee, 0xb2, 0xb1, 0xdd, 0x15, 0xd6, 0x74, - 0x73, 0xd6, 0x74, 0x13, 0x6b, 0xba, 0x66, 0xba, 0x2d, 0x53, 0x4a, 0x45, 0x1d, 0x68, 0x06, 0xe4, - 0x88, 0x86, 0xd4, 0xf7, 0xf4, 0xfa, 0x86, 0xb6, 0xd9, 0x32, 0xd3, 0x31, 0xd2, 0x61, 0xde, 0xf3, - 0x77, 0xb1, 0x35, 0x22, 0x7a, 0x63, 0x43, 0xdb, 0x6c, 0x9a, 0xc9, 0x10, 0x6d, 0xc0, 0x02, 0x66, - 0xec, 0x21, 0xee, 0x13, 0xe7, 0x01, 0x39, 0xd6, 0x67, 0x24, 0x63, 0x7e, 0x4a, 0xf0, 0x62, 0xc6, - 0x1e, 0x61, 0x97, 0xe8, 0xb3, 0x72, 0x35, 0x19, 0xa2, 0xab, 0xd0, 0xf2, 0xb0, 0x4b, 0x42, 0x86, - 0x2d, 0xa2, 0x37, 0xe5, 0x5a, 0x36, 0x81, 0x7e, 0x0e, 0x4b, 0x39, 0xc3, 0x9f, 0xf8, 0x51, 0x60, - 0x11, 0x1d, 0xe4, 0xd6, 0x1f, 0x4f, 0xb7, 0xf5, 0x9d, 0xb2, 0x58, 0x73, 0x52, 0x13, 0xfa, 0x29, - 0xcc, 0xca, 0x93, 0xd7, 0x17, 0x36, 0x1a, 0x67, 0xea, 0xed, 0x58, 0x2c, 0xf2, 0x60, 0x9e, 0x39, - 0x91, 0x4d, 0xbd, 0x50, 0xbf, 0x20, 0x35, 0x3c, 0x9d, 0x4e, 0xc3, 0xae, 0xef, 0x0d, 0xa9, 0x7d, - 0x80, 0x3d, 0x6c, 0x13, 0x97, 0x78, 0xfc, 0x50, 0x0a, 0x37, 0x13, 0x25, 0xe8, 0x05, 0xb4, 0xc7, - 0x51, 0xc8, 0x7d, 0x97, 0xbe, 0x20, 0x8f, 0x99, 0xe0, 0x0d, 0xf5, 0x8b, 0xd2, 0x9b, 0x8f, 0xa6, - 0x53, 0xfc, 0xa0, 0x24, 0xd5, 0x9c, 0xd0, 0x23, 0x82, 0x64, 0x1c, 0xf5, 0xc9, 0x0f, 0x48, 0x20, - 0xa3, 0xeb, 0x52, 0x1c, 0x24, 0xb9, 0xa9, 0x38, 0x8c, 0xa8, 0x1a, 0x85, 0xfa, 0xe2, 0x46, 0x23, - 0x0e, 0xa3, 0x74, 0x0a, 0x6d, 0xc2, 0xe2, 0x11, 0x09, 0xe8, 0xf0, 0xf8, 0x09, 0xb5, 0x3d, 0xcc, - 0xa3, 0x80, 0xe8, 0x6d, 0x19, 0x8a, 0xe5, 0x69, 0xe4, 0xc2, 0xc5, 0x11, 0x71, 0x5c, 0xe1, 0xf2, - 0xdd, 0x80, 0x0c, 0x42, 0x7d, 0x49, 0xfa, 0x77, 0x6f, 0xfa, 0x13, 0x94, 0xe2, 0xcc, 0xa2, 0x74, - 0x61, 0x98, 0xe7, 0x9b, 0xea, 0xa6, 0xc4, 0x77, 0x04, 0xc5, 0x86, 0x95, 0xa6, 0xd1, 0x75, 0xb8, - 0xc4, 0x03, 0x6c, 0x8d, 0xa9, 0x67, 0x1f, 0x10, 0x3e, 0xf2, 0x07, 0xfa, 0x65, 0xe9, 0x89, 0xd2, - 0x2c, 0xb2, 0x00, 0x11, 0x0f, 0xf7, 0x1d, 0x32, 0x88, 0x63, 0xf1, 0xe9, 0x31, 0x23, 0xa1, 0xbe, - 0x2c, 0x77, 0x71, 0xab, 0x9b, 0xcb, 0x50, 0xa5, 0x04, 0xd1, 0xbd, 0x3b, 0xc1, 0x75, 0xd7, 0xe3, - 0xc1, 0xb1, 0x59, 0x21, 0x0e, 0x8d, 0x61, 0x41, 0xec, 0x23, 0x09, 0x85, 0x15, 0x19, 0x0a, 0xf7, - 0xa7, 0xf3, 0xd1, 0x7e, 0x26, 0xd0, 0xcc, 0x4b, 0x47, 0x5d, 0x40, 0x23, 0x1c, 0x1e, 0x44, 0x0e, - 0xa7, 0xcc, 0x21, 0xb1, 0x19, 0xa1, 0xbe, 0x2a, 0xdd, 0x54, 0xb1, 0x82, 0x1e, 0x00, 0x04, 0x64, - 0x98, 0xd0, 0xad, 0xc9, 0x9d, 0xdf, 0x3c, 0x6d, 0xe7, 0x66, 0x4a, 0x1d, 0xef, 0x38, 0xc7, 0xde, - 0xb9, 0x0b, 0x6b, 0x27, 0x38, 0x06, 0xb5, 0xa1, 0x31, 0x26, 0xc7, 0x32, 0xa1, 0xb6, 0x4c, 0xf1, - 0x89, 0x96, 0x61, 0xf6, 0x08, 0x3b, 0x11, 0x91, 0x29, 0xb0, 0x69, 0xc6, 0x83, 0x3b, 0xf5, 0x6f, - 0x6b, 0x9d, 0x5f, 0x6b, 0xb0, 0x58, 0x52, 0x53, 0xc1, 0xff, 0x93, 0x3c, 0xff, 0x19, 0x04, 0xdd, - 0xf0, 0x29, 0x0e, 0x6c, 0xc2, 0x73, 0x86, 0x18, 0xff, 0xd0, 0x40, 0x2f, 0xed, 0xff, 0x87, 0x94, - 0x8f, 0xee, 0x51, 0x87, 0x84, 0xe8, 0x36, 0xcc, 0x07, 0xf1, 0x9c, 0x2a, 0x13, 0x6f, 0x9d, 0xe2, - 0xb6, 0xfd, 0x9a, 0x99, 0x50, 0xa3, 0x8f, 0xa1, 0xe9, 0x12, 0x8e, 0x07, 0x98, 0x63, 0x65, 0xfb, - 0x46, 0x15, 0xa7, 0xd0, 0x72, 0xa0, 0xe8, 0xf6, 0x6b, 0x66, 0xca, 0x83, 0xde, 0x87, 0x59, 0x6b, - 0x14, 0x79, 0x63, 0x59, 0x20, 0x16, 0xb6, 0xdf, 0x3e, 0x89, 0x79, 0x57, 0x10, 0xed, 0xd7, 0xcc, - 0x98, 0xfa, 0x93, 0x39, 0x98, 0x61, 0x38, 0xe0, 0xc6, 0x3d, 0x58, 0xae, 0x52, 0x21, 0xaa, 0x92, - 0x35, 0x22, 0xd6, 0x38, 0x8c, 0x5c, 0xe5, 0xe6, 0x74, 0x8c, 0x10, 0xcc, 0x84, 0xf4, 0x45, 0xec, - 0xea, 0x86, 0x29, 0xbf, 0x8d, 0x6f, 0xc1, 0xd2, 0x84, 0x36, 0x71, 0xa8, 0xb1, 0x6d, 0x42, 0xc2, - 0x05, 0xa5, 0xda, 0x88, 0x60, 0xe5, 0xa9, 0xf4, 0x45, 0x9a, 0x9a, 0xcf, 0xa3, 0xce, 0x1a, 0xfb, - 0xb0, 0x5a, 0x56, 0x1b, 0x32, 0xdf, 0x0b, 0x89, 0xb8, 0x25, 0x32, 0x97, 0x51, 0x32, 0xc8, 0x56, - 0xa5, 0x15, 0x4d, 0xb3, 0x62, 0xc5, 0xf8, 0x45, 0x1d, 0x56, 0x4d, 0x12, 0xfa, 0xce, 0x11, 0x49, - 0x12, 0xcd, 0xf9, 0x40, 0x85, 0x1f, 0x43, 0x03, 0x33, 0xa6, 0xc2, 0xe4, 0xfe, 0x99, 0x15, 0x63, - 0x53, 0x48, 0x45, 0xef, 0xc2, 0x12, 0x76, 0xfb, 0xd4, 0x8e, 0xfc, 0x28, 0x4c, 0xb6, 0x25, 0x83, - 0xaa, 0x65, 0x4e, 0x2e, 0x18, 0x16, 0xac, 0x4d, 0xb8, 0x40, 0xb9, 0x33, 0x0f, 0x68, 0xb4, 0x12, - 0xa0, 0xa9, 0x54, 0x52, 0x3f, 0x49, 0xc9, 0x5f, 0x35, 0x68, 0x67, 0x57, 0x47, 0x89, 0xbf, 0x0a, - 0x2d, 0x57, 0xcd, 0x85, 0xba, 0x26, 0x0b, 0x56, 0x36, 0x51, 0xc4, 0x36, 0xf5, 0x32, 0xb6, 0x59, - 0x85, 0xb9, 0x18, 0x7a, 0xaa, 0x8d, 0xa9, 0x51, 0xc1, 0xe4, 0x99, 0x92, 0xc9, 0xeb, 0x00, 0x61, - 0x9a, 0xbf, 0xf4, 0x39, 0xb9, 0x9a, 0x9b, 0x41, 0x06, 0x5c, 0x88, 0x2b, 0xa1, 0x49, 0xc2, 0xc8, - 0xe1, 0xfa, 0xbc, 0xa4, 0x28, 0xcc, 0x19, 0x3e, 0x2c, 0x3e, 0xa4, 0x62, 0x0f, 0xc3, 0xf0, 0x7c, - 0x82, 0xfd, 0x03, 0x98, 0x11, 0xca, 0xc4, 0xc6, 0xfa, 0x01, 0xf6, 0xac, 0x11, 0x49, 0x7c, 0x95, - 0x8e, 0xc5, 0x35, 0xe6, 0xd8, 0x0e, 0xf5, 0xba, 0x9c, 0x97, 0xdf, 0xc6, 0x1f, 0xeb, 0xb1, 0xa5, - 0x3b, 0x8c, 0x85, 0xdf, 0x3c, 0xfc, 0xad, 0x2e, 0xc8, 0x8d, 0xc9, 0x82, 0x5c, 0x32, 0xf9, 0xeb, - 0x14, 0xe4, 0x33, 0x2a, 0x53, 0x46, 0x04, 0xf3, 0x3b, 0x8c, 0x09, 0x43, 0xd0, 0x16, 0xcc, 0x60, - 0xc6, 0x62, 0x87, 0x97, 0x32, 0xb2, 0x22, 0x11, 0xff, 0x2b, 0x93, 0x24, 0x69, 0xe7, 0x36, 0xb4, - 0xd2, 0xa9, 0x57, 0xa9, 0x6d, 0xe5, 0xd5, 0x6e, 0x00, 0xc4, 0x88, 0xf3, 0xbe, 0x37, 0xf4, 0xc5, - 0x91, 0x8a, 0x60, 0x57, 0xac, 0xf2, 0xdb, 0xb8, 0x93, 0x50, 0x48, 0xdb, 0xde, 0x85, 0x59, 0xca, - 0x89, 0x9b, 0x18, 0xb7, 0x9a, 0x37, 0x2e, 0x13, 0x64, 0xc6, 0x44, 0xc6, 0xdf, 0x9a, 0x70, 0x45, - 0x9c, 0xd8, 0x13, 0x79, 0x4d, 0x76, 0x18, 0xfb, 0x94, 0x70, 0x4c, 0x9d, 0xf0, 0x7b, 0x11, 0x09, - 0x8e, 0xdf, 0x70, 0x60, 0xd8, 0x30, 0x17, 0xdf, 0x32, 0x95, 0xef, 0xce, 0xbc, 0xf9, 0x50, 0xe2, - 0xb3, 0x8e, 0xa3, 0xf1, 0x66, 0x3a, 0x8e, 0xaa, 0x0e, 0x60, 0xe6, 0x9c, 0x3a, 0x80, 0x93, 0x9b, - 0xc0, 0x5c, 0x6b, 0x39, 0x57, 0x6c, 0x2d, 0x2b, 0x80, 0xf5, 0xfc, 0xeb, 0x02, 0xeb, 0x66, 0x25, - 0xb0, 0x76, 0x2b, 0xef, 0x71, 0x4b, 0xba, 0xfb, 0x3b, 0xf9, 0x08, 0x3c, 0x31, 0xd6, 0xa6, 0x81, - 0xd8, 0xf0, 0x46, 0x21, 0xf6, 0xf7, 0x0b, 0x90, 0x39, 0x6e, 0x5a, 0xdf, 0x7f, 0xbd, 0x3d, 0xfd, - 0x2f, 0x81, 0xe7, 0x5f, 0x49, 0xcc, 0xc4, 0xfc, 0xcc, 0x07, 0x69, 0x41, 0x17, 0x75, 0x48, 0x94, - 0x56, 0x95, 0xb4, 0xc4, 0x37, 0xba, 0x09, 0x33, 0xc2, 0xc9, 0x0a, 0xd4, 0xae, 0xe5, 0xfd, 0x29, - 0x4e, 0x62, 0x87, 0xb1, 0x27, 0x8c, 0x58, 0xa6, 0x24, 0x42, 0x77, 0xa0, 0x95, 0x06, 0xbe, 0xba, - 0x59, 0x57, 0xf3, 0x1c, 0xe9, 0x3d, 0x49, 0xd8, 0x32, 0x72, 0xc1, 0x3b, 0xa0, 0x01, 0xb1, 0x24, - 0xe4, 0x9b, 0x9d, 0xe4, 0xfd, 0x34, 0x59, 0x4c, 0x79, 0x53, 0x72, 0xb4, 0x05, 0x73, 0x71, 0x97, - 0x2f, 0x6f, 0xd0, 0xc2, 0xf6, 0x95, 0xc9, 0x64, 0x9a, 0x70, 0x29, 0x42, 0xe3, 0x2f, 0x1a, 0xbc, - 0x93, 0x05, 0x44, 0x72, 0x9b, 0x12, 0xd4, 0xfd, 0xcd, 0x57, 0xdc, 0xeb, 0x70, 0x49, 0xc2, 0xfc, - 0xac, 0xd9, 0x8f, 0xdf, 0x9d, 0x4a, 0xb3, 0xc6, 0x1f, 0x34, 0xb8, 0x36, 0xb9, 0x8f, 0xdd, 0x11, - 0x0e, 0x78, 0x7a, 0xbc, 0xe7, 0xb1, 0x97, 0xa4, 0xe0, 0xd5, 0xb3, 0x82, 0x57, 0xd8, 0x5f, 0xa3, - 0xb8, 0x3f, 0xe3, 0xcf, 0x75, 0x58, 0xc8, 0x05, 0x50, 0x55, 0xc1, 0x14, 0x80, 0x4f, 0xc6, 0xad, - 0x6c, 0xec, 0x64, 0x51, 0x68, 0x99, 0xb9, 0x19, 0x34, 0x06, 0x60, 0x38, 0xc0, 0x2e, 0xe1, 0x24, - 0x10, 0x99, 0x5c, 0xdc, 0xf8, 0x07, 0xd3, 0x67, 0x97, 0xc3, 0x44, 0xa6, 0x99, 0x13, 0x2f, 0x10, - 0xab, 0x54, 0x1d, 0xaa, 0xfc, 0xad, 0x46, 0xe8, 0x4b, 0xb8, 0x34, 0xa4, 0x0e, 0x39, 0xcc, 0x0c, - 0x99, 0x93, 0x86, 0x3c, 0x9e, 0xde, 0x90, 0x7b, 0x79, 0xb9, 0x66, 0x49, 0x8d, 0x71, 0x03, 0xda, - 0xe5, 0xfb, 0x24, 0x8c, 0xa4, 0x2e, 0xb6, 0x53, 0x6f, 0xa9, 0x91, 0x81, 0xa0, 0x5d, 0xbe, 0x3f, - 0xc6, 0x3f, 0xeb, 0xb0, 0x92, 0x8a, 0xdb, 0xf1, 0x3c, 0x3f, 0xf2, 0x2c, 0xf9, 0x70, 0x56, 0x79, - 0x16, 0xcb, 0x30, 0xcb, 0x29, 0x77, 0x52, 0xe0, 0x23, 0x07, 0xa2, 0x76, 0x71, 0xdf, 0x77, 0x38, - 0x65, 0xea, 0x80, 0x93, 0x61, 0x7c, 0xf6, 0xcf, 0x23, 0x1a, 0x90, 0x81, 0xcc, 0x04, 0x4d, 0x33, - 0x1d, 0x8b, 0x35, 0x81, 0x6a, 0x24, 0x8c, 0x8f, 0x9d, 0x99, 0x8e, 0x65, 0xdc, 0xfb, 0x8e, 0x43, - 0x2c, 0xe1, 0x8e, 0x1c, 0xd0, 0x2f, 0xcd, 0xca, 0x06, 0x82, 0x07, 0xd4, 0xb3, 0x15, 0xcc, 0x57, - 0x23, 0x61, 0x27, 0x0e, 0x02, 0x7c, 0xac, 0x37, 0xa5, 0x03, 0xe2, 0x01, 0xfa, 0x08, 0x1a, 0x2e, - 0x66, 0xaa, 0xd0, 0xdd, 0x28, 0x64, 0x87, 0x2a, 0x0f, 0x74, 0x0f, 0x30, 0x8b, 0x2b, 0x81, 0x60, - 0xeb, 0x7c, 0x00, 0xcd, 0x64, 0xe2, 0x6b, 0x41, 0xc2, 0x2f, 0xe0, 0x62, 0x21, 0xf9, 0xa0, 0xcf, - 0x61, 0x35, 0x8b, 0xa8, 0xbc, 0x42, 0x05, 0x02, 0xdf, 0x79, 0xa5, 0x65, 0xe6, 0x09, 0x02, 0x8c, - 0xe7, 0xb0, 0x24, 0x42, 0x46, 0x5e, 0xfc, 0x73, 0x6a, 0x6d, 0x3e, 0x84, 0x56, 0xaa, 0xb2, 0x32, - 0x66, 0x3a, 0xd0, 0x3c, 0x4a, 0x1e, 0x34, 0xe3, 0xde, 0x26, 0x1d, 0x1b, 0x3b, 0x80, 0xf2, 0xf6, - 0xaa, 0x0a, 0x74, 0xb3, 0x08, 0x8a, 0x57, 0xca, 0xe5, 0x46, 0x92, 0x27, 0x98, 0xf8, 0x37, 0x75, - 0x58, 0xdc, 0xa3, 0xf2, 0x95, 0xe3, 0x9c, 0x92, 0xdc, 0x0d, 0x68, 0x87, 0x51, 0xdf, 0xf5, 0x07, - 0x91, 0x43, 0x14, 0x28, 0x50, 0x95, 0x7e, 0x62, 0xfe, 0xb4, 0xe4, 0x27, 0x9c, 0xc5, 0x30, 0x1f, - 0xa9, 0x0e, 0x57, 0x7e, 0xa3, 0x8f, 0xe0, 0xca, 0x23, 0xf2, 0xa5, 0xda, 0xcf, 0x9e, 0xe3, 0xf7, - 0xfb, 0xd4, 0xb3, 0x13, 0x25, 0xb3, 0x52, 0xc9, 0xc9, 0x04, 0xc6, 0x2f, 0x35, 0x68, 0x67, 0xbe, - 0x50, 0xde, 0xbc, 0x1d, 0x47, 0x7d, 0xec, 0xcb, 0x6b, 0x79, 0x5f, 0x96, 0x49, 0xff, 0xf3, 0x80, - 0xbf, 0x90, 0x0f, 0xf8, 0x3f, 0x69, 0xb0, 0xb2, 0x47, 0x79, 0x92, 0x6a, 0xe8, 0x7f, 0xd9, 0xb9, - 0x18, 0x5d, 0x58, 0x2d, 0x9b, 0xaf, 0x5c, 0xb9, 0x0c, 0xb3, 0xe2, 0x94, 0x92, 0xde, 0x3d, 0x1e, - 0x6c, 0x7f, 0xd5, 0x82, 0xa5, 0xac, 0xf8, 0x8a, 0x7f, 0xa9, 0x45, 0xd0, 0x63, 0x68, 0xef, 0xa9, - 0x5f, 0xba, 0x92, 0x37, 0x13, 0x74, 0xda, 0x23, 0x64, 0xe7, 0x6a, 0xf5, 0x62, 0xac, 0xda, 0xa8, - 0x21, 0x0b, 0xae, 0x94, 0x05, 0x66, 0xef, 0x9d, 0xff, 0x7f, 0x8a, 0xe4, 0x94, 0xea, 0x55, 0x2a, - 0x36, 0x35, 0xf4, 0x39, 0x5c, 0x2a, 0xbe, 0xca, 0xa1, 0x42, 0x36, 0xaa, 0x7c, 0x28, 0xec, 0x18, - 0xa7, 0x91, 0xa4, 0xf6, 0x3f, 0x13, 0xd0, 0xb7, 0xf0, 0x44, 0x85, 0x8c, 0x22, 0x30, 0xaf, 0x7a, - 0xc2, 0xeb, 0xfc, 0xdf, 0xa9, 0x34, 0xa9, 0xf4, 0x0f, 0xa1, 0x99, 0x3c, 0xe9, 0x14, 0xdd, 0x5c, - 0x7a, 0xe8, 0xe9, 0xb4, 0x8b, 0xf2, 0x86, 0xa1, 0x51, 0x43, 0x1f, 0xc7, 0xcc, 0xa2, 0xe5, 0x9f, - 0x64, 0xce, 0x3d, 0x64, 0x74, 0x2e, 0x57, 0x3c, 0x1e, 0x18, 0x35, 0xf4, 0x5d, 0x58, 0x10, 0x5f, - 0x87, 0xea, 0x37, 0xa6, 0xd5, 0x6e, 0xfc, 0x93, 0x66, 0x37, 0xf9, 0x49, 0xb3, 0x7b, 0xd7, 0x65, - 0xfc, 0xb8, 0x53, 0xd1, 0xdd, 0x2b, 0x01, 0xcf, 0xe0, 0xe2, 0x1e, 0xe1, 0x19, 0x18, 0x47, 0xd7, - 0x5e, 0xab, 0x65, 0xe9, 0x18, 0x65, 0xb2, 0x49, 0x3c, 0x6f, 0xd4, 0xd0, 0x6f, 0x35, 0xb8, 0xbc, - 0x47, 0x78, 0x19, 0xde, 0xa2, 0xf7, 0xaa, 0x95, 0x9c, 0x00, 0x83, 0x3b, 0x8f, 0xa6, 0xbd, 0xaf, - 0x45, 0xb1, 0x46, 0x0d, 0xfd, 0x5e, 0x83, 0xb5, 0x9c, 0x61, 0x79, 0xbc, 0x8a, 0xb6, 0x4e, 0x37, - 0xae, 0x02, 0xdb, 0x76, 0x3e, 0x9b, 0xf2, 0xa7, 0xc3, 0x9c, 0x48, 0xa3, 0x86, 0x0e, 0xe5, 0x99, - 0x64, 0xe5, 0x09, 0xbd, 0x5d, 0x59, 0x87, 0x52, 0xed, 0xeb, 0x27, 0x2d, 0xa7, 0xe7, 0xf0, 0x19, - 0x2c, 0xec, 0x11, 0x9e, 0x64, 0xdd, 0x62, 0xa4, 0x95, 0x4a, 0x58, 0xf1, 0xaa, 0x96, 0x13, 0xb5, - 0x8c, 0x98, 0xa5, 0x58, 0x56, 0x2e, 0x4f, 0x15, 0xef, 0x6a, 0x65, 0x0a, 0x2e, 0x46, 0x4c, 0x75, - 0x9a, 0x33, 0x6a, 0x9f, 0xec, 0xfc, 0xfd, 0xe5, 0xba, 0xf6, 0xd5, 0xcb, 0x75, 0xed, 0x5f, 0x2f, - 0xd7, 0xb5, 0x1f, 0xdd, 0x7a, 0xc5, 0xef, 0xfd, 0xb9, 0x3f, 0x21, 0xc0, 0x8c, 0x5a, 0x0e, 0x25, - 0x1e, 0xef, 0xcf, 0xc9, 0xe0, 0xbf, 0xf5, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x0b, 0x09, - 0x7b, 0x61, 0x20, 0x00, 0x00, + // 2114 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x5a, 0x5b, 0x6f, 0x1b, 0xc7, + 0x15, 0xe6, 0x92, 0xba, 0x90, 0x47, 0xb2, 0x44, 0x8d, 0x75, 0x59, 0x31, 0x8e, 0xa0, 0x6c, 0x6b, + 0x43, 0xb5, 0x13, 0x12, 0x92, 0x91, 0xb8, 0x70, 0xd2, 0x14, 0x8a, 0x62, 0x4b, 0x8e, 0x2d, 0x5b, + 0x5d, 0xbb, 0x2d, 0xd2, 0xba, 0x2d, 0x86, 0xcb, 0x21, 0xb9, 0xe1, 0x5e, 0xc6, 0xbb, 0xb3, 0x0a, + 0x64, 0xa0, 0x0f, 0x45, 0x8b, 0x02, 0xfd, 0x03, 0x7d, 0xe8, 0xff, 0x28, 0xfa, 0x54, 0xf4, 0xa9, + 0x97, 0xc7, 0xa0, 0x7f, 0xa0, 0x85, 0x1f, 0xfb, 0x2b, 0x8a, 0xb9, 0xec, 0x95, 0x2b, 0xd9, 0x29, + 0x65, 0x19, 0xcd, 0x8b, 0xbd, 0x73, 0xe6, 0xcc, 0x39, 0x67, 0xce, 0x9c, 0xcb, 0x37, 0x43, 0xc1, + 0xb5, 0x80, 0x50, 0x3f, 0x24, 0xc1, 0x31, 0x09, 0x3a, 0xe2, 0xd3, 0x66, 0x7e, 0x70, 0x92, 0xf9, + 0x6c, 0xd3, 0xc0, 0x67, 0x3e, 0x82, 0x94, 0xd2, 0x7a, 0x30, 0xb0, 0xd9, 0x30, 0xea, 0xb6, 0x2d, + 0xdf, 0xed, 0xe0, 0x60, 0xe0, 0xd3, 0xc0, 0xff, 0x42, 0x7c, 0xbc, 0x67, 0xf5, 0x3a, 0xc7, 0x3b, + 0x1d, 0x3a, 0x1a, 0x74, 0x30, 0xb5, 0xc3, 0x0e, 0xa6, 0xd4, 0xb1, 0x2d, 0xcc, 0x6c, 0xdf, 0xeb, + 0x1c, 0x6f, 0x63, 0x87, 0x0e, 0xf1, 0x76, 0x67, 0x40, 0x3c, 0x12, 0x60, 0x46, 0x7a, 0x52, 0x72, + 0xeb, 0xad, 0x81, 0xef, 0x0f, 0x1c, 0xd2, 0x11, 0xa3, 0x6e, 0xd4, 0xef, 0x10, 0x97, 0x32, 0xa5, + 0xd6, 0xf8, 0xcf, 0x3c, 0x2c, 0x1e, 0x62, 0xcf, 0xee, 0x93, 0x90, 0x99, 0xe4, 0x59, 0x44, 0x42, + 0x86, 0x9e, 0xc2, 0x14, 0x37, 0x46, 0xd7, 0x36, 0xb5, 0xad, 0xb9, 0x9d, 0x83, 0x76, 0x6a, 0x4d, + 0x3b, 0xb6, 0x46, 0x7c, 0xfc, 0xc2, 0xea, 0xb5, 0x8f, 0x77, 0xda, 0x74, 0x34, 0x68, 0x73, 0x6b, + 0xda, 0x19, 0x6b, 0xda, 0xb1, 0x35, 0x6d, 0x33, 0xd9, 0x96, 0x29, 0xa4, 0xa2, 0x16, 0xd4, 0x03, + 0x72, 0x6c, 0x87, 0xb6, 0xef, 0xe9, 0xd5, 0x4d, 0x6d, 0xab, 0x61, 0x26, 0x63, 0xa4, 0xc3, 0xac, + 0xe7, 0xef, 0x61, 0x6b, 0x48, 0xf4, 0xda, 0xa6, 0xb6, 0x55, 0x37, 0xe3, 0x21, 0xda, 0x84, 0x39, + 0x4c, 0xe9, 0x03, 0xdc, 0x25, 0xce, 0x7d, 0x72, 0xa2, 0x4f, 0x89, 0x85, 0x59, 0x12, 0x5f, 0x8b, + 0x29, 0x7d, 0x88, 0x5d, 0xa2, 0x4f, 0x8b, 0xd9, 0x78, 0x88, 0xae, 0x40, 0xc3, 0xc3, 0x2e, 0x09, + 0x29, 0xb6, 0x88, 0x5e, 0x17, 0x73, 0x29, 0x01, 0xfd, 0x12, 0x96, 0x32, 0x86, 0x3f, 0xf6, 0xa3, + 0xc0, 0x22, 0x3a, 0x88, 0xad, 0x3f, 0x9a, 0x6c, 0xeb, 0xbb, 0x45, 0xb1, 0xe6, 0xb8, 0x26, 0xf4, + 0x73, 0x98, 0x16, 0x27, 0xaf, 0xcf, 0x6d, 0xd6, 0xce, 0xd5, 0xdb, 0x52, 0x2c, 0xf2, 0x60, 0x96, + 0x3a, 0xd1, 0xc0, 0xf6, 0x42, 0x7d, 0x5e, 0x68, 0x78, 0x32, 0x99, 0x86, 0x3d, 0xdf, 0xeb, 0xdb, + 0x83, 0x43, 0xec, 0xe1, 0x01, 0x71, 0x89, 0xc7, 0x8e, 0x84, 0x70, 0x33, 0x56, 0x82, 0x9e, 0x43, + 0x73, 0x14, 0x85, 0xcc, 0x77, 0xed, 0xe7, 0xe4, 0x11, 0xe5, 0x6b, 0x43, 0xfd, 0x92, 0xf0, 0xe6, + 0xc3, 0xc9, 0x14, 0xdf, 0x2f, 0x48, 0x35, 0xc7, 0xf4, 0xf0, 0x20, 0x19, 0x45, 0x5d, 0xf2, 0x23, + 0x12, 0x88, 0xe8, 0x5a, 0x90, 0x41, 0x92, 0x21, 0xc9, 0x30, 0xb2, 0xd5, 0x28, 0xd4, 0x17, 0x37, + 0x6b, 0x32, 0x8c, 0x12, 0x12, 0xda, 0x82, 0xc5, 0x63, 0x12, 0xd8, 0xfd, 0x93, 0xc7, 0xf6, 0xc0, + 0xc3, 0x2c, 0x0a, 0x88, 0xde, 0x14, 0xa1, 0x58, 0x24, 0x23, 0x17, 0x2e, 0x0d, 0x89, 0xe3, 0x72, + 0x97, 0xef, 0x05, 0xa4, 0x17, 0xea, 0x4b, 0xc2, 0xbf, 0xfb, 0x93, 0x9f, 0xa0, 0x10, 0x67, 0xe6, + 0xa5, 0x73, 0xc3, 0x3c, 0xdf, 0x54, 0x99, 0x22, 0x73, 0x04, 0x49, 0xc3, 0x0a, 0x64, 0x74, 0x0d, + 0x16, 0x58, 0x80, 0xad, 0x91, 0xed, 0x0d, 0x0e, 0x09, 0x1b, 0xfa, 0x3d, 0xfd, 0xb2, 0xf0, 0x44, + 0x81, 0x8a, 0x2c, 0x40, 0xc4, 0xc3, 0x5d, 0x87, 0xf4, 0x64, 0x2c, 0x3e, 0x39, 0xa1, 0x24, 0xd4, + 0x97, 0xc5, 0x2e, 0x6e, 0xb6, 0x33, 0x15, 0xaa, 0x50, 0x20, 0xda, 0x77, 0xc6, 0x56, 0xdd, 0xf1, + 0x58, 0x70, 0x62, 0x96, 0x88, 0x43, 0x23, 0x98, 0xe3, 0xfb, 0x88, 0x43, 0x61, 0x45, 0x84, 0xc2, + 0xbd, 0xc9, 0x7c, 0x74, 0x90, 0x0a, 0x34, 0xb3, 0xd2, 0x51, 0x1b, 0xd0, 0x10, 0x87, 0x87, 0x91, + 0xc3, 0x6c, 0xea, 0x10, 0x69, 0x46, 0xa8, 0xaf, 0x0a, 0x37, 0x95, 0xcc, 0xa0, 0xfb, 0x00, 0x01, + 0xe9, 0xc7, 0x7c, 0x6b, 0x62, 0xe7, 0x37, 0xce, 0xda, 0xb9, 0x99, 0x70, 0xcb, 0x1d, 0x67, 0x96, + 0x73, 0xe5, 0x7c, 0x1b, 0xc4, 0x62, 0x2a, 0xdb, 0x45, 0x5a, 0xeb, 0x22, 0xc4, 0x4a, 0x66, 0x78, + 0x2c, 0x2a, 0xaa, 0x28, 0x5a, 0xeb, 0x32, 0x5a, 0x33, 0xa4, 0xd6, 0x1d, 0x58, 0x3b, 0xc5, 0xd5, + 0xa8, 0x09, 0xb5, 0x11, 0x39, 0x11, 0x25, 0xba, 0x61, 0xf2, 0x4f, 0xb4, 0x0c, 0xd3, 0xc7, 0xd8, + 0x89, 0x88, 0x28, 0xaa, 0x75, 0x53, 0x0e, 0x6e, 0x57, 0xbf, 0xab, 0xb5, 0x7e, 0xab, 0xc1, 0x62, + 0xc1, 0xf0, 0x92, 0xf5, 0x3f, 0xcb, 0xae, 0x3f, 0x87, 0x30, 0xee, 0x3f, 0xc1, 0xc1, 0x80, 0xb0, + 0x8c, 0x21, 0xc6, 0x3f, 0x35, 0xd0, 0x0b, 0x1e, 0xfd, 0xb1, 0xcd, 0x86, 0x77, 0x6d, 0x87, 0x84, + 0xe8, 0x16, 0xcc, 0x06, 0x92, 0xa6, 0x1a, 0xcf, 0x5b, 0x67, 0x1c, 0xc4, 0x41, 0xc5, 0x8c, 0xb9, + 0xd1, 0xc7, 0x50, 0x77, 0x09, 0xc3, 0x3d, 0xcc, 0xb0, 0xb2, 0x7d, 0xb3, 0x6c, 0x25, 0xd7, 0x72, + 0xa8, 0xf8, 0x0e, 0x2a, 0x66, 0xb2, 0x06, 0xbd, 0x0f, 0xd3, 0xd6, 0x30, 0xf2, 0x46, 0xa2, 0xe5, + 0xcc, 0xed, 0xbc, 0x7d, 0xda, 0xe2, 0x3d, 0xce, 0x74, 0x50, 0x31, 0x25, 0xf7, 0x27, 0x33, 0x30, + 0x45, 0x71, 0xc0, 0x8c, 0xbb, 0xb0, 0x5c, 0xa6, 0x82, 0xf7, 0x39, 0x6b, 0x48, 0xac, 0x51, 0x18, + 0xb9, 0xca, 0xcd, 0xc9, 0x18, 0x21, 0x98, 0x0a, 0xed, 0xe7, 0xd2, 0xd5, 0x35, 0x53, 0x7c, 0x1b, + 0xdf, 0x81, 0xa5, 0x31, 0x6d, 0xfc, 0x50, 0xa5, 0x6d, 0x5c, 0xc2, 0xbc, 0x52, 0x6d, 0x44, 0xb0, + 0xf2, 0x44, 0xf8, 0x22, 0x29, 0xf6, 0x17, 0xd1, 0xb9, 0x8d, 0x03, 0x58, 0x2d, 0xaa, 0x0d, 0xa9, + 0xef, 0x85, 0x84, 0x87, 0xbe, 0xa8, 0x8e, 0x36, 0xe9, 0xa5, 0xb3, 0xc2, 0x8a, 0xba, 0x59, 0x32, + 0x63, 0xfc, 0xaa, 0x0a, 0xab, 0x26, 0x09, 0x7d, 0xe7, 0x98, 0xc4, 0xa5, 0xeb, 0x62, 0xc0, 0xc7, + 0x4f, 0xa1, 0x86, 0x29, 0x55, 0x61, 0x72, 0xef, 0xdc, 0xda, 0xbb, 0xc9, 0xa5, 0xa2, 0x77, 0x61, + 0x09, 0xbb, 0x5d, 0x7b, 0x10, 0xf9, 0x51, 0x18, 0x6f, 0x4b, 0x04, 0x55, 0xc3, 0x1c, 0x9f, 0x30, + 0x2c, 0x58, 0x1b, 0x73, 0x81, 0x72, 0x67, 0x16, 0x22, 0x69, 0x05, 0x88, 0x54, 0xaa, 0xa4, 0x7a, + 0x9a, 0x92, 0xbf, 0x69, 0xd0, 0x4c, 0x53, 0x47, 0x89, 0xbf, 0x02, 0x0d, 0x57, 0xd1, 0x42, 0x5d, + 0x13, 0xf5, 0x29, 0x25, 0xe4, 0xd1, 0x52, 0xb5, 0x88, 0x96, 0x56, 0x61, 0x46, 0x82, 0x59, 0xb5, + 0x31, 0x35, 0xca, 0x99, 0x3c, 0x55, 0x30, 0x79, 0x03, 0x20, 0x4c, 0xea, 0x97, 0x3e, 0x23, 0x66, + 0x33, 0x14, 0x64, 0xc0, 0xbc, 0xec, 0xad, 0x26, 0x09, 0x23, 0x87, 0xe9, 0xb3, 0x82, 0x23, 0x47, + 0x33, 0x7c, 0x58, 0x7c, 0x60, 0xf3, 0x3d, 0xf4, 0xc3, 0x8b, 0x09, 0xf6, 0x0f, 0x60, 0x8a, 0x2b, + 0xe3, 0x1b, 0xeb, 0x06, 0xd8, 0xb3, 0x86, 0x24, 0xf6, 0x55, 0x32, 0xe6, 0x69, 0xcc, 0xf0, 0x20, + 0xd4, 0xab, 0x82, 0x2e, 0xbe, 0x8d, 0x3f, 0x55, 0xa5, 0xa5, 0xbb, 0x94, 0x86, 0x6f, 0x1e, 0x50, + 0x97, 0xb7, 0xf8, 0xda, 0x78, 0x8b, 0x2f, 0x98, 0xfc, 0x75, 0x5a, 0xfc, 0x39, 0xb5, 0x29, 0x23, + 0x82, 0xd9, 0x5d, 0x4a, 0xb9, 0x21, 0x68, 0x1b, 0xa6, 0x30, 0xa5, 0xd2, 0xe1, 0x85, 0x8a, 0xac, + 0x58, 0xf8, 0xff, 0xca, 0x24, 0xc1, 0xda, 0xba, 0x05, 0x8d, 0x84, 0xf4, 0x32, 0xb5, 0x8d, 0xac, + 0xda, 0x4d, 0x00, 0x89, 0x61, 0xef, 0x79, 0x7d, 0x9f, 0x1f, 0x29, 0x0f, 0x76, 0xb5, 0x54, 0x7c, + 0x1b, 0xb7, 0x63, 0x0e, 0x61, 0xdb, 0xbb, 0x30, 0x6d, 0x33, 0xe2, 0xc6, 0xc6, 0xad, 0x66, 0x8d, + 0x4b, 0x05, 0x99, 0x92, 0xc9, 0xf8, 0x7b, 0x1d, 0xd6, 0xf9, 0x89, 0x3d, 0x16, 0x69, 0xb2, 0x4b, + 0xe9, 0xa7, 0x84, 0x61, 0xdb, 0x09, 0x7f, 0x10, 0x91, 0xe0, 0xe4, 0x35, 0x07, 0xc6, 0x00, 0x66, + 0x64, 0x96, 0xa9, 0x7a, 0x77, 0xee, 0xd7, 0x19, 0x25, 0x3e, 0xbd, 0xc3, 0xd4, 0x5e, 0xcf, 0x1d, + 0xa6, 0xec, 0x4e, 0x31, 0x75, 0x41, 0x77, 0x8a, 0xd3, 0xaf, 0x95, 0x99, 0xcb, 0xea, 0x4c, 0xfe, + 0xb2, 0x5a, 0x02, 0xd5, 0x67, 0x5f, 0x15, 0xaa, 0xd7, 0x4b, 0xa1, 0xba, 0x5b, 0x9a, 0xc7, 0x0d, + 0xe1, 0xee, 0xef, 0x65, 0x23, 0xf0, 0xd4, 0x58, 0x9b, 0x04, 0xb4, 0xc3, 0x6b, 0x05, 0xed, 0x3f, + 0xcc, 0x81, 0x70, 0x79, 0x0d, 0x7e, 0xff, 0xd5, 0xf6, 0x74, 0x06, 0x1c, 0xff, 0xc6, 0x81, 0xe7, + 0xdf, 0x08, 0xcc, 0x44, 0xfd, 0xd4, 0x07, 0x49, 0x43, 0xe7, 0x7d, 0x88, 0xb7, 0x56, 0x55, 0xb4, + 0xf8, 0x37, 0xba, 0x01, 0x53, 0xdc, 0xc9, 0x0a, 0xd4, 0xae, 0x65, 0xfd, 0xc9, 0x4f, 0x62, 0x97, + 0xd2, 0xc7, 0x94, 0x58, 0xa6, 0x60, 0x42, 0xb7, 0xa1, 0x91, 0x04, 0xbe, 0xca, 0xac, 0x2b, 0xd9, + 0x15, 0x49, 0x9e, 0xc4, 0xcb, 0x52, 0x76, 0xbe, 0xb6, 0x67, 0x07, 0xc4, 0x12, 0x90, 0x6f, 0x7a, + 0x7c, 0xed, 0xa7, 0xf1, 0x64, 0xb2, 0x36, 0x61, 0x47, 0xdb, 0x30, 0x23, 0xdf, 0x0d, 0x44, 0x06, + 0xcd, 0xed, 0xac, 0x8f, 0x17, 0xd3, 0x78, 0x95, 0x62, 0x34, 0xfe, 0xaa, 0xc1, 0x3b, 0x69, 0x40, + 0xc4, 0xd9, 0x14, 0xa3, 0xee, 0x37, 0xdf, 0x71, 0xaf, 0xc1, 0x82, 0x80, 0xf9, 0xe9, 0xf3, 0x81, + 0x7c, 0xc9, 0x2a, 0x50, 0x8d, 0x3f, 0x6a, 0x70, 0x75, 0x7c, 0x1f, 0x7b, 0x43, 0x1c, 0xb0, 0xe4, + 0x78, 0x2f, 0x62, 0x2f, 0x71, 0xc3, 0xab, 0xa6, 0x0d, 0x2f, 0xb7, 0xbf, 0x5a, 0x7e, 0x7f, 0xc6, + 0x5f, 0xaa, 0x30, 0x97, 0x09, 0xa0, 0xb2, 0x86, 0xc9, 0x01, 0x9f, 0x88, 0x5b, 0x71, 0xb1, 0x13, + 0x4d, 0xa1, 0x61, 0x66, 0x28, 0x68, 0x04, 0x40, 0x71, 0x80, 0x5d, 0xc2, 0x48, 0xc0, 0x2b, 0x39, + 0xcf, 0xf8, 0xfb, 0x93, 0x57, 0x97, 0xa3, 0x58, 0xa6, 0x99, 0x11, 0xcf, 0x11, 0xab, 0x50, 0x1d, + 0xaa, 0xfa, 0xad, 0x46, 0xe8, 0x4b, 0x58, 0xe8, 0xdb, 0x0e, 0x39, 0x4a, 0x0d, 0x99, 0x11, 0x86, + 0x3c, 0x9a, 0xdc, 0x90, 0xbb, 0x59, 0xb9, 0x66, 0x41, 0x8d, 0x71, 0x1d, 0x9a, 0xc5, 0x7c, 0xe2, + 0x46, 0xda, 0x2e, 0x1e, 0x24, 0xde, 0x52, 0x23, 0x03, 0x41, 0xb3, 0x98, 0x3f, 0xc6, 0xbf, 0xaa, + 0xb0, 0x92, 0x88, 0xdb, 0xf5, 0x3c, 0x3f, 0xf2, 0x2c, 0xf1, 0x14, 0x57, 0x7a, 0x16, 0xcb, 0x30, + 0xcd, 0x6c, 0xe6, 0x24, 0xc0, 0x47, 0x0c, 0x78, 0xef, 0x62, 0xbe, 0xef, 0x30, 0x9b, 0xaa, 0x03, + 0x8e, 0x87, 0xf2, 0xec, 0x9f, 0x45, 0x76, 0x40, 0x7a, 0xa2, 0x12, 0xd4, 0xcd, 0x64, 0xcc, 0xe7, + 0x38, 0xaa, 0x11, 0x30, 0x5e, 0x3a, 0x33, 0x19, 0x8b, 0xb8, 0xf7, 0x1d, 0x87, 0x58, 0xdc, 0x1d, + 0x19, 0xa0, 0x5f, 0xa0, 0x8a, 0x0b, 0x04, 0x0b, 0x6c, 0x6f, 0xa0, 0x60, 0xbe, 0x1a, 0x71, 0x3b, + 0x71, 0x10, 0xe0, 0x13, 0xbd, 0x2e, 0x1c, 0x20, 0x07, 0xe8, 0x23, 0xa8, 0xb9, 0x98, 0xaa, 0x46, + 0x77, 0x3d, 0x57, 0x1d, 0xca, 0x3c, 0xd0, 0x3e, 0xc4, 0x54, 0x76, 0x02, 0xbe, 0xac, 0xf5, 0x01, + 0xd4, 0x63, 0xc2, 0xd7, 0x82, 0x84, 0x5f, 0xc0, 0xa5, 0x5c, 0xf1, 0x41, 0x9f, 0xc3, 0x6a, 0x1a, + 0x51, 0x59, 0x85, 0x0a, 0x04, 0xbe, 0xf3, 0x52, 0xcb, 0xcc, 0x53, 0x04, 0x18, 0xcf, 0x60, 0x89, + 0x87, 0x8c, 0x48, 0xfc, 0x0b, 0xba, 0xda, 0x7c, 0x08, 0x8d, 0x44, 0x65, 0x69, 0xcc, 0xb4, 0xa0, + 0x7e, 0x1c, 0x3f, 0x91, 0xca, 0xbb, 0x4d, 0x32, 0x36, 0x76, 0x01, 0x65, 0xed, 0x55, 0x1d, 0xe8, + 0x46, 0x1e, 0x14, 0xaf, 0x14, 0xdb, 0x8d, 0x60, 0x8f, 0x31, 0xf1, 0xef, 0xaa, 0xb0, 0xb8, 0x6f, + 0x8b, 0x57, 0x8e, 0x0b, 0x2a, 0x72, 0xd7, 0xa1, 0x19, 0x46, 0x5d, 0xd7, 0xef, 0x45, 0x0e, 0x51, + 0xa0, 0x40, 0x75, 0xfa, 0x31, 0xfa, 0x59, 0xc5, 0x8f, 0x3b, 0x8b, 0x62, 0x36, 0x54, 0x37, 0x5c, + 0xf1, 0x8d, 0x3e, 0x82, 0xf5, 0x87, 0xe4, 0x4b, 0xb5, 0x9f, 0x7d, 0xc7, 0xef, 0x76, 0x6d, 0x6f, + 0x10, 0x2b, 0x99, 0x16, 0x4a, 0x4e, 0x67, 0x30, 0x7e, 0xad, 0x41, 0x33, 0xf5, 0x85, 0xf2, 0xe6, + 0x2d, 0x19, 0xf5, 0xd2, 0x97, 0x57, 0xb3, 0xbe, 0x2c, 0xb2, 0xfe, 0xef, 0x01, 0x3f, 0x9f, 0x0d, + 0xf8, 0x3f, 0x6b, 0xb0, 0xb2, 0x6f, 0xb3, 0xb8, 0xd4, 0xd8, 0xff, 0x67, 0xe7, 0x62, 0xb4, 0x61, + 0xb5, 0x68, 0xbe, 0x72, 0xe5, 0x32, 0x4c, 0xf3, 0x53, 0x8a, 0xef, 0xee, 0x72, 0xb0, 0xf3, 0x55, + 0x03, 0x96, 0xd2, 0xe6, 0xcb, 0xff, 0xb5, 0x2d, 0x82, 0x1e, 0x41, 0x73, 0x5f, 0xfd, 0x76, 0x16, + 0xbf, 0x99, 0xa0, 0xb3, 0x1e, 0x21, 0x5b, 0x57, 0xca, 0x27, 0xa5, 0x6a, 0xa3, 0x82, 0x2c, 0x58, + 0x2f, 0x0a, 0x4c, 0xdf, 0x3b, 0xbf, 0x7d, 0x86, 0xe4, 0x84, 0xeb, 0x65, 0x2a, 0xb6, 0x34, 0xf4, + 0x39, 0x2c, 0xe4, 0x5f, 0xe5, 0x50, 0xae, 0x1a, 0x95, 0x3e, 0x14, 0xb6, 0x8c, 0xb3, 0x58, 0x12, + 0xfb, 0x9f, 0x72, 0xe8, 0x9b, 0x7b, 0xa2, 0x42, 0x46, 0x1e, 0x98, 0x97, 0x3d, 0xe1, 0xb5, 0xbe, + 0x75, 0x26, 0x4f, 0x22, 0xfd, 0x43, 0xa8, 0xc7, 0x4f, 0x3a, 0x79, 0x37, 0x17, 0x1e, 0x7a, 0x5a, + 0xcd, 0xbc, 0xbc, 0x7e, 0x68, 0x54, 0xd0, 0xc7, 0x72, 0x31, 0xbf, 0xf2, 0x8f, 0x2f, 0xce, 0x3c, + 0x64, 0xb4, 0x2e, 0x97, 0x3c, 0x1e, 0x18, 0x15, 0xf4, 0x7d, 0x98, 0xe3, 0x5f, 0x47, 0xea, 0x57, + 0xab, 0xd5, 0xb6, 0xfc, 0x91, 0xb4, 0x1d, 0xff, 0x48, 0xda, 0xbe, 0xe3, 0x52, 0x76, 0xd2, 0x2a, + 0xb9, 0xdd, 0x2b, 0x01, 0x4f, 0xe1, 0xd2, 0x3e, 0x61, 0x29, 0x18, 0x47, 0x57, 0x5f, 0xe9, 0xca, + 0xd2, 0x32, 0x8a, 0x6c, 0xe3, 0x78, 0xde, 0xa8, 0xa0, 0xdf, 0x6b, 0x70, 0x79, 0x9f, 0xb0, 0x22, + 0xbc, 0x45, 0xef, 0x95, 0x2b, 0x39, 0x05, 0x06, 0xb7, 0x1e, 0x4e, 0x9a, 0xaf, 0x79, 0xb1, 0x46, + 0x05, 0xfd, 0x41, 0x83, 0xb5, 0x8c, 0x61, 0x59, 0xbc, 0x8a, 0xb6, 0xcf, 0x36, 0xae, 0x04, 0xdb, + 0xb6, 0x3e, 0x9b, 0xf0, 0xc7, 0xc8, 0x8c, 0x48, 0xa3, 0x82, 0x8e, 0xc4, 0x99, 0xa4, 0xed, 0x09, + 0xbd, 0x5d, 0xda, 0x87, 0x12, 0xed, 0x1b, 0xa7, 0x4d, 0x27, 0xe7, 0xf0, 0x19, 0xcc, 0xed, 0x13, + 0x16, 0x57, 0xdd, 0x7c, 0xa4, 0x15, 0x5a, 0x58, 0x3e, 0x55, 0x8b, 0x85, 0x5a, 0x44, 0xcc, 0x92, + 0x94, 0x95, 0xa9, 0x53, 0xf9, 0x5c, 0x2d, 0x2d, 0xc1, 0xf9, 0x88, 0x29, 0x2f, 0x73, 0x46, 0xe5, + 0x93, 0xdd, 0x7f, 0xbc, 0xd8, 0xd0, 0xbe, 0x7a, 0xb1, 0xa1, 0xfd, 0xfb, 0xc5, 0x86, 0xf6, 0x93, + 0x9b, 0x2f, 0xf9, 0x0b, 0x82, 0xcc, 0x1f, 0x25, 0x60, 0x6a, 0x5b, 0x8e, 0x4d, 0x3c, 0xd6, 0x9d, + 0x11, 0xc1, 0x7f, 0xf3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x86, 0xe4, 0x0d, 0xb3, 0x20, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2902,6 +2922,26 @@ func (m *ManifestRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.ProjectName) > 0 { + i -= len(m.ProjectName) + copy(dAtA[i:], m.ProjectName) + i = encodeVarintRepository(dAtA, i, uint64(len(m.ProjectName))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xca + } + if len(m.ProjectSourceRepos) > 0 { + for iNdEx := len(m.ProjectSourceRepos) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ProjectSourceRepos[iNdEx]) + copy(dAtA[i:], m.ProjectSourceRepos[iNdEx]) + i = encodeVarintRepository(dAtA, i, uint64(len(m.ProjectSourceRepos[iNdEx]))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xc2 + } + } if len(m.RefSources) > 0 { for k := range m.RefSources { v := m.RefSources[k] @@ -4942,6 +4982,16 @@ func (m *ManifestRequest) Size() (n int) { n += mapEntrySize + 2 + sovRepository(uint64(mapEntrySize)) } } + if len(m.ProjectSourceRepos) > 0 { + for _, s := range m.ProjectSourceRepos { + l = len(s) + n += 2 + l + sovRepository(uint64(l)) + } + } + l = len(m.ProjectName) + if l > 0 { + n += 2 + l + sovRepository(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -6536,6 +6586,70 @@ func (m *ManifestRequest) Unmarshal(dAtA []byte) error { } m.RefSources[mapkey] = mapvalue iNdEx = postIndex + case 24: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProjectSourceRepos", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRepository + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRepository + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRepository + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProjectSourceRepos = append(m.ProjectSourceRepos, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 25: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProjectName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRepository + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRepository + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRepository + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProjectName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRepository(dAtA[iNdEx:]) diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go index 3a6ad0fb8d096..c8dbd7b1bf5ec 100644 --- a/reposerver/repository/repository.go +++ b/reposerver/repository/repository.go @@ -1167,6 +1167,20 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie if err != nil { return nil, err } + + var reposNotPermitted []string + // We do a sanity check here to give a nicer error message in case any of the Helm repositories are not permitted by + // the AppProject which the application is a part of + for _, repo := range helmRepos { + if !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { + reposNotPermitted = append(reposNotPermitted, repo.Repo) + } + } + + if len(reposNotPermitted) > 0 { + return nil, status.Errorf(codes.PermissionDenied, "helm repos %s are not permitted in project '%s'", strings.Join(reposNotPermitted, ", "), q.ProjectName) + } + h, err := helm.NewHelmApp(appPath, helmRepos, isLocal, version, proxy, passCredentials) if err != nil { return nil, err diff --git a/reposerver/repository/repository.proto b/reposerver/repository/repository.proto index 37babd739b1c1..8e4b69000f7e1 100644 --- a/reposerver/repository/repository.proto +++ b/reposerver/repository/repository.proto @@ -32,6 +32,10 @@ message ManifestRequest { github.com.argoproj.argo_cd.v2.pkg.apis.application.v1alpha1.HelmOptions helmOptions = 21; bool hasMultipleSources = 22; map refSources = 23; + // This is used to surface "source not permitted" errors for Helm repositories + repeated string projectSourceRepos = 24; + // This is used to surface "source not permitted" errors for Helm repositories + string projectName = 25; } message ManifestRequestWithFiles { diff --git a/reposerver/repository/repository_test.go b/reposerver/repository/repository_test.go index 18429b7665ab7..0ae2c4ba20404 100644 --- a/reposerver/repository/repository_test.go +++ b/reposerver/repository/repository_test.go @@ -154,8 +154,10 @@ func TestGenerateYamlManifestInDir(t *testing.T) { src := argoappv1.ApplicationSource{Path: "."} q := apiclient.ManifestRequest{ - Repo: &argoappv1.Repository{}, - ApplicationSource: &src, + Repo: &argoappv1.Repository{}, + ApplicationSource: &src, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, } // update this value if we add/remove manifests @@ -222,7 +224,8 @@ func Test_GenerateManifests_NoOutOfBoundsAccess(t *testing.T) { mustNotContain = testCaseCopy.mustNotContain } - q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &argoappv1.ApplicationSource{}} + q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &argoappv1.ApplicationSource{}, ProjectName: "something", + ProjectSourceRepos: []string{"*"}} res, err := GenerateManifests(context.Background(), repoDir, "", "", &q, false, &git.NoopCredsStore{}, resource.MustParse("0"), nil) require.Error(t, err) assert.NotContains(t, err.Error(), mustNotContain) @@ -237,7 +240,8 @@ func TestGenerateManifests_MissingSymlinkDestination(t *testing.T) { err := os.Symlink("/obviously/does/not/exist", path.Join(repoDir, "test.yaml")) require.NoError(t, err) - q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &argoappv1.ApplicationSource{}} + q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &argoappv1.ApplicationSource{}, ProjectName: "something", + ProjectSourceRepos: []string{"*"}} _, err = GenerateManifests(context.Background(), repoDir, "", "", &q, false, &git.NoopCredsStore{}, resource.MustParse("0"), nil) require.NoError(t, err) } @@ -247,9 +251,11 @@ func TestGenerateManifests_K8SAPIResetCache(t *testing.T) { src := argoappv1.ApplicationSource{Path: "."} q := apiclient.ManifestRequest{ - KubeVersion: "v1.16.0", - Repo: &argoappv1.Repository{}, - ApplicationSource: &src, + KubeVersion: "v1.16.0", + Repo: &argoappv1.Repository{}, + ApplicationSource: &src, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, } cachedFakeResponse := &apiclient.ManifestResponse{Manifests: []string{"Fake"}} @@ -273,8 +279,10 @@ func TestGenerateManifests_EmptyCache(t *testing.T) { src := argoappv1.ApplicationSource{Path: "."} q := apiclient.ManifestRequest{ - Repo: &argoappv1.Repository{}, - ApplicationSource: &src, + Repo: &argoappv1.Repository{}, + ApplicationSource: &src, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, } err := service.cache.SetManifests(mock.Anything, &src, q.RefSources, &q, "", "", "", "", &cache.CachedManifestResponse{ManifestResponse: nil}, nil) @@ -289,7 +297,8 @@ func TestGenerateManifests_EmptyCache(t *testing.T) { func TestHelmManifestFromChartRepo(t *testing.T) { service := newService(".") source := &argoappv1.ApplicationSource{Chart: "my-chart", TargetRevision: ">= 1.0.0"} - request := &apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: source, NoCache: true} + request := &apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: source, NoCache: true, ProjectName: "something", + ProjectSourceRepos: []string{"*"}} response, err := service.GenerateManifest(context.Background(), request) assert.NoError(t, err) assert.NotNil(t, response) @@ -318,7 +327,8 @@ func TestHelmChartReferencingExternalValues(t *testing.T) { }, nil) refSources, err := argo.GetRefSources(context.Background(), spec, repoDB) require.NoError(t, err) - request := &apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &spec.Sources[0], NoCache: true, RefSources: refSources, HasMultipleSources: true} + request := &apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &spec.Sources[0], NoCache: true, RefSources: refSources, HasMultipleSources: true, ProjectName: "something", + ProjectSourceRepos: []string{"*"}} response, err := service.GenerateManifest(context.Background(), request) assert.NoError(t, err) assert.NotNil(t, response) @@ -370,7 +380,8 @@ func TestGenerateManifestsUseExactRevision(t *testing.T) { src := argoappv1.ApplicationSource{Path: "./testdata/recurse", Directory: &argoappv1.ApplicationSourceDirectory{Recurse: true}} - q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src, Revision: "abc"} + q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src, Revision: "abc", ProjectName: "something", + ProjectSourceRepos: []string{"*"}} res1, err := service.GenerateManifest(context.Background(), &q) assert.Nil(t, err) @@ -383,7 +394,8 @@ func TestRecurseManifestsInDir(t *testing.T) { src := argoappv1.ApplicationSource{Path: "./testdata/recurse", Directory: &argoappv1.ApplicationSourceDirectory{Recurse: true}} - q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src} + q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src, ProjectName: "something", + ProjectSourceRepos: []string{"*"}} res1, err := service.GenerateManifest(context.Background(), &q) assert.Nil(t, err) @@ -438,6 +450,8 @@ func TestGenerateJsonnetManifestInDir(t *testing.T) { }, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, } res1, err := service.GenerateManifest(context.Background(), &q) assert.Nil(t, err) @@ -459,6 +473,8 @@ func TestGenerateJsonnetManifestInRootDir(t *testing.T) { }, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, } res1, err := service.GenerateManifest(context.Background(), &q) assert.Nil(t, err) @@ -478,6 +494,8 @@ func TestGenerateJsonnetLibOutside(t *testing.T) { }, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, } _, err := service.GenerateManifest(context.Background(), &q) require.Error(t, err) @@ -652,6 +670,8 @@ func TestManifestGenErrorCacheFileContentsChange(t *testing.T) { ApplicationSource: &argoappv1.ApplicationSource{ Path: ".", }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) fmt.Println("-", step, "-", res != nil, err != nil, errorExpected) @@ -820,6 +840,8 @@ func TestGenerateHelmWithValues(t *testing.T) { ValuesObject: &runtime.RawExtension{Raw: []byte(`cluster: {slaveCount: 2}`)}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.NoError(t, err) @@ -855,6 +877,8 @@ func TestHelmWithMissingValueFiles(t *testing.T) { ValueFiles: []string{"values-production.yaml", missingValuesFile}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, } // Should fail since we're passing a non-existent values file, and error should indicate that @@ -880,6 +904,8 @@ func TestGenerateHelmWithEnvVars(t *testing.T) { ValueFiles: []string{"values-$ARGOCD_APP_NAME.yaml"}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.NoError(t, err) @@ -915,6 +941,8 @@ func TestGenerateHelmWithValuesDirectoryTraversal(t *testing.T) { ValuesObject: &runtime.RawExtension{Raw: []byte(`cluster: {slaveCount: 2}`)}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.NoError(t, err) @@ -926,6 +954,8 @@ func TestGenerateHelmWithValuesDirectoryTraversal(t *testing.T) { ApplicationSource: &argoappv1.ApplicationSource{ Path: "./my-chart", }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.NoError(t, err) } @@ -950,10 +980,11 @@ func TestHelmManifestFromChartRepoWithValueFile(t *testing.T) { }, } request := &apiclient.ManifestRequest{ - Repo: &argoappv1.Repository{}, - ApplicationSource: source, - NoCache: true, - } + Repo: &argoappv1.Repository{}, + ApplicationSource: source, + NoCache: true, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}} response, err := service.GenerateManifest(context.Background(), request) assert.NoError(t, err) assert.NotNil(t, response) @@ -992,7 +1023,8 @@ func TestHelmManifestFromChartRepoWithValueFileLinks(t *testing.T) { ValueFiles: []string{"my-chart-link.yaml"}, }, } - request := &apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: source, NoCache: true} + request := &apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: source, NoCache: true, ProjectName: "something", + ProjectSourceRepos: []string{"*"}} _, err := service.GenerateManifest(context.Background(), request) assert.NoError(t, err) }) @@ -1011,8 +1043,9 @@ func TestGenerateHelmWithURL(t *testing.T) { ValuesObject: &runtime.RawExtension{Raw: []byte(`cluster: {slaveCount: 2}`)}, }, }, - - HelmOptions: &argoappv1.HelmOptions{ValuesFileSchemes: []string{"https"}}, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, + HelmOptions: &argoappv1.HelmOptions{ValuesFileSchemes: []string{"https"}}, }) assert.NoError(t, err) } @@ -1032,6 +1065,8 @@ func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) { ValuesObject: &runtime.RawExtension{Raw: []byte(`cluster: {slaveCount: 2}`)}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.Error(t, err) assert.Contains(t, err.Error(), "outside repository root") @@ -1049,6 +1084,8 @@ func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) { ValuesObject: &runtime.RawExtension{Raw: []byte(`cluster: {slaveCount: 2}`)}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.NoError(t, err) }) @@ -1065,6 +1102,8 @@ func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) { ValuesObject: &runtime.RawExtension{Raw: []byte(`cluster: {slaveCount: 2}`)}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.NoError(t, err) }) @@ -1081,6 +1120,8 @@ func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) { ValuesObject: &runtime.RawExtension{Raw: []byte(`cluster: {slaveCount: 2}`)}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.Error(t, err) assert.Contains(t, err.Error(), "outside repository root") @@ -1098,6 +1139,8 @@ func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) { ValuesObject: &runtime.RawExtension{Raw: []byte(`cluster: {slaveCount: 2}`)}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.Error(t, err) assert.Contains(t, err.Error(), "is not allowed") @@ -1114,7 +1157,9 @@ func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) { ValueFiles: []string{"s3://my-bucket/my-chart-values.yaml"}, }, }, - HelmOptions: &argoappv1.HelmOptions{ValuesFileSchemes: []string{"s3"}}, + HelmOptions: &argoappv1.HelmOptions{ValuesFileSchemes: []string{"s3"}}, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.Error(t, err) assert.Contains(t, err.Error(), "s3://my-bucket/my-chart-values.yaml: no such file or directory") @@ -1153,6 +1198,8 @@ func TestGenerateHelmWithAbsoluteFileParameter(t *testing.T) { }}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.Error(t, err) } @@ -1179,6 +1226,8 @@ func TestGenerateHelmWithFileParameter(t *testing.T) { }}, }, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.NoError(t, err) assert.Contains(t, res.Manifests[6], `"replicas":2`, "ValuesObject should override Values") @@ -1189,9 +1238,11 @@ func TestGenerateNullList(t *testing.T) { t.Run("null list", func(t *testing.T) { res1, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{ - Repo: &argoappv1.Repository{}, - ApplicationSource: &argoappv1.ApplicationSource{Path: "./testdata/null-list"}, - NoCache: true, + Repo: &argoappv1.Repository{}, + ApplicationSource: &argoappv1.ApplicationSource{Path: "./testdata/null-list"}, + NoCache: true, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.Nil(t, err) assert.Equal(t, len(res1.Manifests), 1) @@ -1200,9 +1251,11 @@ func TestGenerateNullList(t *testing.T) { t.Run("empty list", func(t *testing.T) { res1, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{ - Repo: &argoappv1.Repository{}, - ApplicationSource: &argoappv1.ApplicationSource{Path: "./testdata/empty-list"}, - NoCache: true, + Repo: &argoappv1.Repository{}, + ApplicationSource: &argoappv1.ApplicationSource{Path: "./testdata/empty-list"}, + NoCache: true, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.Nil(t, err) assert.Equal(t, len(res1.Manifests), 1) @@ -1211,9 +1264,11 @@ func TestGenerateNullList(t *testing.T) { t.Run("weird list", func(t *testing.T) { res1, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{ - Repo: &argoappv1.Repository{}, - ApplicationSource: &argoappv1.ApplicationSource{Path: "./testdata/weird-list"}, - NoCache: true, + Repo: &argoappv1.Repository{}, + ApplicationSource: &argoappv1.ApplicationSource{Path: "./testdata/weird-list"}, + NoCache: true, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.Nil(t, err) assert.Len(t, res1.Manifests, 2) @@ -1236,8 +1291,10 @@ func TestIdentifyAppSourceTypeByAppDirWithKustomizations(t *testing.T) { func TestGenerateFromUTF16(t *testing.T) { q := apiclient.ManifestRequest{ - Repo: &argoappv1.Repository{}, - ApplicationSource: &argoappv1.ApplicationSource{}, + Repo: &argoappv1.Repository{}, + ApplicationSource: &argoappv1.ApplicationSource{}, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, } res1, err := GenerateManifests(context.Background(), "./testdata/utf-16", "/", "", &q, false, &git.NoopCredsStore{}, resource.MustParse("0"), nil) assert.Nil(t, err) @@ -1416,9 +1473,11 @@ func TestGetSignatureVerificationResult(t *testing.T) { src := argoappv1.ApplicationSource{Path: "."} q := apiclient.ManifestRequest{ - Repo: &argoappv1.Repository{}, - ApplicationSource: &src, - VerifySignature: true, + Repo: &argoappv1.Repository{}, + ApplicationSource: &src, + VerifySignature: true, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, } res, err := service.GenerateManifest(context.Background(), &q) @@ -1430,7 +1489,8 @@ func TestGetSignatureVerificationResult(t *testing.T) { service := newServiceWithSignature("../../manifests/base") src := argoappv1.ApplicationSource{Path: "."} - q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src} + q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src, ProjectName: "something", + ProjectSourceRepos: []string{"*"}} res, err := service.GenerateManifest(context.Background(), &q) assert.NoError(t, err) @@ -1441,7 +1501,8 @@ func TestGetSignatureVerificationResult(t *testing.T) { service := newService("../../manifests/base") src := argoappv1.ApplicationSource{Path: "."} - q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src, VerifySignature: true} + q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src, VerifySignature: true, ProjectName: "something", + ProjectSourceRepos: []string{"*"}} res, err := service.GenerateManifest(context.Background(), &q) assert.NoError(t, err) @@ -1452,7 +1513,8 @@ func TestGetSignatureVerificationResult(t *testing.T) { service := newService("../../manifests/base") src := argoappv1.ApplicationSource{Path: "."} - q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src, VerifySignature: true} + q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src, VerifySignature: true, ProjectName: "something", + ProjectSourceRepos: []string{"*"}} res, err := service.GenerateManifest(context.Background(), &q) assert.NoError(t, err) @@ -1612,6 +1674,8 @@ func TestGenerateManifestsWithAppParameterFile(t *testing.T) { ApplicationSource: &argoappv1.ApplicationSource{ Path: path, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) require.NoError(t, err) resourceByKindName := make(map[string]*unstructured.Unstructured) @@ -1641,6 +1705,8 @@ func TestGenerateManifestsWithAppParameterFile(t *testing.T) { ApplicationSource: &argoappv1.ApplicationSource{ Path: path, }, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) require.NoError(t, err) resourceByKindName := make(map[string]*unstructured.Unstructured) @@ -1670,7 +1736,9 @@ func TestGenerateManifestsWithAppParameterFile(t *testing.T) { ApplicationSource: &argoappv1.ApplicationSource{ Path: path, }, - AppName: "testapp", + AppName: "testapp", + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) require.NoError(t, err) resourceByKindName := make(map[string]*unstructured.Unstructured) @@ -1700,7 +1768,9 @@ func TestGenerateManifestsWithAppParameterFile(t *testing.T) { ApplicationSource: &argoappv1.ApplicationSource{ Path: path, }, - AppName: "testapp2", + AppName: "testapp2", + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) require.NoError(t, err) resourceByKindName := make(map[string]*unstructured.Unstructured) @@ -1730,9 +1800,11 @@ func TestGenerateManifestsWithAppParameterFile(t *testing.T) { } sourceCopy := source.DeepCopy() // make a copy in case GenerateManifest mutates it. _, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{ - Repo: &argoappv1.Repository{}, - ApplicationSource: sourceCopy, - AppName: "test", + Repo: &argoappv1.Repository{}, + ApplicationSource: sourceCopy, + AppName: "test", + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }) assert.NoError(t, err) res := &cache.CachedManifestResponse{} @@ -1766,7 +1838,9 @@ func TestGenerateManifestWithAnnotatedAndRegularGitTagHashes(t *testing.T) { ApplicationSource: &argoappv1.ApplicationSource{ TargetRevision: regularGitTagHash, }, - NoCache: true, + NoCache: true, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }, wantError: false, service: newServiceWithCommitSHA(".", regularGitTagHash), @@ -1780,7 +1854,9 @@ func TestGenerateManifestWithAnnotatedAndRegularGitTagHashes(t *testing.T) { ApplicationSource: &argoappv1.ApplicationSource{ TargetRevision: annotatedGitTaghash, }, - NoCache: true, + NoCache: true, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }, wantError: false, service: newServiceWithCommitSHA(".", annotatedGitTaghash), @@ -1794,7 +1870,9 @@ func TestGenerateManifestWithAnnotatedAndRegularGitTagHashes(t *testing.T) { ApplicationSource: &argoappv1.ApplicationSource{ TargetRevision: invalidGitTaghash, }, - NoCache: true, + NoCache: true, + ProjectName: "something", + ProjectSourceRepos: []string{"*"}, }, wantError: true, service: newServiceWithCommitSHA(".", invalidGitTaghash), diff --git a/server/application/application.go b/server/application/application.go index a0323cde5bccc..fe9697dc77056 100644 --- a/server/application/application.go +++ b/server/application/application.go @@ -463,6 +463,11 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan return fmt.Errorf("error getting API resources: %w", err) } + proj, err := argo.GetAppProject(a, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr, s.db, ctx) + if err != nil { + return fmt.Errorf("error getting app project: %w", err) + } + manifestInfo, err = client.GenerateManifest(ctx, &apiclient.ManifestRequest{ Repo: repo, Revision: revision, @@ -478,6 +483,8 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan HelmOptions: helmOptions, TrackingMethod: string(argoutil.GetTrackingMethod(s.settingsMgr)), EnabledSourceTypes: enableGenerateManifests, + ProjectName: proj.Name, + ProjectSourceRepos: proj.Spec.SourceRepos, }) if err != nil { return fmt.Errorf("error generating manifests: %w", err) @@ -553,6 +560,12 @@ func (s *Server) GetManifestsWithFiles(stream application.ApplicationService_Get } source := a.Spec.GetSource() + + proj, err := argo.GetAppProject(a, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr, s.db, ctx) + if err != nil { + return fmt.Errorf("error getting app project: %w", err) + } + req := &apiclient.ManifestRequest{ Repo: repo, Revision: source.TargetRevision, @@ -568,6 +581,8 @@ func (s *Server) GetManifestsWithFiles(stream application.ApplicationService_Get HelmOptions: helmOptions, TrackingMethod: string(argoutil.GetTrackingMethod(s.settingsMgr)), EnabledSourceTypes: enableGenerateManifests, + ProjectName: proj.Name, + ProjectSourceRepos: proj.Spec.SourceRepos, } repoStreamClient, err := client.GenerateManifestWithFiles(stream.Context()) @@ -1160,6 +1175,7 @@ func (s *Server) validateAndNormalizeApp(ctx context.Context, app *appv1.Applica } var conditions []appv1.ApplicationCondition + if validate { conditions := make([]appv1.ApplicationCondition, 0) condition, err := argo.ValidateRepo(ctx, app, s.repoClientset, s.db, s.kubectl, proj, s.settingsMgr) diff --git a/util/argo/argo.go b/util/argo/argo.go index b32369ea70c48..9b08d3aeeb847 100644 --- a/util/argo/argo.go +++ b/util/argo/argo.go @@ -419,6 +419,7 @@ func validateRepo(ctx context.Context, helmOptions, app.Name, app.Spec.Destination, + proj, sources, repoClient, cluster.ServerVersion, @@ -703,6 +704,7 @@ func verifyGenerateManifests( helmOptions *argoappv1.HelmOptions, name string, dest argoappv1.ApplicationDestination, + proj *argoappv1.AppProject, sources []argoappv1.ApplicationSource, repoClient apiclient.RepoServerServiceClient, kubeVersion string, @@ -769,6 +771,8 @@ func verifyGenerateManifests( NoRevisionCache: true, HasMultipleSources: hasMultipleSources, RefSources: refSources, + ProjectName: proj.Name, + ProjectSourceRepos: proj.Spec.SourceRepos, } req.Repo.CopyCredentialsFromRepo(repoRes) req.Repo.CopySettingsFrom(repoRes) From 1aad55e8b391fd830c49e7d01ac8f282b5bf3488 Mon Sep 17 00:00:00 2001 From: Blake Pettersson Date: Wed, 9 Aug 2023 22:01:13 +0200 Subject: [PATCH 5/7] wip Signed-off-by: Blake Pettersson --- reposerver/repository/repository.go | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go index c8dbd7b1bf5ec..40def8b3a90e9 100644 --- a/reposerver/repository/repository.go +++ b/reposerver/repository/repository.go @@ -1168,19 +1168,6 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie return nil, err } - var reposNotPermitted []string - // We do a sanity check here to give a nicer error message in case any of the Helm repositories are not permitted by - // the AppProject which the application is a part of - for _, repo := range helmRepos { - if !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { - reposNotPermitted = append(reposNotPermitted, repo.Repo) - } - } - - if len(reposNotPermitted) > 0 { - return nil, status.Errorf(codes.PermissionDenied, "helm repos %s are not permitted in project '%s'", strings.Join(reposNotPermitted, ", "), q.ProjectName) - } - h, err := helm.NewHelmApp(appPath, helmRepos, isLocal, version, proxy, passCredentials) if err != nil { return nil, err @@ -1209,12 +1196,12 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie // We do a sanity check here to give a nicer error message in case any of the Helm repositories are not permitted by // the AppProject which the application is a part of for _, repo := range helmRepos { - msg := err.Error() + //msg := err.Error() - chartCannotBeReached := strings.Contains(msg, "is not a valid chart repository or cannot be reached") - couldNotDownloadChart := strings.Contains(msg, "could not download") + //chartCannotBeReached := strings.Contains(msg, "is not a valid chart repository or cannot be reached") + //couldNotDownloadChart := strings.Contains(msg, "could not download") - if (chartCannotBeReached || couldNotDownloadChart) && !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { + if !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { reposNotPermitted = append(reposNotPermitted, repo.Repo) } } From 712bdce2a35143f028393f29451b4136ef5e50c1 Mon Sep 17 00:00:00 2001 From: Blake Pettersson Date: Thu, 10 Aug 2023 11:45:44 +0200 Subject: [PATCH 6/7] wip Signed-off-by: Blake Pettersson --- reposerver/repository/repository.go | 8 ++++---- test/e2e/helm_test.go | 2 +- .../Chart.yaml | 11 +++++++++++ .../helm-with-multiple-dependencies/Chart.yaml | 4 ++-- 4 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 test/e2e/testdata/helm-with-multiple-dependencies-permission-denied/Chart.yaml diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go index 40def8b3a90e9..61ef2db551ba2 100644 --- a/reposerver/repository/repository.go +++ b/reposerver/repository/repository.go @@ -1196,12 +1196,12 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie // We do a sanity check here to give a nicer error message in case any of the Helm repositories are not permitted by // the AppProject which the application is a part of for _, repo := range helmRepos { - //msg := err.Error() + msg := err.Error() - //chartCannotBeReached := strings.Contains(msg, "is not a valid chart repository or cannot be reached") - //couldNotDownloadChart := strings.Contains(msg, "could not download") + chartCannotBeReached := strings.Contains(msg, "is not a valid chart repository or cannot be reached") + couldNotDownloadChart := strings.Contains(msg, "could not download") - if !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { + if (chartCannotBeReached || couldNotDownloadChart) && !isSourcePermitted(repo.Repo, q.ProjectSourceRepos) { reposNotPermitted = append(reposNotPermitted, repo.Repo) } } diff --git a/test/e2e/helm_test.go b/test/e2e/helm_test.go index 23be345725d1d..107ab226cf558 100644 --- a/test/e2e/helm_test.go +++ b/test/e2e/helm_test.go @@ -429,7 +429,7 @@ func TestHelmWithMultipleDependenciesPermissionDenied(t *testing.T) { expectedErr = fmt.Sprintf("helm repos https://localhost:9443/argo-e2e/testdata.git/helm-repo/local, https://localhost:9443/argo-e2e/testdata.git/helm-repo/local2 are not permitted in project '%s'", projName) GivenWithSameState(t). Project(projName). - Path("helm-with-multiple-dependencies"). + Path("helm-with-multiple-dependencies-permission-denied"). CustomCACertAdded(). HelmHTTPSCredentialsUserPassAdded(). HelmPassCredentials(). diff --git a/test/e2e/testdata/helm-with-multiple-dependencies-permission-denied/Chart.yaml b/test/e2e/testdata/helm-with-multiple-dependencies-permission-denied/Chart.yaml new file mode 100644 index 0000000000000..72f36221ea482 --- /dev/null +++ b/test/e2e/testdata/helm-with-multiple-dependencies-permission-denied/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +name: helm-with-multiple-dependencies-permission-denied +version: v1.0.0 +dependencies: + - name: helm + repository: "https://localhost:9443/argo-e2e/testdata.git/helm-repo/local" + version: v1.0.0 + - name: helm + repository: "https://localhost:9443/argo-e2e/testdata.git/helm-repo/local2" + version: v1.0.0 + alias: helm2 \ No newline at end of file diff --git a/test/e2e/testdata/helm-with-multiple-dependencies/Chart.yaml b/test/e2e/testdata/helm-with-multiple-dependencies/Chart.yaml index 97f351834ff68..f7f144d20e123 100644 --- a/test/e2e/testdata/helm-with-multiple-dependencies/Chart.yaml +++ b/test/e2e/testdata/helm-with-multiple-dependencies/Chart.yaml @@ -3,9 +3,9 @@ name: helm-with-multiple-dependencies version: v1.0.0 dependencies: - name: helm - repository: "https://localhost:9443/argo-e2e/testdata.git/helm-repo/local" + repository: "https://localhost:9444/argo-e2e/testdata.git/helm-repo/local" version: v1.0.0 - name: helm - repository: "https://localhost:9443/argo-e2e/testdata.git/helm-repo/local2" + repository: "https://localhost:9444/argo-e2e/testdata.git/helm-repo/local2" version: v1.0.0 alias: helm2 \ No newline at end of file From ca5911cba6b5ab5bda99831342eb0950c1598dce Mon Sep 17 00:00:00 2001 From: Blake Pettersson Date: Thu, 10 Aug 2023 14:11:30 +0200 Subject: [PATCH 7/7] chore: reword test to reduce confusion Signed-off-by: Blake Pettersson --- test/e2e/helm_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/helm_test.go b/test/e2e/helm_test.go index 107ab226cf558..5fd774ea0c46d 100644 --- a/test/e2e/helm_test.go +++ b/test/e2e/helm_test.go @@ -401,7 +401,7 @@ func TestHelmWithMultipleDependencies(t *testing.T) { Expect(SyncStatusIs(SyncStatusCodeSynced)) } -func TestHelmWithMultipleDependenciesPermissionDenied(t *testing.T) { +func TestHelmDependenciesPermissionDenied(t *testing.T) { SkipOnEnv(t, "HELM") projName := "argo-helm-project-denied"