diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6205c1098d1f9e..7bb87b76e46f6d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -31,6 +31,11 @@ updates: directory: "/" schedule: interval: "daily" + ignore: + # We use consistent go and node versions across a lot of different files, and updating via dependabot would cause + # drift among those files, instead we let renovate bot handle them. + - dependency-name: "library/golang" + - dependency-name: "library/node" - package-ecosystem: "docker" directory: "/test/container/" diff --git a/.github/workflows/ci-build.yaml b/.github/workflows/ci-build.yaml index 5fe31bf6ca9f9c..dca14dd2756e14 100644 --- a/.github/workflows/ci-build.yaml +++ b/.github/workflows/ci-build.yaml @@ -13,7 +13,8 @@ on: env: # Golang version to use across CI steps - GOLANG_VERSION: '1.22' + # renovate: datasource=golang-version packageName=golang + GOLANG_VERSION: '1.23.2' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -31,7 +32,7 @@ jobs: docs: ${{ steps.filter.outputs.docs_any_changed }} steps: - uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0 - - uses: tj-actions/changed-files@48d8f15b2aaa3d255ca5af3eba4870f807ce6b3c # v45.0.2 + - uses: tj-actions/changed-files@c3a1bb2c992d77180ae65be6ae6c166cf40f857c # v45.0.3 id: filter with: # Any file which is not under docs/, ui/ or is not a markdown file is counted as a backend file @@ -81,7 +82,7 @@ jobs: with: go-version: ${{ env.GOLANG_VERSION }} - name: Restore go build cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: ~/.cache/go-build key: ${{ runner.os }}-go-build-v1-${{ github.run_id }} @@ -108,9 +109,10 @@ jobs: with: go-version: ${{ env.GOLANG_VERSION }} - name: Run golangci-lint - uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0 + uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 with: - version: v1.58.2 + # renovate: datasource=go packageName=github.com/golangci/golangci-lint versioning=regex:^v(?\d+)\.(?\d+)\.(?\d+)?$ + version: v1.61.0 args: --verbose test-go: @@ -151,7 +153,7 @@ jobs: run: | echo "/usr/local/bin" >> $GITHUB_PATH - name: Restore go build cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: ~/.cache/go-build key: ${{ runner.os }}-go-build-v1-${{ github.run_id }} @@ -215,7 +217,7 @@ jobs: run: | echo "/usr/local/bin" >> $GITHUB_PATH - name: Restore go build cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: ~/.cache/go-build key: ${{ runner.os }}-go-build-v1-${{ github.run_id }} @@ -305,10 +307,11 @@ jobs: - name: Setup NodeJS uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: - node-version: '21.6.1' + # renovate: datasource=node-version packageName=node versioning=node + node-version: '22.9.0' - name: Restore node dependency cache id: cache-dependencies - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: ui/node_modules key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }} @@ -348,7 +351,7 @@ jobs: fetch-depth: 0 - name: Restore node dependency cache id: cache-dependencies - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: ui/node_modules key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }} @@ -373,7 +376,7 @@ jobs: run: | go tool covdata percent -i=test-results,e2e-code-coverage/applicationset-controller,e2e-code-coverage/repo-server,e2e-code-coverage/app-controller -o test-results/full-coverage.out - name: Upload code coverage information to codecov.io - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0 with: file: test-results/full-coverage.out fail_ci_if_error: true @@ -390,7 +393,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - uses: SonarSource/sonarqube-scan-action@aecaf43ae57e412bd97d70ef9ce6076e672fe0a9 # v2.2 + uses: SonarSource/sonarqube-scan-action@0c0f3958d90fc466625f1d1af1f47bddd4cc6bd1 # v2.2 if: env.sonar_secret != '' test-e2e: name: Run end-to-end tests @@ -400,14 +403,14 @@ jobs: fail-fast: false matrix: k3s: - - version: v1.30.2 + - version: v1.31.0 # We designate the latest version because we only collect code coverage for that version. latest: true - - version: v1.29.6 + - version: v1.30.4 latest: false - - version: v1.28.11 + - version: v1.29.8 latest: false - - version: v1.27.15 + - version: v1.28.13 latest: false needs: - build-go @@ -448,7 +451,7 @@ jobs: sudo chmod go-r $HOME/.kube/config kubectl version - name: Restore go build cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0 with: path: ~/.cache/go-build key: ${{ runner.os }}-go-build-v1-${{ github.run_id }} diff --git a/.github/workflows/image-reuse.yaml b/.github/workflows/image-reuse.yaml index f4b7a851816a8a..1accb04f32982d 100644 --- a/.github/workflows/image-reuse.yaml +++ b/.github/workflows/image-reuse.yaml @@ -74,10 +74,10 @@ jobs: go-version: ${{ inputs.go-version }} - name: Install cosign - uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0 + uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - - uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1 + - uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 - name: Setup tags for container image as a CSV type run: | @@ -143,7 +143,7 @@ jobs: - name: Build and push container image id: image - uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 #v6.7.0 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 #v6.9.0 with: context: . platforms: ${{ inputs.platforms }} diff --git a/.github/workflows/image.yaml b/.github/workflows/image.yaml index 3102e8361aa06d..c9727562b390e2 100644 --- a/.github/workflows/image.yaml +++ b/.github/workflows/image.yaml @@ -52,7 +52,8 @@ jobs: uses: ./.github/workflows/image-reuse.yaml with: # Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations) - go-version: 1.22 + # renovate: datasource=golang-version packageName=golang + go-version: 1.23.2 platforms: ${{ needs.set-vars.outputs.platforms }} push: false @@ -68,7 +69,8 @@ jobs: quay_image_name: quay.io/argoproj/argocd:latest ghcr_image_name: ghcr.io/argoproj/argo-cd/argocd:${{ needs.set-vars.outputs.image-tag }} # Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations) - go-version: 1.22 + # renovate: datasource=golang-version packageName=golang + go-version: 1.23.2 platforms: ${{ needs.set-vars.outputs.platforms }} push: true secrets: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a30e44ec0ec7a4..ab49819359683e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,7 +10,8 @@ on: permissions: {} env: - GOLANG_VERSION: '1.22' # Note: go-version must also be set in job argocd-image.with.go-version + # renovate: datasource=golang-version packageName=golang + GOLANG_VERSION: '1.23.2' # Note: go-version must also be set in job argocd-image.with.go-version jobs: argocd-image: @@ -23,7 +24,8 @@ jobs: with: quay_image_name: quay.io/argoproj/argocd:${{ github.ref_name }} # Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations) - go-version: 1.22 + # renovate: datasource=golang-version packageName=golang + go-version: 1.23.2 platforms: linux/amd64,linux/arm64,linux/s390x,linux/ppc64le push: true secrets: diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 3d69498d27c09d..71bd86159aeb31 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -8,4 +8,4 @@ python: build: os: "ubuntu-22.04" tools: - python: "3.7" + python: "3.12" diff --git a/Dockerfile b/Dockerfile index bc4e6debbfaa1d..ca99b8be19f9e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:24.04@sha256:3f85b7caad41a95462cf5b787d8 # Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image # Also used as the image in CI jobs so needs all dependencies #################################################################################################### -FROM docker.io/library/golang:1.23.1@sha256:2fe82a3f3e006b4f2a316c6a21f62b66e1330ae211d039bb8d1128e12ed57bf1 AS builder +FROM docker.io/library/golang:1.23.2@sha256:adee809c2d0009a4199a11a1b2618990b244c6515149fe609e2788ddf164bd10 AS builder RUN echo 'deb http://archive.debian.org/debian buster-backports main' >> /etc/apt/sources.list @@ -83,7 +83,7 @@ WORKDIR /home/argocd #################################################################################################### # Argo CD UI stage #################################################################################################### -FROM --platform=$BUILDPLATFORM docker.io/library/node:22.9.0@sha256:cbe2d5f94110cea9817dd8c5809d05df49b4bd1aac5203f3594d88665ad37988 AS argocd-ui +FROM --platform=$BUILDPLATFORM docker.io/library/node:22.9.0@sha256:69e667a79aa41ec0db50bc452a60e705ca16f35285eaf037ebe627a65a5cdf52 AS argocd-ui WORKDIR /src COPY ["ui/package.json", "ui/yarn.lock", "./"] @@ -101,7 +101,7 @@ RUN HOST_ARCH=$TARGETARCH NODE_ENV='production' NODE_ONLINE_ENV='online' NODE_OP #################################################################################################### # Argo CD Build stage which performs the actual build of Argo CD binaries #################################################################################################### -FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.23.1@sha256:2fe82a3f3e006b4f2a316c6a21f62b66e1330ae211d039bb8d1128e12ed57bf1 AS argocd-build +FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.23.2@sha256:adee809c2d0009a4199a11a1b2618990b244c6515149fe609e2788ddf164bd10 AS argocd-build WORKDIR /go/src/github.com/argoproj/argo-cd diff --git a/USERS.md b/USERS.md index ab5dbc8c745c11..1d27bb459f9392 100644 --- a/USERS.md +++ b/USERS.md @@ -41,6 +41,7 @@ Currently, the following organizations are **officially** using Argo CD: 1. [Beez Innovation Labs](https://www.beezlabs.com/) 1. [Bedag Informatik AG](https://www.bedag.ch/) 1. [Beleza Na Web](https://www.belezanaweb.com.br/) +1. [Believable Bots](https://believablebots.io) 1. [BigPanda](https://bigpanda.io) 1. [BioBox Analytics](https://biobox.io) 1. [BMW Group](https://www.bmwgroup.com/) @@ -84,6 +85,7 @@ Currently, the following organizations are **officially** using Argo CD: 1. [D2iQ](https://www.d2iq.com) 1. [DaoCloud](https://daocloud.io/) 1. [Datarisk](https://www.datarisk.io/) +1. [Daydream](https://daydream.ing) 1. [Deloitte](https://www.deloitte.com/) 1. [Deutsche Telekom AG](https://telekom.com) 1. [Devopsi - Poland Software/DevOps Consulting](https://devopsi.pl/) @@ -242,6 +244,7 @@ Currently, the following organizations are **officially** using Argo CD: 1. [Optoro](https://www.optoro.com/) 1. [Orbital Insight](https://orbitalinsight.com/) 1. [Oscar Health Insurance](https://hioscar.com/) +1. [Outpost24](https://outpost24.com/) 1. [p3r](https://www.p3r.one/) 1. [Packlink](https://www.packlink.com/) 1. [PagerDuty](https://www.pagerduty.com/) @@ -330,6 +333,7 @@ Currently, the following organizations are **officially** using Argo CD: 1. [TableCheck](https://tablecheck.com/) 1. [Tailor Brands](https://www.tailorbrands.com) 1. [Tamkeen Technologies](https://tamkeentech.sa/) +1. [TBC Bank](https://tbcbank.ge/) 1. [Techcombank](https://www.techcombank.com.vn/trang-chu) 1. [Technacy](https://www.technacy.it/) 1. [Telavita](https://www.telavita.com.br/) diff --git a/applicationset/controllers/applicationset_controller.go b/applicationset/controllers/applicationset_controller.go index d3911f1e0c7c4e..fbba4212a0d2a0 100644 --- a/applicationset/controllers/applicationset_controller.go +++ b/applicationset/controllers/applicationset_controller.go @@ -52,7 +52,6 @@ import ( "github.com/argoproj/argo-cd/v2/util/db" argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" - appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned" argoutil "github.com/argoproj/argo-cd/v2/util/argo" "github.com/argoproj/argo-cd/v2/util/argo/normalizers" @@ -79,7 +78,6 @@ type ApplicationSetReconciler struct { Recorder record.EventRecorder Generators map[string]generators.Generator ArgoDB db.ArgoDB - ArgoAppClientset appclientset.Interface KubeClientset kubernetes.Interface Policy argov1alpha1.ApplicationsSyncPolicy EnablePolicyOverride bool @@ -97,6 +95,7 @@ type ApplicationSetReconciler struct { // +kubebuilder:rbac:groups=argoproj.io,resources=applicationsets/status,verbs=get;update;patch func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + startReconcile := time.Now() logCtx := log.WithField("applicationset", req.NamespacedName) var applicationSetInfo argov1alpha1.ApplicationSet @@ -334,7 +333,7 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque requeueAfter = ReconcileRequeueOnValidationError } - logCtx.WithField("requeueAfter", requeueAfter).Info("end reconcile") + logCtx.WithField("requeueAfter", requeueAfter).Info("end reconcile in ", time.Since(startReconcile)) return ctrl.Result{ RequeueAfter: requeueAfter, @@ -472,7 +471,9 @@ func (r *ApplicationSetReconciler) validateGeneratedApplications(ctx context.Con errorsByIndex[i] = fmt.Errorf("ApplicationSet %s contains applications with duplicate name: %s", applicationSetInfo.Name, app.Name) continue } - _, err := r.ArgoAppClientset.ArgoprojV1alpha1().AppProjects(r.ArgoCDNamespace).Get(ctx, app.Spec.GetProject(), metav1.GetOptions{}) + + appProject := &argov1alpha1.AppProject{} + err := r.Client.Get(ctx, types.NamespacedName{Name: app.Spec.Project, Namespace: r.ArgoCDNamespace}, appProject) if err != nil { if apierr.IsNotFound(err) { errorsByIndex[i] = fmt.Errorf("application references project %s which does not exist", app.Spec.Project) @@ -1484,7 +1485,7 @@ func getOwnsHandlerPredicates(enableProgressiveSyncs bool) predicate.Funcs { return false } requeue := shouldRequeueApplicationSet(appOld, appNew, enableProgressiveSyncs) - logCtx.WithField("requeue", requeue).Debugf("requeue: %t caused by application %s\n", requeue, appNew.Name) + logCtx.WithField("requeue", requeue).Debugf("requeue: %t caused by application %s", requeue, appNew.Name) return requeue }, GenericFunc: func(e event.GenericEvent) bool { diff --git a/applicationset/controllers/applicationset_controller_test.go b/applicationset/controllers/applicationset_controller_test.go index 02608175245b47..1b3a2253985871 100644 --- a/applicationset/controllers/applicationset_controller_test.go +++ b/applicationset/controllers/applicationset_controller_test.go @@ -37,7 +37,6 @@ import ( appsetmetrics "github.com/argoproj/argo-cd/v2/applicationset/metrics" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" - appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned/fake" dbmocks "github.com/argoproj/argo-cd/v2/util/db/mocks" "github.com/argoproj/argo-cd/v2/pkg/apis/application" @@ -48,9 +47,6 @@ func TestCreateOrUpdateInCluster(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - for _, c := range []struct { // name is human-readable test name name string @@ -1091,9 +1087,6 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - for _, c := range []struct { // name is human-readable test name name string @@ -1214,9 +1207,6 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - for _, c := range []struct { // name is human-readable test name name string @@ -1371,9 +1361,6 @@ func TestRemoveOwnerReferencesOnDeleteAppSet(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - for _, c := range []struct { // name is human-readable test name name string @@ -1447,9 +1434,6 @@ func TestCreateApplications(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - testCases := []struct { name string appSet v1alpha1.ApplicationSet @@ -1653,8 +1637,6 @@ func TestDeleteInCluster(t *testing.T) { scheme := runtime.NewScheme() err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) for _, c := range []struct { // appSet is the application set on which the delete function is called @@ -1809,8 +1791,6 @@ func TestGetMinRequeueAfter(t *testing.T) { scheme := runtime.NewScheme() err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) client := fake.NewClientBuilder().WithScheme(scheme).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) @@ -1913,12 +1893,6 @@ func TestValidateGeneratedApplications(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - - client := fake.NewClientBuilder().WithScheme(scheme).Build() - metrics := appsetmetrics.NewFakeAppsetMetrics(client) - // Valid cluster myCluster := v1alpha1.Cluster{ Server: "https://kubernetes.default.svc", @@ -1945,6 +1919,9 @@ func TestValidateGeneratedApplications(t *testing.T) { }, } + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(myProject).Build() + metrics := appsetmetrics.NewFakeAppsetMetrics(client) + // Test a subset of the validations that 'validateGeneratedApplications' performs for _, cc := range []struct { name string @@ -2094,21 +2071,15 @@ func TestValidateGeneratedApplications(t *testing.T) { myCluster, }}, nil) - argoObjs := []runtime.Object{myProject} - for _, app := range cc.apps { - argoObjs = append(argoObjs, &app) - } - r := ApplicationSetReconciler{ - Client: client, - Scheme: scheme, - Recorder: record.NewFakeRecorder(1), - Generators: map[string]generators.Generator{}, - ArgoDB: &argoDBMock, - ArgoCDNamespace: "namespace", - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Metrics: metrics, + Client: client, + Scheme: scheme, + Recorder: record.NewFakeRecorder(1), + Generators: map[string]generators.Generator{}, + ArgoDB: &argoDBMock, + ArgoCDNamespace: "namespace", + KubeClientset: kubeclientset, + Metrics: metrics, } appSetInfo := v1alpha1.ApplicationSet{} @@ -2150,8 +2121,6 @@ func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) { scheme := runtime.NewScheme() err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) project := v1alpha1.AppProject{ ObjectMeta: metav1.ObjectMeta{Name: "good-project", Namespace: "argocd"}, @@ -2190,9 +2159,8 @@ func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) { kubeclientset := kubefake.NewSimpleClientset() argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{&project} - client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &project).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) goodCluster := v1alpha1.Cluster{Server: "https://good-cluster", Name: "good-cluster"} badCluster := v1alpha1.Cluster{Server: "https://bad-cluster", Name: "bad-cluster"} @@ -2210,12 +2178,11 @@ func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) { Generators: map[string]generators.Generator{ "List": generators.NewListGenerator(), }, - ArgoDB: &argoDBMock, - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Policy: v1alpha1.ApplicationsSyncPolicySync, - ArgoCDNamespace: "argocd", - Metrics: metrics, + ArgoDB: &argoDBMock, + KubeClientset: kubeclientset, + Policy: v1alpha1.ApplicationsSyncPolicySync, + ArgoCDNamespace: "argocd", + Metrics: metrics, } req := ctrl.Request{ @@ -2246,8 +2213,6 @@ func TestSetApplicationSetStatusCondition(t *testing.T) { scheme := runtime.NewScheme() err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) testCases := []struct { appset v1alpha1.ApplicationSet @@ -2395,7 +2360,6 @@ func TestSetApplicationSetStatusCondition(t *testing.T) { kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...) argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{} for _, testCase := range testCases { client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&testCase.appset).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).WithStatusSubresource(&testCase.appset).Build() @@ -2409,10 +2373,9 @@ func TestSetApplicationSetStatusCondition(t *testing.T) { Generators: map[string]generators.Generator{ "List": generators.NewListGenerator(), }, - ArgoDB: &argoDBMock, - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Metrics: metrics, + ArgoDB: &argoDBMock, + KubeClientset: kubeclientset, + Metrics: metrics, } for _, condition := range testCase.conditions { @@ -2428,8 +2391,6 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp scheme := runtime.NewScheme() err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) defaultProject := v1alpha1.AppProject{ ObjectMeta: metav1.ObjectMeta{Name: "default", Namespace: "argocd"}, @@ -2469,9 +2430,8 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp kubeclientset := kubefake.NewSimpleClientset() argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{&defaultProject} - client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &defaultProject).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) goodCluster := v1alpha1.Cluster{Server: "https://good-cluster", Name: "good-cluster"} argoDBMock.On("GetCluster", mock.Anything, "https://good-cluster").Return(&goodCluster, nil) @@ -2489,7 +2449,6 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp }, ArgoDB: &argoDBMock, ArgoCDNamespace: "argocd", - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), KubeClientset: kubeclientset, Policy: v1alpha1.ApplicationsSyncPolicySync, EnablePolicyOverride: allowPolicyOverride, @@ -2593,8 +2552,6 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp scheme := runtime.NewScheme() err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) defaultProject := v1alpha1.AppProject{ ObjectMeta: metav1.ObjectMeta{Name: "default", Namespace: "argocd"}, @@ -2634,9 +2591,8 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp kubeclientset := kubefake.NewSimpleClientset() argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{&defaultProject} - client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &defaultProject).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) goodCluster := v1alpha1.Cluster{Server: "https://good-cluster", Name: "good-cluster"} argoDBMock.On("GetCluster", mock.Anything, "https://good-cluster").Return(&goodCluster, nil) @@ -2654,7 +2610,6 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp }, ArgoDB: &argoDBMock, ArgoCDNamespace: "argocd", - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), KubeClientset: kubeclientset, Policy: v1alpha1.ApplicationsSyncPolicySync, EnablePolicyOverride: allowPolicyOverride, @@ -2752,9 +2707,6 @@ func TestPolicies(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - defaultProject := v1alpha1.AppProject{ ObjectMeta: metav1.ObjectMeta{Name: "default", Namespace: "argocd"}, Spec: v1alpha1.AppProjectSpec{SourceRepos: []string{"*"}, Destinations: []v1alpha1.ApplicationDestination{{Namespace: "*", Server: "https://kubernetes.default.svc"}}}, @@ -2767,7 +2719,6 @@ func TestPolicies(t *testing.T) { kubeclientset := kubefake.NewSimpleClientset() argoDBMock := dbmocks.ArgoDB{} argoDBMock.On("GetCluster", mock.Anything, "https://kubernetes.default.svc").Return(&myCluster, nil) - argoObjs := []runtime.Object{&defaultProject} for _, c := range []struct { name string @@ -2839,7 +2790,7 @@ func TestPolicies(t *testing.T) { }, } - client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &defaultProject).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) r := ApplicationSetReconciler{ @@ -2850,12 +2801,11 @@ func TestPolicies(t *testing.T) { Generators: map[string]generators.Generator{ "List": generators.NewListGenerator(), }, - ArgoDB: &argoDBMock, - ArgoCDNamespace: "argocd", - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Policy: policy, - Metrics: metrics, + ArgoDB: &argoDBMock, + ArgoCDNamespace: "argocd", + KubeClientset: kubeclientset, + Policy: policy, + Metrics: metrics, } req := ctrl.Request{ @@ -2923,12 +2873,9 @@ func TestSetApplicationSetApplicationStatus(t *testing.T) { scheme := runtime.NewScheme() err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...) argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{} for _, cc := range []struct { name string @@ -3012,10 +2959,9 @@ func TestSetApplicationSetApplicationStatus(t *testing.T) { Generators: map[string]generators.Generator{ "List": generators.NewListGenerator(), }, - ArgoDB: &argoDBMock, - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Metrics: metrics, + ArgoDB: &argoDBMock, + KubeClientset: kubeclientset, + Metrics: metrics, } err = r.setAppSetApplicationStatus(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.appStatuses) @@ -3031,9 +2977,6 @@ func TestBuildAppDependencyList(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - client := fake.NewClientBuilder().WithScheme(scheme).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) @@ -3766,17 +3709,15 @@ func TestBuildAppDependencyList(t *testing.T) { t.Run(cc.name, func(t *testing.T) { kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...) argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{} r := ApplicationSetReconciler{ - Client: client, - Scheme: scheme, - Recorder: record.NewFakeRecorder(1), - Generators: map[string]generators.Generator{}, - ArgoDB: &argoDBMock, - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Metrics: metrics, + Client: client, + Scheme: scheme, + Recorder: record.NewFakeRecorder(1), + Generators: map[string]generators.Generator{}, + ArgoDB: &argoDBMock, + KubeClientset: kubeclientset, + Metrics: metrics, } appDependencyList, appStepMap := r.buildAppDependencyList(log.NewEntry(log.StandardLogger()), cc.appSet, cc.apps) @@ -3791,9 +3732,6 @@ func TestBuildAppSyncMap(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - client := fake.NewClientBuilder().WithScheme(scheme).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) @@ -4357,17 +4295,15 @@ func TestBuildAppSyncMap(t *testing.T) { t.Run(cc.name, func(t *testing.T) { kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...) argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{} r := ApplicationSetReconciler{ - Client: client, - Scheme: scheme, - Recorder: record.NewFakeRecorder(1), - Generators: map[string]generators.Generator{}, - ArgoDB: &argoDBMock, - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Metrics: metrics, + Client: client, + Scheme: scheme, + Recorder: record.NewFakeRecorder(1), + Generators: map[string]generators.Generator{}, + ArgoDB: &argoDBMock, + KubeClientset: kubeclientset, + Metrics: metrics, } appSyncMap := r.buildAppSyncMap(cc.appSet, cc.appDependencyList, cc.appMap) @@ -4381,9 +4317,6 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - for _, cc := range []struct { name string appSet v1alpha1.ApplicationSet @@ -5144,20 +5077,18 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { t.Run(cc.name, func(t *testing.T) { kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...) argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{} client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&cc.appSet).WithStatusSubresource(&cc.appSet).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) r := ApplicationSetReconciler{ - Client: client, - Scheme: scheme, - Recorder: record.NewFakeRecorder(1), - Generators: map[string]generators.Generator{}, - ArgoDB: &argoDBMock, - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Metrics: metrics, + Client: client, + Scheme: scheme, + Recorder: record.NewFakeRecorder(1), + Generators: map[string]generators.Generator{}, + ArgoDB: &argoDBMock, + KubeClientset: kubeclientset, + Metrics: metrics, } appStatuses, err := r.updateApplicationSetApplicationStatus(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.apps, cc.appStepMap) @@ -5178,9 +5109,6 @@ func TestUpdateApplicationSetApplicationStatusProgress(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - for _, cc := range []struct { name string appSet v1alpha1.ApplicationSet @@ -5898,20 +5826,18 @@ func TestUpdateApplicationSetApplicationStatusProgress(t *testing.T) { t.Run(cc.name, func(t *testing.T) { kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...) argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{} client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&cc.appSet).WithStatusSubresource(&cc.appSet).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) r := ApplicationSetReconciler{ - Client: client, - Scheme: scheme, - Recorder: record.NewFakeRecorder(1), - Generators: map[string]generators.Generator{}, - ArgoDB: &argoDBMock, - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Metrics: metrics, + Client: client, + Scheme: scheme, + Recorder: record.NewFakeRecorder(1), + Generators: map[string]generators.Generator{}, + ArgoDB: &argoDBMock, + KubeClientset: kubeclientset, + Metrics: metrics, } appStatuses, err := r.updateApplicationSetApplicationStatusProgress(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.appSyncMap, cc.appStepMap) @@ -5932,9 +5858,6 @@ func TestUpdateResourceStatus(t *testing.T) { err := v1alpha1.AddToScheme(scheme) require.NoError(t, err) - err = v1alpha1.AddToScheme(scheme) - require.NoError(t, err) - for _, cc := range []struct { name string appSet v1alpha1.ApplicationSet @@ -6114,20 +6037,18 @@ func TestUpdateResourceStatus(t *testing.T) { t.Run(cc.name, func(t *testing.T) { kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...) argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{} client := fake.NewClientBuilder().WithScheme(scheme).WithStatusSubresource(&cc.appSet).WithObjects(&cc.appSet).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) r := ApplicationSetReconciler{ - Client: client, - Scheme: scheme, - Recorder: record.NewFakeRecorder(1), - Generators: map[string]generators.Generator{}, - ArgoDB: &argoDBMock, - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Metrics: metrics, + Client: client, + Scheme: scheme, + Recorder: record.NewFakeRecorder(1), + Generators: map[string]generators.Generator{}, + ArgoDB: &argoDBMock, + KubeClientset: kubeclientset, + Metrics: metrics, } err := r.updateResourcesStatus(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.apps) @@ -6206,20 +6127,18 @@ func TestResourceStatusAreOrdered(t *testing.T) { t.Run(cc.name, func(t *testing.T) { kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...) argoDBMock := dbmocks.ArgoDB{} - argoObjs := []runtime.Object{} client := fake.NewClientBuilder().WithScheme(scheme).WithStatusSubresource(&cc.appSet).WithObjects(&cc.appSet).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) r := ApplicationSetReconciler{ - Client: client, - Scheme: scheme, - Recorder: record.NewFakeRecorder(1), - Generators: map[string]generators.Generator{}, - ArgoDB: &argoDBMock, - ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...), - KubeClientset: kubeclientset, - Metrics: metrics, + Client: client, + Scheme: scheme, + Recorder: record.NewFakeRecorder(1), + Generators: map[string]generators.Generator{}, + ArgoDB: &argoDBMock, + KubeClientset: kubeclientset, + Metrics: metrics, } err := r.updateResourcesStatus(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.apps) diff --git a/applicationset/controllers/requeue_after_test.go b/applicationset/controllers/requeue_after_test.go index fd922f53566a54..674a7ff074bccc 100644 --- a/applicationset/controllers/requeue_after_test.go +++ b/applicationset/controllers/requeue_after_test.go @@ -100,7 +100,8 @@ func TestRequeueAfter(t *testing.T) { } type args struct { - appset *argov1alpha1.ApplicationSet + appset *argov1alpha1.ApplicationSet + requeueAfterOverride string } tests := []struct { name string @@ -108,11 +109,13 @@ func TestRequeueAfter(t *testing.T) { want time.Duration wantErr assert.ErrorAssertionFunc }{ - {name: "Cluster", args: args{appset: &argov1alpha1.ApplicationSet{ - Spec: argov1alpha1.ApplicationSetSpec{ - Generators: []argov1alpha1.ApplicationSetGenerator{{Clusters: &argov1alpha1.ClusterGenerator{}}}, - }, - }}, want: generators.NoRequeueAfter, wantErr: assert.NoError}, + {name: "Cluster", args: args{ + appset: &argov1alpha1.ApplicationSet{ + Spec: argov1alpha1.ApplicationSetSpec{ + Generators: []argov1alpha1.ApplicationSetGenerator{{Clusters: &argov1alpha1.ClusterGenerator{}}}, + }, + }, requeueAfterOverride: "", + }, want: generators.NoRequeueAfter, wantErr: assert.NoError}, {name: "ClusterMergeNested", args: args{&argov1alpha1.ApplicationSet{ Spec: argov1alpha1.ApplicationSetSpec{ Generators: []argov1alpha1.ApplicationSetGenerator{ @@ -127,7 +130,7 @@ func TestRequeueAfter(t *testing.T) { }}, }, }, - }}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError}, + }, ""}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError}, {name: "ClusterMatrixNested", args: args{&argov1alpha1.ApplicationSet{ Spec: argov1alpha1.ApplicationSetSpec{ Generators: []argov1alpha1.ApplicationSetGenerator{ @@ -142,15 +145,65 @@ func TestRequeueAfter(t *testing.T) { }}, }, }, - }}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError}, + }, ""}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError}, {name: "ListGenerator", args: args{appset: &argov1alpha1.ApplicationSet{ Spec: argov1alpha1.ApplicationSetSpec{ Generators: []argov1alpha1.ApplicationSetGenerator{{List: &argov1alpha1.ListGenerator{}}}, }, }}, want: generators.NoRequeueAfter, wantErr: assert.NoError}, + {name: "DuckGenerator", args: args{appset: &argov1alpha1.ApplicationSet{ + Spec: argov1alpha1.ApplicationSetSpec{ + Generators: []argov1alpha1.ApplicationSetGenerator{{ClusterDecisionResource: &argov1alpha1.DuckTypeGenerator{}}}, + }, + }}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError}, + {name: "OverrideRequeueDuck", args: args{ + appset: &argov1alpha1.ApplicationSet{ + Spec: argov1alpha1.ApplicationSetSpec{ + Generators: []argov1alpha1.ApplicationSetGenerator{{ClusterDecisionResource: &argov1alpha1.DuckTypeGenerator{}}}, + }, + }, requeueAfterOverride: "1h", + }, want: 1 * time.Hour, wantErr: assert.NoError}, + {name: "OverrideRequeueGit", args: args{&argov1alpha1.ApplicationSet{ + Spec: argov1alpha1.ApplicationSetSpec{ + Generators: []argov1alpha1.ApplicationSetGenerator{ + {Git: &argov1alpha1.GitGenerator{}}, + }, + }, + }, "1h"}, want: 1 * time.Hour, wantErr: assert.NoError}, + {name: "OverrideRequeueMatrix", args: args{&argov1alpha1.ApplicationSet{ + Spec: argov1alpha1.ApplicationSetSpec{ + Generators: []argov1alpha1.ApplicationSetGenerator{ + {Clusters: &argov1alpha1.ClusterGenerator{}}, + {Merge: &argov1alpha1.MergeGenerator{ + Generators: []argov1alpha1.ApplicationSetNestedGenerator{ + { + Clusters: &argov1alpha1.ClusterGenerator{}, + Git: &argov1alpha1.GitGenerator{}, + }, + }, + }}, + }, + }, + }, "5m"}, want: 5 * time.Minute, wantErr: assert.NoError}, + {name: "OverrideRequeueMerge", args: args{&argov1alpha1.ApplicationSet{ + Spec: argov1alpha1.ApplicationSetSpec{ + Generators: []argov1alpha1.ApplicationSetGenerator{ + {Clusters: &argov1alpha1.ClusterGenerator{}}, + {Merge: &argov1alpha1.MergeGenerator{ + Generators: []argov1alpha1.ApplicationSetNestedGenerator{ + { + Clusters: &argov1alpha1.ClusterGenerator{}, + Git: &argov1alpha1.GitGenerator{}, + }, + }, + }}, + }, + }, + }, "12s"}, want: 12 * time.Second, wantErr: assert.NoError}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Setenv("ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER", tt.args.requeueAfterOverride) assert.Equalf(t, tt.want, r.getMinRequeueAfter(tt.args.appset), "getMinRequeueAfter(%v)", tt.args.appset) }) } diff --git a/applicationset/generators/cluster.go b/applicationset/generators/cluster.go index eafb3de1fabb6e..e3c98f95be84ca 100644 --- a/applicationset/generators/cluster.go +++ b/applicationset/generators/cluster.go @@ -92,6 +92,10 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap secretsFound := []corev1.Secret{} + isFlatMode := appSetGenerator.Clusters.FlatList + log.Debug("Using flat mode = ", isFlatMode, " for cluster generator") + clustersParams := make([]map[string]interface{}, 0) + for _, cluster := range clustersFromArgoCD.Items { // If there is a secret for this cluster, then it's a non-local cluster, so it will be // handled by the next step. @@ -109,7 +113,11 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap return nil, fmt.Errorf("error appending templated values for local cluster: %w", err) } - res = append(res, params) + if isFlatMode { + clustersParams = append(clustersParams, params) + } else { + res = append(res, params) + } log.WithField("cluster", "local cluster").Info("matched local cluster") } @@ -149,11 +157,20 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap return nil, fmt.Errorf("error appending templated values for cluster: %w", err) } - res = append(res, params) + if isFlatMode { + clustersParams = append(clustersParams, params) + } else { + res = append(res, params) + } log.WithField("cluster", cluster.Name).Info("matched cluster secret") } + if isFlatMode { + res = append(res, map[string]interface{}{ + "clusters": clustersParams, + }) + } return res, nil } diff --git a/applicationset/generators/cluster_test.go b/applicationset/generators/cluster_test.go index f319081c092187..09187f56569d37 100644 --- a/applicationset/generators/cluster_test.go +++ b/applicationset/generators/cluster_test.go @@ -84,10 +84,11 @@ func TestGenerateParams(t *testing.T) { }, } testCases := []struct { - name string - selector metav1.LabelSelector - values map[string]string - expected []map[string]interface{} + name string + selector metav1.LabelSelector + isFlatMode bool + values map[string]string + expected []map[string]interface{} // clientError is true if a k8s client error should be simulated clientError bool expectedError error @@ -105,6 +106,7 @@ func TestGenerateParams(t *testing.T) { "aaa": "{{ server }}", "no-op": "{{ this-does-not-exist }}", }, expected: []map[string]interface{}{ + {"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "{{ metadata.annotations.foo.argoproj.io }}", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "{{ metadata.labels.environment }}", "values.aaa": "https://kubernetes.default.svc", "nameNormalized": "in-cluster", "name": "in-cluster", "server": "https://kubernetes.default.svc"}, { "values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "production", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "production", "values.aaa": "https://production-01.example.com", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar", "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production", @@ -114,8 +116,6 @@ func TestGenerateParams(t *testing.T) { "values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "staging", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "staging", "values.aaa": "https://staging-01.example.com", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo", "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging", }, - - {"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "{{ metadata.annotations.foo.argoproj.io }}", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "{{ metadata.labels.environment }}", "values.aaa": "https://kubernetes.default.svc", "nameNormalized": "in-cluster", "name": "in-cluster", "server": "https://kubernetes.default.svc"}, }, clientError: false, expectedError: nil, @@ -228,6 +228,74 @@ func TestGenerateParams(t *testing.T) { clientError: true, expectedError: fmt.Errorf("error getting cluster secrets: could not list Secrets"), }, + { + name: "flat mode without selectors", + selector: metav1.LabelSelector{}, + values: map[string]string{ + "lol1": "lol", + "lol2": "{{values.lol1}}{{values.lol1}}", + "lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", + "foo": "bar", + "bar": "{{ metadata.annotations.foo.argoproj.io }}", + "bat": "{{ metadata.labels.environment }}", + "aaa": "{{ server }}", + "no-op": "{{ this-does-not-exist }}", + }, + expected: []map[string]interface{}{ + { + "clusters": []map[string]interface{}{ + {"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "{{ metadata.annotations.foo.argoproj.io }}", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "{{ metadata.labels.environment }}", "values.aaa": "https://kubernetes.default.svc", "nameNormalized": "in-cluster", "name": "in-cluster", "server": "https://kubernetes.default.svc"}, + { + "values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "production", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "production", "values.aaa": "https://production-01.example.com", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar", + "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production", + }, + + { + "values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "staging", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "staging", "values.aaa": "https://staging-01.example.com", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo", + "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging", + }, + }, + }, + }, + isFlatMode: true, + clientError: false, + expectedError: nil, + }, + { + name: "production or staging with flat mode", + selector: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "environment", + Operator: "In", + Values: []string{ + "production", + "staging", + }, + }, + }, + }, + isFlatMode: true, + values: map[string]string{ + "foo": "bar", + }, + expected: []map[string]interface{}{ + { + "clusters": []map[string]interface{}{ + { + "values.foo": "bar", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar", + "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production", + }, + { + "values.foo": "bar", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo", + "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging", + }, + }, + }, + }, + clientError: false, + expectedError: nil, + }, } // convert []client.Object to []runtime.Object, for use by kubefake package @@ -259,6 +327,7 @@ func TestGenerateParams(t *testing.T) { Clusters: &argoprojiov1alpha1.ClusterGenerator{ Selector: testCase.selector, Values: testCase.values, + FlatList: testCase.isFlatMode, }, }, &applicationSetInfo, nil) @@ -324,10 +393,11 @@ func TestGenerateParamsGoTemplate(t *testing.T) { }, } testCases := []struct { - name string - selector metav1.LabelSelector - values map[string]string - expected []map[string]interface{} + name string + selector metav1.LabelSelector + values map[string]string + isFlatMode bool + expected []map[string]interface{} // clientError is true if a k8s client error should be simulated clientError bool expectedError error @@ -599,6 +669,157 @@ func TestGenerateParamsGoTemplate(t *testing.T) { clientError: true, expectedError: fmt.Errorf("error getting cluster secrets: could not list Secrets"), }, + { + name: "Clusters with flat list mode and no selector", + selector: metav1.LabelSelector{}, + isFlatMode: true, + values: map[string]string{ + "lol1": "lol", + "lol2": "{{ .values.lol1 }}{{ .values.lol1 }}", + "lol3": "{{ .values.lol2 }}{{ .values.lol2 }}{{ .values.lol2 }}", + "foo": "bar", + "bar": "{{ if not (empty .metadata) }}{{index .metadata.annotations \"foo.argoproj.io\" }}{{ end }}", + "bat": "{{ if not (empty .metadata) }}{{.metadata.labels.environment}}{{ end }}", + "aaa": "{{ .server }}", + "no-op": "{{ .thisDoesNotExist }}", + }, + expected: []map[string]interface{}{ + { + "clusters": []map[string]interface{}{ + { + "nameNormalized": "in-cluster", + "name": "in-cluster", + "server": "https://kubernetes.default.svc", + "values": map[string]string{ + "lol1": "lol", + "lol2": "", + "lol3": "", + "foo": "bar", + "bar": "", + "bat": "", + "aaa": "https://kubernetes.default.svc", + "no-op": "", + }, + }, + { + "name": "production_01/west", + "nameNormalized": "production-01-west", + "server": "https://production-01.example.com", + "metadata": map[string]interface{}{ + "labels": map[string]string{ + "argocd.argoproj.io/secret-type": "cluster", + "environment": "production", + "org": "bar", + }, + "annotations": map[string]string{ + "foo.argoproj.io": "production", + }, + }, + "values": map[string]string{ + "lol1": "lol", + "lol2": "", + "lol3": "", + "foo": "bar", + "bar": "production", + "bat": "production", + "aaa": "https://production-01.example.com", + "no-op": "", + }, + }, + { + "name": "staging-01", + "nameNormalized": "staging-01", + "server": "https://staging-01.example.com", + "metadata": map[string]interface{}{ + "labels": map[string]string{ + "argocd.argoproj.io/secret-type": "cluster", + "environment": "staging", + "org": "foo", + }, + "annotations": map[string]string{ + "foo.argoproj.io": "staging", + }, + }, + "values": map[string]string{ + "lol1": "lol", + "lol2": "", + "lol3": "", + "foo": "bar", + "bar": "staging", + "bat": "staging", + "aaa": "https://staging-01.example.com", + "no-op": "", + }, + }, + }, + }, + }, + clientError: false, + expectedError: nil, + }, + { + name: "production or staging with flat mode", + selector: metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "environment", + Operator: "In", + Values: []string{ + "production", + "staging", + }, + }, + }, + }, + isFlatMode: true, + values: map[string]string{ + "foo": "bar", + }, + expected: []map[string]interface{}{ + { + "clusters": []map[string]interface{}{ + { + "name": "production_01/west", + "nameNormalized": "production-01-west", + "server": "https://production-01.example.com", + "metadata": map[string]interface{}{ + "labels": map[string]string{ + "argocd.argoproj.io/secret-type": "cluster", + "environment": "production", + "org": "bar", + }, + "annotations": map[string]string{ + "foo.argoproj.io": "production", + }, + }, + "values": map[string]string{ + "foo": "bar", + }, + }, + { + "name": "staging-01", + "nameNormalized": "staging-01", + "server": "https://staging-01.example.com", + "metadata": map[string]interface{}{ + "labels": map[string]string{ + "argocd.argoproj.io/secret-type": "cluster", + "environment": "staging", + "org": "foo", + }, + "annotations": map[string]string{ + "foo.argoproj.io": "staging", + }, + }, + "values": map[string]string{ + "foo": "bar", + }, + }, + }, + }, + }, + clientError: false, + expectedError: nil, + }, } // convert []client.Object to []runtime.Object, for use by kubefake package @@ -632,6 +853,7 @@ func TestGenerateParamsGoTemplate(t *testing.T) { Clusters: &argoprojiov1alpha1.ClusterGenerator{ Selector: testCase.selector, Values: testCase.values, + FlatList: testCase.isFlatMode, }, }, &applicationSetInfo, nil) diff --git a/applicationset/generators/duck_type.go b/applicationset/generators/duck_type.go index d7ceafd31de3be..7bd78a07146b23 100644 --- a/applicationset/generators/duck_type.go +++ b/applicationset/generators/duck_type.go @@ -52,7 +52,7 @@ func (g *DuckTypeGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1. return time.Duration(*appSetGenerator.ClusterDecisionResource.RequeueAfterSeconds) * time.Second } - return DefaultRequeueAfterSeconds + return getDefaultRequeueAfter() } func (g *DuckTypeGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) *argoprojiov1alpha1.ApplicationSetTemplate { diff --git a/applicationset/generators/git.go b/applicationset/generators/git.go index 74fe02044b4738..d119824f401747 100644 --- a/applicationset/generators/git.go +++ b/applicationset/generators/git.go @@ -48,7 +48,7 @@ func (g *GitGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.Appli return time.Duration(*appSetGenerator.Git.RequeueAfterSeconds) * time.Second } - return DefaultRequeueAfterSeconds + return getDefaultRequeueAfter() } func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet, client client.Client) ([]map[string]interface{}, error) { diff --git a/applicationset/generators/interface.go b/applicationset/generators/interface.go index ea105c78422791..88853c73b2b56b 100644 --- a/applicationset/generators/interface.go +++ b/applicationset/generators/interface.go @@ -7,6 +7,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" + "github.com/argoproj/argo-cd/v2/util/env" ) // Generator defines the interface implemented by all ApplicationSet generators. @@ -30,7 +31,11 @@ var ( NoRequeueAfter time.Duration ) -// DefaultRequeueAfterSeconds is used when GetRequeueAfter is not specified, it is the default time to wait before the next reconcile loop const ( DefaultRequeueAfterSeconds = 3 * time.Minute ) + +func getDefaultRequeueAfter() time.Duration { + // Default is 3 minutes, min is 1 second, max is 1 year + return env.ParseDurationFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER", DefaultRequeueAfterSeconds, 1*time.Second, 8760*time.Hour) +} diff --git a/applicationset/generators/interface_test.go b/applicationset/generators/interface_test.go new file mode 100644 index 00000000000000..d27111bc1453c6 --- /dev/null +++ b/applicationset/generators/interface_test.go @@ -0,0 +1,29 @@ +package generators + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func Test_getDefaultRequeueAfter(t *testing.T) { + tests := []struct { + name string + requeueAfterEnv string + want time.Duration + }{ + {name: "Default", requeueAfterEnv: "", want: DefaultRequeueAfterSeconds}, + {name: "Min", requeueAfterEnv: "1s", want: 1 * time.Second}, + {name: "Max", requeueAfterEnv: "8760h", want: 8760 * time.Hour}, + {name: "Override", requeueAfterEnv: "10m", want: 10 * time.Minute}, + {name: "LessThanMin", requeueAfterEnv: "1ms", want: DefaultRequeueAfterSeconds}, + {name: "MoreThanMax", requeueAfterEnv: "8761h", want: DefaultRequeueAfterSeconds}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Setenv("ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER", tt.requeueAfterEnv) + assert.Equalf(t, tt.want, getDefaultRequeueAfter(), "getDefaultRequeueAfter()") + }) + } +} diff --git a/applicationset/generators/pull_request.go b/applicationset/generators/pull_request.go index 209e09950e5813..3392480bf419bd 100644 --- a/applicationset/generators/pull_request.go +++ b/applicationset/generators/pull_request.go @@ -168,7 +168,7 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera if err != nil { return nil, fmt.Errorf("error fetching Secret Bearer token: %w", err) } - return pullrequest.NewBitbucketServiceBearerToken(ctx, providerConfig.API, appToken, providerConfig.Project, providerConfig.Repo, g.scmRootCAPath, providerConfig.Insecure, caCerts) + return pullrequest.NewBitbucketServiceBearerToken(ctx, appToken, providerConfig.API, providerConfig.Project, providerConfig.Repo, g.scmRootCAPath, providerConfig.Insecure, caCerts) } else if providerConfig.BasicAuth != nil { password, err := utils.GetSecretRef(ctx, g.client, providerConfig.BasicAuth.PasswordRef, applicationSetInfo.Namespace) if err != nil { diff --git a/assets/swagger.json b/assets/swagger.json index 1e8a981c51c669..37e53c2ed2083e 100644 --- a/assets/swagger.json +++ b/assets/swagger.json @@ -4719,6 +4719,9 @@ "impersonationEnabled": { "type": "boolean" }, + "installationID": { + "type": "string" + }, "kustomizeOptions": { "$ref": "#/definitions/v1alpha1KustomizeOptions" }, @@ -6084,7 +6087,7 @@ "properties": { "defaultServiceAccount": { "type": "string", - "title": "ServiceAccountName to be used for impersonation during the sync operation" + "title": "DefaultServiceAccount to be used for impersonation during the sync operation" }, "namespace": { "description": "Namespace specifies the target namespace for the application's resources.", @@ -6614,6 +6617,10 @@ "type": "boolean", "title": "SkipCrds skips custom resource definition installation step (Helm's --skip-crds)" }, + "skipTests": { + "description": "SkipTests skips test manifest installation step (Helm's --skip-tests).", + "type": "boolean" + }, "valueFiles": { "type": "array", "title": "ValuesFiles is a list of Helm value files to use when generating a template", @@ -7156,6 +7163,10 @@ "description": "ClusterGenerator defines a generator to match against clusters registered with ArgoCD.", "type": "object", "properties": { + "flatList": { + "type": "boolean", + "title": "returns the clusters a single 'clusters' value in the template" + }, "selector": { "$ref": "#/definitions/v1LabelSelector" }, diff --git a/cmd/argocd-applicationset-controller/commands/applicationset_controller.go b/cmd/argocd-applicationset-controller/commands/applicationset_controller.go index d2f4ce36d98cf2..e1adc4bf71834d 100644 --- a/cmd/argocd-applicationset-controller/commands/applicationset_controller.go +++ b/cmd/argocd-applicationset-controller/commands/applicationset_controller.go @@ -38,7 +38,6 @@ import ( appsetmetrics "github.com/argoproj/argo-cd/v2/applicationset/metrics" "github.com/argoproj/argo-cd/v2/applicationset/services" appv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" - appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned" "github.com/argoproj/argo-cd/v2/util/cli" "github.com/argoproj/argo-cd/v2/util/db" "github.com/argoproj/argo-cd/v2/util/errors" @@ -162,7 +161,6 @@ func NewCommand() *cobra.Command { errors.CheckError(err) argoSettingsMgr := argosettings.NewSettingsManager(ctx, k8sClient, namespace) - appSetConfig := appclientset.NewForConfigOrDie(mgr.GetConfig()) argoCDDB := db.NewDB(namespace, argoSettingsMgr, k8sClient) scmConfig := generators.NewSCMConfig(scmRootCAPath, allowedScmProviders, enableScmProviders, github_app.NewAuthCredentials(argoCDDB.(db.RepoCredsDB))) @@ -211,7 +209,6 @@ func NewCommand() *cobra.Command { Renderer: &utils.Render{}, Policy: policyObj, EnablePolicyOverride: enablePolicyOverride, - ArgoAppClientset: appSetConfig, KubeClientset: k8sClient, ArgoDB: argoCDDB, ArgoCDNamespace: namespace, diff --git a/cmd/argocd/commands/admin/cluster.go b/cmd/argocd/commands/admin/cluster.go index 48ee0254fd1b70..7841e5bab8c7b6 100644 --- a/cmd/argocd/commands/admin/cluster.go +++ b/cmd/argocd/commands/admin/cluster.go @@ -565,7 +565,9 @@ argocd admin cluster kubeconfig https://cluster-api-url:6443 /path/to/output/kub cluster, err := db.NewDB(namespace, settings.NewSettingsManager(ctx, kubeclientset, namespace), kubeclientset).GetCluster(ctx, serverUrl) errors.CheckError(err) - err = kube.WriteKubeConfig(cluster.RawRestConfig(), namespace, output) + rawConfig, err := cluster.RawRestConfig() + errors.CheckError(err) + err = kube.WriteKubeConfig(rawConfig, namespace, output) errors.CheckError(err) }, } diff --git a/cmd/argocd/commands/admin/redis_initial_password.go b/cmd/argocd/commands/admin/redis_initial_password.go index 3f89b540106592..f54741773fa213 100644 --- a/cmd/argocd/commands/admin/redis_initial_password.go +++ b/cmd/argocd/commands/admin/redis_initial_password.go @@ -45,9 +45,14 @@ func NewRedisInitialPasswordCommand() *cobra.Command { namespace, _, err := clientConfig.Namespace() errors.CheckError(err) - redisInitialPasswordSecretName := common.DefaultRedisInitialPasswordSecretName - redisInitialPasswordKey := common.DefaultRedisInitialPasswordKey - fmt.Printf("Checking for initial Redis password in secret %s/%s at key %s. \n", namespace, redisInitialPasswordSecretName, redisInitialPasswordKey) + // redisInitialCredentials is the kubernetes secret containing + // the redis password + redisInitialCredentials := common.RedisInitialCredentials + + // redisInitialCredentialsKey is the key in the redisInitialCredentials + // secret which maps to the redis password + redisInitialCredentialsKey := common.RedisInitialCredentialsKey + fmt.Printf("Checking for initial Redis password in secret %s/%s at key %s. \n", namespace, redisInitialCredentials, redisInitialCredentialsKey) config, err := clientConfig.ClientConfig() errors.CheckError(err) @@ -59,11 +64,11 @@ func NewRedisInitialPasswordCommand() *cobra.Command { errors.CheckError(err) data := map[string][]byte{ - redisInitialPasswordKey: []byte(randomPassword), + redisInitialCredentialsKey: []byte(randomPassword), } secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: redisInitialPasswordSecretName, + Name: redisInitialCredentials, Namespace: namespace, }, Data: data, @@ -74,14 +79,14 @@ func NewRedisInitialPasswordCommand() *cobra.Command { errors.CheckError(err) } - fmt.Println("Argo CD Redis secret state confirmed: secret name argocd-redis.") - secret, err = kubeClientset.CoreV1().Secrets(namespace).Get(context.Background(), redisInitialPasswordSecretName, v1.GetOptions{}) + fmt.Printf("Argo CD Redis secret state confirmed: secret name %s.\n", redisInitialCredentials) + secret, err = kubeClientset.CoreV1().Secrets(namespace).Get(context.Background(), redisInitialCredentials, v1.GetOptions{}) errors.CheckError(err) - if _, ok := secret.Data[redisInitialPasswordKey]; ok { + if _, ok := secret.Data[redisInitialCredentialsKey]; ok { fmt.Println("Password secret is configured properly.") } else { - err := fmt.Errorf("key %s doesn't exist in secret %s. \n", redisInitialPasswordKey, redisInitialPasswordSecretName) + err := fmt.Errorf("key %s doesn't exist in secret %s. \n", redisInitialCredentialsKey, redisInitialCredentials) errors.CheckError(err) } }, diff --git a/cmd/argocd/commands/admin/settings_test.go b/cmd/argocd/commands/admin/settings_test.go index 4db8ae7ba5eebc..ac19104a5960f5 100644 --- a/cmd/argocd/commands/admin/settings_test.go +++ b/cmd/argocd/commands/admin/settings_test.go @@ -200,8 +200,7 @@ admissionregistration.k8s.io/MutatingWebhookConfiguration: require.NoError(t, err) assert.Contains(t, summary, tc.containsSummary) } else if tc.containsError != "" { - require.Error(t, err) - assert.Contains(t, err.Error(), tc.containsError) + assert.ErrorContains(t, err, tc.containsError) } }) } diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index 500c0ada88260e..8c32ce34399e43 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -1140,6 +1140,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co refresh bool hardRefresh bool exitCode bool + diffExitCode int local string revision string localRepoRoot string @@ -1242,13 +1243,14 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co proj := getProject(c, clientOpts, ctx, app.Spec.Project) foundDiffs := findandPrintDiff(ctx, app, proj.Project, resources, argoSettings, diffOption, ignoreNormalizerOpts) if foundDiffs && exitCode { - os.Exit(1) + os.Exit(diffExitCode) } }, } command.Flags().BoolVar(&refresh, "refresh", false, "Refresh application data when retrieving") command.Flags().BoolVar(&hardRefresh, "hard-refresh", false, "Refresh application data as well as target manifests cache") - command.Flags().BoolVar(&exitCode, "exit-code", true, "Return non-zero exit code when there is a diff") + command.Flags().BoolVar(&exitCode, "exit-code", true, "Return non-zero exit code when there is a diff. May also return non-zero exit code if there is an error.") + command.Flags().IntVar(&diffExitCode, "diff-exit-code", 1, "Return specified exit code when there is a diff. Typical error code is 20.") command.Flags().StringVar(&local, "local", "", "Compare live app to a local manifests") command.Flags().StringVar(&revision, "revision", "", "Compare live app to a particular revision") command.Flags().StringVar(&localRepoRoot, "local-repo-root", "/", "Path to the repository root. Used together with --local allows setting the repository root") @@ -1375,7 +1377,7 @@ func groupObjsForDiff(resources *application.ManagedResourcesResponse, objs map[ } if local, ok := objs[key]; ok || live != nil { if local != nil && !kube.IsCRD(local) { - err = resourceTracking.SetAppInstance(local, argoSettings.AppLabelKey, appName, namespace, argoappv1.TrackingMethod(argoSettings.GetTrackingMethod())) + err = resourceTracking.SetAppInstance(local, argoSettings.AppLabelKey, appName, namespace, argoappv1.TrackingMethod(argoSettings.GetTrackingMethod()), argoSettings.GetInstallationID()) errors.CheckError(err) } diff --git a/cmd/util/app.go b/cmd/util/app.go index 56b48fee82131f..8a1a74537117e1 100644 --- a/cmd/util/app.go +++ b/cmd/util/app.go @@ -48,6 +48,7 @@ type AppOptions struct { helmVersion string helmPassCredentials bool helmSkipCrds bool + helmSkipTests bool helmNamespace string helmKubeVersion string helmApiVersions []string @@ -109,6 +110,7 @@ func AddAppFlags(command *cobra.Command, opts *AppOptions) { command.Flags().StringArrayVar(&opts.helmSetStrings, "helm-set-string", []string{}, "Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2)") command.Flags().StringArrayVar(&opts.helmSetFiles, "helm-set-file", []string{}, "Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2)") command.Flags().BoolVar(&opts.helmSkipCrds, "helm-skip-crds", false, "Skip helm crd installation step") + command.Flags().BoolVar(&opts.helmSkipTests, "helm-skip-tests", false, "Skip helm test manifests installation step") command.Flags().StringVar(&opts.helmNamespace, "helm-namespace", "", "Helm namespace to use when running helm template. If not set, use app.spec.destination.namespace") command.Flags().StringVar(&opts.helmKubeVersion, "helm-kube-version", "", "Helm kube-version to use when running helm template. If not set, use the kube version from the destination cluster") command.Flags().StringArrayVar(&opts.helmApiVersions, "helm-api-versions", []string{}, "Helm api-versions (in format [group/]version/kind) to use when running helm template (Can be repeated to set several values: --helm-api-versions traefik.io/v1alpha1/TLSOption --helm-api-versions v1/Service). If not set, use the api-versions from the destination cluster") @@ -358,6 +360,7 @@ type helmOpts struct { helmSetFiles []string passCredentials bool skipCrds bool + skipTests bool namespace string kubeVersion string apiVersions []string @@ -391,6 +394,9 @@ func setHelmOpt(src *argoappv1.ApplicationSource, opts helmOpts) { if opts.skipCrds { src.Helm.SkipCrds = opts.skipCrds } + if opts.skipTests { + src.Helm.SkipTests = opts.skipTests + } if opts.namespace != "" { src.Helm.Namespace = opts.namespace } @@ -658,6 +664,8 @@ func ConstructSource(source *argoappv1.ApplicationSource, appOpts AppOptions, fl setHelmOpt(source, helmOpts{helmSetFiles: appOpts.helmSetFiles}) case "helm-skip-crds": setHelmOpt(source, helmOpts{skipCrds: appOpts.helmSkipCrds}) + case "helm-skip-tests": + setHelmOpt(source, helmOpts{skipTests: appOpts.helmSkipTests}) case "helm-namespace": setHelmOpt(source, helmOpts{namespace: appOpts.helmNamespace}) case "helm-kube-version": diff --git a/cmd/util/app_test.go b/cmd/util/app_test.go index 595b9be46563e9..c7860cddc03229 100644 --- a/cmd/util/app_test.go +++ b/cmd/util/app_test.go @@ -65,6 +65,11 @@ func Test_setHelmOpt(t *testing.T) { setHelmOpt(&src, helmOpts{skipCrds: true}) assert.True(t, src.Helm.SkipCrds) }) + t.Run("HelmSkipTests", func(t *testing.T) { + src := v1alpha1.ApplicationSource{} + setHelmOpt(&src, helmOpts{skipTests: true}) + assert.True(t, src.Helm.SkipTests) + }) t.Run("HelmNamespace", func(t *testing.T) { src := v1alpha1.ApplicationSource{} setHelmOpt(&src, helmOpts{namespace: "custom-namespace"}) diff --git a/cmd/util/project.go b/cmd/util/project.go index b0a82883dc0bbc..63dff2018c9754 100644 --- a/cmd/util/project.go +++ b/cmd/util/project.go @@ -48,6 +48,8 @@ func AddProjFlags(command *cobra.Command, opts *ProjectOpts) { command.Flags().StringArrayVar(&opts.allowedNamespacedResources, "allow-namespaced-resource", []string{}, "List of allowed namespaced resources") command.Flags().StringArrayVar(&opts.deniedNamespacedResources, "deny-namespaced-resource", []string{}, "List of denied namespaced resources") command.Flags().StringSliceVar(&opts.SourceNamespaces, "source-namespaces", []string{}, "List of source namespaces for applications") + command.Flags().StringArrayVar(&opts.destinationServiceAccounts, "dest-service-accounts", []string{}, + "Destination server, namespace and target service account (e.g. https://192.168.99.100:8443,default,default-sa)") } func getGroupKindList(values []string) []v1.GroupKind { @@ -98,8 +100,8 @@ func (opts *ProjectOpts) GetDestinationServiceAccounts() []v1alpha1.ApplicationD destinationServiceAccounts := make([]v1alpha1.ApplicationDestinationServiceAccount, 0) for _, destStr := range opts.destinationServiceAccounts { parts := strings.Split(destStr, ",") - if len(parts) != 2 { - log.Fatalf("Expected destination of the form: server,namespace. Received: %s", destStr) + if len(parts) != 3 { + log.Fatalf("Expected destination service account of the form: server,namespace, defaultServiceAccount. Received: %s", destStr) } else { destinationServiceAccounts = append(destinationServiceAccounts, v1alpha1.ApplicationDestinationServiceAccount{ Server: parts[0], diff --git a/cmd/util/project_test.go b/cmd/util/project_test.go index bde59d0ab5e886..8c61ee714f2c02 100644 --- a/cmd/util/project_test.go +++ b/cmd/util/project_test.go @@ -5,6 +5,8 @@ import ( "github.com/stretchr/testify/assert" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" ) func TestProjectOpts_ResourceLists(t *testing.T) { @@ -22,3 +24,27 @@ func TestProjectOpts_ResourceLists(t *testing.T) { []v1.GroupKind{{Group: "rbac.authorization.k8s.io", Kind: "ClusterRole"}}, opts.GetDeniedClusterResources(), ) } + +func TestProjectOpts_GetDestinationServiceAccounts(t *testing.T) { + opts := ProjectOpts{ + destinationServiceAccounts: []string{ + "https://192.168.99.100:8443,test-ns,test-sa", + "https://kubernetes.default.svc.local:6443,guestbook,guestbook-sa", + }, + } + + assert.ElementsMatch(t, + []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://192.168.99.100:8443", + Namespace: "test-ns", + DefaultServiceAccount: "test-sa", + }, + { + Server: "https://kubernetes.default.svc.local:6443", + Namespace: "guestbook", + DefaultServiceAccount: "guestbook-sa", + }, + }, opts.GetDestinationServiceAccounts(), + ) +} diff --git a/cmpserver/plugin/plugin_test.go b/cmpserver/plugin/plugin_test.go index 05001c31b3837b..30bd0a97bedc5e 100644 --- a/cmpserver/plugin/plugin_test.go +++ b/cmpserver/plugin/plugin_test.go @@ -451,8 +451,7 @@ func Test_getParametersAnnouncement_invalid_json(t *testing.T) { Args: []string{`[`}, } _, err := getParametersAnnouncement(context.Background(), "", []*repoclient.ParameterAnnouncement{}, command, []*apiclient.EnvEntry{}) - require.Error(t, err) - assert.Contains(t, err.Error(), "unexpected end of JSON input") + assert.ErrorContains(t, err, "unexpected end of JSON input") } func Test_getParametersAnnouncement_bad_command(t *testing.T) { @@ -461,8 +460,7 @@ func Test_getParametersAnnouncement_bad_command(t *testing.T) { Args: []string{"1"}, } _, err := getParametersAnnouncement(context.Background(), "", []*repoclient.ParameterAnnouncement{}, command, []*apiclient.EnvEntry{}) - require.Error(t, err) - assert.Contains(t, err.Error(), "error executing dynamic parameter output command") + assert.ErrorContains(t, err, "error executing dynamic parameter output command") } func Test_getTempDirMustCleanup(t *testing.T) { diff --git a/common/common.go b/common/common.go index 79fcdba195eb6f..82776c8c939966 100644 --- a/common/common.go +++ b/common/common.go @@ -178,6 +178,7 @@ const ( // AnnotationKeyAppInstance is the Argo CD application name is used as the instance name AnnotationKeyAppInstance = "argocd.argoproj.io/tracking-id" + AnnotationInstallationID = "argocd.argoproj.io/installation-id" // AnnotationCompareOptions is a comma-separated list of options for comparison AnnotationCompareOptions = "argocd.argoproj.io/compare-options" @@ -315,7 +316,10 @@ const ( // Constants used by util/clusterauth package const ( ClusterAuthRequestTimeout = 10 * time.Second - BearerTokenTimeout = 30 * time.Second +) + +const ( + BearerTokenTimeout = 30 * time.Second ) const ( @@ -425,8 +429,10 @@ var PermissionDeniedAPIError = status.Error(codes.PermissionDenied, "permission // Redis password consts const ( - DefaultRedisInitialPasswordSecretName = "argocd-redis" - DefaultRedisInitialPasswordKey = "auth" + // RedisInitialCredentials is the name for the argocd kubernetes secret which will have the redis password + RedisInitialCredentials = "argocd-redis" + // RedisInitialCredentialsKey is the key for the argocd kubernetes secret that maps to the redis password + RedisInitialCredentialsKey = "auth" ) /* @@ -435,17 +441,17 @@ SetOptionalRedisPasswordFromKubeConfig sets the optional Redis password if it ex We specify kubeClient as kubernetes.Interface to allow for mocking in tests, but this should be treated as a kubernetes.Clientset param. */ func SetOptionalRedisPasswordFromKubeConfig(ctx context.Context, kubeClient kubernetes.Interface, namespace string, redisOptions *redis.Options) error { - secret, err := kubeClient.CoreV1().Secrets(namespace).Get(ctx, DefaultRedisInitialPasswordSecretName, v1.GetOptions{}) + secret, err := kubeClient.CoreV1().Secrets(namespace).Get(ctx, RedisInitialCredentials, v1.GetOptions{}) if err != nil { - return fmt.Errorf("failed to get secret %s/%s: %w", namespace, DefaultRedisInitialPasswordSecretName, err) + return fmt.Errorf("failed to get secret %s/%s: %w", namespace, RedisInitialCredentials, err) } if secret == nil { - return fmt.Errorf("failed to get secret %s/%s: secret is nil", namespace, DefaultRedisInitialPasswordSecretName) + return fmt.Errorf("failed to get secret %s/%s: secret is nil", namespace, RedisInitialCredentials) } - _, ok := secret.Data[DefaultRedisInitialPasswordKey] + _, ok := secret.Data[RedisInitialCredentialsKey] if !ok { - return fmt.Errorf("secret %s/%s does not contain key %s", namespace, DefaultRedisInitialPasswordSecretName, DefaultRedisInitialPasswordKey) + return fmt.Errorf("secret %s/%s does not contain key %s", namespace, RedisInitialCredentials, RedisInitialCredentialsKey) } - redisOptions.Password = string(secret.Data[DefaultRedisInitialPasswordKey]) + redisOptions.Password = string(secret.Data[RedisInitialCredentialsKey]) return nil } diff --git a/common/common_test.go b/common/common_test.go index 1021a30a14f600..4db2ad76ce0370 100644 --- a/common/common_test.go +++ b/common/common_test.go @@ -63,24 +63,24 @@ func TestSetOptionalRedisPasswordFromKubeConfig(t *testing.T) { expectedPassword: "password123", expectedErr: "", secret: &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{Name: DefaultRedisInitialPasswordSecretName}, - Data: map[string][]byte{DefaultRedisInitialPasswordKey: []byte("password123")}, + ObjectMeta: metav1.ObjectMeta{Name: RedisInitialCredentials}, + Data: map[string][]byte{RedisInitialCredentialsKey: []byte("password123")}, }, }, { name: "Secret does not exist", namespace: "default", expectedPassword: "", - expectedErr: fmt.Sprintf("failed to get secret default/%s", DefaultRedisInitialPasswordSecretName), + expectedErr: fmt.Sprintf("failed to get secret default/%s", RedisInitialCredentials), secret: nil, }, { name: "Secret exists without correct key", namespace: "default", expectedPassword: "", - expectedErr: fmt.Sprintf("secret default/%s does not contain key %s", DefaultRedisInitialPasswordSecretName, DefaultRedisInitialPasswordKey), + expectedErr: fmt.Sprintf("secret default/%s does not contain key %s", RedisInitialCredentials, RedisInitialCredentialsKey), secret: &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{Name: DefaultRedisInitialPasswordSecretName}, + ObjectMeta: metav1.ObjectMeta{Name: RedisInitialCredentials}, Data: map[string][]byte{}, }, }, @@ -101,8 +101,7 @@ func TestSetOptionalRedisPasswordFromKubeConfig(t *testing.T) { } err := SetOptionalRedisPasswordFromKubeConfig(ctx, kubeClient, tc.namespace, redisOptions) if tc.expectedErr != "" { - require.Error(t, err) - require.Contains(t, err.Error(), tc.expectedErr) + require.ErrorContains(t, err, tc.expectedErr) } else { require.NoError(t, err) } diff --git a/controller/appcontroller.go b/controller/appcontroller.go index e607771de586dd..5add405ba31d98 100644 --- a/controller/appcontroller.go +++ b/controller/appcontroller.go @@ -1163,7 +1163,11 @@ func (ctrl *ApplicationController) finalizeApplicationDeletion(app *appv1.Applic logCtx.Infof("Resource entries removed from undefined cluster") return nil } - config := metrics.AddMetricsTransportWrapper(ctrl.metricsServer, app, cluster.RESTConfig()) + clusterRESTConfig, err := cluster.RESTConfig() + if err != nil { + return err + } + config := metrics.AddMetricsTransportWrapper(ctrl.metricsServer, app, clusterRESTConfig) if app.CascadedDeletion() { logCtx.Infof("Deleting resources") diff --git a/controller/appcontroller_test.go b/controller/appcontroller_test.go index 50fb08042719d6..3556e7056c239c 100644 --- a/controller/appcontroller_test.go +++ b/controller/appcontroller_test.go @@ -67,6 +67,7 @@ type fakeData struct { metricsCacheExpiration time.Duration applicationNamespaces []string updateRevisionForPathsResponse *apiclient.UpdateRevisionForPathsResponse + additionalObjs []runtime.Object } type MockKubectl struct { @@ -136,7 +137,9 @@ func newFakeController(data *fakeData, repoErr error) *ApplicationController { }, Data: data.configMapData, } - kubeClient := fake.NewSimpleClientset(&clust, &cm, &secret) + runtimeObjs := []runtime.Object{&clust, &secret, &cm} + runtimeObjs = append(runtimeObjs, data.additionalObjs...) + kubeClient := fake.NewSimpleClientset(runtimeObjs...) settingsMgr := settings.NewSettingsManager(context.Background(), kubeClient, test.FakeArgoCDNamespace) kubectl := &MockKubectl{Kubectl: &kubetest.MockKubectlCmd{}} ctrl, err := NewApplicationController( diff --git a/controller/cache/cache.go b/controller/cache/cache.go index 170f5118b521ab..b17afbca5234b8 100644 --- a/controller/cache/cache.go +++ b/controller/cache/cache.go @@ -197,6 +197,7 @@ type cacheSettings struct { clusterSettings clustercache.Settings appInstanceLabelKey string trackingMethod appv1.TrackingMethod + installationID string // resourceOverrides provides a list of ignored differences to ignore watched resource updates resourceOverrides map[string]appv1.ResourceOverride @@ -225,6 +226,10 @@ func (c *liveStateCache) loadCacheSettings() (*cacheSettings, error) { if err != nil { return nil, err } + installationID, err := c.settingsMgr.GetInstallationID() + if err != nil { + return nil, err + } resourceUpdatesOverrides, err := c.settingsMgr.GetIgnoreResourceUpdatesOverrides() if err != nil { return nil, err @@ -246,7 +251,7 @@ func (c *liveStateCache) loadCacheSettings() (*cacheSettings, error) { ResourcesFilter: resourcesFilter, } - return &cacheSettings{clusterSettings, appInstanceLabelKey, argo.GetTrackingMethod(c.settingsMgr), resourceUpdatesOverrides, ignoreResourceUpdatesEnabled}, nil + return &cacheSettings{clusterSettings, appInstanceLabelKey, argo.GetTrackingMethod(c.settingsMgr), installationID, resourceUpdatesOverrides, ignoreResourceUpdatesEnabled}, nil } func asResourceNode(r *clustercache.Resource) appv1.ResourceNode { @@ -490,7 +495,10 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e return nil, fmt.Errorf("error getting value for %v: %w", settings.RespectRBAC, err) } - clusterCacheConfig := cluster.RESTConfig() + clusterCacheConfig, err := cluster.RESTConfig() + if err != nil { + return nil, fmt.Errorf("error getting cluster RESTConfig: %w", err) + } // Controller dynamically fetches all resource types available on the cluster // using a discovery API that may contain deprecated APIs. // This causes log flooding when managing a large number of clusters. @@ -523,7 +531,7 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e res.Health, _ = health.GetResourceHealth(un, cacheSettings.clusterSettings.ResourceHealthOverride) - appName := c.resourceTracking.GetAppName(un, cacheSettings.appInstanceLabelKey, cacheSettings.trackingMethod) + appName := c.resourceTracking.GetAppName(un, cacheSettings.appInstanceLabelKey, cacheSettings.trackingMethod, cacheSettings.installationID) if isRoot && appName != "" { res.AppName = appName } @@ -821,7 +829,12 @@ func (c *liveStateCache) handleModEvent(oldCluster *appv1.Cluster, newCluster *a var updateSettings []clustercache.UpdateSettingsFunc if !reflect.DeepEqual(oldCluster.Config, newCluster.Config) { - updateSettings = append(updateSettings, clustercache.SetConfig(newCluster.RESTConfig())) + newClusterRESTConfig, err := newCluster.RESTConfig() + if err == nil { + updateSettings = append(updateSettings, clustercache.SetConfig(newClusterRESTConfig)) + } else { + log.Errorf("error getting cluster REST config: %v", err) + } } if !reflect.DeepEqual(oldCluster.Namespaces, newCluster.Namespaces) { updateSettings = append(updateSettings, clustercache.SetNamespaces(newCluster.Namespaces)) diff --git a/controller/state.go b/controller/state.go index 5b59f411dafb13..3dbe157e883798 100644 --- a/controller/state.go +++ b/controller/state.go @@ -161,6 +161,11 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp return nil, nil, false, fmt.Errorf("failed to get Helm settings: %w", err) } + installationID, err := m.settingsMgr.GetInstallationID() + if err != nil { + return nil, nil, false, fmt.Errorf("failed to get installation ID: %w", err) + } + ts.AddCheckpoint("build_options_ms") serverVersion, apiResources, err := m.liveStateCache.GetVersionsInfo(app.Spec.Destination.Server) if err != nil { @@ -230,6 +235,7 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp TrackingMethod: string(argo.GetTrackingMethod(m.settingsMgr)), RefSources: refSources, HasMultipleSources: app.Spec.HasMultipleSources(), + InstallationID: installationID, }) if err != nil { return nil, nil, false, fmt.Errorf("failed to compare revisions for source %d of %d: %w", i+1, len(sources), err) @@ -271,6 +277,7 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp ProjectName: proj.Name, ProjectSourceRepos: proj.Spec.SourceRepos, AnnotationManifestGeneratePaths: app.GetAnnotation(v1alpha1.AnnotationKeyManifestGeneratePaths), + InstallationID: installationID, }) if err != nil { return nil, nil, false, fmt.Errorf("failed to generate manifest for source %d of %d: %w", i+1, len(sources), err) @@ -354,20 +361,24 @@ func DeduplicateTargetObjects( // getComparisonSettings will return the system level settings related to the // diff/normalization process. -func (m *appStateManager) getComparisonSettings() (string, map[string]v1alpha1.ResourceOverride, *settings.ResourcesFilter, error) { +func (m *appStateManager) getComparisonSettings() (string, map[string]v1alpha1.ResourceOverride, *settings.ResourcesFilter, string, error) { resourceOverrides, err := m.settingsMgr.GetResourceOverrides() if err != nil { - return "", nil, nil, err + return "", nil, nil, "", err } appLabelKey, err := m.settingsMgr.GetAppInstanceLabelKey() if err != nil { - return "", nil, nil, err + return "", nil, nil, "", err } resFilter, err := m.settingsMgr.GetResourcesFilter() if err != nil { - return "", nil, nil, err + return "", nil, nil, "", err + } + installationID, err := m.settingsMgr.GetInstallationID() + if err != nil { + return "", nil, nil, "", err } - return appLabelKey, resourceOverrides, resFilter, nil + return appLabelKey, resourceOverrides, resFilter, installationID, nil } // verifyGnuPGSignature verifies the result of a GnuPG operation for a given git @@ -418,7 +429,7 @@ func isManagedNamespace(ns *unstructured.Unstructured, app *v1alpha1.Application // revision and overrides in the app spec. func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1alpha1.AppProject, revisions []string, sources []v1alpha1.ApplicationSource, noCache bool, noRevisionCache bool, localManifests []string, hasMultipleSources bool, rollback bool) (*comparisonResult, error) { ts := stats.NewTimingStats() - appLabelKey, resourceOverrides, resFilter, err := m.getComparisonSettings() + appLabelKey, resourceOverrides, resFilter, installationID, err := m.getComparisonSettings() ts.AddCheckpoint("settings_ms") @@ -586,7 +597,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1 for _, liveObj := range liveObjByKey { if liveObj != nil { - appInstanceName := m.resourceTracking.GetAppName(liveObj, appLabelKey, trackingMethod) + appInstanceName := m.resourceTracking.GetAppName(liveObj, appLabelKey, trackingMethod, installationID) if appInstanceName != "" && appInstanceName != app.InstanceName(m.namespace) { fqInstanceName := strings.ReplaceAll(appInstanceName, "_", "/") conditions = append(conditions, v1alpha1.ApplicationCondition{ @@ -725,7 +736,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1 } gvk := obj.GroupVersionKind() - isSelfReferencedObj := m.isSelfReferencedObj(liveObj, targetObj, app.GetName(), appLabelKey, trackingMethod) + isSelfReferencedObj := m.isSelfReferencedObj(liveObj, targetObj, app.GetName(), appLabelKey, trackingMethod, installationID) resState := v1alpha1.ResourceStatus{ Namespace: obj.GetNamespace(), @@ -1030,7 +1041,7 @@ func NewAppStateManager( // group and kind) match the properties of the live object, or if the tracking method // used does not provide the required properties for matching. // Reference: https://github.com/argoproj/argo-cd/issues/8683 -func (m *appStateManager) isSelfReferencedObj(live, config *unstructured.Unstructured, appName, appLabelKey string, trackingMethod v1alpha1.TrackingMethod) bool { +func (m *appStateManager) isSelfReferencedObj(live, config *unstructured.Unstructured, appName, appLabelKey string, trackingMethod v1alpha1.TrackingMethod, installationID string) bool { if live == nil { return true } @@ -1063,7 +1074,7 @@ func (m *appStateManager) isSelfReferencedObj(live, config *unstructured.Unstruc // to match the properties from the live object. Cluster scoped objects // carry the app's destination namespace in the tracking annotation, // but are unique in GVK + name combination. - appInstance := m.resourceTracking.GetAppInstance(live, appLabelKey, trackingMethod) + appInstance := m.resourceTracking.GetAppInstance(live, appLabelKey, trackingMethod, installationID) if appInstance != nil { return isSelfReferencedObj(live, *appInstance) } diff --git a/controller/state_test.go b/controller/state_test.go index a3b7cb195a94e6..9800c0e9e65926 100644 --- a/controller/state_test.go +++ b/controller/state_test.go @@ -1372,8 +1372,8 @@ func TestIsLiveResourceManaged(t *testing.T) { configObj := managedObj.DeepCopy() // then - assert.True(t, manager.isSelfReferencedObj(managedObj, configObj, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel)) - assert.True(t, manager.isSelfReferencedObj(managedObj, configObj, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation)) + assert.True(t, manager.isSelfReferencedObj(managedObj, configObj, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel, "")) + assert.True(t, manager.isSelfReferencedObj(managedObj, configObj, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation, "")) }) t.Run("will return true if tracked with label", func(t *testing.T) { // given @@ -1381,43 +1381,43 @@ func TestIsLiveResourceManaged(t *testing.T) { configObj := managedObjWithLabel.DeepCopy() // then - assert.True(t, manager.isSelfReferencedObj(managedObjWithLabel, configObj, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel)) + assert.True(t, manager.isSelfReferencedObj(managedObjWithLabel, configObj, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel, "")) }) t.Run("will handle if trackingId has wrong resource name and config is nil", func(t *testing.T) { // given t.Parallel() // then - assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongName, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel)) - assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongName, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation)) + assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongName, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel, "")) + assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongName, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation, "")) }) t.Run("will handle if trackingId has wrong resource group and config is nil", func(t *testing.T) { // given t.Parallel() // then - assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongGroup, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel)) - assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongGroup, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation)) + assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongGroup, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel, "")) + assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongGroup, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation, "")) }) t.Run("will handle if trackingId has wrong kind and config is nil", func(t *testing.T) { // given t.Parallel() // then - assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongKind, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel)) - assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongKind, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation)) + assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongKind, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel, "")) + assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongKind, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation, "")) }) t.Run("will handle if trackingId has wrong namespace and config is nil", func(t *testing.T) { // given t.Parallel() // then - assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongNamespace, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel)) - assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongNamespace, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotationAndLabel)) + assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongNamespace, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodLabel, "")) + assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongNamespace, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotationAndLabel, "")) }) t.Run("will return true if live is nil", func(t *testing.T) { t.Parallel() - assert.True(t, manager.isSelfReferencedObj(nil, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation)) + assert.True(t, manager.isSelfReferencedObj(nil, nil, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation, "")) }) t.Run("will handle upgrade in desired state APIGroup", func(t *testing.T) { @@ -1427,7 +1427,7 @@ func TestIsLiveResourceManaged(t *testing.T) { delete(config.GetAnnotations(), common.AnnotationKeyAppInstance) // then - assert.True(t, manager.isSelfReferencedObj(managedWrongAPIGroup, config, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation)) + assert.True(t, manager.isSelfReferencedObj(managedWrongAPIGroup, config, appName, common.AnnotationKeyAppInstance, argo.TrackingMethodAnnotation, "")) }) } diff --git a/controller/sync.go b/controller/sync.go index 5f896a522f9427..522155977093ef 100644 --- a/controller/sync.go +++ b/controller/sync.go @@ -44,6 +44,10 @@ const ( // EnvVarSyncWaveDelay is an environment variable which controls the delay in seconds between // each sync-wave EnvVarSyncWaveDelay = "ARGOCD_SYNC_WAVE_DELAY" + + // serviceAccountDisallowedCharSet contains the characters that are not allowed to be present + // in a DefaultServiceAccount configured for a DestinationServiceAccount + serviceAccountDisallowedCharSet = "!*[]{}\\/" ) func (m *appStateManager) getOpenAPISchema(server string) (openapi.Resources, error) { @@ -76,7 +80,12 @@ func (m *appStateManager) getResourceOperations(server string) (kube.ResourceOpe if err != nil { return nil, nil, fmt.Errorf("error getting cluster: %w", err) } - ops, cleanup, err := m.kubectl.ManageResources(cluster.RawRestConfig(), clusterCache.GetOpenAPISchema()) + + rawConfig, err := cluster.RawRestConfig() + if err != nil { + return nil, nil, fmt.Errorf("error getting cluster REST config: %w", err) + } + ops, cleanup, err := m.kubectl.ManageResources(rawConfig, clusterCache.GetOpenAPISchema()) if err != nil { return nil, nil, fmt.Errorf("error creating kubectl ResourceOperations: %w", err) } @@ -213,8 +222,20 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha return } - rawConfig := clst.RawRestConfig() - restConfig := metrics.AddMetricsTransportWrapper(m.metricsServer, app, clst.RESTConfig()) + rawConfig, err := clst.RawRestConfig() + if err != nil { + state.Phase = common.OperationError + state.Message = err.Error() + return + } + + clusterRESTConfig, err := clst.RESTConfig() + if err != nil { + state.Phase = common.OperationError + state.Message = err.Error() + return + } + restConfig := metrics.AddMetricsTransportWrapper(m.metricsServer, app, clusterRESTConfig) resourceOverrides, err := m.settingsMgr.GetResourceOverrides() if err != nil { @@ -285,10 +306,20 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha log.Errorf("Could not get appInstanceLabelKey: %v", err) return } + installationID, err := m.settingsMgr.GetInstallationID() + if err != nil { + log.Errorf("Could not get installation ID: %v", err) + return + } trackingMethod := argo.GetTrackingMethod(m.settingsMgr) - if m.settingsMgr.IsImpersonationEnabled() { - serviceAccountToImpersonate, err := deriveServiceAccountName(proj, app) + impersonationEnabled, err := m.settingsMgr.IsImpersonationEnabled() + if err != nil { + log.Errorf("could not get impersonation feature flag: %v", err) + return + } + if impersonationEnabled { + serviceAccountToImpersonate, err := deriveServiceAccountToImpersonate(proj, app) if err != nil { state.Phase = common.OperationError state.Message = fmt.Sprintf("failed to find a matching service account to impersonate: %v", err) @@ -331,7 +362,7 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha return (len(syncOp.Resources) == 0 || isPostDeleteHook(target) || argo.ContainsSyncResource(key.Name, key.Namespace, schema.GroupVersionKind{Kind: key.Kind, Group: key.Group}, syncOp.Resources)) && - m.isSelfReferencedObj(live, target, app.GetName(), appLabelKey, trackingMethod) + m.isSelfReferencedObj(live, target, app.GetName(), appLabelKey, trackingMethod, installationID) }), sync.WithManifestValidation(!syncOp.SyncOptions.HasOption(common.SyncOptionsDisableValidation)), sync.WithSyncWaveHook(delayBetweenSyncWaves), @@ -557,9 +588,9 @@ func syncWindowPreventsSync(app *v1alpha1.Application, proj *v1alpha1.AppProject return !window.CanSync(isManual) } -// deriveServiceAccountName determines the service account to be used for impersonation for the sync operation. +// deriveServiceAccountToImpersonate determines the service account to be used for impersonation for the sync operation. // The returned service account will be fully qualified including namespace and the service account name in the format system:serviceaccount:: -func deriveServiceAccountName(project *v1alpha1.AppProject, application *v1alpha1.Application) (string, error) { +func deriveServiceAccountToImpersonate(project *v1alpha1.AppProject, application *v1alpha1.Application) (string, error) { // spec.Destination.Namespace is optional. If not specified, use the Application's // namespace serviceAccountNamespace := application.Spec.Destination.Namespace @@ -569,10 +600,18 @@ func deriveServiceAccountName(project *v1alpha1.AppProject, application *v1alpha // Loop through the destinationServiceAccounts and see if there is any destination that is a candidate. // if so, return the service account specified for that destination. for _, item := range project.Spec.DestinationServiceAccounts { - dstServerMatched := glob.Match(item.Server, application.Spec.Destination.Server) - dstNamespaceMatched := glob.Match(item.Namespace, application.Spec.Destination.Namespace) + dstServerMatched, err := glob.MatchWithError(item.Server, application.Spec.Destination.Server) + if err != nil { + return "", fmt.Errorf("invalid glob pattern for destination server: %w", err) + } + dstNamespaceMatched, err := glob.MatchWithError(item.Namespace, application.Spec.Destination.Namespace) + if err != nil { + return "", fmt.Errorf("invalid glob pattern for destination namespace: %w", err) + } if dstServerMatched && dstNamespaceMatched { - if strings.Contains(item.DefaultServiceAccount, ":") { + if strings.Trim(item.DefaultServiceAccount, " ") == "" || strings.ContainsAny(item.DefaultServiceAccount, serviceAccountDisallowedCharSet) { + return "", fmt.Errorf("default service account contains invalid chars '%s'", item.DefaultServiceAccount) + } else if strings.Contains(item.DefaultServiceAccount, ":") { // service account is specified along with its namespace. return fmt.Sprintf("system:serviceaccount:%s", item.DefaultServiceAccount), nil } else { diff --git a/controller/sync_test.go b/controller/sync_test.go index 1dbfa2ff9e1a54..a553fd3e37cf7d 100644 --- a/controller/sync_test.go +++ b/controller/sync_test.go @@ -2,6 +2,7 @@ package controller import ( "context" + "strconv" "testing" "github.com/argoproj/gitops-engine/pkg/sync" @@ -9,6 +10,7 @@ import ( "github.com/argoproj/gitops-engine/pkg/utils/kube" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -644,6 +646,771 @@ func TestNormalizeTargetResourcesWithList(t *testing.T) { }) } +func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) { + type fixture struct { + project *v1alpha1.AppProject + application *v1alpha1.Application + } + + setup := func(destinationServiceAccounts []v1alpha1.ApplicationDestinationServiceAccount, destinationNamespace, destinationServerURL, applicationNamespace string) *fixture { + project := &v1alpha1.AppProject{ + ObjectMeta: v1.ObjectMeta{ + Namespace: "argocd-ns", + Name: "testProj", + }, + Spec: v1alpha1.AppProjectSpec{ + DestinationServiceAccounts: destinationServiceAccounts, + }, + } + app := &v1alpha1.Application{ + ObjectMeta: v1.ObjectMeta{ + Namespace: applicationNamespace, + Name: "testApp", + }, + Spec: v1alpha1.ApplicationSpec{ + Project: "testProj", + Destination: v1alpha1.ApplicationDestination{ + Server: destinationServerURL, + Namespace: destinationNamespace, + }, + }, + } + return &fixture{ + project: project, + application: app, + } + } + + t.Run("empty destination service accounts", func(t *testing.T) { + // given an application referring a project with no destination service accounts + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{} + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "" + expectedErrMsg := "no matching service account found for destination server https://kubernetes.svc.local and namespace testns" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + assert.Equal(t, expectedSA, sa) + + // then, there should be an error saying no valid match was found + assert.EqualError(t, err, expectedErrMsg) + }) + + t.Run("exact match of destination namespace", func(t *testing.T) { + // given an application referring a project with exactly one destination service account that matches the application destination, + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:testns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should be no error and should use the right service account for impersonation + require.NoError(t, err) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("exact one match with multiple destination service accounts", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts having one exact match for application destination + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "guestbook", + DefaultServiceAccount: "guestbook-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "guestbook-test", + DefaultServiceAccount: "guestbook-test-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "default", + DefaultServiceAccount: "default-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:testns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should be no error and should use the right service account for impersonation + require.NoError(t, err) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("first match to be used when multiple matches are available", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts having multiple match for application destination + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa-2", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa-3", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "guestbook", + DefaultServiceAccount: "guestbook-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:testns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should be no error and it should use the first matching service account for impersonation + require.NoError(t, err) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("first match to be used when glob pattern is used", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts with glob patterns matching the application destination + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "test*", + DefaultServiceAccount: "test-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa-2", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "default", + DefaultServiceAccount: "default-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:testns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should not be any error and should use the first matching glob pattern service account for impersonation + require.NoError(t, err) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("no match among a valid list", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts with no matches for application destination + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "test1", + DefaultServiceAccount: "test-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "test2", + DefaultServiceAccount: "test-sa-2", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "default", + DefaultServiceAccount: "default-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "" + expectedErrMsg := "no matching service account found for destination server https://kubernetes.svc.local and namespace testns" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should be an error saying no match was found + require.EqualError(t, err, expectedErrMsg) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("app destination namespace is empty", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts with empty application destination namespace + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + DefaultServiceAccount: "test-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "*", + DefaultServiceAccount: "test-sa-2", + }, + } + destinationNamespace := "" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:argocd-ns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should not be any error and the service account configured for with empty namespace should be used. + require.NoError(t, err) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("match done via catch all glob pattern", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts having a catch all glob pattern + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "testns1", + DefaultServiceAccount: "test-sa-2", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "default", + DefaultServiceAccount: "default-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "*", + DefaultServiceAccount: "test-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:testns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should not be any error and the catch all service account should be returned + require.NoError(t, err) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("match done via invalid glob pattern", func(t *testing.T) { + // given an application referring a project with a destination service account having an invalid glob pattern for namespace + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "e[[a*", + DefaultServiceAccount: "test-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there must be an error as the glob pattern is invalid. + require.ErrorContains(t, err, "invalid glob pattern for destination namespace") + assert.Equal(t, expectedSA, sa) + }) + + t.Run("sa specified with a namespace", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts having a matching service account specified with its namespace + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "myns:test-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "default", + DefaultServiceAccount: "default-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "*", + DefaultServiceAccount: "test-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:myns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + assert.Equal(t, expectedSA, sa) + + // then, there should not be any error and the service account with its namespace should be returned. + require.NoError(t, err) + }) +} + +func TestDeriveServiceAccountMatchingServers(t *testing.T) { + type fixture struct { + project *v1alpha1.AppProject + application *v1alpha1.Application + } + + setup := func(destinationServiceAccounts []v1alpha1.ApplicationDestinationServiceAccount, destinationNamespace, destinationServerURL, applicationNamespace string) *fixture { + project := &v1alpha1.AppProject{ + ObjectMeta: v1.ObjectMeta{ + Namespace: "argocd-ns", + Name: "testProj", + }, + Spec: v1alpha1.AppProjectSpec{ + DestinationServiceAccounts: destinationServiceAccounts, + }, + } + app := &v1alpha1.Application{ + ObjectMeta: v1.ObjectMeta{ + Namespace: applicationNamespace, + Name: "testApp", + }, + Spec: v1alpha1.ApplicationSpec{ + Project: "testProj", + Destination: v1alpha1.ApplicationDestination{ + Server: destinationServerURL, + Namespace: destinationNamespace, + }, + }, + } + return &fixture{ + project: project, + application: app, + } + } + + t.Run("exact one match with multiple destination service accounts", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts and one exact match for application destination + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "guestbook", + DefaultServiceAccount: "guestbook-sa", + }, + { + Server: "https://abc.svc.local", + Namespace: "guestbook", + DefaultServiceAccount: "guestbook-test-sa", + }, + { + Server: "https://cde.svc.local", + Namespace: "guestbook", + DefaultServiceAccount: "default-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:testns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should not be any error and the right service account must be returned. + require.NoError(t, err) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("first match to be used when multiple matches are available", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts and multiple matches for application destination + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa-2", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "default", + DefaultServiceAccount: "default-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "guestbook", + DefaultServiceAccount: "guestbook-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:testns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should not be any error and first matching service account should be used + require.NoError(t, err) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("first match to be used when glob pattern is used", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts with a matching glob pattern and exact match + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "test*", + DefaultServiceAccount: "test-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa-2", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "default", + DefaultServiceAccount: "default-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:testns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + assert.Equal(t, expectedSA, sa) + + // then, there should not be any error and the service account of the glob pattern, being the first match should be returned. + require.NoError(t, err) + }) + + t.Run("no match among a valid list", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts with no match + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa", + }, + { + Server: "https://abc.svc.local", + Namespace: "testns", + DefaultServiceAccount: "test-sa-2", + }, + { + Server: "https://cde.svc.local", + Namespace: "default", + DefaultServiceAccount: "default-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://xyz.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "" + expectedErr := "no matching service account found for destination server https://xyz.svc.local and namespace testns" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there an error with appropriate message must be returned + require.EqualError(t, err, expectedErr) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("match done via catch all glob pattern", func(t *testing.T) { + // given an application referring a project with multiple destination service accounts with matching catch all glob pattern + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://kubernetes.svc.local", + Namespace: "testns1", + DefaultServiceAccount: "test-sa-2", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "default", + DefaultServiceAccount: "default-sa", + }, + { + Server: "*", + Namespace: "*", + DefaultServiceAccount: "test-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://localhost:6443" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:testns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should not be any error and the service account of the glob pattern match must be returned. + require.NoError(t, err) + assert.Equal(t, expectedSA, sa) + }) + + t.Run("match done via invalid glob pattern", func(t *testing.T) { + // given an application referring a project with a destination service account having an invalid glob pattern for server + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "e[[a*", + Namespace: "test-ns", + DefaultServiceAccount: "test-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://kubernetes.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there must be an error as the glob pattern is invalid. + require.ErrorContains(t, err, "invalid glob pattern for destination server") + assert.Equal(t, expectedSA, sa) + }) + + t.Run("sa specified with a namespace", func(t *testing.T) { + // given app sync impersonation feature is enabled and matching service account is prefixed with a namespace + t.Parallel() + destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{ + { + Server: "https://abc.svc.local", + Namespace: "testns", + DefaultServiceAccount: "myns:test-sa", + }, + { + Server: "https://kubernetes.svc.local", + Namespace: "default", + DefaultServiceAccount: "default-sa", + }, + { + Server: "*", + Namespace: "*", + DefaultServiceAccount: "test-sa", + }, + } + destinationNamespace := "testns" + destinationServerURL := "https://abc.svc.local" + applicationNamespace := "argocd-ns" + expectedSA := "system:serviceaccount:myns:test-sa" + + f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace) + // when + sa, err := deriveServiceAccountToImpersonate(f.project, f.application) + + // then, there should not be any error and the service account with the given namespace prefix must be returned. + require.NoError(t, err) + assert.Equal(t, expectedSA, sa) + }) +} + +func TestSyncWithImpersonate(t *testing.T) { + type fixture struct { + project *v1alpha1.AppProject + application *v1alpha1.Application + controller *ApplicationController + } + + setup := func(impersonationEnabled bool, destinationNamespace, serviceAccountName string) *fixture { + app := newFakeApp() + app.Status.OperationState = nil + app.Status.History = nil + project := &v1alpha1.AppProject{ + ObjectMeta: v1.ObjectMeta{ + Namespace: test.FakeArgoCDNamespace, + Name: "default", + }, + Spec: v1alpha1.AppProjectSpec{ + DestinationServiceAccounts: []v1alpha1. + ApplicationDestinationServiceAccount{ + { + Server: "https://localhost:6443", + Namespace: destinationNamespace, + DefaultServiceAccount: serviceAccountName, + }, + }, + }, + } + additionalObjs := []runtime.Object{} + if serviceAccountName != "" { + syncServiceAccount := &corev1.ServiceAccount{ + ObjectMeta: v1.ObjectMeta{ + Name: serviceAccountName, + Namespace: test.FakeDestNamespace, + }, + } + additionalObjs = append(additionalObjs, syncServiceAccount) + } + data := fakeData{ + apps: []runtime.Object{app, project}, + manifestResponse: &apiclient.ManifestResponse{ + Manifests: []string{}, + Namespace: test.FakeDestNamespace, + Server: "https://localhost:6443", + Revision: "abc123", + }, + managedLiveObjs: map[kube.ResourceKey]*unstructured.Unstructured{}, + configMapData: map[string]string{ + "application.sync.impersonation.enabled": strconv.FormatBool(impersonationEnabled), + }, + additionalObjs: additionalObjs, + } + ctrl := newFakeController(&data, nil) + return &fixture{ + project: project, + application: app, + controller: ctrl, + } + } + + t.Run("sync with impersonation and no matching service account", func(t *testing.T) { + // given app sync impersonation feature is enabled with an application referring a project no matching service account + f := setup(true, test.FakeArgoCDNamespace, "") + opMessage := "failed to find a matching service account to impersonate: no matching service account found for destination server https://localhost:6443 and namespace fake-dest-ns" + + opState := &v1alpha1.OperationState{ + Operation: v1alpha1.Operation{ + Sync: &v1alpha1.SyncOperation{ + Source: &v1alpha1.ApplicationSource{}, + }, + }, + Phase: common.OperationRunning, + } + // when + f.controller.appStateManager.SyncAppState(f.application, opState) + + // then, app sync should fail with expected error message in operation state + assert.Equal(t, common.OperationError, opState.Phase) + assert.Contains(t, opState.Message, opMessage) + }) + + t.Run("sync with impersonation and empty service account match", func(t *testing.T) { + // given app sync impersonation feature is enabled with an application referring a project matching service account that is an empty string + f := setup(true, test.FakeDestNamespace, "") + opMessage := "failed to find a matching service account to impersonate: default service account contains invalid chars ''" + + opState := &v1alpha1.OperationState{ + Operation: v1alpha1.Operation{ + Sync: &v1alpha1.SyncOperation{ + Source: &v1alpha1.ApplicationSource{}, + }, + }, + Phase: common.OperationRunning, + } + // when + f.controller.appStateManager.SyncAppState(f.application, opState) + + // then app sync should fail with expected error message in operation state + assert.Equal(t, common.OperationError, opState.Phase) + assert.Contains(t, opState.Message, opMessage) + }) + + t.Run("sync with impersonation and matching sa", func(t *testing.T) { + // given app sync impersonation feature is enabled with an application referring a project matching service account + f := setup(true, test.FakeDestNamespace, "test-sa") + opMessage := "successfully synced (no more tasks)" + + opState := &v1alpha1.OperationState{ + Operation: v1alpha1.Operation{ + Sync: &v1alpha1.SyncOperation{ + Source: &v1alpha1.ApplicationSource{}, + }, + }, + Phase: common.OperationRunning, + } + // when + f.controller.appStateManager.SyncAppState(f.application, opState) + + // then app sync should not fail + assert.Equal(t, common.OperationSucceeded, opState.Phase) + assert.Contains(t, opState.Message, opMessage) + }) + + t.Run("sync without impersonation", func(t *testing.T) { + // given app sync impersonation feature is disabled with an application referring a project matching service account + f := setup(false, test.FakeDestNamespace, "") + opMessage := "successfully synced (no more tasks)" + + opState := &v1alpha1.OperationState{ + Operation: v1alpha1.Operation{ + Sync: &v1alpha1.SyncOperation{ + Source: &v1alpha1.ApplicationSource{}, + }, + }, + Phase: common.OperationRunning, + } + // when + f.controller.appStateManager.SyncAppState(f.application, opState) + + // then application sync should pass using the control plane service account + assert.Equal(t, common.OperationSucceeded, opState.Phase) + assert.Contains(t, opState.Message, opMessage) + }) +} + func dig[T any](obj interface{}, path []interface{}) T { i := obj diff --git a/docs/assets/versions.js b/docs/assets/versions.js index b9f0b13e8d0135..af95a7140a4421 100644 --- a/docs/assets/versions.js +++ b/docs/assets/versions.js @@ -32,23 +32,41 @@ function initializeVersionDropdown() { window[callbackName] = function(response) { const div = document.createElement('div'); div.innerHTML = response.html; - document.querySelector(".md-header__inner > .md-header__title").appendChild(div); + const headerTitle = document.querySelector(".md-header__inner > .md-header__title"); + if (headerTitle) { + headerTitle.appendChild(div); + } + const container = div.querySelector('.rst-versions'); + if (!container) return; // Exit if container not found + + // Add caret icon var caret = document.createElement('div'); caret.innerHTML = ""; caret.classList.add('dropdown-caret'); - div.querySelector('.rst-current-version').appendChild(caret); + const currentVersionElem = div.querySelector('.rst-current-version'); + if (currentVersionElem) { + currentVersionElem.appendChild(caret); + } - div.querySelector('.rst-current-version').addEventListener('click', function() { - container.classList.toggle('shift-up'); - }); + // Add click listener to toggle dropdown + if (currentVersionElem && container) { + currentVersionElem.addEventListener('click', function() { + container.classList.toggle('shift-up'); + }); + } + + // Sorting Logic + sortVersionLinks(container); }; + // Load CSS var CSSLink = document.createElement('link'); CSSLink.rel = 'stylesheet'; CSSLink.href = '/assets/versions.css'; document.getElementsByTagName('head')[0].appendChild(CSSLink); + // Load JSONP Script var script = document.createElement('script'); const currentVersion = getCurrentVersion(); script.src = 'https://argo-cd.readthedocs.io/_/api/v2/footer_html/?' + @@ -56,6 +74,58 @@ function initializeVersionDropdown() { document.getElementsByTagName('head')[0].appendChild(script); } +// Function to sort version links +function sortVersionLinks(container) { + // Find all
elements within the container + const dlElements = container.querySelectorAll('dl'); + + dlElements.forEach(dl => { + const dt = dl.querySelector('dt'); + if (dt && dt.textContent.trim().toLowerCase() === 'versions') { + // Found the Versions
+ const ddElements = Array.from(dl.querySelectorAll('dd')); + + // Define sorting criteria + ddElements.sort((a, b) => { + const aText = a.textContent.trim().toLowerCase(); + const bText = b.textContent.trim().toLowerCase(); + + // Prioritize 'latest' and 'stable' + if (aText === 'latest') return -1; + if (bText === 'latest') return 1; + if (aText === 'stable') return -1; + if (bText === 'stable') return 1; + + // Extract version numbers (e.g., release-2.9) + const aVersionMatch = aText.match(/release-(\d+(\.\d+)*)/); + const bVersionMatch = bText.match(/release-(\d+(\.\d+)*)/); + + if (aVersionMatch && bVersionMatch) { + const aVersion = aVersionMatch[1].split('.').map(Number); + const bVersion = bVersionMatch[1].split('.').map(Number); + + for (let i = 0; i < Math.max(aVersion.length, bVersion.length); i++) { + const aNum = aVersion[i] || 0; + const bNum = bVersion[i] || 0; + if (aNum > bNum) return -1; + if (aNum < bNum) return 1; + } + return 0; + } + + // Fallback to alphabetical order + return aText.localeCompare(bText); + }); + + // Remove existing
elements + ddElements.forEach(dd => dl.removeChild(dd)); + + // Append sorted
elements + ddElements.forEach(dd => dl.appendChild(dd)); + } + }); +} + // VERSION WARNINGS window.addEventListener("DOMContentLoaded", function() { var margin = 30; diff --git a/docs/getting_started.md b/docs/getting_started.md index ce0d9688e79633..74623e3f082092 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -141,6 +141,9 @@ service account token to perform its management tasks (i.e. deploy/monitoring). An example repository containing a guestbook application is available at [https://github.com/argoproj/argocd-example-apps.git](https://github.com/argoproj/argocd-example-apps.git) to demonstrate how Argo CD works. +!!! note + Note: The following example application may only be compatible with AMD64 architecture. If you are running on a different architecture (such as ARM64 or ARMv7), you may encounter issues with dependencies or container images that are not built for your platform. Consider verifying the compatibility of the application or building architecture-specific images if necessary. + ### Creating Apps Via CLI First we need to set the current namespace to argocd running the following command: diff --git a/docs/operator-manual/app-sync-using-impersonation.md b/docs/operator-manual/app-sync-using-impersonation.md index 9314f0b376b8ed..98174a82d0e9e8 100644 --- a/docs/operator-manual/app-sync-using-impersonation.md +++ b/docs/operator-manual/app-sync-using-impersonation.md @@ -1,7 +1,7 @@ # Application Sync using impersonation !!! warning "Alpha Feature" - This is an experimental, alpha-quality feature that allows you to control the service account used for the sync operation. The configured service account, could have lesser privileges required for creating resources compared to the highly privileged access required for the control plane operations. + This is an experimental, alpha-quality feature that allows you to control the service account used for the sync operation. The configured service account could have lesser privileges required for creating resources compared to the highly privileged access required for the control plane operations. !!! warning Please read this documentation carefully before you enable this feature. Misconfiguration could lead to potential security issues. @@ -94,7 +94,7 @@ spec: sourceRepos: - '*' destinations: - - * + - '*' destinationServiceAccounts: - server: https://kubernetes.default.svc namespace: guestbook diff --git a/docs/operator-manual/applicationset.yaml b/docs/operator-manual/applicationset.yaml index 88264493e248db..dbe36e076ca2ed 100644 --- a/docs/operator-manual/applicationset.yaml +++ b/docs/operator-manual/applicationset.yaml @@ -3,16 +3,6 @@ kind: ApplicationSet metadata: name: test-hello-world-appset namespace: argocd - # To preserve this annotation and label we can use the preservedFields property - preservedFields: - # This annotation and label exists only on this Application, and not in - # the parent ApplicationSet template: - # ignoreApplicationDifferences is the preferred way to accomplish this now. - annotations: - my-custom-annotation: some-value - labels: - my-custom-label: some-value - spec: generators: @@ -168,29 +158,17 @@ spec: applicationsSync: create-only # Prevents ApplicationSet controller from deleting Applications. Update is allowed - # applicationsSync: create-update + # applicationsSync: create-update # Prevents ApplicationSet controller from modifying Applications. Delete is allowed. - # applicationsSync: create-delete + # applicationsSync: create-delete - syncOptions: - - CreateNamespace=true # Prevent an Application's child resources from being deleted, when the parent Application is deleted preserveResourcesOnDeletion: true - # which fields of the ApplicationSet should be ignored when comparing Applications. - ignoreApplicationDifferences: - - jsonPointers: - - /spec/source/targetRevision - - name: some-app - jqExpressions: - - .spec.source.helm.values - strategy: - # This field lets you define fields which should be ignored when applying Application resources. This is helpful if you - # want to use ApplicationSets to create apps, but also want to allow users to modify those apps without having their - # changes overwritten by the ApplicationSet. - # This update strategy allows you to group Applications by labels present on the generated Application resources + # The RollingSync update strategy allows you to group Applications by labels present on the generated Application resources + # See documentation for "Progressive Syncs" type: RollingSync rollingSync: steps: @@ -214,6 +192,13 @@ spec: - env-prod maxUpdate: 10% # maxUpdate supports both integer and percentage string values (rounds down, but floored at 1 Application for >0%) + # Define annotations and labels of the Application that this ApplicationSet will ignore + # ignoreApplicationDifferences is the preferred way to accomplish this now. + preservedFields: + annotations: [ some-annotation-key ] + labels: [ some-label-key ] + + # Define fields of the that should be ignored when comparing Applications ignoreApplicationDifferences: - jsonPointers: - /spec/source/targetRevision @@ -311,4 +296,4 @@ spec: operator: In values: - https://kubernetes.default.svc - - https://some-other-cluster \ No newline at end of file + - https://some-other-cluster diff --git a/docs/operator-manual/applicationset/Generators-Cluster.md b/docs/operator-manual/applicationset/Generators-Cluster.md index de769b94deed9f..5532b87d6ad3e8 100644 --- a/docs/operator-manual/applicationset/Generators-Cluster.md +++ b/docs/operator-manual/applicationset/Generators-Cluster.md @@ -252,3 +252,63 @@ spec: server: '{{.values.clusterName}}' namespace: guestbook ``` +### Gather cluster information as a flat list + +You may sometimes need to gather your clusters information, without having to deploy one application per cluster found. +For that, you can use the option `flatList` in the cluster generator. + +Here is an example of cluster generator using this option: +```yaml +spec: + goTemplate: true + goTemplateOptions: ["missingkey=error"] + generators: + - clusters: + selector: + matchLabels: + type: 'staging' + flatList: true + template: + metadata: + name: 'flat-list-guestbook' + spec: + project: "my-project" + source: + repoURL: https://github.com/argoproj/argocd-example-apps/ + # The cluster values field for each generator will be substituted here: + targetRevision: 'HEAD' + path: helm-guestbook + helm: + values: | + clusters: + {{- range .clusters }} + - name: {{ .name }} + {{- end }} + destination: + # In this case this is equivalent to just using {{name}} + server: 'my-cluster' + namespace: guestbook +``` + +Given that you have two cluster secrets matching with names cluster1 and cluster2, this would generate the **single** following Application: + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: flat-list-guestbook + namespace: guestbook +spec: + project: "my-project" + source: + repoURL: https://github.com/argoproj/argocd-example-apps/ + targetRevision: 'HEAD' + path: helm-guestbook + helm: + values: | + clusters: + - name: cluster1 + - name: cluster1 +``` + +In case you are using several cluster generators, each with the flatList option, one Application would be generated by cluster generator, as we can't simply merge values and templates that would potentially differ in each generator. \ No newline at end of file diff --git a/docs/operator-manual/argocd-cm.yaml b/docs/operator-manual/argocd-cm.yaml index a8d3be645bcfb4..67460c45ab20bc 100644 --- a/docs/operator-manual/argocd-cm.yaml +++ b/docs/operator-manual/argocd-cm.yaml @@ -283,6 +283,9 @@ data: # - annotation+label : Also uses an annotation for tracking, but additionally labels the resource with the application name application.resourceTrackingMethod: annotation + # Optional installation id. Allows to have multiple installations of Argo CD in the same cluster. + installationID: "my-unique-id" + # disables admin user. Admin is enabled by default admin.enabled: "false" # add an additional local user with apiKey and login capabilities @@ -329,14 +332,14 @@ data: # spread out the refreshes and give time to the repo-server to catch up. The jitter is the maximum duration that can be # added to the sync timeout. So, if the sync timeout is 3 minutes and the jitter is 1 minute, then the actual timeout will # be between 3 and 4 minutes. Disabled when the value is 0, defaults to 0. - timeout.reconciliation.jitter: 0 + timeout.reconciliation.jitter: "0" # cluster.inClusterEnabled indicates whether to allow in-cluster server address. This is enabled by default. cluster.inClusterEnabled: "true" # The maximum number of pod logs to render in UI. If the application has more than this number of pods, the logs will not be rendered. # This is to prevent the UI from becoming unresponsive when rendering a large number of logs. Default is 10. - server.maxPodLogsToRender: 10 + server.maxPodLogsToRender: "10" # Application pod logs RBAC enforcement enables control over who can and who can't view application pod logs. # When you enable the switch, pod logs will be visible only to admin role by default. Other roles/users will not be able to view them via cli and UI. @@ -425,7 +428,7 @@ data: name: some-cluster server: https://some-cluster # The maximum size of the payload that can be sent to the webhook server. - webhook.maxPayloadSizeMB: 1024 + webhook.maxPayloadSizeMB: "1024" - # application.sync.impersonation.enabled indicates whether the application sync can be decoupled from control plane service account using impersonation. + # application.sync.impersonation.enabled enables application sync to use a custom service account, via impersonation. This allows decoupling sync from control-plane service account. application.sync.impersonation.enabled: "false" diff --git a/docs/operator-manual/argocd-cmd-params-cm.yaml b/docs/operator-manual/argocd-cmd-params-cm.yaml index 348677b1cb065a..17808b1f85a74c 100644 --- a/docs/operator-manual/argocd-cmd-params-cm.yaml +++ b/docs/operator-manual/argocd-cmd-params-cm.yaml @@ -241,6 +241,8 @@ data: applicationsetcontroller.enable.scm.providers: "false" # Number of webhook requests processed concurrently (default 50) applicationsetcontroller.webhook.parallelism.limit: "50" + # Override the default requeue time for the controller. (default 3m) + applicationsetcontroller.requeue.after: "3m" ## Argo CD Notifications Controller Properties # Set the logging level. One of: debug|info|warn|error (default "info") diff --git a/docs/operator-manual/health.md b/docs/operator-manual/health.md index 107f2f3f92cdb3..ad23dfa295d112 100644 --- a/docs/operator-manual/health.md +++ b/docs/operator-manual/health.md @@ -98,20 +98,27 @@ data: return hs ``` -In order to prevent duplication of the custom health check for potentially multiple resources, it is also possible to specify a wildcard in the resource kind, and anywhere in the resource group, like this: +In order to prevent duplication of custom health checks for potentially multiple resources, it is also possible to +specify a wildcard in the resource kind, and anywhere in the resource group, like this: ```yaml - resource.customizations.health.ec2.aws.crossplane.io_*: | - ... + resource.customizations: | + ec2.aws.crossplane.io/*: + health.lua: | + ... ``` ```yaml - resource.customizations.health.*.aws.crossplane.io_*: | - ... + # If a key _begins_ with a wildcard, please ensure that the GVK key is quoted. + resource.customizations: | + "*.aws.crossplane.io/*": + health.lua: | + ... ``` !!!important - Please, note that there can be ambiguous resolution of wildcards, see [#16905](https://github.com/argoproj/argo-cd/issues/16905) + Please, note that wildcards are only supported when using the `resource.customizations` key, the `resource.customizations.health._` +style keys do not work since wildcards (`*`) are not supported in Kubernetes configmap keys. The `obj` is a global variable which contains the resource. The script must return an object with status and optional message field. The custom health check might return one of the following health statuses: @@ -121,7 +128,7 @@ The custom health check might return one of the following health statuses: * `Degraded` - the resource is degraded * `Suspended` - the resource is suspended and waiting for some external event to resume (e.g. suspended CronJob or paused Deployment) -By default health typically returns `Progressing` status. +By default, health typically returns a `Progressing` status. NOTE: As a security measure, access to the standard Lua libraries will be disabled by default. Admins can control access by setting `resource.customizations.useOpenLibs._`. In the following example, standard libraries are enabled for health check of `cert-manager.io/Certificate`. diff --git a/docs/operator-manual/notifications/catalog.md b/docs/operator-manual/notifications/catalog.md index f4d88d2cf6aebf..aba74d3c40e34e 100644 --- a/docs/operator-manual/notifications/catalog.md +++ b/docs/operator-manual/notifications/catalog.md @@ -57,8 +57,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true }, { @@ -86,8 +86,8 @@ teams: "value": "{{.app.status.sync.status}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, }, { "name": "Revision", @@ -115,7 +115,7 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] themeColor: '#000080' @@ -143,8 +143,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -167,8 +167,8 @@ teams: "value": "{{.app.status.health.status}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -192,7 +192,7 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] themeColor: '#FF0000' @@ -220,8 +220,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -248,8 +248,8 @@ teams: "value": "{{.app.status.operationState.finishedAt}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -273,7 +273,7 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] themeColor: '#FF0000' @@ -301,8 +301,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -329,8 +329,8 @@ teams: "value": "{{.app.status.operationState.startedAt}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -354,7 +354,7 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] title: Start syncing application {{.app.metadata.name}}. @@ -386,8 +386,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -410,8 +410,8 @@ teams: "value": "{{.app.status.sync.status}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -435,7 +435,7 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] title: Application {{.app.metadata.name}} sync status is 'Unknown' @@ -462,8 +462,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -490,8 +490,8 @@ teams: "value": "{{.app.status.operationState.finishedAt}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -515,7 +515,7 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] themeColor: '#000080' diff --git a/docs/operator-manual/notifications/services/opsgenie.md b/docs/operator-manual/notifications/services/opsgenie.md index 2cc1ebff62abf7..d0caf71c982105 100755 --- a/docs/operator-manual/notifications/services/opsgenie.md +++ b/docs/operator-manual/notifications/services/opsgenie.md @@ -2,28 +2,34 @@ To be able to send notifications with argocd-notifications you have to create an [API Integration](https://docs.opsgenie.com/docs/integrations-overview) inside your [Opsgenie Team](https://docs.opsgenie.com/docs/teams). -1. Login to Opsgenie at https://app.opsgenie.com or https://app.eu.opsgenie.com (if you have an account in the european union) -2. Make sure you already have a team, if not follow this guide https://docs.opsgenie.com/docs/teams -3. Click "Teams" in the Menu on the left -4. Select the team that you want to notify -5. In the teams configuration menu select "Integrations" -6. Click "Add Integration" in the top right corner -7. Select "API" integration -8. Give your integration a name, copy the "API key" and safe it somewhere for later -9. Click "Edit" in the integration settings -10. Make sure the checkbox for "Create and Update Access" is selected, disable the other checkboxes to remove unnecessary permissions -11. Click "Save" at the bottom -12. Click "Turn on integration" in the top right corner -13. Check your browser for the correct server apiURL. If it is "app.opsgenie.com" then use the US/international api url `api.opsgenie.com` in the next step, otherwise use `api.eu.opsgenie.com` (European API). -14. You are finished with configuring Opsgenie. Now you need to configure argocd-notifications. Use the apiUrl, the team name and the apiKey to configure the Opsgenie integration in the `argocd-notifications-secret` secret. -15. You can find the example `argocd-notifications-cm` configuration at the below. +1. Login to Opsgenie at https://app.opsgenie.com or https://app.eu.opsgenie.com (if you have an account in the European Union). +2. Make sure you already have a team; if not, follow this guide: https://docs.opsgenie.com/docs/teams. +3. Click "Teams" in the Menu on the left. +4. Select the team that you want to notify. +5. In the team's configuration menu, select "Integrations". +6. Click "Add Integration" in the top right corner. +7. Select "API" integration. +8. Give your integration a name, copy the "API key", and save it somewhere for later. +9. Click "Edit" in the integration settings. +10. Make sure the checkbox for "Create and Update Access" is selected; disable the other checkboxes to remove unnecessary permissions. +11. Click "Save" at the bottom. +12. Click "Turn on integration" in the top right corner. +13. Check your browser for the correct server apiURL. If it is "app.opsgenie.com", then use the US/international API URL `api.opsgenie.com`; otherwise, use `api.eu.opsgenie.com` (European API). +14. You are finished with configuring Opsgenie. Now you need to configure argocd-notifications. Use the apiUrl, the team name, and the apiKey to configure the Opsgenie integration in the `argocd-notifications-secret` secret. +15. You can find the example `argocd-notifications-cm` configuration below. | **Option** | **Required** | **Type** | **Description** | **Example** | | ------------- | ------------ | -------- | -------------------------------------------------------------------------------------------------------- | -------------------------------- | -| `description` | True | `string` | Description field of the alert that is generally used to provide a detailed information about the alert. | `Hello from Argo CD!` | -| `priority` | False | `string` | Priority level of the alert. Possible values are P1, P2, P3, P4 and P5. Default value is P3. | `P1` | +| `description` | True | `string` | Description field of the alert that is generally used to provide detailed information about the alert. | `Hello from Argo CD!` | +| `priority` | False | `string` | Priority level of the alert. Possible values are P1, P2, P3, P4, and P5. Default value is P3. | `P1` | | `alias` | False | `string` | Client-defined identifier of the alert, that is also the key element of Alert De-Duplication. | `Life is too short for no alias` | -| `note` | False | `string` | Additional note that will be added while creating the alert. | `Error from Argo CD!` | +| `note` | False | `string` | Additional note that will be added while creating the alert. | `Error from Argo CD!` | +| `actions` | False | `[]string` | Custom actions that will be available for the alert. | `["Resolve", "Escalate"]` | +| `tags` | False | `[]string` | Tags of the alert. | `["critical", "deployment"]` | +| `visibleTo` | False | `[]alert.Responder` | Teams and users that the alert will become visible to without sending any notification. The `type` field is mandatory for each item, where possible values are `team` and `user`. In addition to the `type` field, either `id` or `name` should be provided for teams, and either `id` or `username` should be given for users. Please note that alerts will be visible to the teams specified within the `responders` field by default, so there is no need to re-specify them in the `visibleTo` field. | `[{Type: "team", Id: "team_id"}, {Type: "user", Id: "user_id"}]` | +| `details` | False | `map[string]string` | Map of key-value pairs to use as custom properties of the alert. | `{"environment": "production", "service": "web"}` | +| `entity` | False | `string` | Entity field of the alert that is generally used to specify which domain the alert is related to. | `web-server` | +| `user` | False | `string` | Display name of the request owner. | `admin_user` | ```yaml apiVersion: v1 @@ -47,6 +53,26 @@ data: priority: P1 alias: {{.app.metadata.name}} note: Error from Argo CD! + actions: + - Restart + - AnExampleAction + tags: + - OverwriteQuietHours + - Critical + visibleTo: + - Id: "{{.app.metadata.responderId}}" + Type: "team" + - Name: "rocket_team" + Type: "team" + - Id: "{{.app.metadata.responderUserId}}" + Type: "user" + - Username: "trinity@opsgenie.com" + Type: "user" + details: + environment: production + service: web + entity: Argo CD Application + user: John Doe trigger.on-a-problem: | - description: Application has a problem. send: @@ -54,11 +80,11 @@ data: when: app.status.health.status == 'Degraded' or app.status.operationState.phase in ['Error', 'Failed'] or app.status.sync.status == 'Unknown' ``` -16. Add annotation in application yaml file to enable notifications for specific Argo CD app. +16. Add annotation in the application YAML file to enable notifications for a specific Argo CD app. ```yaml - apiVersion: argoproj.io/v1alpha1 - kind: Application - metadata: - annotations: - notifications.argoproj.io/subscribe.on-a-problem.opsgenie: +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + annotations: + notifications.argoproj.io/subscribe.on-a-problem.opsgenie: ``` \ No newline at end of file diff --git a/docs/operator-manual/notifications/services/slack.md b/docs/operator-manual/notifications/services/slack.md index 41bdddd7617c4e..deb979cb68ecb2 100755 --- a/docs/operator-manual/notifications/services/slack.md +++ b/docs/operator-manual/notifications/services/slack.md @@ -21,11 +21,11 @@ The Slack notification service configuration includes following settings: 1. Create Slack Application using https://api.slack.com/apps?new_app=1 ![1](https://user-images.githubusercontent.com/426437/73604308-4cb0c500-4543-11ea-9092-6ca6bae21cbb.png) -1. Once application is created navigate to `Enter OAuth & Permissions` +1. Once application is created navigate to `OAuth & Permissions` ![2](https://user-images.githubusercontent.com/426437/73604309-4d495b80-4543-11ea-9908-4dea403d3399.png) -1. Click `Permissions` under `Add features and functionality` section and add `chat:write` scope. To use the optional username and icon overrides in the Slack notification service also add the `chat:write.customize` scope. +1. Go to `Scopes` > `Bot Token Scopes` > `Add an OAuth Scope`. Add `chat:write` scope. To use the optional username and icon overrides in the Slack notification service also add the `chat:write.customize` scope. ![3](https://user-images.githubusercontent.com/426437/73604310-4d495b80-4543-11ea-8576-09cd91aea0e5.png) -1. Scroll back to the top, click 'Install App to Workspace' button and confirm the installation. +1. `OAuth & Permission` > `OAuth Tokens for Your Workspace` > `Install to Workspace` ![4](https://user-images.githubusercontent.com/426437/73604311-4d495b80-4543-11ea-9155-9d216b20ec86.png) 1. Once installation is completed copy the OAuth token. ![5](https://user-images.githubusercontent.com/426437/73604312-4d495b80-4543-11ea-832b-a9d9d5e4bc29.png) diff --git a/docs/operator-manual/notifications/troubleshooting-errors.md b/docs/operator-manual/notifications/troubleshooting-errors.md index ecfcf7151c0ce2..406f19712a8831 100644 --- a/docs/operator-manual/notifications/troubleshooting-errors.md +++ b/docs/operator-manual/notifications/troubleshooting-errors.md @@ -27,22 +27,22 @@ metadata: data: service.slack: | token: $slack-token - icon: ":rocket:" + icon: ":rocket:" # <- diff here ``` ### service type 'xxxx' is not supported -You need to check your argocd-notifications controller version. For instance, the teams integration is to support `v1.1.0` and more. +Check the `argocd-notifications` controller version. For example, the Teams integration support started in `v1.1.0`. ## Failed to notify recipient ### notification service 'xxxx' is not supported -You have not defined `xxxx` in `argocd-notifications-cm` or to fail to parse settings. +You have not defined `xxxx` in `argocd-notifications-cm` or parsing failed. ### GitHub.repoURL (\u003cno value\u003e) does not have a / using the configuration -You probably have an Application with [multiple sources](https://argo-cd.readthedocs.io/en/stable/user-guide/multiple_sources/): +Likely caused by an Application with [multiple sources](https://argo-cd.readthedocs.io/en/stable/user-guide/multiple_sources/): ```yaml spec: @@ -53,7 +53,7 @@ spec: targetRevision: "{{branch}}" ``` -So standard notification template won't work (`{{.app.spec.source.repoURL}}`). You should choose a single source instead: +The standard notification template only supports a single source (`{{.app.spec.source.repoURL}}`). Use an index to specify the source in the array: ```yaml template.example: | @@ -65,7 +65,7 @@ template.example: | - If you are using a custom secret, check that the secret is in the same namespace - You have added the label: `app.kubernetes.io/part-of: argocd` to the secret -- You have tried restarting argocd-notifications controller +- You have tried restarting `argocd-notifications` controller ### Example: Secret: diff --git a/docs/operator-manual/notifications/troubleshooting.md b/docs/operator-manual/notifications/troubleshooting.md index 616cd4b024e829..b128e8244acc91 100644 --- a/docs/operator-manual/notifications/troubleshooting.md +++ b/docs/operator-manual/notifications/troubleshooting.md @@ -65,7 +65,7 @@ configuration. **Example** ```bash kubectl exec -it argocd-notifications-controller- \ - /app/argocd admin notifications trigger get + /usr/local/bin/argocd admin notifications trigger get ``` ## Commands diff --git a/docs/operator-manual/resource_actions_builtin.md b/docs/operator-manual/resource_actions_builtin.md index 46230a879a875c..7e149ecfe18f6c 100644 --- a/docs/operator-manual/resource_actions_builtin.md +++ b/docs/operator-manual/resource_actions_builtin.md @@ -33,6 +33,10 @@ - [notification.toolkit.fluxcd.io/Receiver/reconcile](https://github.com/argoproj/argo-cd/blob/master/resource_customizations/notification.toolkit.fluxcd.io/Receiver/actions/reconcile/action.lua) - [notification.toolkit.fluxcd.io/Receiver/resume](https://github.com/argoproj/argo-cd/blob/master/resource_customizations/notification.toolkit.fluxcd.io/Receiver/actions/resume/action.lua) - [notification.toolkit.fluxcd.io/Receiver/suspend](https://github.com/argoproj/argo-cd/blob/master/resource_customizations/notification.toolkit.fluxcd.io/Receiver/actions/suspend/action.lua) +- [numaplane.numaproj.io/MonoVertexRollout/pause](https://github.com/argoproj/argo-cd/blob/master/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/pause/action.lua) +- [numaplane.numaproj.io/MonoVertexRollout/unpause](https://github.com/argoproj/argo-cd/blob/master/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/unpause/action.lua) +- [numaplane.numaproj.io/PipelineRollout/pause](https://github.com/argoproj/argo-cd/blob/master/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/pause/action.lua) +- [numaplane.numaproj.io/PipelineRollout/unpause](https://github.com/argoproj/argo-cd/blob/master/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/unpause/action.lua) - [source.toolkit.fluxcd.io/Bucket/reconcile](https://github.com/argoproj/argo-cd/blob/master/resource_customizations/source.toolkit.fluxcd.io/Bucket/actions/reconcile/action.lua) - [source.toolkit.fluxcd.io/Bucket/resume](https://github.com/argoproj/argo-cd/blob/master/resource_customizations/source.toolkit.fluxcd.io/Bucket/actions/resume/action.lua) - [source.toolkit.fluxcd.io/Bucket/suspend](https://github.com/argoproj/argo-cd/blob/master/resource_customizations/source.toolkit.fluxcd.io/Bucket/actions/suspend/action.lua) diff --git a/docs/proposals/decouple-application-sync-user-using-impersonation.md b/docs/proposals/decouple-application-sync-user-using-impersonation.md index 050c8d6b0a6356..2f4ebe776ed8f4 100644 --- a/docs/proposals/decouple-application-sync-user-using-impersonation.md +++ b/docs/proposals/decouple-application-sync-user-using-impersonation.md @@ -68,9 +68,9 @@ This proposal would allow ArgoCD administrators to manage the cluster permission ### Goals - Applications may only impersonate ServiceAccounts that live in the same namespace as the destination namespace configured in the application.If the service account is created in a different namespace, then the user can provide the service account name in the format `:` . ServiceAccount to be used for syncing each application is determined by the target destination configured in the `AppProject` associated with the `Application`. -- If impersonation feature is enabled, and no service account name is provided in the associated `AppProject`, then the sync operation would fail with an appropriate error message. Users can configure a catch all service account matching all destinations to avoid such sync errors. +- If impersonation feature is enabled, and no service account name is provided in the associated `AppProject`, then the default service account of the destination namespace of the `Application` should be used. - Access restrictions implemented through properties in AppProject (if done) must have the existing behavior. From a security standpoint, any restrictions that were available before switching to a service account based approach should continue to exist even when the impersonation feature is enabled. -- The feature can be enabled/disabled only at the system level. Once enabled/disabled, it is applicable to all ArgoCD `Applications`. +- The feature can be enabled/disabled only at the system level. Once enabled/disabled, it is applicable to all Argo CD `Applications`. ### Non-Goals @@ -82,7 +82,7 @@ As part of this proposal, it would be possible for an ArgoCD Admin to specify a When applications gets synced, based on its destination (target cluster and namespace combination), the `defaultServiceAccount` configured in the `AppProject` will be selected and used for impersonation when executing the kubectl commands for the sync operation. -We would be introducing a new element `destinationServiceAccounts` in `AppProject.spec`. This element is used for the sole purpose of specifying the impersonation configuration. The `defaultServiceAccount` configured for the `AppProject` would be used for the sync operation for a particular destination cluster and namespace. If impersonation feature is enabled and no specific service account is provided in the `AppProject` CR, then the sync operation will fail with an error. Users can configure a catch all service account matching all destinations to avoid such sync errors. +We would be introducing a new element `destinationServiceAccounts` in `AppProject.spec`. This element is used for the sole purpose of specifying the impersonation configuration. The `defaultServiceAccount` configured for the `AppProject` would be used for the sync operation for a particular destination cluster and namespace. If impersonation feature is enabled and no specific service account is provided in the `AppProject` CR, then the `default` service account in the destination namespace would be used for impersonation. ```yaml apiVersion: argoproj.io/v1alpha1 @@ -109,7 +109,7 @@ spec: - server: https://kubernetes.default.svc namespace: guestbook-stage defaultServiceAccount: guestbook-stage-deployer - - server: '* + - server: '*' namespace: '*' defaultServiceAccount: default # catch all service account to be used when all other matches fail. ``` @@ -161,7 +161,10 @@ So that, I can use a generic convention of naming service accounts and avoid ass #### Component: ArgoCD Application Controller -- Provide a configuration in `argocd-cm` which can be modified to enable the Impersonation feature. Set `application.sync.impersonation.enabled: "true"` in the Argo CD ConfigMap. Default value of `application.sync.impersonation.enabled` would be `"false"` and user has to explicitly override it to use this feature. +- Provide a configuration in `argocd-cm` which can be modified to enable the Impersonation feature. Set `applicationcontroller.enable.impersonation: true` in the Argo CD ConfigMap. Default value of `applicationcontroller.enable.impersonation` would be `false` and user has to explicitly override it to use this feature. +- Provide an option to override the Impersonation feature using environment variables. +Set `ARGOCD_APPLICATION_CONTROLLER_ENABLE_IMPERSONATION=true` in the Application controller environment variables. Default value of the environment variable must be `false` and user has to explicitly set it to `true` to use this feature. +- Provide an option to enable this feature using a command line flag `--enable-impersonation`. This new argument option needs to be added to the Application controller args. - Fix Application Controller `sync.go` to set the Impersonate configuration from the AppProject CR to the `SyncContext` Object (rawConfig and restConfig field, need to understand which config is used for the actual sync and if both configs need to be impersonated.) #### Component: ArgoCD UI diff --git a/docs/requirements.txt b/docs/requirements.txt index 26b5dc2049e051..180b8473c5a419 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,9 +1,9 @@ -mkdocs==1.3.0 +mkdocs==1.6.1 # Strict mode has been disabled in latest versions of mkdocs-material. # Thus pointing to the older version of mkdocs-material. mkdocs-material==7.1.8 -markdown_include==0.6.0 -pygments==2.15.1 +markdown_include==0.8.1 +pygments==2.18.0 jinja2==3.1.4 -markdown==3.3.7 -pymdown-extensions==10.2.1 \ No newline at end of file +markdown==3.7 +pymdown-extensions==10.11.2 \ No newline at end of file diff --git a/docs/snyk/index.md b/docs/snyk/index.md index b9e7582682786b..83b12c29878102 100644 --- a/docs/snyk/index.md +++ b/docs/snyk/index.md @@ -14,7 +14,7 @@ recent minor releases. | | Critical | High | Medium | Low | |---:|:--------:|:----:|:------:|:---:| | [go.mod](master/argocd-test.html) | 0 | 0 | 1 | 0 | -| [ui/yarn.lock](master/argocd-test.html) | 0 | 0 | 1 | 0 | +| [ui/yarn.lock](master/argocd-test.html) | 0 | 0 | 0 | 0 | | [dex:v2.41.1](master/ghcr.io_dexidp_dex_v2.41.1.html) | 0 | 0 | 0 | 1 | | [haproxy:2.6.17-alpine](master/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html) | 0 | 0 | 2 | 3 | | [redis:7.0.15-alpine](master/public.ecr.aws_docker_library_redis_7.0.15-alpine.html) | 0 | 0 | 0 | 0 | @@ -37,42 +37,42 @@ recent minor releases. | [install.yaml](v2.13.0-rc2/argocd-iac-install.html) | - | - | - | - | | [namespace-install.yaml](v2.13.0-rc2/argocd-iac-namespace-install.html) | - | - | - | - | -### v2.12.3 +### v2.12.4 | | Critical | High | Medium | Low | |---:|:--------:|:----:|:------:|:---:| -| [go.mod](v2.12.3/argocd-test.html) | 0 | 0 | 2 | 0 | -| [ui/yarn.lock](v2.12.3/argocd-test.html) | 0 | 1 | 2 | 0 | -| [dex:v2.38.0](v2.12.3/ghcr.io_dexidp_dex_v2.38.0.html) | 0 | 0 | 6 | 6 | -| [haproxy:2.6.17-alpine](v2.12.3/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html) | 0 | 0 | 2 | 3 | -| [redis:7.0.15-alpine](v2.12.3/public.ecr.aws_docker_library_redis_7.0.15-alpine.html) | 0 | 0 | 0 | 0 | -| [argocd:v2.12.3](v2.12.3/quay.io_argoproj_argocd_v2.12.3.html) | 0 | 0 | 8 | 8 | -| [redis:7.0.15-alpine](v2.12.3/redis_7.0.15-alpine.html) | 0 | 0 | 0 | 0 | -| [install.yaml](v2.12.3/argocd-iac-install.html) | - | - | - | - | -| [namespace-install.yaml](v2.12.3/argocd-iac-namespace-install.html) | - | - | - | - | +| [go.mod](v2.12.4/argocd-test.html) | 0 | 0 | 2 | 0 | +| [ui/yarn.lock](v2.12.4/argocd-test.html) | 0 | 0 | 0 | 0 | +| [dex:v2.38.0](v2.12.4/ghcr.io_dexidp_dex_v2.38.0.html) | 0 | 0 | 6 | 6 | +| [haproxy:2.6.17-alpine](v2.12.4/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html) | 0 | 0 | 2 | 3 | +| [redis:7.0.15-alpine](v2.12.4/public.ecr.aws_docker_library_redis_7.0.15-alpine.html) | 0 | 0 | 0 | 0 | +| [argocd:v2.12.4](v2.12.4/quay.io_argoproj_argocd_v2.12.4.html) | 0 | 0 | 3 | 8 | +| [redis:7.0.15-alpine](v2.12.4/redis_7.0.15-alpine.html) | 0 | 0 | 0 | 0 | +| [install.yaml](v2.12.4/argocd-iac-install.html) | - | - | - | - | +| [namespace-install.yaml](v2.12.4/argocd-iac-namespace-install.html) | - | - | - | - | -### v2.11.8 +### v2.11.9 | | Critical | High | Medium | Low | |---:|:--------:|:----:|:------:|:---:| -| [go.mod](v2.11.8/argocd-test.html) | 0 | 1 | 3 | 0 | -| [ui/yarn.lock](v2.11.8/argocd-test.html) | 0 | 1 | 2 | 0 | -| [dex:v2.38.0](v2.11.8/ghcr.io_dexidp_dex_v2.38.0.html) | 0 | 0 | 6 | 6 | -| [haproxy:2.6.14-alpine](v2.11.8/haproxy_2.6.14-alpine.html) | 0 | 1 | 7 | 6 | -| [argocd:v2.11.8](v2.11.8/quay.io_argoproj_argocd_v2.11.8.html) | 0 | 0 | 8 | 16 | -| [redis:7.0.15-alpine](v2.11.8/redis_7.0.15-alpine.html) | 0 | 0 | 0 | 0 | -| [install.yaml](v2.11.8/argocd-iac-install.html) | - | - | - | - | -| [namespace-install.yaml](v2.11.8/argocd-iac-namespace-install.html) | - | - | - | - | +| [go.mod](v2.11.9/argocd-test.html) | 0 | 1 | 3 | 0 | +| [ui/yarn.lock](v2.11.9/argocd-test.html) | 0 | 0 | 0 | 0 | +| [dex:v2.38.0](v2.11.9/ghcr.io_dexidp_dex_v2.38.0.html) | 0 | 0 | 6 | 6 | +| [haproxy:2.6.14-alpine](v2.11.9/haproxy_2.6.14-alpine.html) | 0 | 1 | 7 | 6 | +| [argocd:v2.11.9](v2.11.9/quay.io_argoproj_argocd_v2.11.9.html) | 0 | 0 | 4 | 17 | +| [redis:7.0.15-alpine](v2.11.9/redis_7.0.15-alpine.html) | 0 | 0 | 0 | 0 | +| [install.yaml](v2.11.9/argocd-iac-install.html) | - | - | - | - | +| [namespace-install.yaml](v2.11.9/argocd-iac-namespace-install.html) | - | - | - | - | -### v2.10.16 +### v2.10.17 | | Critical | High | Medium | Low | |---:|:--------:|:----:|:------:|:---:| -| [go.mod](v2.10.16/argocd-test.html) | 0 | 1 | 4 | 0 | -| [ui/yarn.lock](v2.10.16/argocd-test.html) | 0 | 1 | 2 | 0 | -| [dex:v2.37.0](v2.10.16/ghcr.io_dexidp_dex_v2.37.0.html) | 1 | 1 | 10 | 6 | -| [haproxy:2.6.14-alpine](v2.10.16/haproxy_2.6.14-alpine.html) | 0 | 1 | 7 | 6 | -| [argocd:v2.10.16](v2.10.16/quay.io_argoproj_argocd_v2.10.16.html) | 0 | 0 | 12 | 20 | -| [redis:7.0.15-alpine](v2.10.16/redis_7.0.15-alpine.html) | 0 | 0 | 0 | 0 | -| [install.yaml](v2.10.16/argocd-iac-install.html) | - | - | - | - | -| [namespace-install.yaml](v2.10.16/argocd-iac-namespace-install.html) | - | - | - | - | +| [go.mod](v2.10.17/argocd-test.html) | 0 | 1 | 3 | 0 | +| [ui/yarn.lock](v2.10.17/argocd-test.html) | 0 | 0 | 0 | 0 | +| [dex:v2.37.0](v2.10.17/ghcr.io_dexidp_dex_v2.37.0.html) | 1 | 1 | 10 | 6 | +| [haproxy:2.6.14-alpine](v2.10.17/haproxy_2.6.14-alpine.html) | 0 | 1 | 7 | 6 | +| [argocd:v2.10.17](v2.10.17/quay.io_argoproj_argocd_v2.10.17.html) | 0 | 0 | 4 | 17 | +| [redis:7.0.15-alpine](v2.10.17/redis_7.0.15-alpine.html) | 0 | 0 | 0 | 0 | +| [install.yaml](v2.10.17/argocd-iac-install.html) | - | - | - | - | +| [namespace-install.yaml](v2.10.17/argocd-iac-namespace-install.html) | - | - | - | - | diff --git a/docs/snyk/master/argocd-iac-install.html b/docs/snyk/master/argocd-iac-install.html index 4ffca011eadd2a..1d94aa7eedee1d 100644 --- a/docs/snyk/master/argocd-iac-install.html +++ b/docs/snyk/master/argocd-iac-install.html @@ -456,7 +456,7 @@

Snyk test report

-

September 22nd 2024, 12:21:06 am (UTC+00:00)

+

October 6th 2024, 12:29:10 am (UTC+00:00)

Scanned the following path: @@ -507,7 +507,7 @@

Role or ClusterRole with dangerous permissions

  • - Line number: 22389 + Line number: 22536
  • @@ -553,7 +553,7 @@

    Role or ClusterRole with dangerous permissions

  • - Line number: 22070 + Line number: 22217
  • @@ -599,7 +599,7 @@

    Role or ClusterRole with dangerous permissions

  • - Line number: 22157 + Line number: 22304
  • @@ -645,7 +645,7 @@

    Role or ClusterRole with dangerous permissions

  • - Line number: 22185 + Line number: 22332
  • @@ -691,7 +691,7 @@

    Role or ClusterRole with dangerous permissions

  • - Line number: 22215 + Line number: 22362
  • @@ -737,7 +737,7 @@

    Role or ClusterRole with dangerous permissions

  • - Line number: 22233 + Line number: 22380
  • @@ -783,7 +783,7 @@

    Role or ClusterRole with dangerous permissions

  • - Line number: 22251 + Line number: 22398
  • @@ -829,7 +829,7 @@

    Role or ClusterRole with dangerous permissions

  • - Line number: 22273 + Line number: 22420
  • @@ -881,7 +881,7 @@

    Container could be running with outdated image

  • - Line number: 23345 + Line number: 23505
  • @@ -933,7 +933,7 @@

    Container could be running with outdated image

  • - Line number: 23644 + Line number: 23812
  • @@ -991,7 +991,7 @@

    Container has no CPU limit

  • - Line number: 22882 + Line number: 23030
  • @@ -1049,7 +1049,7 @@

    Container has no CPU limit

  • - Line number: 23151 + Line number: 23307
  • @@ -1107,7 +1107,7 @@

    Container has no CPU limit

  • - Line number: 23105 + Line number: 23261
  • @@ -1165,7 +1165,7 @@

    Container has no CPU limit

  • - Line number: 23211 + Line number: 23369
  • @@ -1223,7 +1223,7 @@

    Container has no CPU limit

  • - Line number: 23316 + Line number: 23476
  • @@ -1281,7 +1281,7 @@

    Container has no CPU limit

  • - Line number: 23340 + Line number: 23500
  • @@ -1339,7 +1339,7 @@

    Container has no CPU limit

  • - Line number: 23644 + Line number: 23812
  • @@ -1397,7 +1397,7 @@

    Container has no CPU limit

  • - Line number: 23397 + Line number: 23559
  • @@ -1455,7 +1455,7 @@

    Container has no CPU limit

  • - Line number: 23729 + Line number: 23899
  • @@ -1513,7 +1513,7 @@

    Container has no CPU limit

  • - Line number: 24119 + Line number: 24291
  • @@ -1565,7 +1565,7 @@

    Container is running with multiple open ports

  • - Line number: 23131 + Line number: 23287
  • @@ -1617,7 +1617,7 @@

    Container is running without liveness probe

  • - Line number: 22882 + Line number: 23030
  • @@ -1669,7 +1669,7 @@

    Container is running without liveness probe

  • - Line number: 23105 + Line number: 23261
  • @@ -1721,7 +1721,7 @@

    Container is running without liveness probe

  • - Line number: 23316 + Line number: 23476
  • @@ -1779,7 +1779,7 @@

    Container is running without memory limit

  • - Line number: 22882 + Line number: 23030
  • @@ -1837,7 +1837,7 @@

    Container is running without memory limit

  • - Line number: 23105 + Line number: 23261
  • @@ -1895,7 +1895,7 @@

    Container is running without memory limit

  • - Line number: 23151 + Line number: 23307
  • @@ -1953,7 +1953,7 @@

    Container is running without memory limit

  • - Line number: 23211 + Line number: 23369
  • @@ -2011,7 +2011,7 @@

    Container is running without memory limit

  • - Line number: 23316 + Line number: 23476
  • @@ -2069,7 +2069,7 @@

    Container is running without memory limit

  • - Line number: 23340 + Line number: 23500
  • @@ -2127,7 +2127,7 @@

    Container is running without memory limit

  • - Line number: 23644 + Line number: 23812
  • @@ -2185,7 +2185,7 @@

    Container is running without memory limit

  • - Line number: 23397 + Line number: 23559
  • @@ -2243,7 +2243,7 @@

    Container is running without memory limit

  • - Line number: 23729 + Line number: 23899
  • @@ -2301,7 +2301,7 @@

    Container is running without memory limit

  • - Line number: 24119 + Line number: 24291
  • @@ -2357,7 +2357,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 23029 + Line number: 23183
  • @@ -2413,7 +2413,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 23159 + Line number: 23315
  • @@ -2469,7 +2469,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 23134 + Line number: 23290
  • @@ -2525,7 +2525,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 23250 + Line number: 23408
  • @@ -2581,7 +2581,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 23333 + Line number: 23493
  • @@ -2637,7 +2637,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 23347 + Line number: 23507
  • @@ -2693,7 +2693,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 23651 + Line number: 23819
  • @@ -2749,7 +2749,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 23617 + Line number: 23785
  • @@ -2805,7 +2805,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 24020 + Line number: 24190
  • @@ -2861,7 +2861,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 24320 + Line number: 24492
  • diff --git a/docs/snyk/master/argocd-iac-namespace-install.html b/docs/snyk/master/argocd-iac-namespace-install.html index a78881186e5894..d0346a0ff1d80a 100644 --- a/docs/snyk/master/argocd-iac-namespace-install.html +++ b/docs/snyk/master/argocd-iac-namespace-install.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:21:16 am (UTC+00:00)

    +

    October 6th 2024, 12:29:19 am (UTC+00:00)

    Scanned the following path: @@ -835,7 +835,7 @@

    Container could be running with outdated image

  • - Line number: 1138 + Line number: 1150
  • @@ -887,7 +887,7 @@

    Container could be running with outdated image

  • - Line number: 1437 + Line number: 1457
  • @@ -1003,7 +1003,7 @@

    Container has no CPU limit

  • - Line number: 944 + Line number: 952
  • @@ -1061,7 +1061,7 @@

    Container has no CPU limit

  • - Line number: 898 + Line number: 906
  • @@ -1119,7 +1119,7 @@

    Container has no CPU limit

  • - Line number: 1004 + Line number: 1014
  • @@ -1177,7 +1177,7 @@

    Container has no CPU limit

  • - Line number: 1109 + Line number: 1121
  • @@ -1235,7 +1235,7 @@

    Container has no CPU limit

  • - Line number: 1133 + Line number: 1145
  • @@ -1293,7 +1293,7 @@

    Container has no CPU limit

  • - Line number: 1437 + Line number: 1457
  • @@ -1351,7 +1351,7 @@

    Container has no CPU limit

  • - Line number: 1190 + Line number: 1204
  • @@ -1409,7 +1409,7 @@

    Container has no CPU limit

  • - Line number: 1522 + Line number: 1544
  • @@ -1467,7 +1467,7 @@

    Container has no CPU limit

  • - Line number: 1912 + Line number: 1936
  • @@ -1519,7 +1519,7 @@

    Container is running with multiple open ports

  • - Line number: 924 + Line number: 932
  • @@ -1623,7 +1623,7 @@

    Container is running without liveness probe

  • - Line number: 898 + Line number: 906
  • @@ -1675,7 +1675,7 @@

    Container is running without liveness probe

  • - Line number: 1109 + Line number: 1121
  • @@ -1791,7 +1791,7 @@

    Container is running without memory limit

  • - Line number: 898 + Line number: 906
  • @@ -1849,7 +1849,7 @@

    Container is running without memory limit

  • - Line number: 944 + Line number: 952
  • @@ -1907,7 +1907,7 @@

    Container is running without memory limit

  • - Line number: 1004 + Line number: 1014
  • @@ -1965,7 +1965,7 @@

    Container is running without memory limit

  • - Line number: 1109 + Line number: 1121
  • @@ -2023,7 +2023,7 @@

    Container is running without memory limit

  • - Line number: 1133 + Line number: 1145
  • @@ -2081,7 +2081,7 @@

    Container is running without memory limit

  • - Line number: 1437 + Line number: 1457
  • @@ -2139,7 +2139,7 @@

    Container is running without memory limit

  • - Line number: 1190 + Line number: 1204
  • @@ -2197,7 +2197,7 @@

    Container is running without memory limit

  • - Line number: 1522 + Line number: 1544
  • @@ -2255,7 +2255,7 @@

    Container is running without memory limit

  • - Line number: 1912 + Line number: 1936
  • @@ -2311,7 +2311,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 822 + Line number: 828
  • @@ -2367,7 +2367,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 952 + Line number: 960
  • @@ -2423,7 +2423,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 927 + Line number: 935
  • @@ -2479,7 +2479,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 1043 + Line number: 1053
  • @@ -2535,7 +2535,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 1126 + Line number: 1138
  • @@ -2591,7 +2591,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 1140 + Line number: 1152
  • @@ -2647,7 +2647,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 1444 + Line number: 1464
  • @@ -2703,7 +2703,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 1410 + Line number: 1430
  • @@ -2759,7 +2759,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 1813 + Line number: 1835
  • @@ -2815,7 +2815,7 @@

    Container's or Pod's UID could clash with hos
  • - Line number: 2113 + Line number: 2137
  • diff --git a/docs/snyk/master/argocd-test.html b/docs/snyk/master/argocd-test.html index 0c91d6f1cb1591..8bf88381b684d7 100644 --- a/docs/snyk/master/argocd-test.html +++ b/docs/snyk/master/argocd-test.html @@ -7,7 +7,7 @@ Snyk test report - + @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:18:54 am (UTC+00:00)

    +

    October 6th 2024, 12:26:59 am (UTC+00:00)

    Scanned the following paths: @@ -467,9 +467,9 @@

    Snyk test report

    -
    2 known vulnerabilities
    -
    4 vulnerable dependency paths
    -
    2132 dependencies
    +
    1 known vulnerabilities
    +
    1 vulnerable dependency paths
    +
    2137 dependencies

    @@ -477,175 +477,6 @@

    Snyk test report

    -
    -

    Regular Expression Denial of Service (ReDoS)

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: /argo-cd โ€บ ui/yarn.lock -
    • -
    • - Package Manager: npm -
    • -
    • - Vulnerable module: - - path-to-regexp -
    • - -
    • Introduced through: - - - argo-cd-ui@1.0.0, react-router@4.3.1 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
    • -
    • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - react-router-dom@4.3.1 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
    • -
    • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - argo-ui@1.0.0 - โ€บ - react-router-dom@4.3.1 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
    • -
    - -
    - -
    - -

    Overview

    -

    Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) when including multiple regular expression parameters in a single segment, which will produce the regular expression /^\/([^\/]+?)-([^\/]+?)\/?$/, if two parameters within a single segment are separated by a character other than a / or .. Poor performance will block the event loop and can lead to a DoS.

    -

    Note: - While the 8.0.0 release has completely eliminated the vulnerable functionality, prior versions that have received the patch to mitigate backtracking may still be vulnerable if custom regular expressions are used. So it is strongly recommended for regular expression input to be controlled to avoid malicious performance degradation in those versions. This behavior is enforced as of version 7.1.0 via the strict option, which returns an error if a dangerous regular expression is detected.

    -

    Workaround

    -

    This vulnerability can be avoided by using a custom regular expression for parameters after the first in a segment, which excludes - and /.

    -

    PoC

    -
    /a${'-a'.repeat(8_000)}/a
    -        
    -

    Details

    -

    Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.

    -

    The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.

    -

    Letโ€™s take the following regular expression as an example:

    -
    regex = /A(B|C+)+D/
    -        
    -

    This regular expression accomplishes the following:

    -
      -
    • A The string must start with the letter 'A'
    • -
    • (B|C+)+ The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the + matches one or more times). The + at the end of this section states that we can look for one or more matches of this section.
    • -
    • D Finally, we ensure this section of the string ends with a 'D'
    • -
    -

    The expression would match inputs such as ABBD, ABCCCCD, ABCBCCCD and ACCCCCD

    -

    It most cases, it doesn't take very long for a regex engine to find a match:

    -
    $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
    -        0.04s user 0.01s system 95% cpu 0.052 total
    -        
    -        $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
    -        1.79s user 0.02s system 99% cpu 1.812 total
    -        
    -

    The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.

    -

    Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesnโ€™t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.

    -

    Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:

    -
      -
    1. CCC
    2. -
    3. CC+C
    4. -
    5. C+CC
    6. -
    7. C+C+C.
    8. -
    -

    The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.

    -

    From there, the number of steps the engine must use to validate a string just continues to grow.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    StringNumber of C'sNumber of steps
    ACCCX338
    ACCCCX471
    ACCCCCX5136
    ACCCCCCCCCCCCCCX1465,553
    -

    By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.

    -

    Remediation

    -

    Upgrade path-to-regexp to version 0.1.10, 1.9.0, 3.3.0, 6.3.0, 8.0.0 or higher.

    -

    References

    - - -
    - - - -

    Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')

    diff --git a/docs/snyk/master/ghcr.io_dexidp_dex_v2.41.1.html b/docs/snyk/master/ghcr.io_dexidp_dex_v2.41.1.html index 55eb2fcbe954bf..9430df1532e001 100644 --- a/docs/snyk/master/ghcr.io_dexidp_dex_v2.41.1.html +++ b/docs/snyk/master/ghcr.io_dexidp_dex_v2.41.1.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:19:01 am (UTC+00:00)

    +

    October 6th 2024, 12:27:12 am (UTC+00:00)

    Scanned the following paths: diff --git a/docs/snyk/master/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html b/docs/snyk/master/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html index d9db5c2fc73c88..9f20b9c3a871e0 100644 --- a/docs/snyk/master/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html +++ b/docs/snyk/master/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:19:15 am (UTC+00:00)

    +

    October 6th 2024, 12:27:17 am (UTC+00:00)

    Scanned the following path: diff --git a/docs/snyk/master/public.ecr.aws_docker_library_redis_7.0.15-alpine.html b/docs/snyk/master/public.ecr.aws_docker_library_redis_7.0.15-alpine.html index ccf5d62549670c..958c48778efb6f 100644 --- a/docs/snyk/master/public.ecr.aws_docker_library_redis_7.0.15-alpine.html +++ b/docs/snyk/master/public.ecr.aws_docker_library_redis_7.0.15-alpine.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:19:21 am (UTC+00:00)

    +

    October 6th 2024, 12:27:22 am (UTC+00:00)

    Scanned the following paths: diff --git a/docs/snyk/master/quay.io_argoproj_argocd_latest.html b/docs/snyk/master/quay.io_argoproj_argocd_latest.html index b01bd7de717147..6b19ba0bab44f0 100644 --- a/docs/snyk/master/quay.io_argoproj_argocd_latest.html +++ b/docs/snyk/master/quay.io_argoproj_argocd_latest.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:19:38 am (UTC+00:00)

    +

    October 6th 2024, 12:27:40 am (UTC+00:00)

    Scanned the following paths: @@ -472,7 +472,7 @@

    Snyk test report

    11 known vulnerabilities
    65 vulnerable dependency paths
    -
    2355 dependencies
    +
    2360 dependencies
    diff --git a/docs/snyk/master/redis_7.0.15-alpine.html b/docs/snyk/master/redis_7.0.15-alpine.html index 86330360ca083e..5135569b7ad170 100644 --- a/docs/snyk/master/redis_7.0.15-alpine.html +++ b/docs/snyk/master/redis_7.0.15-alpine.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:19:42 am (UTC+00:00)

    +

    October 6th 2024, 12:27:44 am (UTC+00:00)

    Scanned the following paths: diff --git a/docs/snyk/v2.10.16/argocd-iac-install.html b/docs/snyk/v2.10.17/argocd-iac-install.html similarity index 99% rename from docs/snyk/v2.10.16/argocd-iac-install.html rename to docs/snyk/v2.10.17/argocd-iac-install.html index caf0aceb5972fb..78e3fdd57accd5 100644 --- a/docs/snyk/v2.10.16/argocd-iac-install.html +++ b/docs/snyk/v2.10.17/argocd-iac-install.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:30:18 am (UTC+00:00)

    +

    October 6th 2024, 12:38:19 am (UTC+00:00)

    Scanned the following path: diff --git a/docs/snyk/v2.10.16/argocd-iac-namespace-install.html b/docs/snyk/v2.10.17/argocd-iac-namespace-install.html similarity index 99% rename from docs/snyk/v2.10.16/argocd-iac-namespace-install.html rename to docs/snyk/v2.10.17/argocd-iac-namespace-install.html index 1a15c2d0c5416e..2adfede1754abb 100644 --- a/docs/snyk/v2.10.16/argocd-iac-namespace-install.html +++ b/docs/snyk/v2.10.17/argocd-iac-namespace-install.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:30:27 am (UTC+00:00)

    +

    October 6th 2024, 12:38:28 am (UTC+00:00)

    Scanned the following path: diff --git a/docs/snyk/v2.10.16/argocd-test.html b/docs/snyk/v2.10.17/argocd-test.html similarity index 85% rename from docs/snyk/v2.10.16/argocd-test.html rename to docs/snyk/v2.10.17/argocd-test.html index 82f63569dbd395..4f892a8771ed62 100644 --- a/docs/snyk/v2.10.16/argocd-test.html +++ b/docs/snyk/v2.10.17/argocd-test.html @@ -7,7 +7,7 @@ Snyk test report - + @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:28:24 am (UTC+00:00)

    +

    October 6th 2024, 12:36:27 am (UTC+00:00)

    Scanned the following paths: @@ -467,8 +467,8 @@

    Snyk test report

    -
    8 known vulnerabilities
    -
    164 vulnerable dependency paths
    +
    4 known vulnerabilities
    +
    147 vulnerable dependency paths
    2042 dependencies
    @@ -3139,329 +3139,6 @@

    References

    More about this vulnerability

    -
    -
    -

    Prototype Pollution

    -
    - -
    - high severity -
    - -
    - -
      -
    • - Manifest file: /argo-cd โ€บ ui/yarn.lock -
    • -
    • - Package Manager: npm -
    • -
    • - Vulnerable module: - - dompurify -
    • - -
    • Introduced through: - - - argo-cd-ui@1.0.0, redoc@2.0.0-rc.64 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - redoc@2.0.0-rc.64 - โ€บ - dompurify@2.3.6 - - - -
    • -
    - -
    - -
    - -

    Overview

    -

    dompurify is a DOM-only XSS sanitizer for HTML, MathML and SVG.

    -

    Affected versions of this package are vulnerable to Prototype Pollution due to improper user input sanitization through the depth-checking mechanism, an attacker can exploit this vulnerability by using special nesting techniques to create a malicious HTML file.

    -

    Details

    -

    Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as __proto__, constructor and prototype. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.

    -

    There are two main ways in which the pollution of prototypes occurs:

    -
      -
    • Unsafe Object recursive merge

      -
    • -
    • Property definition by path

      -
    • -
    -

    Unsafe Object recursive merge

    -

    The logic of a vulnerable recursive merge function follows the following high-level model:

    -
    merge (target, source)
    -        
    -          foreach property of source
    -        
    -            if property exists and is an object on both the target and the source
    -        
    -              merge(target[property], source[property])
    -        
    -            else
    -        
    -              target[property] = source[property]
    -        
    -
    - -

    When the source object contains a property named __proto__ defined with Object.defineProperty() , the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object and the source of Object as defined by the attacker. Properties are then copied on the Object prototype.

    -

    Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source).

    -

    lodash and Hoek are examples of libraries susceptible to recursive merge attacks.

    -

    Property definition by path

    -

    There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)

    -

    If the attacker can control the value of โ€œpathโ€, they can set this value to __proto__.myValue. myValue is then assigned to the prototype of the class of the object.

    -

    Types of attacks

    -

    There are a few methods by which Prototype Pollution can be manipulated:

    - - - - - - - - - - - - - - - - - - - - - - - -
    TypeOriginShort description
    Denial of service (DoS)ClientThis is the most likely attack.
    DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf).
    The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object. In this case, the code fails and is likely to cause a denial of service.
    For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail.
    Remote Code ExecutionClientRemote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation.
    For example: eval(someobject.someattr). In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code.
    Property InjectionClientThe attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens.
    For example: if a codebase checks privileges for someuser.isAdmin, then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true, they can then achieve admin privileges.
    -

    Affected environments

    -

    The following environments are susceptible to a Prototype Pollution attack:

    -
      -
    • Application server

      -
    • -
    • Web server

      -
    • -
    • Web browser

      -
    • -
    -

    How to prevent

    -
      -
    1. Freeze the prototypeโ€” use Object.freeze (Object.prototype).

      -
    2. -
    3. Require schema validation of JSON input.

      -
    4. -
    5. Avoid using unsafe recursive merge functions.

      -
    6. -
    7. Consider using objects without prototypes (for example, Object.create(null)), breaking the prototype chain and preventing pollution.

      -
    8. -
    9. As a best practice use Map instead of Object.

      -
    10. -
    -

    For more information on this vulnerability type:

    -

    Arteau, Oliver. โ€œJavaScript prototype pollution attack in NodeJS application.โ€ GitHub, 26 May 2018

    -

    Remediation

    -

    Upgrade dompurify to version 2.5.4, 3.1.3 or higher.

    -

    References

    - - -
    - - - -
    -
    -

    Regular Expression Denial of Service (ReDoS)

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: /argo-cd โ€บ ui/yarn.lock -
    • -
    • - Package Manager: npm -
    • -
    • - Vulnerable module: - - path-to-regexp -
    • - -
    • Introduced through: - - - argo-cd-ui@1.0.0, react-router@4.3.1 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
    • -
    • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - react-router-dom@4.3.1 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
    • -
    • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - argo-ui@1.0.0 - โ€บ - react-router-dom@4.3.1 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
    • -
    - -
    - -
    - -

    Overview

    -

    Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) when including multiple regular expression parameters in a single segment, which will produce the regular expression /^\/([^\/]+?)-([^\/]+?)\/?$/, if two parameters within a single segment are separated by a character other than a / or .. Poor performance will block the event loop and can lead to a DoS.

    -

    Note: - While the 8.0.0 release has completely eliminated the vulnerable functionality, prior versions that have received the patch to mitigate backtracking may still be vulnerable if custom regular expressions are used. So it is strongly recommended for regular expression input to be controlled to avoid malicious performance degradation in those versions. This behavior is enforced as of version 7.1.0 via the strict option, which returns an error if a dangerous regular expression is detected.

    -

    Workaround

    -

    This vulnerability can be avoided by using a custom regular expression for parameters after the first in a segment, which excludes - and /.

    -

    PoC

    -
    /a${'-a'.repeat(8_000)}/a
    -        
    -

    Details

    -

    Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.

    -

    The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.

    -

    Letโ€™s take the following regular expression as an example:

    -
    regex = /A(B|C+)+D/
    -        
    -

    This regular expression accomplishes the following:

    -
      -
    • A The string must start with the letter 'A'
    • -
    • (B|C+)+ The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the + matches one or more times). The + at the end of this section states that we can look for one or more matches of this section.
    • -
    • D Finally, we ensure this section of the string ends with a 'D'
    • -
    -

    The expression would match inputs such as ABBD, ABCCCCD, ABCBCCCD and ACCCCCD

    -

    It most cases, it doesn't take very long for a regex engine to find a match:

    -
    $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
    -        0.04s user 0.01s system 95% cpu 0.052 total
    -        
    -        $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
    -        1.79s user 0.02s system 99% cpu 1.812 total
    -        
    -

    The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.

    -

    Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesnโ€™t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.

    -

    Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:

    -
      -
    1. CCC
    2. -
    3. CC+C
    4. -
    5. C+CC
    6. -
    7. C+C+C.
    8. -
    -

    The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.

    -

    From there, the number of steps the engine must use to validate a string just continues to grow.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    StringNumber of C'sNumber of steps
    ACCCX338
    ACCCCX471
    ACCCCCX5136
    ACCCCCCCCCCCCCCX1465,553
    -

    By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.

    -

    Remediation

    -

    Upgrade path-to-regexp to version 0.1.10, 1.9.0, 3.3.0, 6.3.0, 8.0.0 or higher.

    -

    References

    - - -
    - - -

    Regular Expression Denial of Service (ReDoS)

    @@ -3789,229 +3466,6 @@

    References

    More about this vulnerability

    -
    -
    -

    Insertion of Sensitive Information into Log File

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: /argo-cd/argoproj/argo-cd/v2 โ€บ go.mod -
    • -
    • - Package Manager: golang -
    • -
    • - Vulnerable module: - - github.com/hashicorp/go-retryablehttp -
    • - -
    • Introduced through: - - github.com/argoproj/argo-cd/v2@0.0.0 and github.com/hashicorp/go-retryablehttp@0.7.4 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/argoproj/notifications-engine/pkg/services@#84b9f7913604 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/xanzy/go-gitlab@0.91.1 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/argoproj/notifications-engine/pkg/subscriptions@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/services@#84b9f7913604 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/argoproj/notifications-engine/pkg/cmd@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/services@#84b9f7913604 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/argoproj/notifications-engine/pkg/services@#84b9f7913604 - โ€บ - github.com/opsgenie/opsgenie-go-sdk-v2/client@1.0.5 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/argoproj/notifications-engine/pkg/api@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/subscriptions@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/services@#84b9f7913604 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/argoproj/notifications-engine/pkg/controller@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/subscriptions@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/services@#84b9f7913604 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/argoproj/notifications-engine/pkg/subscriptions@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/services@#84b9f7913604 - โ€บ - github.com/opsgenie/opsgenie-go-sdk-v2/client@1.0.5 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/argoproj/notifications-engine/pkg/cmd@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/services@#84b9f7913604 - โ€บ - github.com/opsgenie/opsgenie-go-sdk-v2/client@1.0.5 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/argoproj/notifications-engine/pkg/api@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/subscriptions@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/services@#84b9f7913604 - โ€บ - github.com/opsgenie/opsgenie-go-sdk-v2/client@1.0.5 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/argoproj/notifications-engine/pkg/controller@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/subscriptions@#84b9f7913604 - โ€บ - github.com/argoproj/notifications-engine/pkg/services@#84b9f7913604 - โ€บ - github.com/opsgenie/opsgenie-go-sdk-v2/client@1.0.5 - โ€บ - github.com/hashicorp/go-retryablehttp@0.7.4 - - - -
    • -
    - -
    - -
    - -

    Overview

    -

    Affected versions of this package are vulnerable to Insertion of Sensitive Information into Log File due to not sanitizing urls when writing them to the log file. This could lead to an attacker writing sensitive HTTP basic auth credentials to the log file.

    -

    Remediation

    -

    Upgrade github.com/hashicorp/go-retryablehttp to version 0.7.7 or higher.

    -

    References

    - - -
    - - -

    Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')

    @@ -4104,81 +3558,6 @@

    References

    -
    -

    Template Injection

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: /argo-cd โ€บ ui/yarn.lock -
    • -
    • - Package Manager: npm -
    • -
    • - Vulnerable module: - - dompurify -
    • - -
    • Introduced through: - - - argo-cd-ui@1.0.0, redoc@2.0.0-rc.64 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - redoc@2.0.0-rc.64 - โ€บ - dompurify@2.3.6 - - - -
    • -
    - -
    - -
    - -

    Overview

    -

    dompurify is a DOM-only XSS sanitizer for HTML, MathML and SVG.

    -

    Affected versions of this package are vulnerable to Template Injection in purify.js, due to inconsistencies in the parsing of XML and HTML tags. Executable code can be injected in HTML inside XML CDATA blocks.

    -

    PoC

    -
    <![CDATA[ ><img src onerror=alert(1)> ]]>
    -        
    -

    Remediation

    -

    Upgrade dompurify to version 2.4.9, 3.0.11 or higher.

    -

    References

    - - -
    - - - -
    diff --git a/docs/snyk/v2.10.16/ghcr.io_dexidp_dex_v2.37.0.html b/docs/snyk/v2.10.17/ghcr.io_dexidp_dex_v2.37.0.html similarity index 99% rename from docs/snyk/v2.10.16/ghcr.io_dexidp_dex_v2.37.0.html rename to docs/snyk/v2.10.17/ghcr.io_dexidp_dex_v2.37.0.html index f6beb50189acb8..5b4e6a7373ef77 100644 --- a/docs/snyk/v2.10.16/ghcr.io_dexidp_dex_v2.37.0.html +++ b/docs/snyk/v2.10.17/ghcr.io_dexidp_dex_v2.37.0.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:28:32 am (UTC+00:00)

    +

    October 6th 2024, 12:36:34 am (UTC+00:00)

    Scanned the following paths: @@ -2959,7 +2959,7 @@

    Details

    When it comes to open source libraries, DoS vulnerabilities allow attackers to trigger such a crash or crippling of the service by using a flaw either in the application code or from the use of open source libraries.

    Two common types of DoS vulnerabilities:

      -
    • High CPU/Memory Consumption- An attacker sending crafted requests that could cause the system to take a disproportionate amount of time to process. For example, commons-fileupload:commons-fileupload.

      +
    • High CPU/Memory Consumption- An attacker sending crafted requests that could cause the system to take a disproportionate amount of time to process. For example, commons-fileupload:commons-fileupload.

    • Crash - An attacker sending crafted requests that could cause the system to crash. For Example, npm ws package

    • diff --git a/docs/snyk/v2.11.8/haproxy_2.6.14-alpine.html b/docs/snyk/v2.10.17/haproxy_2.6.14-alpine.html similarity index 99% rename from docs/snyk/v2.11.8/haproxy_2.6.14-alpine.html rename to docs/snyk/v2.10.17/haproxy_2.6.14-alpine.html index 51e9cc5e39b950..8d092ed9732985 100644 --- a/docs/snyk/v2.11.8/haproxy_2.6.14-alpine.html +++ b/docs/snyk/v2.10.17/haproxy_2.6.14-alpine.html @@ -456,7 +456,7 @@

      Snyk test report

      -

      September 22nd 2024, 12:26:22 am (UTC+00:00)

      +

      October 6th 2024, 12:36:38 am (UTC+00:00)

      Scanned the following path: diff --git a/docs/snyk/v2.10.16/quay.io_argoproj_argocd_v2.10.16.html b/docs/snyk/v2.10.17/quay.io_argoproj_argocd_v2.10.17.html similarity index 64% rename from docs/snyk/v2.10.16/quay.io_argoproj_argocd_v2.10.16.html rename to docs/snyk/v2.10.17/quay.io_argoproj_argocd_v2.10.17.html index 8ba1cd553e6c15..70751689fb49a0 100644 --- a/docs/snyk/v2.10.16/quay.io_argoproj_argocd_v2.10.16.html +++ b/docs/snyk/v2.10.17/quay.io_argoproj_argocd_v2.10.17.html @@ -7,7 +7,7 @@ Snyk test report - + @@ -456,22 +456,22 @@

      Snyk test report

      -

      September 22nd 2024, 12:28:55 am (UTC+00:00)

      +

      October 6th 2024, 12:36:55 am (UTC+00:00)

      Scanned the following paths:
        -
      • quay.io/argoproj/argocd:v2.10.16/argoproj/argocd/Dockerfile (deb)
      • -
      • quay.io/argoproj/argocd:v2.10.16/argoproj/argo-cd/v2//usr/local/bin/argocd (gomodules)
      • -
      • quay.io/argoproj/argocd:v2.10.16//usr/local/bin/kustomize (gomodules)
      • -
      • quay.io/argoproj/argocd:v2.10.16/helm/v3//usr/local/bin/helm (gomodules)
      • -
      • quay.io/argoproj/argocd:v2.10.16/git-lfs/git-lfs//usr/bin/git-lfs (gomodules)
      • +
      • quay.io/argoproj/argocd:v2.10.17/argoproj/argocd/Dockerfile (deb)
      • +
      • quay.io/argoproj/argocd:v2.10.17/argoproj/argo-cd/v2//usr/local/bin/argocd (gomodules)
      • +
      • quay.io/argoproj/argocd:v2.10.17//usr/local/bin/kustomize (gomodules)
      • +
      • quay.io/argoproj/argocd:v2.10.17/helm/v3//usr/local/bin/helm (gomodules)
      • +
      • quay.io/argoproj/argocd:v2.10.17/git-lfs/git-lfs//usr/bin/git-lfs (gomodules)
      -
      35 known vulnerabilities
      -
      241 vulnerable dependency paths
      +
      23 known vulnerabilities
      +
      169 vulnerable dependency paths
      2278 dependencies
      @@ -492,7 +492,7 @@

      Allocation of Resources Without Limits or Throttling

    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd
    • Package Manager: golang @@ -572,7 +572,7 @@

      CVE-2024-41996

      • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
      • Package Manager: ubuntu:22.04 @@ -585,7 +585,7 @@

        CVE-2024-41996

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and openssl/libssl3@3.0.2-0ubuntu1.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 and openssl/libssl3@3.0.2-0ubuntu1.18
      @@ -598,77 +598,77 @@

      Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 + openssl/libssl3@3.0.2-0ubuntu1.18
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ cyrus-sasl2/libsasl2-modules@2.1.27+dfsg2-3ubuntu1.2 โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 + openssl/libssl3@3.0.2-0ubuntu1.18
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ libfido2/libfido2-1@1.10.0-1 โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 + openssl/libssl3@3.0.2-0ubuntu1.18
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 + openssl/libssl3@3.0.2-0ubuntu1.18
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - ca-certificates@20230311ubuntu0.22.04.1 + ca-certificates@20240203~22.04.1 โ€บ - openssl@3.0.2-0ubuntu1.16 + openssl@3.0.2-0ubuntu1.18 โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 + openssl/libssl3@3.0.2-0ubuntu1.18
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 + openssl/libssl3@3.0.2-0ubuntu1.18
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -680,31 +680,31 @@

        Detailed paths

        โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4 โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 + openssl/libssl3@3.0.2-0ubuntu1.18
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - openssl@3.0.2-0ubuntu1.16 + openssl@3.0.2-0ubuntu1.18
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - ca-certificates@20230311ubuntu0.22.04.1 + ca-certificates@20240203~22.04.1 โ€บ - openssl@3.0.2-0ubuntu1.16 + openssl@3.0.2-0ubuntu1.18 @@ -735,202 +735,6 @@

        References

        More about this vulnerability

    -
    -
    -

    CVE-2024-6119

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - openssl/libssl3 -
    • - -
    • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.10.16 and openssl/libssl3@3.0.2-0ubuntu1.16 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - cyrus-sasl2/libsasl2-modules@2.1.27+dfsg2-3ubuntu1.2 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - libfido2/libfido2-1@1.10.0-1 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssh/openssh-client@1:8.9p1-3ubuntu0.10 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - ca-certificates@20230311ubuntu0.22.04.1 - โ€บ - openssl@3.0.2-0ubuntu1.16 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 - โ€บ - libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssl@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - ca-certificates@20230311ubuntu0.22.04.1 - โ€บ - openssl@3.0.2-0ubuntu1.16 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream openssl package and not the openssl package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    Issue summary: Applications performing certificate name checks (e.g., TLS - clients checking server certificates) may attempt to read an invalid memory - address resulting in abnormal termination of the application process.

    -

    Impact summary: Abnormal termination of an application can a cause a denial of - service.

    -

    Applications performing certificate name checks (e.g., TLS clients checking - server certificates) may attempt to read an invalid memory address when - comparing the expected name with an otherName subject alternative name of an - X.509 certificate. This may result in an exception that terminates the - application program.

    -

    Note that basic certificate chain validation (signatures, dates, ...) is not - affected, the denial of service can occur only when the application also - specifies an expected DNS name, Email address or IP address.

    -

    TLS servers rarely solicit client certificates, and even when they do, they - generally don't perform a name check against a reference identifier (expected - identity), but rather extract the presented identity after checking the - certificate chain. So TLS servers are generally not affected and the severity - of the issue is Moderate.

    -

    The FIPS modules in 3.3, 3.2, 3.1 and 3.0 are not affected by this issue.

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 openssl to version 3.0.2-0ubuntu1.18 or higher.

    -

    References

    - - -
    - - -

    Information Exposure

    @@ -944,7 +748,7 @@

    Information Exposure

    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
    • Package Manager: ubuntu:22.04 @@ -957,7 +761,7 @@

      Information Exposure

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and libgcrypt20@1.9.4-3ubuntu3 + docker-image|quay.io/argoproj/argocd@v2.10.17 and libgcrypt20@1.9.4-3ubuntu3
    @@ -970,7 +774,7 @@

    Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ libgcrypt20@1.9.4-3ubuntu3 @@ -979,7 +783,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/dirmngr@2.2.27-3ubuntu2.1 โ€บ @@ -990,7 +794,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 โ€บ @@ -1001,11 +805,11 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - apt@2.4.12 + apt@2.4.13 โ€บ - apt/libapt-pkg6.0@2.4.12 + apt/libapt-pkg6.0@2.4.13 โ€บ libgcrypt20@1.9.4-3ubuntu3 @@ -1014,9 +818,9 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - apt@2.4.12 + apt@2.4.13 โ€บ gnupg2/gpgv@2.2.27-3ubuntu2.1 โ€บ @@ -1027,7 +831,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 โ€บ @@ -1040,7 +844,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -1053,7 +857,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -1066,7 +870,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -1079,7 +883,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -1092,7 +896,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -1105,11 +909,11 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - apt@2.4.12 + apt@2.4.13 โ€บ - apt/libapt-pkg6.0@2.4.12 + apt/libapt-pkg6.0@2.4.13 โ€บ systemd/libsystemd0@249.11-0ubuntu3.12 โ€บ @@ -1157,7 +961,7 @@

      CVE-2024-26462

      • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
      • Package Manager: ubuntu:22.04 @@ -1170,7 +974,7 @@

        CVE-2024-26462

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and krb5/libk5crypto3@1.19.2-2ubuntu0.3 + docker-image|quay.io/argoproj/argocd@v2.10.17 and krb5/libk5crypto3@1.19.2-2ubuntu0.4
      @@ -1183,16 +987,16 @@

      Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -1204,16 +1008,16 @@

        Detailed paths

        โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -1225,27 +1029,27 @@

        Detailed paths

        โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -1257,64 +1061,64 @@

        Detailed paths

        โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -1326,16 +1130,16 @@

        Detailed paths

        โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libkrb5support0@1.19.2-2ubuntu0.3 + krb5/libkrb5support0@1.19.2-2ubuntu0.4 @@ -1367,7 +1171,7 @@

        References

    -

    CVE-2024-37371

    +

    Denial of Service (DoS)

    @@ -1378,20 +1182,20 @@

    CVE-2024-37371

    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd
    • - Package Manager: ubuntu:22.04 + Package Manager: golang
    • Vulnerable module: - krb5/libk5crypto3 + github.com/rs/cors
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and krb5/libk5crypto3@1.19.2-2ubuntu0.3 + github.com/argoproj/argo-cd/v2@* and github.com/rs/cors@v1.9.0
    @@ -1404,159 +1208,161 @@

    Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + github.com/argoproj/argo-cd/v2@* โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + github.com/rs/cors@v1.9.0
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 - - +
    - -
  • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 - - +
  • - -
  • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - - +
    + +

    Overview

    +

    Affected versions of this package are vulnerable to Denial of Service (DoS) through the processing of malicious preflight requests that include a Access-Control-Request-Headers header with excessive commas. An attacker can induce excessive memory consumption and potentially crash the server by sending specially crafted requests.

    +

    PoC

    +
    
    +        func BenchmarkPreflightAdversarialACRH(b *testing.B) {
    +            resps := makeFakeResponses(b.N)
    +            req, _ := http.NewRequest(http.MethodOptions, dummyEndpoint, nil)
    +            req.Header.Add(headerOrigin, dummyOrigin)
    +            req.Header.Add(headerACRM, http.MethodGet)
    +            req.Header[headerACRH] = adversarialACRH
    +            handler := Default().Handler(testHandler)
             
    -                            
  • -
  • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssh/openssh-client@1:8.9p1-3ubuntu0.10 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - - + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + handler.ServeHTTP(resps[i], req) + } + } -
  • -
  • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - - + var adversarialACRH []string -
  • -
  • + func init() { // populates adversarialACRH + n := int(math.Floor(math.Sqrt(http.DefaultMaxHeaderBytes))) + commas := strings.Repeat(",", n) + res := make([]string, n) + for i := range res { + res[i] = commas + } + adversarialACRH = res + } + +

    Details

    +

    Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its intended and legitimate users.

    +

    Unlike other vulnerabilities, DoS attacks usually do not aim at breaching security. Rather, they are focused on making websites and services unavailable to genuine users resulting in downtime.

    +

    One popular Denial of Service vulnerability is DDoS (a Distributed Denial of Service), an attack that attempts to clog network pipes to the system by generating a large volume of traffic from many machines.

    +

    When it comes to open source libraries, DoS vulnerabilities allow attackers to trigger such a crash or crippling of the service by using a flaw either in the application code or from the use of open source libraries.

    +

    Two common types of DoS vulnerabilities:

    +
      +
    • High CPU/Memory Consumption- An attacker sending crafted requests that could cause the system to take a disproportionate amount of time to process. For example, commons-fileupload:commons-fileupload.

      +
    • +
    • Crash - An attacker sending crafted requests that could cause the system to crash. For Example, npm ws package

      +
    • +
    +

    Remediation

    +

    Upgrade github.com/rs/cors to version 1.11.0 or higher.

    +

    References

    + + +
    + + + +
  • +
    +

    CVE-2023-4039

    +
    + +
    + medium severity +
    + +
    + +
      +
    • + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile +
    • +
    • + Package Manager: ubuntu:22.04 +
    • +
    • + Vulnerable module: + + gcc-12/libstdc++6 +
    • + +
    • Introduced through: + + docker-image|quay.io/argoproj/argocd@v2.10.17 and gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 + +
    • +
    + +
    + + +

    Detailed paths

    + +
      +
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - adduser@3.118ubuntu5 + apt@2.4.13 โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 + gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 + + + +
    • +
    • + Introduced through: + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 + apt@2.4.13 โ€บ - libnsl/libnsl2@1.3.0-2build2 + apt/libapt-pkg6.0@2.4.13 โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 + gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 + + + +
    • +
    • + Introduced through: + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + gcc-12/gcc-12-base@12.3.0-1ubuntu1~22.04
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libkrb5support0@1.19.2-2ubuntu0.3 + gcc-12/libgcc-s1@12.3.0-1ubuntu1~22.04 @@ -1568,38 +1374,50 @@

      Detailed paths


      NVD Description

      -

      Note: Versions mentioned in the description apply only to the upstream krb5 package and not the krb5 package as distributed by Ubuntu. +

      Note: Versions mentioned in the description apply only to the upstream gcc-12 package and not the gcc-12 package as distributed by Ubuntu. See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

      -

      In MIT Kerberos 5 (aka krb5) before 1.21.3, an attacker can cause invalid memory reads during GSS message token handling by sending message tokens with invalid length fields.

      +

      DISPUTEDA failure in the -fstack-protector feature in GCC-based toolchains + that target AArch64 allows an attacker to exploit an existing buffer + overflow in dynamically-sized local variables in your application + without this being detected. This stack-protector failure only applies + to C99-style dynamically-sized local variables or those created using + alloca(). The stack-protector operates as intended for statically-sized + local variables.

      +

      The default behavior when the stack-protector + detects an overflow is to terminate your application, resulting in + controlled loss of availability. An attacker who can exploit a buffer + overflow without triggering the stack-protector might be able to change + program flow control to cause an uncontrolled loss of availability or to + go further and affect confidentiality or integrity. NOTE: The GCC project argues that this is a missed hardening bug and not a vulnerability by itself.

      Remediation

      -

      Upgrade Ubuntu:22.04 krb5 to version 1.19.2-2ubuntu0.4 or higher.

      +

      There is no fixed version for Ubuntu:22.04 gcc-12.

      References


    -
    -

    CVE-2024-37370

    +
    +

    CVE-2023-7008

    -
    - medium severity +
    + low severity

    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
    • Package Manager: ubuntu:22.04 @@ -1607,12 +1425,12 @@

      CVE-2024-37370

    • Vulnerable module: - krb5/libk5crypto3 + systemd/libsystemd0
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and krb5/libk5crypto3@1.19.2-2ubuntu0.3 + docker-image|quay.io/argoproj/argocd@v2.10.17 and systemd/libsystemd0@249.11-0ubuntu3.12
    @@ -1625,159 +1443,110 @@

    Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + systemd/libsystemd0@249.11-0ubuntu3.12
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + apt@2.4.13 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + systemd/libsystemd0@249.11-0ubuntu3.12
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + procps/libprocps8@2:3.3.17-6ubuntu2.1 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + systemd/libsystemd0@249.11-0ubuntu3.12
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 + โ€บ + util-linux@2.37.2-4ubuntu3.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + systemd/libsystemd0@249.11-0ubuntu3.12
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + util-linux/bsdutils@1:2.37.2-4ubuntu3.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + systemd/libsystemd0@249.11-0ubuntu3.12
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + apt@2.4.13 โ€บ - openssh/openssh-client@1:8.9p1-3ubuntu0.10 + apt/libapt-pkg6.0@2.4.13 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + systemd/libsystemd0@249.11-0ubuntu3.12
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + systemd/libudev1@249.11-0ubuntu3.12
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 + libfido2/libfido2-1@1.10.0-1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + systemd/libudev1@249.11-0ubuntu3.12
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 + util-linux@2.37.2-4ubuntu3.4 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + systemd/libudev1@249.11-0ubuntu3.12
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 + โ€บ + apt@2.4.13 + โ€บ + apt/libapt-pkg6.0@2.4.13 โ€บ - krb5/libkrb5support0@1.19.2-2ubuntu0.3 + systemd/libudev1@249.11-0ubuntu3.12 @@ -1789,51 +1558,57 @@

      Detailed paths


      NVD Description

      -

      Note: Versions mentioned in the description apply only to the upstream krb5 package and not the krb5 package as distributed by Ubuntu. +

      Note: Versions mentioned in the description apply only to the upstream systemd package and not the systemd package as distributed by Ubuntu. See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

      -

      In MIT Kerberos 5 (aka krb5) before 1.21.3, an attacker can modify the plaintext Extra Count field of a confidential GSS krb5 wrap token, causing the unwrapped token to appear truncated to the application.

      +

      A vulnerability was found in systemd-resolved. This issue may allow systemd-resolved to accept records of DNSSEC-signed domains even when they have no signature, allowing man-in-the-middles (or the upstream DNS resolver) to manipulate records.

      Remediation

      -

      Upgrade Ubuntu:22.04 krb5 to version 1.19.2-2ubuntu0.4 or higher.

      +

      There is no fixed version for Ubuntu:22.04 systemd.

      References


    -
    -

    Denial of Service (DoS)

    +
    +

    Arbitrary Code Injection

    -
    - medium severity +
    + low severity

    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
    • - Package Manager: golang + Package Manager: ubuntu:22.04
    • Vulnerable module: - github.com/rs/cors + shadow/passwd
    • Introduced through: - github.com/argoproj/argo-cd/v2@* and github.com/rs/cors@v1.9.0 + docker-image|quay.io/argoproj/argocd@v2.10.17 and shadow/passwd@1:4.8.1-2ubuntu2.2
    @@ -1846,119 +1621,40 @@

    Detailed paths

    • Introduced through: - github.com/argoproj/argo-cd/v2@* + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - github.com/rs/cors@v1.9.0 + shadow/passwd@1:4.8.1-2ubuntu2.2
    • -
    +
  • + Introduced through: + docker-image|quay.io/argoproj/argocd@v2.10.17 + โ€บ + adduser@3.118ubuntu5 + โ€บ + shadow/passwd@1:4.8.1-2ubuntu2.2 + + -
  • + +
  • + Introduced through: + docker-image|quay.io/argoproj/argocd@v2.10.17 + โ€บ + openssh/openssh-client@1:8.9p1-3ubuntu0.10 + โ€บ + shadow/passwd@1:4.8.1-2ubuntu2.2 + + -
    - -

    Overview

    -

    Affected versions of this package are vulnerable to Denial of Service (DoS) through the processing of malicious preflight requests that include a Access-Control-Request-Headers header with excessive commas. An attacker can induce excessive memory consumption and potentially crash the server by sending specially crafted requests.

    -

    PoC

    -
    
    -        func BenchmarkPreflightAdversarialACRH(b *testing.B) {
    -            resps := makeFakeResponses(b.N)
    -            req, _ := http.NewRequest(http.MethodOptions, dummyEndpoint, nil)
    -            req.Header.Add(headerOrigin, dummyOrigin)
    -            req.Header.Add(headerACRM, http.MethodGet)
    -            req.Header[headerACRH] = adversarialACRH
    -            handler := Default().Handler(testHandler)
    -        
    -            b.ReportAllocs()
    -            b.ResetTimer()
    -            for i := 0; i < b.N; i++ {
    -                handler.ServeHTTP(resps[i], req)
    -            }
    -        }
    -        
    -        var adversarialACRH []string
    -        
    -        func init() { // populates adversarialACRH
    -            n := int(math.Floor(math.Sqrt(http.DefaultMaxHeaderBytes)))
    -            commas := strings.Repeat(",", n)
    -            res := make([]string, n)
    -            for i := range res {
    -                res[i] = commas
    -            }
    -            adversarialACRH = res
    -        }
    -        
    -

    Details

    -

    Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its intended and legitimate users.

    -

    Unlike other vulnerabilities, DoS attacks usually do not aim at breaching security. Rather, they are focused on making websites and services unavailable to genuine users resulting in downtime.

    -

    One popular Denial of Service vulnerability is DDoS (a Distributed Denial of Service), an attack that attempts to clog network pipes to the system by generating a large volume of traffic from many machines.

    -

    When it comes to open source libraries, DoS vulnerabilities allow attackers to trigger such a crash or crippling of the service by using a flaw either in the application code or from the use of open source libraries.

    -

    Two common types of DoS vulnerabilities:

    -
      -
    • High CPU/Memory Consumption- An attacker sending crafted requests that could cause the system to take a disproportionate amount of time to process. For example, commons-fileupload:commons-fileupload.

      -
    • -
    • Crash - An attacker sending crafted requests that could cause the system to crash. For Example, npm ws package

      -
    • -
    -

    Remediation

    -

    Upgrade github.com/rs/cors to version 1.11.0 or higher.

    -

    References

    - - -
    - - - -
  • -
    -

    Insertion of Sensitive Information into Log File

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd -
    • -
    • - Package Manager: golang -
    • -
    • - Vulnerable module: - - github.com/hashicorp/go-retryablehttp -
    • - -
    • Introduced through: - - github.com/argoproj/argo-cd/v2@* and github.com/hashicorp/go-retryablehttp@v0.7.4 - -
    • -
    - -
    - - -

    Detailed paths

    - -
    -
    -

    CVE-2023-4039

    +
    +

    Uncontrolled Recursion

    -
    - medium severity +
    + low severity

    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
    • Package Manager: ubuntu:22.04 @@ -2006,12 +1707,12 @@

      CVE-2023-4039

    • Vulnerable module: - gcc-12/libstdc++6 + pcre3/libpcre3
    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 + docker-image|quay.io/argoproj/argocd@v2.10.17 and pcre3/libpcre3@2:8.39-13ubuntu0.22.04.1
    @@ -2024,51 +1725,20 @@

    Detailed paths

    -
    +

    Integer Overflow or Wraparound

    -
    - medium severity +
    + low severity

    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
    • Package Manager: ubuntu:22.04 @@ -2131,13 +1795,13 @@

      Integer Overflow or Wraparound

    • Vulnerable module: - expat/libexpat1 + pcre2/libpcre2-8-0
    • Introduced through: + docker-image|quay.io/argoproj/argocd@v2.10.17 and pcre2/libpcre2-8-0@10.39-3ubuntu0.1 - docker-image|quay.io/argoproj/argocd@v2.10.16, git@1:2.34.1-1ubuntu1.11 and others
    @@ -2149,11 +1813,9 @@

    Detailed paths

    -
    -

    XML External Entity (XXE) Injection

    +
    +

    Release of Invalid Pointer or Reference

    -
    - medium severity +
    + low severity

    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
    • Package Manager: ubuntu:22.04 @@ -2204,13 +1866,13 @@

      XML External Entity (XXE) Injection

    • Vulnerable module: - expat/libexpat1 + patch
    • Introduced through: + docker-image|quay.io/argoproj/argocd@v2.10.17 and patch@2.7.6-7build2 - docker-image|quay.io/argoproj/argocd@v2.10.16, git@1:2.34.1-1ubuntu1.11 and others
    @@ -2222,11 +1884,9 @@

    Detailed paths

    -
    -

    Integer Overflow or Wraparound

    +
    +

    Double Free

    -
    - medium severity +
    + low severity

    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
    • Package Manager: ubuntu:22.04 @@ -2277,13 +1936,13 @@

      Integer Overflow or Wraparound

    • Vulnerable module: - expat/libexpat1 + patch
    • Introduced through: + docker-image|quay.io/argoproj/argocd@v2.10.17 and patch@2.7.6-7build2 - docker-image|quay.io/argoproj/argocd@v2.10.16, git@1:2.34.1-1ubuntu1.11 and others
    @@ -2295,11 +1954,9 @@

    Detailed paths

    -
    -

    Out-of-bounds Read

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - curl/libcurl3-gnutls -
    • - -
    • Introduced through: - - - docker-image|quay.io/argoproj/argocd@v2.10.16, git@1:2.34.1-1ubuntu1.11 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream curl package and not the curl package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    libcurl's ASN1 parser code has the GTime2str() function, used for parsing an - ASN.1 Generalized Time field. If given an syntactically incorrect field, the - parser might end up using -1 for the length of the time fraction, leading to - a strlen() getting performed on a pointer to a heap buffer area that is not - (purposely) null terminated.

    -

    This flaw most likely leads to a crash, but can also lead to heap contents - getting returned to the application when - CURLINFO_CERTINFO is used.

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 curl to version 7.81.0-1ubuntu1.17 or higher.

    -

    References

    - - -
    - - - -
    -
    -

    CVE-2024-8096

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - curl/libcurl3-gnutls -
    • - -
    • Introduced through: - - - docker-image|quay.io/argoproj/argocd@v2.10.16, git@1:2.34.1-1ubuntu1.11 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream curl package and not the curl package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    When curl is told to use the Certificate Status Request TLS extension, often referred to as OCSP stapling, to verify that the server certificate is valid, it might fail to detect some OCSP problems and instead wrongly consider the response as fine. If the returned status reports another error than 'revoked' (like for example 'unauthorized') it is not treated as a bad certficate.

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 curl to version 7.81.0-1ubuntu1.18 or higher.

    -

    References

    - - -
    - - - -
    -
    -

    CVE-2023-7008

    -
    - -
    - low severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - systemd/libsystemd0 -
    • - -
    • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.10.16 and systemd/libsystemd0@249.11-0ubuntu3.12 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - systemd/libsystemd0@249.11-0ubuntu3.12 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - apt@2.4.12 - โ€บ - systemd/libsystemd0@249.11-0ubuntu3.12 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - procps/libprocps8@2:3.3.17-6ubuntu2.1 - โ€บ - systemd/libsystemd0@249.11-0ubuntu3.12 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - util-linux@2.37.2-4ubuntu3.4 - โ€บ - systemd/libsystemd0@249.11-0ubuntu3.12 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - util-linux/bsdutils@1:2.37.2-4ubuntu3.4 - โ€บ - systemd/libsystemd0@249.11-0ubuntu3.12 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - apt@2.4.12 - โ€บ - apt/libapt-pkg6.0@2.4.12 - โ€บ - systemd/libsystemd0@249.11-0ubuntu3.12 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - systemd/libudev1@249.11-0ubuntu3.12 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - libfido2/libfido2-1@1.10.0-1 - โ€บ - systemd/libudev1@249.11-0ubuntu3.12 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - util-linux@2.37.2-4ubuntu3.4 - โ€บ - systemd/libudev1@249.11-0ubuntu3.12 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - apt@2.4.12 - โ€บ - apt/libapt-pkg6.0@2.4.12 - โ€บ - systemd/libudev1@249.11-0ubuntu3.12 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream systemd package and not the systemd package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    A vulnerability was found in systemd-resolved. This issue may allow systemd-resolved to accept records of DNSSEC-signed domains even when they have no signature, allowing man-in-the-middles (or the upstream DNS resolver) to manipulate records.

    -

    Remediation

    -

    There is no fixed version for Ubuntu:22.04 systemd.

    -

    References

    - - -
    - - - -
    -
    -

    Arbitrary Code Injection

    -
    - -
    - low severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - shadow/passwd -
    • - -
    • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.10.16 and shadow/passwd@1:4.8.1-2ubuntu2.2 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssh/openssh-client@1:8.9p1-3ubuntu0.10 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - shadow/login@1:4.8.1-2ubuntu2.2 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream shadow package and not the shadow package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    In Shadow 4.13, it is possible to inject control characters into fields provided to the SUID program chfn (change finger). Although it is not possible to exploit this directly (e.g., adding a new user fails because \n is in the block list), it is possible to misrepresent the /etc/passwd file when viewed. Use of \r manipulations and Unicode characters to work around blocking of the : character make it possible to give the impression that a new user has been added. In other words, an adversary may be able to convince a system administrator to take the system offline (an indirect, social-engineered denial of service) by demonstrating that "cat /etc/passwd" shows a rogue user account.

    -

    Remediation

    -

    There is no fixed version for Ubuntu:22.04 shadow.

    -

    References

    - - -
    - - - -
    -
    -

    Uncontrolled Recursion

    -
    - -
    - low severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - pcre3/libpcre3 -
    • - -
    • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.10.16 and pcre3/libpcre3@2:8.39-13ubuntu0.22.04.1 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - pcre3/libpcre3@2:8.39-13ubuntu0.22.04.1 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - grep@3.7-1build1 - โ€บ - pcre3/libpcre3@2:8.39-13ubuntu0.22.04.1 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream pcre3 package and not the pcre3 package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    In PCRE 8.41, the OP_KETRMAX feature in the match function in pcre_exec.c allows stack exhaustion (uncontrolled recursion) when processing a crafted regular expression.

    -

    Remediation

    -

    There is no fixed version for Ubuntu:22.04 pcre3.

    -

    References

    - - -
    - - - -
    -
    -

    Release of Invalid Pointer or Reference

    -
    - -
    - low severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - patch -
    • - -
    • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.10.16 and patch@2.7.6-7build2 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - patch@2.7.6-7build2 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream patch package and not the patch package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    An Invalid Pointer vulnerability exists in GNU patch 2.7 via the another_hunk function, which causes a Denial of Service.

    -

    Remediation

    -

    There is no fixed version for Ubuntu:22.04 patch.

    -

    References

    - - -
    - - - -
    -
    -

    Double Free

    -
    - -
    - low severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - patch -
    • - -
    • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.10.16 and patch@2.7.6-7build2 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - patch@2.7.6-7build2 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream patch package and not the patch package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    A double free exists in the another_hunk function in pch.c in GNU patch through 2.7.6.

    -

    Remediation

    -

    There is no fixed version for Ubuntu:22.04 patch.

    -

    References

    - - -
    - - - -
    -
    -

    CVE-2024-2511

    -
    - -
    - low severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - openssl/libssl3 -
    • - -
    • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.10.16 and openssl/libssl3@3.0.2-0ubuntu1.16 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - cyrus-sasl2/libsasl2-modules@2.1.27+dfsg2-3ubuntu1.2 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - libfido2/libfido2-1@1.10.0-1 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssh/openssh-client@1:8.9p1-3ubuntu0.10 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - ca-certificates@20230311ubuntu0.22.04.1 - โ€บ - openssl@3.0.2-0ubuntu1.16 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 - โ€บ - libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssl@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - ca-certificates@20230311ubuntu0.22.04.1 - โ€บ - openssl@3.0.2-0ubuntu1.16 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream openssl package and not the openssl package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    Issue summary: Some non-default TLS server configurations can cause unbounded - memory growth when processing TLSv1.3 sessions

    -

    Impact summary: An attacker may exploit certain server configurations to trigger - unbounded memory growth that would lead to a Denial of Service

    -

    This problem can occur in TLSv1.3 if the non-default SSL_OP_NO_TICKET option is - being used (but not if early_data support is also configured and the default - anti-replay protection is in use). In this case, under certain conditions, the - session cache can get into an incorrect state and it will fail to flush properly - as it fills. The session cache will continue to grow in an unbounded manner. A - malicious client could deliberately create the scenario for this failure to - force a Denial of Service. It may also happen by accident in normal operation.

    -

    This issue only affects TLS servers supporting TLSv1.3. It does not affect TLS - clients.

    -

    The FIPS modules in 3.2, 3.1 and 3.0 are not affected by this issue. OpenSSL - 1.0.2 is also not affected by this issue.

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 openssl to version 3.0.2-0ubuntu1.17 or higher.

    -

    References

    - - -
    - - - -
    -
    -

    CVE-2024-4603

    -
    - -
    - low severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - openssl/libssl3 -
    • - -
    • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.10.16 and openssl/libssl3@3.0.2-0ubuntu1.16 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - cyrus-sasl2/libsasl2-modules@2.1.27+dfsg2-3ubuntu1.2 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - libfido2/libfido2-1@1.10.0-1 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssh/openssh-client@1:8.9p1-3ubuntu0.10 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - ca-certificates@20230311ubuntu0.22.04.1 - โ€บ - openssl@3.0.2-0ubuntu1.16 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 - โ€บ - libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssl@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - ca-certificates@20230311ubuntu0.22.04.1 - โ€บ - openssl@3.0.2-0ubuntu1.16 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream openssl package and not the openssl package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    Issue summary: Checking excessively long DSA keys or parameters may be very - slow.

    -

    Impact summary: Applications that use the functions EVP_PKEY_param_check() - or EVP_PKEY_public_check() to check a DSA public key or DSA parameters may - experience long delays. Where the key or parameters that are being checked - have been obtained from an untrusted source this may lead to a Denial of - Service.

    -

    The functions EVP_PKEY_param_check() or EVP_PKEY_public_check() perform - various checks on DSA parameters. Some of those computations take a long time - if the modulus (p parameter) is too large.

    -

    Trying to use a very large modulus is slow and OpenSSL will not allow using - public keys with a modulus which is over 10,000 bits in length for signature - verification. However the key and parameter check functions do not limit - the modulus size when performing the checks.

    -

    An application that calls EVP_PKEY_param_check() or EVP_PKEY_public_check() - and supplies a key or parameters obtained from an untrusted source could be - vulnerable to a Denial of Service attack.

    -

    These functions are not called by OpenSSL itself on untrusted DSA keys so - only applications that directly call these functions may be vulnerable.

    -

    Also vulnerable are the OpenSSL pkey and pkeyparam command line applications - when using the -check option.

    -

    The OpenSSL SSL/TLS implementation is not affected by this issue.

    -

    The OpenSSL 3.0 and 3.1 FIPS providers are affected by this issue.

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 openssl to version 3.0.2-0ubuntu1.17 or higher.

    -

    References

    - - -
    - - - -
    -
    -

    CVE-2024-4741

    -
    - -
    - low severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - openssl/libssl3 -
    • - -
    • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.10.16 and openssl/libssl3@3.0.2-0ubuntu1.16 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - cyrus-sasl2/libsasl2-modules@2.1.27+dfsg2-3ubuntu1.2 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - libfido2/libfido2-1@1.10.0-1 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssh/openssh-client@1:8.9p1-3ubuntu0.10 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - ca-certificates@20230311ubuntu0.22.04.1 - โ€บ - openssl@3.0.2-0ubuntu1.16 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 - โ€บ - libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssl@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - ca-certificates@20230311ubuntu0.22.04.1 - โ€บ - openssl@3.0.2-0ubuntu1.16 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    This vulnerability has not been analyzed by NVD yet.

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 openssl to version 3.0.2-0ubuntu1.17 or higher.

    -

    References

    - - -
    - - - -
    -
    -

    CVE-2024-5535

    -
    - -
    - low severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - openssl/libssl3 -
    • - -
    • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.10.16 and openssl/libssl3@3.0.2-0ubuntu1.16 - -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - cyrus-sasl2/libsasl2-modules@2.1.27+dfsg2-3ubuntu1.2 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - libfido2/libfido2-1@1.10.0-1 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssh/openssh-client@1:8.9p1-3ubuntu0.10 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - ca-certificates@20230311ubuntu0.22.04.1 - โ€บ - openssl@3.0.2-0ubuntu1.16 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 - โ€บ - libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - adduser@3.118ubuntu5 - โ€บ - shadow/passwd@1:4.8.1-2ubuntu2.2 - โ€บ - pam/libpam-modules@1.4.0-11ubuntu2.4 - โ€บ - libnsl/libnsl2@1.3.0-2build2 - โ€บ - libtirpc/libtirpc3@1.3.2-2ubuntu0.1 - โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 - โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 - โ€บ - openssl/libssl3@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - openssl@3.0.2-0ubuntu1.16 - - - -
    • -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 - โ€บ - ca-certificates@20230311ubuntu0.22.04.1 - โ€บ - openssl@3.0.2-0ubuntu1.16 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream openssl package and not the openssl package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    Issue summary: Calling the OpenSSL API function SSL_select_next_proto with an - empty supported client protocols buffer may cause a crash or memory contents to - be sent to the peer.

    -

    Impact summary: A buffer overread can have a range of potential consequences - such as unexpected application beahviour or a crash. In particular this issue - could result in up to 255 bytes of arbitrary private data from memory being sent - to the peer leading to a loss of confidentiality. However, only applications - that directly call the SSL_select_next_proto function with a 0 length list of - supported client protocols are affected by this issue. This would normally never - be a valid scenario and is typically not under attacker control but may occur by - accident in the case of a configuration or programming error in the calling - application.

    -

    The OpenSSL API function SSL_select_next_proto is typically used by TLS - applications that support ALPN (Application Layer Protocol Negotiation) or NPN - (Next Protocol Negotiation). NPN is older, was never standardised and - is deprecated in favour of ALPN. We believe that ALPN is significantly more - widely deployed than NPN. The SSL_select_next_proto function accepts a list of - protocols from the server and a list of protocols from the client and returns - the first protocol that appears in the server list that also appears in the - client list. In the case of no overlap between the two lists it returns the - first item in the client list. In either case it will signal whether an overlap - between the two lists was found. In the case where SSL_select_next_proto is - called with a zero length client list it fails to notice this condition and - returns the memory immediately following the client list pointer (and reports - that there was no overlap in the lists).

    -

    This function is typically called from a server side application callback for - ALPN or a client side application callback for NPN. In the case of ALPN the list - of protocols supplied by the client is guaranteed by libssl to never be zero in - length. The list of server protocols comes from the application and should never - normally be expected to be of zero length. In this case if the - SSL_select_next_proto function has been called as expected (with the list - supplied by the client passed in the client/client_len parameters), then the - application will not be vulnerable to this issue. If the application has - accidentally been configured with a zero length server list, and has - accidentally passed that zero length server list in the client/client_len - parameters, and has additionally failed to correctly handle a "no overlap" - response (which would normally result in a handshake failure in ALPN) then it - will be vulnerable to this problem.

    -

    In the case of NPN, the protocol permits the client to opportunistically select - a protocol when there is no overlap. OpenSSL returns the first client protocol - in the no overlap case in support of this. The list of client protocols comes - from the application and should never normally be expected to be of zero length. - However if the SSL_select_next_proto function is accidentally called with a - client_len of 0 then an invalid memory pointer will be returned instead. If the - application uses this output as the opportunistic protocol then the loss of - confidentiality will occur.

    -

    This issue has been assessed as Low severity because applications are most - likely to be vulnerable if they are using NPN instead of ALPN - but NPN is not - widely used. It also requires an application configuration or programming error. - Finally, this issue would not typically be under attacker control making active - exploitation unlikely.

    -

    The FIPS modules in 3.3, 3.2, 3.1 and 3.0 are not affected by this issue.

    -

    Due to the low severity of this issue we are not issuing new releases of - OpenSSL at this time. The fix will be included in the next releases when they - become available.

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 openssl to version 3.0.2-0ubuntu1.17 or higher.

    -

    References

    - - -
    - -
    @@ -3817,7 +2003,7 @@

    CVE-2023-50495

    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
    • Package Manager: ubuntu:22.04 @@ -3830,7 +2016,7 @@

      CVE-2023-50495

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and ncurses/libtinfo6@6.3-2ubuntu0.1 + docker-image|quay.io/argoproj/argocd@v2.10.17 and ncurses/libtinfo6@6.3-2ubuntu0.1
    @@ -3843,7 +2029,7 @@

    Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/libtinfo6@6.3-2ubuntu0.1 @@ -3852,7 +2038,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ bash@5.1-6ubuntu1.1 โ€บ @@ -3863,7 +2049,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/libncursesw6@6.3-2ubuntu0.1 โ€บ @@ -3874,7 +2060,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ less@590-1ubuntu0.22.04.3 โ€บ @@ -3885,7 +2071,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ libedit/libedit2@3.1-20210910-1build1 โ€บ @@ -3896,7 +2082,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/libncurses6@6.3-2ubuntu0.1 โ€บ @@ -3907,7 +2093,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/ncurses-bin@6.3-2ubuntu0.1 โ€บ @@ -3918,7 +2104,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -3929,7 +2115,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ util-linux@2.37.2-4ubuntu3.4 โ€บ @@ -3940,7 +2126,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 โ€บ @@ -3955,7 +2141,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3970,7 +2156,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/libncursesw6@6.3-2ubuntu0.1 @@ -3979,7 +2165,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -3990,7 +2176,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -4005,7 +2191,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/libncurses6@6.3-2ubuntu0.1 @@ -4014,7 +2200,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -4025,7 +2211,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/ncurses-base@6.3-2ubuntu0.1 @@ -4034,7 +2220,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/ncurses-bin@6.3-2ubuntu0.1 @@ -4081,7 +2267,7 @@

      CVE-2023-45918

      • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
      • Package Manager: ubuntu:22.04 @@ -4094,7 +2280,7 @@

        CVE-2023-45918

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and ncurses/libtinfo6@6.3-2ubuntu0.1 + docker-image|quay.io/argoproj/argocd@v2.10.17 and ncurses/libtinfo6@6.3-2ubuntu0.1
      @@ -4107,7 +2293,7 @@

      Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/libtinfo6@6.3-2ubuntu0.1 @@ -4116,7 +2302,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ bash@5.1-6ubuntu1.1 โ€บ @@ -4127,7 +2313,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/libncursesw6@6.3-2ubuntu0.1 โ€บ @@ -4138,7 +2324,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ less@590-1ubuntu0.22.04.3 โ€บ @@ -4149,7 +2335,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ libedit/libedit2@3.1-20210910-1build1 โ€บ @@ -4160,7 +2346,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/libncurses6@6.3-2ubuntu0.1 โ€บ @@ -4171,7 +2357,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/ncurses-bin@6.3-2ubuntu0.1 โ€บ @@ -4182,7 +2368,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -4193,7 +2379,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ util-linux@2.37.2-4ubuntu3.4 โ€บ @@ -4204,7 +2390,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 โ€บ @@ -4219,7 +2405,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -4234,7 +2420,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/libncursesw6@6.3-2ubuntu0.1 @@ -4243,7 +2429,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -4254,7 +2440,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -4269,7 +2455,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/libncurses6@6.3-2ubuntu0.1 @@ -4278,7 +2464,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -4289,7 +2475,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/ncurses-base@6.3-2ubuntu0.1 @@ -4298,7 +2484,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ ncurses/ncurses-bin@6.3-2ubuntu0.1 @@ -4343,7 +2529,7 @@

        Resource Exhaustion

        • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
        • Package Manager: ubuntu:22.04 @@ -4356,7 +2542,7 @@

          Resource Exhaustion

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and libzstd/libzstd1@1.4.8+dfsg-3build1 + docker-image|quay.io/argoproj/argocd@v2.10.17 and libzstd/libzstd1@1.4.8+dfsg-3build1
        @@ -4369,7 +2555,7 @@

        Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ libzstd/libzstd1@1.4.8+dfsg-3build1 @@ -4420,7 +2606,7 @@

          Integer Overflow or Wraparound

          • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
          • Package Manager: ubuntu:22.04 @@ -4433,7 +2619,7 @@

            Integer Overflow or Wraparound

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and krb5/libk5crypto3@1.19.2-2ubuntu0.3 + docker-image|quay.io/argoproj/argocd@v2.10.17 and krb5/libk5crypto3@1.19.2-2ubuntu0.4
          @@ -4446,16 +2632,16 @@

          Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4467,16 +2653,16 @@

            Detailed paths

            โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4488,27 +2674,27 @@

            Detailed paths

            โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4
          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4520,64 +2706,64 @@

            Detailed paths

            โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4
          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4589,16 +2775,16 @@

            Detailed paths

            โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libkrb5support0@1.19.2-2ubuntu0.3 + krb5/libkrb5support0@1.19.2-2ubuntu0.4 @@ -4644,7 +2830,7 @@

            CVE-2024-26461

            • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
            • Package Manager: ubuntu:22.04 @@ -4657,7 +2843,7 @@

              CVE-2024-26461

            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and krb5/libk5crypto3@1.19.2-2ubuntu0.3 + docker-image|quay.io/argoproj/argocd@v2.10.17 and krb5/libk5crypto3@1.19.2-2ubuntu0.4
            @@ -4670,16 +2856,16 @@

            Detailed paths

            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4691,16 +2877,16 @@

              Detailed paths

              โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4712,27 +2898,27 @@

              Detailed paths

              โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4
            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4744,64 +2930,64 @@

              Detailed paths

              โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4
            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4813,16 +2999,16 @@

              Detailed paths

              โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libkrb5support0@1.19.2-2ubuntu0.3 + krb5/libkrb5support0@1.19.2-2ubuntu0.4 @@ -4865,7 +3051,7 @@

              CVE-2024-26458

              • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
              • Package Manager: ubuntu:22.04 @@ -4878,7 +3064,7 @@

                CVE-2024-26458

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and krb5/libk5crypto3@1.19.2-2ubuntu0.3 + docker-image|quay.io/argoproj/argocd@v2.10.17 and krb5/libk5crypto3@1.19.2-2ubuntu0.4
              @@ -4891,16 +3077,16 @@

              Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4912,16 +3098,16 @@

                Detailed paths

                โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4933,27 +3119,27 @@

                Detailed paths

                โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4 โ€บ - krb5/libk5crypto3@1.19.2-2ubuntu0.3 + krb5/libk5crypto3@1.19.2-2ubuntu0.4
              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4
              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -4965,64 +3151,64 @@

                Detailed paths

                โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 โ€บ - krb5/libkrb5-3@1.19.2-2ubuntu0.3 + krb5/libkrb5-3@1.19.2-2ubuntu0.4
              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.16 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ adduser@3.118ubuntu5 โ€บ @@ -5034,16 +3220,16 @@

                Detailed paths

                โ€บ libtirpc/libtirpc3@1.3.2-2ubuntu0.1 โ€บ - krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.3 + krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4
              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - krb5/libkrb5support0@1.19.2-2ubuntu0.3 + krb5/libkrb5support0@1.19.2-2ubuntu0.4 @@ -5086,7 +3272,7 @@

                Out-of-bounds Write

                • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
                • Package Manager: ubuntu:22.04 @@ -5099,7 +3285,7 @@

                  Out-of-bounds Write

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and gnupg2/gpgv@2.2.27-3ubuntu2.1 + docker-image|quay.io/argoproj/argocd@v2.10.17 and gnupg2/gpgv@2.2.27-3ubuntu2.1
                @@ -5112,7 +3298,7 @@

                Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpgv@2.2.27-3ubuntu2.1 @@ -5121,9 +3307,9 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - apt@2.4.12 + apt@2.4.13 โ€บ gnupg2/gpgv@2.2.27-3ubuntu2.1 @@ -5132,7 +3318,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5143,7 +3329,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/dirmngr@2.2.27-3ubuntu2.1 โ€บ @@ -5154,7 +3340,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 โ€บ @@ -5165,7 +3351,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5178,7 +3364,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5191,7 +3377,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/dirmngr@2.2.27-3ubuntu2.1 @@ -5200,7 +3386,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5211,7 +3397,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5224,7 +3410,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg-l10n@2.2.27-3ubuntu2.1 @@ -5233,7 +3419,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5244,7 +3430,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg-utils@2.2.27-3ubuntu2.1 @@ -5253,7 +3439,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5264,7 +3450,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 @@ -5273,7 +3459,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5284,7 +3470,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5297,7 +3483,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5310,7 +3496,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpg-agent@2.2.27-3ubuntu2.1 @@ -5319,7 +3505,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5330,7 +3516,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5343,7 +3529,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5356,7 +3542,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpg-wks-client@2.2.27-3ubuntu2.1 @@ -5365,7 +3551,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5376,7 +3562,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpg-wks-server@2.2.27-3ubuntu2.1 @@ -5385,7 +3571,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5396,7 +3582,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gpgsm@2.2.27-3ubuntu2.1 @@ -5405,7 +3591,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -5416,7 +3602,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 @@ -5465,7 +3651,7 @@

                  Allocation of Resources Without Limits or Throttling

                • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
                • Package Manager: ubuntu:22.04 @@ -5478,7 +3664,7 @@

                  Allocation of Resources Without Limits or Throttling

                  Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and glibc/libc-bin@2.35-0ubuntu3.8 + docker-image|quay.io/argoproj/argocd@v2.10.17 and glibc/libc-bin@2.35-0ubuntu3.8
                @@ -5491,7 +3677,7 @@

                Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ glibc/libc-bin@2.35-0ubuntu3.8 @@ -5500,7 +3686,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ glibc/libc6@2.35-0ubuntu3.8 @@ -5546,7 +3732,7 @@

                  Improper Input Validation

                  • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
                  • Package Manager: ubuntu:22.04 @@ -5560,7 +3746,7 @@

                    Improper Input Validation

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16, git@1:2.34.1-1ubuntu1.11 and others + docker-image|quay.io/argoproj/argocd@v2.10.17, git@1:2.34.1-1ubuntu1.11 and others
                  @@ -5572,7 +3758,7 @@

                  Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ @@ -5583,7 +3769,7 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git@1:2.34.1-1ubuntu1.11 @@ -5592,7 +3778,7 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ git-lfs@3.0.2-1ubuntu0.2 โ€บ @@ -5639,7 +3825,7 @@

                    Uncontrolled Recursion

                    • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
                    • Package Manager: ubuntu:22.04 @@ -5652,7 +3838,7 @@

                      Uncontrolled Recursion

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 + docker-image|quay.io/argoproj/argocd@v2.10.17 and gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04
                    @@ -5665,7 +3851,7 @@

                    Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 @@ -5674,9 +3860,9 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - apt@2.4.12 + apt@2.4.13 โ€บ gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 @@ -5685,11 +3871,11 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ - apt@2.4.12 + apt@2.4.13 โ€บ - apt/libapt-pkg6.0@2.4.12 + apt/libapt-pkg6.0@2.4.13 โ€บ gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 @@ -5698,7 +3884,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gcc-12/gcc-12-base@12.3.0-1ubuntu1~22.04 @@ -5707,7 +3893,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ gcc-12/libgcc-s1@12.3.0-1ubuntu1~22.04 @@ -5754,7 +3940,7 @@

                      Improper Input Validation

                      • - Manifest file: quay.io/argoproj/argocd:v2.10.16/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.10.17/argoproj/argocd โ€บ Dockerfile
                      • Package Manager: ubuntu:22.04 @@ -5767,7 +3953,7 @@

                        Improper Input Validation

                      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 and coreutils@8.32-4.1ubuntu1.2 + docker-image|quay.io/argoproj/argocd@v2.10.17 and coreutils@8.32-4.1ubuntu1.2
                      @@ -5780,7 +3966,7 @@

                      Detailed paths

                      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.10.16 + docker-image|quay.io/argoproj/argocd@v2.10.17 โ€บ coreutils@8.32-4.1ubuntu1.2 diff --git a/docs/snyk/v2.10.16/redis_7.0.15-alpine.html b/docs/snyk/v2.10.17/redis_7.0.15-alpine.html similarity index 99% rename from docs/snyk/v2.10.16/redis_7.0.15-alpine.html rename to docs/snyk/v2.10.17/redis_7.0.15-alpine.html index a425e2171384af..c0350a06c2cd3c 100644 --- a/docs/snyk/v2.10.16/redis_7.0.15-alpine.html +++ b/docs/snyk/v2.10.17/redis_7.0.15-alpine.html @@ -456,7 +456,7 @@

                        Snyk test report

                        -

                        September 22nd 2024, 12:28:59 am (UTC+00:00)

                        +

                        October 6th 2024, 12:37:00 am (UTC+00:00)

                        Scanned the following paths: diff --git a/docs/snyk/v2.11.8/argocd-iac-install.html b/docs/snyk/v2.11.9/argocd-iac-install.html similarity index 99% rename from docs/snyk/v2.11.8/argocd-iac-install.html rename to docs/snyk/v2.11.9/argocd-iac-install.html index e3753708b8045d..33cffb4f583679 100644 --- a/docs/snyk/v2.11.8/argocd-iac-install.html +++ b/docs/snyk/v2.11.9/argocd-iac-install.html @@ -456,7 +456,7 @@

                        Snyk test report

                        -

                        September 22nd 2024, 12:28:02 am (UTC+00:00)

                        +

                        October 6th 2024, 12:36:08 am (UTC+00:00)

                        Scanned the following path: diff --git a/docs/snyk/v2.11.8/argocd-iac-namespace-install.html b/docs/snyk/v2.11.9/argocd-iac-namespace-install.html similarity index 99% rename from docs/snyk/v2.11.8/argocd-iac-namespace-install.html rename to docs/snyk/v2.11.9/argocd-iac-namespace-install.html index 1e254b4038b83a..f1dbfff0059b3b 100644 --- a/docs/snyk/v2.11.8/argocd-iac-namespace-install.html +++ b/docs/snyk/v2.11.9/argocd-iac-namespace-install.html @@ -456,7 +456,7 @@

                        Snyk test report

                        -

                        September 22nd 2024, 12:28:10 am (UTC+00:00)

                        +

                        October 6th 2024, 12:36:17 am (UTC+00:00)

                        Scanned the following path: diff --git a/docs/snyk/v2.11.8/argocd-test.html b/docs/snyk/v2.11.9/argocd-test.html similarity index 90% rename from docs/snyk/v2.11.8/argocd-test.html rename to docs/snyk/v2.11.9/argocd-test.html index ed53a51bfbfd9d..0c5b32a0188081 100644 --- a/docs/snyk/v2.11.8/argocd-test.html +++ b/docs/snyk/v2.11.9/argocd-test.html @@ -7,7 +7,7 @@ Snyk test report - + @@ -456,7 +456,7 @@

                        Snyk test report

                        -

                        September 22nd 2024, 12:26:11 am (UTC+00:00)

                        +

                        October 6th 2024, 12:34:17 am (UTC+00:00)

                        Scanned the following paths: @@ -467,8 +467,8 @@

                        Snyk test report

                        -
                        7 known vulnerabilities
                        -
                        158 vulnerable dependency paths
                        +
                        4 known vulnerabilities
                        +
                        153 vulnerable dependency paths
                        2041 dependencies
                        @@ -3139,329 +3139,6 @@

                        References

                        More about this vulnerability

                        -
                        -
                        -

                        Prototype Pollution

                        -
                        - -
                        - high severity -
                        - -
                        - -
                          -
                        • - Manifest file: /argo-cd โ€บ ui/yarn.lock -
                        • -
                        • - Package Manager: npm -
                        • -
                        • - Vulnerable module: - - dompurify -
                        • - -
                        • Introduced through: - - - argo-cd-ui@1.0.0, redoc@2.0.0-rc.64 and others -
                        • -
                        - -
                        - - -

                        Detailed paths

                        - -
                          -
                        • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - redoc@2.0.0-rc.64 - โ€บ - dompurify@2.3.6 - - - -
                        • -
                        - -
                        - -
                        - -

                        Overview

                        -

                        dompurify is a DOM-only XSS sanitizer for HTML, MathML and SVG.

                        -

                        Affected versions of this package are vulnerable to Prototype Pollution due to improper user input sanitization through the depth-checking mechanism, an attacker can exploit this vulnerability by using special nesting techniques to create a malicious HTML file.

                        -

                        Details

                        -

                        Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as __proto__, constructor and prototype. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.

                        -

                        There are two main ways in which the pollution of prototypes occurs:

                        -
                          -
                        • Unsafe Object recursive merge

                          -
                        • -
                        • Property definition by path

                          -
                        • -
                        -

                        Unsafe Object recursive merge

                        -

                        The logic of a vulnerable recursive merge function follows the following high-level model:

                        -
                        merge (target, source)
                        -        
                        -          foreach property of source
                        -        
                        -            if property exists and is an object on both the target and the source
                        -        
                        -              merge(target[property], source[property])
                        -        
                        -            else
                        -        
                        -              target[property] = source[property]
                        -        
                        -
                        - -

                        When the source object contains a property named __proto__ defined with Object.defineProperty() , the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object and the source of Object as defined by the attacker. Properties are then copied on the Object prototype.

                        -

                        Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source).

                        -

                        lodash and Hoek are examples of libraries susceptible to recursive merge attacks.

                        -

                        Property definition by path

                        -

                        There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)

                        -

                        If the attacker can control the value of โ€œpathโ€, they can set this value to __proto__.myValue. myValue is then assigned to the prototype of the class of the object.

                        -

                        Types of attacks

                        -

                        There are a few methods by which Prototype Pollution can be manipulated:

                        - - - - - - - - - - - - - - - - - - - - - - - -
                        TypeOriginShort description
                        Denial of service (DoS)ClientThis is the most likely attack.
                        DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf).
                        The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object. In this case, the code fails and is likely to cause a denial of service.
                        For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail.
                        Remote Code ExecutionClientRemote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation.
                        For example: eval(someobject.someattr). In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code.
                        Property InjectionClientThe attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens.
                        For example: if a codebase checks privileges for someuser.isAdmin, then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true, they can then achieve admin privileges.
                        -

                        Affected environments

                        -

                        The following environments are susceptible to a Prototype Pollution attack:

                        -
                          -
                        • Application server

                          -
                        • -
                        • Web server

                          -
                        • -
                        • Web browser

                          -
                        • -
                        -

                        How to prevent

                        -
                          -
                        1. Freeze the prototypeโ€” use Object.freeze (Object.prototype).

                          -
                        2. -
                        3. Require schema validation of JSON input.

                          -
                        4. -
                        5. Avoid using unsafe recursive merge functions.

                          -
                        6. -
                        7. Consider using objects without prototypes (for example, Object.create(null)), breaking the prototype chain and preventing pollution.

                          -
                        8. -
                        9. As a best practice use Map instead of Object.

                          -
                        10. -
                        -

                        For more information on this vulnerability type:

                        -

                        Arteau, Oliver. โ€œJavaScript prototype pollution attack in NodeJS application.โ€ GitHub, 26 May 2018

                        -

                        Remediation

                        -

                        Upgrade dompurify to version 2.5.4, 3.1.3 or higher.

                        -

                        References

                        - - -
                        - - - -
                        -
                        -

                        Regular Expression Denial of Service (ReDoS)

                        -
                        - -
                        - medium severity -
                        - -
                        - -
                          -
                        • - Manifest file: /argo-cd โ€บ ui/yarn.lock -
                        • -
                        • - Package Manager: npm -
                        • -
                        • - Vulnerable module: - - path-to-regexp -
                        • - -
                        • Introduced through: - - - argo-cd-ui@1.0.0, react-router@4.3.1 and others -
                        • -
                        - -
                        - - -

                        Detailed paths

                        - -
                          -
                        • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
                        • -
                        • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - react-router-dom@4.3.1 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
                        • -
                        • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - argo-ui@1.0.0 - โ€บ - react-router-dom@4.3.1 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
                        • -
                        - -
                        - -
                        - -

                        Overview

                        -

                        Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) when including multiple regular expression parameters in a single segment, which will produce the regular expression /^\/([^\/]+?)-([^\/]+?)\/?$/, if two parameters within a single segment are separated by a character other than a / or .. Poor performance will block the event loop and can lead to a DoS.

                        -

                        Note: - While the 8.0.0 release has completely eliminated the vulnerable functionality, prior versions that have received the patch to mitigate backtracking may still be vulnerable if custom regular expressions are used. So it is strongly recommended for regular expression input to be controlled to avoid malicious performance degradation in those versions. This behavior is enforced as of version 7.1.0 via the strict option, which returns an error if a dangerous regular expression is detected.

                        -

                        Workaround

                        -

                        This vulnerability can be avoided by using a custom regular expression for parameters after the first in a segment, which excludes - and /.

                        -

                        PoC

                        -
                        /a${'-a'.repeat(8_000)}/a
                        -        
                        -

                        Details

                        -

                        Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.

                        -

                        The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.

                        -

                        Letโ€™s take the following regular expression as an example:

                        -
                        regex = /A(B|C+)+D/
                        -        
                        -

                        This regular expression accomplishes the following:

                        -
                          -
                        • A The string must start with the letter 'A'
                        • -
                        • (B|C+)+ The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the + matches one or more times). The + at the end of this section states that we can look for one or more matches of this section.
                        • -
                        • D Finally, we ensure this section of the string ends with a 'D'
                        • -
                        -

                        The expression would match inputs such as ABBD, ABCCCCD, ABCBCCCD and ACCCCCD

                        -

                        It most cases, it doesn't take very long for a regex engine to find a match:

                        -
                        $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
                        -        0.04s user 0.01s system 95% cpu 0.052 total
                        -        
                        -        $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
                        -        1.79s user 0.02s system 99% cpu 1.812 total
                        -        
                        -

                        The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.

                        -

                        Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesnโ€™t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.

                        -

                        Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:

                        -
                          -
                        1. CCC
                        2. -
                        3. CC+C
                        4. -
                        5. C+CC
                        6. -
                        7. C+C+C.
                        8. -
                        -

                        The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.

                        -

                        From there, the number of steps the engine must use to validate a string just continues to grow.

                        - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                        StringNumber of C'sNumber of steps
                        ACCCX338
                        ACCCCX471
                        ACCCCCX5136
                        ACCCCCCCCCCCCCCX1465,553
                        -

                        By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.

                        -

                        Remediation

                        -

                        Upgrade path-to-regexp to version 0.1.10, 1.9.0, 3.3.0, 6.3.0, 8.0.0 or higher.

                        -

                        References

                        - - -
                        - - -

                        Denial of Service (DoS)

                        @@ -3889,81 +3566,6 @@

                        References

    -
    -

    Template Injection

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: /argo-cd โ€บ ui/yarn.lock -
    • -
    • - Package Manager: npm -
    • -
    • - Vulnerable module: - - dompurify -
    • - -
    • Introduced through: - - - argo-cd-ui@1.0.0, redoc@2.0.0-rc.64 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - redoc@2.0.0-rc.64 - โ€บ - dompurify@2.3.6 - - - -
    • -
    - -
    - -
    - -

    Overview

    -

    dompurify is a DOM-only XSS sanitizer for HTML, MathML and SVG.

    -

    Affected versions of this package are vulnerable to Template Injection in purify.js, due to inconsistencies in the parsing of XML and HTML tags. Executable code can be injected in HTML inside XML CDATA blocks.

    -

    PoC

    -
    <![CDATA[ ><img src onerror=alert(1)> ]]>
    -        
    -

    Remediation

    -

    Upgrade dompurify to version 2.4.9, 3.0.11 or higher.

    -

    References

    - - -
    - - - -
    diff --git a/docs/snyk/v2.11.8/ghcr.io_dexidp_dex_v2.38.0.html b/docs/snyk/v2.11.9/ghcr.io_dexidp_dex_v2.38.0.html similarity index 99% rename from docs/snyk/v2.11.8/ghcr.io_dexidp_dex_v2.38.0.html rename to docs/snyk/v2.11.9/ghcr.io_dexidp_dex_v2.38.0.html index 3c41c7b5408800..2ba4925c88a940 100644 --- a/docs/snyk/v2.11.8/ghcr.io_dexidp_dex_v2.38.0.html +++ b/docs/snyk/v2.11.9/ghcr.io_dexidp_dex_v2.38.0.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:26:16 am (UTC+00:00)

    +

    October 6th 2024, 12:34:22 am (UTC+00:00)

    Scanned the following paths: diff --git a/docs/snyk/v2.10.16/haproxy_2.6.14-alpine.html b/docs/snyk/v2.11.9/haproxy_2.6.14-alpine.html similarity index 99% rename from docs/snyk/v2.10.16/haproxy_2.6.14-alpine.html rename to docs/snyk/v2.11.9/haproxy_2.6.14-alpine.html index 9020dc61d54b12..60e21725f8ee9e 100644 --- a/docs/snyk/v2.10.16/haproxy_2.6.14-alpine.html +++ b/docs/snyk/v2.11.9/haproxy_2.6.14-alpine.html @@ -456,7 +456,7 @@

    Snyk test report

    -

    September 22nd 2024, 12:28:38 am (UTC+00:00)

    +

    October 6th 2024, 12:34:27 am (UTC+00:00)

    Scanned the following path: diff --git a/docs/snyk/v2.11.8/quay.io_argoproj_argocd_v2.11.8.html b/docs/snyk/v2.11.9/quay.io_argoproj_argocd_v2.11.9.html similarity index 91% rename from docs/snyk/v2.11.8/quay.io_argoproj_argocd_v2.11.8.html rename to docs/snyk/v2.11.9/quay.io_argoproj_argocd_v2.11.9.html index 0a77724bd22380..12085ea08de137 100644 --- a/docs/snyk/v2.11.8/quay.io_argoproj_argocd_v2.11.8.html +++ b/docs/snyk/v2.11.9/quay.io_argoproj_argocd_v2.11.9.html @@ -7,7 +7,7 @@ Snyk test report - + @@ -456,22 +456,22 @@

    Snyk test report

    -

    September 22nd 2024, 12:26:39 am (UTC+00:00)

    +

    October 6th 2024, 12:34:45 am (UTC+00:00)

    Scanned the following paths:
      -
    • quay.io/argoproj/argocd:v2.11.8/argoproj/argocd/Dockerfile (deb)
    • -
    • quay.io/argoproj/argocd:v2.11.8/argoproj/argo-cd/v2//usr/local/bin/argocd (gomodules)
    • -
    • quay.io/argoproj/argocd:v2.11.8//usr/local/bin/kustomize (gomodules)
    • -
    • quay.io/argoproj/argocd:v2.11.8/helm/v3//usr/local/bin/helm (gomodules)
    • -
    • quay.io/argoproj/argocd:v2.11.8/git-lfs/git-lfs//usr/bin/git-lfs (gomodules)
    • +
    • quay.io/argoproj/argocd:v2.11.9/argoproj/argocd/Dockerfile (deb)
    • +
    • quay.io/argoproj/argocd:v2.11.9/argoproj/argo-cd/v2//usr/local/bin/argocd (gomodules)
    • +
    • quay.io/argoproj/argocd:v2.11.9//usr/local/bin/kustomize (gomodules)
    • +
    • quay.io/argoproj/argocd:v2.11.9/helm/v3//usr/local/bin/helm (gomodules)
    • +
    • quay.io/argoproj/argocd:v2.11.9/git-lfs/git-lfs//usr/bin/git-lfs (gomodules)
    -
    27 known vulnerabilities
    -
    173 vulnerable dependency paths
    +
    24 known vulnerabilities
    +
    170 vulnerable dependency paths
    2280 dependencies
    @@ -492,7 +492,7 @@

    Allocation of Resources Without Limits or Throttling

  • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd
  • Package Manager: golang @@ -572,7 +572,7 @@

    CVE-2024-41996

    • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
    • Package Manager: ubuntu:22.04 @@ -585,7 +585,7 @@

      CVE-2024-41996

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and openssl/libssl3@3.0.2-0ubuntu1.18 + docker-image|quay.io/argoproj/argocd@v2.11.9 and openssl/libssl3@3.0.2-0ubuntu1.18
    @@ -598,7 +598,7 @@

    Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ openssl/libssl3@3.0.2-0ubuntu1.18 @@ -607,7 +607,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ cyrus-sasl2/libsasl2-modules@2.1.27+dfsg2-3ubuntu1.2 โ€บ @@ -618,7 +618,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ libfido2/libfido2-1@1.10.0-1 โ€บ @@ -629,7 +629,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ @@ -640,9 +640,9 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ - ca-certificates@20230311ubuntu0.22.04.1 + ca-certificates@20240203~22.04.1 โ€บ openssl@3.0.2-0ubuntu1.18 โ€บ @@ -653,11 +653,11 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.17 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 โ€บ @@ -668,7 +668,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -691,7 +691,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ openssl@3.0.2-0ubuntu1.18 @@ -700,9 +700,9 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ - ca-certificates@20230311ubuntu0.22.04.1 + ca-certificates@20240203~22.04.1 โ€บ openssl@3.0.2-0ubuntu1.18 @@ -748,7 +748,7 @@

      Information Exposure

      • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
      • Package Manager: ubuntu:22.04 @@ -761,7 +761,7 @@

        Information Exposure

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and libgcrypt20@1.9.4-3ubuntu3 + docker-image|quay.io/argoproj/argocd@v2.11.9 and libgcrypt20@1.9.4-3ubuntu3
      @@ -774,7 +774,7 @@

      Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ libgcrypt20@1.9.4-3ubuntu3 @@ -783,7 +783,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/dirmngr@2.2.27-3ubuntu2.1 โ€บ @@ -794,7 +794,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 โ€บ @@ -805,7 +805,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -818,7 +818,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -831,7 +831,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 โ€บ @@ -844,7 +844,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -857,7 +857,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -870,7 +870,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -883,7 +883,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -896,7 +896,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -909,7 +909,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -961,7 +961,7 @@

        CVE-2024-26462

        • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
        • Package Manager: ubuntu:22.04 @@ -974,7 +974,7 @@

          CVE-2024-26462

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and krb5/libk5crypto3@1.19.2-2ubuntu0.4 + docker-image|quay.io/argoproj/argocd@v2.11.9 and krb5/libk5crypto3@1.19.2-2ubuntu0.4
        @@ -987,7 +987,7 @@

        Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libk5crypto3@1.19.2-2ubuntu0.4 @@ -996,7 +996,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -1017,7 +1017,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -1040,7 +1040,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libkrb5-3@1.19.2-2ubuntu0.4 @@ -1049,7 +1049,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -1070,7 +1070,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 @@ -1079,7 +1079,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ @@ -1090,11 +1090,11 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.17 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 @@ -1103,11 +1103,11 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.17 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 โ€บ @@ -1118,7 +1118,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -1137,7 +1137,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libkrb5support0@1.19.2-2ubuntu0.4 @@ -1182,7 +1182,7 @@

          Denial of Service (DoS)

          • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd
          • Package Manager: golang @@ -1292,7 +1292,7 @@

            Insertion of Sensitive Information into Log File

            • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd
            • Package Manager: golang @@ -1360,7 +1360,7 @@

              CVE-2023-4039

              • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
              • Package Manager: ubuntu:22.04 @@ -1373,7 +1373,7 @@

                CVE-2023-4039

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 + docker-image|quay.io/argoproj/argocd@v2.11.9 and gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04
              @@ -1386,7 +1386,7 @@

              Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 @@ -1395,7 +1395,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -1406,7 +1406,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -1419,7 +1419,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gcc-12/gcc-12-base@12.3.0-1ubuntu1~22.04 @@ -1428,7 +1428,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gcc-12/libgcc-s1@12.3.0-1ubuntu1~22.04 @@ -1472,299 +1472,6 @@

                References

                More about this vulnerability

  • -
    -
    -

    Integer Overflow or Wraparound

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - expat/libexpat1 -
    • - -
    • Introduced through: - - - docker-image|quay.io/argoproj/argocd@v2.11.8, git@1:2.34.1-1ubuntu1.11 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - expat/libexpat1@2.4.7-1ubuntu0.3 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream expat package and not the expat package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    An issue was discovered in libexpat before 2.6.3. dtdCopy in xmlparse.c can have an integer overflow for nDefaultAtts on 32-bit platforms (where UINT_MAX equals SIZE_MAX).

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 expat to version 2.4.7-1ubuntu0.4 or higher.

    -

    References

    - - -
    - - - -
    -
    -

    XML External Entity (XXE) Injection

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - expat/libexpat1 -
    • - -
    • Introduced through: - - - docker-image|quay.io/argoproj/argocd@v2.11.8, git@1:2.34.1-1ubuntu1.11 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - expat/libexpat1@2.4.7-1ubuntu0.3 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream expat package and not the expat package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    An issue was discovered in libexpat before 2.6.3. xmlparse.c does not reject a negative length for XML_ParseBuffer.

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 expat to version 2.4.7-1ubuntu0.4 or higher.

    -

    References

    - - -
    - - - -
    -
    -

    Integer Overflow or Wraparound

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - expat/libexpat1 -
    • - -
    • Introduced through: - - - docker-image|quay.io/argoproj/argocd@v2.11.8, git@1:2.34.1-1ubuntu1.11 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - expat/libexpat1@2.4.7-1ubuntu0.3 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream expat package and not the expat package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    An issue was discovered in libexpat before 2.6.3. nextScaffoldPart in xmlparse.c can have an integer overflow for m_groupSize on 32-bit platforms (where UINT_MAX equals SIZE_MAX).

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 expat to version 2.4.7-1ubuntu0.4 or higher.

    -

    References

    - - -
    - - - -
    -
    -

    CVE-2024-8096

    -
    - -
    - medium severity -
    - -
    - -
      -
    • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile -
    • -
    • - Package Manager: ubuntu:22.04 -
    • -
    • - Vulnerable module: - - curl/libcurl3-gnutls -
    • - -
    • Introduced through: - - - docker-image|quay.io/argoproj/argocd@v2.11.8, git@1:2.34.1-1ubuntu1.11 and others -
    • -
    - -
    - - -

    Detailed paths

    - -
      -
    • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 - โ€บ - git@1:2.34.1-1ubuntu1.11 - โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.17 - - - -
    • -
    - -
    - -
    - -

    NVD Description

    -

    Note: Versions mentioned in the description apply only to the upstream curl package and not the curl package as distributed by Ubuntu. - See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    -

    When curl is told to use the Certificate Status Request TLS extension, often referred to as OCSP stapling, to verify that the server certificate is valid, it might fail to detect some OCSP problems and instead wrongly consider the response as fine. If the returned status reports another error than 'revoked' (like for example 'unauthorized') it is not treated as a bad certficate.

    -

    Remediation

    -

    Upgrade Ubuntu:22.04 curl to version 7.81.0-1ubuntu1.18 or higher.

    -

    References

    - - -
    - - -

    CVE-2023-7008

    @@ -1778,7 +1485,7 @@

    CVE-2023-7008

    • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
    • Package Manager: ubuntu:22.04 @@ -1791,7 +1498,7 @@

      CVE-2023-7008

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and systemd/libsystemd0@249.11-0ubuntu3.12 + docker-image|quay.io/argoproj/argocd@v2.11.9 and systemd/libsystemd0@249.11-0ubuntu3.12
    @@ -1804,7 +1511,7 @@

    Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ systemd/libsystemd0@249.11-0ubuntu3.12 @@ -1813,7 +1520,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -1824,7 +1531,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ procps/libprocps8@2:3.3.17-6ubuntu2.1 โ€บ @@ -1835,7 +1542,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ util-linux@2.37.2-4ubuntu3.4 โ€บ @@ -1846,7 +1553,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ util-linux/bsdutils@1:2.37.2-4ubuntu3.4 โ€บ @@ -1857,7 +1564,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -1870,7 +1577,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ systemd/libudev1@249.11-0ubuntu3.12 @@ -1879,7 +1586,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ libfido2/libfido2-1@1.10.0-1 โ€บ @@ -1890,7 +1597,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ util-linux@2.37.2-4ubuntu3.4 โ€บ @@ -1901,7 +1608,7 @@

      Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -1956,7 +1663,7 @@

      Arbitrary Code Injection

      • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
      • Package Manager: ubuntu:22.04 @@ -1969,7 +1676,7 @@

        Arbitrary Code Injection

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and shadow/passwd@1:4.8.1-2ubuntu2.2 + docker-image|quay.io/argoproj/argocd@v2.11.9 and shadow/passwd@1:4.8.1-2ubuntu2.2
      @@ -1982,7 +1689,7 @@

      Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ shadow/passwd@1:4.8.1-2ubuntu2.2 @@ -1991,7 +1698,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -2002,7 +1709,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ @@ -2013,7 +1720,7 @@

        Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ shadow/login@1:4.8.1-2ubuntu2.2 @@ -2060,7 +1767,7 @@

        Uncontrolled Recursion

        • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
        • Package Manager: ubuntu:22.04 @@ -2073,7 +1780,7 @@

          Uncontrolled Recursion

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and pcre3/libpcre3@2:8.39-13ubuntu0.22.04.1 + docker-image|quay.io/argoproj/argocd@v2.11.9 and pcre3/libpcre3@2:8.39-13ubuntu0.22.04.1
        @@ -2086,7 +1793,7 @@

        Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ pcre3/libpcre3@2:8.39-13ubuntu0.22.04.1 @@ -2095,7 +1802,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ grep@3.7-1build1 โ€บ @@ -2135,6 +1842,77 @@

          References

          More about this vulnerability

    +
    +
    +

    Integer Overflow or Wraparound

    +
    + +
    + low severity +
    + +
    + +
      +
    • + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile +
    • +
    • + Package Manager: ubuntu:22.04 +
    • +
    • + Vulnerable module: + + pcre2/libpcre2-8-0 +
    • + +
    • Introduced through: + + docker-image|quay.io/argoproj/argocd@v2.11.9 and pcre2/libpcre2-8-0@10.39-3ubuntu0.1 + +
    • +
    + +
    + + +

    Detailed paths

    + +
      +
    • + Introduced through: + docker-image|quay.io/argoproj/argocd@v2.11.9 + โ€บ + pcre2/libpcre2-8-0@10.39-3ubuntu0.1 + + + +
    • +
    + +
    + +
    + +

    NVD Description

    +

    Note: Versions mentioned in the description apply only to the upstream pcre2 package and not the pcre2 package as distributed by Ubuntu. + See How to fix? for Ubuntu:22.04 relevant fixed versions and status.

    +

    Integer overflow vulnerability in pcre2test before 10.41 allows attackers to cause a denial of service or other unspecified impacts via negative input.

    +

    Remediation

    +

    There is no fixed version for Ubuntu:22.04 pcre2.

    +

    References

    + + +
    + + +

    Release of Invalid Pointer or Reference

    @@ -2148,7 +1926,7 @@

    Release of Invalid Pointer or Reference

    • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
    • Package Manager: ubuntu:22.04 @@ -2161,7 +1939,7 @@

      Release of Invalid Pointer or Reference

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and patch@2.7.6-7build2 + docker-image|quay.io/argoproj/argocd@v2.11.9 and patch@2.7.6-7build2
    @@ -2174,7 +1952,7 @@

    Detailed paths

    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ patch@2.7.6-7build2 @@ -2218,7 +1996,7 @@

      Double Free

      • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
      • Package Manager: ubuntu:22.04 @@ -2231,7 +2009,7 @@

        Double Free

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and patch@2.7.6-7build2 + docker-image|quay.io/argoproj/argocd@v2.11.9 and patch@2.7.6-7build2
      @@ -2244,7 +2022,7 @@

      Detailed paths

      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ patch@2.7.6-7build2 @@ -2293,7 +2071,7 @@

        CVE-2023-50495

        • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
        • Package Manager: ubuntu:22.04 @@ -2306,7 +2084,7 @@

          CVE-2023-50495

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and ncurses/libtinfo6@6.3-2ubuntu0.1 + docker-image|quay.io/argoproj/argocd@v2.11.9 and ncurses/libtinfo6@6.3-2ubuntu0.1
        @@ -2319,7 +2097,7 @@

        Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/libtinfo6@6.3-2ubuntu0.1 @@ -2328,7 +2106,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ bash@5.1-6ubuntu1.1 โ€บ @@ -2339,7 +2117,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/libncursesw6@6.3-2ubuntu0.1 โ€บ @@ -2350,7 +2128,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ less@590-1ubuntu0.22.04.3 โ€บ @@ -2361,7 +2139,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ libedit/libedit2@3.1-20210910-1build1 โ€บ @@ -2372,7 +2150,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/libncurses6@6.3-2ubuntu0.1 โ€บ @@ -2383,7 +2161,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/ncurses-bin@6.3-2ubuntu0.1 โ€บ @@ -2394,7 +2172,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -2405,7 +2183,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ util-linux@2.37.2-4ubuntu3.4 โ€บ @@ -2416,7 +2194,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 โ€บ @@ -2431,7 +2209,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -2446,7 +2224,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/libncursesw6@6.3-2ubuntu0.1 @@ -2455,7 +2233,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -2466,7 +2244,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -2481,7 +2259,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/libncurses6@6.3-2ubuntu0.1 @@ -2490,7 +2268,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -2501,7 +2279,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/ncurses-base@6.3-2ubuntu0.1 @@ -2510,7 +2288,7 @@

          Detailed paths

        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/ncurses-bin@6.3-2ubuntu0.1 @@ -2557,7 +2335,7 @@

          CVE-2023-45918

          • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
          • Package Manager: ubuntu:22.04 @@ -2570,7 +2348,7 @@

            CVE-2023-45918

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and ncurses/libtinfo6@6.3-2ubuntu0.1 + docker-image|quay.io/argoproj/argocd@v2.11.9 and ncurses/libtinfo6@6.3-2ubuntu0.1
          @@ -2583,7 +2361,7 @@

          Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/libtinfo6@6.3-2ubuntu0.1 @@ -2592,7 +2370,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ bash@5.1-6ubuntu1.1 โ€บ @@ -2603,7 +2381,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/libncursesw6@6.3-2ubuntu0.1 โ€บ @@ -2614,7 +2392,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ less@590-1ubuntu0.22.04.3 โ€บ @@ -2625,7 +2403,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ libedit/libedit2@3.1-20210910-1build1 โ€บ @@ -2636,7 +2414,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/libncurses6@6.3-2ubuntu0.1 โ€บ @@ -2647,7 +2425,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/ncurses-bin@6.3-2ubuntu0.1 โ€บ @@ -2658,7 +2436,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -2669,7 +2447,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ util-linux@2.37.2-4ubuntu3.4 โ€บ @@ -2680,7 +2458,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 โ€บ @@ -2695,7 +2473,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -2710,7 +2488,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/libncursesw6@6.3-2ubuntu0.1 @@ -2719,7 +2497,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -2730,7 +2508,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -2745,7 +2523,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/libncurses6@6.3-2ubuntu0.1 @@ -2754,7 +2532,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ procps@2:3.3.17-6ubuntu2.1 โ€บ @@ -2765,7 +2543,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/ncurses-base@6.3-2ubuntu0.1 @@ -2774,7 +2552,7 @@

            Detailed paths

          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ ncurses/ncurses-bin@6.3-2ubuntu0.1 @@ -2819,7 +2597,7 @@

            Resource Exhaustion

            • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
            • Package Manager: ubuntu:22.04 @@ -2832,7 +2610,7 @@

              Resource Exhaustion

            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and libzstd/libzstd1@1.4.8+dfsg-3build1 + docker-image|quay.io/argoproj/argocd@v2.11.9 and libzstd/libzstd1@1.4.8+dfsg-3build1
            @@ -2845,7 +2623,7 @@

            Detailed paths

            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ libzstd/libzstd1@1.4.8+dfsg-3build1 @@ -2896,7 +2674,7 @@

              Integer Overflow or Wraparound

              • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
              • Package Manager: ubuntu:22.04 @@ -2909,7 +2687,7 @@

                Integer Overflow or Wraparound

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and krb5/libk5crypto3@1.19.2-2ubuntu0.4 + docker-image|quay.io/argoproj/argocd@v2.11.9 and krb5/libk5crypto3@1.19.2-2ubuntu0.4
              @@ -2922,7 +2700,7 @@

              Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libk5crypto3@1.19.2-2ubuntu0.4 @@ -2931,7 +2709,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -2952,7 +2730,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -2975,7 +2753,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libkrb5-3@1.19.2-2ubuntu0.4 @@ -2984,7 +2762,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -3005,7 +2783,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 @@ -3014,7 +2792,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ @@ -3025,11 +2803,11 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.17 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 @@ -3038,11 +2816,11 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.17 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 โ€บ @@ -3053,7 +2831,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -3072,7 +2850,7 @@

                Detailed paths

              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libkrb5support0@1.19.2-2ubuntu0.4 @@ -3120,7 +2898,7 @@

                CVE-2024-26461

                • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
                • Package Manager: ubuntu:22.04 @@ -3133,7 +2911,7 @@

                  CVE-2024-26461

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and krb5/libk5crypto3@1.19.2-2ubuntu0.4 + docker-image|quay.io/argoproj/argocd@v2.11.9 and krb5/libk5crypto3@1.19.2-2ubuntu0.4
                @@ -3146,7 +2924,7 @@

                Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libk5crypto3@1.19.2-2ubuntu0.4 @@ -3155,7 +2933,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -3176,7 +2954,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -3199,7 +2977,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libkrb5-3@1.19.2-2ubuntu0.4 @@ -3208,7 +2986,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -3229,7 +3007,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 @@ -3238,7 +3016,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ @@ -3249,11 +3027,11 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.17 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 @@ -3262,11 +3040,11 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.17 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 โ€บ @@ -3277,7 +3055,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -3296,7 +3074,7 @@

                  Detailed paths

                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libkrb5support0@1.19.2-2ubuntu0.4 @@ -3341,7 +3119,7 @@

                  CVE-2024-26458

                  • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
                  • Package Manager: ubuntu:22.04 @@ -3354,7 +3132,7 @@

                    CVE-2024-26458

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and krb5/libk5crypto3@1.19.2-2ubuntu0.4 + docker-image|quay.io/argoproj/argocd@v2.11.9 and krb5/libk5crypto3@1.19.2-2ubuntu0.4
                  @@ -3367,7 +3145,7 @@

                  Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libk5crypto3@1.19.2-2ubuntu0.4 @@ -3376,7 +3154,7 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -3397,7 +3175,7 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -3420,7 +3198,7 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libkrb5-3@1.19.2-2ubuntu0.4 @@ -3429,7 +3207,7 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -3450,7 +3228,7 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 @@ -3459,7 +3237,7 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ openssh/openssh-client@1:8.9p1-3ubuntu0.10 โ€บ @@ -3470,11 +3248,11 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.17 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ krb5/libgssapi-krb5-2@1.19.2-2ubuntu0.4 @@ -3483,11 +3261,11 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ - curl/libcurl3-gnutls@7.81.0-1ubuntu1.17 + curl/libcurl3-gnutls@7.81.0-1ubuntu1.18 โ€บ libssh/libssh-4@0.9.6-2ubuntu0.22.04.3 โ€บ @@ -3498,7 +3276,7 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ adduser@3.118ubuntu5 โ€บ @@ -3517,7 +3295,7 @@

                    Detailed paths

                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ krb5/libkrb5support0@1.19.2-2ubuntu0.4 @@ -3562,7 +3340,7 @@

                    Out-of-bounds Write

                    • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
                    • Package Manager: ubuntu:22.04 @@ -3575,7 +3353,7 @@

                      Out-of-bounds Write

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and gnupg2/gpgv@2.2.27-3ubuntu2.1 + docker-image|quay.io/argoproj/argocd@v2.11.9 and gnupg2/gpgv@2.2.27-3ubuntu2.1
                    @@ -3588,7 +3366,7 @@

                    Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpgv@2.2.27-3ubuntu2.1 @@ -3597,7 +3375,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -3608,7 +3386,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3619,7 +3397,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/dirmngr@2.2.27-3ubuntu2.1 โ€บ @@ -3630,7 +3408,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 โ€บ @@ -3641,7 +3419,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3654,7 +3432,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3667,7 +3445,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/dirmngr@2.2.27-3ubuntu2.1 @@ -3676,7 +3454,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3687,7 +3465,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3700,7 +3478,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg-l10n@2.2.27-3ubuntu2.1 @@ -3709,7 +3487,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3720,7 +3498,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg-utils@2.2.27-3ubuntu2.1 @@ -3729,7 +3507,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3740,7 +3518,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpg@2.2.27-3ubuntu2.1 @@ -3749,7 +3527,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3760,7 +3538,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3773,7 +3551,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3786,7 +3564,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpg-agent@2.2.27-3ubuntu2.1 @@ -3795,7 +3573,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3806,7 +3584,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3819,7 +3597,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3832,7 +3610,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpg-wks-client@2.2.27-3ubuntu2.1 @@ -3841,7 +3619,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3852,7 +3630,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpg-wks-server@2.2.27-3ubuntu2.1 @@ -3861,7 +3639,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3872,7 +3650,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gpgsm@2.2.27-3ubuntu2.1 @@ -3881,7 +3659,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 โ€บ @@ -3892,7 +3670,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gnupg2/gnupg@2.2.27-3ubuntu2.1 @@ -3941,7 +3719,7 @@

                      Allocation of Resources Without Limits or Throttling

                    • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
                    • Package Manager: ubuntu:22.04 @@ -3954,7 +3732,7 @@

                      Allocation of Resources Without Limits or Throttling

                      Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and glibc/libc-bin@2.35-0ubuntu3.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 and glibc/libc-bin@2.35-0ubuntu3.8
                    @@ -3967,7 +3745,7 @@

                    Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ glibc/libc-bin@2.35-0ubuntu3.8 @@ -3976,7 +3754,7 @@

                      Detailed paths

                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ glibc/libc6@2.35-0ubuntu3.8 @@ -4022,7 +3800,7 @@

                      Improper Input Validation

                      • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
                      • Package Manager: ubuntu:22.04 @@ -4036,7 +3814,7 @@

                        Improper Input Validation

                      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8, git@1:2.34.1-1ubuntu1.11 and others + docker-image|quay.io/argoproj/argocd@v2.11.9, git@1:2.34.1-1ubuntu1.11 and others
                      @@ -4048,7 +3826,7 @@

                      Detailed paths

                      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 โ€บ @@ -4059,7 +3837,7 @@

                        Detailed paths

                      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git@1:2.34.1-1ubuntu1.11 @@ -4068,7 +3846,7 @@

                        Detailed paths

                      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ git-lfs@3.0.2-1ubuntu0.2 โ€บ @@ -4115,7 +3893,7 @@

                        Uncontrolled Recursion

                        • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
                        • Package Manager: ubuntu:22.04 @@ -4128,7 +3906,7 @@

                          Uncontrolled Recursion

                        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 + docker-image|quay.io/argoproj/argocd@v2.11.9 and gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04
                        @@ -4141,7 +3919,7 @@

                        Detailed paths

                        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gcc-12/libstdc++6@12.3.0-1ubuntu1~22.04 @@ -4150,7 +3928,7 @@

                          Detailed paths

                        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -4161,7 +3939,7 @@

                          Detailed paths

                        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ apt@2.4.13 โ€บ @@ -4174,7 +3952,7 @@

                          Detailed paths

                        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gcc-12/gcc-12-base@12.3.0-1ubuntu1~22.04 @@ -4183,7 +3961,7 @@

                          Detailed paths

                        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ gcc-12/libgcc-s1@12.3.0-1ubuntu1~22.04 @@ -4230,7 +4008,7 @@

                          Improper Input Validation

                          • - Manifest file: quay.io/argoproj/argocd:v2.11.8/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.11.9/argoproj/argocd โ€บ Dockerfile
                          • Package Manager: ubuntu:22.04 @@ -4243,7 +4021,7 @@

                            Improper Input Validation

                          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 and coreutils@8.32-4.1ubuntu1.2 + docker-image|quay.io/argoproj/argocd@v2.11.9 and coreutils@8.32-4.1ubuntu1.2
                          @@ -4256,7 +4034,7 @@

                          Detailed paths

                          • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.11.8 + docker-image|quay.io/argoproj/argocd@v2.11.9 โ€บ coreutils@8.32-4.1ubuntu1.2 diff --git a/docs/snyk/v2.11.8/redis_7.0.15-alpine.html b/docs/snyk/v2.11.9/redis_7.0.15-alpine.html similarity index 99% rename from docs/snyk/v2.11.8/redis_7.0.15-alpine.html rename to docs/snyk/v2.11.9/redis_7.0.15-alpine.html index 1a6806f71cefa0..83858d50513c2a 100644 --- a/docs/snyk/v2.11.8/redis_7.0.15-alpine.html +++ b/docs/snyk/v2.11.9/redis_7.0.15-alpine.html @@ -456,7 +456,7 @@

                            Snyk test report

                            -

                            September 22nd 2024, 12:26:43 am (UTC+00:00)

                            +

                            October 6th 2024, 12:34:48 am (UTC+00:00)

                            Scanned the following paths: diff --git a/docs/snyk/v2.12.3/argocd-test.html b/docs/snyk/v2.12.3/argocd-test.html deleted file mode 100644 index c5ace95defe545..00000000000000 --- a/docs/snyk/v2.12.3/argocd-test.html +++ /dev/null @@ -1,1086 +0,0 @@ - - - - - - - - - Snyk test report - - - - - - - - - -
                            -
                            -
                            -
                            - - - Snyk - Open Source Security - - - - - - - -
                            -

                            Snyk test report

                            - -

                            September 22nd 2024, 12:23:57 am (UTC+00:00)

                            -
                            -
                            - Scanned the following paths: -
                              -
                            • /argo-cd/argoproj/argo-cd/v2/go.mod (gomodules)
                            • -
                            • /argo-cd/ui/yarn.lock (yarn)
                            • -
                            -
                            - -
                            -
                            5 known vulnerabilities
                            -
                            7 vulnerable dependency paths
                            -
                            2061 dependencies
                            -
                            -
                            -
                            -
                            - -
                            -
                            -
                            -

                            Prototype Pollution

                            -
                            - -
                            - high severity -
                            - -
                            - -
                              -
                            • - Manifest file: /argo-cd โ€บ ui/yarn.lock -
                            • -
                            • - Package Manager: npm -
                            • -
                            • - Vulnerable module: - - dompurify -
                            • - -
                            • Introduced through: - - - argo-cd-ui@1.0.0, redoc@2.0.0-rc.64 and others -
                            • -
                            - -
                            - - -

                            Detailed paths

                            - -
                              -
                            • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - redoc@2.0.0-rc.64 - โ€บ - dompurify@2.3.6 - - - -
                            • -
                            - -
                            - -
                            - -

                            Overview

                            -

                            dompurify is a DOM-only XSS sanitizer for HTML, MathML and SVG.

                            -

                            Affected versions of this package are vulnerable to Prototype Pollution due to improper user input sanitization through the depth-checking mechanism, an attacker can exploit this vulnerability by using special nesting techniques to create a malicious HTML file.

                            -

                            Details

                            -

                            Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as __proto__, constructor and prototype. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.

                            -

                            There are two main ways in which the pollution of prototypes occurs:

                            -
                              -
                            • Unsafe Object recursive merge

                              -
                            • -
                            • Property definition by path

                              -
                            • -
                            -

                            Unsafe Object recursive merge

                            -

                            The logic of a vulnerable recursive merge function follows the following high-level model:

                            -
                            merge (target, source)
                            -        
                            -          foreach property of source
                            -        
                            -            if property exists and is an object on both the target and the source
                            -        
                            -              merge(target[property], source[property])
                            -        
                            -            else
                            -        
                            -              target[property] = source[property]
                            -        
                            -
                            - -

                            When the source object contains a property named __proto__ defined with Object.defineProperty() , the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object and the source of Object as defined by the attacker. Properties are then copied on the Object prototype.

                            -

                            Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source).

                            -

                            lodash and Hoek are examples of libraries susceptible to recursive merge attacks.

                            -

                            Property definition by path

                            -

                            There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)

                            -

                            If the attacker can control the value of โ€œpathโ€, they can set this value to __proto__.myValue. myValue is then assigned to the prototype of the class of the object.

                            -

                            Types of attacks

                            -

                            There are a few methods by which Prototype Pollution can be manipulated:

                            - - - - - - - - - - - - - - - - - - - - - - - -
                            TypeOriginShort description
                            Denial of service (DoS)ClientThis is the most likely attack.
                            DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf).
                            The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object. In this case, the code fails and is likely to cause a denial of service.
                            For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail.
                            Remote Code ExecutionClientRemote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation.
                            For example: eval(someobject.someattr). In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code.
                            Property InjectionClientThe attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens.
                            For example: if a codebase checks privileges for someuser.isAdmin, then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true, they can then achieve admin privileges.
                            -

                            Affected environments

                            -

                            The following environments are susceptible to a Prototype Pollution attack:

                            -
                              -
                            • Application server

                              -
                            • -
                            • Web server

                              -
                            • -
                            • Web browser

                              -
                            • -
                            -

                            How to prevent

                            -
                              -
                            1. Freeze the prototypeโ€” use Object.freeze (Object.prototype).

                              -
                            2. -
                            3. Require schema validation of JSON input.

                              -
                            4. -
                            5. Avoid using unsafe recursive merge functions.

                              -
                            6. -
                            7. Consider using objects without prototypes (for example, Object.create(null)), breaking the prototype chain and preventing pollution.

                              -
                            8. -
                            9. As a best practice use Map instead of Object.

                              -
                            10. -
                            -

                            For more information on this vulnerability type:

                            -

                            Arteau, Oliver. โ€œJavaScript prototype pollution attack in NodeJS application.โ€ GitHub, 26 May 2018

                            -

                            Remediation

                            -

                            Upgrade dompurify to version 2.5.4, 3.1.3 or higher.

                            -

                            References

                            - - -
                            - - - -
                            -
                            -

                            Regular Expression Denial of Service (ReDoS)

                            -
                            - -
                            - medium severity -
                            - -
                            - -
                              -
                            • - Manifest file: /argo-cd โ€บ ui/yarn.lock -
                            • -
                            • - Package Manager: npm -
                            • -
                            • - Vulnerable module: - - path-to-regexp -
                            • - -
                            • Introduced through: - - - argo-cd-ui@1.0.0, react-router@4.3.1 and others -
                            • -
                            - -
                            - - -

                            Detailed paths

                            - -
                              -
                            • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
                            • -
                            • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - react-router-dom@4.3.1 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
                            • -
                            • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - argo-ui@1.0.0 - โ€บ - react-router-dom@4.3.1 - โ€บ - react-router@4.3.1 - โ€บ - path-to-regexp@1.8.0 - - - -
                            • -
                            - -
                            - -
                            - -

                            Overview

                            -

                            Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) when including multiple regular expression parameters in a single segment, which will produce the regular expression /^\/([^\/]+?)-([^\/]+?)\/?$/, if two parameters within a single segment are separated by a character other than a / or .. Poor performance will block the event loop and can lead to a DoS.

                            -

                            Note: - While the 8.0.0 release has completely eliminated the vulnerable functionality, prior versions that have received the patch to mitigate backtracking may still be vulnerable if custom regular expressions are used. So it is strongly recommended for regular expression input to be controlled to avoid malicious performance degradation in those versions. This behavior is enforced as of version 7.1.0 via the strict option, which returns an error if a dangerous regular expression is detected.

                            -

                            Workaround

                            -

                            This vulnerability can be avoided by using a custom regular expression for parameters after the first in a segment, which excludes - and /.

                            -

                            PoC

                            -
                            /a${'-a'.repeat(8_000)}/a
                            -        
                            -

                            Details

                            -

                            Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.

                            -

                            The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.

                            -

                            Letโ€™s take the following regular expression as an example:

                            -
                            regex = /A(B|C+)+D/
                            -        
                            -

                            This regular expression accomplishes the following:

                            -
                              -
                            • A The string must start with the letter 'A'
                            • -
                            • (B|C+)+ The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the + matches one or more times). The + at the end of this section states that we can look for one or more matches of this section.
                            • -
                            • D Finally, we ensure this section of the string ends with a 'D'
                            • -
                            -

                            The expression would match inputs such as ABBD, ABCCCCD, ABCBCCCD and ACCCCCD

                            -

                            It most cases, it doesn't take very long for a regex engine to find a match:

                            -
                            $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
                            -        0.04s user 0.01s system 95% cpu 0.052 total
                            -        
                            -        $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
                            -        1.79s user 0.02s system 99% cpu 1.812 total
                            -        
                            -

                            The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.

                            -

                            Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesnโ€™t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.

                            -

                            Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:

                            -
                              -
                            1. CCC
                            2. -
                            3. CC+C
                            4. -
                            5. C+CC
                            6. -
                            7. C+C+C.
                            8. -
                            -

                            The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.

                            -

                            From there, the number of steps the engine must use to validate a string just continues to grow.

                            - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                            StringNumber of C'sNumber of steps
                            ACCCX338
                            ACCCCX471
                            ACCCCCX5136
                            ACCCCCCCCCCCCCCX1465,553
                            -

                            By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.

                            -

                            Remediation

                            -

                            Upgrade path-to-regexp to version 0.1.10, 1.9.0, 3.3.0, 6.3.0, 8.0.0 or higher.

                            -

                            References

                            - - -
                            - - - -
                            -
                            -

                            Denial of Service (DoS)

                            -
                            - -
                            - medium severity -
                            - -
                            - -
                              -
                            • - Manifest file: /argo-cd/argoproj/argo-cd/v2 โ€บ go.mod -
                            • -
                            • - Package Manager: golang -
                            • -
                            • - Vulnerable module: - - github.com/rs/cors -
                            • - -
                            • Introduced through: - - - github.com/argoproj/argo-cd/v2@0.0.0, github.com/improbable-eng/grpc-web/go/grpcweb@0.15.0 and others -
                            • -
                            - -
                            - - -

                            Detailed paths

                            - -
                              -
                            • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/improbable-eng/grpc-web/go/grpcweb@0.15.0 - โ€บ - github.com/rs/cors@1.9.0 - - - -
                            • -
                            - -
                            - -
                            - -

                            Overview

                            -

                            Affected versions of this package are vulnerable to Denial of Service (DoS) through the processing of malicious preflight requests that include a Access-Control-Request-Headers header with excessive commas. An attacker can induce excessive memory consumption and potentially crash the server by sending specially crafted requests.

                            -

                            PoC

                            -
                            
                            -        func BenchmarkPreflightAdversarialACRH(b *testing.B) {
                            -            resps := makeFakeResponses(b.N)
                            -            req, _ := http.NewRequest(http.MethodOptions, dummyEndpoint, nil)
                            -            req.Header.Add(headerOrigin, dummyOrigin)
                            -            req.Header.Add(headerACRM, http.MethodGet)
                            -            req.Header[headerACRH] = adversarialACRH
                            -            handler := Default().Handler(testHandler)
                            -        
                            -            b.ReportAllocs()
                            -            b.ResetTimer()
                            -            for i := 0; i < b.N; i++ {
                            -                handler.ServeHTTP(resps[i], req)
                            -            }
                            -        }
                            -        
                            -        var adversarialACRH []string
                            -        
                            -        func init() { // populates adversarialACRH
                            -            n := int(math.Floor(math.Sqrt(http.DefaultMaxHeaderBytes)))
                            -            commas := strings.Repeat(",", n)
                            -            res := make([]string, n)
                            -            for i := range res {
                            -                res[i] = commas
                            -            }
                            -            adversarialACRH = res
                            -        }
                            -        
                            -

                            Details

                            -

                            Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its intended and legitimate users.

                            -

                            Unlike other vulnerabilities, DoS attacks usually do not aim at breaching security. Rather, they are focused on making websites and services unavailable to genuine users resulting in downtime.

                            -

                            One popular Denial of Service vulnerability is DDoS (a Distributed Denial of Service), an attack that attempts to clog network pipes to the system by generating a large volume of traffic from many machines.

                            -

                            When it comes to open source libraries, DoS vulnerabilities allow attackers to trigger such a crash or crippling of the service by using a flaw either in the application code or from the use of open source libraries.

                            -

                            Two common types of DoS vulnerabilities:

                            -
                              -
                            • High CPU/Memory Consumption- An attacker sending crafted requests that could cause the system to take a disproportionate amount of time to process. For example, commons-fileupload:commons-fileupload.

                              -
                            • -
                            • Crash - An attacker sending crafted requests that could cause the system to crash. For Example, npm ws package

                              -
                            • -
                            -

                            Remediation

                            -

                            Upgrade github.com/rs/cors to version 1.11.0 or higher.

                            -

                            References

                            - - -
                            - - - -
                            -
                            -

                            Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')

                            -
                            - -
                            - medium severity -
                            - -
                            - -
                              -
                            • - Manifest file: /argo-cd/argoproj/argo-cd/v2 โ€บ go.mod -
                            • -
                            • - Package Manager: golang -
                            • -
                            • - Vulnerable module: - - github.com/Azure/azure-sdk-for-go/sdk/azidentity -
                            • - -
                            • Introduced through: - - - github.com/argoproj/argo-cd/v2@0.0.0, github.com/Azure/kubelogin/pkg/token@0.0.20 and others -
                            • -
                            - -
                            - - -

                            Detailed paths

                            - -
                              -
                            • - Introduced through: - github.com/argoproj/argo-cd/v2@0.0.0 - โ€บ - github.com/Azure/kubelogin/pkg/token@0.0.20 - โ€บ - github.com/Azure/azure-sdk-for-go/sdk/azidentity@1.1.0 - - - -
                            • -
                            - -
                            - -
                            - -

                            Overview

                            -

                            github.com/Azure/azure-sdk-for-go/sdk/azidentity is a module that provides Microsoft Entra ID (formerly Azure Active Directory) token authentication support across the Azure SDK. It includes a set of TokenCredential implementations, which can be used with Azure SDK clients supporting token authentication.

                            -

                            Affected versions of this package are vulnerable to Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition') in the authentication process. An attacker can elevate privileges by exploiting race conditions during the token validation steps. This is only exploitable if the application is configured to use multiple threads or processes for handling authentication requests.

                            -

                            Notes:

                            -
                              -
                            1. An attacker who successfully exploited the vulnerability could elevate privileges and read any file on the file system with SYSTEM access permissions;

                              -
                            2. -
                            3. An attacker who successfully exploits this vulnerability can only obtain read access to the system files by exploiting this vulnerability. The attacker cannot perform write or delete operations on the files;

                              -
                            4. -
                            5. The vulnerability exists in the following credential types: DefaultAzureCredential and ManagedIdentityCredential;

                              -
                            6. -
                            7. The vulnerability exists in the following credential types:

                              -
                            8. -
                            -

                            ManagedIdentityApplication (.NET)

                            -

                            ManagedIdentityApplication (Java)

                            -

                            ManagedIdentityApplication (Node.js)

                            -

                            Remediation

                            -

                            Upgrade github.com/Azure/azure-sdk-for-go/sdk/azidentity to version 1.6.0 or higher.

                            -

                            References

                            - - -
                            - - - -
                            -
                            -

                            Template Injection

                            -
                            - -
                            - medium severity -
                            - -
                            - -
                              -
                            • - Manifest file: /argo-cd โ€บ ui/yarn.lock -
                            • -
                            • - Package Manager: npm -
                            • -
                            • - Vulnerable module: - - dompurify -
                            • - -
                            • Introduced through: - - - argo-cd-ui@1.0.0, redoc@2.0.0-rc.64 and others -
                            • -
                            - -
                            - - -

                            Detailed paths

                            - -
                              -
                            • - Introduced through: - argo-cd-ui@1.0.0 - โ€บ - redoc@2.0.0-rc.64 - โ€บ - dompurify@2.3.6 - - - -
                            • -
                            - -
                            - -
                            - -

                            Overview

                            -

                            dompurify is a DOM-only XSS sanitizer for HTML, MathML and SVG.

                            -

                            Affected versions of this package are vulnerable to Template Injection in purify.js, due to inconsistencies in the parsing of XML and HTML tags. Executable code can be injected in HTML inside XML CDATA blocks.

                            -

                            PoC

                            -
                            <![CDATA[ ><img src onerror=alert(1)> ]]>
                            -        
                            -

                            Remediation

                            -

                            Upgrade dompurify to version 2.4.9, 3.0.11 or higher.

                            -

                            References

                            - - -
                            - - - -
                            -
                            -
                            -
                            - - - diff --git a/docs/snyk/v2.12.3/argocd-iac-install.html b/docs/snyk/v2.12.4/argocd-iac-install.html similarity index 99% rename from docs/snyk/v2.12.3/argocd-iac-install.html rename to docs/snyk/v2.12.4/argocd-iac-install.html index 268b77b876e08d..58c9e5b2c5dc12 100644 --- a/docs/snyk/v2.12.3/argocd-iac-install.html +++ b/docs/snyk/v2.12.4/argocd-iac-install.html @@ -456,7 +456,7 @@

                            Snyk test report

                            -

                            September 22nd 2024, 12:25:50 am (UTC+00:00)

                            +

                            October 6th 2024, 12:33:54 am (UTC+00:00)

                            Scanned the following path: diff --git a/docs/snyk/v2.12.3/argocd-iac-namespace-install.html b/docs/snyk/v2.12.4/argocd-iac-namespace-install.html similarity index 99% rename from docs/snyk/v2.12.3/argocd-iac-namespace-install.html rename to docs/snyk/v2.12.4/argocd-iac-namespace-install.html index aab9b5b3686cbd..746cfd20b5af68 100644 --- a/docs/snyk/v2.12.3/argocd-iac-namespace-install.html +++ b/docs/snyk/v2.12.4/argocd-iac-namespace-install.html @@ -456,7 +456,7 @@

                            Snyk test report

                            -

                            September 22nd 2024, 12:25:59 am (UTC+00:00)

                            +

                            October 6th 2024, 12:34:04 am (UTC+00:00)

                            Scanned the following path: diff --git a/docs/snyk/v2.12.4/argocd-test.html b/docs/snyk/v2.12.4/argocd-test.html new file mode 100644 index 00000000000000..09be8834d23dc2 --- /dev/null +++ b/docs/snyk/v2.12.4/argocd-test.html @@ -0,0 +1,688 @@ + + + + + + + + + Snyk test report + + + + + + + + + +
                            +
                            +
                            +
                            + + + Snyk - Open Source Security + + + + + + + +
                            +

                            Snyk test report

                            + +

                            October 6th 2024, 12:31:58 am (UTC+00:00)

                            +
                            +
                            + Scanned the following paths: +
                              +
                            • /argo-cd/argoproj/argo-cd/v2/go.mod (gomodules)
                            • +
                            • /argo-cd/ui/yarn.lock (yarn)
                            • +
                            +
                            + +
                            +
                            2 known vulnerabilities
                            +
                            2 vulnerable dependency paths
                            +
                            2061 dependencies
                            +
                            +
                            +
                            +
                            + +
                            +
                            +
                            +

                            Denial of Service (DoS)

                            +
                            + +
                            + medium severity +
                            + +
                            + +
                              +
                            • + Manifest file: /argo-cd/argoproj/argo-cd/v2 โ€บ go.mod +
                            • +
                            • + Package Manager: golang +
                            • +
                            • + Vulnerable module: + + github.com/rs/cors +
                            • + +
                            • Introduced through: + + + github.com/argoproj/argo-cd/v2@0.0.0, github.com/improbable-eng/grpc-web/go/grpcweb@0.15.0 and others +
                            • +
                            + +
                            + + +

                            Detailed paths

                            + +
                              +
                            • + Introduced through: + github.com/argoproj/argo-cd/v2@0.0.0 + โ€บ + github.com/improbable-eng/grpc-web/go/grpcweb@0.15.0 + โ€บ + github.com/rs/cors@1.9.0 + + + +
                            • +
                            + +
                            + +
                            + +

                            Overview

                            +

                            Affected versions of this package are vulnerable to Denial of Service (DoS) through the processing of malicious preflight requests that include a Access-Control-Request-Headers header with excessive commas. An attacker can induce excessive memory consumption and potentially crash the server by sending specially crafted requests.

                            +

                            PoC

                            +
                            
                            +        func BenchmarkPreflightAdversarialACRH(b *testing.B) {
                            +            resps := makeFakeResponses(b.N)
                            +            req, _ := http.NewRequest(http.MethodOptions, dummyEndpoint, nil)
                            +            req.Header.Add(headerOrigin, dummyOrigin)
                            +            req.Header.Add(headerACRM, http.MethodGet)
                            +            req.Header[headerACRH] = adversarialACRH
                            +            handler := Default().Handler(testHandler)
                            +        
                            +            b.ReportAllocs()
                            +            b.ResetTimer()
                            +            for i := 0; i < b.N; i++ {
                            +                handler.ServeHTTP(resps[i], req)
                            +            }
                            +        }
                            +        
                            +        var adversarialACRH []string
                            +        
                            +        func init() { // populates adversarialACRH
                            +            n := int(math.Floor(math.Sqrt(http.DefaultMaxHeaderBytes)))
                            +            commas := strings.Repeat(",", n)
                            +            res := make([]string, n)
                            +            for i := range res {
                            +                res[i] = commas
                            +            }
                            +            adversarialACRH = res
                            +        }
                            +        
                            +

                            Details

                            +

                            Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its intended and legitimate users.

                            +

                            Unlike other vulnerabilities, DoS attacks usually do not aim at breaching security. Rather, they are focused on making websites and services unavailable to genuine users resulting in downtime.

                            +

                            One popular Denial of Service vulnerability is DDoS (a Distributed Denial of Service), an attack that attempts to clog network pipes to the system by generating a large volume of traffic from many machines.

                            +

                            When it comes to open source libraries, DoS vulnerabilities allow attackers to trigger such a crash or crippling of the service by using a flaw either in the application code or from the use of open source libraries.

                            +

                            Two common types of DoS vulnerabilities:

                            +
                              +
                            • High CPU/Memory Consumption- An attacker sending crafted requests that could cause the system to take a disproportionate amount of time to process. For example, commons-fileupload:commons-fileupload.

                              +
                            • +
                            • Crash - An attacker sending crafted requests that could cause the system to crash. For Example, npm ws package

                              +
                            • +
                            +

                            Remediation

                            +

                            Upgrade github.com/rs/cors to version 1.11.0 or higher.

                            +

                            References

                            + + +
                            + + + +
                            +
                            +

                            Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')

                            +
                            + +
                            + medium severity +
                            + +
                            + +
                              +
                            • + Manifest file: /argo-cd/argoproj/argo-cd/v2 โ€บ go.mod +
                            • +
                            • + Package Manager: golang +
                            • +
                            • + Vulnerable module: + + github.com/Azure/azure-sdk-for-go/sdk/azidentity +
                            • + +
                            • Introduced through: + + + github.com/argoproj/argo-cd/v2@0.0.0, github.com/Azure/kubelogin/pkg/token@0.0.20 and others +
                            • +
                            + +
                            + + +

                            Detailed paths

                            + +
                              +
                            • + Introduced through: + github.com/argoproj/argo-cd/v2@0.0.0 + โ€บ + github.com/Azure/kubelogin/pkg/token@0.0.20 + โ€บ + github.com/Azure/azure-sdk-for-go/sdk/azidentity@1.1.0 + + + +
                            • +
                            + +
                            + +
                            + +

                            Overview

                            +

                            github.com/Azure/azure-sdk-for-go/sdk/azidentity is a module that provides Microsoft Entra ID (formerly Azure Active Directory) token authentication support across the Azure SDK. It includes a set of TokenCredential implementations, which can be used with Azure SDK clients supporting token authentication.

                            +

                            Affected versions of this package are vulnerable to Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition') in the authentication process. An attacker can elevate privileges by exploiting race conditions during the token validation steps. This is only exploitable if the application is configured to use multiple threads or processes for handling authentication requests.

                            +

                            Notes:

                            +
                              +
                            1. An attacker who successfully exploited the vulnerability could elevate privileges and read any file on the file system with SYSTEM access permissions;

                              +
                            2. +
                            3. An attacker who successfully exploits this vulnerability can only obtain read access to the system files by exploiting this vulnerability. The attacker cannot perform write or delete operations on the files;

                              +
                            4. +
                            5. The vulnerability exists in the following credential types: DefaultAzureCredential and ManagedIdentityCredential;

                              +
                            6. +
                            7. The vulnerability exists in the following credential types:

                              +
                            8. +
                            +

                            ManagedIdentityApplication (.NET)

                            +

                            ManagedIdentityApplication (Java)

                            +

                            ManagedIdentityApplication (Node.js)

                            +

                            Remediation

                            +

                            Upgrade github.com/Azure/azure-sdk-for-go/sdk/azidentity to version 1.6.0 or higher.

                            +

                            References

                            + + +
                            + + + +
                            +
                            +
                            +
                            + + + diff --git a/docs/snyk/v2.12.3/ghcr.io_dexidp_dex_v2.38.0.html b/docs/snyk/v2.12.4/ghcr.io_dexidp_dex_v2.38.0.html similarity index 99% rename from docs/snyk/v2.12.3/ghcr.io_dexidp_dex_v2.38.0.html rename to docs/snyk/v2.12.4/ghcr.io_dexidp_dex_v2.38.0.html index c40058cb449a26..ff13e73301db3d 100644 --- a/docs/snyk/v2.12.3/ghcr.io_dexidp_dex_v2.38.0.html +++ b/docs/snyk/v2.12.4/ghcr.io_dexidp_dex_v2.38.0.html @@ -456,7 +456,7 @@

                            Snyk test report

                            -

                            September 22nd 2024, 12:24:06 am (UTC+00:00)

                            +

                            October 6th 2024, 12:32:06 am (UTC+00:00)

                            Scanned the following paths: diff --git a/docs/snyk/v2.12.3/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html b/docs/snyk/v2.12.4/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html similarity index 99% rename from docs/snyk/v2.12.3/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html rename to docs/snyk/v2.12.4/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html index bed01faa336f7c..f840d693ddf2d5 100644 --- a/docs/snyk/v2.12.3/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html +++ b/docs/snyk/v2.12.4/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html @@ -456,7 +456,7 @@

                            Snyk test report

                            -

                            September 22nd 2024, 12:24:09 am (UTC+00:00)

                            +

                            October 6th 2024, 12:32:10 am (UTC+00:00)

                            Scanned the following path: diff --git a/docs/snyk/v2.12.3/public.ecr.aws_docker_library_redis_7.0.15-alpine.html b/docs/snyk/v2.12.4/public.ecr.aws_docker_library_redis_7.0.15-alpine.html similarity index 99% rename from docs/snyk/v2.12.3/public.ecr.aws_docker_library_redis_7.0.15-alpine.html rename to docs/snyk/v2.12.4/public.ecr.aws_docker_library_redis_7.0.15-alpine.html index dbc79e2e50588d..30e7dcce615793 100644 --- a/docs/snyk/v2.12.3/public.ecr.aws_docker_library_redis_7.0.15-alpine.html +++ b/docs/snyk/v2.12.4/public.ecr.aws_docker_library_redis_7.0.15-alpine.html @@ -456,7 +456,7 @@

                            Snyk test report

                            -

                            September 22nd 2024, 12:24:12 am (UTC+00:00)

                            +

                            October 6th 2024, 12:32:14 am (UTC+00:00)

                            Scanned the following paths: diff --git a/docs/snyk/v2.12.3/quay.io_argoproj_argocd_v2.12.3.html b/docs/snyk/v2.12.4/quay.io_argoproj_argocd_v2.12.4.html similarity index 76% rename from docs/snyk/v2.12.3/quay.io_argoproj_argocd_v2.12.3.html rename to docs/snyk/v2.12.4/quay.io_argoproj_argocd_v2.12.4.html index 0bd0879c74d782..9dba71186c6493 100644 --- a/docs/snyk/v2.12.3/quay.io_argoproj_argocd_v2.12.3.html +++ b/docs/snyk/v2.12.4/quay.io_argoproj_argocd_v2.12.4.html @@ -7,7 +7,7 @@ Snyk test report - + @@ -456,22 +456,22 @@

                            Snyk test report

                            -

                            September 22nd 2024, 12:24:27 am (UTC+00:00)

                            +

                            October 6th 2024, 12:32:30 am (UTC+00:00)

                            Scanned the following paths:
                              -
                            • quay.io/argoproj/argocd:v2.12.3/argoproj/argocd/Dockerfile (deb)
                            • -
                            • quay.io/argoproj/argocd:v2.12.3/argoproj/argo-cd/v2//usr/local/bin/argocd (gomodules)
                            • -
                            • quay.io/argoproj/argocd:v2.12.3//usr/local/bin/kustomize (gomodules)
                            • -
                            • quay.io/argoproj/argocd:v2.12.3/helm/v3//usr/local/bin/helm (gomodules)
                            • -
                            • quay.io/argoproj/argocd:v2.12.3/git-lfs/git-lfs//usr/bin/git-lfs (gomodules)
                            • +
                            • quay.io/argoproj/argocd:v2.12.4/argoproj/argocd/Dockerfile (deb)
                            • +
                            • quay.io/argoproj/argocd:v2.12.4/argoproj/argo-cd/v2//usr/local/bin/argocd (gomodules)
                            • +
                            • quay.io/argoproj/argocd:v2.12.4//usr/local/bin/kustomize (gomodules)
                            • +
                            • quay.io/argoproj/argocd:v2.12.4/helm/v3//usr/local/bin/helm (gomodules)
                            • +
                            • quay.io/argoproj/argocd:v2.12.4/git-lfs/git-lfs//usr/bin/git-lfs (gomodules)
                            -
                            17 known vulnerabilities
                            -
                            81 vulnerable dependency paths
                            +
                            12 known vulnerabilities
                            +
                            66 vulnerable dependency paths
                            2292 dependencies
                            @@ -492,7 +492,7 @@

                            CVE-2024-41996

                            • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                            • Package Manager: ubuntu:24.04 @@ -505,7 +505,7 @@

                              CVE-2024-41996

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 and openssl/libssl3t64@3.0.13-0ubuntu3.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 and openssl/libssl3t64@3.0.13-0ubuntu3.4
                            @@ -518,135 +518,135 @@

                            Detailed paths

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 + openssl/libssl3t64@3.0.13-0ubuntu3.4
                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ coreutils@9.4-3ubuntu6 โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 + openssl/libssl3t64@3.0.13-0ubuntu3.4
                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ cyrus-sasl2/libsasl2-modules@2.1.28+dfsg1-5ubuntu3.1 โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 + openssl/libssl3t64@3.0.13-0ubuntu3.4
                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ libfido2/libfido2-1@1.14.0-1build3 โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 + openssl/libssl3t64@3.0.13-0ubuntu3.4
                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ openssh/openssh-client@1:9.6p1-3ubuntu13.5 โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 + openssl/libssl3t64@3.0.13-0ubuntu3.4
                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ ca-certificates@20240203 โ€บ - openssl@3.0.13-0ubuntu3.3 + openssl@3.0.13-0ubuntu3.4 โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 + openssl/libssl3t64@3.0.13-0ubuntu3.4
                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ libssh/libssh-4@0.10.6-2build2 โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 + openssl/libssl3t64@3.0.13-0ubuntu3.4
                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ krb5/libkrb5-3@1.20.1-6ubuntu2.1 โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 + openssl/libssl3t64@3.0.13-0ubuntu3.4
                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ openldap/libldap2@2.6.7+dfsg-1~exp1ubuntu8 โ€บ cyrus-sasl2/libsasl2-2@2.1.28+dfsg1-5ubuntu3.1 โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 + openssl/libssl3t64@3.0.13-0ubuntu3.4
                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ - openssl@3.0.13-0ubuntu3.3 + openssl@3.0.13-0ubuntu3.4
                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ ca-certificates@20240203 โ€บ - openssl@3.0.13-0ubuntu3.3 + openssl@3.0.13-0ubuntu3.4 @@ -677,224 +677,6 @@

                              References

                              More about this vulnerability

                            -
                            -
                            -

                            CVE-2024-6119

                            -
                            - -
                            - medium severity -
                            - -
                            - -
                              -
                            • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile -
                            • -
                            • - Package Manager: ubuntu:24.04 -
                            • -
                            • - Vulnerable module: - - openssl/libssl3t64 -
                            • - -
                            • Introduced through: - - docker-image|quay.io/argoproj/argocd@v2.12.3 and openssl/libssl3t64@3.0.13-0ubuntu3.3 - -
                            • -
                            - -
                            - - -

                            Detailed paths

                            - -
                              -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 - - - -
                            • -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - coreutils@9.4-3ubuntu6 - โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 - - - -
                            • -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - cyrus-sasl2/libsasl2-modules@2.1.28+dfsg1-5ubuntu3.1 - โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 - - - -
                            • -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - libfido2/libfido2-1@1.14.0-1build3 - โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 - - - -
                            • -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - openssh/openssh-client@1:9.6p1-3ubuntu13.5 - โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 - - - -
                            • -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - ca-certificates@20240203 - โ€บ - openssl@3.0.13-0ubuntu3.3 - โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 - - - -
                            • -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - git@1:2.43.0-1ubuntu7.1 - โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 - โ€บ - libssh/libssh-4@0.10.6-2build2 - โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 - - - -
                            • -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - git@1:2.43.0-1ubuntu7.1 - โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 - โ€บ - krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 - โ€บ - krb5/libkrb5-3@1.20.1-6ubuntu2.1 - โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 - - - -
                            • -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - git@1:2.43.0-1ubuntu7.1 - โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 - โ€บ - openldap/libldap2@2.6.7+dfsg-1~exp1ubuntu8 - โ€บ - cyrus-sasl2/libsasl2-2@2.1.28+dfsg1-5ubuntu3.1 - โ€บ - openssl/libssl3t64@3.0.13-0ubuntu3.3 - - - -
                            • -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - openssl@3.0.13-0ubuntu3.3 - - - -
                            • -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - ca-certificates@20240203 - โ€บ - openssl@3.0.13-0ubuntu3.3 - - - -
                            • -
                            - -
                            - -
                            - -

                            NVD Description

                            -

                            Note: Versions mentioned in the description apply only to the upstream openssl package and not the openssl package as distributed by Ubuntu. - See How to fix? for Ubuntu:24.04 relevant fixed versions and status.

                            -

                            Issue summary: Applications performing certificate name checks (e.g., TLS - clients checking server certificates) may attempt to read an invalid memory - address resulting in abnormal termination of the application process.

                            -

                            Impact summary: Abnormal termination of an application can a cause a denial of - service.

                            -

                            Applications performing certificate name checks (e.g., TLS clients checking - server certificates) may attempt to read an invalid memory address when - comparing the expected name with an otherName subject alternative name of an - X.509 certificate. This may result in an exception that terminates the - application program.

                            -

                            Note that basic certificate chain validation (signatures, dates, ...) is not - affected, the denial of service can occur only when the application also - specifies an expected DNS name, Email address or IP address.

                            -

                            TLS servers rarely solicit client certificates, and even when they do, they - generally don't perform a name check against a reference identifier (expected - identity), but rather extract the presented identity after checking the - certificate chain. So TLS servers are generally not affected and the severity - of the issue is Moderate.

                            -

                            The FIPS modules in 3.3, 3.2, 3.1 and 3.0 are not affected by this issue.

                            -

                            Remediation

                            -

                            Upgrade Ubuntu:24.04 openssl to version 3.0.13-0ubuntu3.4 or higher.

                            -

                            References

                            - - -
                            - - -

                            Information Exposure

                            @@ -908,7 +690,7 @@

                            Information Exposure

                            • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                            • Package Manager: ubuntu:24.04 @@ -921,7 +703,7 @@

                              Information Exposure

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 and libgcrypt20@1.10.3-2build1 + docker-image|quay.io/argoproj/argocd@v2.12.4 and libgcrypt20@1.10.3-2build1
                            @@ -934,7 +716,7 @@

                            Detailed paths

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ libgcrypt20@1.10.3-2build1 @@ -943,7 +725,7 @@

                              Detailed paths

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/dirmngr@2.4.4-2ubuntu17 โ€บ @@ -954,7 +736,7 @@

                              Detailed paths

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/gpg@2.4.4-2ubuntu17 โ€บ @@ -965,7 +747,7 @@

                              Detailed paths

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/gpg-agent@2.4.4-2ubuntu17 โ€บ @@ -976,7 +758,7 @@

                              Detailed paths

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ apt@2.7.14build2 โ€บ @@ -989,7 +771,7 @@

                              Detailed paths

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ apt@2.7.14build2 โ€บ @@ -1002,7 +784,7 @@

                              Detailed paths

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/gpg@2.4.4-2ubuntu17 โ€บ @@ -1015,7 +797,7 @@

                              Detailed paths

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ apt@2.7.14build2 โ€บ @@ -1071,7 +853,7 @@

                              CVE-2024-26462

                              • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                              • Package Manager: ubuntu:24.04 @@ -1085,7 +867,7 @@

                                CVE-2024-26462

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3, git@1:2.43.0-1ubuntu7.1 and others + docker-image|quay.io/argoproj/argocd@v2.12.4, git@1:2.43.0-1ubuntu7.1 and others
                              @@ -1097,11 +879,11 @@

                              Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1112,11 +894,11 @@

                                Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1129,11 +911,11 @@

                                Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1144,11 +926,11 @@

                                Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1161,11 +943,11 @@

                                Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1180,11 +962,11 @@

                                Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1195,7 +977,7 @@

                                Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ openssh/openssh-client@1:9.6p1-3ubuntu13.5 โ€บ @@ -1206,11 +988,11 @@

                                Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 @@ -1219,11 +1001,11 @@

                                Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ libssh/libssh-4@0.10.6-2build2 โ€บ @@ -1234,7 +1016,7 @@

                                Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ krb5/krb5-locales@1.20.1-6ubuntu2.1 @@ -1279,7 +1061,7 @@

                                Denial of Service (DoS)

                                • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argo-cd/v2 โ€บ /usr/local/bin/argocd
                                • Package Manager: golang @@ -1376,299 +1158,6 @@

                                  References

                                  More about this vulnerability

                            -
                            -
                            -

                            Integer Overflow or Wraparound

                            -
                            - -
                            - medium severity -
                            - -
                            - -
                              -
                            • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile -
                            • -
                            • - Package Manager: ubuntu:24.04 -
                            • -
                            • - Vulnerable module: - - expat/libexpat1 -
                            • - -
                            • Introduced through: - - - docker-image|quay.io/argoproj/argocd@v2.12.3, git@1:2.43.0-1ubuntu7.1 and others -
                            • -
                            - -
                            - - -

                            Detailed paths

                            - -
                              -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - git@1:2.43.0-1ubuntu7.1 - โ€บ - expat/libexpat1@2.6.1-2build1 - - - -
                            • -
                            - -
                            - -
                            - -

                            NVD Description

                            -

                            Note: Versions mentioned in the description apply only to the upstream expat package and not the expat package as distributed by Ubuntu. - See How to fix? for Ubuntu:24.04 relevant fixed versions and status.

                            -

                            An issue was discovered in libexpat before 2.6.3. dtdCopy in xmlparse.c can have an integer overflow for nDefaultAtts on 32-bit platforms (where UINT_MAX equals SIZE_MAX).

                            -

                            Remediation

                            -

                            Upgrade Ubuntu:24.04 expat to version 2.6.1-2ubuntu0.1 or higher.

                            -

                            References

                            - - -
                            - - - -
                            -
                            -

                            XML External Entity (XXE) Injection

                            -
                            - -
                            - medium severity -
                            - -
                            - -
                              -
                            • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile -
                            • -
                            • - Package Manager: ubuntu:24.04 -
                            • -
                            • - Vulnerable module: - - expat/libexpat1 -
                            • - -
                            • Introduced through: - - - docker-image|quay.io/argoproj/argocd@v2.12.3, git@1:2.43.0-1ubuntu7.1 and others -
                            • -
                            - -
                            - - -

                            Detailed paths

                            - -
                              -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - git@1:2.43.0-1ubuntu7.1 - โ€บ - expat/libexpat1@2.6.1-2build1 - - - -
                            • -
                            - -
                            - -
                            - -

                            NVD Description

                            -

                            Note: Versions mentioned in the description apply only to the upstream expat package and not the expat package as distributed by Ubuntu. - See How to fix? for Ubuntu:24.04 relevant fixed versions and status.

                            -

                            An issue was discovered in libexpat before 2.6.3. xmlparse.c does not reject a negative length for XML_ParseBuffer.

                            -

                            Remediation

                            -

                            Upgrade Ubuntu:24.04 expat to version 2.6.1-2ubuntu0.1 or higher.

                            -

                            References

                            - - -
                            - - - -
                            -
                            -

                            Integer Overflow or Wraparound

                            -
                            - -
                            - medium severity -
                            - -
                            - -
                              -
                            • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile -
                            • -
                            • - Package Manager: ubuntu:24.04 -
                            • -
                            • - Vulnerable module: - - expat/libexpat1 -
                            • - -
                            • Introduced through: - - - docker-image|quay.io/argoproj/argocd@v2.12.3, git@1:2.43.0-1ubuntu7.1 and others -
                            • -
                            - -
                            - - -

                            Detailed paths

                            - -
                              -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - git@1:2.43.0-1ubuntu7.1 - โ€บ - expat/libexpat1@2.6.1-2build1 - - - -
                            • -
                            - -
                            - -
                            - -

                            NVD Description

                            -

                            Note: Versions mentioned in the description apply only to the upstream expat package and not the expat package as distributed by Ubuntu. - See How to fix? for Ubuntu:24.04 relevant fixed versions and status.

                            -

                            An issue was discovered in libexpat before 2.6.3. nextScaffoldPart in xmlparse.c can have an integer overflow for m_groupSize on 32-bit platforms (where UINT_MAX equals SIZE_MAX).

                            -

                            Remediation

                            -

                            Upgrade Ubuntu:24.04 expat to version 2.6.1-2ubuntu0.1 or higher.

                            -

                            References

                            - - -
                            - - - -
                            -
                            -

                            CVE-2024-8096

                            -
                            - -
                            - medium severity -
                            - -
                            - -
                              -
                            • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile -
                            • -
                            • - Package Manager: ubuntu:24.04 -
                            • -
                            • - Vulnerable module: - - curl/libcurl3t64-gnutls -
                            • - -
                            • Introduced through: - - - docker-image|quay.io/argoproj/argocd@v2.12.3, git@1:2.43.0-1ubuntu7.1 and others -
                            • -
                            - -
                            - - -

                            Detailed paths

                            - -
                              -
                            • - Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 - โ€บ - git@1:2.43.0-1ubuntu7.1 - โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 - - - -
                            • -
                            - -
                            - -
                            - -

                            NVD Description

                            -

                            Note: Versions mentioned in the description apply only to the upstream curl package and not the curl package as distributed by Ubuntu. - See How to fix? for Ubuntu:24.04 relevant fixed versions and status.

                            -

                            When curl is told to use the Certificate Status Request TLS extension, often referred to as OCSP stapling, to verify that the server certificate is valid, it might fail to detect some OCSP problems and instead wrongly consider the response as fine. If the returned status reports another error than 'revoked' (like for example 'unauthorized') it is not treated as a bad certficate.

                            -

                            Remediation

                            -

                            Upgrade Ubuntu:24.04 curl to version 8.5.0-2ubuntu10.4 or higher.

                            -

                            References

                            - - -
                            - - -

                            Release of Invalid Pointer or Reference

                            @@ -1682,7 +1171,7 @@

                            Release of Invalid Pointer or Reference

                            • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                            • Package Manager: ubuntu:24.04 @@ -1695,7 +1184,7 @@

                              Release of Invalid Pointer or Reference

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 and patch@2.7.6-7build3 + docker-image|quay.io/argoproj/argocd@v2.12.4 and patch@2.7.6-7build3
                            @@ -1708,7 +1197,7 @@

                            Detailed paths

                            • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ patch@2.7.6-7build3 @@ -1752,7 +1241,7 @@

                              Double Free

                              • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                              • Package Manager: ubuntu:24.04 @@ -1765,7 +1254,7 @@

                                Double Free

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 and patch@2.7.6-7build3 + docker-image|quay.io/argoproj/argocd@v2.12.4 and patch@2.7.6-7build3
                              @@ -1778,7 +1267,7 @@

                              Detailed paths

                              • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ patch@2.7.6-7build3 @@ -1827,7 +1316,7 @@

                                CVE-2024-26458

                                • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                                • Package Manager: ubuntu:24.04 @@ -1841,7 +1330,7 @@

                                  CVE-2024-26458

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3, git@1:2.43.0-1ubuntu7.1 and others + docker-image|quay.io/argoproj/argocd@v2.12.4, git@1:2.43.0-1ubuntu7.1 and others
                                @@ -1853,11 +1342,11 @@

                                Detailed paths

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1868,11 +1357,11 @@

                                  Detailed paths

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1885,11 +1374,11 @@

                                  Detailed paths

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1900,11 +1389,11 @@

                                  Detailed paths

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1917,11 +1406,11 @@

                                  Detailed paths

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1936,11 +1425,11 @@

                                  Detailed paths

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -1951,7 +1440,7 @@

                                  Detailed paths

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ openssh/openssh-client@1:9.6p1-3ubuntu13.5 โ€บ @@ -1962,11 +1451,11 @@

                                  Detailed paths

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 @@ -1975,11 +1464,11 @@

                                  Detailed paths

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ libssh/libssh-4@0.10.6-2build2 โ€บ @@ -1990,7 +1479,7 @@

                                  Detailed paths

                                • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ krb5/krb5-locales@1.20.1-6ubuntu2.1 @@ -2035,7 +1524,7 @@

                                  CVE-2024-26461

                                  • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                                  • Package Manager: ubuntu:24.04 @@ -2049,7 +1538,7 @@

                                    CVE-2024-26461

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3, git@1:2.43.0-1ubuntu7.1 and others + docker-image|quay.io/argoproj/argocd@v2.12.4, git@1:2.43.0-1ubuntu7.1 and others
                                  @@ -2061,11 +1550,11 @@

                                  Detailed paths

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -2076,11 +1565,11 @@

                                    Detailed paths

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -2093,11 +1582,11 @@

                                    Detailed paths

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -2108,11 +1597,11 @@

                                    Detailed paths

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -2125,11 +1614,11 @@

                                    Detailed paths

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -2144,11 +1633,11 @@

                                    Detailed paths

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 โ€บ @@ -2159,7 +1648,7 @@

                                    Detailed paths

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ openssh/openssh-client@1:9.6p1-3ubuntu13.5 โ€บ @@ -2170,11 +1659,11 @@

                                    Detailed paths

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ krb5/libgssapi-krb5-2@1.20.1-6ubuntu2.1 @@ -2183,11 +1672,11 @@

                                    Detailed paths

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ - curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.3 + curl/libcurl3t64-gnutls@8.5.0-2ubuntu10.4 โ€บ libssh/libssh-4@0.10.6-2build2 โ€บ @@ -2198,7 +1687,7 @@

                                    Detailed paths

                                  • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ krb5/krb5-locales@1.20.1-6ubuntu2.1 @@ -2243,7 +1732,7 @@

                                    Out-of-bounds Write

                                    • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                                    • Package Manager: ubuntu:24.04 @@ -2256,7 +1745,7 @@

                                      Out-of-bounds Write

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 and gnupg2/gpgv@2.4.4-2ubuntu17 + docker-image|quay.io/argoproj/argocd@v2.12.4 and gnupg2/gpgv@2.4.4-2ubuntu17
                                    @@ -2269,7 +1758,7 @@

                                    Detailed paths

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/gpgv@2.4.4-2ubuntu17 @@ -2278,7 +1767,7 @@

                                      Detailed paths

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ apt@2.7.14build2 โ€บ @@ -2289,7 +1778,7 @@

                                      Detailed paths

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/dirmngr@2.4.4-2ubuntu17 โ€บ @@ -2300,7 +1789,7 @@

                                      Detailed paths

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/gpg-agent@2.4.4-2ubuntu17 โ€บ @@ -2311,7 +1800,7 @@

                                      Detailed paths

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/gpg@2.4.4-2ubuntu17 โ€บ @@ -2322,7 +1811,7 @@

                                      Detailed paths

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/dirmngr@2.4.4-2ubuntu17 @@ -2331,7 +1820,7 @@

                                      Detailed paths

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/gpg@2.4.4-2ubuntu17 @@ -2340,7 +1829,7 @@

                                      Detailed paths

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ gnupg2/gpg-agent@2.4.4-2ubuntu17 @@ -2389,7 +1878,7 @@

                                      Allocation of Resources Without Limits or Throttling

                                    • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                                    • Package Manager: ubuntu:24.04 @@ -2402,7 +1891,7 @@

                                      Allocation of Resources Without Limits or Throttling

                                      Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 and glibc/libc-bin@2.39-0ubuntu8.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 and glibc/libc-bin@2.39-0ubuntu8.3
                                    @@ -2415,7 +1904,7 @@

                                    Detailed paths

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ glibc/libc-bin@2.39-0ubuntu8.3 @@ -2424,7 +1913,7 @@

                                      Detailed paths

                                    • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ glibc/libc6@2.39-0ubuntu8.3 @@ -2470,7 +1959,7 @@

                                      Improper Input Validation

                                      • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                                      • Package Manager: ubuntu:24.04 @@ -2484,7 +1973,7 @@

                                        Improper Input Validation

                                      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3, git@1:2.43.0-1ubuntu7.1 and others + docker-image|quay.io/argoproj/argocd@v2.12.4, git@1:2.43.0-1ubuntu7.1 and others
                                      @@ -2496,7 +1985,7 @@

                                      Detailed paths

                                      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 โ€บ @@ -2507,7 +1996,7 @@

                                        Detailed paths

                                      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git@1:2.43.0-1ubuntu7.1 @@ -2516,7 +2005,7 @@

                                        Detailed paths

                                      • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ git-lfs@3.4.1-1ubuntu0.1 โ€บ @@ -2563,7 +2052,7 @@

                                        Improper Input Validation

                                        • - Manifest file: quay.io/argoproj/argocd:v2.12.3/argoproj/argocd โ€บ Dockerfile + Manifest file: quay.io/argoproj/argocd:v2.12.4/argoproj/argocd โ€บ Dockerfile
                                        • Package Manager: ubuntu:24.04 @@ -2576,7 +2065,7 @@

                                          Improper Input Validation

                                        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 and coreutils@9.4-3ubuntu6 + docker-image|quay.io/argoproj/argocd@v2.12.4 and coreutils@9.4-3ubuntu6
                                        @@ -2589,7 +2078,7 @@

                                        Detailed paths

                                        • Introduced through: - docker-image|quay.io/argoproj/argocd@v2.12.3 + docker-image|quay.io/argoproj/argocd@v2.12.4 โ€บ coreutils@9.4-3ubuntu6 diff --git a/docs/snyk/v2.12.3/redis_7.0.15-alpine.html b/docs/snyk/v2.12.4/redis_7.0.15-alpine.html similarity index 99% rename from docs/snyk/v2.12.3/redis_7.0.15-alpine.html rename to docs/snyk/v2.12.4/redis_7.0.15-alpine.html index e3cc28e76700fe..ec96ccc6815041 100644 --- a/docs/snyk/v2.12.3/redis_7.0.15-alpine.html +++ b/docs/snyk/v2.12.4/redis_7.0.15-alpine.html @@ -456,7 +456,7 @@

                                          Snyk test report

                                          -

                                          September 22nd 2024, 12:24:31 am (UTC+00:00)

                                          +

                                          October 6th 2024, 12:32:34 am (UTC+00:00)

                                          Scanned the following paths: diff --git a/docs/snyk/v2.13.0-rc2/argocd-iac-install.html b/docs/snyk/v2.13.0-rc2/argocd-iac-install.html index 1fb9ff7afdb66f..c335dd9fa67fc9 100644 --- a/docs/snyk/v2.13.0-rc2/argocd-iac-install.html +++ b/docs/snyk/v2.13.0-rc2/argocd-iac-install.html @@ -456,7 +456,7 @@

                                          Snyk test report

                                          -

                                          September 22nd 2024, 12:23:23 am (UTC+00:00)

                                          +

                                          October 6th 2024, 12:31:26 am (UTC+00:00)

                                          Scanned the following path: diff --git a/docs/snyk/v2.13.0-rc2/argocd-iac-namespace-install.html b/docs/snyk/v2.13.0-rc2/argocd-iac-namespace-install.html index ecec28af1a8cd9..54b0b0fcf5aa3e 100644 --- a/docs/snyk/v2.13.0-rc2/argocd-iac-namespace-install.html +++ b/docs/snyk/v2.13.0-rc2/argocd-iac-namespace-install.html @@ -456,7 +456,7 @@

                                          Snyk test report

                                          -

                                          September 22nd 2024, 12:23:32 am (UTC+00:00)

                                          +

                                          October 6th 2024, 12:31:35 am (UTC+00:00)

                                          Scanned the following path: diff --git a/docs/snyk/v2.13.0-rc2/argocd-test.html b/docs/snyk/v2.13.0-rc2/argocd-test.html index 339b8e739fba16..b9f1130aa02665 100644 --- a/docs/snyk/v2.13.0-rc2/argocd-test.html +++ b/docs/snyk/v2.13.0-rc2/argocd-test.html @@ -456,7 +456,7 @@

                                          Snyk test report

                                          -

                                          September 22nd 2024, 12:21:26 am (UTC+00:00)

                                          +

                                          October 6th 2024, 12:29:29 am (UTC+00:00)

                                          Scanned the following paths: diff --git a/docs/snyk/v2.13.0-rc2/ghcr.io_dexidp_dex_v2.41.1.html b/docs/snyk/v2.13.0-rc2/ghcr.io_dexidp_dex_v2.41.1.html index 6a121eec058198..52e02668a290b8 100644 --- a/docs/snyk/v2.13.0-rc2/ghcr.io_dexidp_dex_v2.41.1.html +++ b/docs/snyk/v2.13.0-rc2/ghcr.io_dexidp_dex_v2.41.1.html @@ -456,7 +456,7 @@

                                          Snyk test report

                                          -

                                          September 22nd 2024, 12:21:32 am (UTC+00:00)

                                          +

                                          October 6th 2024, 12:29:34 am (UTC+00:00)

                                          Scanned the following paths: diff --git a/docs/snyk/v2.13.0-rc2/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html b/docs/snyk/v2.13.0-rc2/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html index 8197e5ec4909eb..a9e4bc3247cca7 100644 --- a/docs/snyk/v2.13.0-rc2/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html +++ b/docs/snyk/v2.13.0-rc2/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html @@ -456,7 +456,7 @@

                                          Snyk test report

                                          -

                                          September 22nd 2024, 12:21:37 am (UTC+00:00)

                                          +

                                          October 6th 2024, 12:29:38 am (UTC+00:00)

                                          Scanned the following path: diff --git a/docs/snyk/v2.13.0-rc2/public.ecr.aws_docker_library_redis_7.0.15-alpine.html b/docs/snyk/v2.13.0-rc2/public.ecr.aws_docker_library_redis_7.0.15-alpine.html index 26e6ff3618a3f1..a2aca1f99ef53d 100644 --- a/docs/snyk/v2.13.0-rc2/public.ecr.aws_docker_library_redis_7.0.15-alpine.html +++ b/docs/snyk/v2.13.0-rc2/public.ecr.aws_docker_library_redis_7.0.15-alpine.html @@ -456,7 +456,7 @@

                                          Snyk test report

                                          -

                                          September 22nd 2024, 12:21:40 am (UTC+00:00)

                                          +

                                          October 6th 2024, 12:29:41 am (UTC+00:00)

                                          Scanned the following paths: diff --git a/docs/snyk/v2.13.0-rc2/quay.io_argoproj_argocd_v2.13.0-rc2.html b/docs/snyk/v2.13.0-rc2/quay.io_argoproj_argocd_v2.13.0-rc2.html index 043d857a863c83..e342553fab3eee 100644 --- a/docs/snyk/v2.13.0-rc2/quay.io_argoproj_argocd_v2.13.0-rc2.html +++ b/docs/snyk/v2.13.0-rc2/quay.io_argoproj_argocd_v2.13.0-rc2.html @@ -456,7 +456,7 @@

                                          Snyk test report

                                          -

                                          September 22nd 2024, 12:21:56 am (UTC+00:00)

                                          +

                                          October 6th 2024, 12:29:58 am (UTC+00:00)

                                          Scanned the following paths: diff --git a/docs/snyk/v2.13.0-rc2/redis_7.0.15-alpine.html b/docs/snyk/v2.13.0-rc2/redis_7.0.15-alpine.html index 9ce47860347050..3f63a9036018be 100644 --- a/docs/snyk/v2.13.0-rc2/redis_7.0.15-alpine.html +++ b/docs/snyk/v2.13.0-rc2/redis_7.0.15-alpine.html @@ -456,7 +456,7 @@

                                          Snyk test report

                                          -

                                          September 22nd 2024, 12:22:00 am (UTC+00:00)

                                          +

                                          October 6th 2024, 12:30:02 am (UTC+00:00)

                                          Scanned the following paths: diff --git a/docs/user-guide/commands/argocd_admin_app_generate-spec.md b/docs/user-guide/commands/argocd_admin_app_generate-spec.md index 2826917d4765c6..5f45d5456c2240 100644 --- a/docs/user-guide/commands/argocd_admin_app_generate-spec.md +++ b/docs/user-guide/commands/argocd_admin_app_generate-spec.md @@ -56,6 +56,7 @@ argocd admin app generate-spec APPNAME [flags] --helm-set-file stringArray Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2) --helm-set-string stringArray Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2) --helm-skip-crds Skip helm crd installation step + --helm-skip-tests Skip helm test manifests installation step --helm-version string Helm version -h, --help help for generate-spec --ignore-missing-value-files Ignore locally missing valueFiles when setting helm template --values diff --git a/docs/user-guide/commands/argocd_admin_proj_generate-spec.md b/docs/user-guide/commands/argocd_admin_proj_generate-spec.md index c94eba4365ef8e..2be37408d8153f 100644 --- a/docs/user-guide/commands/argocd_admin_proj_generate-spec.md +++ b/docs/user-guide/commands/argocd_admin_proj_generate-spec.md @@ -30,6 +30,7 @@ argocd admin proj generate-spec PROJECT [flags] --deny-namespaced-resource stringArray List of denied namespaced resources --description string Project description -d, --dest stringArray Permitted destination server and namespace (e.g. https://192.168.99.100:8443,default) + --dest-service-accounts stringArray Destination server, namespace and target service account (e.g. https://192.168.99.100:8443,default,default-sa) -f, --file string Filename or URL to Kubernetes manifests for the project -h, --help help for generate-spec -i, --inline If set then generated resource is written back to the file specified in --file flag diff --git a/docs/user-guide/commands/argocd_app_add-source.md b/docs/user-guide/commands/argocd_app_add-source.md index b6bc3ae3de6c23..afc59c1c2e57cc 100644 --- a/docs/user-guide/commands/argocd_app_add-source.md +++ b/docs/user-guide/commands/argocd_app_add-source.md @@ -38,6 +38,7 @@ argocd app add-source APPNAME [flags] --helm-set-file stringArray Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2) --helm-set-string stringArray Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2) --helm-skip-crds Skip helm crd installation step + --helm-skip-tests Skip helm test manifests installation step --helm-version string Helm version -h, --help help for add-source --ignore-missing-value-files Ignore locally missing valueFiles when setting helm template --values diff --git a/docs/user-guide/commands/argocd_app_create.md b/docs/user-guide/commands/argocd_app_create.md index 662ee0b92644a0..a042c6af8c67eb 100644 --- a/docs/user-guide/commands/argocd_app_create.md +++ b/docs/user-guide/commands/argocd_app_create.md @@ -58,6 +58,7 @@ argocd app create APPNAME [flags] --helm-set-file stringArray Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2) --helm-set-string stringArray Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2) --helm-skip-crds Skip helm crd installation step + --helm-skip-tests Skip helm test manifests installation step --helm-version string Helm version -h, --help help for create --ignore-missing-value-files Ignore locally missing valueFiles when setting helm template --values diff --git a/docs/user-guide/commands/argocd_app_diff.md b/docs/user-guide/commands/argocd_app_diff.md index 07efe70af6b40b..d4c22d323db6b6 100644 --- a/docs/user-guide/commands/argocd_app_diff.md +++ b/docs/user-guide/commands/argocd_app_diff.md @@ -19,7 +19,8 @@ argocd app diff APPNAME [flags] ``` -N, --app-namespace string Only render the difference in namespace - --exit-code Return non-zero exit code when there is a diff (default true) + --diff-exit-code int Return specified exit code when there is a diff. Typical error code is 20. (default 1) + --exit-code Return non-zero exit code when there is a diff. May also return non-zero exit code if there is an error. (default true) --hard-refresh Refresh application data as well as target manifests cache -h, --help help for diff --ignore-normalizer-jq-execution-timeout duration Set ignore normalizer JQ execution timeout (default 1s) diff --git a/docs/user-guide/commands/argocd_app_set.md b/docs/user-guide/commands/argocd_app_set.md index 878d6e098e3ca1..4d4269b5bee117 100644 --- a/docs/user-guide/commands/argocd_app_set.md +++ b/docs/user-guide/commands/argocd_app_set.md @@ -47,6 +47,7 @@ argocd app set APPNAME [flags] --helm-set-file stringArray Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2) --helm-set-string stringArray Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2) --helm-skip-crds Skip helm crd installation step + --helm-skip-tests Skip helm test manifests installation step --helm-version string Helm version -h, --help help for set --ignore-missing-value-files Ignore locally missing valueFiles when setting helm template --values diff --git a/docs/user-guide/commands/argocd_proj_create.md b/docs/user-guide/commands/argocd_proj_create.md index c8b27e35bb7624..5d222c7a6eab00 100644 --- a/docs/user-guide/commands/argocd_proj_create.md +++ b/docs/user-guide/commands/argocd_proj_create.md @@ -27,6 +27,7 @@ argocd proj create PROJECT [flags] --deny-namespaced-resource stringArray List of denied namespaced resources --description string Project description -d, --dest stringArray Permitted destination server and namespace (e.g. https://192.168.99.100:8443,default) + --dest-service-accounts stringArray Destination server, namespace and target service account (e.g. https://192.168.99.100:8443,default,default-sa) -f, --file string Filename or URL to Kubernetes manifests for the project -h, --help help for create --orphaned-resources Enables orphaned resources monitoring diff --git a/docs/user-guide/commands/argocd_proj_set.md b/docs/user-guide/commands/argocd_proj_set.md index 7b4d79ff135889..daf633a7cb9ca0 100644 --- a/docs/user-guide/commands/argocd_proj_set.md +++ b/docs/user-guide/commands/argocd_proj_set.md @@ -27,6 +27,7 @@ argocd proj set PROJECT [flags] --deny-namespaced-resource stringArray List of denied namespaced resources --description string Project description -d, --dest stringArray Permitted destination server and namespace (e.g. https://192.168.99.100:8443,default) + --dest-service-accounts stringArray Destination server, namespace and target service account (e.g. https://192.168.99.100:8443,default,default-sa) -h, --help help for set --orphaned-resources Enables orphaned resources monitoring --orphaned-resources-warn Specifies if applications should have a warning condition when orphaned resources detected diff --git a/docs/user-guide/helm.md b/docs/user-guide/helm.md index c768b50835a246..cae8ffdcefca23 100644 --- a/docs/user-guide/helm.md +++ b/docs/user-guide/helm.md @@ -418,7 +418,7 @@ repoServer: value: /helm-working-dir initContainers: - name: helm-gcp-authentication - image: alpine/helm:3.8.1 + image: alpine/helm:3.16.1 volumeMounts: - name: helm-working-dir mountPath: /helm-working-dir @@ -498,3 +498,23 @@ spec: helm: skipCrds: true ``` + + +## Helm `--skip-tests` + +By default, Helm includes test manifests when rendering templates. Argo CD currently skips manifests that include hooks not supported by Argo CD, including [Helm test hooks](https://helm.sh/docs/topics/chart_tests/). While this feature covers many testing use cases, it is not totally congruent with --skip-tests, so the --skip-tests option can be used. + +If needed, it is possible to skip the test manifests installation step with the `helm-skip-tests` flag on the cli: + +```bash +argocd app set helm-guestbook --helm-skip-tests +``` + +Or using declarative syntax: + +```yaml +spec: + source: + helm: + skipTests: true # or false +``` \ No newline at end of file diff --git a/docs/user-guide/resource_tracking.md b/docs/user-guide/resource_tracking.md index e62a7c094f4e26..ff43d6d739910f 100644 --- a/docs/user-guide/resource_tracking.md +++ b/docs/user-guide/resource_tracking.md @@ -65,6 +65,14 @@ metadata: The advantages of using the tracking id annotation is that there are no clashes any more with other Kubernetes tools and Argo CD is never confused about the owner of a resource. The `annotation+label` can also be used if you want other tools to understand resources managed by Argo CD. +### Installation ID + +If you are managing one cluster using multiple Argo CD instances, you will need to set `installationID` in the Argo CD ConfigMap. This will prevent conflicts between +the different Argo CD instances: + +* Each managed resource will have the annotation `argocd.argoproj.io/tracking-id: ` +* It is possible to have applications with the same name in Argo CD instances without causing conflicts. + ### Non self-referencing annotations When using the tracking method `annotation` or `annotation+label`, Argo CD will consider the resource properties in the annotation (name, namespace, group and kind) to determine whether the resource should be compared against the desired state. If the tracking annotation does not reference the resource it is applied to, the resource will neither affect the application's sync status nor be marked for pruning. diff --git a/go.mod b/go.mod index 2d020f68e928a5..71488e82e9f2c3 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/alicebob/miniredis/v2 v2.33.0 github.com/antonmedv/expr v1.15.1 github.com/argoproj/gitops-engine v0.7.1-0.20240917171920-72bcdda3f0a5 - github.com/argoproj/notifications-engine v0.4.1-0.20240606074338-0802cd427621 + github.com/argoproj/notifications-engine v0.4.1-0.20241005182503-22ccfe0caf45 github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1 github.com/aws/aws-sdk-go v1.55.5 github.com/bmatcuk/doublestar/v4 v4.6.1 @@ -22,7 +22,7 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 github.com/chainguard-dev/git-urls v1.0.2 github.com/coreos/go-oidc/v3 v3.11.0 - github.com/cyphar/filepath-securejoin v0.3.2 + github.com/cyphar/filepath-securejoin v0.3.3 github.com/dustin/go-humanize v1.0.1 github.com/evanphx/json-patch v5.9.0+incompatible github.com/expr-lang/expr v1.16.9 @@ -77,21 +77,21 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 github.com/valyala/fasttemplate v1.2.2 - github.com/xanzy/go-gitlab v0.109.0 + github.com/xanzy/go-gitlab v0.110.0 github.com/yuin/gopher-lua v1.1.1 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 go.opentelemetry.io/otel v1.30.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 go.opentelemetry.io/otel/sdk v1.30.0 - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.28.0 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 - golang.org/x/net v0.29.0 + golang.org/x/net v0.30.0 golang.org/x/oauth2 v0.23.0 golang.org/x/sync v0.8.0 - golang.org/x/term v0.24.0 - golang.org/x/time v0.6.0 + golang.org/x/term v0.25.0 + golang.org/x/time v0.7.0 google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 - google.golang.org/grpc v1.67.0 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 @@ -150,8 +150,8 @@ require ( go.opencensus.io v0.24.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/api v0.132.0 // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect diff --git a/go.sum b/go.sum index 74da7903bd3dd6..131c551adb326c 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb github.com/appscode/go v0.0.0-20191119085241-0887d8ec2ecc/go.mod h1:OawnOmAL4ZX3YaPdN+8HTNwBveT1jMsqP74moa9XUbE= github.com/argoproj/gitops-engine v0.7.1-0.20240917171920-72bcdda3f0a5 h1:K/e+NsNmE4BccRu21QpqUxkTHxU9YWjU3M775Ck+V/E= github.com/argoproj/gitops-engine v0.7.1-0.20240917171920-72bcdda3f0a5/go.mod h1:b1vuwkyMUszyUK+USUJqC8vJijnQsEPNDpC+sDdDLtM= -github.com/argoproj/notifications-engine v0.4.1-0.20240606074338-0802cd427621 h1:Yg1nt+D2uDK1SL2jSlfukA4yc7db184TTN7iWy3voRE= -github.com/argoproj/notifications-engine v0.4.1-0.20240606074338-0802cd427621/go.mod h1:N0A4sEws2soZjEpY4hgZpQS8mRIEw6otzwfkgc3g9uQ= +github.com/argoproj/notifications-engine v0.4.1-0.20241005182503-22ccfe0caf45 h1:ry/oysT+kBvzLbLPhYAfaqhAtpRl/ONCuWnFZo1emIM= +github.com/argoproj/notifications-engine v0.4.1-0.20241005182503-22ccfe0caf45/go.mod h1:N0A4sEws2soZjEpY4hgZpQS8mRIEw6otzwfkgc3g9uQ= github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1 h1:qsHwwOJ21K2Ao0xPju1sNuqphyMnMYkyB3ZLoLtxWpo= github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1/go.mod h1:CZHlkyAD1/+FbEn6cB2DQTj48IoLGvEYsWEvtzP3238= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -205,8 +205,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.3.2 h1:QhZu5AxQ+o1XZH0Ye05YzvJ0kAdK6VQc0z9NNMek7gc= -github.com/cyphar/filepath-securejoin v0.3.2/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= +github.com/cyphar/filepath-securejoin v0.3.3 h1:lofZkCEVFIBe0KcdQOzFs8Soy9oaHOWl4gGtPI+gCFc= +github.com/cyphar/filepath-securejoin v0.3.3/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -950,8 +950,8 @@ github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAh github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xanzy/go-gitlab v0.109.0 h1:RcRme5w8VpLXTSTTMZdVoQWY37qTJWg+gwdQl4aAttE= -github.com/xanzy/go-gitlab v0.109.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY= +github.com/xanzy/go-gitlab v0.110.0 h1:hsFIFp01v/0D0sdUXoZfRk6CROzZbHQplk6NzKSFKhc= +github.com/xanzy/go-gitlab v0.110.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -1041,8 +1041,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= @@ -1126,8 +1126,8 @@ golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1223,8 +1223,8 @@ golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1249,8 +1249,8 @@ golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1270,13 +1270,13 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1365,8 +1365,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= diff --git a/hack/installers/install-lint-tools.sh b/hack/installers/install-lint-tools.sh index 54e7b725478c85..d11c3f7d7b491b 100755 --- a/hack/installers/install-lint-tools.sh +++ b/hack/installers/install-lint-tools.sh @@ -1,4 +1,7 @@ #!/bin/bash set -eux -o pipefail -GO111MODULE=on go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.58.2 +# renovate: datasource=go packageName=github.com/golangci/golangci-lint +GOLANGCI_LINT_VERSION=1.61.0 + +GO111MODULE=on go install "github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}" diff --git a/manifests/base/application-controller-deployment/argocd-application-controller-deployment.yaml b/manifests/base/application-controller-deployment/argocd-application-controller-deployment.yaml index 619c4ca4817b82..d0de4c9a5b812a 100644 --- a/manifests/base/application-controller-deployment/argocd-application-controller-deployment.yaml +++ b/manifests/base/application-controller-deployment/argocd-application-controller-deployment.yaml @@ -264,3 +264,5 @@ spec: items: - key: controller.profile.enabled path: profiler.enabled + nodeSelector: + kubernetes.io/os: linux \ No newline at end of file diff --git a/manifests/base/application-controller/argocd-application-controller-statefulset.yaml b/manifests/base/application-controller/argocd-application-controller-statefulset.yaml index ca09f482c35f70..cebe2006558fbe 100644 --- a/manifests/base/application-controller/argocd-application-controller-statefulset.yaml +++ b/manifests/base/application-controller/argocd-application-controller-statefulset.yaml @@ -272,4 +272,6 @@ spec: name: argocd-cmd-params-cm items: - key: controller.profile.enabled - path: profiler.enabled \ No newline at end of file + path: profiler.enabled + nodeSelector: + kubernetes.io/os: linux \ No newline at end of file diff --git a/manifests/base/applicationset-controller/argocd-applicationset-controller-deployment.yaml b/manifests/base/applicationset-controller/argocd-applicationset-controller-deployment.yaml index 6bade745f76c19..8886c1587916bd 100644 --- a/manifests/base/applicationset-controller/argocd-applicationset-controller-deployment.yaml +++ b/manifests/base/applicationset-controller/argocd-applicationset-controller-deployment.yaml @@ -163,6 +163,12 @@ spec: name: argocd-cmd-params-cm key: applicationsetcontroller.webhook.parallelism.limit optional: true + - name: ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER + valueFrom: + configMapKeyRef: + name: argocd-cmd-params-cm + key: applicationsetcontroller.requeue.after + optional: true volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -211,3 +217,5 @@ spec: path: tls.key - key: ca.crt path: ca.crt + nodeSelector: + kubernetes.io/os: linux \ No newline at end of file diff --git a/manifests/base/dex/argocd-dex-server-deployment.yaml b/manifests/base/dex/argocd-dex-server-deployment.yaml index f2d77c6ac1f6aa..87d7d0a2fbbd8e 100644 --- a/manifests/base/dex/argocd-dex-server-deployment.yaml +++ b/manifests/base/dex/argocd-dex-server-deployment.yaml @@ -104,3 +104,5 @@ spec: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname + nodeSelector: + kubernetes.io/os: linux \ No newline at end of file diff --git a/manifests/base/notification/argocd-notifications-controller-deployment.yaml b/manifests/base/notification/argocd-notifications-controller-deployment.yaml index b13acf718f93ce..c3a533e5a4350f 100644 --- a/manifests/base/notification/argocd-notifications-controller-deployment.yaml +++ b/manifests/base/notification/argocd-notifications-controller-deployment.yaml @@ -89,3 +89,5 @@ spec: runAsNonRoot: true seccompProfile: type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux \ No newline at end of file diff --git a/manifests/base/redis/argocd-redis-deployment.yaml b/manifests/base/redis/argocd-redis-deployment.yaml index c591db0d0aa4a0..cbfebb8a2127c1 100644 --- a/manifests/base/redis/argocd-redis-deployment.yaml +++ b/manifests/base/redis/argocd-redis-deployment.yaml @@ -77,3 +77,5 @@ spec: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname + nodeSelector: + kubernetes.io/os: linux \ No newline at end of file diff --git a/manifests/base/repo-server/argocd-repo-server-deployment.yaml b/manifests/base/repo-server/argocd-repo-server-deployment.yaml index f6a073c32d6e96..02a11fabe97154 100644 --- a/manifests/base/repo-server/argocd-repo-server-deployment.yaml +++ b/manifests/base/repo-server/argocd-repo-server-deployment.yaml @@ -151,10 +151,10 @@ spec: optional: true - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS valueFrom: - configMapKeyRef: - key: reposerver.plugin.use.manifest.generate.paths - name: argocd-cmd-params-cm - optional: true + configMapKeyRef: + key: reposerver.plugin.use.manifest.generate.paths + name: argocd-cmd-params-cm + optional: true - name: ARGOCD_REPO_SERVER_ALLOW_OUT_OF_BOUNDS_SYMLINKS valueFrom: configMapKeyRef: @@ -336,3 +336,5 @@ spec: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname + nodeSelector: + kubernetes.io/os: linux \ No newline at end of file diff --git a/manifests/base/server/argocd-server-deployment.yaml b/manifests/base/server/argocd-server-deployment.yaml index 56b479fdcfd44b..328dfcb2146f61 100644 --- a/manifests/base/server/argocd-server-deployment.yaml +++ b/manifests/base/server/argocd-server-deployment.yaml @@ -385,3 +385,5 @@ spec: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname + nodeSelector: + kubernetes.io/os: linux \ No newline at end of file diff --git a/manifests/cluster-rbac/server/argocd-server-clusterrole.yaml b/manifests/cluster-rbac/server/argocd-server-clusterrole.yaml index b33820950fcb63..3ee074622c15cc 100644 --- a/manifests/cluster-rbac/server/argocd-server-clusterrole.yaml +++ b/manifests/cluster-rbac/server/argocd-server-clusterrole.yaml @@ -15,6 +15,7 @@ rules: - delete # supports deletion a live object in UI - get # supports viewing live object manifest in UI - patch # supports `argocd app patch` + - list # supports `argocd appset generate` with cluster generator - apiGroups: - "" resources: diff --git a/manifests/core-install.yaml b/manifests/core-install.yaml index b9d59aae424d07..0fd229ee768d07 100644 --- a/manifests/core-install.yaml +++ b/manifests/core-install.yaml @@ -304,6 +304,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -670,6 +674,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -1151,6 +1159,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation step + (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -1508,6 +1520,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2030,6 +2046,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2399,6 +2419,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2913,6 +2937,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -3300,6 +3328,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -3804,6 +3836,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -4185,6 +4221,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -4710,6 +4750,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -5091,6 +5135,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -5579,6 +5627,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -5809,6 +5859,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6013,6 +6065,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -6201,6 +6255,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6431,6 +6487,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6824,6 +6882,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7054,6 +7114,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7427,6 +7489,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7657,6 +7721,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8055,6 +8121,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8285,6 +8353,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8489,6 +8559,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -8677,6 +8749,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8907,6 +8981,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9300,6 +9376,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9530,6 +9608,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9903,6 +9983,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10133,6 +10215,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10514,6 +10598,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10744,6 +10830,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -11344,6 +11432,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -11574,6 +11664,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12169,6 +12261,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12399,6 +12493,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12789,6 +12885,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13019,6 +13117,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13419,6 +13519,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13649,6 +13751,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13853,6 +13957,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -14041,6 +14147,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14271,6 +14379,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14664,6 +14774,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14894,6 +15006,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15267,6 +15381,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15497,6 +15613,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15878,6 +15996,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -16108,6 +16228,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -16708,6 +16830,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -16938,6 +17062,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -17533,6 +17659,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -17763,6 +17891,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18157,6 +18287,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18387,6 +18519,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18767,6 +18901,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18997,6 +19133,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -19597,6 +19735,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -19827,6 +19967,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -20422,6 +20564,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -20652,6 +20796,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -21117,6 +21263,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -21347,6 +21495,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -21735,7 +21885,7 @@ spec: sync operation. properties: defaultServiceAccount: - description: ServiceAccountName to be used for impersonation + description: DefaultServiceAccount to be used for impersonation during the sync operation type: string namespace: @@ -21746,6 +21896,9 @@ spec: description: Server specifies the URL of the target cluster's Kubernetes control plane API. type: string + required: + - defaultServiceAccount + - server type: object type: array destinations: @@ -22558,6 +22711,12 @@ spec: key: applicationsetcontroller.webhook.parallelism.limit name: argocd-cmd-params-cm optional: true + - name: ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER + valueFrom: + configMapKeyRef: + key: applicationsetcontroller.requeue.after + name: argocd-cmd-params-cm + optional: true image: quay.io/argoproj/argocd:latest imagePullPolicy: Always name: argocd-applicationset-controller @@ -22588,6 +22747,8 @@ spec: name: tmp - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-applicationset-controller volumes: - configMap: @@ -22688,6 +22849,8 @@ spec: runAsNonRoot: true seccompProfile: type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux securityContext: runAsNonRoot: true runAsUser: 999 @@ -22857,12 +23020,12 @@ spec: key: reposerver.plugin.tar.exclusions name: argocd-cmd-params-cm optional: true - - configMapKeyRef: - key: reposerver.plugin.use.manifest.generate.paths - name: argocd-cmd-params-cm - optional: true - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS - valueFrom: null + - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS + valueFrom: + configMapKeyRef: + key: reposerver.plugin.use.manifest.generate.paths + name: argocd-cmd-params-cm + optional: true - name: ARGOCD_REPO_SERVER_ALLOW_OUT_OF_BOUNDS_SYMLINKS valueFrom: configMapKeyRef: @@ -23001,6 +23164,8 @@ spec: volumeMounts: - mountPath: /var/run/argocd name: var-files + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-repo-server volumes: - configMap: @@ -23287,6 +23452,8 @@ spec: - mountPath: /home/argocd/params name: argocd-cmd-params-cm workingDir: /home/argocd + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-application-controller volumes: - emptyDir: {} diff --git a/manifests/crds/application-crd.yaml b/manifests/crds/application-crd.yaml index 5878e6eacd6a7e..0210473ecb58fa 100644 --- a/manifests/crds/application-crd.yaml +++ b/manifests/crds/application-crd.yaml @@ -303,6 +303,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -669,6 +673,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -1150,6 +1158,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation step + (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -1507,6 +1519,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2029,6 +2045,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2398,6 +2418,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2912,6 +2936,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -3299,6 +3327,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -3803,6 +3835,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -4184,6 +4220,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -4709,6 +4749,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -5090,6 +5134,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template diff --git a/manifests/crds/applicationset-crd.yaml b/manifests/crds/applicationset-crd.yaml index ddfa9b27be0566..1b6a00b6d23a0b 100644 --- a/manifests/crds/applicationset-crd.yaml +++ b/manifests/crds/applicationset-crd.yaml @@ -231,6 +231,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -461,6 +463,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -665,6 +669,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -853,6 +859,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -1083,6 +1091,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -1476,6 +1486,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -1706,6 +1718,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -2079,6 +2093,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -2309,6 +2325,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -2707,6 +2725,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -2937,6 +2957,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -3141,6 +3163,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -3329,6 +3353,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -3559,6 +3585,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -3952,6 +3980,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -4182,6 +4212,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -4555,6 +4587,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -4785,6 +4819,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -5166,6 +5202,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -5396,6 +5434,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -5996,6 +6036,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6226,6 +6268,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6821,6 +6865,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7051,6 +7097,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7441,6 +7489,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7671,6 +7721,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8071,6 +8123,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8301,6 +8355,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8505,6 +8561,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -8693,6 +8751,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8923,6 +8983,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9316,6 +9378,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9546,6 +9610,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9919,6 +9985,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10149,6 +10217,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10530,6 +10600,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10760,6 +10832,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -11360,6 +11434,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -11590,6 +11666,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12185,6 +12263,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12415,6 +12495,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12809,6 +12891,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13039,6 +13123,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13419,6 +13505,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13649,6 +13737,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14249,6 +14339,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14479,6 +14571,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15074,6 +15168,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15304,6 +15400,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15769,6 +15867,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15999,6 +16099,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string diff --git a/manifests/crds/appproject-crd.yaml b/manifests/crds/appproject-crd.yaml index 07e98e13b5928d..a72a8de146939f 100644 --- a/manifests/crds/appproject-crd.yaml +++ b/manifests/crds/appproject-crd.yaml @@ -95,7 +95,7 @@ spec: sync operation. properties: defaultServiceAccount: - description: ServiceAccountName to be used for impersonation + description: DefaultServiceAccount to be used for impersonation during the sync operation type: string namespace: @@ -106,6 +106,9 @@ spec: description: Server specifies the URL of the target cluster's Kubernetes control plane API. type: string + required: + - defaultServiceAccount + - server type: object type: array destinations: diff --git a/manifests/ha/install.yaml b/manifests/ha/install.yaml index 334b2befea9f1b..1fbf8b1461fb27 100644 --- a/manifests/ha/install.yaml +++ b/manifests/ha/install.yaml @@ -304,6 +304,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -670,6 +674,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -1151,6 +1159,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation step + (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -1508,6 +1520,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2030,6 +2046,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2399,6 +2419,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2913,6 +2937,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -3300,6 +3328,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -3804,6 +3836,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -4185,6 +4221,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -4710,6 +4750,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -5091,6 +5135,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -5579,6 +5627,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -5809,6 +5859,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6013,6 +6065,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -6201,6 +6255,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6431,6 +6487,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6824,6 +6882,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7054,6 +7114,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7427,6 +7489,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7657,6 +7721,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8055,6 +8121,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8285,6 +8353,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8489,6 +8559,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -8677,6 +8749,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8907,6 +8981,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9300,6 +9376,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9530,6 +9608,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9903,6 +9983,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10133,6 +10215,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10514,6 +10598,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10744,6 +10830,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -11344,6 +11432,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -11574,6 +11664,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12169,6 +12261,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12399,6 +12493,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12789,6 +12885,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13019,6 +13117,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13419,6 +13519,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13649,6 +13751,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13853,6 +13957,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -14041,6 +14147,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14271,6 +14379,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14664,6 +14774,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14894,6 +15006,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15267,6 +15381,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15497,6 +15613,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15878,6 +15996,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -16108,6 +16228,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -16708,6 +16830,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -16938,6 +17062,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -17533,6 +17659,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -17763,6 +17891,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18157,6 +18287,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18387,6 +18519,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18767,6 +18901,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18997,6 +19133,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -19597,6 +19735,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -19827,6 +19967,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -20422,6 +20564,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -20652,6 +20796,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -21117,6 +21263,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -21347,6 +21495,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -21735,7 +21885,7 @@ spec: sync operation. properties: defaultServiceAccount: - description: ServiceAccountName to be used for impersonation + description: DefaultServiceAccount to be used for impersonation during the sync operation type: string namespace: @@ -21746,6 +21896,9 @@ spec: description: Server specifies the URL of the target cluster's Kubernetes control plane API. type: string + required: + - defaultServiceAccount + - server type: object type: array destinations: @@ -22463,6 +22616,7 @@ rules: - delete - get - patch + - list - apiGroups: - "" resources: @@ -23901,6 +24055,12 @@ spec: key: applicationsetcontroller.webhook.parallelism.limit name: argocd-cmd-params-cm optional: true + - name: ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER + valueFrom: + configMapKeyRef: + key: applicationsetcontroller.requeue.after + name: argocd-cmd-params-cm + optional: true image: quay.io/argoproj/argocd:latest imagePullPolicy: Always name: argocd-applicationset-controller @@ -23931,6 +24091,8 @@ spec: name: tmp - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-applicationset-controller volumes: - configMap: @@ -24053,6 +24215,8 @@ spec: name: static-files - mountPath: /tmp name: dexconfig + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-dex-server volumes: - emptyDir: {} @@ -24142,6 +24306,8 @@ spec: - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls workingDir: /app + nodeSelector: + kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: @@ -24452,11 +24618,12 @@ spec: key: reposerver.plugin.tar.exclusions name: argocd-cmd-params-cm optional: true - - configMapKeyRef: - key: reposerver.plugin.use.manifest.generate.paths - name: argocd-cmd-params-cm - optional: true - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS + - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS + valueFrom: + configMapKeyRef: + key: reposerver.plugin.use.manifest.generate.paths + name: argocd-cmd-params-cm + optional: true - name: ARGOCD_REPO_SERVER_ALLOW_OUT_OF_BOUNDS_SYMLINKS valueFrom: configMapKeyRef: @@ -24595,6 +24762,8 @@ spec: volumeMounts: - mountPath: /var/run/argocd name: var-files + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-repo-server volumes: - configMap: @@ -24978,6 +25147,8 @@ spec: name: tmp - mountPath: /home/argocd/params name: argocd-cmd-params-cm + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-server volumes: - emptyDir: {} @@ -25271,6 +25442,8 @@ spec: - mountPath: /home/argocd/params name: argocd-cmd-params-cm workingDir: /home/argocd + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-application-controller volumes: - emptyDir: {} diff --git a/manifests/ha/namespace-install.yaml b/manifests/ha/namespace-install.yaml index eb8efee7630240..9f282cd5bdc4f2 100644 --- a/manifests/ha/namespace-install.yaml +++ b/manifests/ha/namespace-install.yaml @@ -1694,6 +1694,12 @@ spec: key: applicationsetcontroller.webhook.parallelism.limit name: argocd-cmd-params-cm optional: true + - name: ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER + valueFrom: + configMapKeyRef: + key: applicationsetcontroller.requeue.after + name: argocd-cmd-params-cm + optional: true image: quay.io/argoproj/argocd:latest imagePullPolicy: Always name: argocd-applicationset-controller @@ -1724,6 +1730,8 @@ spec: name: tmp - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-applicationset-controller volumes: - configMap: @@ -1846,6 +1854,8 @@ spec: name: static-files - mountPath: /tmp name: dexconfig + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-dex-server volumes: - emptyDir: {} @@ -1935,6 +1945,8 @@ spec: - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls workingDir: /app + nodeSelector: + kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: @@ -2245,11 +2257,12 @@ spec: key: reposerver.plugin.tar.exclusions name: argocd-cmd-params-cm optional: true - - configMapKeyRef: - key: reposerver.plugin.use.manifest.generate.paths - name: argocd-cmd-params-cm - optional: true - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS + - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS + valueFrom: + configMapKeyRef: + key: reposerver.plugin.use.manifest.generate.paths + name: argocd-cmd-params-cm + optional: true - name: ARGOCD_REPO_SERVER_ALLOW_OUT_OF_BOUNDS_SYMLINKS valueFrom: configMapKeyRef: @@ -2388,6 +2401,8 @@ spec: volumeMounts: - mountPath: /var/run/argocd name: var-files + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-repo-server volumes: - configMap: @@ -2771,6 +2786,8 @@ spec: name: tmp - mountPath: /home/argocd/params name: argocd-cmd-params-cm + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-server volumes: - emptyDir: {} @@ -3064,6 +3081,8 @@ spec: - mountPath: /home/argocd/params name: argocd-cmd-params-cm workingDir: /home/argocd + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-application-controller volumes: - emptyDir: {} diff --git a/manifests/install.yaml b/manifests/install.yaml index 868793d2f8e52e..a01fddf9ab3bb4 100644 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -304,6 +304,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -670,6 +674,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -1151,6 +1159,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation step + (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -1508,6 +1520,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2030,6 +2046,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2399,6 +2419,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -2913,6 +2937,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -3300,6 +3328,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -3804,6 +3836,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -4185,6 +4221,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -4710,6 +4750,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -5091,6 +5135,10 @@ spec: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean + skipTests: + description: SkipTests skips test manifest installation + step (Helm's --skip-tests). + type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template @@ -5579,6 +5627,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -5809,6 +5859,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6013,6 +6065,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -6201,6 +6255,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6431,6 +6487,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -6824,6 +6882,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7054,6 +7114,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7427,6 +7489,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -7657,6 +7721,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8055,6 +8121,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8285,6 +8353,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8489,6 +8559,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -8677,6 +8749,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -8907,6 +8981,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9300,6 +9376,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9530,6 +9608,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -9903,6 +9983,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10133,6 +10215,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10514,6 +10598,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -10744,6 +10830,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -11344,6 +11432,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -11574,6 +11664,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12169,6 +12261,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12399,6 +12493,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -12789,6 +12885,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13019,6 +13117,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13419,6 +13519,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13649,6 +13751,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -13853,6 +13957,8 @@ spec: type: object clusters: properties: + flatList: + type: boolean selector: properties: matchExpressions: @@ -14041,6 +14147,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14271,6 +14379,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14664,6 +14774,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -14894,6 +15006,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15267,6 +15381,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15497,6 +15613,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -15878,6 +15996,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -16108,6 +16228,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -16708,6 +16830,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -16938,6 +17062,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -17533,6 +17659,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -17763,6 +17891,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18157,6 +18287,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18387,6 +18519,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18767,6 +18901,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -18997,6 +19133,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -19597,6 +19735,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -19827,6 +19967,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -20422,6 +20564,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -20652,6 +20796,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -21117,6 +21263,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -21347,6 +21495,8 @@ spec: type: string skipCrds: type: boolean + skipTests: + type: boolean valueFiles: items: type: string @@ -21735,7 +21885,7 @@ spec: sync operation. properties: defaultServiceAccount: - description: ServiceAccountName to be used for impersonation + description: DefaultServiceAccount to be used for impersonation during the sync operation type: string namespace: @@ -21746,6 +21896,9 @@ spec: description: Server specifies the URL of the target cluster's Kubernetes control plane API. type: string + required: + - defaultServiceAccount + - server type: object type: array destinations: @@ -22430,6 +22583,7 @@ rules: - delete - get - patch + - list - apiGroups: - "" resources: @@ -23018,6 +23172,12 @@ spec: key: applicationsetcontroller.webhook.parallelism.limit name: argocd-cmd-params-cm optional: true + - name: ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER + valueFrom: + configMapKeyRef: + key: applicationsetcontroller.requeue.after + name: argocd-cmd-params-cm + optional: true image: quay.io/argoproj/argocd:latest imagePullPolicy: Always name: argocd-applicationset-controller @@ -23048,6 +23208,8 @@ spec: name: tmp - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-applicationset-controller volumes: - configMap: @@ -23170,6 +23332,8 @@ spec: name: static-files - mountPath: /tmp name: dexconfig + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-dex-server volumes: - emptyDir: {} @@ -23259,6 +23423,8 @@ spec: - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls workingDir: /app + nodeSelector: + kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: @@ -23353,6 +23519,8 @@ spec: runAsNonRoot: true seccompProfile: type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux securityContext: runAsNonRoot: true runAsUser: 999 @@ -23522,12 +23690,12 @@ spec: key: reposerver.plugin.tar.exclusions name: argocd-cmd-params-cm optional: true - - configMapKeyRef: - key: reposerver.plugin.use.manifest.generate.paths - name: argocd-cmd-params-cm - optional: true - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS - valueFrom: null + - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS + valueFrom: + configMapKeyRef: + key: reposerver.plugin.use.manifest.generate.paths + name: argocd-cmd-params-cm + optional: true - name: ARGOCD_REPO_SERVER_ALLOW_OUT_OF_BOUNDS_SYMLINKS valueFrom: configMapKeyRef: @@ -23666,6 +23834,8 @@ spec: volumeMounts: - mountPath: /var/run/argocd name: var-files + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-repo-server volumes: - configMap: @@ -24047,6 +24217,8 @@ spec: name: tmp - mountPath: /home/argocd/params name: argocd-cmd-params-cm + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-server volumes: - emptyDir: {} @@ -24340,6 +24512,8 @@ spec: - mountPath: /home/argocd/params name: argocd-cmd-params-cm workingDir: /home/argocd + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-application-controller volumes: - emptyDir: {} diff --git a/manifests/namespace-install.yaml b/manifests/namespace-install.yaml index 905bd717f05b9e..2b8220f28363f9 100644 --- a/manifests/namespace-install.yaml +++ b/manifests/namespace-install.yaml @@ -811,6 +811,12 @@ spec: key: applicationsetcontroller.webhook.parallelism.limit name: argocd-cmd-params-cm optional: true + - name: ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER + valueFrom: + configMapKeyRef: + key: applicationsetcontroller.requeue.after + name: argocd-cmd-params-cm + optional: true image: quay.io/argoproj/argocd:latest imagePullPolicy: Always name: argocd-applicationset-controller @@ -841,6 +847,8 @@ spec: name: tmp - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-applicationset-controller volumes: - configMap: @@ -963,6 +971,8 @@ spec: name: static-files - mountPath: /tmp name: dexconfig + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-dex-server volumes: - emptyDir: {} @@ -1052,6 +1062,8 @@ spec: - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls workingDir: /app + nodeSelector: + kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: @@ -1146,6 +1158,8 @@ spec: runAsNonRoot: true seccompProfile: type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux securityContext: runAsNonRoot: true runAsUser: 999 @@ -1315,12 +1329,12 @@ spec: key: reposerver.plugin.tar.exclusions name: argocd-cmd-params-cm optional: true - - configMapKeyRef: - key: reposerver.plugin.use.manifest.generate.paths - name: argocd-cmd-params-cm - optional: true - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS - valueFrom: null + - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS + valueFrom: + configMapKeyRef: + key: reposerver.plugin.use.manifest.generate.paths + name: argocd-cmd-params-cm + optional: true - name: ARGOCD_REPO_SERVER_ALLOW_OUT_OF_BOUNDS_SYMLINKS valueFrom: configMapKeyRef: @@ -1459,6 +1473,8 @@ spec: volumeMounts: - mountPath: /var/run/argocd name: var-files + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-repo-server volumes: - configMap: @@ -1840,6 +1856,8 @@ spec: name: tmp - mountPath: /home/argocd/params name: argocd-cmd-params-cm + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-server volumes: - emptyDir: {} @@ -2133,6 +2151,8 @@ spec: - mountPath: /home/argocd/params name: argocd-cmd-params-cm workingDir: /home/argocd + nodeSelector: + kubernetes.io/os: linux serviceAccountName: argocd-application-controller volumes: - emptyDir: {} diff --git a/notifications_catalog/install.yaml b/notifications_catalog/install.yaml index 7457b25ddad897..8572072616b455 100644 --- a/notifications_catalog/install.yaml +++ b/notifications_catalog/install.yaml @@ -30,8 +30,8 @@ data: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true }, { @@ -59,8 +59,8 @@ data: "value": "{{.app.status.sync.status}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, }, { "name": "Revision", @@ -88,7 +88,7 @@ data: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] themeColor: '#000080' @@ -112,8 +112,8 @@ data: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -136,8 +136,8 @@ data: "value": "{{.app.status.health.status}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -161,7 +161,7 @@ data: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] themeColor: '#FF0000' @@ -185,8 +185,8 @@ data: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -213,8 +213,8 @@ data: "value": "{{.app.status.operationState.finishedAt}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -238,7 +238,7 @@ data: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] themeColor: '#FF0000' @@ -262,8 +262,8 @@ data: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -290,8 +290,8 @@ data: "value": "{{.app.status.operationState.startedAt}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -315,7 +315,7 @@ data: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] title: Start syncing application {{.app.metadata.name}}. @@ -343,8 +343,8 @@ data: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -367,8 +367,8 @@ data: "value": "{{.app.status.sync.status}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -392,7 +392,7 @@ data: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] title: Application {{.app.metadata.name}} sync status is 'Unknown' @@ -415,8 +415,8 @@ data: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -443,8 +443,8 @@ data: "value": "{{.app.status.operationState.finishedAt}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -468,7 +468,7 @@ data: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] themeColor: '#000080' diff --git a/notifications_catalog/templates/app-deployed.yaml b/notifications_catalog/templates/app-deployed.yaml index ee58c775f1fd80..cf54628c30eb4a 100644 --- a/notifications_catalog/templates/app-deployed.yaml +++ b/notifications_catalog/templates/app-deployed.yaml @@ -15,8 +15,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true }, { @@ -43,8 +43,8 @@ teams: "value": "{{.app.status.sync.status}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, }, { "name": "Revision", @@ -72,6 +72,6 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] \ No newline at end of file diff --git a/notifications_catalog/templates/app-health-degraded.yaml b/notifications_catalog/templates/app-health-degraded.yaml index 59115c9a14935f..fcb0022785e77a 100644 --- a/notifications_catalog/templates/app-health-degraded.yaml +++ b/notifications_catalog/templates/app-health-degraded.yaml @@ -16,8 +16,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -39,8 +39,8 @@ teams: "value": "{{.app.status.health.status}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -64,6 +64,6 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] diff --git a/notifications_catalog/templates/app-sync-failed.yaml b/notifications_catalog/templates/app-sync-failed.yaml index a4c23787dde8b2..37f57549ac1c6e 100644 --- a/notifications_catalog/templates/app-sync-failed.yaml +++ b/notifications_catalog/templates/app-sync-failed.yaml @@ -16,8 +16,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -43,8 +43,8 @@ teams: "value": "{{.app.status.operationState.finishedAt}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -68,6 +68,6 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] \ No newline at end of file diff --git a/notifications_catalog/templates/app-sync-running.yaml b/notifications_catalog/templates/app-sync-running.yaml index 434132ad86d896..06d133cd047dbf 100644 --- a/notifications_catalog/templates/app-sync-running.yaml +++ b/notifications_catalog/templates/app-sync-running.yaml @@ -16,8 +16,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -42,8 +42,8 @@ teams: "value": "{{.app.status.operationState.startedAt}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -67,6 +67,6 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] \ No newline at end of file diff --git a/notifications_catalog/templates/app-sync-status-unknown.yaml b/notifications_catalog/templates/app-sync-status-unknown.yaml index c893070bfcc63a..fd13d2b64fcf60 100644 --- a/notifications_catalog/templates/app-sync-status-unknown.yaml +++ b/notifications_catalog/templates/app-sync-status-unknown.yaml @@ -21,8 +21,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -43,8 +43,8 @@ teams: "value": "{{.app.status.sync.status}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -68,6 +68,6 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] \ No newline at end of file diff --git a/notifications_catalog/templates/app-sync-succeeded.yaml b/notifications_catalog/templates/app-sync-succeeded.yaml index 76e467bd1c37dd..2e5f0d3863de68 100644 --- a/notifications_catalog/templates/app-sync-succeeded.yaml +++ b/notifications_catalog/templates/app-sync-succeeded.yaml @@ -16,8 +16,8 @@ slack: "short": true }, { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", + "title": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, "short": true } {{range $index, $c := .app.status.conditions}} @@ -43,8 +43,8 @@ teams: "value": "{{.app.status.operationState.finishedAt}}" }, { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" + "name": {{- if .app.spec.source }} "Repository" {{- else if .app.spec.sources }} "Repositories" {{- end }}, + "value": {{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }}, } {{range $index, $c := .app.status.conditions}} , @@ -68,6 +68,6 @@ teams: "name":"Open Repository", "targets":[{ "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" + "uri":{{- if .app.spec.source }} ":arrow_heading_up: {{ .app.spec.source.repoURL }}" {{- else if .app.spec.sources }} "{{- range $index, $source := .app.spec.sources }}{{ if $index }}\n{{ end }}:arrow_heading_up: {{ $source.repoURL }}{{- end }}" {{- end }},}}" {{- end }}, }] }] \ No newline at end of file diff --git a/pkg/apiclient/settings/settings.pb.go b/pkg/apiclient/settings/settings.pb.go index 3345756bd0aadc..202228f7ef6f1e 100644 --- a/pkg/apiclient/settings/settings.pb.go +++ b/pkg/apiclient/settings/settings.pb.go @@ -102,6 +102,7 @@ type Settings struct { ControllerNamespace string `protobuf:"bytes,23,opt,name=controllerNamespace,proto3" json:"controllerNamespace,omitempty"` AppsInAnyNamespaceEnabled bool `protobuf:"varint,24,opt,name=appsInAnyNamespaceEnabled,proto3" json:"appsInAnyNamespaceEnabled,omitempty"` ImpersonationEnabled bool `protobuf:"varint,25,opt,name=impersonationEnabled,proto3" json:"impersonationEnabled,omitempty"` + InstallationID string `protobuf:"bytes,26,opt,name=installationID,proto3" json:"installationID,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -315,6 +316,13 @@ func (m *Settings) GetImpersonationEnabled() bool { return false } +func (m *Settings) GetInstallationID() string { + if m != nil { + return m.InstallationID + } + return "" +} + type GoogleAnalyticsConfig struct { TrackingID string `protobuf:"bytes,1,opt,name=trackingID,proto3" json:"trackingID,omitempty"` AnonymizeUsers bool `protobuf:"varint,2,opt,name=anonymizeUsers,proto3" json:"anonymizeUsers,omitempty"` @@ -748,84 +756,86 @@ func init() { func init() { proto.RegisterFile("server/settings/settings.proto", fileDescriptor_a480d494da040caa) } var fileDescriptor_a480d494da040caa = []byte{ - // 1232 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0x97, 0xeb, 0x34, 0xb1, 0x9f, 0x9b, 0x3a, 0x99, 0xa6, 0xe9, 0xd6, 0x2a, 0x89, 0xf1, 0xa1, - 0x32, 0x08, 0xd6, 0x8d, 0x2b, 0x04, 0xaa, 0xa8, 0xa0, 0xb6, 0xab, 0xd6, 0x34, 0x6d, 0xc3, 0xb4, - 0xe9, 0x81, 0x4b, 0x35, 0x59, 0x3f, 0xd6, 0x4b, 0xd6, 0x33, 0xab, 0x99, 0x59, 0x13, 0xf7, 0xc8, - 0x07, 0xe0, 0x02, 0x9f, 0x86, 0x3b, 0x82, 0x23, 0x12, 0xf7, 0x08, 0x59, 0x9c, 0xf8, 0x14, 0x68, - 0x67, 0xff, 0x64, 0xb3, 0x76, 0x0a, 0x52, 0x6f, 0x33, 0xbf, 0xdf, 0xfb, 0x37, 0x6f, 0xde, 0x9b, - 0x79, 0xb0, 0xa3, 0x50, 0x4e, 0x51, 0x76, 0x14, 0x6a, 0xed, 0x71, 0x57, 0x65, 0x0b, 0x3b, 0x90, - 0x42, 0x0b, 0xb2, 0xe6, 0xf8, 0xa1, 0xd2, 0x28, 0x1b, 0x5b, 0xae, 0x70, 0x85, 0xc1, 0x3a, 0xd1, - 0x2a, 0xa6, 0x1b, 0xb7, 0x5c, 0x21, 0x5c, 0x1f, 0x3b, 0x2c, 0xf0, 0x3a, 0x8c, 0x73, 0xa1, 0x99, - 0xf6, 0x04, 0x4f, 0x94, 0x1b, 0xfb, 0xae, 0xa7, 0xc7, 0xe1, 0x91, 0xed, 0x88, 0x49, 0x87, 0x49, - 0xa3, 0xfe, 0x9d, 0x59, 0x7c, 0xec, 0x8c, 0x3a, 0xd3, 0x6e, 0x27, 0x38, 0x76, 0x23, 0x4d, 0xd5, - 0x61, 0x41, 0xe0, 0x7b, 0x8e, 0xd1, 0xed, 0x4c, 0xf7, 0x98, 0x1f, 0x8c, 0xd9, 0x5e, 0xc7, 0x45, - 0x8e, 0x92, 0x69, 0x1c, 0x25, 0xd6, 0xbe, 0xfc, 0x0f, 0x6b, 0xc5, 0x93, 0x08, 0x6f, 0xe4, 0x74, - 0x1c, 0x9f, 0x79, 0x93, 0x24, 0x9e, 0x56, 0x1d, 0xd6, 0x5f, 0x24, 0xec, 0xd7, 0x21, 0xca, 0x59, - 0xeb, 0x9f, 0x1a, 0x54, 0x52, 0x84, 0xdc, 0x84, 0x72, 0x28, 0x7d, 0xab, 0xd4, 0x2c, 0xb5, 0xab, - 0xbd, 0xb5, 0xf9, 0xe9, 0x6e, 0xf9, 0x90, 0xee, 0xd3, 0x08, 0x23, 0x77, 0xa0, 0x3a, 0xc2, 0x93, - 0xbe, 0xe0, 0xdf, 0x7a, 0xae, 0x75, 0xa9, 0x59, 0x6a, 0xd7, 0xba, 0xc4, 0x4e, 0x32, 0x63, 0x0f, - 0x52, 0x86, 0x9e, 0x09, 0x91, 0x3e, 0x40, 0xe4, 0x3f, 0x51, 0x29, 0x1b, 0x95, 0x6b, 0x99, 0xca, - 0xf3, 0xe1, 0xa0, 0x1f, 0x53, 0xbd, 0xab, 0xf3, 0xd3, 0x5d, 0x38, 0xdb, 0xd3, 0x9c, 0x1a, 0x69, - 0x42, 0x8d, 0x05, 0xc1, 0x3e, 0x3b, 0x42, 0xff, 0x09, 0xce, 0xac, 0x95, 0x28, 0x32, 0x9a, 0x87, - 0xc8, 0x2b, 0xd8, 0x94, 0xa8, 0x44, 0x28, 0x1d, 0x7c, 0x3e, 0x45, 0x29, 0xbd, 0x11, 0x2a, 0xeb, - 0x72, 0xb3, 0xdc, 0xae, 0x75, 0xdb, 0x99, 0xb7, 0xf4, 0x84, 0x36, 0x2d, 0x8a, 0x3e, 0xe4, 0x5a, - 0xce, 0xe8, 0xa2, 0x09, 0x62, 0x03, 0x51, 0x9a, 0xe9, 0x50, 0xf5, 0xd8, 0xc8, 0xc5, 0x87, 0x9c, - 0x1d, 0xf9, 0x38, 0xb2, 0x56, 0x9b, 0xa5, 0x76, 0x85, 0x2e, 0x61, 0xc8, 0x63, 0xa8, 0xc7, 0x95, - 0xf0, 0x80, 0x33, 0x7f, 0xa6, 0x3d, 0x47, 0x59, 0x6b, 0xe6, 0xcc, 0x3b, 0x59, 0x14, 0x8f, 0xce, - 0xf3, 0xc9, 0x71, 0x8b, 0x6a, 0xe4, 0x0d, 0x6c, 0x1c, 0x87, 0x4a, 0x8b, 0x89, 0xf7, 0x06, 0x9f, - 0x07, 0xa6, 0x9a, 0xac, 0x8a, 0x31, 0xf5, 0xcc, 0x3e, 0x2b, 0x00, 0x3b, 0x2d, 0x00, 0xb3, 0x78, - 0xed, 0x8c, 0xec, 0x69, 0xd7, 0x0e, 0x8e, 0x5d, 0x3b, 0x2a, 0x27, 0x3b, 0x57, 0x4e, 0x76, 0x5a, - 0x4e, 0xf6, 0x93, 0x82, 0x55, 0xba, 0xe0, 0x87, 0xbc, 0x0f, 0x2b, 0x63, 0xf4, 0x03, 0xab, 0x6a, - 0xfc, 0xad, 0x67, 0xa1, 0x3f, 0x46, 0x3f, 0xa0, 0x86, 0x22, 0x1f, 0xc0, 0x5a, 0xe0, 0x87, 0xae, - 0xc7, 0x95, 0x05, 0x26, 0xcd, 0xf5, 0x4c, 0xea, 0xc0, 0xe0, 0x34, 0xe5, 0xa3, 0x1c, 0x86, 0x0a, - 0xe5, 0xbe, 0x88, 0x76, 0x03, 0x4f, 0xc5, 0x39, 0xac, 0xc5, 0x39, 0x5c, 0x64, 0xc8, 0x8f, 0x25, - 0xb8, 0xe1, 0x98, 0xac, 0x3c, 0x65, 0x9c, 0xb9, 0x38, 0x41, 0xae, 0x0f, 0x12, 0x5f, 0x57, 0x8c, - 0xaf, 0x97, 0xef, 0x96, 0x81, 0xfe, 0x52, 0xe3, 0xf4, 0x22, 0xa7, 0xe4, 0x23, 0xd8, 0xcc, 0x52, - 0xf4, 0x0a, 0xa5, 0x32, 0x77, 0xb1, 0xde, 0x2c, 0xb7, 0xab, 0x74, 0x91, 0x20, 0x0d, 0xa8, 0x84, - 0x5e, 0x5f, 0xa9, 0x43, 0xba, 0x6f, 0x5d, 0x35, 0x95, 0x9a, 0xed, 0x49, 0x1b, 0xea, 0xa1, 0xd7, - 0x63, 0x9c, 0xa3, 0xec, 0x0b, 0xae, 0x91, 0x6b, 0xab, 0x6e, 0x44, 0x8a, 0x70, 0x54, 0xf2, 0x29, - 0x14, 0x19, 0xda, 0x88, 0x4b, 0x3e, 0x07, 0x45, 0xb6, 0x02, 0xa6, 0xd4, 0xf7, 0x42, 0x8e, 0x0e, - 0x98, 0xd6, 0x28, 0xb9, 0xb5, 0x19, 0xdb, 0x2a, 0xc0, 0xe4, 0x36, 0x5c, 0xd5, 0x92, 0x39, 0xc7, - 0x1e, 0x77, 0x9f, 0xa2, 0x1e, 0x8b, 0x91, 0x45, 0x8c, 0x60, 0x01, 0x8d, 0xce, 0x99, 0x3a, 0x38, - 0x40, 0x39, 0x61, 0x3c, 0x8a, 0xef, 0x9a, 0xb9, 0xa7, 0x45, 0x82, 0x7c, 0x08, 0x1b, 0x19, 0x28, - 0x94, 0x17, 0xa5, 0xd8, 0xda, 0x32, 0x76, 0x17, 0xf0, 0x42, 0x1b, 0x51, 0x21, 0xf4, 0xa1, 0xf4, - 0xad, 0xeb, 0x46, 0x7a, 0x09, 0x13, 0x9d, 0x1e, 0x4f, 0xd0, 0x49, 0xfb, 0x6d, 0xdb, 0xc4, 0x90, - 0x87, 0xc8, 0x1d, 0xb8, 0xe6, 0x08, 0xae, 0xa5, 0xf0, 0x7d, 0x94, 0xcf, 0xd8, 0x04, 0x55, 0xc0, - 0x1c, 0xb4, 0x6e, 0x18, 0x93, 0xcb, 0x28, 0xf2, 0x39, 0xdc, 0x64, 0x41, 0xa0, 0x86, 0xfc, 0x01, - 0x9f, 0x65, 0x68, 0xea, 0xc1, 0x32, 0x1e, 0x2e, 0x16, 0x20, 0x5d, 0xd8, 0xf2, 0x26, 0x01, 0x4a, - 0x25, 0xb8, 0xa9, 0xa6, 0x54, 0xf1, 0xa6, 0x51, 0x5c, 0xca, 0x35, 0x7e, 0x2e, 0xc1, 0xf6, 0xf2, - 0xa7, 0x86, 0x6c, 0x40, 0xf9, 0x18, 0x67, 0xf1, 0x1b, 0x4b, 0xa3, 0x25, 0x19, 0xc1, 0xe5, 0x29, - 0xf3, 0x43, 0x4c, 0x9e, 0xd5, 0x77, 0x6c, 0xf2, 0xa2, 0x5b, 0x1a, 0x1b, 0xbf, 0x77, 0xe9, 0xb3, - 0x52, 0xeb, 0x35, 0x5c, 0x5f, 0xfa, 0x06, 0x91, 0x1d, 0x80, 0xb4, 0x22, 0x86, 0x83, 0x24, 0xb6, - 0x1c, 0x12, 0xd5, 0x11, 0xe3, 0x82, 0xcf, 0xa2, 0x72, 0x3f, 0x54, 0x28, 0x95, 0x89, 0xb5, 0x42, - 0x0b, 0x68, 0x6b, 0x00, 0x37, 0xd2, 0xa7, 0x36, 0x69, 0x21, 0x8a, 0x2a, 0x10, 0x5c, 0x61, 0xfe, - 0xd9, 0x28, 0xbd, 0xfd, 0xd9, 0x68, 0xfd, 0x52, 0x82, 0x95, 0xe8, 0xc1, 0x21, 0x16, 0xac, 0x39, - 0x63, 0x66, 0x2a, 0x26, 0x8e, 0x29, 0xdd, 0x46, 0xad, 0x16, 0x2d, 0x5f, 0xe2, 0x89, 0x36, 0xa1, - 0x54, 0x69, 0xb6, 0x27, 0xf7, 0x01, 0x8e, 0x3c, 0xce, 0xe4, 0xec, 0x50, 0xfa, 0xca, 0x2a, 0x1b, - 0x67, 0xef, 0x9d, 0x7b, 0xc9, 0xec, 0x5e, 0xc6, 0xc7, 0xef, 0x7f, 0x4e, 0xa1, 0x71, 0x1f, 0xea, - 0x05, 0x7a, 0xc9, 0x9d, 0x6d, 0xe5, 0xef, 0xac, 0x9a, 0xcf, 0xf1, 0x2d, 0x58, 0x8d, 0xcf, 0x43, - 0x08, 0xac, 0x70, 0x36, 0xc1, 0x44, 0xcd, 0xac, 0x5b, 0x5f, 0x40, 0x35, 0xfb, 0x2c, 0x49, 0x17, - 0xc0, 0x11, 0x9c, 0xa3, 0xa3, 0x85, 0x4c, 0xb3, 0x72, 0xf6, 0xa9, 0xf6, 0x53, 0x8a, 0xe6, 0xa4, - 0x5a, 0x77, 0xa1, 0x9a, 0x11, 0xcb, 0x3c, 0x44, 0x98, 0x9e, 0x05, 0x69, 0x60, 0x66, 0xdd, 0xfa, - 0xb5, 0x0c, 0xb9, 0x0f, 0x76, 0xa9, 0xda, 0x36, 0xac, 0x7a, 0x4a, 0x85, 0x28, 0x13, 0xc5, 0x64, - 0x47, 0xda, 0x50, 0x71, 0x7c, 0x0f, 0xb9, 0x1e, 0x0e, 0xcc, 0x1f, 0x5e, 0xed, 0x5d, 0x99, 0x9f, - 0xee, 0x56, 0xfa, 0x09, 0x46, 0x33, 0x96, 0xec, 0x41, 0xcd, 0xf1, 0xbd, 0x94, 0x88, 0xbf, 0xea, - 0x5e, 0x7d, 0x7e, 0xba, 0x5b, 0xeb, 0xef, 0x0f, 0x33, 0xf9, 0xbc, 0x4c, 0xe4, 0x54, 0x39, 0x22, - 0x48, 0x3e, 0xec, 0x2a, 0x4d, 0x76, 0xe4, 0x35, 0xac, 0x7b, 0xa3, 0x97, 0xe2, 0x18, 0x79, 0xdf, - 0x0c, 0x2f, 0xd6, 0xaa, 0xc9, 0xcd, 0xed, 0x25, 0xd3, 0x83, 0x3d, 0xcc, 0x0b, 0x9a, 0xeb, 0xea, - 0x6d, 0xce, 0x4f, 0x77, 0xd7, 0x87, 0x83, 0x1c, 0x4e, 0xcf, 0xdb, 0x23, 0xf7, 0xc0, 0x42, 0xd3, - 0xaa, 0x07, 0x4f, 0xfa, 0x0f, 0x1f, 0x84, 0x7a, 0x8c, 0x5c, 0x27, 0x9d, 0x64, 0x7e, 0xed, 0x0a, - 0xbd, 0x90, 0x6f, 0xcc, 0x80, 0x2c, 0xfa, 0x5c, 0x52, 0x22, 0x4f, 0xcf, 0xb7, 0xf5, 0xa7, 0x6f, - 0x6d, 0xeb, 0x78, 0x72, 0xb3, 0xb3, 0xd1, 0x33, 0x1a, 0x81, 0x6c, 0x63, 0x3f, 0x57, 0x5b, 0xdd, - 0xdf, 0x4a, 0x50, 0x4f, 0xfb, 0xeb, 0x05, 0xca, 0xa9, 0xe7, 0x20, 0xf9, 0x0a, 0xca, 0x8f, 0x50, - 0x93, 0xed, 0x85, 0x59, 0xc7, 0xcc, 0x77, 0x8d, 0xcd, 0x05, 0xbc, 0x65, 0xfd, 0xf0, 0xe7, 0xdf, - 0x3f, 0x5d, 0x22, 0x64, 0xc3, 0xcc, 0xac, 0xd3, 0xbd, 0x6c, 0x5e, 0x24, 0x63, 0x80, 0x47, 0x98, - 0x7d, 0x7e, 0x17, 0x99, 0x6c, 0x2e, 0xe0, 0x85, 0x5e, 0x6f, 0x35, 0x8d, 0x87, 0x06, 0xb1, 0x8a, - 0x1e, 0x3a, 0x49, 0x8b, 0xf7, 0xfa, 0xbf, 0xcf, 0x77, 0x4a, 0x7f, 0xcc, 0x77, 0x4a, 0x7f, 0xcd, - 0x77, 0x4a, 0xdf, 0x7c, 0xf2, 0xff, 0xa6, 0xe4, 0xb8, 0xd4, 0x32, 0x63, 0x47, 0xab, 0x66, 0xa6, - 0xbd, 0xfb, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8d, 0xd6, 0x25, 0xb7, 0xc2, 0x0b, 0x00, 0x00, + // 1249 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x4f, 0x6f, 0x1b, 0xb7, + 0x12, 0xc7, 0x46, 0x8e, 0x2d, 0x8d, 0xe3, 0xc8, 0x66, 0x1c, 0x67, 0x23, 0xe4, 0xd9, 0x7a, 0x3a, + 0x04, 0x7a, 0x0f, 0xed, 0x2a, 0x56, 0x50, 0xb4, 0x08, 0x1a, 0xb4, 0x91, 0x14, 0x24, 0x6a, 0x9c, + 0xc4, 0xdd, 0xc4, 0x39, 0xf4, 0x12, 0xd0, 0xab, 0xe9, 0x6a, 0xeb, 0x15, 0xb9, 0x20, 0xb9, 0x6a, + 0x94, 0x63, 0x3f, 0x40, 0x0f, 0x6d, 0x3f, 0x4d, 0xef, 0x45, 0x7b, 0x2c, 0xd0, 0xbb, 0x51, 0x08, + 0xfd, 0x20, 0x05, 0xb9, 0x7f, 0xbc, 0x5e, 0xc9, 0x69, 0x81, 0xdc, 0xc8, 0xdf, 0x6f, 0xfe, 0x71, + 0x38, 0x43, 0x0e, 0xec, 0x4a, 0x14, 0x53, 0x14, 0x1d, 0x89, 0x4a, 0x05, 0xcc, 0x97, 0xf9, 0xc2, + 0x89, 0x04, 0x57, 0x9c, 0xac, 0x79, 0x61, 0x2c, 0x15, 0x8a, 0xc6, 0xb6, 0xcf, 0x7d, 0x6e, 0xb0, + 0x8e, 0x5e, 0x25, 0x74, 0xe3, 0x96, 0xcf, 0xb9, 0x1f, 0x62, 0x87, 0x46, 0x41, 0x87, 0x32, 0xc6, + 0x15, 0x55, 0x01, 0x67, 0xa9, 0x72, 0xe3, 0xc0, 0x0f, 0xd4, 0x38, 0x3e, 0x76, 0x3c, 0x3e, 0xe9, + 0x50, 0x61, 0xd4, 0xbf, 0x31, 0x8b, 0x0f, 0xbd, 0x51, 0x67, 0xda, 0xed, 0x44, 0x27, 0xbe, 0xd6, + 0x94, 0x1d, 0x1a, 0x45, 0x61, 0xe0, 0x19, 0xdd, 0xce, 0x74, 0x9f, 0x86, 0xd1, 0x98, 0xee, 0x77, + 0x7c, 0x64, 0x28, 0xa8, 0xc2, 0x51, 0x6a, 0xed, 0xf3, 0x7f, 0xb0, 0x56, 0x3e, 0x09, 0x0f, 0x46, + 0x5e, 0xc7, 0x0b, 0x69, 0x30, 0x49, 0xe3, 0x69, 0xd5, 0x61, 0xe3, 0x45, 0xca, 0x7e, 0x19, 0xa3, + 0x98, 0xb5, 0x7e, 0xb8, 0x02, 0xd5, 0x0c, 0x21, 0x37, 0xa1, 0x12, 0x8b, 0xd0, 0xb6, 0x9a, 0x56, + 0xbb, 0xd6, 0x5b, 0x9b, 0x9f, 0xee, 0x55, 0x8e, 0xdc, 0x03, 0x57, 0x63, 0xe4, 0x0e, 0xd4, 0x46, + 0xf8, 0xa6, 0xcf, 0xd9, 0xd7, 0x81, 0x6f, 0x5f, 0x6a, 0x5a, 0xed, 0xf5, 0x2e, 0x71, 0xd2, 0xcc, + 0x38, 0x83, 0x8c, 0x71, 0xcf, 0x84, 0x48, 0x1f, 0x40, 0xfb, 0x4f, 0x55, 0x2a, 0x46, 0xe5, 0x5a, + 0xae, 0xf2, 0x7c, 0x38, 0xe8, 0x27, 0x54, 0xef, 0xea, 0xfc, 0x74, 0x0f, 0xce, 0xf6, 0x6e, 0x41, + 0x8d, 0x34, 0x61, 0x9d, 0x46, 0xd1, 0x01, 0x3d, 0xc6, 0xf0, 0x09, 0xce, 0xec, 0x15, 0x1d, 0x99, + 0x5b, 0x84, 0xc8, 0x2b, 0xd8, 0x12, 0x28, 0x79, 0x2c, 0x3c, 0x7c, 0x3e, 0x45, 0x21, 0x82, 0x11, + 0x4a, 0xfb, 0x72, 0xb3, 0xd2, 0x5e, 0xef, 0xb6, 0x73, 0x6f, 0xd9, 0x09, 0x1d, 0xb7, 0x2c, 0xfa, + 0x90, 0x29, 0x31, 0x73, 0x17, 0x4d, 0x10, 0x07, 0x88, 0x54, 0x54, 0xc5, 0xb2, 0x47, 0x47, 0x3e, + 0x3e, 0x64, 0xf4, 0x38, 0xc4, 0x91, 0xbd, 0xda, 0xb4, 0xda, 0x55, 0x77, 0x09, 0x43, 0x1e, 0x43, + 0x3d, 0xa9, 0x84, 0x07, 0x8c, 0x86, 0x33, 0x15, 0x78, 0xd2, 0x5e, 0x33, 0x67, 0xde, 0xcd, 0xa3, + 0x78, 0x74, 0x9e, 0x4f, 0x8f, 0x5b, 0x56, 0x23, 0x6f, 0x61, 0xf3, 0x24, 0x96, 0x8a, 0x4f, 0x82, + 0xb7, 0xf8, 0x3c, 0x32, 0xd5, 0x64, 0x57, 0x8d, 0xa9, 0x67, 0xce, 0x59, 0x01, 0x38, 0x59, 0x01, + 0x98, 0xc5, 0x6b, 0x6f, 0xe4, 0x4c, 0xbb, 0x4e, 0x74, 0xe2, 0x3b, 0xba, 0x9c, 0x9c, 0x42, 0x39, + 0x39, 0x59, 0x39, 0x39, 0x4f, 0x4a, 0x56, 0xdd, 0x05, 0x3f, 0xe4, 0xbf, 0xb0, 0x32, 0xc6, 0x30, + 0xb2, 0x6b, 0xc6, 0xdf, 0x46, 0x1e, 0xfa, 0x63, 0x0c, 0x23, 0xd7, 0x50, 0xe4, 0x7f, 0xb0, 0x16, + 0x85, 0xb1, 0x1f, 0x30, 0x69, 0x83, 0x49, 0x73, 0x3d, 0x97, 0x3a, 0x34, 0xb8, 0x9b, 0xf1, 0x3a, + 0x87, 0xb1, 0x44, 0x71, 0xc0, 0xf5, 0x6e, 0x10, 0xc8, 0x24, 0x87, 0xeb, 0x49, 0x0e, 0x17, 0x19, + 0xf2, 0xbd, 0x05, 0x37, 0x3c, 0x93, 0x95, 0xa7, 0x94, 0x51, 0x1f, 0x27, 0xc8, 0xd4, 0x61, 0xea, + 0xeb, 0x8a, 0xf1, 0xf5, 0xf2, 0xfd, 0x32, 0xd0, 0x5f, 0x6a, 0xdc, 0xbd, 0xc8, 0x29, 0xf9, 0x00, + 0xb6, 0xf2, 0x14, 0xbd, 0x42, 0x21, 0xcd, 0x5d, 0x6c, 0x34, 0x2b, 0xed, 0x9a, 0xbb, 0x48, 0x90, + 0x06, 0x54, 0xe3, 0xa0, 0x2f, 0xe5, 0x91, 0x7b, 0x60, 0x5f, 0x35, 0x95, 0x9a, 0xef, 0x49, 0x1b, + 0xea, 0x71, 0xd0, 0xa3, 0x8c, 0xa1, 0xe8, 0x73, 0xa6, 0x90, 0x29, 0xbb, 0x6e, 0x44, 0xca, 0xb0, + 0x2e, 0xf9, 0x0c, 0xd2, 0x86, 0x36, 0x93, 0x92, 0x2f, 0x40, 0xda, 0x56, 0x44, 0xa5, 0xfc, 0x96, + 0x8b, 0xd1, 0x21, 0x55, 0x0a, 0x05, 0xb3, 0xb7, 0x12, 0x5b, 0x25, 0x98, 0xdc, 0x86, 0xab, 0x4a, + 0x50, 0xef, 0x24, 0x60, 0xfe, 0x53, 0x54, 0x63, 0x3e, 0xb2, 0x89, 0x11, 0x2c, 0xa1, 0xfa, 0x9c, + 0x99, 0x83, 0x43, 0x14, 0x13, 0xca, 0x74, 0x7c, 0xd7, 0xcc, 0x3d, 0x2d, 0x12, 0xe4, 0xff, 0xb0, + 0x99, 0x83, 0x5c, 0x06, 0x3a, 0xc5, 0xf6, 0xb6, 0xb1, 0xbb, 0x80, 0x97, 0xda, 0xc8, 0xe5, 0x5c, + 0x1d, 0x89, 0xd0, 0xbe, 0x6e, 0xa4, 0x97, 0x30, 0xfa, 0xf4, 0xf8, 0x06, 0xbd, 0xac, 0xdf, 0x76, + 0x4c, 0x0c, 0x45, 0x88, 0xdc, 0x81, 0x6b, 0x1e, 0x67, 0x4a, 0xf0, 0x30, 0x44, 0xf1, 0x8c, 0x4e, + 0x50, 0x46, 0xd4, 0x43, 0xfb, 0x86, 0x31, 0xb9, 0x8c, 0x22, 0x9f, 0xc2, 0x4d, 0x1a, 0x45, 0x72, + 0xc8, 0x1e, 0xb0, 0x59, 0x8e, 0x66, 0x1e, 0x6c, 0xe3, 0xe1, 0x62, 0x01, 0xd2, 0x85, 0xed, 0x60, + 0x12, 0xa1, 0x90, 0x9c, 0x99, 0x6a, 0xca, 0x14, 0x6f, 0x1a, 0xc5, 0xa5, 0x9c, 0xce, 0x7b, 0xc0, + 0xa4, 0xa2, 0x61, 0x68, 0xe0, 0xe1, 0xc0, 0x6e, 0x24, 0x79, 0x3f, 0x8f, 0x36, 0x7e, 0xb2, 0x60, + 0x67, 0xf9, 0x93, 0x44, 0x36, 0xa1, 0x72, 0x82, 0xb3, 0xe4, 0x2d, 0x76, 0xf5, 0x92, 0x8c, 0xe0, + 0xf2, 0x94, 0x86, 0x31, 0xa6, 0xcf, 0xef, 0x7b, 0x3e, 0x06, 0x65, 0xb7, 0x6e, 0x62, 0xfc, 0xde, + 0xa5, 0x4f, 0xac, 0xd6, 0x6b, 0xb8, 0xbe, 0xf4, 0xad, 0x22, 0xbb, 0x00, 0x59, 0xe5, 0x0c, 0x07, + 0x69, 0x6c, 0x05, 0x44, 0x9f, 0x9b, 0x32, 0xce, 0x66, 0xba, 0x2d, 0x8e, 0x24, 0x0a, 0x69, 0x62, + 0xad, 0xba, 0x25, 0xb4, 0x35, 0x80, 0x1b, 0xd9, 0x93, 0x9c, 0xb6, 0x9a, 0x8b, 0x32, 0xe2, 0x4c, + 0x62, 0xf1, 0x79, 0xb1, 0xde, 0xfd, 0xbc, 0xb4, 0x7e, 0xb6, 0x60, 0x45, 0x3f, 0x4c, 0xc4, 0x86, + 0x35, 0x6f, 0x4c, 0x4d, 0x65, 0x25, 0x31, 0x65, 0x5b, 0xdd, 0x92, 0x7a, 0xf9, 0x12, 0xdf, 0x28, + 0x13, 0x4a, 0xcd, 0xcd, 0xf7, 0xe4, 0x3e, 0xc0, 0x71, 0xc0, 0xa8, 0x98, 0x1d, 0x89, 0x50, 0xda, + 0x15, 0xe3, 0xec, 0x3f, 0xe7, 0x5e, 0x3c, 0xa7, 0x97, 0xf3, 0xc9, 0x3f, 0x51, 0x50, 0x68, 0xdc, + 0x87, 0x7a, 0x89, 0x5e, 0x72, 0x67, 0xdb, 0xc5, 0x3b, 0xab, 0x15, 0x73, 0x7c, 0x0b, 0x56, 0x93, + 0xf3, 0x10, 0x02, 0x2b, 0x8c, 0x4e, 0x30, 0x55, 0x33, 0xeb, 0xd6, 0x67, 0x50, 0xcb, 0x3f, 0x55, + 0xd2, 0x05, 0xf0, 0x38, 0x63, 0xe8, 0x29, 0x2e, 0xb2, 0xac, 0x9c, 0x7d, 0xbe, 0xfd, 0x8c, 0x72, + 0x0b, 0x52, 0xad, 0xbb, 0x50, 0xcb, 0x89, 0x65, 0x1e, 0x34, 0xa6, 0x66, 0x51, 0x16, 0x98, 0x59, + 0xb7, 0x7e, 0xa9, 0x40, 0xe1, 0x23, 0x5e, 0xaa, 0xb6, 0x03, 0xab, 0x81, 0x94, 0x31, 0x8a, 0x54, + 0x31, 0xdd, 0x91, 0x36, 0x54, 0xbd, 0x30, 0x40, 0xa6, 0x86, 0x03, 0xf3, 0xd7, 0xd7, 0x7a, 0x57, + 0xe6, 0xa7, 0x7b, 0xd5, 0x7e, 0x8a, 0xb9, 0x39, 0x4b, 0xf6, 0x61, 0xdd, 0x0b, 0x83, 0x8c, 0x48, + 0xbe, 0xf4, 0x5e, 0x7d, 0x7e, 0xba, 0xb7, 0xde, 0x3f, 0x18, 0xe6, 0xf2, 0x45, 0x19, 0xed, 0x54, + 0x7a, 0x3c, 0x4a, 0x3f, 0xf6, 0x9a, 0x9b, 0xee, 0xc8, 0x6b, 0xd8, 0x08, 0x46, 0x2f, 0xf9, 0x09, + 0xb2, 0xbe, 0x19, 0x72, 0xec, 0x55, 0x93, 0x9b, 0xdb, 0x4b, 0xa6, 0x0c, 0x67, 0x58, 0x14, 0x34, + 0xd7, 0xd5, 0xdb, 0x9a, 0x9f, 0xee, 0x6d, 0x0c, 0x07, 0x05, 0xdc, 0x3d, 0x6f, 0x8f, 0xdc, 0x03, + 0x1b, 0x4d, 0x4b, 0x1f, 0x3e, 0xe9, 0x3f, 0x7c, 0x10, 0xab, 0x31, 0x32, 0x95, 0x76, 0x92, 0xf9, + 0xdd, 0xab, 0xee, 0x85, 0x7c, 0x63, 0x06, 0x64, 0xd1, 0xe7, 0x92, 0x12, 0x79, 0x7a, 0xbe, 0xad, + 0x3f, 0x7e, 0x67, 0x5b, 0x27, 0x13, 0x9e, 0x93, 0x8f, 0xa8, 0x7a, 0x54, 0x72, 0x8c, 0xfd, 0x42, + 0x6d, 0x75, 0x7f, 0xb5, 0xa0, 0x9e, 0xf5, 0xd7, 0x0b, 0x14, 0xd3, 0xc0, 0x43, 0xf2, 0x05, 0x54, + 0x1e, 0xa1, 0x22, 0x3b, 0x0b, 0x33, 0x91, 0x99, 0x03, 0x1b, 0x5b, 0x0b, 0x78, 0xcb, 0xfe, 0xee, + 0x8f, 0xbf, 0x7e, 0xbc, 0x44, 0xc8, 0xa6, 0x99, 0x6d, 0xa7, 0xfb, 0xf9, 0x5c, 0x49, 0xc6, 0x00, + 0x8f, 0x30, 0xff, 0x24, 0x2f, 0x32, 0xd9, 0x5c, 0xc0, 0x4b, 0xbd, 0xde, 0x6a, 0x1a, 0x0f, 0x0d, + 0x62, 0x97, 0x3d, 0x74, 0xd2, 0x16, 0xef, 0xf5, 0x7f, 0x9b, 0xef, 0x5a, 0xbf, 0xcf, 0x77, 0xad, + 0x3f, 0xe7, 0xbb, 0xd6, 0x57, 0x1f, 0xfd, 0xbb, 0x69, 0x3a, 0x29, 0xb5, 0xdc, 0xd8, 0xf1, 0xaa, + 0x99, 0x7d, 0xef, 0xfe, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x99, 0x28, 0x60, 0x2e, 0xea, 0x0b, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -999,6 +1009,15 @@ func (m *Settings) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.InstallationID) > 0 { + i -= len(m.InstallationID) + copy(dAtA[i:], m.InstallationID) + i = encodeVarintSettings(dAtA, i, uint64(len(m.InstallationID))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xd2 + } if m.ImpersonationEnabled { i-- if m.ImpersonationEnabled { @@ -1774,6 +1793,10 @@ func (m *Settings) Size() (n int) { if m.ImpersonationEnabled { n += 3 } + l = len(m.InstallationID) + if l > 0 { + n += 2 + l + sovSettings(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -2884,6 +2907,38 @@ func (m *Settings) Unmarshal(dAtA []byte) error { } } m.ImpersonationEnabled = bool(v != 0) + case 26: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InstallationID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSettings + } + 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 ErrInvalidLengthSettings + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthSettings + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.InstallationID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipSettings(dAtA[iNdEx:]) diff --git a/pkg/apis/application/v1alpha1/app_project_types.go b/pkg/apis/application/v1alpha1/app_project_types.go index b888cd37391b3b..436e578548e3da 100644 --- a/pkg/apis/application/v1alpha1/app_project_types.go +++ b/pkg/apis/application/v1alpha1/app_project_types.go @@ -6,15 +6,22 @@ import ( "strconv" "strings" - "github.com/argoproj/argo-cd/v2/util/git" - "github.com/argoproj/argo-cd/v2/util/glob" - + globutil "github.com/gobwas/glob" "github.com/google/go-cmp/cmp" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/argoproj/argo-cd/v2/util/git" + "github.com/argoproj/argo-cd/v2/util/glob" +) + +const ( + // serviceAccountDisallowedCharSet contains the characters that are not allowed to be present + // in a DefaultServiceAccount configured for a DestinationServiceAccount + serviceAccountDisallowedCharSet = "!*[]{}\\/" ) type ErrApplicationNotAllowedToUseProject struct { @@ -267,12 +274,27 @@ func (p *AppProject) ValidateProject() error { destServiceAccts := make(map[string]bool) for _, destServiceAcct := range p.Spec.DestinationServiceAccounts { - if destServiceAcct.Server == "!*" { - return status.Errorf(codes.InvalidArgument, "server has an invalid format, '!*'") + if strings.Contains(destServiceAcct.Server, "!") { + return status.Errorf(codes.InvalidArgument, "server has an invalid format, '%s'", destServiceAcct.Server) } - if destServiceAcct.Namespace == "!*" { - return status.Errorf(codes.InvalidArgument, "namespace has an invalid format, '!*'") + if strings.Contains(destServiceAcct.Namespace, "!") { + return status.Errorf(codes.InvalidArgument, "namespace has an invalid format, '%s'", destServiceAcct.Namespace) + } + + if strings.Trim(destServiceAcct.DefaultServiceAccount, " ") == "" || + strings.ContainsAny(destServiceAcct.DefaultServiceAccount, serviceAccountDisallowedCharSet) { + return status.Errorf(codes.InvalidArgument, "defaultServiceAccount has an invalid format, '%s'", destServiceAcct.DefaultServiceAccount) + } + + _, err := globutil.Compile(destServiceAcct.Server) + if err != nil { + return status.Errorf(codes.InvalidArgument, "server has an invalid format, '%s'", destServiceAcct.Server) + } + + _, err = globutil.Compile(destServiceAcct.Namespace) + if err != nil { + return status.Errorf(codes.InvalidArgument, "namespace has an invalid format, '%s'", destServiceAcct.Namespace) } key := fmt.Sprintf("%s/%s", destServiceAcct.Server, destServiceAcct.Namespace) @@ -461,7 +483,6 @@ func (proj AppProject) IsDestinationPermitted(dst ApplicationDestination, projec func (proj AppProject) isDestinationMatched(dst ApplicationDestination) bool { anyDestinationMatched := false - noDenyDestinationsMatched := true for _, item := range proj.Spec.Destinations { dstNameMatched := dst.Name != "" && globMatch(item.Name, dst.Name, true) @@ -471,12 +492,14 @@ func (proj AppProject) isDestinationMatched(dst ApplicationDestination) bool { matched := (dstServerMatched || dstNameMatched) && dstNamespaceMatched if matched { anyDestinationMatched = true - } else if ((!dstNameMatched && isDenyPattern(item.Name)) || (!dstServerMatched && isDenyPattern(item.Server))) || (!dstNamespaceMatched && isDenyPattern(item.Namespace)) { - noDenyDestinationsMatched = false + } else if (!dstNameMatched && isDenyPattern(item.Name)) || (!dstServerMatched && isDenyPattern(item.Server)) && dstNamespaceMatched { + return false + } else if !dstNamespaceMatched && isDenyPattern(item.Namespace) && dstServerMatched { + return false } } - return anyDestinationMatched && noDenyDestinationsMatched + return anyDestinationMatched } func isDenyPattern(pattern string) bool { diff --git a/pkg/apis/application/v1alpha1/applicationset_types.go b/pkg/apis/application/v1alpha1/applicationset_types.go index d4446130c70264..16f9eeecd5d85e 100644 --- a/pkg/apis/application/v1alpha1/applicationset_types.go +++ b/pkg/apis/application/v1alpha1/applicationset_types.go @@ -379,6 +379,9 @@ type ClusterGenerator struct { // Values contains key/value pairs which are passed directly as parameters to the template Values map[string]string `json:"values,omitempty" protobuf:"bytes,3,name=values"` + + // returns the clusters a single 'clusters' value in the template + FlatList bool `json:"flatList,omitempty" protobuf:"bytes,4,name=flatList"` } // DuckType defines a generator to match against clusters registered with ArgoCD. diff --git a/pkg/apis/application/v1alpha1/generated.pb.go b/pkg/apis/application/v1alpha1/generated.pb.go index 5fc96609621cad..30de74a3b90389 100644 --- a/pkg/apis/application/v1alpha1/generated.pb.go +++ b/pkg/apis/application/v1alpha1/generated.pb.go @@ -4593,717 +4593,720 @@ func init() { } var fileDescriptor_030104ce3b95bcac = []byte{ - // 11357 bytes of a gzipped FileDescriptorProto + // 11394 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x70, 0x1c, 0xc9, 0x75, 0x98, 0x66, 0x17, 0x0b, 0xec, 0x3e, 0x7c, 0x11, 0x4d, 0xf2, 0x0e, 0xa4, 0xee, 0x0e, 0xf4, 0x9c, 0x7d, 0x3a, 0x45, 0x77, 0x80, 0x8f, 0xba, 0x93, 0x2f, 0x3a, 0x4b, 0x32, 0x3e, 0x48, 0x10, 0x24, 0x40, 0xe0, 0x1a, 0x20, 0x29, 0x9d, 0x7c, 0x3a, 0x0d, 0x66, 0x1b, 0x8b, 0x21, 0x66, 0x67, 0xf6, 0x66, 0x66, 0x41, 0xe2, 0x2c, 0xc9, 0x92, 0x25, 0xd9, 0x72, 0xf4, 0x71, 0x8a, 0x94, 0xaa, - 0x9c, 0x13, 0x4b, 0x91, 0x2d, 0x27, 0x95, 0x54, 0x4a, 0x15, 0x25, 0xf9, 0x11, 0x27, 0xb6, 0xcb, - 0x15, 0x3b, 0xe5, 0x52, 0xe2, 0xa4, 0xec, 0x52, 0xa9, 0x2c, 0x25, 0xb1, 0x11, 0x89, 0x71, 0x2a, - 0xa9, 0xfc, 0x70, 0x55, 0x9c, 0xfc, 0x48, 0x31, 0xf9, 0x91, 0xea, 0xef, 0x9e, 0xd9, 0x59, 0x60, - 0x41, 0x0c, 0x40, 0x4a, 0xb9, 0x7f, 0xbb, 0xfd, 0x5e, 0xf7, 0xeb, 0xe9, 0x8f, 0xf7, 0x5e, 0xbf, - 0x7e, 0xef, 0x35, 0x2c, 0x36, 0xbc, 0x64, 0xb3, 0xbd, 0x3e, 0xe9, 0x86, 0xcd, 0x29, 0x27, 0x6a, - 0x84, 0xad, 0x28, 0xbc, 0xc9, 0x7e, 0x3c, 0xed, 0xd6, 0xa7, 0xb6, 0xcf, 0x4f, 0xb5, 0xb6, 0x1a, - 0x53, 0x4e, 0xcb, 0x8b, 0xa7, 0x9c, 0x56, 0xcb, 0xf7, 0x5c, 0x27, 0xf1, 0xc2, 0x60, 0x6a, 0xfb, - 0x19, 0xc7, 0x6f, 0x6d, 0x3a, 0xcf, 0x4c, 0x35, 0x48, 0x40, 0x22, 0x27, 0x21, 0xf5, 0xc9, 0x56, - 0x14, 0x26, 0x21, 0xfa, 0x69, 0xdd, 0xda, 0xa4, 0x6c, 0x8d, 0xfd, 0x78, 0xc5, 0xad, 0x4f, 0x6e, - 0x9f, 0x9f, 0x6c, 0x6d, 0x35, 0x26, 0x69, 0x6b, 0x93, 0x46, 0x6b, 0x93, 0xb2, 0xb5, 0xb3, 0x4f, - 0x1b, 0x7d, 0x69, 0x84, 0x8d, 0x70, 0x8a, 0x35, 0xba, 0xde, 0xde, 0x60, 0xff, 0xd8, 0x1f, 0xf6, - 0x8b, 0x13, 0x3b, 0x6b, 0x6f, 0x3d, 0x1f, 0x4f, 0x7a, 0x21, 0xed, 0xde, 0x94, 0x1b, 0x46, 0x64, - 0x6a, 0xbb, 0xa3, 0x43, 0x67, 0x2f, 0x69, 0x1c, 0x72, 0x3b, 0x21, 0x41, 0xec, 0x85, 0x41, 0xfc, - 0x34, 0xed, 0x02, 0x89, 0xb6, 0x49, 0x64, 0x7e, 0x9e, 0x81, 0x90, 0xd7, 0xd2, 0xb3, 0xba, 0xa5, - 0xa6, 0xe3, 0x6e, 0x7a, 0x01, 0x89, 0x76, 0x74, 0xf5, 0x26, 0x49, 0x9c, 0xbc, 0x5a, 0x53, 0xdd, - 0x6a, 0x45, 0xed, 0x20, 0xf1, 0x9a, 0xa4, 0xa3, 0xc2, 0xbb, 0xf6, 0xab, 0x10, 0xbb, 0x9b, 0xa4, - 0xe9, 0x74, 0xd4, 0x7b, 0x67, 0xb7, 0x7a, 0xed, 0xc4, 0xf3, 0xa7, 0xbc, 0x20, 0x89, 0x93, 0x28, - 0x5b, 0xc9, 0xfe, 0x55, 0x0b, 0x86, 0xa7, 0x6f, 0xac, 0x4e, 0xb7, 0x93, 0xcd, 0xd9, 0x30, 0xd8, - 0xf0, 0x1a, 0xe8, 0x39, 0x18, 0x74, 0xfd, 0x76, 0x9c, 0x90, 0xe8, 0xaa, 0xd3, 0x24, 0xe3, 0xd6, - 0x39, 0xeb, 0xc9, 0xda, 0xcc, 0xc9, 0x6f, 0xed, 0x4e, 0xbc, 0xe5, 0xce, 0xee, 0xc4, 0xe0, 0xac, - 0x06, 0x61, 0x13, 0x0f, 0xbd, 0x1d, 0x06, 0xa2, 0xd0, 0x27, 0xd3, 0xf8, 0xea, 0x78, 0x89, 0x55, - 0x19, 0x15, 0x55, 0x06, 0x30, 0x2f, 0xc6, 0x12, 0x4e, 0x51, 0x5b, 0x51, 0xb8, 0xe1, 0xf9, 0x64, - 0xbc, 0x9c, 0x46, 0x5d, 0xe1, 0xc5, 0x58, 0xc2, 0xed, 0x3f, 0x29, 0x01, 0x4c, 0xb7, 0x5a, 0x2b, - 0x51, 0x78, 0x93, 0xb8, 0x09, 0xfa, 0x30, 0x54, 0xe9, 0x30, 0xd7, 0x9d, 0xc4, 0x61, 0x1d, 0x1b, - 0x3c, 0xff, 0x93, 0x93, 0xfc, 0xab, 0x27, 0xcd, 0xaf, 0xd6, 0x8b, 0x8c, 0x62, 0x4f, 0x6e, 0x3f, - 0x33, 0xb9, 0xbc, 0x4e, 0xeb, 0x2f, 0x91, 0xc4, 0x99, 0x41, 0x82, 0x18, 0xe8, 0x32, 0xac, 0x5a, - 0x45, 0x01, 0xf4, 0xc5, 0x2d, 0xe2, 0xb2, 0x6f, 0x18, 0x3c, 0xbf, 0x38, 0x79, 0x98, 0xd5, 0x3c, - 0xa9, 0x7b, 0xbe, 0xda, 0x22, 0xee, 0xcc, 0x90, 0xa0, 0xdc, 0x47, 0xff, 0x61, 0x46, 0x07, 0x6d, - 0x43, 0x7f, 0x9c, 0x38, 0x49, 0x3b, 0x66, 0x43, 0x31, 0x78, 0xfe, 0x6a, 0x61, 0x14, 0x59, 0xab, - 0x33, 0x23, 0x82, 0x66, 0x3f, 0xff, 0x8f, 0x05, 0x35, 0xfb, 0xcf, 0x2c, 0x18, 0xd1, 0xc8, 0x8b, - 0x5e, 0x9c, 0xa0, 0x9f, 0xed, 0x18, 0xdc, 0xc9, 0xde, 0x06, 0x97, 0xd6, 0x66, 0x43, 0x7b, 0x42, - 0x10, 0xab, 0xca, 0x12, 0x63, 0x60, 0x9b, 0x50, 0xf1, 0x12, 0xd2, 0x8c, 0xc7, 0x4b, 0xe7, 0xca, - 0x4f, 0x0e, 0x9e, 0xbf, 0x54, 0xd4, 0x77, 0xce, 0x0c, 0x0b, 0xa2, 0x95, 0x05, 0xda, 0x3c, 0xe6, - 0x54, 0xec, 0xbf, 0x1c, 0x36, 0xbf, 0x8f, 0x0e, 0x38, 0x7a, 0x06, 0x06, 0xe3, 0xb0, 0x1d, 0xb9, - 0x04, 0x93, 0x56, 0x18, 0x8f, 0x5b, 0xe7, 0xca, 0x74, 0xe9, 0xd1, 0x45, 0xbd, 0xaa, 0x8b, 0xb1, - 0x89, 0x83, 0xbe, 0x60, 0xc1, 0x50, 0x9d, 0xc4, 0x89, 0x17, 0x30, 0xfa, 0xb2, 0xf3, 0x6b, 0x87, - 0xee, 0xbc, 0x2c, 0x9c, 0xd3, 0x8d, 0xcf, 0x9c, 0x12, 0x1f, 0x32, 0x64, 0x14, 0xc6, 0x38, 0x45, - 0x9f, 0x6e, 0xce, 0x3a, 0x89, 0xdd, 0xc8, 0x6b, 0xd1, 0xff, 0x62, 0xfb, 0xa8, 0xcd, 0x39, 0xa7, - 0x41, 0xd8, 0xc4, 0x43, 0x01, 0x54, 0xe8, 0xe6, 0x8b, 0xc7, 0xfb, 0x58, 0xff, 0x17, 0x0e, 0xd7, - 0x7f, 0x31, 0xa8, 0x74, 0x5f, 0xeb, 0xd1, 0xa7, 0xff, 0x62, 0xcc, 0xc9, 0xa0, 0xcf, 0x5b, 0x30, - 0x2e, 0x98, 0x03, 0x26, 0x7c, 0x40, 0x6f, 0x6c, 0x7a, 0x09, 0xf1, 0xbd, 0x38, 0x19, 0xaf, 0xb0, - 0x3e, 0x4c, 0xf5, 0xb6, 0xb6, 0xe6, 0xa3, 0xb0, 0xdd, 0xba, 0xe2, 0x05, 0xf5, 0x99, 0x73, 0x82, - 0xd2, 0xf8, 0x6c, 0x97, 0x86, 0x71, 0x57, 0x92, 0xe8, 0xcb, 0x16, 0x9c, 0x0d, 0x9c, 0x26, 0x89, - 0x5b, 0x0e, 0x9d, 0x5a, 0x0e, 0x9e, 0xf1, 0x1d, 0x77, 0x8b, 0xf5, 0xa8, 0xff, 0xde, 0x7a, 0x64, - 0x8b, 0x1e, 0x9d, 0xbd, 0xda, 0xb5, 0x69, 0xbc, 0x07, 0x59, 0xf4, 0x75, 0x0b, 0xc6, 0xc2, 0xa8, - 0xb5, 0xe9, 0x04, 0xa4, 0x2e, 0xa1, 0xf1, 0xf8, 0x00, 0xdb, 0x7a, 0x1f, 0x3a, 0xdc, 0x14, 0x2d, - 0x67, 0x9b, 0x5d, 0x0a, 0x03, 0x2f, 0x09, 0xa3, 0x55, 0x92, 0x24, 0x5e, 0xd0, 0x88, 0x67, 0x4e, - 0xdf, 0xd9, 0x9d, 0x18, 0xeb, 0xc0, 0xc2, 0x9d, 0xfd, 0x41, 0x3f, 0x07, 0x83, 0xf1, 0x4e, 0xe0, - 0xde, 0xf0, 0x82, 0x7a, 0x78, 0x2b, 0x1e, 0xaf, 0x16, 0xb1, 0x7d, 0x57, 0x55, 0x83, 0x62, 0x03, - 0x6a, 0x02, 0xd8, 0xa4, 0x96, 0x3f, 0x71, 0x7a, 0x29, 0xd5, 0x8a, 0x9e, 0x38, 0xbd, 0x98, 0xf6, - 0x20, 0x8b, 0x7e, 0xc9, 0x82, 0xe1, 0xd8, 0x6b, 0x04, 0x4e, 0xd2, 0x8e, 0xc8, 0x15, 0xb2, 0x13, - 0x8f, 0x03, 0xeb, 0xc8, 0xe5, 0x43, 0x8e, 0x8a, 0xd1, 0xe4, 0xcc, 0x69, 0xd1, 0xc7, 0x61, 0xb3, - 0x34, 0xc6, 0x69, 0xba, 0x79, 0x1b, 0x4d, 0x2f, 0xeb, 0xc1, 0x62, 0x37, 0x9a, 0x5e, 0xd4, 0x5d, - 0x49, 0xa2, 0x9f, 0x81, 0x13, 0xbc, 0x48, 0x8d, 0x6c, 0x3c, 0x3e, 0xc4, 0x18, 0xed, 0xa9, 0x3b, - 0xbb, 0x13, 0x27, 0x56, 0x33, 0x30, 0xdc, 0x81, 0x8d, 0x5e, 0x85, 0x89, 0x16, 0x89, 0x9a, 0x5e, - 0xb2, 0x1c, 0xf8, 0x3b, 0x92, 0x7d, 0xbb, 0x61, 0x8b, 0xd4, 0x45, 0x77, 0xe2, 0xf1, 0xe1, 0x73, - 0xd6, 0x93, 0xd5, 0x99, 0xb7, 0x89, 0x6e, 0x4e, 0xac, 0xec, 0x8d, 0x8e, 0xf7, 0x6b, 0x0f, 0xfd, - 0x81, 0x05, 0x67, 0x0d, 0x2e, 0xbb, 0x4a, 0xa2, 0x6d, 0xcf, 0x25, 0xd3, 0xae, 0x1b, 0xb6, 0x83, - 0x24, 0x1e, 0x1f, 0x61, 0xc3, 0xb8, 0x7e, 0x14, 0x3c, 0x3f, 0x4d, 0x4a, 0xaf, 0xcb, 0xae, 0x28, - 0x31, 0xde, 0xa3, 0xa7, 0xf6, 0xbf, 0x2e, 0xc1, 0x89, 0xac, 0x06, 0x80, 0xfe, 0x9e, 0x05, 0xa3, - 0x37, 0x6f, 0x25, 0x6b, 0xe1, 0x16, 0x09, 0xe2, 0x99, 0x1d, 0xca, 0xa7, 0x99, 0xec, 0x1b, 0x3c, - 0xef, 0x16, 0xab, 0x6b, 0x4c, 0x5e, 0x4e, 0x53, 0xb9, 0x10, 0x24, 0xd1, 0xce, 0xcc, 0xc3, 0xe2, - 0x9b, 0x46, 0x2f, 0xdf, 0x58, 0x33, 0xa1, 0x38, 0xdb, 0xa9, 0xb3, 0x9f, 0xb5, 0xe0, 0x54, 0x5e, - 0x13, 0xe8, 0x04, 0x94, 0xb7, 0xc8, 0x0e, 0xd7, 0x44, 0x31, 0xfd, 0x89, 0x5e, 0x86, 0xca, 0xb6, - 0xe3, 0xb7, 0x89, 0x50, 0xd3, 0xe6, 0x0f, 0xf7, 0x21, 0xaa, 0x67, 0x98, 0xb7, 0xfa, 0xee, 0xd2, - 0xf3, 0x96, 0xfd, 0x47, 0x65, 0x18, 0x34, 0x26, 0xed, 0x18, 0x54, 0xcf, 0x30, 0xa5, 0x7a, 0x2e, - 0x15, 0xb6, 0xde, 0xba, 0xea, 0x9e, 0xb7, 0x32, 0xba, 0xe7, 0x72, 0x71, 0x24, 0xf7, 0x54, 0x3e, - 0x51, 0x02, 0xb5, 0xb0, 0x45, 0x8f, 0x21, 0x54, 0x87, 0xe9, 0x2b, 0x62, 0x0a, 0x97, 0x65, 0x73, - 0x33, 0xc3, 0x77, 0x76, 0x27, 0x6a, 0xea, 0x2f, 0xd6, 0x84, 0xec, 0xef, 0x5a, 0x70, 0xca, 0xe8, - 0xe3, 0x6c, 0x18, 0xd4, 0x3d, 0x36, 0xb5, 0xe7, 0xa0, 0x2f, 0xd9, 0x69, 0xc9, 0xa3, 0x8e, 0x1a, - 0xa9, 0xb5, 0x9d, 0x16, 0xc1, 0x0c, 0x42, 0x4f, 0x2c, 0x4d, 0x12, 0xc7, 0x4e, 0x83, 0x64, 0x0f, - 0x37, 0x4b, 0xbc, 0x18, 0x4b, 0x38, 0x8a, 0x00, 0xf9, 0x4e, 0x9c, 0xac, 0x45, 0x4e, 0x10, 0xb3, - 0xe6, 0xd7, 0xbc, 0x26, 0x11, 0x03, 0xfc, 0x57, 0x7a, 0x5b, 0x31, 0xb4, 0xc6, 0xcc, 0x43, 0x77, - 0x76, 0x27, 0xd0, 0x62, 0x47, 0x4b, 0x38, 0xa7, 0x75, 0xfb, 0xcb, 0x16, 0x3c, 0x94, 0xcf, 0x60, - 0xd0, 0x13, 0xd0, 0xcf, 0xcf, 0xb9, 0xe2, 0xeb, 0xf4, 0x94, 0xb0, 0x52, 0x2c, 0xa0, 0x68, 0x0a, - 0x6a, 0x4a, 0xe0, 0x89, 0x6f, 0x1c, 0x13, 0xa8, 0x35, 0x2d, 0x25, 0x35, 0x0e, 0x1d, 0x34, 0xfa, - 0x47, 0xa8, 0xa0, 0x6a, 0xd0, 0xd8, 0xc1, 0x90, 0x41, 0xec, 0xef, 0x58, 0xf0, 0xe3, 0xbd, 0xb0, - 0xbd, 0xa3, 0xeb, 0xe3, 0x2a, 0x9c, 0xae, 0x93, 0x0d, 0xa7, 0xed, 0x27, 0x69, 0x8a, 0xa2, 0xd3, - 0x8f, 0x8a, 0xca, 0xa7, 0xe7, 0xf2, 0x90, 0x70, 0x7e, 0x5d, 0xfb, 0x3f, 0x59, 0x30, 0x6a, 0x7c, - 0xd6, 0x31, 0x1c, 0x9d, 0x82, 0xf4, 0xd1, 0x69, 0xa1, 0xb0, 0x6d, 0xda, 0xe5, 0xec, 0xf4, 0x79, - 0x0b, 0xce, 0x1a, 0x58, 0x4b, 0x4e, 0xe2, 0x6e, 0x5e, 0xb8, 0xdd, 0x8a, 0x48, 0x1c, 0xd3, 0x25, - 0xf5, 0xa8, 0xc1, 0x8e, 0x67, 0x06, 0x45, 0x0b, 0xe5, 0x2b, 0x64, 0x87, 0xf3, 0xe6, 0xa7, 0xa0, - 0xca, 0xf7, 0x5c, 0x18, 0x89, 0x49, 0x52, 0xdf, 0xb6, 0x2c, 0xca, 0xb1, 0xc2, 0x40, 0x36, 0xf4, - 0x33, 0x9e, 0x4b, 0x79, 0x10, 0x55, 0x13, 0x80, 0xce, 0xfb, 0x75, 0x56, 0x82, 0x05, 0xc4, 0x8e, - 0x53, 0xdd, 0x59, 0x89, 0x08, 0x5b, 0x0f, 0xf5, 0x8b, 0x1e, 0xf1, 0xeb, 0x31, 0x3d, 0xd6, 0x39, - 0x41, 0x10, 0x26, 0xe2, 0x84, 0x66, 0x1c, 0xeb, 0xa6, 0x75, 0x31, 0x36, 0x71, 0x28, 0x51, 0xdf, - 0x59, 0x27, 0x3e, 0x1f, 0x51, 0x41, 0x74, 0x91, 0x95, 0x60, 0x01, 0xb1, 0xef, 0x94, 0xd8, 0x01, - 0x52, 0x71, 0x34, 0x72, 0x1c, 0xd6, 0x87, 0x28, 0x25, 0x02, 0x56, 0x8a, 0xe3, 0xc7, 0xa4, 0xbb, - 0x05, 0xe2, 0xb5, 0x8c, 0x14, 0xc0, 0x85, 0x52, 0xdd, 0xdb, 0x0a, 0xf1, 0xf1, 0x32, 0x4c, 0xa4, - 0x2b, 0x74, 0x08, 0x11, 0x7a, 0xe4, 0x35, 0x08, 0x65, 0xed, 0x51, 0x06, 0x3e, 0x36, 0xf1, 0xba, - 0xf0, 0xe1, 0xd2, 0x51, 0xf2, 0x61, 0x53, 0x4c, 0x94, 0xf7, 0x11, 0x13, 0x4f, 0xa8, 0x51, 0xef, - 0xcb, 0xf0, 0xbc, 0xb4, 0xa8, 0x3c, 0x07, 0x7d, 0x71, 0x42, 0x5a, 0xe3, 0x95, 0x34, 0x9b, 0x5d, - 0x4d, 0x48, 0x0b, 0x33, 0x08, 0x7a, 0x0f, 0x8c, 0x26, 0x4e, 0xd4, 0x20, 0x49, 0x44, 0xb6, 0x3d, - 0x66, 0xbb, 0x64, 0xe7, 0xd9, 0xda, 0xcc, 0x49, 0xaa, 0x75, 0xad, 0x31, 0x10, 0x96, 0x20, 0x9c, - 0xc5, 0xb5, 0xff, 0x7b, 0x09, 0x1e, 0x4e, 0x4f, 0x81, 0x16, 0x8c, 0xef, 0x4b, 0x09, 0xc6, 0x77, - 0x98, 0x82, 0xf1, 0xee, 0xee, 0xc4, 0x5b, 0xbb, 0x54, 0xfb, 0xa1, 0x91, 0x9b, 0x68, 0x3e, 0x33, - 0x09, 0x53, 0xe9, 0x49, 0xb8, 0xbb, 0x3b, 0xf1, 0x68, 0x97, 0x6f, 0xcc, 0xcc, 0xd2, 0x13, 0xd0, - 0x1f, 0x11, 0x27, 0x0e, 0x03, 0x31, 0x4f, 0x6a, 0x36, 0x31, 0x2b, 0xc5, 0x02, 0x6a, 0x7f, 0xbb, - 0x96, 0x1d, 0xec, 0x79, 0x6e, 0x8f, 0x0d, 0x23, 0xe4, 0x41, 0x1f, 0x3b, 0xb5, 0x71, 0xce, 0x72, - 0xe5, 0x70, 0xbb, 0x90, 0x4a, 0x11, 0xd5, 0xf4, 0x4c, 0x95, 0xce, 0x1a, 0x2d, 0xc2, 0x8c, 0x04, - 0xba, 0x0d, 0x55, 0x57, 0x1e, 0xa6, 0x4a, 0x45, 0x98, 0x1d, 0xc5, 0x51, 0x4a, 0x53, 0x1c, 0xa2, - 0xec, 0x5e, 0x9d, 0xc0, 0x14, 0x35, 0x44, 0xa0, 0xdc, 0xf0, 0x12, 0x31, 0xad, 0x87, 0x3c, 0x2e, - 0xcf, 0x7b, 0xc6, 0x27, 0x0e, 0x50, 0x19, 0x34, 0xef, 0x25, 0x98, 0xb6, 0x8f, 0x3e, 0x6d, 0xc1, - 0x60, 0xec, 0x36, 0x57, 0xa2, 0x70, 0xdb, 0xab, 0x93, 0x48, 0xe8, 0x98, 0x87, 0xe4, 0x6c, 0xab, - 0xb3, 0x4b, 0xb2, 0x41, 0x4d, 0x97, 0x9b, 0x2f, 0x34, 0x04, 0x9b, 0x74, 0xe9, 0xd9, 0xeb, 0x61, - 0xf1, 0xed, 0x73, 0xc4, 0x65, 0x3b, 0x4e, 0x9e, 0x99, 0xd9, 0x4a, 0x39, 0xb4, 0xce, 0x3d, 0xd7, - 0x76, 0xb7, 0xe8, 0x7e, 0xd3, 0x1d, 0x7a, 0xeb, 0x9d, 0xdd, 0x89, 0x87, 0x67, 0xf3, 0x69, 0xe2, - 0x6e, 0x9d, 0x61, 0x03, 0xd6, 0x6a, 0xfb, 0x3e, 0x26, 0xaf, 0xb6, 0x09, 0xb3, 0x88, 0x15, 0x30, - 0x60, 0x2b, 0xba, 0xc1, 0xcc, 0x80, 0x19, 0x10, 0x6c, 0xd2, 0x45, 0xaf, 0x42, 0x7f, 0xd3, 0x49, - 0x22, 0xef, 0xb6, 0x30, 0x83, 0x1d, 0xf2, 0x14, 0xb4, 0xc4, 0xda, 0xd2, 0xc4, 0x99, 0xa0, 0xe7, - 0x85, 0x58, 0x10, 0x42, 0x4d, 0xa8, 0x34, 0x49, 0xd4, 0x20, 0xe3, 0xd5, 0x22, 0x4c, 0xfe, 0x4b, - 0xb4, 0x29, 0x4d, 0xb0, 0x46, 0x95, 0x2b, 0x56, 0x86, 0x39, 0x15, 0xf4, 0x32, 0x54, 0x63, 0xe2, - 0x13, 0x97, 0xaa, 0x47, 0x35, 0x46, 0xf1, 0x9d, 0x3d, 0xaa, 0x8a, 0x54, 0x2f, 0x59, 0x15, 0x55, - 0xf9, 0x06, 0x93, 0xff, 0xb0, 0x6a, 0x92, 0x0e, 0x60, 0xcb, 0x6f, 0x37, 0xbc, 0x60, 0x1c, 0x8a, - 0x18, 0xc0, 0x15, 0xd6, 0x56, 0x66, 0x00, 0x79, 0x21, 0x16, 0x84, 0xec, 0xff, 0x62, 0x01, 0x4a, - 0x33, 0xb5, 0x63, 0xd0, 0x89, 0x5f, 0x4d, 0xeb, 0xc4, 0x8b, 0x45, 0x2a, 0x2d, 0x5d, 0xd4, 0xe2, - 0xdf, 0xaa, 0x41, 0x46, 0x1c, 0x5c, 0x25, 0x71, 0x42, 0xea, 0x6f, 0xb2, 0xf0, 0x37, 0x59, 0xf8, - 0x9b, 0x2c, 0x5c, 0xb1, 0xf0, 0xf5, 0x0c, 0x0b, 0x7f, 0xaf, 0xb1, 0xeb, 0xf5, 0xfd, 0xfa, 0x2b, - 0xea, 0x02, 0xde, 0xec, 0x81, 0x81, 0x40, 0x39, 0xc1, 0xe5, 0xd5, 0xe5, 0xab, 0xb9, 0x3c, 0xfb, - 0x95, 0x34, 0xcf, 0x3e, 0x2c, 0x89, 0xff, 0x1f, 0xb8, 0xf4, 0x1f, 0x58, 0xf0, 0xb6, 0x34, 0xf7, - 0x92, 0x2b, 0x67, 0xa1, 0x11, 0x84, 0x11, 0x99, 0xf3, 0x36, 0x36, 0x48, 0x44, 0x02, 0x97, 0xc4, - 0xca, 0xb6, 0x63, 0x75, 0xb3, 0xed, 0xa0, 0x67, 0x61, 0xe8, 0x66, 0x1c, 0x06, 0x2b, 0xa1, 0x17, - 0x08, 0x16, 0x44, 0x4f, 0x1c, 0x27, 0xee, 0xec, 0x4e, 0x0c, 0xd1, 0x11, 0x95, 0xe5, 0x38, 0x85, - 0x85, 0x66, 0x61, 0xec, 0xe6, 0xab, 0x2b, 0x4e, 0x62, 0x58, 0x13, 0xe4, 0xb9, 0x9f, 0xdd, 0x47, - 0x5d, 0x7e, 0x31, 0x03, 0xc4, 0x9d, 0xf8, 0xf6, 0xdf, 0x2e, 0xc1, 0x99, 0xcc, 0x87, 0x84, 0xbe, - 0x1f, 0xb6, 0x13, 0x7a, 0x26, 0x42, 0x5f, 0xb5, 0xe0, 0x44, 0x33, 0x6d, 0xb0, 0x88, 0x85, 0xb9, - 0xfb, 0xfd, 0x85, 0xc9, 0x88, 0x8c, 0x45, 0x64, 0x66, 0x5c, 0x8c, 0xd0, 0x89, 0x0c, 0x20, 0xc6, - 0x1d, 0x7d, 0x41, 0x2f, 0x43, 0xad, 0xe9, 0xdc, 0xbe, 0xd6, 0xaa, 0x3b, 0x89, 0x3c, 0x8e, 0x76, - 0xb7, 0x22, 0xb4, 0x13, 0xcf, 0x9f, 0xe4, 0x9e, 0x1b, 0x93, 0x0b, 0x41, 0xb2, 0x1c, 0xad, 0x26, - 0x91, 0x17, 0x34, 0xb8, 0x91, 0x73, 0x49, 0x36, 0x83, 0x75, 0x8b, 0xf6, 0x57, 0xac, 0xac, 0x90, - 0x52, 0xa3, 0x13, 0x39, 0x09, 0x69, 0xec, 0xa0, 0x8f, 0x40, 0x85, 0x9e, 0x1b, 0xe5, 0xa8, 0xdc, - 0x28, 0x52, 0x72, 0x1a, 0x33, 0xa1, 0x85, 0x28, 0xfd, 0x17, 0x63, 0x4e, 0xd4, 0xfe, 0x6a, 0x2d, - 0xab, 0x2c, 0xb0, 0xbb, 0xf9, 0xf3, 0x00, 0x8d, 0x70, 0x8d, 0x34, 0x5b, 0x3e, 0x1d, 0x16, 0x8b, - 0x5d, 0xf0, 0x28, 0x53, 0xc9, 0xbc, 0x82, 0x60, 0x03, 0x0b, 0xfd, 0xb2, 0x05, 0xd0, 0x90, 0x6b, - 0x5e, 0x2a, 0x02, 0xd7, 0x8a, 0xfc, 0x1c, 0xbd, 0xa3, 0x74, 0x5f, 0x14, 0x41, 0x6c, 0x10, 0x47, - 0xbf, 0x60, 0x41, 0x35, 0x91, 0xdd, 0xe7, 0xa2, 0x71, 0xad, 0xc8, 0x9e, 0xc8, 0x8f, 0xd6, 0x3a, - 0x91, 0x1a, 0x12, 0x45, 0x17, 0xfd, 0xa2, 0x05, 0x10, 0xef, 0x04, 0xee, 0x4a, 0xe8, 0x7b, 0xee, - 0x8e, 0x90, 0x98, 0xd7, 0x0b, 0x35, 0xe7, 0xa8, 0xd6, 0x67, 0x46, 0xe8, 0x68, 0xe8, 0xff, 0xd8, - 0xa0, 0x8c, 0x3e, 0x06, 0xd5, 0x58, 0x2c, 0x37, 0x21, 0x23, 0xd7, 0x8a, 0x35, 0x2a, 0xf1, 0xb6, - 0x05, 0x7b, 0x15, 0xff, 0xb0, 0xa2, 0x89, 0xfe, 0xa6, 0x05, 0xa3, 0xad, 0xb4, 0x99, 0x50, 0x88, - 0xc3, 0xe2, 0x78, 0x40, 0xc6, 0x0c, 0xc9, 0xad, 0x2d, 0x99, 0x42, 0x9c, 0xed, 0x05, 0xe5, 0x80, - 0x7a, 0x05, 0x2f, 0xb7, 0xb8, 0xc9, 0x72, 0x40, 0x73, 0xc0, 0xf9, 0x2c, 0x10, 0x77, 0xe2, 0xa3, - 0x15, 0x38, 0x45, 0x7b, 0xb7, 0xc3, 0xd5, 0x4f, 0x29, 0x5e, 0x62, 0x26, 0x0c, 0xab, 0x33, 0x8f, - 0x88, 0x15, 0xc2, 0xee, 0x3a, 0xb2, 0x38, 0x38, 0xb7, 0x26, 0xfa, 0x23, 0x0b, 0x1e, 0xf1, 0x98, - 0x18, 0x30, 0x0d, 0xf6, 0x5a, 0x22, 0x88, 0x8b, 0x76, 0x52, 0x28, 0xaf, 0xe8, 0x26, 0x7e, 0x66, - 0x7e, 0x5c, 0x7c, 0xc1, 0x23, 0x0b, 0x7b, 0x74, 0x09, 0xef, 0xd9, 0x61, 0xf4, 0x53, 0x30, 0x2c, - 0xf7, 0xc5, 0x0a, 0x65, 0xc1, 0x4c, 0xd0, 0xd6, 0x66, 0xc6, 0xee, 0xec, 0x4e, 0x0c, 0xaf, 0x99, - 0x00, 0x9c, 0xc6, 0xb3, 0xff, 0x4d, 0x39, 0x75, 0x4b, 0xa4, 0x6c, 0x98, 0x8c, 0xdd, 0xb8, 0xd2, - 0xfe, 0x23, 0xb9, 0x67, 0xa1, 0xec, 0x46, 0x59, 0x97, 0x34, 0xbb, 0x51, 0x45, 0x31, 0x36, 0x88, - 0x53, 0xa5, 0x74, 0xcc, 0xc9, 0x5a, 0x4a, 0x05, 0x07, 0x7c, 0xb9, 0xc8, 0x2e, 0x75, 0xde, 0xe9, - 0x9d, 0x11, 0x5d, 0x1b, 0xeb, 0x00, 0xe1, 0xce, 0x2e, 0xa1, 0x8f, 0x42, 0x2d, 0x52, 0x9e, 0x2d, - 0xe5, 0x22, 0x8e, 0x6a, 0x72, 0xd9, 0x88, 0xee, 0xa8, 0x0b, 0x20, 0xed, 0xc3, 0xa2, 0x29, 0xda, - 0x7f, 0x98, 0xbe, 0x18, 0x33, 0x78, 0x47, 0x0f, 0x97, 0x7e, 0x5f, 0xb0, 0x60, 0x30, 0x0a, 0x7d, - 0xdf, 0x0b, 0x1a, 0x94, 0xcf, 0x09, 0x61, 0xfd, 0xc1, 0x23, 0x91, 0x97, 0x82, 0xa1, 0x31, 0xcd, - 0x1a, 0x6b, 0x9a, 0xd8, 0xec, 0x80, 0xfd, 0x67, 0x16, 0x8c, 0x77, 0xe3, 0xc7, 0x88, 0xc0, 0x5b, - 0x25, 0xb3, 0x51, 0x43, 0xb1, 0x1c, 0xcc, 0x11, 0x9f, 0x28, 0xb3, 0x79, 0x75, 0xe6, 0x71, 0xf1, - 0x99, 0x6f, 0x5d, 0xe9, 0x8e, 0x8a, 0xf7, 0x6a, 0x07, 0xbd, 0x04, 0x27, 0x8c, 0xef, 0x8a, 0xd5, - 0xc0, 0xd4, 0x66, 0x26, 0xa9, 0x02, 0x34, 0x9d, 0x81, 0xdd, 0xdd, 0x9d, 0x78, 0x28, 0x5b, 0x26, - 0x04, 0x46, 0x47, 0x3b, 0xf6, 0x6f, 0x94, 0xb2, 0xb3, 0xa5, 0x64, 0xfd, 0x1b, 0x56, 0x87, 0x35, - 0xe1, 0xfd, 0x47, 0x21, 0x5f, 0x99, 0xdd, 0x41, 0xb9, 0x61, 0x74, 0xc7, 0xb9, 0x8f, 0xd7, 0xf6, - 0xf6, 0xbf, 0xed, 0x83, 0x3d, 0x7a, 0xd6, 0x83, 0xf2, 0x7e, 0xe0, 0x7b, 0xd4, 0xcf, 0x59, 0xea, - 0xc2, 0x8c, 0xef, 0xe1, 0xfa, 0x51, 0x8d, 0x3d, 0x3f, 0x3f, 0xc5, 0xdc, 0x75, 0x44, 0x59, 0xd1, - 0xd3, 0x57, 0x73, 0xe8, 0x6b, 0x56, 0xfa, 0xca, 0x8f, 0x3b, 0x35, 0x7a, 0x47, 0xd6, 0x27, 0xe3, - 0x1e, 0x91, 0x77, 0x4c, 0xdf, 0x3e, 0x75, 0xbb, 0x61, 0x9c, 0x04, 0xd8, 0xf0, 0x02, 0xc7, 0xf7, - 0x5e, 0xa3, 0xa7, 0xa3, 0x0a, 0x13, 0xf0, 0x4c, 0x63, 0xba, 0xa8, 0x4a, 0xb1, 0x81, 0x71, 0xf6, - 0xaf, 0xc2, 0xa0, 0xf1, 0xe5, 0x39, 0x1e, 0x2f, 0xa7, 0x4c, 0x8f, 0x97, 0x9a, 0xe1, 0xa8, 0x72, - 0xf6, 0xbd, 0x70, 0x22, 0xdb, 0xc1, 0x83, 0xd4, 0xb7, 0xff, 0xf7, 0x40, 0xf6, 0x0e, 0x6e, 0x8d, - 0x44, 0x4d, 0xda, 0xb5, 0x37, 0x0d, 0x5b, 0x6f, 0x1a, 0xb6, 0xde, 0x34, 0x6c, 0x99, 0x77, 0x13, - 0xc2, 0x68, 0x33, 0x70, 0x4c, 0x46, 0x9b, 0x94, 0x19, 0xaa, 0x5a, 0xb8, 0x19, 0xca, 0xfe, 0x74, - 0x87, 0xe5, 0x7e, 0x2d, 0x22, 0x04, 0x85, 0x50, 0x09, 0xc2, 0x3a, 0x91, 0x3a, 0xee, 0xe5, 0x62, - 0x14, 0xb6, 0xab, 0x61, 0xdd, 0x70, 0x17, 0xa7, 0xff, 0x62, 0xcc, 0xe9, 0xd8, 0x77, 0x2a, 0x90, - 0x52, 0x27, 0xf9, 0xbc, 0xbf, 0x1d, 0x06, 0x22, 0xd2, 0x0a, 0xaf, 0xe1, 0x45, 0x21, 0xcb, 0x74, - 0x44, 0x09, 0x2f, 0xc6, 0x12, 0x4e, 0x65, 0x5e, 0xcb, 0x49, 0x36, 0x85, 0x30, 0x53, 0x32, 0x6f, - 0xc5, 0x49, 0x36, 0x31, 0x83, 0xa0, 0xf7, 0xc2, 0x48, 0x92, 0xba, 0x0a, 0x17, 0x57, 0xbe, 0x0f, - 0x09, 0xdc, 0x91, 0xf4, 0x45, 0x39, 0xce, 0x60, 0xa3, 0x57, 0xa1, 0x6f, 0x93, 0xf8, 0x4d, 0x31, - 0xf5, 0xab, 0xc5, 0xc9, 0x1a, 0xf6, 0xad, 0x97, 0x88, 0xdf, 0xe4, 0x9c, 0x90, 0xfe, 0xc2, 0x8c, - 0x14, 0x5d, 0xf7, 0xb5, 0xad, 0x76, 0x9c, 0x84, 0x4d, 0xef, 0x35, 0x69, 0xe9, 0x7c, 0x7f, 0xc1, - 0x84, 0xaf, 0xc8, 0xf6, 0xb9, 0x49, 0x49, 0xfd, 0xc5, 0x9a, 0x32, 0xeb, 0x47, 0xdd, 0x8b, 0xd8, - 0x92, 0xd9, 0x11, 0x06, 0xcb, 0xa2, 0xfb, 0x31, 0x27, 0xdb, 0xe7, 0xfd, 0x50, 0x7f, 0xb1, 0xa6, - 0x8c, 0x76, 0xd4, 0xfe, 0x1b, 0x64, 0x7d, 0xb8, 0x56, 0x70, 0x1f, 0xf8, 0xde, 0xcb, 0xdd, 0x87, - 0x8f, 0x43, 0xc5, 0xdd, 0x74, 0xa2, 0x64, 0x7c, 0x88, 0x2d, 0x1a, 0xb5, 0x8a, 0x67, 0x69, 0x21, - 0xe6, 0x30, 0xf4, 0x28, 0x94, 0x23, 0xb2, 0xc1, 0xbc, 0x93, 0x0d, 0xbf, 0x28, 0x4c, 0x36, 0x30, - 0x2d, 0xb7, 0x7f, 0xad, 0x94, 0x56, 0xdb, 0xd2, 0xdf, 0xcd, 0x57, 0xbb, 0xdb, 0x8e, 0x62, 0x69, - 0xfe, 0x32, 0x56, 0x3b, 0x2b, 0xc6, 0x12, 0x8e, 0x3e, 0x61, 0xc1, 0xc0, 0xcd, 0x38, 0x0c, 0x02, - 0x92, 0x08, 0x11, 0x79, 0xbd, 0xe0, 0xa1, 0xb8, 0xcc, 0x5b, 0xd7, 0x7d, 0x10, 0x05, 0x58, 0xd2, - 0xa5, 0xdd, 0x25, 0xb7, 0x5d, 0xbf, 0x5d, 0xef, 0x70, 0x75, 0xb9, 0xc0, 0x8b, 0xb1, 0x84, 0x53, - 0x54, 0x2f, 0xe0, 0xa8, 0x7d, 0x69, 0xd4, 0x85, 0x40, 0xa0, 0x0a, 0xb8, 0xfd, 0xcd, 0x01, 0x38, - 0x9d, 0xbb, 0x39, 0xa8, 0x42, 0xc5, 0x54, 0x96, 0x8b, 0x9e, 0x4f, 0xa4, 0x93, 0x17, 0x53, 0xa8, - 0xae, 0xab, 0x52, 0x6c, 0x60, 0xa0, 0x9f, 0x07, 0x68, 0x39, 0x91, 0xd3, 0x24, 0xca, 0x3c, 0x7d, - 0x68, 0xbd, 0x85, 0xf6, 0x63, 0x45, 0xb6, 0xa9, 0x8f, 0xe8, 0xaa, 0x28, 0xc6, 0x06, 0x49, 0xf4, - 0x1c, 0x0c, 0x46, 0xc4, 0x27, 0x4e, 0xcc, 0x9c, 0xdb, 0xb3, 0x91, 0x3a, 0x58, 0x83, 0xb0, 0x89, - 0x87, 0x9e, 0x50, 0xfe, 0x70, 0x19, 0xbf, 0xa0, 0xb4, 0x4f, 0x1c, 0x7a, 0xdd, 0x82, 0x91, 0x0d, - 0xcf, 0x27, 0x9a, 0xba, 0x88, 0xab, 0x59, 0x3e, 0xfc, 0x47, 0x5e, 0x34, 0xdb, 0xd5, 0x1c, 0x32, - 0x55, 0x1c, 0xe3, 0x0c, 0x79, 0x3a, 0xcd, 0xdb, 0x24, 0x62, 0xac, 0xb5, 0x3f, 0x3d, 0xcd, 0xd7, - 0x79, 0x31, 0x96, 0x70, 0x34, 0x0d, 0xa3, 0x2d, 0x27, 0x8e, 0x67, 0x23, 0x52, 0x27, 0x41, 0xe2, - 0x39, 0x3e, 0x8f, 0x7a, 0xa9, 0x6a, 0x67, 0xf1, 0x95, 0x34, 0x18, 0x67, 0xf1, 0xd1, 0x07, 0xe0, - 0x61, 0x6e, 0xff, 0x59, 0xf2, 0xe2, 0xd8, 0x0b, 0x1a, 0x7a, 0x19, 0x08, 0x33, 0xd8, 0x84, 0x68, - 0xea, 0xe1, 0x85, 0x7c, 0x34, 0xdc, 0xad, 0x3e, 0x7a, 0x0a, 0xaa, 0xf1, 0x96, 0xd7, 0x9a, 0x8d, - 0xea, 0x31, 0xbb, 0xfb, 0xa9, 0x6a, 0xa3, 0xeb, 0xaa, 0x28, 0xc7, 0x0a, 0x03, 0xb9, 0x30, 0xc4, - 0xa7, 0x84, 0x3b, 0xf4, 0x09, 0xfe, 0xf8, 0x74, 0x57, 0x31, 0x2d, 0x82, 0x38, 0x27, 0xb1, 0x73, - 0xeb, 0x82, 0xbc, 0x89, 0xe2, 0x17, 0x27, 0xd7, 0x8d, 0x66, 0x70, 0xaa, 0xd1, 0xf4, 0x89, 0x6d, - 0xb0, 0x87, 0x13, 0xdb, 0x73, 0x30, 0xb8, 0xd5, 0x5e, 0x27, 0x62, 0xe4, 0x05, 0xdb, 0x52, 0xab, - 0xef, 0x8a, 0x06, 0x61, 0x13, 0x8f, 0xf9, 0x52, 0xb6, 0x3c, 0xf1, 0x2f, 0x1e, 0x1f, 0x36, 0x7c, - 0x29, 0x57, 0x16, 0x64, 0x31, 0x36, 0x71, 0xec, 0x5f, 0x29, 0xa5, 0x8d, 0x12, 0x26, 0xff, 0x40, - 0x31, 0xe5, 0x12, 0xc9, 0x75, 0x27, 0x92, 0xba, 0xc4, 0x21, 0xe3, 0x86, 0x44, 0xbb, 0xd7, 0x9d, - 0xc8, 0xe4, 0x37, 0x8c, 0x00, 0x96, 0x94, 0xd0, 0x4d, 0xe8, 0x4b, 0x7c, 0xa7, 0xa0, 0x40, 0x43, - 0x83, 0xa2, 0xb6, 0x11, 0x2d, 0x4e, 0xc7, 0x98, 0xd1, 0x40, 0x8f, 0xd0, 0x83, 0xd1, 0xba, 0xbc, - 0xc4, 0x12, 0x67, 0x99, 0xf5, 0x18, 0xb3, 0x52, 0xfb, 0xcf, 0x07, 0x73, 0x58, 0xbe, 0x92, 0xb1, - 0xe8, 0x3c, 0x00, 0x9d, 0xb1, 0x95, 0x88, 0x6c, 0x78, 0xb7, 0x85, 0x8e, 0xa3, 0xd8, 0xca, 0x55, - 0x05, 0xc1, 0x06, 0x96, 0xac, 0xb3, 0xda, 0xde, 0xa0, 0x75, 0x4a, 0x9d, 0x75, 0x38, 0x04, 0x1b, - 0x58, 0xe8, 0x59, 0xe8, 0xf7, 0x9a, 0x4e, 0x43, 0xf9, 0xd8, 0x3e, 0x42, 0xf9, 0xc9, 0x02, 0x2b, - 0xb9, 0xbb, 0x3b, 0x31, 0xa2, 0x3a, 0xc4, 0x8a, 0xb0, 0xc0, 0x45, 0xbf, 0x61, 0xc1, 0x90, 0x1b, - 0x36, 0x9b, 0x61, 0xc0, 0x4f, 0xa6, 0xe2, 0x98, 0x7d, 0xf3, 0xa8, 0x34, 0x90, 0xc9, 0x59, 0x83, - 0x18, 0x3f, 0x67, 0xab, 0x88, 0x48, 0x13, 0x84, 0x53, 0xbd, 0x32, 0xd9, 0x4e, 0x65, 0x1f, 0xb6, - 0xf3, 0x9b, 0x16, 0x8c, 0xf1, 0xba, 0xc6, 0x81, 0x59, 0x04, 0xff, 0x85, 0x47, 0xfc, 0x59, 0x1d, - 0x36, 0x04, 0x65, 0x47, 0xed, 0x80, 0xe3, 0xce, 0x4e, 0xa2, 0x79, 0x18, 0xdb, 0x08, 0x23, 0x97, - 0x98, 0x03, 0x21, 0x78, 0xa6, 0x6a, 0xe8, 0x62, 0x16, 0x01, 0x77, 0xd6, 0x41, 0xd7, 0xe1, 0x21, - 0xa3, 0xd0, 0x1c, 0x07, 0xce, 0x36, 0x1f, 0x13, 0xad, 0x3d, 0x74, 0x31, 0x17, 0x0b, 0x77, 0xa9, - 0x9d, 0xe6, 0x50, 0xb5, 0x1e, 0x38, 0xd4, 0x2b, 0x70, 0xc6, 0xed, 0x1c, 0x99, 0xed, 0xb8, 0xbd, - 0x1e, 0x73, 0x26, 0x5a, 0x9d, 0xf9, 0x31, 0xd1, 0xc0, 0x99, 0xd9, 0x6e, 0x88, 0xb8, 0x7b, 0x1b, - 0xe8, 0x23, 0x50, 0x8d, 0x08, 0x9b, 0x95, 0x58, 0x44, 0xc2, 0x1d, 0xd2, 0x90, 0xa0, 0x95, 0x63, - 0xde, 0xac, 0x16, 0x0b, 0xa2, 0x20, 0xc6, 0x8a, 0x22, 0xba, 0x05, 0x03, 0x2d, 0x27, 0x71, 0x37, - 0x45, 0xfc, 0xdb, 0xa1, 0xcd, 0xde, 0x8a, 0x38, 0xbb, 0xa5, 0x30, 0x22, 0xe6, 0x39, 0x11, 0x2c, - 0xa9, 0x51, 0x45, 0xc9, 0x0d, 0x9b, 0xad, 0x30, 0x20, 0x41, 0x22, 0x39, 0xf8, 0x08, 0xbf, 0x4a, - 0x90, 0xa5, 0xd8, 0xc0, 0x40, 0x2b, 0x70, 0x8a, 0x99, 0xd5, 0x6e, 0x78, 0xc9, 0x66, 0xd8, 0x4e, - 0xe4, 0x29, 0x71, 0x7c, 0x24, 0x7d, 0x99, 0xb4, 0x98, 0x83, 0x83, 0x73, 0x6b, 0x66, 0x65, 0xcf, - 0xe8, 0xbd, 0xc9, 0x9e, 0x13, 0xfb, 0xcb, 0x9e, 0xb3, 0xef, 0x83, 0xb1, 0x0e, 0xa6, 0x71, 0x20, - 0xdb, 0xd9, 0x1c, 0x3c, 0x94, 0xbf, 0x3d, 0x0f, 0x64, 0x41, 0xfb, 0xa7, 0x19, 0x17, 0x6a, 0xe3, - 0x34, 0xd1, 0x83, 0x35, 0xd6, 0x81, 0x32, 0x09, 0xb6, 0x85, 0xb4, 0xba, 0x78, 0xb8, 0x55, 0x72, - 0x21, 0xd8, 0xe6, 0xdc, 0x85, 0x99, 0x9c, 0x2e, 0x04, 0xdb, 0x98, 0xb6, 0x8d, 0xbe, 0x64, 0xa5, - 0xb4, 0x61, 0x6e, 0xc3, 0xfd, 0xd0, 0x91, 0x1c, 0x9f, 0x7a, 0x56, 0x90, 0xed, 0x7f, 0x57, 0x82, - 0x73, 0xfb, 0x35, 0xd2, 0xc3, 0xf0, 0x3d, 0x0e, 0xfd, 0x31, 0x73, 0x8a, 0x10, 0xec, 0x7f, 0x90, - 0xee, 0x0a, 0xee, 0x26, 0xf1, 0x0a, 0x16, 0x20, 0xe4, 0x43, 0xb9, 0xe9, 0xb4, 0x84, 0x69, 0x6f, - 0xe1, 0xb0, 0xa1, 0x66, 0xf4, 0xbf, 0xe3, 0x2f, 0x39, 0x2d, 0xbe, 0x3c, 0x8d, 0x02, 0x4c, 0xc9, - 0xa0, 0x04, 0x2a, 0x4e, 0x14, 0x39, 0xf2, 0x06, 0xfe, 0x4a, 0x31, 0xf4, 0xa6, 0x69, 0x93, 0xfc, - 0x02, 0x33, 0x55, 0x84, 0x39, 0x31, 0xfb, 0x73, 0x03, 0xa9, 0xb8, 0x24, 0xe6, 0x56, 0x11, 0x43, - 0xbf, 0xb0, 0xe8, 0x59, 0x45, 0x47, 0xf8, 0xf1, 0xc0, 0x5f, 0x76, 0x58, 0x16, 0xe9, 0x13, 0x04, - 0x29, 0xf4, 0x59, 0x8b, 0x25, 0x29, 0x90, 0xc1, 0x5e, 0xe2, 0x88, 0x7a, 0x34, 0x39, 0x13, 0xcc, - 0xd4, 0x07, 0xb2, 0x10, 0x9b, 0xd4, 0x45, 0xb2, 0x11, 0xa6, 0x9a, 0x77, 0x26, 0x1b, 0x61, 0xaa, - 0xb6, 0x84, 0xa3, 0xdb, 0x39, 0xee, 0x13, 0x05, 0x04, 0xba, 0xf7, 0xe0, 0x30, 0xf1, 0x35, 0x0b, - 0xc6, 0xbc, 0xec, 0x3d, 0xb8, 0x38, 0xd0, 0xdd, 0x28, 0xc6, 0xfc, 0xd6, 0x79, 0xcd, 0xae, 0x14, - 0x87, 0x0e, 0x10, 0xee, 0xec, 0x0c, 0xaa, 0x43, 0x9f, 0x17, 0x6c, 0x84, 0x42, 0x5d, 0x9a, 0x39, - 0x5c, 0xa7, 0x16, 0x82, 0x8d, 0x50, 0xef, 0x66, 0xfa, 0x0f, 0xb3, 0xd6, 0xd1, 0x22, 0x9c, 0x92, - 0xa1, 0x29, 0x97, 0xbc, 0x38, 0x09, 0xa3, 0x9d, 0x45, 0xaf, 0xe9, 0x25, 0x4c, 0xd5, 0x29, 0xcf, - 0x8c, 0x53, 0x49, 0x84, 0x73, 0xe0, 0x38, 0xb7, 0x16, 0x7a, 0x0d, 0x06, 0xe4, 0xdd, 0x73, 0xb5, - 0x88, 0xc3, 0x71, 0xe7, 0xfa, 0x57, 0x8b, 0x69, 0x55, 0x5c, 0x3e, 0x4b, 0x82, 0xf6, 0xeb, 0x83, - 0xd0, 0x79, 0x45, 0x9e, 0xbe, 0x0f, 0xb7, 0x8e, 0xfb, 0x3e, 0x9c, 0x1e, 0x8d, 0x62, 0x7d, 0x95, - 0x5d, 0xc0, 0xda, 0x16, 0x54, 0xf5, 0x35, 0xe5, 0x4e, 0xe0, 0x62, 0x46, 0x03, 0x45, 0xd0, 0xbf, - 0x49, 0x1c, 0x3f, 0xd9, 0x2c, 0xe6, 0x46, 0xe5, 0x12, 0x6b, 0x2b, 0x1b, 0x4f, 0xc6, 0x4b, 0xb1, - 0xa0, 0x84, 0x6e, 0xc3, 0xc0, 0x26, 0x5f, 0x00, 0xe2, 0xb4, 0xb2, 0x74, 0xd8, 0xc1, 0x4d, 0xad, - 0x2a, 0x3d, 0xdd, 0xa2, 0x00, 0x4b, 0x72, 0xcc, 0xf7, 0xca, 0xf0, 0x0e, 0xe1, 0x5b, 0xb7, 0xb8, - 0x50, 0xba, 0xde, 0x5d, 0x43, 0x3e, 0x0c, 0x43, 0x11, 0x71, 0xc3, 0xc0, 0xf5, 0x7c, 0x52, 0x9f, - 0x96, 0xb7, 0x25, 0x07, 0x89, 0xa0, 0x62, 0xc6, 0x08, 0x6c, 0xb4, 0x81, 0x53, 0x2d, 0xa2, 0xcf, - 0x58, 0x30, 0xa2, 0xa2, 0xaa, 0xe9, 0x84, 0x10, 0x61, 0x15, 0x5f, 0x2c, 0x28, 0x86, 0x9b, 0xb5, - 0x39, 0x83, 0xee, 0xec, 0x4e, 0x8c, 0xa4, 0xcb, 0x70, 0x86, 0x2e, 0x7a, 0x09, 0x20, 0x5c, 0xe7, - 0x0e, 0x56, 0xd3, 0x89, 0x30, 0x91, 0x1f, 0xe4, 0x53, 0x47, 0x78, 0x24, 0xa6, 0x6c, 0x01, 0x1b, - 0xad, 0xa1, 0x2b, 0x00, 0x7c, 0xdb, 0xac, 0xed, 0xb4, 0xe4, 0x91, 0x46, 0x86, 0xc0, 0xc1, 0xaa, - 0x82, 0xdc, 0xdd, 0x9d, 0xe8, 0x34, 0x59, 0x32, 0x2f, 0x12, 0xa3, 0x3a, 0xfa, 0x39, 0x18, 0x88, - 0xdb, 0xcd, 0xa6, 0xa3, 0x0c, 0xe8, 0x05, 0xc6, 0x76, 0xf2, 0x76, 0x0d, 0x56, 0xc4, 0x0b, 0xb0, - 0xa4, 0x88, 0x6e, 0x52, 0xa6, 0x1a, 0x0b, 0x5b, 0x2a, 0xdb, 0x45, 0x5c, 0x27, 0xe0, 0x86, 0xa4, - 0x77, 0x49, 0x15, 0x1f, 0xe7, 0xe0, 0xdc, 0xdd, 0x9d, 0x78, 0x28, 0x5d, 0xbe, 0x18, 0x8a, 0x68, - 0xcb, 0xdc, 0x36, 0xd1, 0x65, 0x99, 0x64, 0x89, 0x7e, 0xb6, 0xcc, 0xfd, 0xf1, 0xa4, 0x4e, 0xb2, - 0xc4, 0x8a, 0xbb, 0x8f, 0x99, 0x59, 0x19, 0x2d, 0xc1, 0x49, 0x37, 0x0c, 0x92, 0x28, 0xf4, 0x7d, - 0x9e, 0x64, 0x8c, 0x9f, 0x2e, 0xb9, 0x81, 0xfd, 0xad, 0xa2, 0xdb, 0x27, 0x67, 0x3b, 0x51, 0x70, - 0x5e, 0x3d, 0x3b, 0x48, 0x5f, 0x76, 0x89, 0xc1, 0x79, 0x16, 0x86, 0xc8, 0xed, 0x84, 0x44, 0x81, - 0xe3, 0x5f, 0xc3, 0x8b, 0xd2, 0xb4, 0xcc, 0xf6, 0xc0, 0x05, 0xa3, 0x1c, 0xa7, 0xb0, 0x90, 0xad, - 0x4c, 0x2a, 0x46, 0x04, 0x31, 0x37, 0xa9, 0x48, 0x03, 0x8a, 0xfd, 0xcd, 0x72, 0x4a, 0x21, 0xbb, - 0x2f, 0x57, 0x6b, 0x2c, 0x55, 0x8d, 0xcc, 0xe9, 0xc3, 0x00, 0xe2, 0xa0, 0x51, 0x24, 0x65, 0x95, - 0xaa, 0x66, 0xd9, 0x24, 0x84, 0xd3, 0x74, 0xd1, 0x16, 0x54, 0x36, 0xc3, 0x38, 0x91, 0xc7, 0x8f, - 0x43, 0x9e, 0x74, 0x2e, 0x85, 0x71, 0xc2, 0xb4, 0x08, 0xf5, 0xd9, 0xb4, 0x24, 0xc6, 0x9c, 0x06, - 0x3d, 0x83, 0xc6, 0x9b, 0x4e, 0x54, 0x8f, 0x67, 0x59, 0xbc, 0x7f, 0x1f, 0x53, 0x1f, 0x94, 0xb2, - 0xb8, 0xaa, 0x41, 0xd8, 0xc4, 0xb3, 0xff, 0xab, 0x95, 0xba, 0x7f, 0xb8, 0xc1, 0x9c, 0xb7, 0xb7, - 0x49, 0x40, 0xb9, 0x81, 0xe9, 0x2e, 0xf6, 0x53, 0x99, 0x50, 0xd8, 0xb7, 0x75, 0x4b, 0xbd, 0x77, - 0x8b, 0xb6, 0x30, 0xc9, 0x9a, 0x30, 0x3c, 0xcb, 0x3e, 0x6e, 0xa5, 0x63, 0x9a, 0x4b, 0x45, 0x9c, - 0x4b, 0xcc, 0xb8, 0xfe, 0x7d, 0xc3, 0xa3, 0xed, 0x2f, 0x59, 0x30, 0x30, 0xe3, 0xb8, 0x5b, 0xe1, - 0xc6, 0x06, 0x7a, 0x0a, 0xaa, 0xf5, 0x76, 0x64, 0x86, 0x57, 0x2b, 0xcb, 0xc6, 0x9c, 0x28, 0xc7, - 0x0a, 0x83, 0x2e, 0xfd, 0x0d, 0xc7, 0x95, 0xd1, 0xfd, 0x65, 0xbe, 0xf4, 0x2f, 0xb2, 0x12, 0x2c, - 0x20, 0x74, 0xf8, 0x9b, 0xce, 0x6d, 0x59, 0x39, 0x7b, 0xf9, 0xb1, 0xa4, 0x41, 0xd8, 0xc4, 0xb3, - 0xff, 0x95, 0x05, 0xe3, 0x33, 0x4e, 0xec, 0xb9, 0xd3, 0xed, 0x64, 0x73, 0xc6, 0x4b, 0xd6, 0xdb, - 0xee, 0x16, 0x49, 0x78, 0x16, 0x08, 0xda, 0xcb, 0x76, 0x4c, 0x77, 0xa0, 0x3a, 0x0e, 0xaa, 0x5e, - 0x5e, 0x13, 0xe5, 0x58, 0x61, 0xa0, 0xd7, 0x60, 0xb0, 0xe5, 0xc4, 0xf1, 0xad, 0x30, 0xaa, 0x63, - 0xb2, 0x51, 0x4c, 0x9e, 0x98, 0x55, 0xe2, 0x46, 0x24, 0xc1, 0x64, 0x43, 0x38, 0x0a, 0xe8, 0xf6, - 0xb1, 0x49, 0xcc, 0xfe, 0x65, 0x0b, 0x4e, 0xcd, 0x10, 0x27, 0x22, 0x11, 0x4b, 0x2b, 0xa3, 0x3e, - 0x04, 0xbd, 0x0a, 0xd5, 0x84, 0x96, 0xd0, 0x1e, 0x59, 0xc5, 0xf6, 0x88, 0x5d, 0xf1, 0xaf, 0x89, - 0xc6, 0xb1, 0x22, 0x63, 0x7f, 0xc1, 0x82, 0x33, 0x79, 0x7d, 0x99, 0xf5, 0xc3, 0x76, 0xfd, 0x7e, - 0x74, 0xe8, 0x6f, 0x59, 0x30, 0xc4, 0xae, 0x4d, 0xe7, 0x48, 0xe2, 0x78, 0x7e, 0x47, 0x4a, 0x3b, - 0xab, 0xc7, 0x94, 0x76, 0xe7, 0xa0, 0x6f, 0x33, 0x6c, 0x92, 0xec, 0x95, 0xff, 0xa5, 0xb0, 0x49, - 0x30, 0x83, 0xa0, 0x67, 0xe8, 0x22, 0xf4, 0x82, 0xc4, 0xa1, 0xdb, 0x51, 0xda, 0xbe, 0x47, 0xf9, - 0x02, 0x54, 0xc5, 0xd8, 0xc4, 0xb1, 0xff, 0x65, 0x0d, 0x06, 0x84, 0x7f, 0x4a, 0xcf, 0x59, 0x49, - 0xa4, 0x89, 0xa2, 0xd4, 0xd5, 0x44, 0x11, 0x43, 0xbf, 0xcb, 0x72, 0x6b, 0x0a, 0x4d, 0xf8, 0x4a, - 0x21, 0x0e, 0x4d, 0x3c, 0x5d, 0xa7, 0xee, 0x16, 0xff, 0x8f, 0x05, 0x29, 0xf4, 0x45, 0x0b, 0x46, - 0xdd, 0x30, 0x08, 0x88, 0xab, 0xd5, 0xb4, 0xbe, 0x22, 0xfc, 0x56, 0x66, 0xd3, 0x8d, 0xea, 0x3b, - 0xbb, 0x0c, 0x00, 0x67, 0xc9, 0xa3, 0x17, 0x60, 0x98, 0x8f, 0xd9, 0xf5, 0x94, 0xc1, 0x5e, 0x67, - 0x3a, 0x33, 0x81, 0x38, 0x8d, 0x8b, 0x26, 0xf9, 0xc5, 0x87, 0xc8, 0x29, 0xd6, 0xaf, 0xed, 0x9a, - 0x46, 0x36, 0x31, 0x03, 0x03, 0x45, 0x80, 0x22, 0xb2, 0x11, 0x91, 0x78, 0x53, 0xf8, 0xef, 0x30, - 0x15, 0x71, 0xe0, 0xde, 0xf2, 0x09, 0xe0, 0x8e, 0x96, 0x70, 0x4e, 0xeb, 0x68, 0x4b, 0x9c, 0x91, - 0xab, 0x45, 0xf0, 0x73, 0x31, 0xcd, 0x5d, 0x8f, 0xca, 0x13, 0x50, 0x61, 0xa2, 0x8b, 0xa9, 0xa6, - 0x65, 0x1e, 0xc3, 0xc6, 0x04, 0x1b, 0xe6, 0xe5, 0x68, 0x0e, 0x4e, 0x64, 0xf2, 0xb4, 0xc5, 0xc2, - 0xb0, 0xae, 0xe2, 0x95, 0x32, 0x19, 0xde, 0x62, 0xdc, 0x51, 0xc3, 0xb4, 0x9f, 0x0c, 0xee, 0x63, - 0x3f, 0xd9, 0x51, 0x5e, 0xa2, 0xdc, 0xe4, 0xfd, 0x62, 0x21, 0x03, 0xd0, 0x93, 0x4b, 0xe8, 0xe7, - 0x33, 0x2e, 0xa1, 0xc3, 0xac, 0x03, 0xd7, 0x8b, 0xe9, 0xc0, 0xc1, 0xfd, 0x3f, 0xef, 0xa7, 0x3f, - 0xe7, 0xff, 0xb2, 0x40, 0xce, 0xeb, 0xac, 0xe3, 0x6e, 0x12, 0xba, 0x64, 0xd0, 0x7b, 0x61, 0x44, - 0x59, 0x01, 0xb8, 0x4a, 0x64, 0xb1, 0x55, 0xa3, 0x2e, 0xf7, 0x71, 0x0a, 0x8a, 0x33, 0xd8, 0x68, - 0x0a, 0x6a, 0x74, 0x9c, 0x78, 0x55, 0x2e, 0xf7, 0x95, 0xa5, 0x61, 0x7a, 0x65, 0x41, 0xd4, 0xd2, - 0x38, 0x28, 0x84, 0x31, 0xdf, 0x89, 0x13, 0xd6, 0x83, 0xd5, 0x9d, 0xc0, 0xbd, 0xc7, 0x6c, 0x1e, - 0x2c, 0x28, 0x66, 0x31, 0xdb, 0x10, 0xee, 0x6c, 0xdb, 0xfe, 0x6e, 0x1f, 0x0c, 0xa7, 0x38, 0xe3, - 0x01, 0x15, 0x86, 0xa7, 0xa0, 0x2a, 0x65, 0x78, 0x36, 0x6d, 0x91, 0x12, 0xf4, 0x0a, 0x83, 0x0a, - 0xad, 0x75, 0x2d, 0x55, 0xb3, 0x0a, 0x8e, 0x21, 0x70, 0xb1, 0x89, 0xc7, 0x98, 0x72, 0xe2, 0xc7, - 0xb3, 0xbe, 0x47, 0x82, 0x84, 0x77, 0xb3, 0x18, 0xa6, 0xbc, 0xb6, 0xb8, 0x6a, 0x36, 0xaa, 0x99, - 0x72, 0x06, 0x80, 0xb3, 0xe4, 0xd1, 0xa7, 0x2c, 0x18, 0x76, 0x6e, 0xc5, 0x3a, 0x01, 0xb4, 0x70, - 0xfe, 0x3c, 0xa4, 0x90, 0x4a, 0xe5, 0x94, 0xe6, 0x56, 0xeb, 0x54, 0x11, 0x4e, 0x13, 0x45, 0x6f, - 0x58, 0x80, 0xc8, 0x6d, 0xe2, 0x4a, 0xf7, 0x54, 0xd1, 0x97, 0xfe, 0x22, 0x0e, 0xcb, 0x17, 0x3a, - 0xda, 0xe5, 0x5c, 0xbd, 0xb3, 0x1c, 0xe7, 0xf4, 0xc1, 0xfe, 0x17, 0x65, 0xb5, 0xa1, 0xb4, 0x47, - 0xb4, 0x63, 0x78, 0x66, 0x5a, 0xf7, 0xee, 0x99, 0xa9, 0x3d, 0x4b, 0x3a, 0x83, 0x84, 0x53, 0x31, - 0x85, 0xa5, 0xfb, 0x14, 0x53, 0xf8, 0x0b, 0x56, 0x2a, 0x41, 0xd7, 0xe0, 0xf9, 0x97, 0x8a, 0xf5, - 0xc6, 0x9e, 0xe4, 0x5e, 0x2f, 0x19, 0xee, 0x9e, 0x76, 0x76, 0xa2, 0xdc, 0xd4, 0x40, 0x3b, 0x10, - 0x37, 0xfc, 0x0f, 0x65, 0x18, 0x34, 0x24, 0x69, 0xae, 0x5a, 0x64, 0x3d, 0x60, 0x6a, 0x51, 0xe9, - 0x00, 0x6a, 0xd1, 0xcf, 0x43, 0xcd, 0x95, 0x5c, 0xbe, 0x98, 0x14, 0xe2, 0x59, 0xd9, 0xa1, 0x19, - 0xbd, 0x2a, 0xc2, 0x9a, 0x26, 0x9a, 0x4f, 0x45, 0xa2, 0xa5, 0xce, 0xdb, 0x79, 0xa1, 0x62, 0x42, - 0x52, 0x74, 0xd6, 0xc9, 0xde, 0xff, 0x56, 0x7a, 0xf0, 0x3d, 0xfa, 0xae, 0xa5, 0x26, 0xf7, 0x18, - 0x52, 0x8e, 0xdc, 0x4c, 0xa7, 0x1c, 0xb9, 0x50, 0xc8, 0x30, 0x77, 0xc9, 0x35, 0x72, 0x15, 0x06, - 0x66, 0xc3, 0x66, 0xd3, 0x09, 0xea, 0xe8, 0x27, 0x60, 0xc0, 0xe5, 0x3f, 0x85, 0x6d, 0x8a, 0xdd, - 0x70, 0x0a, 0x28, 0x96, 0x30, 0xf4, 0x08, 0xf4, 0x39, 0x51, 0x43, 0xda, 0xa3, 0x98, 0x27, 0xd2, - 0x74, 0xd4, 0x88, 0x31, 0x2b, 0xb5, 0xff, 0x49, 0x1f, 0x30, 0x07, 0x00, 0x27, 0x22, 0xf5, 0xb5, - 0x90, 0x65, 0xfe, 0x3c, 0xd2, 0x7b, 0x41, 0x7d, 0x58, 0x7a, 0x90, 0xef, 0x06, 0x8d, 0xfb, 0xa1, - 0xf2, 0x31, 0xdf, 0x0f, 0x75, 0xb9, 0xf2, 0xeb, 0x7b, 0x80, 0xae, 0xfc, 0xec, 0xcf, 0x59, 0x80, - 0x94, 0xd7, 0x88, 0xbe, 0x93, 0x9f, 0x82, 0x9a, 0xf2, 0x1f, 0x11, 0x8a, 0x95, 0x66, 0x11, 0x12, - 0x80, 0x35, 0x4e, 0x0f, 0x27, 0xe4, 0xc7, 0x25, 0xff, 0x2e, 0xa7, 0xfd, 0xab, 0x19, 0xd7, 0x17, - 0xec, 0xdc, 0xfe, 0xbd, 0x12, 0x3c, 0xc4, 0x45, 0xf2, 0x92, 0x13, 0x38, 0x0d, 0xd2, 0xa4, 0xbd, - 0xea, 0xd5, 0xcb, 0xc2, 0xa5, 0x47, 0x33, 0x4f, 0xfa, 0x4b, 0x1f, 0x76, 0xef, 0xf2, 0x3d, 0xc7, - 0x77, 0xd9, 0x42, 0xe0, 0x25, 0x98, 0x35, 0x8e, 0x62, 0xa8, 0xca, 0xf7, 0x35, 0x04, 0x2f, 0x2e, - 0x88, 0x90, 0x62, 0x4b, 0x42, 0x6e, 0x12, 0xac, 0x08, 0x51, 0xc5, 0xd5, 0x0f, 0xdd, 0x2d, 0x4c, - 0x5a, 0x21, 0xe3, 0xbb, 0x86, 0xbb, 0xea, 0xa2, 0x28, 0xc7, 0x0a, 0xc3, 0x6e, 0xc2, 0xa8, 0x1c, - 0xc3, 0xd6, 0x15, 0xb2, 0x83, 0xc9, 0x06, 0x95, 0x3f, 0xae, 0x2c, 0x32, 0x9e, 0xfc, 0x50, 0xf2, - 0x67, 0xd6, 0x04, 0xe2, 0x34, 0xae, 0x4c, 0x06, 0x5a, 0xca, 0x4f, 0x06, 0x6a, 0xff, 0x9e, 0x05, - 0x59, 0x01, 0x68, 0xa4, 0x3e, 0xb4, 0xf6, 0x4c, 0x7d, 0x78, 0x80, 0xe4, 0x81, 0x3f, 0x0b, 0x83, - 0x4e, 0x42, 0x75, 0x16, 0x7e, 0xca, 0x2f, 0xdf, 0xdb, 0x45, 0xd0, 0x52, 0x58, 0xf7, 0x36, 0x3c, - 0x76, 0xba, 0x37, 0x9b, 0xb3, 0xff, 0xb2, 0x0f, 0xc6, 0x3a, 0x82, 0x99, 0xd0, 0xf3, 0x30, 0xa4, - 0x86, 0x42, 0xda, 0xcf, 0x6a, 0xa6, 0xcb, 0xa2, 0x86, 0xe1, 0x14, 0x66, 0x0f, 0xfb, 0x61, 0x01, - 0x4e, 0x46, 0xe4, 0xd5, 0x36, 0x69, 0x93, 0xe9, 0x8d, 0x84, 0x44, 0xab, 0xc4, 0x0d, 0x83, 0x3a, - 0x4f, 0xd0, 0x59, 0x9e, 0x79, 0xf8, 0xce, 0xee, 0xc4, 0x49, 0xdc, 0x09, 0xc6, 0x79, 0x75, 0x50, - 0x0b, 0x86, 0x7d, 0x53, 0xe5, 0x14, 0xe7, 0x8d, 0x7b, 0xd2, 0x56, 0xd5, 0x92, 0x48, 0x15, 0xe3, - 0x34, 0x81, 0xb4, 0xde, 0x5a, 0xb9, 0x4f, 0x7a, 0xeb, 0x27, 0xb5, 0xde, 0xca, 0x3d, 0x16, 0x3e, - 0x58, 0x70, 0x30, 0xdb, 0x51, 0x2b, 0xae, 0x2f, 0x42, 0x55, 0x7a, 0x73, 0xf5, 0xe4, 0x05, 0x65, - 0xb6, 0xd3, 0x85, 0x81, 0x3e, 0x01, 0x3f, 0x7e, 0x21, 0x8a, 0x8c, 0xc1, 0xbc, 0x1a, 0x26, 0xd3, - 0xbe, 0x1f, 0xde, 0xa2, 0x3a, 0xc1, 0xb5, 0x98, 0x08, 0x83, 0x8e, 0x7d, 0xb7, 0x04, 0x39, 0x67, - 0x23, 0xba, 0x1f, 0xb5, 0x22, 0x92, 0xda, 0x8f, 0x07, 0x53, 0x46, 0xd0, 0x6d, 0xee, 0xf1, 0xc6, - 0x45, 0xee, 0x07, 0x8a, 0x3e, 0xdb, 0x69, 0x27, 0x38, 0xc5, 0x8e, 0x94, 0x23, 0xdc, 0x79, 0x00, - 0xad, 0x3f, 0x8a, 0x08, 0x0b, 0x75, 0xa1, 0xae, 0xd5, 0x4c, 0x6c, 0x60, 0xd1, 0xa3, 0xbe, 0x17, - 0xc4, 0x89, 0xe3, 0xfb, 0x97, 0xbc, 0x20, 0x11, 0x36, 0x4b, 0xa5, 0x5b, 0x2c, 0x68, 0x10, 0x36, - 0xf1, 0xce, 0xbe, 0xcb, 0x98, 0xbf, 0x83, 0xcc, 0xfb, 0x26, 0x9c, 0x99, 0xf7, 0x12, 0x15, 0x17, - 0xa4, 0xd6, 0x1b, 0x55, 0x0f, 0x55, 0x9c, 0x9b, 0xd5, 0x35, 0xce, 0xcd, 0x88, 0xcb, 0x29, 0xa5, - 0xc3, 0x88, 0xb2, 0x71, 0x39, 0xf6, 0xf3, 0x70, 0x6a, 0xde, 0x4b, 0x2e, 0x7a, 0x3e, 0x39, 0x20, - 0x11, 0xfb, 0x77, 0xfb, 0x61, 0xc8, 0x8c, 0x70, 0x3d, 0x48, 0xa8, 0xde, 0x17, 0xa8, 0x06, 0x28, - 0xbe, 0xce, 0x53, 0xd7, 0x91, 0x37, 0x0e, 0x1d, 0x6e, 0x9b, 0x3f, 0x62, 0x86, 0x12, 0xa8, 0x69, - 0x62, 0xb3, 0x03, 0xe8, 0x16, 0x54, 0x36, 0x58, 0xdc, 0x48, 0xb9, 0x08, 0x9f, 0x8d, 0xbc, 0x11, - 0xd5, 0xdb, 0x91, 0x47, 0x9e, 0x70, 0x7a, 0x54, 0x70, 0x47, 0xe9, 0x60, 0x44, 0xc3, 0xa1, 0x58, - 0x84, 0x21, 0x2a, 0x8c, 0x6e, 0x22, 0xa1, 0x72, 0x0f, 0x22, 0x21, 0xc5, 0xa0, 0xfb, 0xef, 0x13, - 0x83, 0x66, 0x31, 0x40, 0xc9, 0x26, 0x53, 0x2b, 0x45, 0x04, 0xc4, 0x00, 0x1b, 0x04, 0x23, 0x06, - 0x28, 0x05, 0xc6, 0x59, 0x7c, 0xf4, 0x31, 0xc5, 0xe2, 0xab, 0x45, 0x98, 0x7b, 0xcd, 0x15, 0x7d, - 0xd4, 0xdc, 0xfd, 0x73, 0x25, 0x18, 0x99, 0x0f, 0xda, 0x2b, 0xf3, 0x2b, 0xed, 0x75, 0xdf, 0x73, - 0xaf, 0x90, 0x1d, 0xca, 0xc2, 0xb7, 0xc8, 0xce, 0xc2, 0x9c, 0xd8, 0x41, 0x6a, 0xcd, 0x5c, 0xa1, - 0x85, 0x98, 0xc3, 0x28, 0x33, 0xda, 0xf0, 0x82, 0x06, 0x89, 0x5a, 0x91, 0x27, 0x2c, 0xb1, 0x06, - 0x33, 0xba, 0xa8, 0x41, 0xd8, 0xc4, 0xa3, 0x6d, 0x87, 0xb7, 0x02, 0x12, 0x65, 0xf5, 0xeb, 0x65, - 0x5a, 0x88, 0x39, 0x8c, 0x22, 0x25, 0x51, 0x3b, 0x4e, 0xc4, 0x62, 0x54, 0x48, 0x6b, 0xb4, 0x10, - 0x73, 0x18, 0xdd, 0xe9, 0x71, 0x7b, 0x9d, 0xb9, 0xc4, 0x64, 0xc2, 0x2d, 0x56, 0x79, 0x31, 0x96, - 0x70, 0x8a, 0xba, 0x45, 0x76, 0xe6, 0xe8, 0x61, 0x3c, 0x13, 0x10, 0x76, 0x85, 0x17, 0x63, 0x09, - 0x67, 0x29, 0x44, 0xd3, 0xc3, 0xf1, 0x43, 0x97, 0x42, 0x34, 0xdd, 0xfd, 0x2e, 0xc7, 0xfa, 0x5f, - 0xb7, 0x60, 0xc8, 0x74, 0x64, 0x43, 0x8d, 0x8c, 0x2e, 0xbc, 0xdc, 0x91, 0x81, 0xfa, 0x3d, 0x79, - 0xaf, 0x33, 0x36, 0xbc, 0x24, 0x6c, 0xc5, 0x4f, 0x93, 0xa0, 0xe1, 0x05, 0x84, 0x39, 0x1a, 0x70, - 0x07, 0xb8, 0x94, 0x97, 0xdc, 0x6c, 0x58, 0x27, 0xf7, 0xa0, 0x4c, 0xdb, 0x37, 0x60, 0xac, 0x23, - 0x0a, 0xb0, 0x07, 0x15, 0x64, 0xdf, 0x18, 0x6c, 0x1b, 0xc3, 0x20, 0x6d, 0x58, 0xa6, 0xb1, 0x9a, - 0x85, 0x31, 0xbe, 0x91, 0x28, 0xa5, 0x55, 0x77, 0x93, 0x34, 0x55, 0x64, 0x27, 0x33, 0xfb, 0x5f, - 0xcf, 0x02, 0x71, 0x27, 0xbe, 0xfd, 0x79, 0x0b, 0x86, 0x53, 0x81, 0x99, 0x05, 0x29, 0x4b, 0x6c, - 0xa7, 0x85, 0xcc, 0xaf, 0x92, 0x39, 0x97, 0x97, 0x99, 0x30, 0xd5, 0x3b, 0x4d, 0x83, 0xb0, 0x89, - 0x67, 0x7f, 0xa9, 0x04, 0x55, 0xe9, 0x9b, 0xd2, 0x43, 0x57, 0x3e, 0x6b, 0xc1, 0xb0, 0xba, 0x6a, - 0x61, 0x36, 0xbc, 0x52, 0x11, 0xa1, 0x2a, 0xb4, 0x07, 0xca, 0x0a, 0x10, 0x6c, 0x84, 0x5a, 0x73, - 0xc7, 0x26, 0x31, 0x9c, 0xa6, 0x8d, 0xae, 0x03, 0xc4, 0x3b, 0x71, 0x42, 0x9a, 0x86, 0x35, 0xd1, - 0x36, 0x76, 0xdc, 0xa4, 0x1b, 0x46, 0x84, 0xee, 0xaf, 0xab, 0x61, 0x9d, 0xac, 0x2a, 0x4c, 0xad, - 0x42, 0xe9, 0x32, 0x6c, 0xb4, 0x64, 0xff, 0xa3, 0x12, 0x9c, 0xc8, 0x76, 0x09, 0x7d, 0x10, 0x86, - 0x24, 0x75, 0xe3, 0xd4, 0x29, 0x3d, 0x6b, 0x86, 0xb0, 0x01, 0xbb, 0xbb, 0x3b, 0x31, 0xd1, 0xf9, - 0xd2, 0xe7, 0xa4, 0x89, 0x82, 0x53, 0x8d, 0xf1, 0xfb, 0x2e, 0x71, 0x31, 0x3b, 0xb3, 0x33, 0xdd, - 0x6a, 0x89, 0x4b, 0x2b, 0xe3, 0xbe, 0xcb, 0x84, 0xe2, 0x0c, 0x36, 0x5a, 0x81, 0x53, 0x46, 0xc9, - 0x55, 0xe2, 0x35, 0x36, 0xd7, 0xc3, 0x48, 0x9e, 0xc0, 0x1e, 0xd1, 0x2e, 0x73, 0x9d, 0x38, 0x38, - 0xb7, 0x26, 0x95, 0xf6, 0xae, 0xd3, 0x72, 0x5c, 0x2f, 0xd9, 0x11, 0xe6, 0x51, 0xc5, 0x9b, 0x66, - 0x45, 0x39, 0x56, 0x18, 0xf6, 0x12, 0xf4, 0xf5, 0xb8, 0x82, 0x7a, 0xd2, 0xfc, 0x5f, 0x84, 0x2a, - 0x6d, 0x4e, 0xaa, 0x77, 0x45, 0x34, 0x19, 0x42, 0x55, 0xbe, 0x9b, 0x84, 0x6c, 0x28, 0x7b, 0x8e, - 0xbc, 0x52, 0x54, 0x9f, 0xb5, 0x10, 0xc7, 0x6d, 0x76, 0x98, 0xa6, 0x40, 0xf4, 0x38, 0x94, 0xc9, - 0xed, 0x56, 0xf6, 0xee, 0xf0, 0xc2, 0xed, 0x96, 0x17, 0x91, 0x98, 0x22, 0x91, 0xdb, 0x2d, 0x74, - 0x16, 0x4a, 0x5e, 0x5d, 0x08, 0x29, 0x10, 0x38, 0xa5, 0x85, 0x39, 0x5c, 0xf2, 0xea, 0xf6, 0x6d, - 0xa8, 0xa9, 0x87, 0x9a, 0xd0, 0x96, 0xe4, 0xdd, 0x56, 0x11, 0xce, 0x64, 0xb2, 0xdd, 0x2e, 0x5c, - 0xbb, 0x0d, 0xa0, 0xc3, 0x40, 0x8b, 0xe2, 0x2f, 0xe7, 0xa0, 0xcf, 0x0d, 0x45, 0xf4, 0x7c, 0x55, - 0x37, 0xc3, 0x98, 0x36, 0x83, 0xd8, 0x37, 0x60, 0xe4, 0x4a, 0x10, 0xde, 0x62, 0xef, 0x29, 0xb0, - 0xf4, 0x81, 0xb4, 0xe1, 0x0d, 0xfa, 0x23, 0xab, 0x22, 0x30, 0x28, 0xe6, 0x30, 0x95, 0xd8, 0xac, - 0xd4, 0x2d, 0xb1, 0x99, 0xfd, 0x71, 0x0b, 0x86, 0x54, 0x3c, 0xd9, 0xfc, 0xf6, 0x16, 0x6d, 0xb7, - 0x11, 0x85, 0xed, 0x56, 0xb6, 0x5d, 0xf6, 0x26, 0x1c, 0xe6, 0x30, 0x33, 0xd0, 0xb2, 0xb4, 0x4f, - 0xa0, 0xe5, 0x39, 0xe8, 0xdb, 0xf2, 0x82, 0x7a, 0xf6, 0x6d, 0xa0, 0x2b, 0x5e, 0x50, 0xc7, 0x0c, - 0x42, 0xbb, 0x70, 0x42, 0x75, 0x41, 0x0a, 0x84, 0xe7, 0x61, 0x68, 0xbd, 0xed, 0xf9, 0x75, 0x99, - 0x17, 0x31, 0x63, 0x51, 0x99, 0x31, 0x60, 0x38, 0x85, 0x49, 0xcf, 0x75, 0xeb, 0x5e, 0xe0, 0x44, - 0x3b, 0x2b, 0x5a, 0x02, 0x29, 0xa6, 0x34, 0xa3, 0x20, 0xd8, 0xc0, 0xb2, 0x5f, 0x2f, 0xc3, 0x48, - 0x3a, 0xaa, 0xae, 0x87, 0xe3, 0xd5, 0xe3, 0x50, 0x61, 0x81, 0x76, 0xd9, 0xa9, 0xe5, 0xa9, 0x04, - 0x39, 0x0c, 0xc5, 0xd0, 0xcf, 0xb3, 0x87, 0x14, 0xf3, 0xae, 0x96, 0xea, 0xa4, 0xb2, 0xc3, 0x30, - 0x97, 0x3b, 0x91, 0xb0, 0x44, 0x90, 0x42, 0x9f, 0xb2, 0x60, 0x20, 0x6c, 0x99, 0x09, 0xb1, 0x3e, - 0x50, 0x64, 0xc4, 0xa1, 0x08, 0x43, 0x12, 0x1a, 0xb1, 0x9a, 0x7a, 0x39, 0x1d, 0x92, 0xf4, 0xd9, - 0x77, 0xc3, 0x90, 0x89, 0xb9, 0x9f, 0x52, 0x5c, 0x35, 0x95, 0xe2, 0xcf, 0x9a, 0x8b, 0x42, 0xc4, - 0x54, 0xf6, 0xb0, 0xdd, 0xae, 0x41, 0xc5, 0x55, 0x7e, 0x09, 0xf7, 0x94, 0x4d, 0x57, 0xa5, 0xf3, - 0x60, 0x77, 0x53, 0xbc, 0x35, 0xfb, 0xbb, 0x96, 0xb1, 0x3e, 0x30, 0x89, 0x17, 0xea, 0x28, 0x82, - 0x72, 0x63, 0x7b, 0x4b, 0xa8, 0xa2, 0x97, 0x0b, 0x1a, 0xde, 0xf9, 0xed, 0x2d, 0xbd, 0xc6, 0xcd, - 0x52, 0x4c, 0x89, 0xf5, 0x60, 0x2c, 0x4c, 0x85, 0xde, 0x96, 0xf7, 0x0f, 0xbd, 0xb5, 0xdf, 0x28, - 0xc1, 0x58, 0xc7, 0xa2, 0x42, 0xaf, 0x41, 0x25, 0xa2, 0x5f, 0x29, 0x3e, 0x6f, 0xb1, 0xb0, 0x60, - 0xd9, 0x78, 0xa1, 0xae, 0xe5, 0x6e, 0xba, 0x1c, 0x73, 0x92, 0xe8, 0x32, 0x20, 0xed, 0x3d, 0xa3, - 0x2c, 0x95, 0xfc, 0x93, 0xcf, 0x8a, 0xaa, 0x68, 0xba, 0x03, 0x03, 0xe7, 0xd4, 0x42, 0x2f, 0x64, - 0x0d, 0x9e, 0xe5, 0xb4, 0x39, 0x7b, 0x2f, 0xdb, 0xa5, 0xfd, 0xdb, 0x25, 0x18, 0x4e, 0xe5, 0x27, - 0x43, 0x3e, 0x54, 0x89, 0xcf, 0xee, 0x1a, 0xa4, 0xb0, 0x39, 0x6c, 0xb6, 0x71, 0x25, 0x20, 0x2f, - 0x88, 0x76, 0xb1, 0xa2, 0xf0, 0x60, 0xdc, 0xf9, 0x3f, 0x0f, 0x43, 0xb2, 0x43, 0x1f, 0x70, 0x9a, - 0xbe, 0x18, 0x40, 0xb5, 0x46, 0x2f, 0x18, 0x30, 0x9c, 0xc2, 0xb4, 0x7f, 0xbf, 0x0c, 0xe3, 0xfc, - 0x72, 0xa6, 0xae, 0x56, 0xde, 0x92, 0x3c, 0x6f, 0xfd, 0x35, 0x9d, 0x45, 0xd0, 0x2a, 0xe2, 0x49, - 0xcd, 0x6e, 0x84, 0x7a, 0x72, 0x18, 0xfb, 0x6a, 0xc6, 0x61, 0x8c, 0xab, 0xdd, 0x8d, 0x23, 0xea, - 0xd1, 0x0f, 0x97, 0x07, 0xd9, 0xdf, 0x2f, 0xc1, 0x68, 0xe6, 0xe5, 0x14, 0xf4, 0x7a, 0x3a, 0xd9, - 0xb6, 0x55, 0x84, 0x4d, 0x7d, 0xcf, 0xc7, 0x34, 0x0e, 0x96, 0x72, 0xfb, 0x3e, 0x6d, 0x15, 0xfb, - 0x3b, 0x25, 0x18, 0x49, 0x3f, 0xf9, 0xf2, 0x00, 0x8e, 0xd4, 0x3b, 0xa0, 0xc6, 0x5e, 0x35, 0x60, - 0x2f, 0x15, 0x73, 0x93, 0x3c, 0x4f, 0x20, 0x2f, 0x0b, 0xb1, 0x86, 0x3f, 0x10, 0x99, 0xcc, 0xed, - 0x7f, 0x68, 0xc1, 0x69, 0xfe, 0x95, 0xd9, 0x75, 0xf8, 0xd7, 0xf3, 0x46, 0xf7, 0xe5, 0x62, 0x3b, - 0x98, 0xc9, 0x7e, 0xb9, 0xdf, 0xf8, 0xb2, 0x87, 0x45, 0x45, 0x6f, 0xd3, 0x4b, 0xe1, 0x01, 0xec, - 0xec, 0x81, 0x16, 0x83, 0xfd, 0x9d, 0x32, 0xe8, 0xb7, 0x54, 0x91, 0x27, 0xa2, 0x47, 0x0b, 0xc9, - 0x02, 0xba, 0xba, 0x13, 0xb8, 0xfa, 0xd5, 0xd6, 0x6a, 0x26, 0x78, 0xf4, 0x97, 0x2c, 0x18, 0xf4, - 0x02, 0x2f, 0xf1, 0x1c, 0x76, 0x8c, 0x2e, 0xe6, 0x41, 0x44, 0x45, 0x6e, 0x81, 0xb7, 0x1c, 0x46, - 0xe6, 0x3d, 0x8e, 0x22, 0x86, 0x4d, 0xca, 0xe8, 0xc3, 0xc2, 0xa7, 0xbb, 0x5c, 0x58, 0xdc, 0x73, - 0x35, 0xe3, 0xc8, 0xdd, 0xa2, 0x8a, 0x57, 0x12, 0x15, 0x94, 0x2e, 0x00, 0xd3, 0xa6, 0x54, 0x42, - 0x69, 0xfd, 0x3c, 0x3f, 0x2d, 0xc6, 0x9c, 0x90, 0x1d, 0x03, 0xea, 0x1c, 0x8b, 0x03, 0xfa, 0xcb, - 0x4e, 0x41, 0xcd, 0x69, 0x27, 0x61, 0x93, 0x0e, 0x93, 0xb8, 0x6a, 0xd2, 0x1e, 0xc1, 0x12, 0x80, - 0x35, 0x8e, 0xfd, 0x7a, 0x05, 0x32, 0xe1, 0x9c, 0xe8, 0xb6, 0xf9, 0x0e, 0xb0, 0x55, 0xec, 0x3b, - 0xc0, 0xaa, 0x33, 0x79, 0x6f, 0x01, 0xa3, 0x06, 0x54, 0x5a, 0x9b, 0x4e, 0x2c, 0xd5, 0xea, 0x17, - 0xd5, 0x39, 0x8e, 0x16, 0xde, 0xdd, 0x9d, 0xf8, 0x99, 0xde, 0xac, 0xae, 0x74, 0xad, 0x4e, 0xf1, - 0x14, 0x34, 0x9a, 0x34, 0x6b, 0x03, 0xf3, 0xf6, 0x0f, 0xf2, 0x24, 0xe4, 0x27, 0xc4, 0xf3, 0x0d, - 0x98, 0xc4, 0x6d, 0x3f, 0x11, 0xab, 0xe1, 0xc5, 0x02, 0x77, 0x19, 0x6f, 0x58, 0x27, 0x22, 0xe0, - 0xff, 0xb1, 0x41, 0x14, 0x7d, 0x10, 0x6a, 0x71, 0xe2, 0x44, 0xc9, 0x3d, 0x86, 0x0e, 0xab, 0x41, - 0x5f, 0x95, 0x8d, 0x60, 0xdd, 0x1e, 0x7a, 0x89, 0x25, 0x45, 0xf6, 0xe2, 0xcd, 0x7b, 0x0c, 0xc5, - 0x90, 0x09, 0x94, 0x45, 0x0b, 0xd8, 0x68, 0x0d, 0x9d, 0x07, 0x60, 0x6b, 0x9b, 0xfb, 0x1f, 0x56, - 0x99, 0x95, 0x49, 0xb1, 0x42, 0xac, 0x20, 0xd8, 0xc0, 0xb2, 0x7f, 0x12, 0xd2, 0x99, 0x34, 0xd0, - 0x84, 0x4c, 0xdc, 0xc1, 0xad, 0xd0, 0x2c, 0xa4, 0x22, 0x95, 0x63, 0xe3, 0x37, 0x2d, 0x30, 0xd3, - 0x7d, 0xa0, 0x57, 0x79, 0x5e, 0x11, 0xab, 0x88, 0x9b, 0x43, 0xa3, 0xdd, 0xc9, 0x25, 0xa7, 0x95, - 0xb9, 0xc2, 0x96, 0xc9, 0x45, 0xce, 0xbe, 0x0b, 0xaa, 0x12, 0x7a, 0x20, 0xa5, 0xee, 0x63, 0x70, - 0x52, 0x86, 0x67, 0x4a, 0xbb, 0xa9, 0xb8, 0x75, 0xda, 0xdf, 0xf4, 0x23, 0xed, 0x39, 0xa5, 0x6e, - 0xf6, 0x9c, 0x1e, 0x5e, 0x83, 0xfe, 0x2d, 0x0b, 0xce, 0x65, 0x3b, 0x10, 0x2f, 0x85, 0x81, 0x97, - 0x84, 0xd1, 0x2a, 0x49, 0x12, 0x2f, 0x68, 0xb0, 0x74, 0x6a, 0xb7, 0x9c, 0x48, 0x66, 0xab, 0x67, - 0x8c, 0xf2, 0x86, 0x13, 0x05, 0x98, 0x95, 0xa2, 0x1d, 0xe8, 0xe7, 0x4e, 0x6a, 0x42, 0x5b, 0x3f, - 0xe4, 0xde, 0xc8, 0x19, 0x0e, 0x7d, 0x5c, 0xe0, 0x0e, 0x72, 0x58, 0x10, 0xb4, 0xbf, 0x6f, 0x01, - 0x5a, 0xde, 0x26, 0x51, 0xe4, 0xd5, 0x0d, 0xb7, 0x3a, 0xf6, 0x0c, 0x92, 0xf1, 0xdc, 0x91, 0x19, - 0x3c, 0x9c, 0x79, 0x06, 0xc9, 0xf8, 0x97, 0xff, 0x0c, 0x52, 0xe9, 0x60, 0xcf, 0x20, 0xa1, 0x65, - 0x38, 0xdd, 0xe4, 0xc7, 0x0d, 0xfe, 0xb4, 0x08, 0x3f, 0x7b, 0xa8, 0x38, 0xb7, 0x33, 0x77, 0x76, - 0x27, 0x4e, 0x2f, 0xe5, 0x21, 0xe0, 0xfc, 0x7a, 0xf6, 0xbb, 0x00, 0x71, 0x6f, 0xba, 0xd9, 0x3c, - 0x5f, 0xa5, 0xae, 0xe6, 0x17, 0xfb, 0x2b, 0x15, 0x18, 0xcd, 0xe4, 0x32, 0xa6, 0x47, 0xbd, 0x4e, - 0xe7, 0xa8, 0x43, 0xcb, 0xef, 0xce, 0xee, 0xf5, 0xe4, 0x6e, 0x15, 0x40, 0xc5, 0x0b, 0x5a, 0xed, - 0xa4, 0x98, 0x30, 0x5b, 0xde, 0x89, 0x05, 0xda, 0xa0, 0x61, 0x2e, 0xa6, 0x7f, 0x31, 0x27, 0x53, - 0xa4, 0xf3, 0x56, 0x4a, 0x19, 0xef, 0xbb, 0x4f, 0xe6, 0x80, 0x4f, 0x68, 0x57, 0xaa, 0x4a, 0x11, - 0x86, 0xc5, 0xcc, 0x62, 0x39, 0xea, 0xab, 0xf6, 0x6f, 0x96, 0x60, 0xd0, 0x98, 0x34, 0xf4, 0x6b, - 0xe9, 0x64, 0x58, 0x56, 0x71, 0x9f, 0xc4, 0xda, 0x9f, 0xd4, 0xe9, 0xae, 0xf8, 0x27, 0x3d, 0xd1, - 0x99, 0x07, 0xeb, 0xee, 0xee, 0xc4, 0x89, 0x4c, 0xa6, 0xab, 0x54, 0x6e, 0xac, 0xb3, 0x1f, 0x85, - 0xd1, 0x4c, 0x33, 0x39, 0x9f, 0xbc, 0x66, 0x7e, 0xf2, 0xa1, 0xcd, 0x52, 0xe6, 0x90, 0x7d, 0x83, - 0x0e, 0x99, 0x88, 0xee, 0x0b, 0x7d, 0xd2, 0x83, 0x0d, 0x36, 0x13, 0xc4, 0x5b, 0xea, 0x31, 0x88, - 0xf7, 0x49, 0xa8, 0xb6, 0x42, 0xdf, 0x73, 0x3d, 0x95, 0x9b, 0x92, 0x85, 0x0d, 0xaf, 0x88, 0x32, - 0xac, 0xa0, 0xe8, 0x16, 0xd4, 0x6e, 0xde, 0x4a, 0xf8, 0xed, 0x8f, 0xb0, 0x6f, 0x17, 0x75, 0xe9, - 0xa3, 0x94, 0x16, 0x75, 0xbd, 0x84, 0x35, 0x2d, 0x64, 0x43, 0x3f, 0x13, 0x82, 0x32, 0x22, 0x81, - 0xd9, 0xde, 0x99, 0x74, 0x8c, 0xb1, 0x80, 0xd8, 0x5f, 0xaf, 0xc1, 0xa9, 0xbc, 0x84, 0xf2, 0xe8, - 0x23, 0xd0, 0xcf, 0xfb, 0x58, 0xcc, 0x9b, 0x25, 0x79, 0x34, 0xe6, 0x59, 0x83, 0xa2, 0x5b, 0xec, - 0x37, 0x16, 0x34, 0x05, 0x75, 0xdf, 0x59, 0x17, 0x2b, 0xe4, 0x68, 0xa8, 0x2f, 0x3a, 0x9a, 0xfa, - 0xa2, 0xc3, 0xa9, 0xfb, 0xce, 0x3a, 0xba, 0x0d, 0x95, 0x86, 0x97, 0x10, 0x47, 0x18, 0x11, 0x6e, - 0x1c, 0x09, 0x71, 0xe2, 0x70, 0x2d, 0x8d, 0xfd, 0xc4, 0x9c, 0x20, 0xfa, 0x9a, 0x05, 0xa3, 0xeb, - 0xe9, 0xec, 0x01, 0x82, 0x79, 0x3a, 0x47, 0xf0, 0x68, 0x40, 0x9a, 0x10, 0x7f, 0x07, 0x2c, 0x53, - 0x88, 0xb3, 0xdd, 0x41, 0x9f, 0xb4, 0x60, 0x60, 0xc3, 0xf3, 0x8d, 0xbc, 0xcd, 0x47, 0x30, 0x39, - 0x17, 0x19, 0x01, 0x7d, 0xe2, 0xe0, 0xff, 0x63, 0x2c, 0x29, 0x77, 0x93, 0x54, 0xfd, 0x87, 0x95, - 0x54, 0x03, 0xf7, 0x49, 0x52, 0x7d, 0xc6, 0x82, 0x9a, 0x1a, 0x69, 0x11, 0x85, 0xfd, 0xc1, 0x23, - 0x9c, 0x72, 0x6e, 0x39, 0x51, 0x7f, 0xb1, 0x26, 0x8e, 0xbe, 0x68, 0xc1, 0xa0, 0xf3, 0x5a, 0x3b, - 0x22, 0x75, 0xb2, 0x1d, 0xb6, 0x62, 0xf1, 0x88, 0xe8, 0xcb, 0xc5, 0x77, 0x66, 0x9a, 0x12, 0x99, - 0x23, 0xdb, 0xcb, 0xad, 0x58, 0x44, 0x4b, 0xe9, 0x02, 0x6c, 0x76, 0xc1, 0xde, 0x2d, 0xc1, 0xc4, - 0x3e, 0x2d, 0xa0, 0xe7, 0x61, 0x28, 0x8c, 0x1a, 0x4e, 0xe0, 0xbd, 0x66, 0xa6, 0x03, 0x51, 0x5a, - 0xd6, 0xb2, 0x01, 0xc3, 0x29, 0x4c, 0x33, 0x4e, 0xbc, 0xb4, 0x4f, 0x9c, 0xf8, 0x39, 0xe8, 0x8b, - 0x48, 0x2b, 0xcc, 0x1e, 0x16, 0x58, 0xa4, 0x02, 0x83, 0xa0, 0x47, 0xa1, 0xec, 0xb4, 0x3c, 0xe1, - 0x88, 0xa6, 0xce, 0x40, 0xd3, 0x2b, 0x0b, 0x98, 0x96, 0xa7, 0xd2, 0x56, 0x54, 0x8e, 0x25, 0x6d, - 0x05, 0x15, 0x03, 0xe2, 0xee, 0xa2, 0x5f, 0x8b, 0x81, 0xf4, 0x9d, 0x82, 0xfd, 0x46, 0x19, 0x1e, - 0xdd, 0x73, 0xbd, 0x68, 0x3f, 0x3c, 0x6b, 0x0f, 0x3f, 0x3c, 0x39, 0x3c, 0xa5, 0xfd, 0x86, 0xa7, - 0xdc, 0x65, 0x78, 0x3e, 0x49, 0xb7, 0x81, 0x4c, 0xa3, 0x52, 0xcc, 0x33, 0x90, 0xdd, 0xb2, 0xb2, - 0x88, 0x1d, 0x20, 0xa1, 0x58, 0xd3, 0xa5, 0x67, 0x80, 0x54, 0x8c, 0x74, 0xa5, 0x08, 0x31, 0xd0, - 0x35, 0x95, 0x09, 0x5f, 0xfb, 0xdd, 0x02, 0xaf, 0xed, 0xdf, 0xe9, 0x83, 0xc7, 0x7b, 0xe0, 0xde, - 0xe6, 0x2a, 0xb6, 0x7a, 0x5c, 0xc5, 0x3f, 0xe4, 0xd3, 0xf4, 0xe9, 0xdc, 0x69, 0xc2, 0xc5, 0x4f, - 0xd3, 0xde, 0x33, 0x84, 0x9e, 0x82, 0xaa, 0x17, 0xc4, 0xc4, 0x6d, 0x47, 0xdc, 0x27, 0xd9, 0x08, - 0x63, 0x5a, 0x10, 0xe5, 0x58, 0x61, 0xd0, 0x33, 0x9d, 0xeb, 0xd0, 0xed, 0x3f, 0x50, 0x50, 0xec, - 0xae, 0x19, 0x11, 0xc5, 0x55, 0x8a, 0xd9, 0x69, 0xca, 0x01, 0x38, 0x19, 0xfb, 0x6f, 0x58, 0x70, - 0xb6, 0xbb, 0x88, 0x45, 0xcf, 0xc0, 0xe0, 0x7a, 0xe4, 0x04, 0xee, 0x26, 0x7b, 0x00, 0x58, 0x2e, - 0x1d, 0xf6, 0xbd, 0xba, 0x18, 0x9b, 0x38, 0x68, 0x16, 0xc6, 0xb8, 0xe7, 0x86, 0x81, 0x21, 0x23, - 0x7f, 0xef, 0xec, 0x4e, 0x8c, 0xad, 0x65, 0x81, 0xb8, 0x13, 0xdf, 0xfe, 0x41, 0x39, 0xbf, 0x5b, - 0x5c, 0x15, 0x3b, 0xc8, 0x6a, 0x16, 0x6b, 0xb5, 0xd4, 0x03, 0xc7, 0x2d, 0x1f, 0x37, 0xc7, 0xed, - 0xeb, 0xc6, 0x71, 0xd1, 0x1c, 0x9c, 0x30, 0x5e, 0x68, 0xe2, 0xd1, 0xdc, 0xdc, 0x2d, 0x59, 0xa5, - 0x38, 0x59, 0xc9, 0xc0, 0x71, 0x47, 0x8d, 0x07, 0x7c, 0xe9, 0xfd, 0x7a, 0x09, 0xce, 0x74, 0xd5, - 0x7e, 0x8f, 0x49, 0xa2, 0x98, 0xd3, 0xdf, 0x77, 0x3c, 0xd3, 0x6f, 0x4e, 0x4a, 0x65, 0xbf, 0x49, - 0xb1, 0xff, 0xa4, 0xd4, 0x75, 0x23, 0xd0, 0x93, 0xd0, 0x8f, 0xec, 0x28, 0xbd, 0x00, 0xc3, 0x4e, - 0xab, 0xc5, 0xf1, 0x98, 0x17, 0x6d, 0x26, 0xa5, 0xd2, 0xb4, 0x09, 0xc4, 0x69, 0xdc, 0x9e, 0x74, - 0x9a, 0x3f, 0xb5, 0xa0, 0x86, 0xc9, 0x06, 0xe7, 0x46, 0xe8, 0xa6, 0x18, 0x22, 0xab, 0x88, 0xfc, - 0xb1, 0x74, 0x60, 0x63, 0x8f, 0xe5, 0x55, 0xcd, 0x1b, 0xec, 0xce, 0x17, 0xbb, 0x4a, 0x07, 0x7a, - 0xb1, 0x4b, 0xbd, 0xd9, 0x54, 0xee, 0xfe, 0x66, 0x93, 0xfd, 0xbd, 0x01, 0xfa, 0x79, 0xad, 0x70, - 0x36, 0x22, 0xf5, 0x98, 0xce, 0x6f, 0x3b, 0xf2, 0xc5, 0x22, 0x51, 0xf3, 0x7b, 0x0d, 0x2f, 0x62, - 0x5a, 0x9e, 0xba, 0x20, 0x2b, 0x1d, 0x28, 0xa1, 0x4c, 0x79, 0xdf, 0x84, 0x32, 0x2f, 0xc0, 0x70, - 0x1c, 0x6f, 0xae, 0x44, 0xde, 0xb6, 0x93, 0x90, 0x2b, 0x64, 0x47, 0xe8, 0xbe, 0x3a, 0x09, 0xc4, - 0xea, 0x25, 0x0d, 0xc4, 0x69, 0x5c, 0x34, 0x0f, 0x63, 0x3a, 0xad, 0x0b, 0x89, 0x12, 0x16, 0x73, - 0xc1, 0x57, 0x82, 0x8a, 0xf8, 0xd6, 0x89, 0x60, 0x04, 0x02, 0xee, 0xac, 0x43, 0xf9, 0x69, 0xaa, - 0x90, 0x76, 0xa4, 0x3f, 0xcd, 0x4f, 0x53, 0xed, 0xd0, 0xbe, 0x74, 0xd4, 0x40, 0x4b, 0x70, 0x92, - 0x2f, 0x8c, 0xe9, 0x56, 0xcb, 0xf8, 0xa2, 0x81, 0x74, 0xde, 0xce, 0xf9, 0x4e, 0x14, 0x9c, 0x57, - 0x0f, 0x3d, 0x07, 0x83, 0xaa, 0x78, 0x61, 0x4e, 0xdc, 0xed, 0x28, 0xdb, 0x92, 0x6a, 0x66, 0xa1, - 0x8e, 0x4d, 0x3c, 0xf4, 0x01, 0x78, 0x58, 0xff, 0xe5, 0x81, 0x79, 0xfc, 0xc2, 0x73, 0x4e, 0x64, - 0xcc, 0x52, 0x2f, 0x04, 0xcd, 0xe7, 0xa2, 0xd5, 0x71, 0xb7, 0xfa, 0x68, 0x1d, 0xce, 0x2a, 0xd0, - 0x85, 0x20, 0x61, 0x51, 0x36, 0x31, 0x99, 0x71, 0x62, 0x72, 0x2d, 0xf2, 0xc5, 0x4b, 0xd3, 0xea, - 0x11, 0xd9, 0x79, 0x2f, 0xb9, 0x94, 0x87, 0x89, 0x17, 0xf1, 0x1e, 0xad, 0xa0, 0x29, 0xa8, 0x91, - 0xc0, 0x59, 0xf7, 0xc9, 0xf2, 0xec, 0x02, 0xcb, 0xbc, 0x65, 0xdc, 0xaf, 0x5e, 0x90, 0x00, 0xac, - 0x71, 0x94, 0xdf, 0xef, 0x50, 0xd7, 0x07, 0x8d, 0x57, 0xe0, 0x54, 0xc3, 0x6d, 0x51, 0x8d, 0xd0, - 0x73, 0xc9, 0xb4, 0xcb, 0xdc, 0x1c, 0xe9, 0xc4, 0xf0, 0x84, 0xaa, 0xca, 0xa9, 0x7d, 0x7e, 0x76, - 0xa5, 0x03, 0x07, 0xe7, 0xd6, 0x64, 0xee, 0xb0, 0x51, 0x78, 0x7b, 0x67, 0xfc, 0x64, 0xc6, 0x1d, - 0x96, 0x16, 0x62, 0x0e, 0x43, 0x97, 0x01, 0xb1, 0x08, 0x89, 0x4b, 0x49, 0xd2, 0x52, 0x2a, 0xe8, - 0xf8, 0x29, 0xf6, 0x49, 0xca, 0xb9, 0xef, 0x62, 0x07, 0x06, 0xce, 0xa9, 0x45, 0x35, 0x9a, 0x20, - 0x64, 0xad, 0x8f, 0x3f, 0x9c, 0xd6, 0x68, 0xae, 0xf2, 0x62, 0x2c, 0xe1, 0xf6, 0x7f, 0xb4, 0x60, - 0x58, 0x6d, 0xed, 0x63, 0x08, 0x27, 0xf2, 0xd3, 0xe1, 0x44, 0xf3, 0x87, 0x67, 0x8e, 0xac, 0xe7, - 0x5d, 0x7c, 0xd2, 0xbf, 0x39, 0x08, 0xa0, 0x19, 0xa8, 0x92, 0x5d, 0x56, 0x57, 0xd9, 0xf5, 0xc0, - 0x32, 0xaf, 0xbc, 0x8c, 0x3c, 0x95, 0xfb, 0x9b, 0x91, 0x67, 0x15, 0x4e, 0x4b, 0xcd, 0x82, 0x5f, - 0xf6, 0x5d, 0x0a, 0x63, 0xc5, 0x0b, 0xab, 0x33, 0x8f, 0x8a, 0x86, 0x4e, 0x2f, 0xe4, 0x21, 0xe1, - 0xfc, 0xba, 0x29, 0x85, 0x66, 0x60, 0x5f, 0x2d, 0x53, 0x6d, 0xff, 0xc5, 0x0d, 0xf9, 0x34, 0x4f, - 0x66, 0xfb, 0x2f, 0x5e, 0x5c, 0xc5, 0x1a, 0x27, 0x5f, 0x06, 0xd4, 0x0a, 0x92, 0x01, 0x70, 0x60, - 0x19, 0x20, 0xb9, 0xd1, 0x60, 0x57, 0x6e, 0x24, 0x2f, 0x15, 0x86, 0xba, 0x5e, 0x2a, 0xbc, 0x17, - 0x46, 0xbc, 0x60, 0x93, 0x44, 0x5e, 0x42, 0xea, 0x6c, 0x2f, 0x30, 0x4e, 0x55, 0xd5, 0x1a, 0xc0, - 0x42, 0x0a, 0x8a, 0x33, 0xd8, 0x69, 0x16, 0x3a, 0xd2, 0x03, 0x0b, 0xed, 0x22, 0xb8, 0x46, 0x8b, - 0x11, 0x5c, 0x27, 0x0e, 0x2f, 0xb8, 0xc6, 0x8e, 0x54, 0x70, 0xa1, 0x42, 0x04, 0x57, 0x4f, 0x32, - 0xc1, 0x38, 0x99, 0x9e, 0xda, 0xe7, 0x64, 0xda, 0x4d, 0x6a, 0x9d, 0xbe, 0x67, 0xa9, 0x95, 0x2f, - 0x90, 0x1e, 0x3a, 0x6a, 0x81, 0xf4, 0x99, 0x12, 0x9c, 0xd6, 0x2c, 0x9b, 0x6e, 0x14, 0x6f, 0x83, - 0x32, 0x2d, 0xf6, 0x10, 0x1c, 0xbf, 0xa3, 0x33, 0x02, 0xe1, 0x74, 0x4c, 0x9d, 0x82, 0x60, 0x03, - 0x8b, 0xc5, 0x93, 0x91, 0x88, 0x65, 0x95, 0xce, 0xf2, 0xf3, 0x59, 0x51, 0x8e, 0x15, 0x06, 0x5d, - 0x8a, 0xf4, 0xb7, 0x88, 0xd1, 0xcd, 0xe6, 0x2b, 0x9c, 0xd5, 0x20, 0x6c, 0xe2, 0xa1, 0x27, 0x39, - 0x11, 0xc6, 0x4b, 0x28, 0x4f, 0x1f, 0x12, 0x8f, 0x67, 0x4b, 0xf6, 0xa1, 0xa0, 0xb2, 0x3b, 0x2c, - 0x70, 0xb0, 0xd2, 0xd9, 0x1d, 0xe6, 0xee, 0xa6, 0x30, 0xec, 0xff, 0x69, 0xc1, 0x99, 0xdc, 0xa1, - 0x38, 0x06, 0x39, 0x7d, 0x3b, 0x2d, 0xa7, 0x57, 0x8b, 0x3a, 0xc4, 0x18, 0x5f, 0xd1, 0x45, 0x66, - 0xff, 0x7b, 0x0b, 0x46, 0x34, 0xfe, 0x31, 0x7c, 0xaa, 0x97, 0xfe, 0xd4, 0xe2, 0xce, 0x6b, 0xb5, - 0x8e, 0x6f, 0xfb, 0xfd, 0x12, 0xa8, 0x1c, 0xa2, 0xd3, 0xae, 0xcc, 0xd0, 0xbc, 0xcf, 0xad, 0xf1, - 0x0e, 0xf4, 0xb3, 0x4b, 0xef, 0xb8, 0x18, 0x87, 0x9e, 0x34, 0x7d, 0x76, 0x81, 0xae, 0x1d, 0x0a, - 0xd8, 0xdf, 0x18, 0x0b, 0x82, 0x2c, 0xe7, 0xb9, 0x17, 0x53, 0xc6, 0x5f, 0x17, 0x21, 0x78, 0x3a, - 0xe7, 0xb9, 0x28, 0xc7, 0x0a, 0x83, 0x4a, 0x12, 0xcf, 0x0d, 0x83, 0x59, 0xdf, 0x89, 0xe5, 0xc3, - 0xac, 0x4a, 0x92, 0x2c, 0x48, 0x00, 0xd6, 0x38, 0xec, 0x3e, 0xdc, 0x8b, 0x5b, 0xbe, 0xb3, 0x63, - 0x9c, 0xca, 0x8d, 0x5c, 0x14, 0x0a, 0x84, 0x4d, 0x3c, 0xbb, 0x09, 0xe3, 0xe9, 0x8f, 0x98, 0x23, - 0x1b, 0xcc, 0x19, 0xb5, 0xa7, 0xe1, 0x9c, 0x82, 0x9a, 0xc3, 0x6a, 0x2d, 0xb6, 0x1d, 0xc1, 0x13, - 0xb4, 0x4b, 0xa6, 0x04, 0x60, 0x8d, 0x63, 0xff, 0x03, 0x0b, 0x4e, 0xe6, 0x0c, 0x5a, 0x81, 0x21, - 0x8e, 0x89, 0xe6, 0x36, 0x79, 0x3a, 0xc0, 0xdb, 0x61, 0xa0, 0x4e, 0x36, 0x1c, 0xe9, 0xee, 0x68, - 0x70, 0xcf, 0x39, 0x5e, 0x8c, 0x25, 0xdc, 0xfe, 0xed, 0x12, 0x8c, 0xa6, 0xfb, 0x1a, 0xb3, 0xb0, - 0x21, 0x3e, 0x4c, 0x5e, 0xec, 0x86, 0xdb, 0x24, 0xda, 0xa1, 0x5f, 0x6e, 0x65, 0xc2, 0x86, 0x3a, - 0x30, 0x70, 0x4e, 0x2d, 0x96, 0x41, 0xb8, 0xae, 0x46, 0x5b, 0xae, 0xc8, 0xeb, 0x45, 0xae, 0x48, - 0x3d, 0x99, 0xa6, 0x6b, 0x84, 0x22, 0x89, 0x4d, 0xfa, 0x54, 0x17, 0x61, 0x7e, 0xd8, 0x33, 0x6d, - 0xcf, 0x4f, 0xbc, 0x40, 0x7c, 0xb2, 0x58, 0xab, 0x4a, 0x17, 0x59, 0xea, 0x44, 0xc1, 0x79, 0xf5, - 0xec, 0xef, 0xf7, 0x81, 0x0a, 0xa9, 0x66, 0xae, 0x6b, 0x05, 0x39, 0xfe, 0x1d, 0x34, 0xf8, 0x4c, - 0xad, 0xad, 0xbe, 0xbd, 0x7c, 0x49, 0xb8, 0x29, 0xc7, 0xb4, 0xe7, 0xaa, 0x01, 0x5b, 0xd3, 0x20, - 0x6c, 0xe2, 0xd1, 0x9e, 0xf8, 0xde, 0x36, 0xe1, 0x95, 0xfa, 0xd3, 0x3d, 0x59, 0x94, 0x00, 0xac, - 0x71, 0x68, 0x4f, 0xea, 0xde, 0xc6, 0x86, 0xb0, 0x4b, 0xa8, 0x9e, 0xd0, 0xd1, 0xc1, 0x0c, 0xc2, - 0x73, 0xcc, 0x87, 0x5b, 0x42, 0xff, 0x36, 0x72, 0xcc, 0x87, 0x5b, 0x98, 0x41, 0xe8, 0x2c, 0x05, - 0x61, 0xd4, 0x74, 0x7c, 0xef, 0x35, 0x52, 0x57, 0x54, 0x84, 0xde, 0xad, 0x66, 0xe9, 0x6a, 0x27, - 0x0a, 0xce, 0xab, 0x47, 0x17, 0x74, 0x2b, 0x22, 0x75, 0xcf, 0x4d, 0xcc, 0xd6, 0x20, 0xbd, 0xa0, - 0x57, 0x3a, 0x30, 0x70, 0x4e, 0x2d, 0x34, 0x0d, 0xa3, 0x32, 0x24, 0x5e, 0x26, 0x3c, 0x1a, 0x4c, - 0x27, 0x58, 0xc1, 0x69, 0x30, 0xce, 0xe2, 0x53, 0x26, 0xd9, 0x14, 0x39, 0xd1, 0x98, 0x9a, 0x6e, - 0x30, 0x49, 0x99, 0x2b, 0x0d, 0x2b, 0x0c, 0xfb, 0x13, 0x65, 0x2a, 0xd4, 0xbb, 0xa4, 0x1e, 0x3c, - 0x36, 0x47, 0xd3, 0xf4, 0x8a, 0xec, 0xeb, 0x61, 0x45, 0x3e, 0x0b, 0x43, 0x37, 0xe3, 0x30, 0x50, - 0x4e, 0x9c, 0x95, 0xae, 0x4e, 0x9c, 0x06, 0x56, 0xbe, 0x13, 0x67, 0x7f, 0x51, 0x4e, 0x9c, 0x03, - 0xf7, 0xe8, 0xc4, 0xf9, 0x87, 0x15, 0x50, 0xef, 0xf5, 0x5c, 0x25, 0xc9, 0xad, 0x30, 0xda, 0xf2, - 0x82, 0x06, 0x4b, 0x25, 0xf0, 0x35, 0x0b, 0x86, 0xf8, 0x7e, 0x59, 0x34, 0x83, 0xf0, 0x36, 0x0a, - 0x7a, 0x08, 0x26, 0x45, 0x6c, 0x72, 0xcd, 0x20, 0x94, 0x79, 0xcb, 0xd7, 0x04, 0xe1, 0x54, 0x8f, - 0xd0, 0x47, 0x01, 0xa4, 0x11, 0x77, 0x43, 0x72, 0xe0, 0x85, 0x62, 0xfa, 0x87, 0xc9, 0x86, 0x56, - 0xa9, 0xd7, 0x14, 0x11, 0x6c, 0x10, 0x44, 0x9f, 0xd1, 0x01, 0x8a, 0x3c, 0xda, 0xe3, 0xc3, 0x47, - 0x32, 0x36, 0xbd, 0x84, 0x27, 0x62, 0x18, 0xf0, 0x82, 0x06, 0x5d, 0x27, 0xc2, 0xd9, 0xed, 0x6d, - 0x79, 0x69, 0x38, 0x16, 0x43, 0xa7, 0x3e, 0xe3, 0xf8, 0x4e, 0xe0, 0x92, 0x68, 0x81, 0xa3, 0x9b, - 0x8f, 0xeb, 0xb3, 0x02, 0x2c, 0x1b, 0xea, 0x78, 0xe9, 0xa8, 0xd2, 0xcb, 0x4b, 0x47, 0x67, 0xdf, - 0x07, 0x63, 0x1d, 0x93, 0x79, 0xa0, 0x68, 0xc4, 0x7b, 0x0f, 0x64, 0xb4, 0x7f, 0xa7, 0x5f, 0x0b, - 0xad, 0xab, 0x61, 0x9d, 0x3f, 0x9c, 0x13, 0xe9, 0x19, 0x15, 0x2a, 0x73, 0x81, 0x4b, 0xc4, 0x78, - 0xa0, 0x5f, 0x15, 0x62, 0x93, 0x24, 0x5d, 0xa3, 0x2d, 0x27, 0x22, 0xc1, 0x51, 0xaf, 0xd1, 0x15, - 0x45, 0x04, 0x1b, 0x04, 0xd1, 0x66, 0x2a, 0x1c, 0xe9, 0xe2, 0xe1, 0xc3, 0x91, 0x58, 0x82, 0xb2, - 0xbc, 0xf7, 0x25, 0xbe, 0x68, 0xc1, 0x48, 0x90, 0x5a, 0xb9, 0xc5, 0x78, 0x20, 0xe7, 0xef, 0x0a, - 0xfe, 0xdc, 0x5b, 0xba, 0x0c, 0x67, 0xe8, 0xe7, 0x89, 0xb4, 0xca, 0x01, 0x45, 0x9a, 0x7e, 0xb8, - 0xab, 0xbf, 0xdb, 0xc3, 0x5d, 0x28, 0x50, 0x2f, 0x17, 0x0e, 0x14, 0xfe, 0x72, 0x21, 0xe4, 0xbc, - 0x5a, 0x78, 0x03, 0x6a, 0x6e, 0x44, 0x9c, 0xe4, 0x1e, 0x1f, 0xb1, 0x63, 0xbe, 0x1d, 0xb3, 0xb2, - 0x01, 0xac, 0xdb, 0xb2, 0xff, 0x4f, 0x1f, 0x9c, 0x90, 0x23, 0x22, 0xa3, 0x17, 0xa8, 0x7c, 0xe4, - 0x74, 0xb5, 0xae, 0xac, 0xe4, 0xe3, 0x25, 0x09, 0xc0, 0x1a, 0x87, 0xea, 0x63, 0xed, 0x98, 0x2c, - 0xb7, 0x48, 0xb0, 0xe8, 0xad, 0xc7, 0xe2, 0x32, 0x56, 0x6d, 0x94, 0x6b, 0x1a, 0x84, 0x4d, 0x3c, - 0xaa, 0xdb, 0x3b, 0x86, 0xd2, 0x6a, 0xe8, 0xf6, 0x52, 0x51, 0x95, 0x70, 0xf4, 0x2b, 0xb9, 0xb9, - 0x90, 0x8b, 0x89, 0xf9, 0xeb, 0x08, 0xda, 0x38, 0xe0, 0xbb, 0xa7, 0x7f, 0xd7, 0x82, 0xd3, 0xbc, - 0x54, 0x8e, 0xe4, 0xb5, 0x56, 0xdd, 0x49, 0x48, 0x5c, 0xcc, 0xdb, 0x04, 0x39, 0xfd, 0xd3, 0xe6, - 0xe5, 0x3c, 0xb2, 0x38, 0xbf, 0x37, 0xe8, 0x75, 0x0b, 0x46, 0xb7, 0x52, 0xe9, 0x62, 0xa4, 0xe8, - 0x38, 0x6c, 0x26, 0x87, 0x54, 0xa3, 0x7a, 0xab, 0xa5, 0xcb, 0x63, 0x9c, 0xa5, 0x6e, 0xff, 0x0f, - 0x0b, 0x4c, 0x36, 0x7a, 0xfc, 0x59, 0x66, 0x0e, 0xae, 0x0a, 0x4a, 0xed, 0xb2, 0xd2, 0x55, 0xbb, - 0x7c, 0x14, 0xca, 0x6d, 0xaf, 0x2e, 0xce, 0x17, 0xfa, 0x8a, 0x78, 0x61, 0x0e, 0xd3, 0x72, 0xfb, - 0x9f, 0x57, 0xb4, 0x19, 0x44, 0x84, 0xd4, 0xfd, 0x48, 0x7c, 0xf6, 0x86, 0xca, 0x53, 0xc7, 0xbf, - 0xfc, 0x6a, 0x47, 0x9e, 0xba, 0x9f, 0x3e, 0x78, 0xc4, 0x24, 0x1f, 0xa0, 0x6e, 0x69, 0xea, 0x06, - 0xf6, 0x09, 0x97, 0xbc, 0x09, 0x55, 0x7a, 0x04, 0x63, 0xf6, 0xcc, 0x6a, 0xaa, 0x53, 0xd5, 0x4b, - 0xa2, 0xfc, 0xee, 0xee, 0xc4, 0xbb, 0x0f, 0xde, 0x2d, 0x59, 0x1b, 0xab, 0xf6, 0x51, 0x0c, 0x35, - 0xfa, 0x9b, 0x45, 0x76, 0x8a, 0xc3, 0xdd, 0x35, 0xc5, 0x33, 0x25, 0xa0, 0x90, 0xb0, 0x51, 0x4d, - 0x07, 0x05, 0x50, 0x63, 0x4f, 0x44, 0x33, 0xa2, 0xfc, 0x0c, 0xb8, 0xa2, 0xe2, 0x2b, 0x25, 0xe0, - 0xee, 0xee, 0xc4, 0x0b, 0x07, 0x27, 0xaa, 0xaa, 0x63, 0x4d, 0xc2, 0xfe, 0x52, 0x9f, 0x5e, 0xbb, - 0x22, 0x3d, 0xe1, 0x8f, 0xc4, 0xda, 0x7d, 0x3e, 0xb3, 0x76, 0xcf, 0x75, 0xac, 0xdd, 0x11, 0xfd, - 0x94, 0x71, 0x6a, 0x35, 0x1e, 0xb7, 0x22, 0xb0, 0xbf, 0xbd, 0x81, 0x69, 0x40, 0xaf, 0xb6, 0xbd, - 0x88, 0xc4, 0x2b, 0x51, 0x3b, 0xf0, 0x82, 0x06, 0x5b, 0x8e, 0x55, 0x53, 0x03, 0x4a, 0x81, 0x71, - 0x16, 0x9f, 0x1e, 0xea, 0xe9, 0x9c, 0xdf, 0x70, 0xb6, 0xf9, 0xaa, 0x32, 0x32, 0xb6, 0xad, 0x8a, - 0x72, 0xac, 0x30, 0xec, 0x6f, 0xb0, 0x5b, 0x74, 0x23, 0xa4, 0x9c, 0xae, 0x09, 0x9f, 0xbd, 0xc9, - 0xcd, 0xd3, 0xbd, 0xa9, 0x35, 0xc1, 0x1f, 0xe2, 0xe6, 0x30, 0x74, 0x0b, 0x06, 0xd6, 0xf9, 0xeb, - 0x92, 0xc5, 0x64, 0xdc, 0x17, 0x4f, 0x55, 0xb2, 0x77, 0x7b, 0xe4, 0xbb, 0x95, 0x77, 0xf5, 0x4f, - 0x2c, 0xa9, 0xd9, 0xdf, 0xae, 0xc0, 0x68, 0xe6, 0xd5, 0xe6, 0x54, 0xa2, 0xdd, 0xd2, 0xbe, 0x89, - 0x76, 0x3f, 0x04, 0x50, 0x27, 0x2d, 0x3f, 0xdc, 0x61, 0xea, 0x58, 0xdf, 0x81, 0xd5, 0x31, 0xa5, - 0xc1, 0xcf, 0xa9, 0x56, 0xb0, 0xd1, 0xa2, 0xc8, 0x71, 0xc7, 0xf3, 0xf6, 0x66, 0x72, 0xdc, 0x19, - 0xef, 0x72, 0xf4, 0x1f, 0xef, 0xbb, 0x1c, 0x1e, 0x8c, 0xf2, 0x2e, 0xaa, 0xc0, 0xed, 0x7b, 0x88, - 0xcf, 0x66, 0xa1, 0x2f, 0x73, 0xe9, 0x66, 0x70, 0xb6, 0xdd, 0xfb, 0xf9, 0x28, 0x3b, 0x7a, 0x07, - 0xd4, 0xe4, 0x3c, 0xc7, 0xe3, 0x35, 0x9d, 0xfc, 0x42, 0x2e, 0x03, 0xf6, 0x58, 0xba, 0xf8, 0xd9, - 0x91, 0x83, 0x02, 0xee, 0x57, 0x0e, 0x0a, 0xfb, 0x0b, 0x25, 0xaa, 0xc7, 0xf3, 0x7e, 0xa9, 0x74, - 0x4a, 0x4f, 0x40, 0xbf, 0xd3, 0x4e, 0x36, 0xc3, 0x8e, 0xf7, 0x29, 0xa7, 0x59, 0x29, 0x16, 0x50, - 0xb4, 0x08, 0x7d, 0x75, 0x9d, 0x22, 0xe7, 0x20, 0xf3, 0xa9, 0x4d, 0xa2, 0x4e, 0x42, 0x30, 0x6b, - 0x05, 0x3d, 0x02, 0x7d, 0x89, 0xd3, 0x90, 0xd1, 0x7a, 0x2c, 0x42, 0x7b, 0xcd, 0x69, 0xc4, 0x98, - 0x95, 0x9a, 0xe2, 0xbb, 0x6f, 0x1f, 0xf1, 0xfd, 0x02, 0x0c, 0xc7, 0x5e, 0x23, 0x70, 0x92, 0x76, - 0x44, 0x8c, 0x5b, 0x43, 0xed, 0x33, 0x62, 0x02, 0x71, 0x1a, 0xd7, 0xfe, 0xdd, 0x21, 0x38, 0xb5, - 0x3a, 0xbb, 0x24, 0x13, 0xbf, 0x1f, 0x59, 0xc0, 0x5d, 0x1e, 0x8d, 0xe3, 0x0b, 0xb8, 0xeb, 0x42, - 0xdd, 0x37, 0x02, 0xee, 0x7c, 0x23, 0xe0, 0x2e, 0x1d, 0xfd, 0x54, 0x2e, 0x22, 0xfa, 0x29, 0xaf, - 0x07, 0xbd, 0x44, 0x3f, 0x1d, 0x59, 0x04, 0xde, 0x9e, 0x1d, 0x3a, 0x50, 0x04, 0x9e, 0x0a, 0x4f, - 0x2c, 0x24, 0x2e, 0xa5, 0xcb, 0x54, 0xe5, 0x86, 0x27, 0xaa, 0xd0, 0x30, 0x1e, 0x73, 0x25, 0x58, - 0xfd, 0xcb, 0xc5, 0x77, 0xa0, 0x87, 0xd0, 0x30, 0x11, 0xf6, 0x65, 0x86, 0x23, 0x0e, 0x14, 0x11, - 0x8e, 0x98, 0xd7, 0x9d, 0x7d, 0xc3, 0x11, 0x5f, 0x80, 0x61, 0xd7, 0x0f, 0x03, 0xb2, 0x12, 0x85, - 0x49, 0xe8, 0x86, 0xbe, 0x50, 0xeb, 0xf5, 0x43, 0x34, 0x26, 0x10, 0xa7, 0x71, 0xbb, 0xc5, 0x32, - 0xd6, 0x0e, 0x1b, 0xcb, 0x08, 0xf7, 0x29, 0x96, 0xf1, 0x17, 0x75, 0xd4, 0xfd, 0x20, 0x9b, 0x91, - 0x0f, 0x15, 0x3f, 0x23, 0xbd, 0x84, 0xde, 0xa3, 0x37, 0xf8, 0x03, 0x91, 0x54, 0x31, 0x9e, 0x0d, - 0x9b, 0x54, 0xf1, 0x1b, 0x62, 0x43, 0xf2, 0xca, 0x11, 0x2c, 0xd8, 0x1b, 0xab, 0x9a, 0x8c, 0x7a, - 0x34, 0x52, 0x17, 0xe1, 0x74, 0x47, 0x0e, 0x93, 0x15, 0xe0, 0x2b, 0x25, 0xf8, 0xb1, 0x7d, 0xbb, - 0x80, 0x6e, 0x01, 0x24, 0x4e, 0x43, 0x2c, 0x54, 0x71, 0x61, 0x72, 0x48, 0xc7, 0xce, 0x35, 0xd9, - 0x1e, 0x4f, 0x67, 0xa3, 0xfe, 0xb2, 0xab, 0x08, 0xf9, 0x9b, 0xf9, 0x73, 0x86, 0x7e, 0x47, 0xd6, - 0x4f, 0x1c, 0xfa, 0x04, 0x33, 0x08, 0x15, 0xff, 0x11, 0x69, 0xe8, 0xd7, 0xd5, 0xd5, 0xf4, 0x61, - 0x56, 0x8a, 0x05, 0x14, 0x3d, 0x07, 0x83, 0x8e, 0xef, 0xf3, 0xa0, 0x21, 0x12, 0x8b, 0x17, 0xa2, - 0x74, 0xfa, 0x41, 0x0d, 0xc2, 0x26, 0x9e, 0xfd, 0x17, 0x25, 0x98, 0xd8, 0x87, 0xa7, 0x74, 0x04, - 0x8b, 0x56, 0x7a, 0x0e, 0x16, 0x15, 0x81, 0x14, 0xfd, 0x5d, 0x02, 0x29, 0x9e, 0x83, 0xc1, 0x84, - 0x38, 0x4d, 0xe1, 0x0a, 0x26, 0x2c, 0x01, 0xfa, 0x06, 0x58, 0x83, 0xb0, 0x89, 0x47, 0xb9, 0xd8, - 0x88, 0xe3, 0xba, 0x24, 0x8e, 0x65, 0xa4, 0x84, 0xb0, 0xa6, 0x16, 0x16, 0x86, 0xc1, 0x8c, 0xd4, - 0xd3, 0x29, 0x12, 0x38, 0x43, 0x32, 0x3b, 0xe0, 0xb5, 0x1e, 0x07, 0xfc, 0xeb, 0x25, 0x78, 0x74, - 0x4f, 0xe9, 0xd6, 0x73, 0x10, 0x4b, 0x3b, 0x26, 0x51, 0x76, 0xe1, 0x5c, 0x8b, 0x49, 0x84, 0x19, - 0x84, 0x8f, 0x52, 0xab, 0x65, 0xbc, 0x5e, 0x5f, 0x74, 0x44, 0x17, 0x1f, 0xa5, 0x14, 0x09, 0x9c, - 0x21, 0x79, 0xaf, 0xcb, 0xf2, 0xdb, 0x7d, 0xf0, 0x78, 0x0f, 0x3a, 0x40, 0x81, 0x91, 0x6f, 0xe9, - 0x28, 0xcd, 0xf2, 0x7d, 0x8a, 0xd2, 0xbc, 0xb7, 0xe1, 0x7a, 0x33, 0xb8, 0xb3, 0xa7, 0x08, 0xbb, - 0x6f, 0x94, 0xe0, 0x6c, 0x77, 0x85, 0x05, 0xbd, 0x07, 0x46, 0x23, 0xe5, 0xfa, 0x66, 0x06, 0x78, - 0x9e, 0xe4, 0xf6, 0x96, 0x14, 0x08, 0x67, 0x71, 0xd1, 0x24, 0x40, 0xcb, 0x49, 0x36, 0xe3, 0x0b, - 0xb7, 0xbd, 0x38, 0x11, 0x69, 0x9e, 0x46, 0xf8, 0x0d, 0x9f, 0x2c, 0xc5, 0x06, 0x06, 0x25, 0xc7, - 0xfe, 0xcd, 0x85, 0x57, 0xc3, 0x84, 0x57, 0xe2, 0x87, 0xad, 0x93, 0xf2, 0x51, 0x1c, 0x03, 0x84, - 0xb3, 0xb8, 0x94, 0x1c, 0xbb, 0x43, 0xe6, 0x1d, 0xe5, 0xa7, 0x30, 0x46, 0x6e, 0x51, 0x95, 0x62, - 0x03, 0x23, 0x1b, 0xba, 0x5a, 0xd9, 0x3f, 0x74, 0xd5, 0xfe, 0x67, 0x25, 0x38, 0xd3, 0x55, 0xe1, - 0xed, 0x8d, 0x4d, 0x3d, 0x78, 0xe1, 0xa6, 0xf7, 0xb8, 0xc3, 0x0e, 0x16, 0xa6, 0xf8, 0xa7, 0x5d, - 0x56, 0x9a, 0x08, 0x53, 0xbc, 0xf7, 0xec, 0x0b, 0x0f, 0xde, 0x78, 0x76, 0x44, 0x26, 0xf6, 0x1d, - 0x20, 0x32, 0x31, 0x33, 0x19, 0x95, 0x1e, 0xa5, 0xc3, 0x9f, 0xf7, 0x75, 0x1d, 0x5e, 0x7a, 0x40, - 0xee, 0xc9, 0x9a, 0x3d, 0x07, 0x27, 0xbc, 0x80, 0x3d, 0x90, 0xb6, 0xda, 0x5e, 0x17, 0x99, 0x7f, - 0x78, 0x7a, 0x4b, 0x15, 0xfe, 0xb0, 0x90, 0x81, 0xe3, 0x8e, 0x1a, 0x0f, 0x60, 0xa4, 0xe8, 0xbd, - 0x0d, 0xe9, 0x01, 0x39, 0xf7, 0x32, 0x9c, 0x96, 0x43, 0xb1, 0xe9, 0x44, 0xa4, 0x2e, 0x84, 0x6d, - 0x2c, 0x02, 0x5e, 0xce, 0xf0, 0xa0, 0x99, 0x1c, 0x04, 0x9c, 0x5f, 0x8f, 0xbd, 0x49, 0x15, 0xb6, - 0x3c, 0x57, 0x1c, 0x05, 0xf5, 0x9b, 0x54, 0xb4, 0x10, 0x73, 0x98, 0x96, 0x17, 0xb5, 0xe3, 0x91, - 0x17, 0x1f, 0x82, 0x9a, 0x1a, 0x6f, 0xee, 0xbb, 0xaf, 0x16, 0x79, 0x87, 0xef, 0xbe, 0x5a, 0xe1, - 0x06, 0xd6, 0x7e, 0x8f, 0xa6, 0xbe, 0x13, 0x86, 0x94, 0xf5, 0xab, 0xd7, 0x97, 0xc1, 0xec, 0x2f, - 0xf5, 0xc3, 0x70, 0x2a, 0xdb, 0x67, 0xca, 0xec, 0x6d, 0xed, 0x6b, 0xf6, 0x66, 0x61, 0x1b, 0xed, - 0x40, 0x3e, 0x1b, 0x68, 0x84, 0x6d, 0xb4, 0x03, 0x82, 0x39, 0x8c, 0x1e, 0x3a, 0xea, 0xd1, 0x0e, - 0x6e, 0x07, 0xc2, 0x0f, 0x55, 0x1d, 0x3a, 0xe6, 0x58, 0x29, 0x16, 0x50, 0xf4, 0x71, 0x0b, 0x86, - 0x62, 0x76, 0xa7, 0xc2, 0x2f, 0x0d, 0xc4, 0x22, 0xbf, 0x7c, 0xf8, 0x64, 0xa6, 0x2a, 0xb3, 0x2d, - 0xf3, 0x5b, 0x32, 0x4b, 0x70, 0x8a, 0x22, 0xfa, 0x94, 0x05, 0x35, 0xf5, 0xba, 0x91, 0x78, 0x03, - 0x74, 0xb5, 0xd8, 0x64, 0xaa, 0xdc, 0xda, 0xac, 0xae, 0xa7, 0x54, 0x56, 0x4b, 0xac, 0x09, 0xa3, - 0x58, 0x59, 0xf4, 0x07, 0x8e, 0xc6, 0xa2, 0x0f, 0x39, 0xd6, 0xfc, 0x77, 0x40, 0xad, 0xe9, 0x04, - 0xde, 0x06, 0x89, 0x13, 0x6e, 0x64, 0x97, 0x39, 0x9e, 0x65, 0x21, 0xd6, 0x70, 0xaa, 0x00, 0xc4, - 0xec, 0xc3, 0x12, 0xc3, 0x2a, 0xce, 0x14, 0x80, 0x55, 0x5d, 0x8c, 0x4d, 0x1c, 0xd3, 0x84, 0x0f, - 0xf7, 0xd5, 0x84, 0x3f, 0xb8, 0xb7, 0x09, 0xdf, 0xfe, 0xc7, 0x16, 0x9c, 0xce, 0x9d, 0xb5, 0x07, - 0xd7, 0x1d, 0xd5, 0xfe, 0x72, 0x05, 0x4e, 0xe6, 0xa4, 0xed, 0x45, 0x3b, 0xe6, 0x7a, 0xb6, 0x8a, - 0xf0, 0xec, 0x48, 0x3b, 0x2a, 0xc8, 0x61, 0xcc, 0x59, 0xc4, 0x07, 0xbb, 0x40, 0xd3, 0x97, 0x58, - 0xe5, 0xe3, 0xbd, 0xc4, 0x32, 0x96, 0x65, 0xdf, 0x7d, 0x5d, 0x96, 0x95, 0x7d, 0x6e, 0x96, 0xbe, - 0x69, 0xc1, 0x78, 0xb3, 0xcb, 0x5b, 0x11, 0xc2, 0x1c, 0x7c, 0xfd, 0x68, 0x5e, 0xa2, 0x98, 0x79, - 0xe4, 0xce, 0xee, 0x44, 0xd7, 0x27, 0x3a, 0x70, 0xd7, 0x5e, 0xd9, 0xdf, 0x2f, 0x03, 0xcb, 0x19, - 0xcd, 0x52, 0x33, 0xee, 0xa0, 0x8f, 0x99, 0xd9, 0xbf, 0xad, 0xa2, 0x32, 0x55, 0xf3, 0xc6, 0x55, - 0xf6, 0x70, 0x3e, 0x82, 0x79, 0xc9, 0xc4, 0xb3, 0x4c, 0xab, 0xd4, 0x03, 0xd3, 0xf2, 0x65, 0x9a, - 0xf5, 0x72, 0xf1, 0x69, 0xd6, 0x6b, 0xd9, 0x14, 0xeb, 0x7b, 0x4f, 0x71, 0xdf, 0x03, 0x39, 0xc5, - 0xbf, 0x6a, 0x71, 0xc6, 0x93, 0x99, 0x05, 0xad, 0x19, 0x58, 0x7b, 0x68, 0x06, 0x4f, 0x41, 0x35, - 0x26, 0xfe, 0xc6, 0x25, 0xe2, 0xf8, 0x42, 0x83, 0xd0, 0x5e, 0x05, 0xa2, 0x1c, 0x2b, 0x0c, 0xf6, - 0x0e, 0xb3, 0xef, 0x87, 0xb7, 0x2e, 0x34, 0x5b, 0xc9, 0x8e, 0xd0, 0x25, 0xf4, 0x3b, 0xcc, 0x0a, - 0x82, 0x0d, 0x2c, 0xfb, 0xef, 0x94, 0xf8, 0x0a, 0x14, 0xae, 0x29, 0xcf, 0x67, 0x5e, 0xce, 0xec, - 0xdd, 0xab, 0xe3, 0x23, 0x00, 0x6e, 0xd8, 0x6c, 0x51, 0x3d, 0x73, 0x2d, 0x14, 0x37, 0x75, 0x97, - 0x0e, 0xfd, 0x4e, 0xbf, 0x68, 0x4f, 0x7f, 0x86, 0x2e, 0xc3, 0x06, 0xbd, 0x14, 0x2f, 0x2d, 0xef, - 0xcb, 0x4b, 0x53, 0x6c, 0xa5, 0x6f, 0x1f, 0x69, 0xf7, 0x17, 0x16, 0xa4, 0x34, 0x22, 0xd4, 0x82, - 0x0a, 0xed, 0xee, 0x8e, 0xd8, 0xa1, 0xcb, 0xc5, 0xa9, 0x5f, 0x94, 0x35, 0x8a, 0x65, 0xcf, 0x7e, - 0x62, 0x4e, 0x08, 0xf9, 0xc2, 0x83, 0x85, 0x8f, 0xea, 0xd5, 0xe2, 0x08, 0x5e, 0x0a, 0xc3, 0x2d, - 0x7e, 0xdd, 0xac, 0xbd, 0x61, 0xec, 0xe7, 0x61, 0xac, 0xa3, 0x53, 0xec, 0x91, 0xbc, 0x90, 0x4a, - 0x9f, 0xcc, 0x72, 0x65, 0x01, 0xbd, 0x98, 0xc3, 0xec, 0x6f, 0x58, 0x70, 0x22, 0xdb, 0x3c, 0x7a, - 0xc3, 0x82, 0xb1, 0x38, 0xdb, 0xde, 0x51, 0x8d, 0x9d, 0xf2, 0x42, 0xed, 0x00, 0xe1, 0xce, 0x4e, - 0xd8, 0xff, 0x57, 0x2c, 0xfe, 0x1b, 0x5e, 0x50, 0x0f, 0x6f, 0x29, 0xc5, 0xc4, 0xea, 0xaa, 0x98, - 0xd0, 0xfd, 0xe8, 0x6e, 0x92, 0x7a, 0xdb, 0xef, 0x08, 0x0f, 0x5e, 0x15, 0xe5, 0x58, 0x61, 0xb0, - 0x68, 0xc8, 0xb6, 0x78, 0x87, 0x21, 0xb3, 0x28, 0xe7, 0x44, 0x39, 0x56, 0x18, 0xe8, 0x59, 0x18, - 0x32, 0x3e, 0x52, 0xae, 0x4b, 0xa6, 0x90, 0x1b, 0x22, 0x33, 0xc6, 0x29, 0x2c, 0x34, 0x09, 0xa0, - 0x94, 0x1c, 0x29, 0x22, 0x99, 0x61, 0x4a, 0x71, 0xa2, 0x18, 0x1b, 0x18, 0x2c, 0xf6, 0xd8, 0x6f, - 0xc7, 0xec, 0xe6, 0xa5, 0x5f, 0xe7, 0x06, 0x9e, 0x15, 0x65, 0x58, 0x41, 0x29, 0x37, 0x69, 0x3a, - 0x41, 0xdb, 0xf1, 0xe9, 0x08, 0x89, 0xa3, 0xa6, 0xda, 0x86, 0x4b, 0x0a, 0x82, 0x0d, 0x2c, 0xfa, - 0xc5, 0x89, 0xd7, 0x24, 0x2f, 0x85, 0x81, 0xf4, 0x1e, 0xd4, 0x97, 0x71, 0xa2, 0x1c, 0x2b, 0x0c, - 0xfb, 0xbf, 0x59, 0x30, 0xaa, 0x93, 0x1e, 0xf0, 0xe7, 0xf0, 0xcd, 0x93, 0xb1, 0xb5, 0xef, 0xc9, - 0x38, 0x1d, 0xe2, 0x5d, 0xea, 0x29, 0xc4, 0xdb, 0x8c, 0xbe, 0x2e, 0xef, 0x19, 0x7d, 0xfd, 0x13, - 0xfa, 0xa9, 0x65, 0x1e, 0xa6, 0x3d, 0x98, 0xf7, 0xcc, 0x32, 0xb2, 0xa1, 0xdf, 0x75, 0x54, 0x72, - 0xa0, 0x21, 0x7e, 0x76, 0x98, 0x9d, 0x66, 0x48, 0x02, 0x62, 0x2f, 0x43, 0x4d, 0xdd, 0x49, 0xc9, - 0x83, 0xaa, 0x95, 0x7f, 0x50, 0xed, 0x29, 0x0a, 0x74, 0x66, 0xfd, 0x5b, 0x3f, 0x78, 0xec, 0x2d, - 0x7f, 0xfc, 0x83, 0xc7, 0xde, 0xf2, 0xbd, 0x1f, 0x3c, 0xf6, 0x96, 0x8f, 0xdf, 0x79, 0xcc, 0xfa, - 0xd6, 0x9d, 0xc7, 0xac, 0x3f, 0xbe, 0xf3, 0x98, 0xf5, 0xbd, 0x3b, 0x8f, 0x59, 0xdf, 0xbf, 0xf3, - 0x98, 0xf5, 0xc5, 0xff, 0xfc, 0xd8, 0x5b, 0x5e, 0xca, 0x75, 0x1f, 0xa5, 0x3f, 0x9e, 0x76, 0xeb, - 0x53, 0xdb, 0xe7, 0x99, 0x07, 0x23, 0xdd, 0x5e, 0x53, 0xc6, 0x9a, 0x9a, 0x92, 0xdb, 0xeb, 0xff, - 0x05, 0x00, 0x00, 0xff, 0xff, 0xf9, 0x7b, 0xca, 0xa6, 0xc3, 0xea, 0x00, 0x00, + 0x9c, 0x13, 0x4b, 0x91, 0x2d, 0x27, 0x95, 0x54, 0x4a, 0x15, 0x25, 0xf9, 0x11, 0xa7, 0x6c, 0x97, + 0x2b, 0x76, 0xca, 0xa5, 0xc4, 0x49, 0xd9, 0xa5, 0x52, 0x59, 0x4a, 0x62, 0x23, 0x12, 0xe3, 0x54, + 0x5c, 0xf9, 0xe1, 0xaa, 0x38, 0xf9, 0x91, 0x62, 0xf2, 0x23, 0xd5, 0xdf, 0x3d, 0xb3, 0xb3, 0xc0, + 0x82, 0x18, 0x80, 0x94, 0x72, 0xff, 0x76, 0xfb, 0xbd, 0xe9, 0xf7, 0xa6, 0xa7, 0xfb, 0xbd, 0xd7, + 0xaf, 0xdf, 0x7b, 0x0d, 0x8b, 0x0d, 0x2f, 0xd9, 0x6c, 0xaf, 0x4f, 0xba, 0x61, 0x73, 0xca, 0x89, + 0x1a, 0x61, 0x2b, 0x0a, 0x6f, 0xb2, 0x1f, 0x4f, 0xbb, 0xf5, 0xa9, 0xed, 0xf3, 0x53, 0xad, 0xad, + 0xc6, 0x94, 0xd3, 0xf2, 0xe2, 0x29, 0xa7, 0xd5, 0xf2, 0x3d, 0xd7, 0x49, 0xbc, 0x30, 0x98, 0xda, + 0x7e, 0xc6, 0xf1, 0x5b, 0x9b, 0xce, 0x33, 0x53, 0x0d, 0x12, 0x90, 0xc8, 0x49, 0x48, 0x7d, 0xb2, + 0x15, 0x85, 0x49, 0x88, 0x7e, 0x5a, 0xf7, 0x36, 0x29, 0x7b, 0x63, 0x3f, 0x5e, 0x71, 0xeb, 0x93, + 0xdb, 0xe7, 0x27, 0x5b, 0x5b, 0x8d, 0x49, 0xda, 0xdb, 0xa4, 0xd1, 0xdb, 0xa4, 0xec, 0xed, 0xec, + 0xd3, 0x06, 0x2f, 0x8d, 0xb0, 0x11, 0x4e, 0xb1, 0x4e, 0xd7, 0xdb, 0x1b, 0xec, 0x1f, 0xfb, 0xc3, + 0x7e, 0x71, 0x62, 0x67, 0xed, 0xad, 0xe7, 0xe3, 0x49, 0x2f, 0xa4, 0xec, 0x4d, 0xb9, 0x61, 0x44, + 0xa6, 0xb6, 0x3b, 0x18, 0x3a, 0x7b, 0x49, 0xe3, 0x90, 0xdb, 0x09, 0x09, 0x62, 0x2f, 0x0c, 0xe2, + 0xa7, 0x29, 0x0b, 0x24, 0xda, 0x26, 0x91, 0xf9, 0x7a, 0x06, 0x42, 0x5e, 0x4f, 0xcf, 0xea, 0x9e, + 0x9a, 0x8e, 0xbb, 0xe9, 0x05, 0x24, 0xda, 0xd1, 0x8f, 0x37, 0x49, 0xe2, 0xe4, 0x3d, 0x35, 0xd5, + 0xed, 0xa9, 0xa8, 0x1d, 0x24, 0x5e, 0x93, 0x74, 0x3c, 0xf0, 0xae, 0xfd, 0x1e, 0x88, 0xdd, 0x4d, + 0xd2, 0x74, 0x3a, 0x9e, 0x7b, 0x67, 0xb7, 0xe7, 0xda, 0x89, 0xe7, 0x4f, 0x79, 0x41, 0x12, 0x27, + 0x51, 0xf6, 0x21, 0xfb, 0x57, 0x2d, 0x18, 0x9e, 0xbe, 0xb1, 0x3a, 0xdd, 0x4e, 0x36, 0x67, 0xc3, + 0x60, 0xc3, 0x6b, 0xa0, 0xe7, 0x60, 0xd0, 0xf5, 0xdb, 0x71, 0x42, 0xa2, 0xab, 0x4e, 0x93, 0x8c, + 0x5b, 0xe7, 0xac, 0x27, 0x6b, 0x33, 0x27, 0xbf, 0xb5, 0x3b, 0xf1, 0x96, 0x3b, 0xbb, 0x13, 0x83, + 0xb3, 0x1a, 0x84, 0x4d, 0x3c, 0xf4, 0x76, 0x18, 0x88, 0x42, 0x9f, 0x4c, 0xe3, 0xab, 0xe3, 0x25, + 0xf6, 0xc8, 0xa8, 0x78, 0x64, 0x00, 0xf3, 0x66, 0x2c, 0xe1, 0x14, 0xb5, 0x15, 0x85, 0x1b, 0x9e, + 0x4f, 0xc6, 0xcb, 0x69, 0xd4, 0x15, 0xde, 0x8c, 0x25, 0xdc, 0xfe, 0x93, 0x12, 0xc0, 0x74, 0xab, + 0xb5, 0x12, 0x85, 0x37, 0x89, 0x9b, 0xa0, 0x0f, 0x43, 0x95, 0x0e, 0x73, 0xdd, 0x49, 0x1c, 0xc6, + 0xd8, 0xe0, 0xf9, 0x9f, 0x9c, 0xe4, 0x6f, 0x3d, 0x69, 0xbe, 0xb5, 0x9e, 0x64, 0x14, 0x7b, 0x72, + 0xfb, 0x99, 0xc9, 0xe5, 0x75, 0xfa, 0xfc, 0x12, 0x49, 0x9c, 0x19, 0x24, 0x88, 0x81, 0x6e, 0xc3, + 0xaa, 0x57, 0x14, 0x40, 0x5f, 0xdc, 0x22, 0x2e, 0x7b, 0x87, 0xc1, 0xf3, 0x8b, 0x93, 0x87, 0x99, + 0xcd, 0x93, 0x9a, 0xf3, 0xd5, 0x16, 0x71, 0x67, 0x86, 0x04, 0xe5, 0x3e, 0xfa, 0x0f, 0x33, 0x3a, + 0x68, 0x1b, 0xfa, 0xe3, 0xc4, 0x49, 0xda, 0x31, 0x1b, 0x8a, 0xc1, 0xf3, 0x57, 0x0b, 0xa3, 0xc8, + 0x7a, 0x9d, 0x19, 0x11, 0x34, 0xfb, 0xf9, 0x7f, 0x2c, 0xa8, 0xd9, 0x7f, 0x66, 0xc1, 0x88, 0x46, + 0x5e, 0xf4, 0xe2, 0x04, 0xfd, 0x6c, 0xc7, 0xe0, 0x4e, 0xf6, 0x36, 0xb8, 0xf4, 0x69, 0x36, 0xb4, + 0x27, 0x04, 0xb1, 0xaa, 0x6c, 0x31, 0x06, 0xb6, 0x09, 0x15, 0x2f, 0x21, 0xcd, 0x78, 0xbc, 0x74, + 0xae, 0xfc, 0xe4, 0xe0, 0xf9, 0x4b, 0x45, 0xbd, 0xe7, 0xcc, 0xb0, 0x20, 0x5a, 0x59, 0xa0, 0xdd, + 0x63, 0x4e, 0xc5, 0xfe, 0xab, 0x61, 0xf3, 0xfd, 0xe8, 0x80, 0xa3, 0x67, 0x60, 0x30, 0x0e, 0xdb, + 0x91, 0x4b, 0x30, 0x69, 0x85, 0xf1, 0xb8, 0x75, 0xae, 0x4c, 0xa7, 0x1e, 0x9d, 0xd4, 0xab, 0xba, + 0x19, 0x9b, 0x38, 0xe8, 0x0b, 0x16, 0x0c, 0xd5, 0x49, 0x9c, 0x78, 0x01, 0xa3, 0x2f, 0x99, 0x5f, + 0x3b, 0x34, 0xf3, 0xb2, 0x71, 0x4e, 0x77, 0x3e, 0x73, 0x4a, 0xbc, 0xc8, 0x90, 0xd1, 0x18, 0xe3, + 0x14, 0x7d, 0xba, 0x38, 0xeb, 0x24, 0x76, 0x23, 0xaf, 0x45, 0xff, 0x8b, 0xe5, 0xa3, 0x16, 0xe7, + 0x9c, 0x06, 0x61, 0x13, 0x0f, 0x05, 0x50, 0xa1, 0x8b, 0x2f, 0x1e, 0xef, 0x63, 0xfc, 0x2f, 0x1c, + 0x8e, 0x7f, 0x31, 0xa8, 0x74, 0x5d, 0xeb, 0xd1, 0xa7, 0xff, 0x62, 0xcc, 0xc9, 0xa0, 0xcf, 0x5b, + 0x30, 0x2e, 0x84, 0x03, 0x26, 0x7c, 0x40, 0x6f, 0x6c, 0x7a, 0x09, 0xf1, 0xbd, 0x38, 0x19, 0xaf, + 0x30, 0x1e, 0xa6, 0x7a, 0x9b, 0x5b, 0xf3, 0x51, 0xd8, 0x6e, 0x5d, 0xf1, 0x82, 0xfa, 0xcc, 0x39, + 0x41, 0x69, 0x7c, 0xb6, 0x4b, 0xc7, 0xb8, 0x2b, 0x49, 0xf4, 0x65, 0x0b, 0xce, 0x06, 0x4e, 0x93, + 0xc4, 0x2d, 0x87, 0x7e, 0x5a, 0x0e, 0x9e, 0xf1, 0x1d, 0x77, 0x8b, 0x71, 0xd4, 0x7f, 0x6f, 0x1c, + 0xd9, 0x82, 0xa3, 0xb3, 0x57, 0xbb, 0x76, 0x8d, 0xf7, 0x20, 0x8b, 0xbe, 0x6e, 0xc1, 0x58, 0x18, + 0xb5, 0x36, 0x9d, 0x80, 0xd4, 0x25, 0x34, 0x1e, 0x1f, 0x60, 0x4b, 0xef, 0x43, 0x87, 0xfb, 0x44, + 0xcb, 0xd9, 0x6e, 0x97, 0xc2, 0xc0, 0x4b, 0xc2, 0x68, 0x95, 0x24, 0x89, 0x17, 0x34, 0xe2, 0x99, + 0xd3, 0x77, 0x76, 0x27, 0xc6, 0x3a, 0xb0, 0x70, 0x27, 0x3f, 0xe8, 0xe7, 0x60, 0x30, 0xde, 0x09, + 0xdc, 0x1b, 0x5e, 0x50, 0x0f, 0x6f, 0xc5, 0xe3, 0xd5, 0x22, 0x96, 0xef, 0xaa, 0xea, 0x50, 0x2c, + 0x40, 0x4d, 0x00, 0x9b, 0xd4, 0xf2, 0x3f, 0x9c, 0x9e, 0x4a, 0xb5, 0xa2, 0x3f, 0x9c, 0x9e, 0x4c, + 0x7b, 0x90, 0x45, 0xbf, 0x64, 0xc1, 0x70, 0xec, 0x35, 0x02, 0x27, 0x69, 0x47, 0xe4, 0x0a, 0xd9, + 0x89, 0xc7, 0x81, 0x31, 0x72, 0xf9, 0x90, 0xa3, 0x62, 0x74, 0x39, 0x73, 0x5a, 0xf0, 0x38, 0x6c, + 0xb6, 0xc6, 0x38, 0x4d, 0x37, 0x6f, 0xa1, 0xe9, 0x69, 0x3d, 0x58, 0xec, 0x42, 0xd3, 0x93, 0xba, + 0x2b, 0x49, 0xf4, 0x33, 0x70, 0x82, 0x37, 0xa9, 0x91, 0x8d, 0xc7, 0x87, 0x98, 0xa0, 0x3d, 0x75, + 0x67, 0x77, 0xe2, 0xc4, 0x6a, 0x06, 0x86, 0x3b, 0xb0, 0xd1, 0xab, 0x30, 0xd1, 0x22, 0x51, 0xd3, + 0x4b, 0x96, 0x03, 0x7f, 0x47, 0x8a, 0x6f, 0x37, 0x6c, 0x91, 0xba, 0x60, 0x27, 0x1e, 0x1f, 0x3e, + 0x67, 0x3d, 0x59, 0x9d, 0x79, 0x9b, 0x60, 0x73, 0x62, 0x65, 0x6f, 0x74, 0xbc, 0x5f, 0x7f, 0xe8, + 0x0f, 0x2c, 0x38, 0x6b, 0x48, 0xd9, 0x55, 0x12, 0x6d, 0x7b, 0x2e, 0x99, 0x76, 0xdd, 0xb0, 0x1d, + 0x24, 0xf1, 0xf8, 0x08, 0x1b, 0xc6, 0xf5, 0xa3, 0x90, 0xf9, 0x69, 0x52, 0x7a, 0x5e, 0x76, 0x45, + 0x89, 0xf1, 0x1e, 0x9c, 0xda, 0xff, 0xa6, 0x04, 0x27, 0xb2, 0x16, 0x00, 0xfa, 0x07, 0x16, 0x8c, + 0xde, 0xbc, 0x95, 0xac, 0x85, 0x5b, 0x24, 0x88, 0x67, 0x76, 0xa8, 0x9c, 0x66, 0xba, 0x6f, 0xf0, + 0xbc, 0x5b, 0xac, 0xad, 0x31, 0x79, 0x39, 0x4d, 0xe5, 0x42, 0x90, 0x44, 0x3b, 0x33, 0x0f, 0x8b, + 0x77, 0x1a, 0xbd, 0x7c, 0x63, 0xcd, 0x84, 0xe2, 0x2c, 0x53, 0x67, 0x3f, 0x6b, 0xc1, 0xa9, 0xbc, + 0x2e, 0xd0, 0x09, 0x28, 0x6f, 0x91, 0x1d, 0x6e, 0x89, 0x62, 0xfa, 0x13, 0xbd, 0x0c, 0x95, 0x6d, + 0xc7, 0x6f, 0x13, 0x61, 0xa6, 0xcd, 0x1f, 0xee, 0x45, 0x14, 0x67, 0x98, 0xf7, 0xfa, 0xee, 0xd2, + 0xf3, 0x96, 0xfd, 0x47, 0x65, 0x18, 0x34, 0x3e, 0xda, 0x31, 0x98, 0x9e, 0x61, 0xca, 0xf4, 0x5c, + 0x2a, 0x6c, 0xbe, 0x75, 0xb5, 0x3d, 0x6f, 0x65, 0x6c, 0xcf, 0xe5, 0xe2, 0x48, 0xee, 0x69, 0x7c, + 0xa2, 0x04, 0x6a, 0x61, 0x8b, 0x6e, 0x43, 0xa8, 0x0d, 0xd3, 0x57, 0xc4, 0x27, 0x5c, 0x96, 0xdd, + 0xcd, 0x0c, 0xdf, 0xd9, 0x9d, 0xa8, 0xa9, 0xbf, 0x58, 0x13, 0xb2, 0xbf, 0x6b, 0xc1, 0x29, 0x83, + 0xc7, 0xd9, 0x30, 0xa8, 0x7b, 0xec, 0xd3, 0x9e, 0x83, 0xbe, 0x64, 0xa7, 0x25, 0xb7, 0x3a, 0x6a, + 0xa4, 0xd6, 0x76, 0x5a, 0x04, 0x33, 0x08, 0xdd, 0xb1, 0x34, 0x49, 0x1c, 0x3b, 0x0d, 0x92, 0xdd, + 0xdc, 0x2c, 0xf1, 0x66, 0x2c, 0xe1, 0x28, 0x02, 0xe4, 0x3b, 0x71, 0xb2, 0x16, 0x39, 0x41, 0xcc, + 0xba, 0x5f, 0xf3, 0x9a, 0x44, 0x0c, 0xf0, 0x5f, 0xeb, 0x6d, 0xc6, 0xd0, 0x27, 0x66, 0x1e, 0xba, + 0xb3, 0x3b, 0x81, 0x16, 0x3b, 0x7a, 0xc2, 0x39, 0xbd, 0xdb, 0x5f, 0xb6, 0xe0, 0xa1, 0x7c, 0x01, + 0x83, 0x9e, 0x80, 0x7e, 0xbe, 0xcf, 0x15, 0x6f, 0xa7, 0x3f, 0x09, 0x6b, 0xc5, 0x02, 0x8a, 0xa6, + 0xa0, 0xa6, 0x14, 0x9e, 0x78, 0xc7, 0x31, 0x81, 0x5a, 0xd3, 0x5a, 0x52, 0xe3, 0xd0, 0x41, 0xa3, + 0x7f, 0x84, 0x09, 0xaa, 0x06, 0x8d, 0x6d, 0x0c, 0x19, 0xc4, 0xfe, 0x8e, 0x05, 0x3f, 0xde, 0x8b, + 0xd8, 0x3b, 0x3a, 0x1e, 0x57, 0xe1, 0x74, 0x9d, 0x6c, 0x38, 0x6d, 0x3f, 0x49, 0x53, 0x14, 0x4c, + 0x3f, 0x2a, 0x1e, 0x3e, 0x3d, 0x97, 0x87, 0x84, 0xf3, 0x9f, 0xb5, 0xff, 0xb3, 0x05, 0xa3, 0xc6, + 0x6b, 0x1d, 0xc3, 0xd6, 0x29, 0x48, 0x6f, 0x9d, 0x16, 0x0a, 0x5b, 0xa6, 0x5d, 0xf6, 0x4e, 0x9f, + 0xb7, 0xe0, 0xac, 0x81, 0xb5, 0xe4, 0x24, 0xee, 0xe6, 0x85, 0xdb, 0xad, 0x88, 0xc4, 0x31, 0x9d, + 0x52, 0x8f, 0x1a, 0xe2, 0x78, 0x66, 0x50, 0xf4, 0x50, 0xbe, 0x42, 0x76, 0xb8, 0x6c, 0x7e, 0x0a, + 0xaa, 0x7c, 0xcd, 0x85, 0x91, 0xf8, 0x48, 0xea, 0xdd, 0x96, 0x45, 0x3b, 0x56, 0x18, 0xc8, 0x86, + 0x7e, 0x26, 0x73, 0xa9, 0x0c, 0xa2, 0x66, 0x02, 0xd0, 0xef, 0x7e, 0x9d, 0xb5, 0x60, 0x01, 0xb1, + 0xe3, 0x14, 0x3b, 0x2b, 0x11, 0x61, 0xf3, 0xa1, 0x7e, 0xd1, 0x23, 0x7e, 0x3d, 0xa6, 0xdb, 0x3a, + 0x27, 0x08, 0xc2, 0x44, 0xec, 0xd0, 0x8c, 0x6d, 0xdd, 0xb4, 0x6e, 0xc6, 0x26, 0x0e, 0x25, 0xea, + 0x3b, 0xeb, 0xc4, 0xe7, 0x23, 0x2a, 0x88, 0x2e, 0xb2, 0x16, 0x2c, 0x20, 0xf6, 0x9d, 0x12, 0xdb, + 0x40, 0x2a, 0x89, 0x46, 0x8e, 0xc3, 0xfb, 0x10, 0xa5, 0x54, 0xc0, 0x4a, 0x71, 0xf2, 0x98, 0x74, + 0xf7, 0x40, 0xbc, 0x96, 0xd1, 0x02, 0xb8, 0x50, 0xaa, 0x7b, 0x7b, 0x21, 0x3e, 0x5e, 0x86, 0x89, + 0xf4, 0x03, 0x1d, 0x4a, 0x84, 0x6e, 0x79, 0x0d, 0x42, 0x59, 0x7f, 0x94, 0x81, 0x8f, 0x4d, 0xbc, + 0x2e, 0x72, 0xb8, 0x74, 0x94, 0x72, 0xd8, 0x54, 0x13, 0xe5, 0x7d, 0xd4, 0xc4, 0x13, 0x6a, 0xd4, + 0xfb, 0x32, 0x32, 0x2f, 0xad, 0x2a, 0xcf, 0x41, 0x5f, 0x9c, 0x90, 0xd6, 0x78, 0x25, 0x2d, 0x66, + 0x57, 0x13, 0xd2, 0xc2, 0x0c, 0x82, 0xde, 0x03, 0xa3, 0x89, 0x13, 0x35, 0x48, 0x12, 0x91, 0x6d, + 0x8f, 0xf9, 0x2e, 0xd9, 0x7e, 0xb6, 0x36, 0x73, 0x92, 0x5a, 0x5d, 0x6b, 0x0c, 0x84, 0x25, 0x08, + 0x67, 0x71, 0xed, 0xff, 0x5e, 0x82, 0x87, 0xd3, 0x9f, 0x40, 0x2b, 0xc6, 0xf7, 0xa5, 0x14, 0xe3, + 0x3b, 0x4c, 0xc5, 0x78, 0x77, 0x77, 0xe2, 0xad, 0x5d, 0x1e, 0xfb, 0xa1, 0xd1, 0x9b, 0x68, 0x3e, + 0xf3, 0x11, 0xa6, 0xd2, 0x1f, 0xe1, 0xee, 0xee, 0xc4, 0xa3, 0x5d, 0xde, 0x31, 0xf3, 0x95, 0x9e, + 0x80, 0xfe, 0x88, 0x38, 0x71, 0x18, 0x88, 0xef, 0xa4, 0xbe, 0x26, 0x66, 0xad, 0x58, 0x40, 0xed, + 0x6f, 0xd7, 0xb2, 0x83, 0x3d, 0xcf, 0xfd, 0xb1, 0x61, 0x84, 0x3c, 0xe8, 0x63, 0xbb, 0x36, 0x2e, + 0x59, 0xae, 0x1c, 0x6e, 0x15, 0x52, 0x2d, 0xa2, 0xba, 0x9e, 0xa9, 0xd2, 0xaf, 0x46, 0x9b, 0x30, + 0x23, 0x81, 0x6e, 0x43, 0xd5, 0x95, 0x9b, 0xa9, 0x52, 0x11, 0x6e, 0x47, 0xb1, 0x95, 0xd2, 0x14, + 0x87, 0xa8, 0xb8, 0x57, 0x3b, 0x30, 0x45, 0x0d, 0x11, 0x28, 0x37, 0xbc, 0x44, 0x7c, 0xd6, 0x43, + 0x6e, 0x97, 0xe7, 0x3d, 0xe3, 0x15, 0x07, 0xa8, 0x0e, 0x9a, 0xf7, 0x12, 0x4c, 0xfb, 0x47, 0x9f, + 0xb6, 0x60, 0x30, 0x76, 0x9b, 0x2b, 0x51, 0xb8, 0xed, 0xd5, 0x49, 0x24, 0x6c, 0xcc, 0x43, 0x4a, + 0xb6, 0xd5, 0xd9, 0x25, 0xd9, 0xa1, 0xa6, 0xcb, 0xdd, 0x17, 0x1a, 0x82, 0x4d, 0xba, 0x74, 0xef, + 0xf5, 0xb0, 0x78, 0xf7, 0x39, 0xe2, 0xb2, 0x15, 0x27, 0xf7, 0xcc, 0x6c, 0xa6, 0x1c, 0xda, 0xe6, + 0x9e, 0x6b, 0xbb, 0x5b, 0x74, 0xbd, 0x69, 0x86, 0xde, 0x7a, 0x67, 0x77, 0xe2, 0xe1, 0xd9, 0x7c, + 0x9a, 0xb8, 0x1b, 0x33, 0x6c, 0xc0, 0x5a, 0x6d, 0xdf, 0xc7, 0xe4, 0xd5, 0x36, 0x61, 0x1e, 0xb1, + 0x02, 0x06, 0x6c, 0x45, 0x77, 0x98, 0x19, 0x30, 0x03, 0x82, 0x4d, 0xba, 0xe8, 0x55, 0xe8, 0x6f, + 0x3a, 0x49, 0xe4, 0xdd, 0x16, 0x6e, 0xb0, 0x43, 0xee, 0x82, 0x96, 0x58, 0x5f, 0x9a, 0x38, 0x53, + 0xf4, 0xbc, 0x11, 0x0b, 0x42, 0xa8, 0x09, 0x95, 0x26, 0x89, 0x1a, 0x64, 0xbc, 0x5a, 0x84, 0xcb, + 0x7f, 0x89, 0x76, 0xa5, 0x09, 0xd6, 0xa8, 0x71, 0xc5, 0xda, 0x30, 0xa7, 0x82, 0x5e, 0x86, 0x6a, + 0x4c, 0x7c, 0xe2, 0x52, 0xf3, 0xa8, 0xc6, 0x28, 0xbe, 0xb3, 0x47, 0x53, 0x91, 0xda, 0x25, 0xab, + 0xe2, 0x51, 0xbe, 0xc0, 0xe4, 0x3f, 0xac, 0xba, 0xa4, 0x03, 0xd8, 0xf2, 0xdb, 0x0d, 0x2f, 0x18, + 0x87, 0x22, 0x06, 0x70, 0x85, 0xf5, 0x95, 0x19, 0x40, 0xde, 0x88, 0x05, 0x21, 0xfb, 0xbf, 0x5a, + 0x80, 0xd2, 0x42, 0xed, 0x18, 0x6c, 0xe2, 0x57, 0xd3, 0x36, 0xf1, 0x62, 0x91, 0x46, 0x4b, 0x17, + 0xb3, 0xf8, 0xb7, 0x6a, 0x90, 0x51, 0x07, 0x57, 0x49, 0x9c, 0x90, 0xfa, 0x9b, 0x22, 0xfc, 0x4d, + 0x11, 0xfe, 0xa6, 0x08, 0x57, 0x22, 0x7c, 0x3d, 0x23, 0xc2, 0xdf, 0x6b, 0xac, 0x7a, 0x7d, 0xbe, + 0xfe, 0x8a, 0x3a, 0x80, 0x37, 0x39, 0x30, 0x10, 0xa8, 0x24, 0xb8, 0xbc, 0xba, 0x7c, 0x35, 0x57, + 0x66, 0xbf, 0x92, 0x96, 0xd9, 0x87, 0x25, 0xf1, 0xff, 0x83, 0x94, 0xfe, 0x03, 0x0b, 0xde, 0x96, + 0x96, 0x5e, 0x72, 0xe6, 0x2c, 0x34, 0x82, 0x30, 0x22, 0x73, 0xde, 0xc6, 0x06, 0x89, 0x48, 0xe0, + 0x92, 0x58, 0xf9, 0x76, 0xac, 0x6e, 0xbe, 0x1d, 0xf4, 0x2c, 0x0c, 0xdd, 0x8c, 0xc3, 0x60, 0x25, + 0xf4, 0x02, 0x21, 0x82, 0xe8, 0x8e, 0xe3, 0xc4, 0x9d, 0xdd, 0x89, 0x21, 0x3a, 0xa2, 0xb2, 0x1d, + 0xa7, 0xb0, 0xd0, 0x2c, 0x8c, 0xdd, 0x7c, 0x75, 0xc5, 0x49, 0x0c, 0x6f, 0x82, 0xdc, 0xf7, 0xb3, + 0xf3, 0xa8, 0xcb, 0x2f, 0x66, 0x80, 0xb8, 0x13, 0xdf, 0xfe, 0xbb, 0x25, 0x38, 0x93, 0x79, 0x91, + 0xd0, 0xf7, 0xc3, 0x76, 0x42, 0xf7, 0x44, 0xe8, 0xab, 0x16, 0x9c, 0x68, 0xa6, 0x1d, 0x16, 0xb1, + 0x70, 0x77, 0xbf, 0xbf, 0x30, 0x1d, 0x91, 0xf1, 0x88, 0xcc, 0x8c, 0x8b, 0x11, 0x3a, 0x91, 0x01, + 0xc4, 0xb8, 0x83, 0x17, 0xf4, 0x32, 0xd4, 0x9a, 0xce, 0xed, 0x6b, 0xad, 0xba, 0x93, 0xc8, 0xed, + 0x68, 0x77, 0x2f, 0x42, 0x3b, 0xf1, 0xfc, 0x49, 0x1e, 0xb9, 0x31, 0xb9, 0x10, 0x24, 0xcb, 0xd1, + 0x6a, 0x12, 0x79, 0x41, 0x83, 0x3b, 0x39, 0x97, 0x64, 0x37, 0x58, 0xf7, 0x68, 0x7f, 0xc5, 0xca, + 0x2a, 0x29, 0x35, 0x3a, 0x91, 0x93, 0x90, 0xc6, 0x0e, 0xfa, 0x08, 0x54, 0xe8, 0xbe, 0x51, 0x8e, + 0xca, 0x8d, 0x22, 0x35, 0xa7, 0xf1, 0x25, 0xb4, 0x12, 0xa5, 0xff, 0x62, 0xcc, 0x89, 0xda, 0x5f, + 0xad, 0x65, 0x8d, 0x05, 0x76, 0x36, 0x7f, 0x1e, 0xa0, 0x11, 0xae, 0x91, 0x66, 0xcb, 0xa7, 0xc3, + 0x62, 0xb1, 0x03, 0x1e, 0xe5, 0x2a, 0x99, 0x57, 0x10, 0x6c, 0x60, 0xa1, 0x5f, 0xb6, 0x00, 0x1a, + 0x72, 0xce, 0x4b, 0x43, 0xe0, 0x5a, 0x91, 0xaf, 0xa3, 0x57, 0x94, 0xe6, 0x45, 0x11, 0xc4, 0x06, + 0x71, 0xf4, 0x0b, 0x16, 0x54, 0x13, 0xc9, 0x3e, 0x57, 0x8d, 0x6b, 0x45, 0x72, 0x22, 0x5f, 0x5a, + 0xdb, 0x44, 0x6a, 0x48, 0x14, 0x5d, 0xf4, 0x8b, 0x16, 0x40, 0xbc, 0x13, 0xb8, 0x2b, 0xa1, 0xef, + 0xb9, 0x3b, 0x42, 0x63, 0x5e, 0x2f, 0xd4, 0x9d, 0xa3, 0x7a, 0x9f, 0x19, 0xa1, 0xa3, 0xa1, 0xff, + 0x63, 0x83, 0x32, 0xfa, 0x18, 0x54, 0x63, 0x31, 0xdd, 0x84, 0x8e, 0x5c, 0x2b, 0xd6, 0xa9, 0xc4, + 0xfb, 0x16, 0xe2, 0x55, 0xfc, 0xc3, 0x8a, 0x26, 0xfa, 0xdb, 0x16, 0x8c, 0xb6, 0xd2, 0x6e, 0x42, + 0xa1, 0x0e, 0x8b, 0x93, 0x01, 0x19, 0x37, 0x24, 0xf7, 0xb6, 0x64, 0x1a, 0x71, 0x96, 0x0b, 0x2a, + 0x01, 0xf5, 0x0c, 0x5e, 0x6e, 0x71, 0x97, 0xe5, 0x80, 0x96, 0x80, 0xf3, 0x59, 0x20, 0xee, 0xc4, + 0x47, 0x2b, 0x70, 0x8a, 0x72, 0xb7, 0xc3, 0xcd, 0x4f, 0xa9, 0x5e, 0x62, 0xa6, 0x0c, 0xab, 0x33, + 0x8f, 0x88, 0x19, 0xc2, 0xce, 0x3a, 0xb2, 0x38, 0x38, 0xf7, 0x49, 0xf4, 0x47, 0x16, 0x3c, 0xe2, + 0x31, 0x35, 0x60, 0x3a, 0xec, 0xb5, 0x46, 0x10, 0x07, 0xed, 0xa4, 0x50, 0x59, 0xd1, 0x4d, 0xfd, + 0xcc, 0xfc, 0xb8, 0x78, 0x83, 0x47, 0x16, 0xf6, 0x60, 0x09, 0xef, 0xc9, 0x30, 0xfa, 0x29, 0x18, + 0x96, 0xeb, 0x62, 0x85, 0x8a, 0x60, 0xa6, 0x68, 0x6b, 0x33, 0x63, 0x77, 0x76, 0x27, 0x86, 0xd7, + 0x4c, 0x00, 0x4e, 0xe3, 0xd9, 0xff, 0xb6, 0x9c, 0x3a, 0x25, 0x52, 0x3e, 0x4c, 0x26, 0x6e, 0x5c, + 0xe9, 0xff, 0x91, 0xd2, 0xb3, 0x50, 0x71, 0xa3, 0xbc, 0x4b, 0x5a, 0xdc, 0xa8, 0xa6, 0x18, 0x1b, + 0xc4, 0xa9, 0x51, 0x3a, 0xe6, 0x64, 0x3d, 0xa5, 0x42, 0x02, 0xbe, 0x5c, 0x24, 0x4b, 0x9d, 0x67, + 0x7a, 0x67, 0x04, 0x6b, 0x63, 0x1d, 0x20, 0xdc, 0xc9, 0x12, 0xfa, 0x28, 0xd4, 0x22, 0x15, 0xd9, + 0x52, 0x2e, 0x62, 0xab, 0x26, 0xa7, 0x8d, 0x60, 0x47, 0x1d, 0x00, 0xe9, 0x18, 0x16, 0x4d, 0xd1, + 0xfe, 0xc3, 0xf4, 0xc1, 0x98, 0x21, 0x3b, 0x7a, 0x38, 0xf4, 0xfb, 0x82, 0x05, 0x83, 0x51, 0xe8, + 0xfb, 0x5e, 0xd0, 0xa0, 0x72, 0x4e, 0x28, 0xeb, 0x0f, 0x1e, 0x89, 0xbe, 0x14, 0x02, 0x8d, 0x59, + 0xd6, 0x58, 0xd3, 0xc4, 0x26, 0x03, 0xf6, 0x9f, 0x59, 0x30, 0xde, 0x4d, 0x1e, 0x23, 0x02, 0x6f, + 0x95, 0xc2, 0x46, 0x0d, 0xc5, 0x72, 0x30, 0x47, 0x7c, 0xa2, 0xdc, 0xe6, 0xd5, 0x99, 0xc7, 0xc5, + 0x6b, 0xbe, 0x75, 0xa5, 0x3b, 0x2a, 0xde, 0xab, 0x1f, 0xf4, 0x12, 0x9c, 0x30, 0xde, 0x2b, 0x56, + 0x03, 0x53, 0x9b, 0x99, 0xa4, 0x06, 0xd0, 0x74, 0x06, 0x76, 0x77, 0x77, 0xe2, 0xa1, 0x6c, 0x9b, + 0x50, 0x18, 0x1d, 0xfd, 0xd8, 0xbf, 0x51, 0xca, 0x7e, 0x2d, 0xa5, 0xeb, 0xdf, 0xb0, 0x3a, 0xbc, + 0x09, 0xef, 0x3f, 0x0a, 0xfd, 0xca, 0xfc, 0x0e, 0x2a, 0x0c, 0xa3, 0x3b, 0xce, 0x7d, 0x3c, 0xb6, + 0xb7, 0xff, 0x5d, 0x1f, 0xec, 0xc1, 0x59, 0x0f, 0xc6, 0xfb, 0x81, 0xcf, 0x51, 0x3f, 0x67, 0xa9, + 0x03, 0x33, 0xbe, 0x86, 0xeb, 0x47, 0x35, 0xf6, 0x7c, 0xff, 0x14, 0xf3, 0xd0, 0x11, 0xe5, 0x45, + 0x4f, 0x1f, 0xcd, 0xa1, 0xaf, 0x59, 0xe9, 0x23, 0x3f, 0x1e, 0xd4, 0xe8, 0x1d, 0x19, 0x4f, 0xc6, + 0x39, 0x22, 0x67, 0x4c, 0x9f, 0x3e, 0x75, 0x3b, 0x61, 0x9c, 0x04, 0xd8, 0xf0, 0x02, 0xc7, 0xf7, + 0x5e, 0xa3, 0xbb, 0xa3, 0x0a, 0x53, 0xf0, 0xcc, 0x62, 0xba, 0xa8, 0x5a, 0xb1, 0x81, 0x71, 0xf6, + 0xaf, 0xc3, 0xa0, 0xf1, 0xe6, 0x39, 0x11, 0x2f, 0xa7, 0xcc, 0x88, 0x97, 0x9a, 0x11, 0xa8, 0x72, + 0xf6, 0xbd, 0x70, 0x22, 0xcb, 0xe0, 0x41, 0x9e, 0xb7, 0xff, 0xf7, 0x40, 0xf6, 0x0c, 0x6e, 0x8d, + 0x44, 0x4d, 0xca, 0xda, 0x9b, 0x8e, 0xad, 0x37, 0x1d, 0x5b, 0x6f, 0x3a, 0xb6, 0xcc, 0xb3, 0x09, + 0xe1, 0xb4, 0x19, 0x38, 0x26, 0xa7, 0x4d, 0xca, 0x0d, 0x55, 0x2d, 0xdc, 0x0d, 0x65, 0x7f, 0xba, + 0xc3, 0x73, 0xbf, 0x16, 0x11, 0x82, 0x42, 0xa8, 0x04, 0x61, 0x9d, 0x48, 0x1b, 0xf7, 0x72, 0x31, + 0x06, 0xdb, 0xd5, 0xb0, 0x6e, 0x84, 0x8b, 0xd3, 0x7f, 0x31, 0xe6, 0x74, 0xec, 0x3b, 0x15, 0x48, + 0x99, 0x93, 0xfc, 0xbb, 0xbf, 0x1d, 0x06, 0x22, 0xd2, 0x0a, 0xaf, 0xe1, 0x45, 0xa1, 0xcb, 0x74, + 0x46, 0x09, 0x6f, 0xc6, 0x12, 0x4e, 0x75, 0x5e, 0xcb, 0x49, 0x36, 0x85, 0x32, 0x53, 0x3a, 0x6f, + 0xc5, 0x49, 0x36, 0x31, 0x83, 0xa0, 0xf7, 0xc2, 0x48, 0x92, 0x3a, 0x0a, 0x17, 0x47, 0xbe, 0x0f, + 0x09, 0xdc, 0x91, 0xf4, 0x41, 0x39, 0xce, 0x60, 0xa3, 0x57, 0xa1, 0x6f, 0x93, 0xf8, 0x4d, 0xf1, + 0xe9, 0x57, 0x8b, 0xd3, 0x35, 0xec, 0x5d, 0x2f, 0x11, 0xbf, 0xc9, 0x25, 0x21, 0xfd, 0x85, 0x19, + 0x29, 0x3a, 0xef, 0x6b, 0x5b, 0xed, 0x38, 0x09, 0x9b, 0xde, 0x6b, 0xd2, 0xd3, 0xf9, 0xfe, 0x82, + 0x09, 0x5f, 0x91, 0xfd, 0x73, 0x97, 0x92, 0xfa, 0x8b, 0x35, 0x65, 0xc6, 0x47, 0xdd, 0x8b, 0xd8, + 0x94, 0xd9, 0x11, 0x0e, 0xcb, 0xa2, 0xf9, 0x98, 0x93, 0xfd, 0x73, 0x3e, 0xd4, 0x5f, 0xac, 0x29, + 0xa3, 0x1d, 0xb5, 0xfe, 0x06, 0x19, 0x0f, 0xd7, 0x0a, 0xe6, 0x81, 0xaf, 0xbd, 0xdc, 0x75, 0xf8, + 0x38, 0x54, 0xdc, 0x4d, 0x27, 0x4a, 0xc6, 0x87, 0xd8, 0xa4, 0x51, 0xb3, 0x78, 0x96, 0x36, 0x62, + 0x0e, 0x43, 0x8f, 0x42, 0x39, 0x22, 0x1b, 0x2c, 0x3a, 0xd9, 0x88, 0x8b, 0xc2, 0x64, 0x03, 0xd3, + 0x76, 0xfb, 0xd7, 0x4a, 0x69, 0xb3, 0x2d, 0xfd, 0xde, 0x7c, 0xb6, 0xbb, 0xed, 0x28, 0x96, 0xee, + 0x2f, 0x63, 0xb6, 0xb3, 0x66, 0x2c, 0xe1, 0xe8, 0x13, 0x16, 0x0c, 0xdc, 0x8c, 0xc3, 0x20, 0x20, + 0x89, 0x50, 0x91, 0xd7, 0x0b, 0x1e, 0x8a, 0xcb, 0xbc, 0x77, 0xcd, 0x83, 0x68, 0xc0, 0x92, 0x2e, + 0x65, 0x97, 0xdc, 0x76, 0xfd, 0x76, 0xbd, 0x23, 0xd4, 0xe5, 0x02, 0x6f, 0xc6, 0x12, 0x4e, 0x51, + 0xbd, 0x80, 0xa3, 0xf6, 0xa5, 0x51, 0x17, 0x02, 0x81, 0x2a, 0xe0, 0xf6, 0x0f, 0x06, 0xe0, 0x74, + 0xee, 0xe2, 0xa0, 0x06, 0x15, 0x33, 0x59, 0x2e, 0x7a, 0x3e, 0x91, 0x41, 0x5e, 0xcc, 0xa0, 0xba, + 0xae, 0x5a, 0xb1, 0x81, 0x81, 0x7e, 0x1e, 0xa0, 0xe5, 0x44, 0x4e, 0x93, 0x28, 0xf7, 0xf4, 0xa1, + 0xed, 0x16, 0xca, 0xc7, 0x8a, 0xec, 0x53, 0x6f, 0xd1, 0x55, 0x53, 0x8c, 0x0d, 0x92, 0xe8, 0x39, + 0x18, 0x8c, 0x88, 0x4f, 0x9c, 0x98, 0x05, 0xb7, 0x67, 0x33, 0x75, 0xb0, 0x06, 0x61, 0x13, 0x0f, + 0x3d, 0xa1, 0xe2, 0xe1, 0x32, 0x71, 0x41, 0xe9, 0x98, 0x38, 0xf4, 0xba, 0x05, 0x23, 0x1b, 0x9e, + 0x4f, 0x34, 0x75, 0x91, 0x57, 0xb3, 0x7c, 0xf8, 0x97, 0xbc, 0x68, 0xf6, 0xab, 0x25, 0x64, 0xaa, + 0x39, 0xc6, 0x19, 0xf2, 0xf4, 0x33, 0x6f, 0x93, 0x88, 0x89, 0xd6, 0xfe, 0xf4, 0x67, 0xbe, 0xce, + 0x9b, 0xb1, 0x84, 0xa3, 0x69, 0x18, 0x6d, 0x39, 0x71, 0x3c, 0x1b, 0x91, 0x3a, 0x09, 0x12, 0xcf, + 0xf1, 0x79, 0xd6, 0x4b, 0x55, 0x07, 0x8b, 0xaf, 0xa4, 0xc1, 0x38, 0x8b, 0x8f, 0x3e, 0x00, 0x0f, + 0x73, 0xff, 0xcf, 0x92, 0x17, 0xc7, 0x5e, 0xd0, 0xd0, 0xd3, 0x40, 0xb8, 0xc1, 0x26, 0x44, 0x57, + 0x0f, 0x2f, 0xe4, 0xa3, 0xe1, 0x6e, 0xcf, 0xa3, 0xa7, 0xa0, 0x1a, 0x6f, 0x79, 0xad, 0xd9, 0xa8, + 0x1e, 0xb3, 0xb3, 0x9f, 0xaa, 0x76, 0xba, 0xae, 0x8a, 0x76, 0xac, 0x30, 0x90, 0x0b, 0x43, 0xfc, + 0x93, 0xf0, 0x80, 0x3e, 0x21, 0x1f, 0x9f, 0xee, 0xaa, 0xa6, 0x45, 0x12, 0xe7, 0x24, 0x76, 0x6e, + 0x5d, 0x90, 0x27, 0x51, 0xfc, 0xe0, 0xe4, 0xba, 0xd1, 0x0d, 0x4e, 0x75, 0x9a, 0xde, 0xb1, 0x0d, + 0xf6, 0xb0, 0x63, 0x7b, 0x0e, 0x06, 0xb7, 0xda, 0xeb, 0x44, 0x8c, 0xbc, 0x10, 0x5b, 0x6a, 0xf6, + 0x5d, 0xd1, 0x20, 0x6c, 0xe2, 0xb1, 0x58, 0xca, 0x96, 0x27, 0xfe, 0xc5, 0xe3, 0xc3, 0x46, 0x2c, + 0xe5, 0xca, 0x82, 0x6c, 0xc6, 0x26, 0x0e, 0x65, 0x8d, 0x8e, 0xc5, 0x1a, 0x89, 0x59, 0xaa, 0x04, + 0x1d, 0x2e, 0xc5, 0xda, 0xaa, 0x04, 0x60, 0x8d, 0x63, 0xff, 0x4a, 0x29, 0xed, 0xc5, 0x30, 0x05, + 0x0e, 0x8a, 0xa9, 0x58, 0x49, 0xae, 0x3b, 0x91, 0x34, 0x3e, 0x0e, 0x99, 0x68, 0x24, 0xfa, 0xbd, + 0xee, 0x44, 0xa6, 0x80, 0x62, 0x04, 0xb0, 0xa4, 0x84, 0x6e, 0x42, 0x5f, 0xe2, 0x3b, 0x05, 0x65, + 0x26, 0x1a, 0x14, 0xb5, 0x53, 0x69, 0x71, 0x3a, 0xc6, 0x8c, 0x06, 0x7a, 0x84, 0xee, 0xa4, 0xd6, + 0xe5, 0xa9, 0x97, 0xd8, 0xfc, 0xac, 0xc7, 0x98, 0xb5, 0xda, 0x7f, 0x3e, 0x98, 0xa3, 0x23, 0x94, + 0x52, 0x46, 0xe7, 0x01, 0xe8, 0x27, 0x5e, 0x89, 0xc8, 0x86, 0x77, 0x5b, 0x18, 0x45, 0x4a, 0x0e, + 0x5d, 0x55, 0x10, 0x6c, 0x60, 0xc9, 0x67, 0x56, 0xdb, 0x1b, 0xf4, 0x99, 0x52, 0xe7, 0x33, 0x1c, + 0x82, 0x0d, 0x2c, 0xf4, 0x2c, 0xf4, 0x7b, 0x4d, 0xa7, 0xa1, 0x82, 0x72, 0x1f, 0xa1, 0x02, 0x68, + 0x81, 0xb5, 0xdc, 0xdd, 0x9d, 0x18, 0x51, 0x0c, 0xb1, 0x26, 0x2c, 0x70, 0xd1, 0x6f, 0x58, 0x30, + 0xe4, 0x86, 0xcd, 0x66, 0x18, 0xf0, 0xad, 0xac, 0xd8, 0x97, 0xdf, 0x3c, 0x2a, 0x93, 0x65, 0x72, + 0xd6, 0x20, 0xc6, 0x37, 0xe6, 0x2a, 0x85, 0xd2, 0x04, 0xe1, 0x14, 0x57, 0xa6, 0x9c, 0xaa, 0xec, + 0x23, 0xa7, 0x7e, 0xd3, 0x82, 0x31, 0xfe, 0xac, 0xb1, 0xc3, 0x16, 0xd9, 0x82, 0xe1, 0x11, 0xbf, + 0x56, 0x87, 0xd3, 0x41, 0x39, 0x5e, 0x3b, 0xe0, 0xb8, 0x93, 0x49, 0x34, 0x0f, 0x63, 0x1b, 0x61, + 0xe4, 0x12, 0x73, 0x20, 0x84, 0x90, 0x55, 0x1d, 0x5d, 0xcc, 0x22, 0xe0, 0xce, 0x67, 0xd0, 0x75, + 0x78, 0xc8, 0x68, 0x34, 0xc7, 0x81, 0xcb, 0xd9, 0xc7, 0x44, 0x6f, 0x0f, 0x5d, 0xcc, 0xc5, 0xc2, + 0x5d, 0x9e, 0x4e, 0x8b, 0xb4, 0x5a, 0x0f, 0x22, 0xed, 0x15, 0x38, 0xe3, 0x76, 0x8e, 0xcc, 0x76, + 0xdc, 0x5e, 0x8f, 0xb9, 0xd4, 0xad, 0xce, 0xfc, 0x98, 0xe8, 0xe0, 0xcc, 0x6c, 0x37, 0x44, 0xdc, + 0xbd, 0x0f, 0xf4, 0x11, 0xa8, 0x46, 0x84, 0x7d, 0x95, 0x58, 0xa4, 0xce, 0x1d, 0xd2, 0xf3, 0xa0, + 0xad, 0x69, 0xde, 0xad, 0xd6, 0x23, 0xa2, 0x21, 0xc6, 0x8a, 0x22, 0xba, 0x05, 0x03, 0x2d, 0x27, + 0x71, 0x37, 0x45, 0xc2, 0xdc, 0xa1, 0xfd, 0xe4, 0x8a, 0x38, 0x3b, 0xd6, 0x30, 0x52, 0xec, 0x39, + 0x11, 0x2c, 0xa9, 0x51, 0xcb, 0xca, 0x0d, 0x9b, 0xad, 0x30, 0x20, 0x41, 0x22, 0x45, 0xfe, 0x08, + 0x3f, 0x7b, 0x90, 0xad, 0xd8, 0xc0, 0x40, 0x2b, 0x70, 0x8a, 0xf9, 0xe1, 0x6e, 0x78, 0xc9, 0x66, + 0xd8, 0x4e, 0xe4, 0xb6, 0x52, 0xc8, 0x7e, 0x75, 0xfa, 0xb4, 0x98, 0x83, 0x83, 0x73, 0x9f, 0xcc, + 0x2a, 0xab, 0xd1, 0x7b, 0x53, 0x56, 0x27, 0xf6, 0x57, 0x56, 0x67, 0xdf, 0x07, 0x63, 0x1d, 0x42, + 0xe3, 0x40, 0xce, 0xb6, 0x39, 0x78, 0x28, 0x7f, 0x79, 0x1e, 0xc8, 0xe5, 0xf6, 0xcf, 0x33, 0x31, + 0xd7, 0xc6, 0xf6, 0xa3, 0x07, 0xf7, 0xad, 0x03, 0x65, 0x12, 0x6c, 0x0b, 0x6d, 0x75, 0xf1, 0x70, + 0xb3, 0xe4, 0x42, 0xb0, 0xcd, 0xa5, 0x0b, 0xf3, 0x51, 0x5d, 0x08, 0xb6, 0x31, 0xed, 0x1b, 0x7d, + 0xc9, 0x4a, 0x99, 0xcf, 0xdc, 0xe9, 0xfb, 0xa1, 0x23, 0xd9, 0x6f, 0xf5, 0x6c, 0x51, 0xdb, 0xff, + 0xbe, 0x04, 0xe7, 0xf6, 0xeb, 0xa4, 0x87, 0xe1, 0x7b, 0x1c, 0xfa, 0x63, 0x16, 0x45, 0x21, 0xc4, + 0xff, 0x20, 0x5d, 0x15, 0x3c, 0xae, 0xe2, 0x15, 0x2c, 0x40, 0xc8, 0x87, 0x72, 0xd3, 0x69, 0x09, + 0x5f, 0xe0, 0xc2, 0x61, 0x73, 0xd3, 0xe8, 0x7f, 0xc7, 0x5f, 0x72, 0x5a, 0x7c, 0x7a, 0x1a, 0x0d, + 0x98, 0x92, 0x41, 0x09, 0x54, 0x9c, 0x28, 0x72, 0xe4, 0x91, 0xfd, 0x95, 0x62, 0xe8, 0x4d, 0xd3, + 0x2e, 0xf9, 0x89, 0x67, 0xaa, 0x09, 0x73, 0x62, 0xf6, 0xe7, 0x06, 0x52, 0x89, 0x4c, 0x2c, 0x0e, + 0x23, 0x86, 0x7e, 0xe1, 0x02, 0xb4, 0x8a, 0x4e, 0x09, 0xe4, 0x99, 0xc2, 0x6c, 0x77, 0x2d, 0xea, + 0x2d, 0x08, 0x52, 0xe8, 0xb3, 0x16, 0xab, 0x6a, 0x20, 0xb3, 0xc3, 0xc4, 0x9e, 0xf6, 0x68, 0x8a, + 0x2c, 0x98, 0xb5, 0x12, 0x64, 0x23, 0x36, 0xa9, 0x8b, 0xea, 0x24, 0xcc, 0x96, 0xef, 0xac, 0x4e, + 0xc2, 0x6c, 0x73, 0x09, 0x47, 0xb7, 0x73, 0xe2, 0x2d, 0x0a, 0xc8, 0x8c, 0xef, 0x21, 0xc2, 0xe2, + 0x6b, 0x16, 0x8c, 0x79, 0xd9, 0x83, 0x73, 0xb1, 0x03, 0xbc, 0x51, 0x8c, 0xbf, 0xae, 0xf3, 0x5c, + 0x5e, 0x19, 0x0e, 0x1d, 0x20, 0xdc, 0xc9, 0x0c, 0xaa, 0x43, 0x9f, 0x17, 0x6c, 0x84, 0xc2, 0x5c, + 0x9a, 0x39, 0x1c, 0x53, 0x0b, 0xc1, 0x46, 0xa8, 0x57, 0x33, 0xfd, 0x87, 0x59, 0xef, 0x68, 0x11, + 0x4e, 0xc9, 0x5c, 0x96, 0x4b, 0x5e, 0x9c, 0x84, 0xd1, 0xce, 0xa2, 0xd7, 0xf4, 0x12, 0x66, 0xea, + 0x94, 0x67, 0xc6, 0xa9, 0x26, 0xc2, 0x39, 0x70, 0x9c, 0xfb, 0x14, 0x7a, 0x0d, 0x06, 0xe4, 0x61, + 0x75, 0xb5, 0x88, 0xdd, 0x74, 0xe7, 0xfc, 0x57, 0x93, 0x69, 0x55, 0x9c, 0x56, 0x4b, 0x82, 0xf6, + 0xeb, 0x83, 0xd0, 0x79, 0xa6, 0x9e, 0x3e, 0x40, 0xb7, 0x8e, 0xfb, 0x00, 0x9d, 0x6e, 0x8d, 0x62, + 0x7d, 0xf6, 0x5d, 0xc0, 0xdc, 0x16, 0x54, 0xf5, 0xb9, 0xe6, 0x4e, 0xe0, 0x62, 0x46, 0x03, 0x45, + 0xd0, 0xbf, 0x49, 0x1c, 0x3f, 0xd9, 0x2c, 0xe6, 0x08, 0xe6, 0x12, 0xeb, 0x2b, 0x9b, 0x80, 0xc6, + 0x5b, 0xb1, 0xa0, 0x84, 0x6e, 0xc3, 0xc0, 0x26, 0x9f, 0x00, 0x62, 0xb7, 0xb2, 0x74, 0xd8, 0xc1, + 0x4d, 0xcd, 0x2a, 0xfd, 0xb9, 0x45, 0x03, 0x96, 0xe4, 0x58, 0xb0, 0x96, 0x11, 0x4e, 0xc2, 0x97, + 0x6e, 0x71, 0xb9, 0x77, 0xbd, 0xc7, 0x92, 0x7c, 0x18, 0x86, 0x22, 0xe2, 0x86, 0x81, 0xeb, 0xf9, + 0xa4, 0x3e, 0x2d, 0x8f, 0x57, 0x0e, 0x92, 0x72, 0xc5, 0xbc, 0x17, 0xd8, 0xe8, 0x03, 0xa7, 0x7a, + 0x44, 0x9f, 0xb1, 0x60, 0x44, 0xa5, 0x61, 0xd3, 0x0f, 0x42, 0x84, 0x1b, 0x7d, 0xb1, 0xa0, 0xa4, + 0x6f, 0xd6, 0xe7, 0x0c, 0xba, 0xb3, 0x3b, 0x31, 0x92, 0x6e, 0xc3, 0x19, 0xba, 0xe8, 0x25, 0x80, + 0x70, 0x9d, 0x47, 0x64, 0x4d, 0x27, 0xc2, 0xa7, 0x7e, 0x90, 0x57, 0x1d, 0xe1, 0xa9, 0x9b, 0xb2, + 0x07, 0x6c, 0xf4, 0x86, 0xae, 0x00, 0xf0, 0x65, 0xb3, 0xb6, 0xd3, 0x92, 0x5b, 0x1a, 0x99, 0x33, + 0x07, 0xab, 0x0a, 0x72, 0x77, 0x77, 0xa2, 0xd3, 0xc7, 0xc9, 0xc2, 0x4e, 0x8c, 0xc7, 0xd1, 0xcf, + 0xc1, 0x40, 0xdc, 0x6e, 0x36, 0x1d, 0xe5, 0x71, 0x2f, 0x30, 0x19, 0x94, 0xf7, 0x6b, 0x88, 0x22, + 0xde, 0x80, 0x25, 0x45, 0x74, 0x93, 0x0a, 0xd5, 0x58, 0x38, 0x5f, 0xd9, 0x2a, 0xe2, 0x36, 0x01, + 0xf7, 0x3c, 0xbd, 0x4b, 0x9a, 0xf8, 0x38, 0x07, 0xe7, 0xee, 0xee, 0xc4, 0x43, 0xe9, 0xf6, 0xc5, + 0x50, 0xa4, 0x67, 0xe6, 0xf6, 0x89, 0x2e, 0xcb, 0xaa, 0x4c, 0xf4, 0xb5, 0x65, 0xb1, 0x90, 0x27, + 0x75, 0x55, 0x26, 0xd6, 0xdc, 0x7d, 0xcc, 0xcc, 0x87, 0xd1, 0x12, 0x9c, 0x74, 0xc3, 0x20, 0x89, + 0x42, 0xdf, 0xe7, 0x55, 0xc9, 0xf8, 0xee, 0x92, 0x7b, 0xe4, 0xdf, 0x2a, 0xd8, 0x3e, 0x39, 0xdb, + 0x89, 0x82, 0xf3, 0x9e, 0xb3, 0x83, 0xf4, 0xe9, 0x98, 0x18, 0x9c, 0x67, 0x61, 0x88, 0xdc, 0x4e, + 0x48, 0x14, 0x38, 0xfe, 0x35, 0xbc, 0x28, 0x7d, 0xd1, 0x6c, 0x0d, 0x5c, 0x30, 0xda, 0x71, 0x0a, + 0x0b, 0xd9, 0xca, 0xa5, 0x62, 0xa4, 0x1c, 0x73, 0x97, 0x8a, 0x74, 0xa0, 0xd8, 0xdf, 0x2c, 0xa7, + 0x0c, 0xb2, 0xfb, 0x72, 0x16, 0xc7, 0x6a, 0xdb, 0xc8, 0x22, 0x40, 0x0c, 0x20, 0x36, 0x1a, 0x45, + 0x52, 0x56, 0xb5, 0x6d, 0x96, 0x4d, 0x42, 0x38, 0x4d, 0x17, 0x6d, 0x41, 0x65, 0x33, 0x8c, 0x13, + 0xb9, 0xfd, 0x38, 0xe4, 0x4e, 0xe7, 0x52, 0x18, 0x27, 0xcc, 0x8a, 0x50, 0xaf, 0x4d, 0x5b, 0x62, + 0xcc, 0x69, 0xd0, 0x3d, 0x68, 0xbc, 0xe9, 0x44, 0xf5, 0x78, 0x96, 0x15, 0x08, 0xe8, 0x63, 0xe6, + 0x83, 0x32, 0x16, 0x57, 0x35, 0x08, 0x9b, 0x78, 0xf6, 0x7f, 0xb3, 0x52, 0x07, 0x16, 0x37, 0x58, + 0xb4, 0xf7, 0x36, 0x09, 0xa8, 0x34, 0x30, 0xe3, 0xcb, 0x7e, 0x2a, 0x93, 0x3b, 0xfb, 0xb6, 0x6e, + 0xb5, 0xfa, 0x6e, 0xd1, 0x1e, 0x26, 0x59, 0x17, 0x46, 0x28, 0xda, 0xc7, 0xad, 0x74, 0x12, 0x74, + 0xa9, 0x88, 0x7d, 0x89, 0x59, 0x08, 0x60, 0xdf, 0x7c, 0x6a, 0xfb, 0x4b, 0x16, 0x0c, 0xcc, 0x38, + 0xee, 0x56, 0xb8, 0xb1, 0x81, 0x9e, 0x82, 0x6a, 0xbd, 0x1d, 0x99, 0xf9, 0xd8, 0xca, 0xb3, 0x31, + 0x27, 0xda, 0xb1, 0xc2, 0xa0, 0x53, 0x7f, 0xc3, 0x71, 0x65, 0x39, 0x80, 0x32, 0x9f, 0xfa, 0x17, + 0x59, 0x0b, 0x16, 0x10, 0x3a, 0xfc, 0x4d, 0xe7, 0xb6, 0x7c, 0x38, 0x7b, 0x5a, 0xb2, 0xa4, 0x41, + 0xd8, 0xc4, 0xb3, 0xff, 0xb5, 0x05, 0xe3, 0x33, 0x4e, 0xec, 0xb9, 0xd3, 0xed, 0x64, 0x73, 0xc6, + 0x4b, 0xd6, 0xdb, 0xee, 0x16, 0x49, 0x78, 0xd9, 0x08, 0xca, 0x65, 0x3b, 0xa6, 0x2b, 0x50, 0x6d, + 0x07, 0x15, 0x97, 0xd7, 0x44, 0x3b, 0x56, 0x18, 0xe8, 0x35, 0x18, 0x6c, 0x39, 0x71, 0x7c, 0x2b, + 0x8c, 0xea, 0x98, 0x6c, 0x14, 0x53, 0x58, 0x66, 0x95, 0xb8, 0x11, 0x49, 0x30, 0xd9, 0x10, 0x91, + 0x05, 0xba, 0x7f, 0x6c, 0x12, 0xb3, 0x7f, 0xd9, 0x82, 0x53, 0x33, 0xc4, 0x89, 0x48, 0xc4, 0xea, + 0xd0, 0xa8, 0x17, 0x41, 0xaf, 0x42, 0x35, 0xa1, 0x2d, 0x94, 0x23, 0xab, 0x58, 0x8e, 0x58, 0x4c, + 0xc0, 0x9a, 0xe8, 0x1c, 0x2b, 0x32, 0xf6, 0x17, 0x2c, 0x38, 0x93, 0xc7, 0xcb, 0xac, 0x1f, 0xb6, + 0xeb, 0xf7, 0x83, 0xa1, 0xbf, 0x63, 0xc1, 0x10, 0x3b, 0x67, 0x9d, 0x23, 0x89, 0xe3, 0xf9, 0x1d, + 0x35, 0xf0, 0xac, 0x1e, 0x6b, 0xe0, 0x9d, 0x83, 0xbe, 0xcd, 0xb0, 0x49, 0xb2, 0x31, 0x02, 0x97, + 0xc2, 0x26, 0xc1, 0x0c, 0x82, 0x9e, 0xa1, 0x93, 0xd0, 0x0b, 0x12, 0x87, 0x2e, 0x47, 0xe9, 0xfb, + 0x1e, 0xe5, 0x13, 0x50, 0x35, 0x63, 0x13, 0xc7, 0xfe, 0x57, 0x35, 0x18, 0x10, 0x01, 0x2d, 0x3d, + 0x97, 0x31, 0x91, 0x2e, 0x8a, 0x52, 0x57, 0x17, 0x45, 0x0c, 0xfd, 0x2e, 0x2b, 0xc6, 0x29, 0x2c, + 0xe1, 0x2b, 0x85, 0x44, 0x40, 0xf1, 0xfa, 0x9e, 0x9a, 0x2d, 0xfe, 0x1f, 0x0b, 0x52, 0xe8, 0x8b, + 0x16, 0x8c, 0xba, 0x61, 0x10, 0x10, 0x57, 0x9b, 0x69, 0x7d, 0x45, 0x04, 0xba, 0xcc, 0xa6, 0x3b, + 0xd5, 0x87, 0x7c, 0x19, 0x00, 0xce, 0x92, 0x47, 0x2f, 0xc0, 0x30, 0x1f, 0xb3, 0xeb, 0x29, 0x87, + 0xbd, 0x2e, 0x8d, 0x66, 0x02, 0x71, 0x1a, 0x17, 0x4d, 0xf2, 0x83, 0x0f, 0x51, 0x84, 0xac, 0x5f, + 0xfb, 0x35, 0x8d, 0xf2, 0x63, 0x06, 0x06, 0x8a, 0x00, 0x45, 0x64, 0x23, 0x22, 0xf1, 0xa6, 0x08, + 0xf8, 0x61, 0x26, 0xe2, 0xc0, 0xbd, 0x15, 0x20, 0xc0, 0x1d, 0x3d, 0xe1, 0x9c, 0xde, 0xd1, 0x96, + 0xd8, 0x23, 0x57, 0x8b, 0x90, 0xe7, 0xe2, 0x33, 0x77, 0xdd, 0x2a, 0x4f, 0x40, 0x85, 0xa9, 0x2e, + 0x66, 0x9a, 0x96, 0x79, 0xd2, 0x1b, 0x53, 0x6c, 0x98, 0xb7, 0xa3, 0x39, 0x38, 0x91, 0x29, 0xec, + 0x16, 0x0b, 0xc7, 0xba, 0x4a, 0x70, 0xca, 0x94, 0x84, 0x8b, 0x71, 0xc7, 0x13, 0xa6, 0xff, 0x64, + 0x70, 0x1f, 0xff, 0xc9, 0x8e, 0x0a, 0x2b, 0xe5, 0x2e, 0xef, 0x17, 0x0b, 0x19, 0x80, 0x9e, 0x62, + 0x48, 0x3f, 0x9f, 0x89, 0x21, 0x1d, 0x66, 0x0c, 0x5c, 0x2f, 0x86, 0x81, 0x83, 0x07, 0x8c, 0xde, + 0xcf, 0x00, 0xd0, 0xff, 0x65, 0x81, 0xfc, 0xae, 0xb3, 0x8e, 0xbb, 0x49, 0xe8, 0x94, 0x41, 0xef, + 0x85, 0x11, 0xe5, 0x05, 0xe0, 0x26, 0x91, 0xc5, 0x66, 0x8d, 0x8a, 0x06, 0xc0, 0x29, 0x28, 0xce, + 0x60, 0xa3, 0x29, 0xa8, 0xd1, 0x71, 0xe2, 0x8f, 0x72, 0xbd, 0xaf, 0x3c, 0x0d, 0xd3, 0x2b, 0x0b, + 0xe2, 0x29, 0x8d, 0x83, 0x42, 0x18, 0xf3, 0x9d, 0x38, 0x61, 0x1c, 0xac, 0xee, 0x04, 0xee, 0x3d, + 0x96, 0xff, 0x60, 0x59, 0x34, 0x8b, 0xd9, 0x8e, 0x70, 0x67, 0xdf, 0xf6, 0x77, 0xfb, 0x60, 0x38, + 0x25, 0x19, 0x0f, 0x68, 0x30, 0x3c, 0x05, 0x55, 0xa9, 0xc3, 0xb3, 0x75, 0x8e, 0x94, 0xa2, 0x57, + 0x18, 0x54, 0x69, 0xad, 0x6b, 0xad, 0x9a, 0x35, 0x70, 0x0c, 0x85, 0x8b, 0x4d, 0x3c, 0x26, 0x94, + 0x13, 0x3f, 0x9e, 0xf5, 0x3d, 0x12, 0x24, 0x9c, 0xcd, 0x62, 0x84, 0xf2, 0xda, 0xe2, 0xaa, 0xd9, + 0xa9, 0x16, 0xca, 0x19, 0x00, 0xce, 0x92, 0x47, 0x9f, 0xb2, 0x60, 0xd8, 0xb9, 0x15, 0xeb, 0x8a, + 0xd1, 0x22, 0x5a, 0xf4, 0x90, 0x4a, 0x2a, 0x55, 0x84, 0x9a, 0x7b, 0xad, 0x53, 0x4d, 0x38, 0x4d, + 0x14, 0xbd, 0x61, 0x01, 0x22, 0xb7, 0x89, 0x2b, 0xe3, 0x59, 0x05, 0x2f, 0xfd, 0x45, 0x6c, 0x96, + 0x2f, 0x74, 0xf4, 0xcb, 0xa5, 0x7a, 0x67, 0x3b, 0xce, 0xe1, 0xc1, 0xfe, 0x8b, 0xb2, 0x5a, 0x50, + 0x3a, 0x84, 0xda, 0x31, 0x42, 0x39, 0xad, 0x7b, 0x0f, 0xe5, 0xd4, 0xa1, 0x28, 0x9d, 0x59, 0xc5, + 0xa9, 0x24, 0xc4, 0xd2, 0x7d, 0x4a, 0x42, 0xfc, 0x05, 0x2b, 0x55, 0xd1, 0x6b, 0xf0, 0xfc, 0x4b, + 0xc5, 0x86, 0x6f, 0x4f, 0xf2, 0x30, 0x99, 0x8c, 0x74, 0xcf, 0x44, 0x47, 0x3d, 0x05, 0xd5, 0x0d, + 0xdf, 0x61, 0x75, 0x28, 0xd8, 0x72, 0x31, 0x42, 0x78, 0x2e, 0x8a, 0x76, 0xac, 0x30, 0xa8, 0xec, + 0x35, 0x3a, 0x3d, 0x90, 0xec, 0xfc, 0x8f, 0x65, 0x18, 0x34, 0xf4, 0x6e, 0xae, 0x11, 0x65, 0x3d, + 0x60, 0x46, 0x54, 0xe9, 0x00, 0x46, 0xd4, 0xcf, 0x43, 0xcd, 0x95, 0x3a, 0xa1, 0x98, 0x0a, 0xe5, + 0x59, 0x4d, 0xa3, 0xd5, 0x82, 0x6a, 0xc2, 0x9a, 0x26, 0x9a, 0x4f, 0x25, 0xba, 0xa5, 0x76, 0xe7, + 0x79, 0x99, 0x68, 0x42, 0xaf, 0x74, 0x3e, 0x93, 0x3d, 0x2d, 0xae, 0xec, 0x7f, 0x5a, 0x6c, 0x7f, + 0xd7, 0x52, 0x1f, 0xf7, 0x18, 0x2a, 0x9a, 0xdc, 0x4c, 0x57, 0x34, 0xb9, 0x50, 0xc8, 0x30, 0x77, + 0x29, 0x65, 0x72, 0x15, 0x06, 0x66, 0xc3, 0x66, 0xd3, 0x09, 0xea, 0xe8, 0x27, 0x60, 0xc0, 0xe5, + 0x3f, 0x85, 0x27, 0x8b, 0x9d, 0x87, 0x0a, 0x28, 0x96, 0x30, 0xf4, 0x08, 0xf4, 0x39, 0x51, 0x43, + 0x7a, 0xaf, 0x58, 0xdc, 0xd2, 0x74, 0xd4, 0x88, 0x31, 0x6b, 0xb5, 0xff, 0x59, 0x1f, 0xb0, 0x70, + 0x01, 0x27, 0x22, 0xf5, 0xb5, 0x90, 0x15, 0x16, 0x3d, 0xd2, 0x53, 0x44, 0xbd, 0xb5, 0x7a, 0x90, + 0x4f, 0x12, 0x8d, 0xd3, 0xa4, 0xf2, 0x31, 0x9f, 0x26, 0x75, 0x39, 0x20, 0xec, 0x7b, 0x80, 0x0e, + 0x08, 0xed, 0xcf, 0x59, 0x80, 0x54, 0x8c, 0x89, 0x3e, 0xc1, 0x9f, 0x82, 0x9a, 0x8a, 0x36, 0x11, + 0x66, 0x98, 0x16, 0x11, 0x12, 0x80, 0x35, 0x4e, 0x0f, 0xfb, 0xe9, 0xc7, 0xa5, 0xfc, 0x2e, 0xa7, + 0xc3, 0xb7, 0x99, 0xd4, 0x17, 0xe2, 0xdc, 0xfe, 0xbd, 0x12, 0x3c, 0xc4, 0x15, 0xf8, 0x92, 0x13, + 0x38, 0x0d, 0xd2, 0xa4, 0x5c, 0xf5, 0x1a, 0x93, 0xe1, 0xd2, 0x8d, 0x9c, 0x27, 0xc3, 0xb1, 0x0f, + 0xbb, 0x76, 0xf9, 0x9a, 0xe3, 0xab, 0x6c, 0x21, 0xf0, 0x12, 0xcc, 0x3a, 0x47, 0x31, 0x54, 0xe5, + 0xf5, 0x1d, 0x42, 0x16, 0x17, 0x44, 0x48, 0x89, 0x25, 0xa1, 0x65, 0x09, 0x56, 0x84, 0xa8, 0x2a, + 0xf5, 0x43, 0x77, 0x0b, 0x93, 0x56, 0x98, 0x55, 0xa5, 0x8b, 0xa2, 0x1d, 0x2b, 0x0c, 0xbb, 0x09, + 0xa3, 0x72, 0x0c, 0x5b, 0x57, 0xc8, 0x0e, 0x26, 0x1b, 0x54, 0xff, 0xb8, 0xb2, 0xc9, 0xb8, 0x51, + 0x44, 0xe9, 0x9f, 0x59, 0x13, 0x88, 0xd3, 0xb8, 0xb2, 0xd6, 0x68, 0x29, 0xbf, 0xd6, 0xa8, 0xfd, + 0x7b, 0x16, 0x64, 0x15, 0xa0, 0x51, 0x59, 0xd1, 0xda, 0xb3, 0xb2, 0xe2, 0x01, 0x6a, 0x13, 0xfe, + 0x2c, 0x0c, 0x3a, 0x09, 0xb5, 0x70, 0xb8, 0x4f, 0xa0, 0x7c, 0x6f, 0xc7, 0x46, 0x4b, 0x61, 0xdd, + 0xdb, 0xf0, 0x98, 0x2f, 0xc0, 0xec, 0xce, 0xfe, 0xab, 0x3e, 0x18, 0xeb, 0xc8, 0x95, 0x42, 0xcf, + 0xc3, 0x90, 0x1a, 0x0a, 0xe9, 0x6d, 0xab, 0x99, 0x01, 0x8e, 0x1a, 0x86, 0x53, 0x98, 0x3d, 0xac, + 0x87, 0x05, 0x38, 0x19, 0x91, 0x57, 0xdb, 0xa4, 0x4d, 0xa6, 0x37, 0x12, 0x12, 0xad, 0x12, 0x37, + 0x0c, 0xea, 0xbc, 0xfe, 0x67, 0x79, 0xe6, 0xe1, 0x3b, 0xbb, 0x13, 0x27, 0x71, 0x27, 0x18, 0xe7, + 0x3d, 0x83, 0x5a, 0x30, 0xec, 0x9b, 0x06, 0xaa, 0xd8, 0x9d, 0xdc, 0x93, 0x6d, 0xab, 0xa6, 0x44, + 0xaa, 0x19, 0xa7, 0x09, 0xa4, 0xad, 0xdc, 0xca, 0x7d, 0xb2, 0x72, 0x3f, 0xa9, 0xad, 0x5c, 0x1e, + 0xdf, 0xf0, 0xc1, 0x82, 0x73, 0xe5, 0x7a, 0x31, 0x73, 0x0f, 0x63, 0xb8, 0xbe, 0x08, 0x55, 0x19, + 0xfb, 0xd5, 0x53, 0xcc, 0x94, 0xd9, 0x4f, 0x17, 0x01, 0xfa, 0x04, 0xfc, 0xf8, 0x85, 0x28, 0x32, + 0x06, 0xf3, 0x6a, 0x98, 0x4c, 0xfb, 0x7e, 0x78, 0x8b, 0xda, 0x04, 0xd7, 0x62, 0x22, 0xdc, 0x3f, + 0xf6, 0xdd, 0x12, 0xe4, 0xec, 0xa4, 0xe8, 0x7a, 0xd4, 0x86, 0x48, 0x6a, 0x3d, 0x1e, 0xcc, 0x18, + 0x41, 0xb7, 0x79, 0x7c, 0x1c, 0x57, 0xb9, 0x1f, 0x28, 0x7a, 0x27, 0xa8, 0x43, 0xe6, 0x94, 0x38, + 0x52, 0x61, 0x73, 0xe7, 0x01, 0xb4, 0xfd, 0x28, 0x12, 0x38, 0xd4, 0xf1, 0xbb, 0x36, 0x33, 0xb1, + 0x81, 0x85, 0x9e, 0x83, 0x41, 0x2f, 0x88, 0x13, 0xc7, 0xf7, 0x2f, 0x79, 0x41, 0x22, 0x3c, 0x9c, + 0xca, 0xb6, 0x58, 0xd0, 0x20, 0x6c, 0xe2, 0x9d, 0x7d, 0x97, 0xf1, 0xfd, 0x0e, 0xf2, 0xdd, 0x37, + 0xe1, 0xcc, 0xbc, 0x97, 0xa8, 0xb4, 0x23, 0x35, 0xdf, 0xa8, 0x79, 0xa8, 0xd2, 0xe8, 0xac, 0xae, + 0x69, 0x74, 0x46, 0xda, 0x4f, 0x29, 0x9d, 0xa5, 0x94, 0x4d, 0xfb, 0xb1, 0x9f, 0x87, 0x53, 0xf3, + 0x5e, 0x72, 0xd1, 0xf3, 0xc9, 0x01, 0x89, 0xd8, 0xbf, 0xdb, 0x0f, 0x43, 0x66, 0x02, 0xed, 0x41, + 0x32, 0x01, 0xbf, 0x40, 0x2d, 0x40, 0xf1, 0x76, 0x9e, 0x3a, 0xbc, 0xbc, 0x71, 0xe8, 0x6c, 0xde, + 0xfc, 0x11, 0x33, 0x8c, 0x40, 0x4d, 0x13, 0x9b, 0x0c, 0xa0, 0x5b, 0x50, 0xd9, 0x60, 0x69, 0x29, + 0xe5, 0x22, 0x22, 0x3c, 0xf2, 0x46, 0x54, 0x2f, 0x47, 0x9e, 0xd8, 0xc2, 0xe9, 0x51, 0xc5, 0x1d, + 0xa5, 0x73, 0x1d, 0x8d, 0xf0, 0x63, 0x91, 0xe5, 0xa8, 0x30, 0xba, 0xa9, 0x84, 0xca, 0x3d, 0xa8, + 0x84, 0x94, 0x80, 0xee, 0xbf, 0x4f, 0x02, 0x9a, 0xa5, 0x18, 0x25, 0x9b, 0xcc, 0xac, 0x14, 0xf9, + 0x12, 0x03, 0x6c, 0x10, 0x8c, 0x14, 0xa3, 0x14, 0x18, 0x67, 0xf1, 0xd1, 0xc7, 0x94, 0x88, 0xaf, + 0x16, 0xe1, 0x1c, 0x36, 0x67, 0xf4, 0x51, 0x4b, 0xf7, 0xcf, 0x95, 0x60, 0x64, 0x3e, 0x68, 0xaf, + 0xcc, 0xaf, 0xb4, 0xd7, 0x7d, 0xcf, 0xbd, 0x42, 0x76, 0xa8, 0x08, 0xdf, 0x22, 0x3b, 0x0b, 0x73, + 0x62, 0x05, 0xa9, 0x39, 0x73, 0x85, 0x36, 0x62, 0x0e, 0xa3, 0xc2, 0x68, 0xc3, 0x0b, 0x1a, 0x24, + 0x6a, 0x45, 0x9e, 0xf0, 0xdb, 0x1a, 0xc2, 0xe8, 0xa2, 0x06, 0x61, 0x13, 0x8f, 0xf6, 0x1d, 0xde, + 0x0a, 0x48, 0x94, 0xb5, 0xaf, 0x97, 0x69, 0x23, 0xe6, 0x30, 0x8a, 0x94, 0x44, 0x6d, 0xe1, 0x90, + 0x31, 0x90, 0xd6, 0x68, 0x23, 0xe6, 0x30, 0xba, 0xd2, 0xe3, 0xf6, 0x3a, 0x0b, 0xa0, 0xc9, 0x24, + 0x67, 0xac, 0xf2, 0x66, 0x2c, 0xe1, 0x14, 0x75, 0x8b, 0xec, 0xcc, 0xd1, 0xcd, 0x78, 0x26, 0xdf, + 0xec, 0x0a, 0x6f, 0xc6, 0x12, 0xce, 0x2a, 0x94, 0xa6, 0x87, 0xe3, 0x87, 0xae, 0x42, 0x69, 0x9a, + 0xfd, 0x2e, 0xdb, 0xfa, 0x5f, 0xb7, 0x60, 0xc8, 0x0c, 0x7b, 0x43, 0x8d, 0x8c, 0x2d, 0xbc, 0xdc, + 0x51, 0xe0, 0xfa, 0x3d, 0x79, 0x97, 0x3f, 0x36, 0xbc, 0x24, 0x6c, 0xc5, 0x4f, 0x93, 0xa0, 0xe1, + 0x05, 0x84, 0x85, 0x25, 0xf0, 0x70, 0xb9, 0x54, 0x4c, 0xdd, 0x6c, 0x58, 0x27, 0xf7, 0x60, 0x4c, + 0xdb, 0x37, 0x60, 0xac, 0x23, 0xc9, 0xb0, 0x07, 0x13, 0x64, 0xdf, 0x14, 0x6f, 0x1b, 0xc3, 0x20, + 0xed, 0x58, 0x56, 0xc9, 0x9a, 0x85, 0x31, 0xbe, 0x90, 0x28, 0xa5, 0x55, 0x77, 0x93, 0x34, 0x55, + 0xe2, 0x28, 0x3b, 0x24, 0xb8, 0x9e, 0x05, 0xe2, 0x4e, 0x7c, 0xfb, 0xf3, 0x16, 0x0c, 0xa7, 0xf2, + 0x3e, 0x0b, 0x32, 0x96, 0xd8, 0x4a, 0x0b, 0x59, 0x14, 0x26, 0x0b, 0x45, 0x2f, 0x33, 0x65, 0xaa, + 0x57, 0x9a, 0x06, 0x61, 0x13, 0xcf, 0xfe, 0x52, 0x09, 0xaa, 0x32, 0x92, 0xa5, 0x07, 0x56, 0x3e, + 0x6b, 0xc1, 0xb0, 0x3a, 0x98, 0x61, 0x3e, 0xbc, 0x52, 0x11, 0x89, 0x2d, 0x94, 0x03, 0xe5, 0x05, + 0x08, 0x36, 0x42, 0x6d, 0xb9, 0x63, 0x93, 0x18, 0x4e, 0xd3, 0x46, 0xd7, 0x01, 0xe2, 0x9d, 0x38, + 0x21, 0x4d, 0xc3, 0x9b, 0x68, 0x1b, 0x2b, 0x6e, 0xd2, 0x0d, 0x23, 0x42, 0xd7, 0xd7, 0xd5, 0xb0, + 0x4e, 0x56, 0x15, 0xa6, 0x36, 0xa1, 0x74, 0x1b, 0x36, 0x7a, 0xb2, 0xff, 0x49, 0x09, 0x4e, 0x64, + 0x59, 0x42, 0x1f, 0x84, 0x21, 0x49, 0xdd, 0xd8, 0x75, 0xca, 0x38, 0x9c, 0x21, 0x6c, 0xc0, 0xee, + 0xee, 0x4e, 0x4c, 0x74, 0x5e, 0x24, 0x3a, 0x69, 0xa2, 0xe0, 0x54, 0x67, 0xfc, 0x74, 0x4c, 0x1c, + 0xe3, 0xce, 0xec, 0x4c, 0xb7, 0x5a, 0xe2, 0x88, 0xcb, 0x38, 0x1d, 0x33, 0xa1, 0x38, 0x83, 0x8d, + 0x56, 0xe0, 0x94, 0xd1, 0x72, 0x95, 0x78, 0x8d, 0xcd, 0xf5, 0x30, 0x92, 0x3b, 0xb0, 0x47, 0x74, + 0x80, 0x5d, 0x27, 0x0e, 0xce, 0x7d, 0x92, 0x6a, 0x7b, 0xd7, 0x69, 0x39, 0xae, 0x97, 0xec, 0x08, + 0xf7, 0xa8, 0x92, 0x4d, 0xb3, 0xa2, 0x1d, 0x2b, 0x0c, 0x7b, 0x09, 0xfa, 0x7a, 0x9c, 0x41, 0x3d, + 0x59, 0xfe, 0x2f, 0x42, 0x95, 0x76, 0x27, 0xcd, 0xbb, 0x22, 0xba, 0x0c, 0xa1, 0x2a, 0xaf, 0x65, + 0x42, 0x36, 0x94, 0x3d, 0x47, 0x1e, 0x40, 0xaa, 0xd7, 0x5a, 0x88, 0xe3, 0x36, 0xdb, 0x4c, 0x53, + 0x20, 0x7a, 0x1c, 0xca, 0xe4, 0x76, 0x2b, 0x7b, 0xd2, 0x78, 0xe1, 0x76, 0xcb, 0x8b, 0x48, 0x4c, + 0x91, 0xc8, 0xed, 0x16, 0x3a, 0x0b, 0x25, 0xaf, 0x2e, 0x94, 0x14, 0x08, 0x9c, 0xd2, 0xc2, 0x1c, + 0x2e, 0x79, 0x75, 0xfb, 0x36, 0xd4, 0xd4, 0x3d, 0x50, 0x68, 0x4b, 0xca, 0x6e, 0xab, 0x88, 0xd0, + 0x33, 0xd9, 0x6f, 0x17, 0xa9, 0xdd, 0x06, 0xd0, 0x49, 0xa3, 0x45, 0xc9, 0x97, 0x73, 0xd0, 0xe7, + 0x86, 0x22, 0x39, 0xbf, 0xaa, 0xbb, 0x61, 0x42, 0x9b, 0x41, 0xec, 0x1b, 0x30, 0x72, 0x25, 0x08, + 0x6f, 0xb1, 0xeb, 0x1a, 0x58, 0x75, 0x42, 0xda, 0xf1, 0x06, 0xfd, 0x91, 0x35, 0x11, 0x18, 0x14, + 0x73, 0x98, 0xaa, 0x9b, 0x56, 0xea, 0x56, 0x37, 0xcd, 0xfe, 0xb8, 0x05, 0x43, 0x2a, 0xfb, 0x6c, + 0x7e, 0x7b, 0x8b, 0xf6, 0xdb, 0x88, 0xc2, 0x76, 0x2b, 0xdb, 0x2f, 0xbb, 0x72, 0x0e, 0x73, 0x98, + 0x99, 0x96, 0x59, 0xda, 0x27, 0x2d, 0xf3, 0x1c, 0xf4, 0x6d, 0x79, 0x41, 0x3d, 0x7b, 0xf5, 0xd0, + 0x15, 0x2f, 0xa8, 0x63, 0x06, 0xa1, 0x2c, 0x9c, 0x50, 0x2c, 0x48, 0x85, 0xf0, 0x3c, 0x0c, 0xad, + 0xb7, 0x3d, 0xbf, 0x2e, 0xcb, 0x2e, 0x66, 0x3c, 0x2a, 0x33, 0x06, 0x0c, 0xa7, 0x30, 0xe9, 0xbe, + 0x6e, 0xdd, 0x0b, 0x9c, 0x68, 0x67, 0x45, 0x6b, 0x20, 0x25, 0x94, 0x66, 0x14, 0x04, 0x1b, 0x58, + 0xf6, 0xeb, 0x65, 0x18, 0x49, 0xe7, 0xe0, 0xf5, 0xb0, 0xbd, 0x7a, 0x1c, 0x2a, 0x2c, 0x2d, 0x2f, + 0xfb, 0x69, 0x79, 0xa5, 0x42, 0x0e, 0x43, 0x31, 0xf4, 0xf3, 0xe2, 0x24, 0xc5, 0x5c, 0xdb, 0xa5, + 0x98, 0x54, 0x7e, 0x18, 0x16, 0xa0, 0x27, 0xea, 0xa1, 0x08, 0x52, 0xe8, 0x53, 0x16, 0x0c, 0x84, + 0x2d, 0xb3, 0xde, 0xd6, 0x07, 0x8a, 0xcc, 0x4f, 0x14, 0x49, 0x4b, 0xc2, 0x22, 0x56, 0x9f, 0x5e, + 0x7e, 0x0e, 0x49, 0xfa, 0xec, 0xbb, 0x61, 0xc8, 0xc4, 0xdc, 0xcf, 0x28, 0xae, 0x9a, 0x46, 0xf1, + 0x67, 0xcd, 0x49, 0x21, 0x32, 0x30, 0x7b, 0x58, 0x6e, 0xd7, 0xa0, 0xe2, 0xaa, 0x28, 0x86, 0x7b, + 0x2a, 0xd6, 0xab, 0xaa, 0x85, 0xb0, 0xb3, 0x29, 0xde, 0x9b, 0xfd, 0x5d, 0xcb, 0x98, 0x1f, 0x98, + 0xc4, 0x0b, 0x75, 0x14, 0x41, 0xb9, 0xb1, 0xbd, 0x25, 0x4c, 0xd1, 0xcb, 0x05, 0x0d, 0xef, 0xfc, + 0xf6, 0x96, 0x9e, 0xe3, 0x66, 0x2b, 0xa6, 0xc4, 0x7a, 0x70, 0x16, 0xa6, 0x12, 0x75, 0xcb, 0xfb, + 0x27, 0xea, 0xda, 0x6f, 0x94, 0x60, 0xac, 0x63, 0x52, 0xa1, 0xd7, 0xa0, 0x12, 0xd1, 0xb7, 0x14, + 0xaf, 0xb7, 0x58, 0x58, 0x6a, 0x6d, 0xbc, 0x50, 0xd7, 0x7a, 0x37, 0xdd, 0x8e, 0x39, 0x49, 0x74, + 0x19, 0x90, 0x8e, 0xb5, 0x51, 0x9e, 0x4a, 0xfe, 0xca, 0x67, 0xc5, 0xa3, 0x68, 0xba, 0x03, 0x03, + 0xe7, 0x3c, 0x85, 0x5e, 0xc8, 0x3a, 0x3c, 0xcb, 0x69, 0x77, 0xf6, 0x5e, 0xbe, 0x4b, 0xfb, 0xb7, + 0x4b, 0x30, 0x9c, 0x2a, 0x7f, 0x86, 0x7c, 0xa8, 0x12, 0x9f, 0x9d, 0x35, 0x48, 0x65, 0x73, 0xd8, + 0x62, 0xe6, 0x4a, 0x41, 0x5e, 0x10, 0xfd, 0x62, 0x45, 0xe1, 0xc1, 0x88, 0x10, 0x78, 0x1e, 0x86, + 0x24, 0x43, 0x1f, 0x70, 0x9a, 0xbe, 0x18, 0x40, 0x35, 0x47, 0x2f, 0x18, 0x30, 0x9c, 0xc2, 0xb4, + 0x7f, 0xbf, 0x0c, 0xe3, 0xfc, 0x70, 0xa6, 0xae, 0x66, 0xde, 0x92, 0xdc, 0x6f, 0xfd, 0x0d, 0x5d, + 0xa4, 0xd0, 0x2a, 0xe2, 0xc6, 0xce, 0x6e, 0x84, 0x7a, 0x0a, 0x2f, 0xfb, 0x6a, 0x26, 0xbc, 0x8c, + 0x9b, 0xdd, 0x8d, 0x23, 0xe2, 0xe8, 0x87, 0x2b, 0xde, 0xec, 0x1f, 0x96, 0x60, 0x34, 0x73, 0x31, + 0x0b, 0x7a, 0x3d, 0x5d, 0xcb, 0xdb, 0x2a, 0xc2, 0xa7, 0xbe, 0xe7, 0x5d, 0x1d, 0x07, 0xab, 0xe8, + 0x7d, 0x9f, 0x96, 0x8a, 0xfd, 0x9d, 0x12, 0x8c, 0xa4, 0x6f, 0x94, 0x79, 0x00, 0x47, 0xea, 0x1d, + 0x50, 0x63, 0x97, 0x26, 0xb0, 0x8b, 0x90, 0xb9, 0x4b, 0x9e, 0xd7, 0xa7, 0x97, 0x8d, 0x58, 0xc3, + 0x1f, 0x88, 0x42, 0xe9, 0xf6, 0x3f, 0xb6, 0xe0, 0x34, 0x7f, 0xcb, 0xec, 0x3c, 0xfc, 0x9b, 0x79, + 0xa3, 0xfb, 0x72, 0xb1, 0x0c, 0x66, 0x8a, 0x6b, 0xee, 0x37, 0xbe, 0xec, 0xde, 0x52, 0xc1, 0x6d, + 0x7a, 0x2a, 0x3c, 0x80, 0xcc, 0x1e, 0x68, 0x32, 0xd8, 0xdf, 0x29, 0x83, 0xbe, 0xaa, 0x15, 0x79, + 0x22, 0xd7, 0xb4, 0x90, 0x22, 0xa3, 0xab, 0x3b, 0x81, 0xab, 0x2f, 0x85, 0xad, 0x66, 0x52, 0x4d, + 0x7f, 0xc9, 0x82, 0x41, 0x2f, 0xf0, 0x12, 0xcf, 0x61, 0xdb, 0xe8, 0x62, 0xee, 0x5b, 0x54, 0xe4, + 0x16, 0x78, 0xcf, 0x61, 0x64, 0x9e, 0xe3, 0x28, 0x62, 0xd8, 0xa4, 0x8c, 0x3e, 0x2c, 0x22, 0xc0, + 0xcb, 0x85, 0x65, 0x49, 0x57, 0x33, 0x61, 0xdf, 0x2d, 0x6a, 0x78, 0x25, 0x51, 0x41, 0xc5, 0x05, + 0x30, 0xed, 0x4a, 0xd5, 0xab, 0xd6, 0xb7, 0xff, 0xd3, 0x66, 0xcc, 0x09, 0xd9, 0x31, 0xa0, 0xce, + 0xb1, 0x38, 0x60, 0x74, 0xed, 0x14, 0xd4, 0x9c, 0x76, 0x12, 0x36, 0xe9, 0x30, 0x89, 0xa3, 0x26, + 0x1d, 0x3f, 0x2c, 0x01, 0x58, 0xe3, 0xd8, 0xaf, 0x57, 0x20, 0x93, 0xfc, 0x89, 0x6e, 0x9b, 0xd7, + 0x0c, 0x5b, 0xc5, 0x5e, 0x33, 0xac, 0x98, 0xc9, 0xbb, 0x6a, 0x18, 0x35, 0xa0, 0xd2, 0xda, 0x74, + 0x62, 0x69, 0x56, 0xbf, 0xa8, 0xf6, 0x71, 0xb4, 0xf1, 0xee, 0xee, 0xc4, 0xcf, 0xf4, 0xe6, 0x75, + 0xa5, 0x73, 0x75, 0x8a, 0x17, 0xac, 0xd1, 0xa4, 0x59, 0x1f, 0x98, 0xf7, 0x7f, 0x90, 0x1b, 0x27, + 0x3f, 0x21, 0x6e, 0x87, 0xc0, 0x24, 0x6e, 0xfb, 0x89, 0x98, 0x0d, 0x2f, 0x16, 0xb8, 0xca, 0x78, + 0xc7, 0xba, 0x6c, 0x01, 0xff, 0x8f, 0x0d, 0xa2, 0xe8, 0x83, 0x50, 0x8b, 0x13, 0x27, 0x4a, 0xee, + 0x31, 0xd1, 0x58, 0x17, 0x16, 0x93, 0x9d, 0x60, 0xdd, 0x1f, 0x7a, 0x89, 0xd5, 0x5c, 0xf6, 0xe2, + 0xcd, 0x7b, 0x4c, 0xdc, 0x90, 0xf5, 0x99, 0x45, 0x0f, 0xd8, 0xe8, 0x0d, 0x9d, 0x07, 0x60, 0x73, + 0x9b, 0xc7, 0x1f, 0x56, 0x99, 0x97, 0x49, 0x89, 0x42, 0xac, 0x20, 0xd8, 0xc0, 0xb2, 0x7f, 0x12, + 0xd2, 0x75, 0x37, 0xd0, 0x84, 0x2c, 0xf3, 0xc1, 0xbd, 0xd0, 0x2c, 0x01, 0x23, 0x55, 0x91, 0xe3, + 0x37, 0x2d, 0x30, 0x8b, 0x83, 0xa0, 0x57, 0x79, 0x15, 0x12, 0xab, 0x88, 0x93, 0x43, 0xa3, 0xdf, + 0xc9, 0x25, 0xa7, 0x95, 0x39, 0xc2, 0x96, 0xa5, 0x48, 0xce, 0xbe, 0x0b, 0xaa, 0x12, 0x7a, 0x20, + 0xa3, 0xee, 0x63, 0x70, 0x52, 0x26, 0x73, 0x4a, 0xbf, 0xa9, 0x38, 0x75, 0xda, 0xdf, 0xf5, 0x23, + 0xfd, 0x39, 0xa5, 0x6e, 0xfe, 0x9c, 0x1e, 0x2e, 0x9b, 0xfe, 0x2d, 0x0b, 0xce, 0x65, 0x19, 0x88, + 0x97, 0xc2, 0xc0, 0x4b, 0xc2, 0x68, 0x95, 0x24, 0x89, 0x17, 0x34, 0x58, 0xf1, 0xb5, 0x5b, 0x4e, + 0x24, 0x8b, 0xe1, 0x33, 0x41, 0x79, 0xc3, 0x89, 0x02, 0xcc, 0x5a, 0xd1, 0x0e, 0xf4, 0xf3, 0x20, + 0x35, 0x61, 0xad, 0x1f, 0x72, 0x6d, 0xe4, 0x0c, 0x87, 0xde, 0x2e, 0xf0, 0x00, 0x39, 0x2c, 0x08, + 0xda, 0xdf, 0xb7, 0x00, 0x2d, 0x6f, 0x93, 0x28, 0xf2, 0xea, 0x46, 0x58, 0x1d, 0xbb, 0x65, 0xc9, + 0xb8, 0x4d, 0xc9, 0x4c, 0x35, 0xce, 0xdc, 0xb2, 0x64, 0xfc, 0xcb, 0xbf, 0x65, 0xa9, 0x74, 0xb0, + 0x5b, 0x96, 0xd0, 0x32, 0x9c, 0x6e, 0xf2, 0xed, 0x06, 0xbf, 0xb9, 0x84, 0xef, 0x3d, 0x54, 0x56, + 0xdc, 0x99, 0x3b, 0xbb, 0x13, 0xa7, 0x97, 0xf2, 0x10, 0x70, 0xfe, 0x73, 0xf6, 0xbb, 0x00, 0xf1, + 0x68, 0xba, 0xd9, 0xbc, 0x58, 0xa5, 0xae, 0xee, 0x17, 0xfb, 0x2b, 0x15, 0x18, 0xcd, 0x94, 0x4a, + 0xa6, 0x5b, 0xbd, 0xce, 0xe0, 0xa8, 0x43, 0xeb, 0xef, 0x4e, 0xf6, 0x7a, 0x0a, 0xb7, 0x0a, 0xa0, + 0xe2, 0x05, 0xad, 0x76, 0x52, 0x4c, 0x52, 0x2e, 0x67, 0x62, 0x81, 0x76, 0x68, 0xb8, 0x8b, 0xe9, + 0x5f, 0xcc, 0xc9, 0x14, 0x19, 0xbc, 0x95, 0x32, 0xc6, 0xfb, 0xee, 0x93, 0x3b, 0xe0, 0x13, 0x3a, + 0x94, 0xaa, 0x52, 0x84, 0x63, 0x31, 0x33, 0x59, 0x8e, 0xfa, 0xa8, 0xfd, 0x9b, 0x25, 0x18, 0x34, + 0x3e, 0x1a, 0xfa, 0xb5, 0x74, 0xe9, 0x2c, 0xab, 0xb8, 0x57, 0x62, 0xfd, 0x4f, 0xea, 0xe2, 0x58, + 0xfc, 0x95, 0x9e, 0xe8, 0xac, 0x9a, 0x75, 0x77, 0x77, 0xe2, 0x44, 0xa6, 0x2e, 0x56, 0xaa, 0x92, + 0xd6, 0xd9, 0x8f, 0xc2, 0x68, 0xa6, 0x9b, 0x9c, 0x57, 0x5e, 0x33, 0x5f, 0xf9, 0xd0, 0x6e, 0x29, + 0x73, 0xc8, 0xbe, 0x41, 0x87, 0x4c, 0xe4, 0x02, 0x86, 0x3e, 0xe9, 0xc1, 0x07, 0x9b, 0x49, 0xf9, + 0x2d, 0xf5, 0x98, 0xf2, 0xfb, 0x24, 0x54, 0x5b, 0xa1, 0xef, 0xb9, 0x9e, 0xaa, 0x64, 0xc9, 0x92, + 0x8c, 0x57, 0x44, 0x1b, 0x56, 0x50, 0x74, 0x0b, 0x6a, 0x37, 0x6f, 0x25, 0xfc, 0xf4, 0x47, 0xf8, + 0xb7, 0x8b, 0x3a, 0xf4, 0x51, 0x46, 0x8b, 0x3a, 0x5e, 0xc2, 0x9a, 0x16, 0xb2, 0xa1, 0x9f, 0x29, + 0x41, 0x99, 0x91, 0xc0, 0x7c, 0xef, 0x4c, 0x3b, 0xc6, 0x58, 0x40, 0xec, 0xaf, 0xd7, 0xe0, 0x54, + 0x5e, 0xbd, 0x7a, 0xf4, 0x11, 0xe8, 0xe7, 0x3c, 0x16, 0x73, 0x25, 0x4a, 0x1e, 0x8d, 0x79, 0xd6, + 0xa1, 0x60, 0x8b, 0xfd, 0xc6, 0x82, 0xa6, 0xa0, 0xee, 0x3b, 0xeb, 0x62, 0x86, 0x1c, 0x0d, 0xf5, + 0x45, 0x47, 0x53, 0x5f, 0x74, 0x38, 0x75, 0xdf, 0x59, 0x47, 0xb7, 0xa1, 0xd2, 0xf0, 0x12, 0xe2, + 0x08, 0x27, 0xc2, 0x8d, 0x23, 0x21, 0x4e, 0x1c, 0x6e, 0xa5, 0xb1, 0x9f, 0x98, 0x13, 0x44, 0x5f, + 0xb3, 0x60, 0x74, 0x3d, 0x5d, 0x6b, 0x40, 0x08, 0x4f, 0xe7, 0x08, 0xee, 0x24, 0x48, 0x13, 0xe2, + 0xd7, 0x8c, 0x65, 0x1a, 0x71, 0x96, 0x1d, 0xf4, 0x49, 0x0b, 0x06, 0x36, 0x3c, 0xdf, 0x28, 0x0b, + 0x7d, 0x04, 0x1f, 0xe7, 0x22, 0x23, 0xa0, 0x77, 0x1c, 0xfc, 0x7f, 0x8c, 0x25, 0xe5, 0x6e, 0x9a, + 0xaa, 0xff, 0xb0, 0x9a, 0x6a, 0xe0, 0x3e, 0x69, 0xaa, 0xcf, 0x58, 0x50, 0x53, 0x23, 0x2d, 0x72, + 0xb6, 0x3f, 0x78, 0x84, 0x9f, 0x9c, 0x7b, 0x4e, 0xd4, 0x5f, 0xac, 0x89, 0xa3, 0x2f, 0x5a, 0x30, + 0xe8, 0xbc, 0xd6, 0x8e, 0x48, 0x9d, 0x6c, 0x87, 0xad, 0x58, 0xdc, 0x51, 0xfa, 0x72, 0xf1, 0xcc, + 0x4c, 0x53, 0x22, 0x73, 0x64, 0x7b, 0xb9, 0x15, 0x8b, 0x6c, 0x29, 0xdd, 0x80, 0x4d, 0x16, 0xec, + 0xdd, 0x12, 0x4c, 0xec, 0xd3, 0x03, 0x7a, 0x1e, 0x86, 0xc2, 0xa8, 0xe1, 0x04, 0xde, 0x6b, 0x66, + 0xf1, 0x10, 0x65, 0x65, 0x2d, 0x1b, 0x30, 0x9c, 0xc2, 0x34, 0xb3, 0xca, 0x4b, 0xfb, 0x64, 0x95, + 0x9f, 0x83, 0xbe, 0x88, 0xb4, 0xc2, 0xec, 0x66, 0x81, 0x65, 0x2a, 0x30, 0x08, 0x7a, 0x14, 0xca, + 0x4e, 0xcb, 0x13, 0x81, 0x68, 0x6a, 0x0f, 0x34, 0xbd, 0xb2, 0x80, 0x69, 0x7b, 0xaa, 0xc8, 0x45, + 0xe5, 0x58, 0x8a, 0x5c, 0x50, 0x35, 0x20, 0xce, 0x2e, 0xfa, 0xb5, 0x1a, 0x48, 0x9f, 0x29, 0xd8, + 0x6f, 0x94, 0xe1, 0xd1, 0x3d, 0xe7, 0x8b, 0x8e, 0xc3, 0xb3, 0xf6, 0x88, 0xc3, 0x93, 0xc3, 0x53, + 0xda, 0x6f, 0x78, 0xca, 0x5d, 0x86, 0xe7, 0x93, 0x74, 0x19, 0xc8, 0xa2, 0x2b, 0xc5, 0xdc, 0x32, + 0xd9, 0xad, 0x86, 0x8b, 0x58, 0x01, 0x12, 0x8a, 0x35, 0x5d, 0xba, 0x07, 0x48, 0x65, 0x54, 0x57, + 0x8a, 0x50, 0x03, 0x5d, 0x0b, 0x9f, 0xf0, 0xb9, 0xdf, 0x2d, 0x4d, 0xdb, 0xfe, 0x9d, 0x3e, 0x78, + 0xbc, 0x07, 0xe9, 0x6d, 0xce, 0x62, 0xab, 0xc7, 0x59, 0xfc, 0x43, 0xfe, 0x99, 0x3e, 0x9d, 0xfb, + 0x99, 0x70, 0xf1, 0x9f, 0x69, 0xef, 0x2f, 0x84, 0x9e, 0x82, 0xaa, 0x17, 0xc4, 0xc4, 0x6d, 0x47, + 0x3c, 0x26, 0xd9, 0x48, 0x63, 0x5a, 0x10, 0xed, 0x58, 0x61, 0xd0, 0x3d, 0x9d, 0xeb, 0xd0, 0xe5, + 0x3f, 0x50, 0x50, 0xee, 0xae, 0x99, 0x11, 0xc5, 0x4d, 0x8a, 0xd9, 0x69, 0x2a, 0x01, 0x38, 0x19, + 0xfb, 0x6f, 0x59, 0x70, 0xb6, 0xbb, 0x8a, 0x45, 0xcf, 0xc0, 0xe0, 0x7a, 0xe4, 0x04, 0xee, 0x26, + 0xbb, 0x5f, 0x58, 0x4e, 0x1d, 0xf6, 0xbe, 0xba, 0x19, 0x9b, 0x38, 0x68, 0x16, 0xc6, 0x78, 0xe4, + 0x86, 0x81, 0x21, 0x33, 0x7f, 0xef, 0xec, 0x4e, 0x8c, 0xad, 0x65, 0x81, 0xb8, 0x13, 0xdf, 0xfe, + 0x41, 0x39, 0x9f, 0x2d, 0x6e, 0x8a, 0x1d, 0x64, 0x36, 0x8b, 0xb9, 0x5a, 0xea, 0x41, 0xe2, 0x96, + 0x8f, 0x5b, 0xe2, 0xf6, 0x75, 0x93, 0xb8, 0x68, 0x0e, 0x4e, 0x18, 0x17, 0x40, 0xf1, 0x6c, 0x6e, + 0x1e, 0x96, 0xac, 0x0a, 0xa2, 0xac, 0x64, 0xe0, 0xb8, 0xe3, 0x89, 0x07, 0x7c, 0xea, 0xfd, 0x7a, + 0x09, 0xce, 0x74, 0xb5, 0x7e, 0x8f, 0x49, 0xa3, 0x98, 0x9f, 0xbf, 0xef, 0x78, 0x3e, 0xbf, 0xf9, + 0x51, 0x2a, 0xfb, 0x7d, 0x14, 0xfb, 0x4f, 0x4a, 0x5d, 0x17, 0x02, 0xdd, 0x09, 0xfd, 0xc8, 0x8e, + 0xd2, 0x0b, 0x30, 0xec, 0xb4, 0x5a, 0x1c, 0x8f, 0x45, 0xd1, 0x66, 0x0a, 0x30, 0x4d, 0x9b, 0x40, + 0x9c, 0xc6, 0xed, 0xc9, 0xa6, 0xf9, 0x53, 0x0b, 0x6a, 0x98, 0x6c, 0x70, 0x69, 0x84, 0x6e, 0x8a, + 0x21, 0xb2, 0x8a, 0xa8, 0x36, 0x4b, 0x07, 0x36, 0xf6, 0x58, 0x15, 0xd6, 0xbc, 0xc1, 0xee, 0xbc, + 0x10, 0xac, 0x74, 0xa0, 0x0b, 0xc1, 0xd4, 0x95, 0x50, 0xe5, 0xee, 0x57, 0x42, 0xd9, 0xdf, 0x1b, + 0xa0, 0xaf, 0xd7, 0x0a, 0x67, 0x23, 0x52, 0x8f, 0xe9, 0xf7, 0x6d, 0x47, 0xbe, 0x98, 0x24, 0xea, + 0xfb, 0x5e, 0xc3, 0x8b, 0x98, 0xb6, 0xa7, 0x0e, 0xc8, 0x4a, 0x07, 0x2a, 0x3f, 0x53, 0xde, 0xb7, + 0xfc, 0xcc, 0x0b, 0x30, 0x1c, 0xc7, 0x9b, 0x2b, 0x91, 0xb7, 0xed, 0x24, 0xe4, 0x0a, 0xd9, 0x11, + 0xb6, 0xaf, 0x2e, 0x02, 0xb1, 0x7a, 0x49, 0x03, 0x71, 0x1a, 0x17, 0xcd, 0xc3, 0x98, 0x2e, 0x02, + 0x43, 0xa2, 0x84, 0xe5, 0x5c, 0xf0, 0x99, 0xa0, 0x32, 0xbe, 0x75, 0xd9, 0x18, 0x81, 0x80, 0x3b, + 0x9f, 0xa1, 0xf2, 0x34, 0xd5, 0x48, 0x19, 0xe9, 0x4f, 0xcb, 0xd3, 0x54, 0x3f, 0x94, 0x97, 0x8e, + 0x27, 0xd0, 0x12, 0x9c, 0xe4, 0x13, 0x63, 0xba, 0xd5, 0x32, 0xde, 0x68, 0x20, 0x5d, 0xe5, 0x73, + 0xbe, 0x13, 0x05, 0xe7, 0x3d, 0x87, 0x9e, 0x83, 0x41, 0xd5, 0xbc, 0x30, 0x27, 0xce, 0x76, 0x94, + 0x6f, 0x49, 0x75, 0xb3, 0x50, 0xc7, 0x26, 0x1e, 0xfa, 0x00, 0x3c, 0xac, 0xff, 0xf2, 0xc4, 0x3c, + 0x7e, 0xe0, 0x39, 0x27, 0xea, 0x6b, 0xa9, 0x0b, 0x88, 0xe6, 0x73, 0xd1, 0xea, 0xb8, 0xdb, 0xf3, + 0x68, 0x1d, 0xce, 0x2a, 0xd0, 0x85, 0x20, 0x61, 0x59, 0x36, 0x31, 0x99, 0x71, 0x62, 0x72, 0x2d, + 0xf2, 0xc5, 0x45, 0xd6, 0xea, 0x8e, 0xda, 0x79, 0x2f, 0xb9, 0x94, 0x87, 0x89, 0x17, 0xf1, 0x1e, + 0xbd, 0xa0, 0x29, 0xa8, 0x91, 0xc0, 0x59, 0xf7, 0xc9, 0xf2, 0xec, 0x02, 0xab, 0xd3, 0x65, 0x9c, + 0xaf, 0x5e, 0x90, 0x00, 0xac, 0x71, 0x54, 0xdc, 0xef, 0x50, 0xd7, 0xfb, 0x92, 0x57, 0xe0, 0x54, + 0xc3, 0x6d, 0x51, 0x8b, 0xd0, 0x73, 0xc9, 0xb4, 0xcb, 0xc2, 0x1c, 0xe9, 0x87, 0xe1, 0xe5, 0x57, + 0x55, 0x50, 0xfb, 0xfc, 0xec, 0x4a, 0x07, 0x0e, 0xce, 0x7d, 0x92, 0x85, 0xc3, 0x46, 0xe1, 0xed, + 0x9d, 0xf1, 0x93, 0x99, 0x70, 0x58, 0xda, 0x88, 0x39, 0x0c, 0x5d, 0x06, 0xc4, 0x32, 0x24, 0x2e, + 0x25, 0x49, 0x4b, 0x99, 0xa0, 0xe3, 0xa7, 0xd8, 0x2b, 0xa9, 0xe0, 0xbe, 0x8b, 0x1d, 0x18, 0x38, + 0xe7, 0x29, 0x6a, 0xd1, 0x04, 0x21, 0xeb, 0x7d, 0xfc, 0xe1, 0xb4, 0x45, 0x73, 0x95, 0x37, 0x63, + 0x09, 0xb7, 0xff, 0x93, 0x05, 0xc3, 0x6a, 0x69, 0x1f, 0x43, 0x3a, 0x91, 0x9f, 0x4e, 0x27, 0x9a, + 0x3f, 0xbc, 0x70, 0x64, 0x9c, 0x77, 0x89, 0x49, 0xff, 0xe6, 0x20, 0x80, 0x16, 0xa0, 0x4a, 0x77, + 0x59, 0x5d, 0x75, 0xd7, 0x03, 0x2b, 0xbc, 0xf2, 0x2a, 0xf2, 0x54, 0xee, 0x6f, 0x45, 0x9e, 0x55, + 0x38, 0x2d, 0x2d, 0x0b, 0x7e, 0xd8, 0x77, 0x29, 0x8c, 0x95, 0x2c, 0xac, 0xce, 0x3c, 0x2a, 0x3a, + 0x3a, 0xbd, 0x90, 0x87, 0x84, 0xf3, 0x9f, 0x4d, 0x19, 0x34, 0x03, 0xfb, 0x5a, 0x99, 0x6a, 0xf9, + 0x2f, 0x6e, 0xc8, 0x8b, 0x7c, 0x32, 0xcb, 0x7f, 0xf1, 0xe2, 0x2a, 0xd6, 0x38, 0xf9, 0x3a, 0xa0, + 0x56, 0x90, 0x0e, 0x80, 0x03, 0xeb, 0x00, 0x29, 0x8d, 0x06, 0xbb, 0x4a, 0x23, 0x79, 0xa8, 0x30, + 0xd4, 0xf5, 0x50, 0xe1, 0xbd, 0x30, 0xe2, 0x05, 0x9b, 0x24, 0xf2, 0x12, 0x52, 0x67, 0x6b, 0x81, + 0x49, 0xaa, 0xaa, 0xb6, 0x00, 0x16, 0x52, 0x50, 0x9c, 0xc1, 0x4e, 0x8b, 0xd0, 0x91, 0x1e, 0x44, + 0x68, 0x17, 0xc5, 0x35, 0x5a, 0x8c, 0xe2, 0x3a, 0x71, 0x78, 0xc5, 0x35, 0x76, 0xa4, 0x8a, 0x0b, + 0x15, 0xa2, 0xb8, 0x7a, 0xd2, 0x09, 0xc6, 0xce, 0xf4, 0xd4, 0x3e, 0x3b, 0xd3, 0x6e, 0x5a, 0xeb, + 0xf4, 0x3d, 0x6b, 0xad, 0x7c, 0x85, 0xf4, 0xd0, 0x51, 0x2b, 0xa4, 0xcf, 0x94, 0xe0, 0xb4, 0x16, + 0xd9, 0x74, 0xa1, 0x78, 0x1b, 0x54, 0x68, 0xb1, 0x6b, 0xe3, 0xf8, 0x19, 0x9d, 0x91, 0x08, 0xa7, + 0x73, 0xea, 0x14, 0x04, 0x1b, 0x58, 0x2c, 0x9f, 0x8c, 0x44, 0xac, 0x06, 0x75, 0x56, 0x9e, 0xcf, + 0x8a, 0x76, 0xac, 0x30, 0xe8, 0x54, 0xa4, 0xbf, 0x45, 0x8e, 0x6e, 0xb6, 0xba, 0xe1, 0xac, 0x06, + 0x61, 0x13, 0x0f, 0x3d, 0xc9, 0x89, 0x30, 0x59, 0x42, 0x65, 0xfa, 0x90, 0xb8, 0x9b, 0x5b, 0x8a, + 0x0f, 0x05, 0x95, 0xec, 0xb0, 0xc4, 0xc1, 0x4a, 0x27, 0x3b, 0x2c, 0xdc, 0x4d, 0x61, 0xd8, 0xff, + 0xd3, 0x82, 0x33, 0xb9, 0x43, 0x71, 0x0c, 0x7a, 0xfa, 0x76, 0x5a, 0x4f, 0xaf, 0x16, 0xb5, 0x89, + 0x31, 0xde, 0xa2, 0x8b, 0xce, 0xfe, 0x0f, 0x16, 0x8c, 0x68, 0xfc, 0x63, 0x78, 0x55, 0x2f, 0xfd, + 0xaa, 0xc5, 0xed, 0xd7, 0x6a, 0x1d, 0xef, 0xf6, 0xfb, 0x25, 0x50, 0x15, 0x47, 0xa7, 0x5d, 0x59, + 0xcf, 0x79, 0x9f, 0x53, 0xe3, 0x1d, 0xe8, 0x67, 0x87, 0xde, 0x71, 0x31, 0x01, 0x3d, 0x69, 0xfa, + 0xec, 0x00, 0x5d, 0x07, 0x14, 0xb0, 0xbf, 0x31, 0x16, 0x04, 0x59, 0x85, 0x74, 0x2f, 0xa6, 0x82, + 0xbf, 0x2e, 0x52, 0xf0, 0x74, 0x85, 0x74, 0xd1, 0x8e, 0x15, 0x06, 0xd5, 0x24, 0x9e, 0x1b, 0x06, + 0xb3, 0xbe, 0x13, 0xcb, 0x7b, 0x5f, 0x95, 0x26, 0x59, 0x90, 0x00, 0xac, 0x71, 0xd8, 0x79, 0xb8, + 0x17, 0xb7, 0x7c, 0x67, 0xc7, 0xd8, 0x95, 0x1b, 0xb5, 0x28, 0x14, 0x08, 0x9b, 0x78, 0x76, 0x13, + 0xc6, 0xd3, 0x2f, 0x31, 0x47, 0x36, 0x58, 0x30, 0x6a, 0x4f, 0xc3, 0x39, 0x05, 0x35, 0x87, 0x3d, + 0xb5, 0xd8, 0x76, 0x84, 0x4c, 0xd0, 0x21, 0x99, 0x12, 0x80, 0x35, 0x8e, 0xfd, 0x8f, 0x2c, 0x38, + 0x99, 0x33, 0x68, 0x05, 0xa6, 0x38, 0x26, 0x5a, 0xda, 0xe4, 0xd9, 0x00, 0x6f, 0x87, 0x81, 0x3a, + 0xd9, 0x70, 0x64, 0xb8, 0xa3, 0x21, 0x3d, 0xe7, 0x78, 0x33, 0x96, 0x70, 0xfb, 0xb7, 0x4b, 0x30, + 0x9a, 0xe6, 0x35, 0x66, 0x69, 0x43, 0x7c, 0x98, 0xbc, 0xd8, 0x0d, 0xb7, 0x49, 0xb4, 0x43, 0xdf, + 0xdc, 0xca, 0xa4, 0x0d, 0x75, 0x60, 0xe0, 0x9c, 0xa7, 0x58, 0xbd, 0xe1, 0xba, 0x1a, 0x6d, 0x39, + 0x23, 0xaf, 0x17, 0x39, 0x23, 0xf5, 0xc7, 0x34, 0x43, 0x23, 0x14, 0x49, 0x6c, 0xd2, 0xa7, 0xb6, + 0x08, 0x8b, 0xc3, 0x9e, 0x69, 0x7b, 0x7e, 0xe2, 0x05, 0xe2, 0x95, 0xc5, 0x5c, 0x55, 0xb6, 0xc8, + 0x52, 0x27, 0x0a, 0xce, 0x7b, 0xce, 0xfe, 0x7e, 0x1f, 0xa8, 0x94, 0x6a, 0x16, 0xba, 0x56, 0x50, + 0xe0, 0xdf, 0x41, 0x93, 0xcf, 0xd4, 0xdc, 0xea, 0xdb, 0x2b, 0x96, 0x84, 0xbb, 0x72, 0x4c, 0x7f, + 0xae, 0x1a, 0xb0, 0x35, 0x0d, 0xc2, 0x26, 0x1e, 0xe5, 0xc4, 0xf7, 0xb6, 0x09, 0x7f, 0xa8, 0x3f, + 0xcd, 0xc9, 0xa2, 0x04, 0x60, 0x8d, 0x43, 0x39, 0xa9, 0x7b, 0x1b, 0x1b, 0xc2, 0x2f, 0xa1, 0x38, + 0xa1, 0xa3, 0x83, 0x19, 0x84, 0x57, 0xa4, 0x0f, 0xb7, 0x84, 0xfd, 0x6d, 0x54, 0xa4, 0x0f, 0xb7, + 0x30, 0x83, 0xd0, 0xaf, 0x14, 0x84, 0x51, 0xd3, 0xf1, 0xbd, 0xd7, 0x48, 0x5d, 0x51, 0x11, 0x76, + 0xb7, 0xfa, 0x4a, 0x57, 0x3b, 0x51, 0x70, 0xde, 0x73, 0x74, 0x42, 0xb7, 0x22, 0x52, 0xf7, 0xdc, + 0xc4, 0xec, 0x0d, 0xd2, 0x13, 0x7a, 0xa5, 0x03, 0x03, 0xe7, 0x3c, 0x85, 0xa6, 0x61, 0x54, 0xa6, + 0xc4, 0xcb, 0x82, 0x47, 0x83, 0xe9, 0x02, 0x2b, 0x38, 0x0d, 0xc6, 0x59, 0x7c, 0x2a, 0x24, 0x9b, + 0xa2, 0x26, 0x1a, 0x33, 0xd3, 0x0d, 0x21, 0x29, 0x6b, 0xa5, 0x61, 0x85, 0x61, 0x7f, 0xa2, 0x4c, + 0x95, 0x7a, 0x97, 0xd2, 0x83, 0xc7, 0x16, 0x68, 0x9a, 0x9e, 0x91, 0x7d, 0x3d, 0xcc, 0xc8, 0x67, + 0x61, 0xe8, 0x66, 0x1c, 0x06, 0x2a, 0x88, 0xb3, 0xd2, 0x35, 0x88, 0xd3, 0xc0, 0xca, 0x0f, 0xe2, + 0xec, 0x2f, 0x2a, 0x88, 0x73, 0xe0, 0x1e, 0x83, 0x38, 0xff, 0xb0, 0x02, 0xea, 0x76, 0x9f, 0xab, + 0x24, 0xb9, 0x15, 0x46, 0x5b, 0x5e, 0xd0, 0x60, 0xa5, 0x04, 0xbe, 0x66, 0xc1, 0x10, 0x5f, 0x2f, + 0x8b, 0x66, 0x12, 0xde, 0x46, 0x41, 0xd7, 0xc6, 0xa4, 0x88, 0x4d, 0xae, 0x19, 0x84, 0x32, 0x37, + 0xff, 0x9a, 0x20, 0x9c, 0xe2, 0x08, 0x7d, 0x14, 0x40, 0x3a, 0x71, 0x37, 0xa4, 0x04, 0x5e, 0x28, + 0x86, 0x3f, 0x4c, 0x36, 0xb4, 0x49, 0xbd, 0xa6, 0x88, 0x60, 0x83, 0x20, 0xfa, 0x8c, 0x4e, 0x50, + 0xe4, 0xd9, 0x1e, 0x1f, 0x3e, 0x92, 0xb1, 0xe9, 0x25, 0x3d, 0x11, 0xc3, 0x80, 0x17, 0x34, 0xe8, + 0x3c, 0x11, 0xc1, 0x6e, 0x6f, 0xcb, 0x2b, 0xc3, 0xb1, 0x18, 0x3a, 0xf5, 0x19, 0xc7, 0x77, 0x02, + 0x97, 0x44, 0x0b, 0x1c, 0xdd, 0xbc, 0xbb, 0x9f, 0x35, 0x60, 0xd9, 0x51, 0xc7, 0xbd, 0x48, 0x95, + 0x5e, 0xee, 0x45, 0x3a, 0xfb, 0x3e, 0x18, 0xeb, 0xf8, 0x98, 0x07, 0xca, 0x46, 0xbc, 0xf7, 0x44, + 0x46, 0xfb, 0x77, 0xfa, 0xb5, 0xd2, 0xba, 0x1a, 0xd6, 0xf9, 0x35, 0x3b, 0x91, 0xfe, 0xa2, 0xc2, + 0x64, 0x2e, 0x70, 0x8a, 0x18, 0xf7, 0xff, 0xab, 0x46, 0x6c, 0x92, 0xa4, 0x73, 0xb4, 0xe5, 0x44, + 0x24, 0x38, 0xea, 0x39, 0xba, 0xa2, 0x88, 0x60, 0x83, 0x20, 0xda, 0x4c, 0xa5, 0x23, 0x5d, 0x3c, + 0x7c, 0x3a, 0x12, 0x2b, 0x50, 0x96, 0x77, 0x1b, 0xc5, 0x17, 0x2d, 0x18, 0x09, 0x52, 0x33, 0xb7, + 0x98, 0x08, 0xe4, 0xfc, 0x55, 0xc1, 0x2f, 0x87, 0x4b, 0xb7, 0xe1, 0x0c, 0xfd, 0x3c, 0x95, 0x56, + 0x39, 0xa0, 0x4a, 0xd3, 0xd7, 0x7c, 0xf5, 0x77, 0xbb, 0xe6, 0x0b, 0x05, 0xea, 0x9e, 0xc3, 0x81, + 0xc2, 0xef, 0x39, 0x84, 0x9c, 0x3b, 0x0e, 0x6f, 0x40, 0xcd, 0x8d, 0x88, 0x93, 0xdc, 0xe3, 0x95, + 0x77, 0x2c, 0xb6, 0x63, 0x56, 0x76, 0x80, 0x75, 0x5f, 0xf6, 0xff, 0xe9, 0x83, 0x13, 0x72, 0x44, + 0x64, 0xf6, 0x02, 0xd5, 0x8f, 0x9c, 0xae, 0xb6, 0x95, 0x95, 0x7e, 0xbc, 0x24, 0x01, 0x58, 0xe3, + 0x50, 0x7b, 0xac, 0x1d, 0x93, 0xe5, 0x16, 0x09, 0x16, 0xbd, 0xf5, 0x58, 0x1c, 0xc6, 0xaa, 0x85, + 0x72, 0x4d, 0x83, 0xb0, 0x89, 0x47, 0x6d, 0x7b, 0xc7, 0x30, 0x5a, 0x0d, 0xdb, 0x5e, 0x1a, 0xaa, + 0x12, 0x8e, 0x7e, 0x25, 0xb7, 0x16, 0x72, 0x31, 0x39, 0x7f, 0x1d, 0x49, 0x1b, 0x07, 0xbc, 0x25, + 0xf5, 0xef, 0x5b, 0x70, 0x9a, 0xb7, 0xca, 0x91, 0xbc, 0xd6, 0xaa, 0x3b, 0x09, 0x89, 0x8b, 0xb9, + 0xc9, 0x20, 0x87, 0x3f, 0xed, 0x5e, 0xce, 0x23, 0x8b, 0xf3, 0xb9, 0x41, 0xaf, 0x5b, 0x30, 0xba, + 0x95, 0x2a, 0x17, 0x23, 0x55, 0xc7, 0x61, 0x2b, 0x39, 0xa4, 0x3a, 0xd5, 0x4b, 0x2d, 0xdd, 0x1e, + 0xe3, 0x2c, 0x75, 0xfb, 0x7f, 0x58, 0x60, 0x8a, 0xd1, 0xe3, 0xaf, 0x32, 0x73, 0x70, 0x53, 0x50, + 0x5a, 0x97, 0x95, 0xae, 0xd6, 0xe5, 0xa3, 0x50, 0x6e, 0x7b, 0x75, 0xb1, 0xbf, 0xd0, 0x47, 0xc4, + 0x0b, 0x73, 0x98, 0xb6, 0xdb, 0xff, 0xb2, 0xa2, 0xdd, 0x20, 0x22, 0xa5, 0xee, 0x47, 0xe2, 0xb5, + 0x37, 0x54, 0x9d, 0x3a, 0xfe, 0xe6, 0x57, 0x3b, 0xea, 0xd4, 0xfd, 0xf4, 0xc1, 0x33, 0x26, 0xf9, + 0x00, 0x75, 0x2b, 0x53, 0x37, 0xb0, 0x4f, 0xba, 0xe4, 0x4d, 0xa8, 0xd2, 0x2d, 0x18, 0xf3, 0x67, + 0x56, 0x53, 0x4c, 0x55, 0x2f, 0x89, 0xf6, 0xbb, 0xbb, 0x13, 0xef, 0x3e, 0x38, 0x5b, 0xf2, 0x69, + 0xac, 0xfa, 0x47, 0x31, 0xd4, 0xe8, 0x6f, 0x96, 0xd9, 0x29, 0x36, 0x77, 0xd7, 0x94, 0xcc, 0x94, + 0x80, 0x42, 0xd2, 0x46, 0x35, 0x1d, 0x14, 0x40, 0x8d, 0x5d, 0x28, 0xcd, 0x88, 0xf2, 0x3d, 0xe0, + 0x8a, 0xca, 0xaf, 0x94, 0x80, 0xbb, 0xbb, 0x13, 0x2f, 0x1c, 0x9c, 0xa8, 0x7a, 0x1c, 0x6b, 0x12, + 0xf6, 0x97, 0xfa, 0xf4, 0xdc, 0x15, 0xe5, 0x09, 0x7f, 0x24, 0xe6, 0xee, 0xf3, 0x99, 0xb9, 0x7b, + 0xae, 0x63, 0xee, 0x8e, 0xe8, 0x8b, 0x8f, 0x53, 0xb3, 0xf1, 0xb8, 0x0d, 0x81, 0xfd, 0xfd, 0x0d, + 0xcc, 0x02, 0x7a, 0xb5, 0xed, 0x45, 0x24, 0x5e, 0x89, 0xda, 0x81, 0x17, 0x34, 0xd8, 0x74, 0xac, + 0x9a, 0x16, 0x50, 0x0a, 0x8c, 0xb3, 0xf8, 0x74, 0x53, 0x4f, 0xbf, 0xf9, 0x0d, 0x67, 0x9b, 0xcf, + 0x2a, 0xa3, 0x62, 0xdb, 0xaa, 0x68, 0xc7, 0x0a, 0xc3, 0xfe, 0x06, 0x3b, 0x45, 0x37, 0x52, 0xca, + 0xe9, 0x9c, 0xf0, 0xd9, 0x0d, 0xde, 0xbc, 0xdc, 0x9b, 0x9a, 0x13, 0xfc, 0xda, 0x6e, 0x0e, 0x43, + 0xb7, 0x60, 0x60, 0x9d, 0xdf, 0x45, 0x59, 0x4c, 0xc5, 0x7d, 0x71, 0xb1, 0x25, 0xbb, 0xe5, 0x47, + 0xde, 0x72, 0x79, 0x57, 0xff, 0xc4, 0x92, 0x9a, 0xfd, 0xed, 0x0a, 0x8c, 0x66, 0xee, 0x78, 0x4e, + 0x15, 0xda, 0x2d, 0xed, 0x5b, 0x68, 0xf7, 0x43, 0x00, 0x75, 0xd2, 0xf2, 0xc3, 0x1d, 0x66, 0x8e, + 0xf5, 0x1d, 0xd8, 0x1c, 0x53, 0x16, 0xfc, 0x9c, 0xea, 0x05, 0x1b, 0x3d, 0x8a, 0x1a, 0x77, 0xbc, + 0x6e, 0x6f, 0xa6, 0xc6, 0x9d, 0x71, 0x2f, 0x47, 0xff, 0xf1, 0xde, 0xcb, 0xe1, 0xc1, 0x28, 0x67, + 0x51, 0x25, 0x6e, 0xdf, 0x43, 0x7e, 0x36, 0x4b, 0x7d, 0x99, 0x4b, 0x77, 0x83, 0xb3, 0xfd, 0xde, + 0xcf, 0x2b, 0xdc, 0xd1, 0x3b, 0xa0, 0x26, 0xbf, 0x73, 0x3c, 0x5e, 0xd3, 0xc5, 0x2f, 0xe4, 0x34, + 0x60, 0x57, 0xab, 0x8b, 0x9f, 0x1d, 0x35, 0x28, 0xe0, 0x7e, 0xd5, 0xa0, 0xb0, 0xbf, 0x50, 0xa2, + 0x76, 0x3c, 0xe7, 0x4b, 0x95, 0x53, 0x7a, 0x02, 0xfa, 0x9d, 0x76, 0xb2, 0x19, 0x76, 0xdc, 0x66, + 0x39, 0xcd, 0x5a, 0xb1, 0x80, 0xa2, 0x45, 0xe8, 0xab, 0xeb, 0x12, 0x39, 0x07, 0xf9, 0x9e, 0xda, + 0x25, 0xea, 0x24, 0x04, 0xb3, 0x5e, 0xd0, 0x23, 0xd0, 0x97, 0x38, 0x0d, 0x99, 0xad, 0xc7, 0x32, + 0xb4, 0xd7, 0x9c, 0x46, 0x8c, 0x59, 0xab, 0xa9, 0xbe, 0xfb, 0xf6, 0x51, 0xdf, 0x2f, 0xc0, 0x70, + 0xec, 0x35, 0x02, 0x27, 0x69, 0x47, 0xc4, 0x38, 0x35, 0xd4, 0x31, 0x23, 0x26, 0x10, 0xa7, 0x71, + 0xed, 0xdf, 0x1d, 0x82, 0x53, 0xab, 0xb3, 0x4b, 0xb2, 0xf0, 0xfb, 0x91, 0x25, 0xdc, 0xe5, 0xd1, + 0x38, 0xbe, 0x84, 0xbb, 0x2e, 0xd4, 0x7d, 0x23, 0xe1, 0xce, 0x37, 0x12, 0xee, 0xd2, 0xd9, 0x4f, + 0xe5, 0x22, 0xb2, 0x9f, 0xf2, 0x38, 0xe8, 0x25, 0xfb, 0xe9, 0xc8, 0x32, 0xf0, 0xf6, 0x64, 0xe8, + 0x40, 0x19, 0x78, 0x2a, 0x3d, 0xb1, 0x90, 0xbc, 0x94, 0x2e, 0x9f, 0x2a, 0x37, 0x3d, 0x51, 0xa5, + 0x86, 0xf1, 0x9c, 0x2b, 0x21, 0xea, 0x5f, 0x2e, 0x9e, 0x81, 0x1e, 0x52, 0xc3, 0x44, 0xda, 0x97, + 0x99, 0x8e, 0x38, 0x50, 0x44, 0x3a, 0x62, 0x1e, 0x3b, 0xfb, 0xa6, 0x23, 0xbe, 0x00, 0xc3, 0xae, + 0x1f, 0x06, 0x64, 0x25, 0x0a, 0x93, 0xd0, 0x0d, 0x7d, 0x61, 0xd6, 0xeb, 0x8b, 0x68, 0x4c, 0x20, + 0x4e, 0xe3, 0x76, 0xcb, 0x65, 0xac, 0x1d, 0x36, 0x97, 0x11, 0xee, 0x53, 0x2e, 0xe3, 0x2f, 0xea, + 0xac, 0xfb, 0x41, 0xf6, 0x45, 0x3e, 0x54, 0xfc, 0x17, 0xe9, 0xe9, 0xaa, 0xbe, 0x37, 0xf8, 0x75, + 0x92, 0xd4, 0x30, 0x9e, 0x0d, 0x9b, 0xd4, 0xf0, 0x1b, 0x62, 0x43, 0xf2, 0xca, 0x11, 0x4c, 0xd8, + 0x1b, 0xab, 0x9a, 0x8c, 0xba, 0x62, 0x52, 0x37, 0xe1, 0x34, 0x23, 0x87, 0xa9, 0x0a, 0xf0, 0x95, + 0x12, 0xfc, 0xd8, 0xbe, 0x2c, 0xa0, 0x5b, 0x00, 0x89, 0xd3, 0x10, 0x13, 0x55, 0x1c, 0x98, 0x1c, + 0x32, 0xb0, 0x73, 0x4d, 0xf6, 0xc7, 0xcb, 0xd9, 0xa8, 0xbf, 0xec, 0x28, 0x42, 0xfe, 0x66, 0xf1, + 0x9c, 0xa1, 0xdf, 0x51, 0xf5, 0x13, 0x87, 0x3e, 0xc1, 0x0c, 0x42, 0xd5, 0x7f, 0x44, 0x1a, 0xfa, + 0x2e, 0x76, 0xf5, 0xf9, 0x30, 0x6b, 0xc5, 0x02, 0x8a, 0x9e, 0x83, 0x41, 0xc7, 0xf7, 0x79, 0xd2, + 0x10, 0x89, 0xc5, 0x0d, 0x51, 0xba, 0xfc, 0xa0, 0x06, 0x61, 0x13, 0xcf, 0xfe, 0xcb, 0x12, 0x4c, + 0xec, 0x23, 0x53, 0x3a, 0x92, 0x45, 0x2b, 0x3d, 0x27, 0x8b, 0x8a, 0x44, 0x8a, 0xfe, 0x2e, 0x89, + 0x14, 0xcf, 0xc1, 0x60, 0x42, 0x9c, 0xa6, 0x08, 0x05, 0x13, 0x9e, 0x00, 0x7d, 0x02, 0xac, 0x41, + 0xd8, 0xc4, 0xa3, 0x52, 0x6c, 0xc4, 0x71, 0x5d, 0x12, 0xc7, 0x32, 0x53, 0x42, 0x78, 0x53, 0x0b, + 0x4b, 0xc3, 0x60, 0x4e, 0xea, 0xe9, 0x14, 0x09, 0x9c, 0x21, 0x99, 0x1d, 0xf0, 0x5a, 0x8f, 0x03, + 0xfe, 0xf5, 0x12, 0x3c, 0xba, 0xa7, 0x76, 0xeb, 0x39, 0x89, 0xa5, 0x1d, 0x93, 0x28, 0x3b, 0x71, + 0xae, 0xc5, 0x24, 0xc2, 0x0c, 0xc2, 0x47, 0xa9, 0xd5, 0x32, 0xee, 0xba, 0x2f, 0x3a, 0xa3, 0x8b, + 0x8f, 0x52, 0x8a, 0x04, 0xce, 0x90, 0xbc, 0xd7, 0x69, 0xf9, 0xed, 0x3e, 0x78, 0xbc, 0x07, 0x1b, + 0xa0, 0xc0, 0xcc, 0xb7, 0x74, 0x96, 0x66, 0xf9, 0x3e, 0x65, 0x69, 0xde, 0xdb, 0x70, 0xbd, 0x99, + 0xdc, 0xd9, 0x53, 0x86, 0xdd, 0x37, 0x4a, 0x70, 0xb6, 0xbb, 0xc1, 0x82, 0xde, 0x03, 0xa3, 0x91, + 0x0a, 0x7d, 0x33, 0x13, 0x3c, 0x4f, 0x72, 0x7f, 0x4b, 0x0a, 0x84, 0xb3, 0xb8, 0x68, 0x12, 0xa0, + 0xe5, 0x24, 0x9b, 0xf1, 0x85, 0xdb, 0x5e, 0x9c, 0x88, 0x32, 0x4f, 0x23, 0xfc, 0x84, 0x4f, 0xb6, + 0x62, 0x03, 0x83, 0x92, 0x63, 0xff, 0xe6, 0xc2, 0xab, 0x61, 0xc2, 0x1f, 0xe2, 0x9b, 0xad, 0x93, + 0xf2, 0x52, 0x1c, 0x03, 0x84, 0xb3, 0xb8, 0x94, 0x1c, 0x3b, 0x43, 0xe6, 0x8c, 0xf2, 0x5d, 0x18, + 0x23, 0xb7, 0xa8, 0x5a, 0xb1, 0x81, 0x91, 0x4d, 0x5d, 0xad, 0xec, 0x9f, 0xba, 0x6a, 0xff, 0x8b, + 0x12, 0x9c, 0xe9, 0x6a, 0xf0, 0xf6, 0x26, 0xa6, 0x1e, 0xbc, 0x74, 0xd3, 0x7b, 0x5c, 0x61, 0x07, + 0x4b, 0x53, 0xfc, 0xd3, 0x2e, 0x33, 0x4d, 0xa4, 0x29, 0xde, 0x7b, 0xf5, 0x85, 0x07, 0x6f, 0x3c, + 0x3b, 0x32, 0x13, 0xfb, 0x0e, 0x90, 0x99, 0x98, 0xf9, 0x18, 0x95, 0x1e, 0xb5, 0xc3, 0x9f, 0xf7, + 0x75, 0x1d, 0x5e, 0xba, 0x41, 0xee, 0xc9, 0x9b, 0x3d, 0x07, 0x27, 0xbc, 0x80, 0x5d, 0x90, 0xb6, + 0xda, 0x5e, 0x17, 0x95, 0x7f, 0x78, 0x79, 0x4b, 0x95, 0xfe, 0xb0, 0x90, 0x81, 0xe3, 0x8e, 0x27, + 0x1e, 0xc0, 0x4c, 0xd1, 0x7b, 0x1b, 0xd2, 0x03, 0x4a, 0xee, 0x65, 0x38, 0x2d, 0x87, 0x62, 0xd3, + 0x89, 0x48, 0x5d, 0x28, 0xdb, 0x58, 0x24, 0xbc, 0x9c, 0xe1, 0x49, 0x33, 0x39, 0x08, 0x38, 0xff, + 0x39, 0x76, 0x27, 0x55, 0xd8, 0xf2, 0x5c, 0xb1, 0x15, 0xd4, 0x77, 0x52, 0xd1, 0x46, 0xcc, 0x61, + 0x5a, 0x5f, 0xd4, 0x8e, 0x47, 0x5f, 0x7c, 0x08, 0x6a, 0x6a, 0xbc, 0x79, 0xec, 0xbe, 0x9a, 0xe4, + 0x1d, 0xb1, 0xfb, 0x6a, 0x86, 0x1b, 0x58, 0xfb, 0x5d, 0x9a, 0xfa, 0x4e, 0x18, 0x52, 0xde, 0xaf, + 0x5e, 0x6f, 0x06, 0xb3, 0xbf, 0xd4, 0x0f, 0xc3, 0xa9, 0x6a, 0x9f, 0x29, 0xb7, 0xb7, 0xb5, 0xaf, + 0xdb, 0x9b, 0xa5, 0x6d, 0xb4, 0x03, 0x79, 0x6d, 0xa0, 0x91, 0xb6, 0xd1, 0x0e, 0x08, 0xe6, 0x30, + 0xba, 0xe9, 0xa8, 0x47, 0x3b, 0xb8, 0x1d, 0x88, 0x38, 0x54, 0xb5, 0xe9, 0x98, 0x63, 0xad, 0x58, + 0x40, 0xd1, 0xc7, 0x2d, 0x18, 0x8a, 0xd9, 0x99, 0x0a, 0x3f, 0x34, 0x10, 0x93, 0xfc, 0xf2, 0xe1, + 0x8b, 0x99, 0xaa, 0xca, 0xb6, 0x2c, 0x6e, 0xc9, 0x6c, 0xc1, 0x29, 0x8a, 0xe8, 0x53, 0x16, 0xd4, + 0xd4, 0xed, 0x46, 0xe2, 0x0e, 0xd0, 0xd5, 0x62, 0x8b, 0xa9, 0x72, 0x6f, 0xb3, 0x3a, 0x9e, 0x52, + 0x55, 0x2d, 0xb1, 0x26, 0x8c, 0x62, 0xe5, 0xd1, 0x1f, 0x38, 0x1a, 0x8f, 0x3e, 0xe4, 0x78, 0xf3, + 0xdf, 0x01, 0xb5, 0xa6, 0x13, 0x78, 0x1b, 0x24, 0x4e, 0xb8, 0x93, 0x5d, 0xd6, 0x78, 0x96, 0x8d, + 0x58, 0xc3, 0xa9, 0x01, 0x10, 0xb3, 0x17, 0x4b, 0x0c, 0xaf, 0x38, 0x33, 0x00, 0x56, 0x75, 0x33, + 0x36, 0x71, 0x4c, 0x17, 0x3e, 0xdc, 0x57, 0x17, 0xfe, 0xe0, 0xde, 0x2e, 0x7c, 0xfb, 0x9f, 0x5a, + 0x70, 0x3a, 0xf7, 0xab, 0x3d, 0xb8, 0xe1, 0xa8, 0xf6, 0x97, 0x2b, 0x70, 0x32, 0xa7, 0x6c, 0x2f, + 0xda, 0x31, 0xe7, 0xb3, 0x55, 0x44, 0x64, 0x47, 0x3a, 0x50, 0x41, 0x0e, 0x63, 0xce, 0x24, 0x3e, + 0xd8, 0x01, 0x9a, 0x3e, 0xc4, 0x2a, 0x1f, 0xef, 0x21, 0x96, 0x31, 0x2d, 0xfb, 0xee, 0xeb, 0xb4, + 0xac, 0xec, 0x73, 0xb2, 0xf4, 0x4d, 0x0b, 0xc6, 0x9b, 0x5d, 0xee, 0x8a, 0x10, 0xee, 0xe0, 0xeb, + 0x47, 0x73, 0x13, 0xc5, 0xcc, 0x23, 0x77, 0x76, 0x27, 0xba, 0x5e, 0xd1, 0x81, 0xbb, 0x72, 0x65, + 0x7f, 0xbf, 0x0c, 0xac, 0x66, 0x34, 0x2b, 0xcd, 0xb8, 0x83, 0x3e, 0x66, 0x56, 0xff, 0xb6, 0x8a, + 0xaa, 0x54, 0xcd, 0x3b, 0x57, 0xd5, 0xc3, 0xf9, 0x08, 0xe6, 0x15, 0x13, 0xcf, 0x0a, 0xad, 0x52, + 0x0f, 0x42, 0xcb, 0x97, 0x65, 0xd6, 0xcb, 0xc5, 0x97, 0x59, 0xaf, 0x65, 0x4b, 0xac, 0xef, 0xfd, + 0x89, 0xfb, 0x1e, 0xc8, 0x4f, 0xfc, 0xab, 0x16, 0x17, 0x3c, 0x99, 0xaf, 0xa0, 0x2d, 0x03, 0x6b, + 0x0f, 0xcb, 0xe0, 0x29, 0xa8, 0xc6, 0xc4, 0xdf, 0xb8, 0x44, 0x1c, 0x5f, 0x58, 0x10, 0x3a, 0xaa, + 0x40, 0xb4, 0x63, 0x85, 0xc1, 0xee, 0x61, 0xf6, 0xfd, 0xf0, 0xd6, 0x85, 0x66, 0x2b, 0xd9, 0x11, + 0xb6, 0x84, 0xbe, 0x87, 0x59, 0x41, 0xb0, 0x81, 0x65, 0xff, 0xbd, 0x12, 0x9f, 0x81, 0x22, 0x34, + 0xe5, 0xf9, 0xcc, 0xcd, 0x99, 0xbd, 0x47, 0x75, 0x7c, 0x04, 0xc0, 0x0d, 0x9b, 0x2d, 0x6a, 0x67, + 0xae, 0x85, 0xe2, 0xa4, 0xee, 0xd2, 0xa1, 0xef, 0xe9, 0x17, 0xfd, 0xe9, 0xd7, 0xd0, 0x6d, 0xd8, + 0xa0, 0x97, 0x92, 0xa5, 0xe5, 0x7d, 0x65, 0x69, 0x4a, 0xac, 0xf4, 0xed, 0xa3, 0xed, 0xfe, 0xd2, + 0x82, 0x94, 0x45, 0x84, 0x5a, 0x50, 0xa1, 0xec, 0xee, 0x88, 0x15, 0xba, 0x5c, 0x9c, 0xf9, 0x45, + 0x45, 0xa3, 0x98, 0xf6, 0xec, 0x27, 0xe6, 0x84, 0x90, 0x2f, 0x22, 0x58, 0xf8, 0xa8, 0x5e, 0x2d, + 0x8e, 0xe0, 0xa5, 0x30, 0xdc, 0xe2, 0xc7, 0xcd, 0x3a, 0x1a, 0xc6, 0x7e, 0x1e, 0xc6, 0x3a, 0x98, + 0x62, 0x97, 0xe4, 0x85, 0x54, 0xfb, 0x64, 0xa6, 0x2b, 0x4b, 0xe8, 0xc5, 0x1c, 0x66, 0x7f, 0xc3, + 0x82, 0x13, 0xd9, 0xee, 0xd1, 0x1b, 0x16, 0x8c, 0xc5, 0xd9, 0xfe, 0x8e, 0x6a, 0xec, 0x54, 0x14, + 0x6a, 0x07, 0x08, 0x77, 0x32, 0x61, 0xff, 0x5f, 0x31, 0xf9, 0x6f, 0x78, 0x41, 0x3d, 0xbc, 0xa5, + 0x0c, 0x13, 0xab, 0xab, 0x61, 0x42, 0xd7, 0xa3, 0xbb, 0x49, 0xea, 0x6d, 0xbf, 0x23, 0x3d, 0x78, + 0x55, 0xb4, 0x63, 0x85, 0xc1, 0xb2, 0x21, 0xdb, 0xe2, 0x1e, 0x86, 0xcc, 0xa4, 0x9c, 0x13, 0xed, + 0x58, 0x61, 0xa0, 0x67, 0x61, 0xc8, 0x78, 0x49, 0x39, 0x2f, 0x99, 0x41, 0x6e, 0xa8, 0xcc, 0x18, + 0xa7, 0xb0, 0xd0, 0x24, 0x80, 0x32, 0x72, 0xa4, 0x8a, 0x64, 0x8e, 0x29, 0x25, 0x89, 0x62, 0x6c, + 0x60, 0xb0, 0xdc, 0x63, 0xbf, 0x1d, 0xb3, 0x93, 0x97, 0x7e, 0x5d, 0x1b, 0x78, 0x56, 0xb4, 0x61, + 0x05, 0xa5, 0xd2, 0xa4, 0xe9, 0x04, 0x6d, 0xc7, 0xa7, 0x23, 0x24, 0xb6, 0x9a, 0x6a, 0x19, 0x2e, + 0x29, 0x08, 0x36, 0xb0, 0xe8, 0x1b, 0x27, 0x5e, 0x93, 0xbc, 0x14, 0x06, 0x32, 0x7a, 0x50, 0x1f, + 0xc6, 0x89, 0x76, 0xac, 0x30, 0xec, 0xbf, 0xb0, 0x60, 0x54, 0x17, 0x3d, 0xe0, 0xd7, 0xe1, 0x9b, + 0x3b, 0x63, 0x6b, 0xdf, 0x9d, 0x71, 0x3a, 0xc5, 0xbb, 0xd4, 0x53, 0x8a, 0xb7, 0x99, 0x7d, 0x5d, + 0xde, 0x33, 0xfb, 0xfa, 0x27, 0xf4, 0x55, 0xcb, 0x3c, 0x4d, 0x7b, 0x30, 0xef, 0x9a, 0x65, 0x64, + 0x43, 0xbf, 0xeb, 0xa8, 0xe2, 0x40, 0x43, 0x7c, 0xef, 0x30, 0x3b, 0xcd, 0x90, 0x04, 0xc4, 0x5e, + 0x86, 0x9a, 0x3a, 0x93, 0x92, 0x1b, 0x55, 0x2b, 0x7f, 0xa3, 0xda, 0x53, 0x16, 0xe8, 0xcc, 0xfa, + 0xb7, 0x7e, 0xf0, 0xd8, 0x5b, 0xfe, 0xf8, 0x07, 0x8f, 0xbd, 0xe5, 0x7b, 0x3f, 0x78, 0xec, 0x2d, + 0x1f, 0xbf, 0xf3, 0x98, 0xf5, 0xad, 0x3b, 0x8f, 0x59, 0x7f, 0x7c, 0xe7, 0x31, 0xeb, 0x7b, 0x77, + 0x1e, 0xb3, 0xbe, 0x7f, 0xe7, 0x31, 0xeb, 0x8b, 0xff, 0xe5, 0xb1, 0xb7, 0xbc, 0x94, 0x1b, 0x3e, + 0x4a, 0x7f, 0x3c, 0xed, 0xd6, 0xa7, 0xb6, 0xcf, 0xb3, 0x08, 0x46, 0xba, 0xbc, 0xa6, 0x8c, 0x39, + 0x35, 0x25, 0x97, 0xd7, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x6b, 0x48, 0xca, 0xc0, 0x22, 0xeb, + 0x00, 0x00, } func (m *AWSAuthConfig) Marshal() (dAtA []byte, err error) { @@ -7369,6 +7372,14 @@ func (m *ApplicationSourceHelm) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + i-- + if m.SkipTests { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x70 if len(m.APIVersions) > 0 { for iNdEx := len(m.APIVersions) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.APIVersions[iNdEx]) @@ -8728,6 +8739,14 @@ func (m *ClusterGenerator) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + i-- + if m.FlatList { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 if len(m.Values) > 0 { keysForValues := make([]string, 0, len(m.Values)) for k := range m.Values { @@ -15689,6 +15708,7 @@ func (m *ApplicationSourceHelm) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + n += 2 return n } @@ -16182,6 +16202,7 @@ func (m *ClusterGenerator) Size() (n int) { n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) } } + n += 2 return n } @@ -19035,6 +19056,7 @@ func (this *ApplicationSourceHelm) String() string { `Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`, `KubeVersion:` + fmt.Sprintf("%v", this.KubeVersion) + `,`, `APIVersions:` + fmt.Sprintf("%v", this.APIVersions) + `,`, + `SkipTests:` + fmt.Sprintf("%v", this.SkipTests) + `,`, `}`, }, "") return s @@ -19412,6 +19434,7 @@ func (this *ClusterGenerator) String() string { `Selector:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Selector), "LabelSelector", "v1.LabelSelector", 1), `&`, ``, 1) + `,`, `Template:` + strings.Replace(strings.Replace(this.Template.String(), "ApplicationSetTemplate", "ApplicationSetTemplate", 1), `&`, ``, 1) + `,`, `Values:` + mapStringForValues + `,`, + `FlatList:` + fmt.Sprintf("%v", this.FlatList) + `,`, `}`, }, "") return s @@ -27732,6 +27755,26 @@ func (m *ApplicationSourceHelm) Unmarshal(dAtA []byte) error { } m.APIVersions = append(m.APIVersions, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SkipTests", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.SkipTests = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -31950,6 +31993,26 @@ func (m *ClusterGenerator) Unmarshal(dAtA []byte) error { } m.Values[mapkey] = mapvalue iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field FlatList", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.FlatList = bool(v != 0) default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/pkg/apis/application/v1alpha1/generated.proto b/pkg/apis/application/v1alpha1/generated.proto index 0b79d47202cb90..e16c8b5aa3c261 100644 --- a/pkg/apis/application/v1alpha1/generated.proto +++ b/pkg/apis/application/v1alpha1/generated.proto @@ -156,7 +156,7 @@ message ApplicationDestinationServiceAccount { // Namespace specifies the target namespace for the application's resources. optional string namespace = 2; - // ServiceAccountName to be used for impersonation during the sync operation + // DefaultServiceAccount to be used for impersonation during the sync operation optional string defaultServiceAccount = 3; } @@ -515,6 +515,9 @@ message ApplicationSourceHelm { // APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, // Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. repeated string apiVersions = 13; + + // SkipTests skips test manifest installation step (Helm's --skip-tests). + optional bool skipTests = 14; } // ApplicationSourceJsonnet holds options specific to applications of type Jsonnet @@ -851,6 +854,9 @@ message ClusterGenerator { // Values contains key/value pairs which are passed directly as parameters to the template map values = 3; + + // returns the clusters a single 'clusters' value in the template + optional bool flatList = 4; } // ClusterInfo contains information about the cluster diff --git a/pkg/apis/application/v1alpha1/openapi_generated.go b/pkg/apis/application/v1alpha1/openapi_generated.go index 1b2533532bc0e6..5221381ed80da3 100644 --- a/pkg/apis/application/v1alpha1/openapi_generated.go +++ b/pkg/apis/application/v1alpha1/openapi_generated.go @@ -2997,6 +2997,13 @@ func schema_pkg_apis_application_v1alpha1_ClusterGenerator(ref common.ReferenceC }, }, }, + "flatList": { + SchemaProps: spec.SchemaProps{ + Description: "returns the clusters a single 'clusters' value in the template", + Type: []string{"boolean"}, + Format: "", + }, + }, }, }, }, diff --git a/pkg/apis/application/v1alpha1/types.go b/pkg/apis/application/v1alpha1/types.go index 1337bd8c72772b..0795cce32a678b 100644 --- a/pkg/apis/application/v1alpha1/types.go +++ b/pkg/apis/application/v1alpha1/types.go @@ -395,6 +395,8 @@ type ApplicationSourceHelm struct { // APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, // Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. APIVersions []string `json:"apiVersions,omitempty" protobuf:"bytes,13,opt,name=apiVersions"` + // SkipTests skips test manifest installation step (Helm's --skip-tests). + SkipTests bool `json:"skipTests,omitempty" protobuf:"bytes,14,opt,name=skipTests"` } // HelmParameter is a parameter that's passed to helm template during manifest generation @@ -476,7 +478,7 @@ func (in *ApplicationSourceHelm) AddFileParameter(p HelmFileParameter) { // IsZero Returns true if the Helm options in an application source are considered zero func (h *ApplicationSourceHelm) IsZero() bool { - return h == nil || (h.Version == "") && (h.ReleaseName == "") && len(h.ValueFiles) == 0 && len(h.Parameters) == 0 && len(h.FileParameters) == 0 && h.ValuesIsEmpty() && !h.PassCredentials && !h.IgnoreMissingValueFiles && !h.SkipCrds && h.KubeVersion == "" && len(h.APIVersions) == 0 && h.Namespace == "" + return h == nil || (h.Version == "") && (h.ReleaseName == "") && len(h.ValueFiles) == 0 && len(h.Parameters) == 0 && len(h.FileParameters) == 0 && h.ValuesIsEmpty() && !h.PassCredentials && !h.IgnoreMissingValueFiles && !h.SkipCrds && !h.SkipTests && h.KubeVersion == "" && len(h.APIVersions) == 0 && h.Namespace == "" } // KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: @@ -2767,11 +2769,11 @@ type KustomizeOptions struct { // ApplicationDestinationServiceAccount holds information about the service account to be impersonated for the application sync operation. type ApplicationDestinationServiceAccount struct { // Server specifies the URL of the target cluster's Kubernetes control plane API. - Server string `json:"server,omitempty" protobuf:"bytes,1,opt,name=server"` + Server string `json:"server" protobuf:"bytes,1,opt,name=server"` // Namespace specifies the target namespace for the application's resources. Namespace string `json:"namespace,omitempty" protobuf:"bytes,2,opt,name=namespace"` - // ServiceAccountName to be used for impersonation during the sync operation - DefaultServiceAccount string `json:"defaultServiceAccount,omitempty" protobuf:"bytes,3,opt,name=defaultServiceAccount"` + // DefaultServiceAccount to be used for impersonation during the sync operation + DefaultServiceAccount string `json:"defaultServiceAccount" protobuf:"bytes,3,opt,name=defaultServiceAccount"` } // CascadedDeletion indicates if the deletion finalizer is set and controller should delete the application and it's cascaded resources @@ -3098,7 +3100,7 @@ func SetK8SConfigDefaults(config *rest.Config) error { } // RawRestConfig returns a go-client REST config from cluster that might be serialized into the file using kube.WriteKubeConfig method. -func (c *Cluster) RawRestConfig() *rest.Config { +func (c *Cluster) RawRestConfig() (*rest.Config, error) { var config *rest.Config var err error if c.Server == KubernetesInternalAPIServerAddr && env.ParseBoolFromEnv(EnvVarFakeInClusterConfig, false) { @@ -3182,22 +3184,25 @@ func (c *Cluster) RawRestConfig() *rest.Config { } } if err != nil { - panic(fmt.Sprintf("Unable to create K8s REST config: %v", err)) + return nil, fmt.Errorf("Unable to create K8s REST config: %w", err) } config.Timeout = K8sServerSideTimeout config.QPS = K8sClientConfigQPS config.Burst = K8sClientConfigBurst - return config + return config, nil } // RESTConfig returns a go-client REST config from cluster with tuned throttling and HTTP client settings. -func (c *Cluster) RESTConfig() *rest.Config { - config := c.RawRestConfig() - err := SetK8SConfigDefaults(config) +func (c *Cluster) RESTConfig() (*rest.Config, error) { + config, err := c.RawRestConfig() + if err != nil { + return nil, fmt.Errorf("Unable to get K8s RAW REST config: %w", err) + } + err = SetK8SConfigDefaults(config) if err != nil { - panic(fmt.Sprintf("Unable to apply K8s REST config defaults: %v", err)) + return nil, fmt.Errorf("Unable to apply K8s REST config defaults: %w", err) } - return config + return config, nil } // UnmarshalToUnstructured unmarshals a resource representation in JSON to unstructured data diff --git a/pkg/apis/application/v1alpha1/types_test.go b/pkg/apis/application/v1alpha1/types_test.go index 08b83c238a93d7..d614711b811db2 100644 --- a/pkg/apis/application/v1alpha1/types_test.go +++ b/pkg/apis/application/v1alpha1/types_test.go @@ -320,7 +320,7 @@ func TestAppProject_IsNegatedDestinationPermitted(t *testing.T) { Server: "*", Namespace: "!kube-system", }}, appDest: ApplicationDestination{Server: "https://kubernetes.default.svc", Namespace: "default"}, - isPermitted: false, + isPermitted: true, }, { projDest: []ApplicationDestination{{ Server: "*", Namespace: "*", @@ -339,6 +339,22 @@ func TestAppProject_IsNegatedDestinationPermitted(t *testing.T) { }}, appDest: ApplicationDestination{Name: "test", Namespace: "test"}, isPermitted: false, + }, { + projDest: []ApplicationDestination{{ + Server: "*", Namespace: "test", + }, { + Server: "!https://test-server", Namespace: "other", + }}, + appDest: ApplicationDestination{Server: "https://test-server", Namespace: "test"}, + isPermitted: true, + }, { + projDest: []ApplicationDestination{{ + Server: "*", Namespace: "*", + }, { + Server: "https://test-server", Namespace: "!other", + }}, + appDest: ApplicationDestination{Server: "https://other-test-server", Namespace: "other"}, + isPermitted: true, }} for _, data := range testData { @@ -350,7 +366,7 @@ func TestAppProject_IsNegatedDestinationPermitted(t *testing.T) { permitted, _ := proj.IsDestinationPermitted(data.appDest, func(project string) ([]*Cluster, error) { return []*Cluster{}, nil }) - assert.Equal(t, data.isPermitted, permitted) + assert.Equalf(t, data.isPermitted, permitted, "appDest mismatch for %+v with project destinations %+v", data.appDest, data.projDest) } } @@ -438,8 +454,7 @@ func TestAppProject_IsDestinationPermitted_PermitOnlyProjectScopedClusters(t *te _, err := proj.IsDestinationPermitted(ApplicationDestination{Server: "https://my-cluster.123.com", Namespace: "default"}, func(_ string) ([]*Cluster, error) { return nil, errors.New("some error") }) - require.Error(t, err) - assert.Contains(t, err.Error(), "could not retrieve project clusters") + assert.ErrorContains(t, err, "could not retrieve project clusters") } func TestAppProject_IsGroupKindPermitted(t *testing.T) { @@ -801,8 +816,7 @@ func TestAppProject_InvalidPolicyRules(t *testing.T) { for _, bad := range badPolicies { p.Spec.Roles[0].Policies = []string{bad.policy} err = p.ValidateProject() - require.Error(t, err) - assert.Contains(t, err.Error(), bad.errmsg) + assert.ErrorContains(t, err, bad.errmsg) } } @@ -3959,3 +3973,158 @@ func TestApplicationTree_Merge(t *testing.T) { }, }, tree) } + +func TestAppProject_ValidateDestinationServiceAccount(t *testing.T) { + testData := []struct { + server string + namespace string + defaultServiceAccount string + expectedErrMsg string + }{ + { + // Given, a project + // When, a default destination service account with all valid fields is added to it, + // Then, there is no error. + server: "https://192.168.99.100:8443", + namespace: "test-ns", + defaultServiceAccount: "test-sa", + expectedErrMsg: "", + }, + { + // Given, a project + // When, a default destination service account with negation glob pattern for server is added, + // Then, there is an error with appropriate message. + server: "!abc", + namespace: "test-ns", + defaultServiceAccount: "test-sa", + expectedErrMsg: "server has an invalid format, '!abc'", + }, + { + // Given, a project + // When, a default destination service account with empty namespace is added to it, + // Then, there is no error. + server: "https://192.168.99.100:8443", + namespace: "", + defaultServiceAccount: "test-sa", + expectedErrMsg: "", + }, + { + // Given, a project, + // When, a default destination service account with negation glob pattern for server is added, + // Then, there is an error with appropriate message. + server: "!*", + namespace: "test-ns", + defaultServiceAccount: "test-sa", + expectedErrMsg: "server has an invalid format, '!*'", + }, + { + // Given, a project, + // When, a default destination service account with negation glob pattern for namespace is added, + // Then, there is an error with appropriate message. + server: "https://192.168.99.100:8443", + namespace: "!*", + defaultServiceAccount: "test-sa", + expectedErrMsg: "namespace has an invalid format, '!*'", + }, + { + // Given, a project, + // When, a default destination service account with negation glob pattern for namespace is added, + // Then, there is an error with appropriate message. + server: "https://192.168.99.100:8443", + namespace: "!abc", + defaultServiceAccount: "test-sa", + expectedErrMsg: "namespace has an invalid format, '!abc'", + }, + { + // Given, a project, + // When, a default destination service account with empty service account is added, + // Then, there is an error with appropriate message. + server: "https://192.168.99.100:8443", + namespace: "test-ns", + defaultServiceAccount: "", + expectedErrMsg: "defaultServiceAccount has an invalid format, ''", + }, + { + // Given, a project, + // When, a default destination service account with service account having just white spaces is added, + // Then, there is an error with appropriate message. + server: "https://192.168.99.100:8443", + namespace: "test-ns", + defaultServiceAccount: " ", + expectedErrMsg: "defaultServiceAccount has an invalid format, ' '", + }, + { + // Given, a project, + // When, a default destination service account with service account having backwards slash char is added, + // Then, there is an error with appropriate message. + server: "https://192.168.99.100:8443", + namespace: "test-ns", + defaultServiceAccount: "test\\sa", + expectedErrMsg: "defaultServiceAccount has an invalid format, 'test\\sa'", + }, + { + // Given, a project, + // When, a default destination service account with service account having forward slash char is added, + // Then, there is an error with appropriate message. + server: "https://192.168.99.100:8443", + namespace: "test-ns", + defaultServiceAccount: "test/sa", + expectedErrMsg: "defaultServiceAccount has an invalid format, 'test/sa'", + }, + { + // Given, a project, + // When, a default destination service account with service account having square braces char is added, + // Then, there is an error with appropriate message. + server: "https://192.168.99.100:8443", + namespace: "test-ns", + defaultServiceAccount: "[test-sa]", + expectedErrMsg: "defaultServiceAccount has an invalid format, '[test-sa]'", + }, + { + // Given, a project, + // When, a default destination service account with service account having curly braces char is added, + // Then, there is an error with appropriate message. + server: "https://192.168.99.100:8443", + namespace: "test-ns", + defaultServiceAccount: "{test-sa}", + expectedErrMsg: "defaultServiceAccount has an invalid format, '{test-sa}'", + }, + { + // Given, a project, + // When, a default destination service account with service account having curly braces char is added, + // Then, there is an error with appropriate message. + server: "[[ech*", + namespace: "test-ns", + defaultServiceAccount: "test-sa", + expectedErrMsg: "server has an invalid format, '[[ech*'", + }, + { + // Given, a project, + // When, a default destination service account with service account having curly braces char is added, + // Then, there is an error with appropriate message. + server: "https://192.168.99.100:8443", + namespace: "[[ech*", + defaultServiceAccount: "test-sa", + expectedErrMsg: "namespace has an invalid format, '[[ech*'", + }, + } + for _, data := range testData { + proj := AppProject{ + Spec: AppProjectSpec{ + DestinationServiceAccounts: []ApplicationDestinationServiceAccount{ + { + Server: data.server, + Namespace: data.namespace, + DefaultServiceAccount: data.defaultServiceAccount, + }, + }, + }, + } + err := proj.ValidateProject() + if data.expectedErrMsg == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, data.expectedErrMsg) + } + } +} diff --git a/renovate-presets/README.md b/renovate-presets/README.md new file mode 100644 index 00000000000000..ef15ce04b2c289 --- /dev/null +++ b/renovate-presets/README.md @@ -0,0 +1,60 @@ +# Renovate shared presets + +Presets makes rules easier to maintain and reusable across multiple repositories. + +# How to use a preset + +Reference the preset in the `extends` field of the `renovate.json` file in the repository. +Presets can reference other presets. (read more about [shared presets](https://docs.renovatebot.com/config-presets/)) + +```json +{ + "extends": [ + "github>argoproj/argo-cd//renovate-presets/custom-managers/bash.json5" +] +} +``` + +### Note : + +It would make sense to move this folder to a new repository in the future. + +Benefits: +- Avoids consuming the repository's CI/CD resources. +- Faster feedback loop for configuration changes. +- Avoid polluting the master git history. +- The `renovate.json` in each repository can be simplified to only include a single presets : + ```json + { + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "github>argoproj/renovate-presets//argoproj/argo-cd/renovate.json5" + ], + // rules are empty and this file won't need to be modified again. + "packageRules": [] + } + ``` +Inconvenient: +- Owners of a repository can impact the configuration of all repositories. Use codeowners to reduce the risk. + +Example of repo structure : +```shell +. +โ”œโ”€โ”€ README.md +โ”œโ”€โ”€ .github/CODEOWNERS +โ”œโ”€โ”€ common.json5 # common presets for all repositories +โ”œโ”€โ”€ fix/ +โ”‚ โ””โ”€โ”€ openssf-merge-confidence-columns.json5 +โ”œโ”€โ”€ custom-managers/ +โ”‚ โ”œโ”€โ”€ bash.json5 +โ”‚ โ””โ”€โ”€ yaml.json5 +โ””โ”€โ”€ argoproj/ # organization + โ”œโ”€โ”€ argo-cd/ # repository + โ”‚ โ”œโ”€โ”€ devtools.json5 # rules specific to the devtool (CI and dev environment...) + โ”‚ โ”œโ”€โ”€ docs.json5 # rules specific to the docs folder. + โ”‚ โ”œโ”€โ”€ # etc... + โ”‚ โ””โ”€โ”€ renovate.json5 # this is the single preset referenced from the repository argopro/argo-cd. + โ””โ”€โ”€ argo-rollouts/ # repository + โ””โ”€โ”€ renovate.json5 + +``` diff --git a/renovate-presets/commons.json5 b/renovate-presets/commons.json5 new file mode 100644 index 00000000000000..f6676a1d28540f --- /dev/null +++ b/renovate-presets/commons.json5 @@ -0,0 +1,74 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "description": "Contains rules that makes sense to enforce by default.", + "dependencyDashboard": true, + "dependencyDashboardOSVVulnerabilitySummary": "all", + "osvVulnerabilityAlerts": true, + "vulnerabilityAlerts": { + "description": "Settings specific to PRs of type security", + "addLabels": ["security"] + }, + "extends": [ + "config:best-practices", + ":gitSignOff", + ":labels(dependencies)", + "customManagers:dockerfileVersions", + "security:openssf-scorecard", + "mergeConfidence:all-badges", + "github>argoproj/argo-cd//renovate-presets/fix/openssf-merge-confidence-columns.json5", + ], + "packageRules": [ + { + "description": "Define the label to make Renovate stop updating a PR.", + "stopUpdatingLabel": "renovate:stop-updating" + }, + { + "description": "Define the label to make Renovate rebase a PR.", + "rebaseLabel": "renovate:do-rebase" + }, + { + "description": "Define labels of the dependency dashboard issues.", + "dependencyDashboardLabels": [ + "dependencies", + ] + }, + { + "description": "Add label major to PRs with major updates", + "matchUpdateTypes": [ + "major" + ], + "addLabels": [ + "major" + ] + }, + { + "description": "Add labels for PRs related to javascript", + "matchDatasources": [ + "node-version", + "npm" + ], + "addLabels": [ + "javascript" + ] + }, + { + "description": "Add labels for PRs related to go", + "matchDatasources": [ + "golang-version", + "go" + ], + "addLabels": [ + "go" + ] + }, + { + "description": "Add labels for PRs related to python", + "matchCategories": [ + "python" + ], + "addLabels": [ + "python" + ] + } + ] +} \ No newline at end of file diff --git a/renovate-presets/custom-managers/shell.json5 b/renovate-presets/custom-managers/shell.json5 new file mode 100644 index 00000000000000..9ce3c1805d31e6 --- /dev/null +++ b/renovate-presets/custom-managers/shell.json5 @@ -0,0 +1,16 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "customManagers": [ + { + "description": "A generic custom manager for updating any shell scripts.", + "customType": "regex", + "fileMatch": [ + ".+\\.(?:bash|sh|ksh)$" + ], + "matchStrings": [ + "# renovate: datasource=(?.*?)(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?.*?))?(?: extractVersion=(?.*?))?\\s.+?_VERSION\\s*=\\s*(?:'|\")(?[^(?:'|\")]+)(?:'|\")", + "# renovate: datasource=(?.*?)(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?.*?))?(?: extractVersion=(?.*?))?\\s.+?_VERSION\\s*=\\s*(?[^'\"\\s]+)" + ] + } + ] +} \ No newline at end of file diff --git a/renovate-presets/custom-managers/yaml.json5 b/renovate-presets/custom-managers/yaml.json5 new file mode 100644 index 00000000000000..8729f611c8ea73 --- /dev/null +++ b/renovate-presets/custom-managers/yaml.json5 @@ -0,0 +1,16 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "customManagers": [ + { + "description": "A generic custom manager for updating any yaml fields ending by 'version:' (case insensitive)", + "customType": "regex", + "fileMatch": [ + ".github\\/workflows.+\\.(?:yml|yaml)$" + ], + "matchStrings": [ + "# renovate: datasource=(?.*?)(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?.*?))?(?: extractVersion=(?.*?))?\\s.+?((?i)VERSION)\\s*:\\s*(?:'|\")(?[^(?:'|\")]+)(?:'|\")", + "# renovate: datasource=(?.*?)(?: depName=(?.+?))? packageName=(?.+?)(?: versioning=(?.*?))?(?: extractVersion=(?.*?))?\\s.+?((?i)VERSION)\\s*:\\s*(?[^'\"\\s]+)" + ] + } + ] +} \ No newline at end of file diff --git a/renovate-presets/devtool.json5 b/renovate-presets/devtool.json5 new file mode 100644 index 00000000000000..96ad51d3808e68 --- /dev/null +++ b/renovate-presets/devtool.json5 @@ -0,0 +1,72 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "description": "Rules specific to the devtool (CI, dev environment...)", + "packageRules": [ + { + "description": "Enable updates from specified datasources", + "matchDatasources": [ + "node-version", + "golang-version" + ], + "enabled": true + }, + { + "description": "Enable updates from specified go modules", + "matchDatasources": [ + "go" + ], + "matchPackageNames": [ + "github.com/golangci/golangci-lint" + ], + "enabled": true + }, + { + "description": "Enable updates from specified docker images", + "matchDatasources": [ + "docker" + ], + "matchPackageNames": [ + "docker.io/library/node", + "docker.io/library/golang" + ], + "enabled": true + }, + { + "description": "Group golang-version packages", + "groupName": "group golang", + "matchDatasources": [ + "docker", + "golang-version" + ], + "matchPackageNames": [ + "/(?:^|/)golang$/" + ] + }, + { + "description": "Group node-version packages", + "groupName": "group node", + "matchDatasources": [ + "docker", + "node-version" + ], + "matchPackageNames": [ + "/(?:^|/)node$/", + "!calico/node", + "!docker.io/calico/node", + "!kindest/node" + ] + }, + { + "description": "Example to reduce noise with the automerge features.", + "matchDatasources": [ + "golang-version" + ], + "matchUpdateTypes": [ + "patch", + "pin", + "digest" + ], + "automerge": false + } + ] +} \ No newline at end of file diff --git a/renovate-presets/docs.json5 b/renovate-presets/docs.json5 new file mode 100644 index 00000000000000..0eb67107f73086 --- /dev/null +++ b/renovate-presets/docs.json5 @@ -0,0 +1,21 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "description": "Rules specific to the docs directory", + "packageRules": [ + { + "description": "Group all dependencies from the docs directory", + "matchFileNames": ["docs/**"], + "matchCategories": [ + "python" + ], + "excludePackageNames": [ + "mkdocs-material" + ], + "groupName": "Docs dependencies", + "enabled": true + } + ] +} + + + diff --git a/renovate-presets/fix/disable-all-updates.json5 b/renovate-presets/fix/disable-all-updates.json5 new file mode 100644 index 00000000000000..5db24b27f02a9a --- /dev/null +++ b/renovate-presets/fix/disable-all-updates.json5 @@ -0,0 +1,13 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "description": "Disable all updates to avoid conflicts with dependabot, then enable what you need.", + "packageRules": [ + { + "matchPackageNames": [ + "*" + ], + "enabled": false + } + ] +} + diff --git a/renovate-presets/fix/openssf-merge-confidence-columns.json5 b/renovate-presets/fix/openssf-merge-confidence-columns.json5 new file mode 100644 index 00000000000000..b099487113bf5c --- /dev/null +++ b/renovate-presets/fix/openssf-merge-confidence-columns.json5 @@ -0,0 +1,22 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "description": "Merge the output of mergeConfidence:all-badges and security:openssf-scorecard. See https://github.com/renovatebot/renovate/discussions/25125 for rationale.", + "packageRules": [ + { + "matchPackagePatterns": [ + ".*" + ], + "prBodyColumns": [ + "Package", + "Type", + "Update", + "Change", + "Age", + "Adoption", + "Passing", + "Confidence", + "OpenSSF" + ] + } + ] +} \ No newline at end of file diff --git a/renovate.json b/renovate.json new file mode 100644 index 00000000000000..f395a491f4a761 --- /dev/null +++ b/renovate.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "github>argoproj/argo-cd//renovate-presets/commons.json5", + "github>argoproj/argo-cd//renovate-presets/custom-managers/shell.json5", + "github>argoproj/argo-cd//renovate-presets/custom-managers/yaml.json5", + "github>argoproj/argo-cd//renovate-presets/fix/disable-all-updates.json5", + "github>argoproj/argo-cd//renovate-presets/devtool.json5", + "github>argoproj/argo-cd//renovate-presets/docs.json5" + ] +} diff --git a/reposerver/apiclient/repository.pb.go b/reposerver/apiclient/repository.pb.go index 61c14068bdd18f..1e4083d9897697 100644 --- a/reposerver/apiclient/repository.pb.go +++ b/reposerver/apiclient/repository.pb.go @@ -61,10 +61,12 @@ type ManifestRequest struct { // This is used to surface "source not permitted" errors for Helm repositories ProjectName string `protobuf:"bytes,25,opt,name=projectName,proto3" json:"projectName,omitempty"` // argocd.argoproj.io/manifest-generate-paths annotation value of the Application to allow optimize which resources propagated to cmpserver - AnnotationManifestGeneratePaths string `protobuf:"bytes,26,opt,name=AnnotationManifestGeneratePaths,proto3" json:"AnnotationManifestGeneratePaths,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + AnnotationManifestGeneratePaths string `protobuf:"bytes,26,opt,name=annotationManifestGeneratePaths,proto3" json:"annotationManifestGeneratePaths,omitempty"` + // Holds instance installation id + InstallationID string `protobuf:"bytes,27,opt,name=installationID,proto3" json:"installationID,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ManifestRequest) Reset() { *m = ManifestRequest{} } @@ -261,6 +263,13 @@ func (m *ManifestRequest) GetAnnotationManifestGeneratePaths() string { return "" } +func (m *ManifestRequest) GetInstallationID() string { + if m != nil { + return m.InstallationID + } + return "" +} + type ManifestRequestWithFiles struct { // Types that are valid to be assigned to Part: // *ManifestRequestWithFiles_Request @@ -2217,6 +2226,7 @@ type UpdateRevisionForPathsRequest struct { Revision string `protobuf:"bytes,12,opt,name=revision,proto3" json:"revision,omitempty"` Paths []string `protobuf:"bytes,13,rep,name=paths,proto3" json:"paths,omitempty"` NoRevisionCache bool `protobuf:"varint,14,opt,name=noRevisionCache,proto3" json:"noRevisionCache,omitempty"` + InstallationID string `protobuf:"bytes,15,opt,name=installationID,proto3" json:"installationID,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2353,6 +2363,13 @@ func (m *UpdateRevisionForPathsRequest) GetNoRevisionCache() bool { return false } +func (m *UpdateRevisionForPathsRequest) GetInstallationID() string { + if m != nil { + return m.InstallationID + } + return "" +} + type UpdateRevisionForPathsResponse struct { Changes bool `protobuf:"varint,1,opt,name=changes,proto3" json:"changes,omitempty"` Revision string `protobuf:"bytes,2,opt,name=revision,proto3" json:"revision,omitempty"` @@ -2458,154 +2475,156 @@ func init() { } var fileDescriptor_dd8723cfcc820480 = []byte{ - // 2352 bytes of a gzipped FileDescriptorProto + // 2376 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x1a, 0x4d, 0x73, 0x1c, 0x47, - 0x55, 0xfb, 0xa9, 0xdd, 0x27, 0xeb, 0xab, 0x6d, 0xcb, 0xe3, 0x8d, 0x2d, 0x94, 0x01, 0xbb, 0x1c, - 0x3b, 0x59, 0x95, 0xe5, 0x4a, 0x0c, 0x4e, 0x08, 0xa5, 0x28, 0xb6, 0xe4, 0xd8, 0xb2, 0xc5, 0xd8, - 0x09, 0x65, 0x30, 0x50, 0xbd, 0xb3, 0xad, 0xd9, 0x89, 0xe6, 0xa3, 0x3d, 0xd3, 0xa3, 0xb0, 0xae, - 0xe2, 0x04, 0xc5, 0x85, 0x3b, 0x07, 0xae, 0xfc, 0x05, 0x28, 0x8e, 0x1c, 0x28, 0x0a, 0x8e, 0x14, - 0x17, 0xaa, 0xb8, 0x40, 0xf9, 0x97, 0x50, 0xfd, 0x31, 0x9f, 0x3b, 0xbb, 0x52, 0x58, 0x59, 0x01, - 0x2e, 0xd2, 0xf4, 0xeb, 0xd7, 0xef, 0xbd, 0x7e, 0x5f, 0xfd, 0x5e, 0xf7, 0xc2, 0xd5, 0x80, 0x50, - 0x3f, 0x24, 0xc1, 0x21, 0x09, 0xd6, 0xc5, 0xa7, 0xcd, 0xfc, 0x60, 0x98, 0xf9, 0xec, 0xd2, 0xc0, - 0x67, 0x3e, 0x82, 0x14, 0xd2, 0x79, 0x68, 0xd9, 0x6c, 0x10, 0xf5, 0xba, 0xa6, 0xef, 0xae, 0xe3, - 0xc0, 0xf2, 0x69, 0xe0, 0x7f, 0x2e, 0x3e, 0xde, 0x31, 0xfb, 0xeb, 0x87, 0x1b, 0xeb, 0xf4, 0xc0, - 0x5a, 0xc7, 0xd4, 0x0e, 0xd7, 0x31, 0xa5, 0x8e, 0x6d, 0x62, 0x66, 0xfb, 0xde, 0xfa, 0xe1, 0x4d, - 0xec, 0xd0, 0x01, 0xbe, 0xb9, 0x6e, 0x11, 0x8f, 0x04, 0x98, 0x91, 0xbe, 0xa4, 0xdc, 0x79, 0xc3, - 0xf2, 0x7d, 0xcb, 0x21, 0xeb, 0x62, 0xd4, 0x8b, 0xf6, 0xd7, 0x89, 0x4b, 0x99, 0x62, 0xab, 0xff, - 0x76, 0x1e, 0x16, 0x77, 0xb1, 0x67, 0xef, 0x93, 0x90, 0x19, 0xe4, 0x45, 0x44, 0x42, 0x86, 0x9e, - 0x43, 0x9d, 0x0b, 0xa3, 0x55, 0xd6, 0x2a, 0xd7, 0xe6, 0x36, 0x76, 0xba, 0xa9, 0x34, 0xdd, 0x58, - 0x1a, 0xf1, 0xf1, 0x63, 0xb3, 0xdf, 0x3d, 0xdc, 0xe8, 0xd2, 0x03, 0xab, 0xcb, 0xa5, 0xe9, 0x66, - 0xa4, 0xe9, 0xc6, 0xd2, 0x74, 0x8d, 0x64, 0x5b, 0x86, 0xa0, 0x8a, 0x3a, 0xd0, 0x0a, 0xc8, 0xa1, - 0x1d, 0xda, 0xbe, 0xa7, 0x55, 0xd7, 0x2a, 0xd7, 0xda, 0x46, 0x32, 0x46, 0x1a, 0xcc, 0x7a, 0xfe, - 0x16, 0x36, 0x07, 0x44, 0xab, 0xad, 0x55, 0xae, 0xb5, 0x8c, 0x78, 0x88, 0xd6, 0x60, 0x0e, 0x53, - 0xfa, 0x10, 0xf7, 0x88, 0xf3, 0x80, 0x0c, 0xb5, 0xba, 0x58, 0x98, 0x05, 0xf1, 0xb5, 0x98, 0xd2, - 0x47, 0xd8, 0x25, 0x5a, 0x43, 0xcc, 0xc6, 0x43, 0x74, 0x09, 0xda, 0x1e, 0x76, 0x49, 0x48, 0xb1, - 0x49, 0xb4, 0x96, 0x98, 0x4b, 0x01, 0xe8, 0xa7, 0xb0, 0x9c, 0x11, 0xfc, 0x89, 0x1f, 0x05, 0x26, - 0xd1, 0x40, 0x6c, 0xfd, 0xf1, 0x74, 0x5b, 0xdf, 0x2c, 0x92, 0x35, 0x46, 0x39, 0xa1, 0x1f, 0x41, - 0x43, 0x58, 0x5e, 0x9b, 0x5b, 0xab, 0x9d, 0xa8, 0xb6, 0x25, 0x59, 0xe4, 0xc1, 0x2c, 0x75, 0x22, - 0xcb, 0xf6, 0x42, 0xed, 0x8c, 0xe0, 0xf0, 0x74, 0x3a, 0x0e, 0x5b, 0xbe, 0xb7, 0x6f, 0x5b, 0xbb, - 0xd8, 0xc3, 0x16, 0x71, 0x89, 0xc7, 0xf6, 0x04, 0x71, 0x23, 0x66, 0x82, 0x5e, 0xc2, 0xd2, 0x41, - 0x14, 0x32, 0xdf, 0xb5, 0x5f, 0x92, 0xc7, 0x94, 0xaf, 0x0d, 0xb5, 0x79, 0xa1, 0xcd, 0x47, 0xd3, - 0x31, 0x7e, 0x50, 0xa0, 0x6a, 0x8c, 0xf0, 0xe1, 0x4e, 0x72, 0x10, 0xf5, 0xc8, 0x67, 0x24, 0x10, - 0xde, 0xb5, 0x20, 0x9d, 0x24, 0x03, 0x92, 0x6e, 0x64, 0xab, 0x51, 0xa8, 0x2d, 0xae, 0xd5, 0xa4, - 0x1b, 0x25, 0x20, 0x74, 0x0d, 0x16, 0x0f, 0x49, 0x60, 0xef, 0x0f, 0x9f, 0xd8, 0x96, 0x87, 0x59, - 0x14, 0x10, 0x6d, 0x49, 0xb8, 0x62, 0x11, 0x8c, 0x5c, 0x98, 0x1f, 0x10, 0xc7, 0xe5, 0x2a, 0xdf, - 0x0a, 0x48, 0x3f, 0xd4, 0x96, 0x85, 0x7e, 0xb7, 0xa7, 0xb7, 0xa0, 0x20, 0x67, 0xe4, 0xa9, 0x73, - 0xc1, 0x3c, 0xdf, 0x50, 0x91, 0x22, 0x63, 0x04, 0x49, 0xc1, 0x0a, 0x60, 0x74, 0x15, 0x16, 0x58, - 0x80, 0xcd, 0x03, 0xdb, 0xb3, 0x76, 0x09, 0x1b, 0xf8, 0x7d, 0xed, 0xac, 0xd0, 0x44, 0x01, 0x8a, - 0x4c, 0x40, 0xc4, 0xc3, 0x3d, 0x87, 0xf4, 0xa5, 0x2f, 0x3e, 0x1d, 0x52, 0x12, 0x6a, 0xe7, 0xc4, - 0x2e, 0x6e, 0x75, 0x33, 0x19, 0xaa, 0x90, 0x20, 0xba, 0x77, 0x47, 0x56, 0xdd, 0xf5, 0x58, 0x30, - 0x34, 0x4a, 0xc8, 0xa1, 0x03, 0x98, 0xe3, 0xfb, 0x88, 0x5d, 0xe1, 0xbc, 0x70, 0x85, 0xfb, 0xd3, - 0xe9, 0x68, 0x27, 0x25, 0x68, 0x64, 0xa9, 0xa3, 0x2e, 0xa0, 0x01, 0x0e, 0x77, 0x23, 0x87, 0xd9, - 0xd4, 0x21, 0x52, 0x8c, 0x50, 0x5b, 0x11, 0x6a, 0x2a, 0x99, 0x41, 0x0f, 0x00, 0x02, 0xb2, 0x1f, - 0xe3, 0x5d, 0x10, 0x3b, 0xbf, 0x31, 0x69, 0xe7, 0x46, 0x82, 0x2d, 0x77, 0x9c, 0x59, 0xce, 0x99, - 0xf3, 0x6d, 0x10, 0x93, 0xa9, 0x68, 0x17, 0x61, 0xad, 0x09, 0x17, 0x2b, 0x99, 0xe1, 0xbe, 0xa8, - 0xa0, 0x22, 0x69, 0x5d, 0x94, 0xde, 0x9a, 0x01, 0xa1, 0x1d, 0xf8, 0xda, 0xa6, 0xe7, 0xf9, 0x4c, - 0x6c, 0x3f, 0x16, 0x65, 0x5b, 0xa5, 0xf7, 0x3d, 0xcc, 0x06, 0xa1, 0xd6, 0x11, 0xab, 0x8e, 0x42, - 0xeb, 0xdc, 0x85, 0x0b, 0x63, 0x8c, 0x86, 0x96, 0xa0, 0x76, 0x40, 0x86, 0x22, 0xd9, 0xb7, 0x0d, - 0xfe, 0x89, 0xce, 0x41, 0xe3, 0x10, 0x3b, 0x11, 0x11, 0xe9, 0xb9, 0x65, 0xc8, 0xc1, 0x9d, 0xea, - 0x37, 0x2b, 0x9d, 0x5f, 0x54, 0x60, 0xb1, 0xa0, 0x82, 0x92, 0xf5, 0x3f, 0xcc, 0xae, 0x3f, 0x81, - 0x80, 0xd8, 0x7f, 0x8a, 0x03, 0x8b, 0xb0, 0x8c, 0x20, 0xfa, 0xdf, 0x2a, 0xa0, 0x15, 0x6c, 0xf3, - 0x3d, 0x9b, 0x0d, 0xee, 0xd9, 0x0e, 0x09, 0xd1, 0x6d, 0x98, 0x0d, 0x24, 0x4c, 0x1d, 0x61, 0x6f, - 0x4c, 0x30, 0xe9, 0xce, 0x8c, 0x11, 0x63, 0xa3, 0x0f, 0xa1, 0xe5, 0x12, 0x86, 0xfb, 0x98, 0x61, - 0x25, 0xfb, 0x5a, 0xd9, 0x4a, 0xce, 0x65, 0x57, 0xe1, 0xed, 0xcc, 0x18, 0xc9, 0x1a, 0xf4, 0x2e, - 0x34, 0xcc, 0x41, 0xe4, 0x1d, 0x88, 0xc3, 0x6b, 0x6e, 0xe3, 0xf2, 0xb8, 0xc5, 0x5b, 0x1c, 0x69, - 0x67, 0xc6, 0x90, 0xd8, 0x1f, 0x35, 0xa1, 0x4e, 0x71, 0xc0, 0xf4, 0x7b, 0x70, 0xae, 0x8c, 0x05, - 0x3f, 0x31, 0xcd, 0x01, 0x31, 0x0f, 0xc2, 0xc8, 0x55, 0x6a, 0x4e, 0xc6, 0x08, 0x41, 0x3d, 0xb4, - 0x5f, 0x4a, 0x55, 0xd7, 0x0c, 0xf1, 0xad, 0xbf, 0x05, 0xcb, 0x23, 0xdc, 0xb8, 0x51, 0xa5, 0x6c, - 0x9c, 0xc2, 0x19, 0xc5, 0x5a, 0x8f, 0xe0, 0xfc, 0x53, 0xa1, 0x8b, 0xe4, 0xd8, 0x38, 0x8d, 0x1a, - 0x40, 0xdf, 0x81, 0x95, 0x22, 0xdb, 0x90, 0xfa, 0x5e, 0x48, 0x78, 0x10, 0x89, 0x3c, 0x6b, 0x93, - 0x7e, 0x3a, 0x2b, 0xa4, 0x68, 0x19, 0x25, 0x33, 0xfa, 0x6f, 0xaa, 0xb0, 0x62, 0x90, 0xd0, 0x77, - 0x0e, 0x49, 0x9c, 0x04, 0x4f, 0xa7, 0x8c, 0xf9, 0x01, 0xd4, 0x30, 0xa5, 0xca, 0x4d, 0xee, 0x9f, - 0x58, 0xa1, 0x60, 0x70, 0xaa, 0xe8, 0x6d, 0x58, 0xc6, 0x6e, 0xcf, 0xb6, 0x22, 0x3f, 0x0a, 0xe3, - 0x6d, 0x09, 0xa7, 0x6a, 0x1b, 0xa3, 0x13, 0x3c, 0x91, 0x84, 0x22, 0x22, 0xef, 0x7b, 0x7d, 0xf2, - 0x13, 0x51, 0x1b, 0xd5, 0x8c, 0x2c, 0x48, 0x37, 0xe1, 0xc2, 0x88, 0x92, 0x94, 0xc2, 0xb3, 0xe5, - 0x58, 0xa5, 0x50, 0x8e, 0x95, 0x8a, 0x51, 0x1d, 0x23, 0x86, 0xfe, 0xaa, 0x02, 0x4b, 0x69, 0x70, - 0x29, 0xf2, 0x97, 0xa0, 0xed, 0x2a, 0x58, 0xa8, 0x55, 0x44, 0x2e, 0x4c, 0x01, 0xf9, 0xca, 0xac, - 0x5a, 0xac, 0xcc, 0x56, 0xa0, 0x29, 0x0b, 0x67, 0xb5, 0x75, 0x35, 0xca, 0x89, 0x5c, 0x2f, 0x88, - 0xbc, 0x0a, 0x10, 0x26, 0x19, 0x4e, 0x6b, 0x8a, 0xd9, 0x0c, 0x04, 0xe9, 0x70, 0x46, 0x9e, 0xe3, - 0x06, 0x09, 0x23, 0x87, 0x69, 0xb3, 0x02, 0x23, 0x07, 0x13, 0xf1, 0xe6, 0xbb, 0x2e, 0xf6, 0xfa, - 0xa1, 0xd6, 0x12, 0x22, 0x27, 0x63, 0xdd, 0x87, 0xc5, 0x87, 0x36, 0xdf, 0xdf, 0x7e, 0x78, 0x3a, - 0xa1, 0xf2, 0x1e, 0xd4, 0x39, 0x33, 0x2e, 0x54, 0x2f, 0xc0, 0x9e, 0x39, 0x20, 0xb1, 0x1e, 0x93, - 0x31, 0x4f, 0x02, 0x0c, 0x5b, 0xa1, 0x56, 0x15, 0x70, 0xf1, 0xad, 0xff, 0xbe, 0x2a, 0x25, 0xdd, - 0xa4, 0x34, 0xfc, 0xea, 0x0b, 0xfb, 0xf2, 0x52, 0xa3, 0x36, 0x5a, 0x6a, 0x14, 0x44, 0xfe, 0x32, - 0xa5, 0xc6, 0x09, 0x1d, 0x72, 0x7a, 0x04, 0xb3, 0x9b, 0x94, 0x72, 0x41, 0xd0, 0x4d, 0xa8, 0x63, - 0x4a, 0xa5, 0xc2, 0x0b, 0xf9, 0x5c, 0xa1, 0xf0, 0xff, 0x4a, 0x24, 0x81, 0xda, 0xb9, 0x0d, 0xed, - 0x04, 0x74, 0x14, 0xdb, 0x76, 0x96, 0xed, 0x1a, 0x80, 0xac, 0xa5, 0xef, 0x7b, 0xfb, 0x3e, 0x37, - 0x29, 0x0f, 0x04, 0xb5, 0x54, 0x7c, 0xeb, 0x77, 0x62, 0x0c, 0x21, 0xdb, 0xdb, 0xd0, 0xb0, 0x19, - 0x71, 0x63, 0xe1, 0x56, 0xb2, 0xc2, 0xa5, 0x84, 0x0c, 0x89, 0xa4, 0xff, 0xb9, 0x05, 0x17, 0xb9, - 0xc5, 0x9e, 0x88, 0x10, 0xda, 0xa4, 0xf4, 0x63, 0xc2, 0xb0, 0xed, 0x84, 0xdf, 0x8d, 0x48, 0x30, - 0x7c, 0xcd, 0x8e, 0x61, 0x41, 0x53, 0x46, 0xa0, 0xca, 0x96, 0x27, 0xde, 0x56, 0x29, 0xf2, 0x69, - 0x2f, 0x55, 0x7b, 0x3d, 0xbd, 0x54, 0x59, 0x6f, 0x53, 0x3f, 0xa5, 0xde, 0x66, 0x7c, 0x7b, 0x9b, - 0x69, 0x9a, 0x9b, 0xf9, 0xa6, 0xb9, 0xa4, 0x65, 0x98, 0x3d, 0x6e, 0xcb, 0xd0, 0x2a, 0x6d, 0x19, - 0xdc, 0xd2, 0x38, 0x6e, 0x0b, 0x75, 0x7f, 0x3b, 0xeb, 0x81, 0x63, 0x7d, 0x6d, 0x9a, 0xe6, 0x01, - 0x5e, 0x6b, 0xf3, 0xf0, 0x69, 0xae, 0x19, 0x90, 0xed, 0xf8, 0xbb, 0xc7, 0xdb, 0xd3, 0x84, 0xb6, - 0xe0, 0xff, 0xae, 0xf4, 0xfe, 0xb9, 0xa8, 0xb8, 0xa8, 0x9f, 0xea, 0x20, 0x39, 0xec, 0xf9, 0x39, - 0xc4, 0x8f, 0x5d, 0x95, 0xb4, 0xf8, 0x37, 0xba, 0x01, 0x75, 0xae, 0x64, 0x55, 0x12, 0x5f, 0xc8, - 0xea, 0x93, 0x5b, 0x62, 0x93, 0xd2, 0x27, 0x94, 0x98, 0x86, 0x40, 0x42, 0x77, 0xa0, 0x9d, 0x38, - 0xbe, 0x8a, 0xac, 0x4b, 0xd9, 0x15, 0x49, 0x9c, 0xc4, 0xcb, 0x52, 0x74, 0xbe, 0xb6, 0x6f, 0x07, - 0xc4, 0x14, 0x05, 0x63, 0x63, 0x74, 0xed, 0xc7, 0xf1, 0x64, 0xb2, 0x36, 0x41, 0x47, 0x37, 0xa1, - 0x29, 0xef, 0x2f, 0x44, 0x04, 0xcd, 0x6d, 0x5c, 0x1c, 0x4d, 0xa6, 0xf1, 0x2a, 0x85, 0xa8, 0xff, - 0xa9, 0x02, 0x6f, 0xa6, 0x0e, 0x11, 0x47, 0x53, 0x5c, 0xb3, 0x7f, 0xf5, 0x27, 0xee, 0x55, 0x58, - 0x10, 0x4d, 0x42, 0x7a, 0x8d, 0x21, 0x6f, 0xd4, 0x0a, 0x50, 0xfd, 0x77, 0x15, 0xb8, 0x32, 0xba, - 0x8f, 0xad, 0x01, 0x0e, 0x58, 0x62, 0xde, 0xd3, 0xd8, 0x4b, 0x7c, 0xe0, 0x55, 0xd3, 0x03, 0x2f, - 0xb7, 0xbf, 0x5a, 0x7e, 0x7f, 0xfa, 0x1f, 0xaa, 0x30, 0x97, 0x71, 0xa0, 0xb2, 0x03, 0x93, 0x17, - 0x83, 0xc2, 0x6f, 0x45, 0x5b, 0x28, 0x0e, 0x85, 0xb6, 0x91, 0x81, 0xa0, 0x03, 0x00, 0x8a, 0x03, - 0xec, 0x12, 0x46, 0x02, 0x9e, 0xc9, 0x79, 0xc4, 0x3f, 0x98, 0x3e, 0xbb, 0xec, 0xc5, 0x34, 0x8d, - 0x0c, 0x79, 0x5e, 0xcd, 0x0a, 0xd6, 0xa1, 0xca, 0xdf, 0x6a, 0x84, 0xbe, 0x80, 0x85, 0x7d, 0xdb, - 0x21, 0x7b, 0xa9, 0x20, 0x4d, 0x21, 0xc8, 0xe3, 0xe9, 0x05, 0xb9, 0x97, 0xa5, 0x6b, 0x14, 0xd8, - 0xe8, 0xd7, 0x61, 0xa9, 0x18, 0x4f, 0x5c, 0x48, 0xdb, 0xc5, 0x56, 0xa2, 0x2d, 0x35, 0xd2, 0x11, - 0x2c, 0x15, 0xe3, 0x47, 0xff, 0x67, 0x15, 0xce, 0x27, 0xe4, 0x36, 0x3d, 0xcf, 0x8f, 0x3c, 0x53, - 0x5c, 0x09, 0x96, 0xda, 0xe2, 0x1c, 0x34, 0x98, 0xcd, 0x9c, 0xa4, 0xf0, 0x11, 0x03, 0x7e, 0x76, - 0x31, 0xdf, 0x77, 0x98, 0x4d, 0x95, 0x81, 0xe3, 0xa1, 0xb4, 0xfd, 0x8b, 0xc8, 0x0e, 0x48, 0x5f, - 0x64, 0x82, 0x96, 0x91, 0x8c, 0xf9, 0x1c, 0xaf, 0x6a, 0x44, 0x89, 0x2f, 0x95, 0x99, 0x8c, 0x85, - 0xdf, 0xfb, 0x8e, 0x43, 0x4c, 0xae, 0x8e, 0x4c, 0x13, 0x50, 0x80, 0x8a, 0xe6, 0x82, 0x05, 0xb6, - 0x67, 0xa9, 0x16, 0x40, 0x8d, 0xb8, 0x9c, 0x38, 0x08, 0xf0, 0x50, 0x55, 0xfe, 0x72, 0x80, 0x3e, - 0x80, 0x9a, 0x8b, 0xa9, 0x3a, 0xe8, 0xae, 0xe7, 0xb2, 0x43, 0x99, 0x06, 0xba, 0xbb, 0x98, 0xca, - 0x93, 0x80, 0x2f, 0xeb, 0xbc, 0x07, 0xad, 0x18, 0xf0, 0xa5, 0x4a, 0xc2, 0xcf, 0x61, 0x3e, 0x97, - 0x7c, 0xd0, 0x33, 0x58, 0x49, 0x3d, 0x2a, 0xcb, 0x50, 0x15, 0x81, 0x6f, 0x1e, 0x29, 0x99, 0x31, - 0x86, 0x80, 0xfe, 0x02, 0x96, 0xb9, 0xcb, 0x88, 0xc0, 0x3f, 0xa5, 0xd6, 0xe6, 0x7d, 0x68, 0x27, - 0x2c, 0x4b, 0x7d, 0xa6, 0x03, 0xad, 0xc3, 0xf8, 0xaa, 0x56, 0xf6, 0x36, 0xc9, 0x58, 0xdf, 0x04, - 0x94, 0x95, 0x57, 0x9d, 0x40, 0x37, 0xf2, 0x45, 0xf1, 0xf9, 0xe2, 0x71, 0x23, 0xd0, 0xe3, 0x9a, - 0xf8, 0xef, 0x55, 0x58, 0xdc, 0xb6, 0xc5, 0x1d, 0xc9, 0x29, 0x25, 0xb9, 0xeb, 0xb0, 0x14, 0x46, - 0x3d, 0xd7, 0xef, 0x47, 0x0e, 0x51, 0x45, 0x81, 0x3a, 0xe9, 0x47, 0xe0, 0x93, 0x92, 0x1f, 0x57, - 0x16, 0xc5, 0x6c, 0xa0, 0xba, 0x5f, 0xf1, 0x8d, 0x3e, 0x80, 0x8b, 0x8f, 0xc8, 0x17, 0x6a, 0x3f, - 0xdb, 0x8e, 0xdf, 0xeb, 0xd9, 0x9e, 0x15, 0x33, 0x69, 0x08, 0x26, 0xe3, 0x11, 0xca, 0x4a, 0xc5, - 0x66, 0x79, 0xa9, 0x98, 0x74, 0xd0, 0x5b, 0xbe, 0xeb, 0xda, 0x4c, 0x55, 0x94, 0x39, 0x98, 0xfe, - 0xb3, 0x0a, 0x2c, 0xa5, 0x9a, 0x55, 0xb6, 0xb9, 0x2d, 0x63, 0x48, 0x5a, 0xe6, 0x4a, 0xd6, 0x32, - 0x45, 0xd4, 0xff, 0x3c, 0x7c, 0xce, 0x64, 0xc3, 0xe7, 0x97, 0x55, 0x38, 0xbf, 0x6d, 0xb3, 0x38, - 0x71, 0xd9, 0xff, 0x6b, 0x56, 0x2e, 0xb1, 0x49, 0xfd, 0x78, 0x36, 0x69, 0x94, 0xd8, 0xa4, 0x0b, - 0x2b, 0x45, 0x65, 0x28, 0xc3, 0x9c, 0x83, 0x06, 0x15, 0x97, 0xc9, 0xf2, 0x5e, 0x41, 0x0e, 0xf4, - 0x7f, 0x34, 0xe1, 0xf2, 0xa7, 0xb4, 0x8f, 0x59, 0x72, 0x67, 0x74, 0xcf, 0x0f, 0xc4, 0x6d, 0xf2, - 0xe9, 0x68, 0xb1, 0xf0, 0xe2, 0x57, 0x9d, 0xf8, 0xe2, 0x57, 0x9b, 0xf0, 0xe2, 0x57, 0x3f, 0xd6, - 0x8b, 0x5f, 0xe3, 0xd4, 0x5e, 0xfc, 0x46, 0x7b, 0xad, 0x66, 0x69, 0xaf, 0xf5, 0x2c, 0xd7, 0x8f, - 0xcc, 0x8a, 0xb0, 0xf9, 0x56, 0x36, 0x6c, 0x26, 0x5a, 0x67, 0xe2, 0x53, 0x45, 0xe1, 0xa1, 0xac, - 0x75, 0xe4, 0x43, 0x59, 0x7b, 0xf4, 0xa1, 0xac, 0xfc, 0xad, 0x05, 0xc6, 0xbe, 0xb5, 0x5c, 0x85, - 0x85, 0x70, 0xe8, 0x99, 0xa4, 0x9f, 0xdc, 0x24, 0xce, 0xc9, 0x6d, 0xe7, 0xa1, 0xb9, 0x88, 0x38, - 0x53, 0x88, 0x88, 0xc4, 0x53, 0xe7, 0x33, 0x9e, 0x5a, 0x16, 0x27, 0x0b, 0xa5, 0x71, 0xf2, 0xdf, - 0xd3, 0x44, 0x7d, 0x06, 0xab, 0xe3, 0xac, 0xa7, 0x82, 0x52, 0x83, 0x59, 0x73, 0x80, 0x3d, 0x4b, - 0x5c, 0xf7, 0x89, 0xae, 0x5e, 0x0d, 0x27, 0x55, 0xfd, 0x1b, 0x7f, 0x04, 0x58, 0x4e, 0xab, 0x79, - 0xfe, 0xd7, 0x36, 0x09, 0x7a, 0x0c, 0x4b, 0xf1, 0x73, 0x50, 0x7c, 0x41, 0x8b, 0x26, 0xbd, 0x89, - 0x74, 0x2e, 0x95, 0x4f, 0x4a, 0xd1, 0xf4, 0x19, 0x64, 0xc2, 0xc5, 0x22, 0xc1, 0xf4, 0xf9, 0xe5, - 0x1b, 0x13, 0x28, 0x27, 0x58, 0x47, 0xb1, 0xb8, 0x56, 0x41, 0xcf, 0x60, 0x21, 0xff, 0x48, 0x80, - 0x72, 0xe5, 0x4d, 0xe9, 0xbb, 0x45, 0x47, 0x9f, 0x84, 0x92, 0xc8, 0xff, 0x9c, 0xbb, 0x41, 0xee, - 0x3e, 0x1c, 0xe9, 0xf9, 0x4e, 0xbf, 0xec, 0x45, 0xa1, 0xf3, 0xf5, 0x89, 0x38, 0x09, 0xf5, 0xf7, - 0xa1, 0x15, 0xdf, 0x11, 0xe7, 0xd5, 0x5c, 0xb8, 0x39, 0xee, 0x2c, 0xe5, 0xe9, 0xed, 0x87, 0xfa, - 0x0c, 0xfa, 0x50, 0x2e, 0xde, 0xa4, 0xb4, 0x64, 0x71, 0xe6, 0x66, 0xb4, 0x73, 0xb6, 0xe4, 0x36, - 0x52, 0x9f, 0x41, 0xdf, 0x81, 0x39, 0xfe, 0xb5, 0xa7, 0x9e, 0xe3, 0x57, 0xba, 0xf2, 0xd7, 0x1f, - 0xdd, 0xf8, 0xd7, 0x1f, 0xdd, 0xbb, 0x2e, 0x65, 0xc3, 0x4e, 0xc9, 0x75, 0xa1, 0x22, 0xf0, 0x1c, - 0xe6, 0xb7, 0x09, 0x4b, 0xbb, 0x7b, 0x74, 0xe5, 0x58, 0x77, 0x20, 0x1d, 0xbd, 0x88, 0x36, 0x7a, - 0x41, 0xa0, 0xcf, 0xa0, 0x5f, 0x55, 0xe0, 0xec, 0x36, 0x61, 0xc5, 0x7e, 0x19, 0xbd, 0x53, 0xce, - 0x64, 0x4c, 0x5f, 0xdd, 0x79, 0x34, 0x6d, 0x4c, 0xe6, 0xc9, 0xea, 0x33, 0xe8, 0xd7, 0x15, 0xb8, - 0x90, 0x11, 0x2c, 0xdb, 0x00, 0xa3, 0x9b, 0x93, 0x85, 0x2b, 0x69, 0x96, 0x3b, 0x9f, 0x4c, 0xf9, - 0x2b, 0x8b, 0x0c, 0x49, 0x7d, 0x06, 0xed, 0x09, 0x9b, 0xa4, 0xf5, 0x2e, 0xba, 0x5c, 0x5a, 0xd8, - 0x26, 0xdc, 0x57, 0xc7, 0x4d, 0x27, 0x76, 0xf8, 0x04, 0xe6, 0xb6, 0x09, 0x8b, 0x0b, 0xaf, 0xbc, - 0xa7, 0x15, 0x6a, 0xe2, 0x7c, 0xa8, 0x16, 0x6b, 0x35, 0xe1, 0x31, 0xcb, 0x92, 0x56, 0xa6, 0xb8, - 0xc8, 0xc7, 0x6a, 0x69, 0x15, 0x96, 0xf7, 0x98, 0xf2, 0xda, 0x44, 0x9f, 0x41, 0x2f, 0x60, 0xa5, - 0x3c, 0x55, 0xa2, 0xb7, 0x8e, 0x7d, 0x18, 0x76, 0xae, 0x1f, 0x07, 0x35, 0x66, 0xf9, 0xd1, 0xe6, - 0x5f, 0x5e, 0xad, 0x56, 0xfe, 0xfa, 0x6a, 0xb5, 0xf2, 0xaf, 0x57, 0xab, 0x95, 0xef, 0xdf, 0x3a, - 0xe2, 0xd7, 0x58, 0x99, 0x1f, 0x78, 0x61, 0x6a, 0x9b, 0x8e, 0x4d, 0x3c, 0xd6, 0x6b, 0x8a, 0x78, - 0xbb, 0xf5, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xed, 0x52, 0xaa, 0xcc, 0xff, 0x25, 0x00, 0x00, + 0x55, 0xfb, 0x25, 0xed, 0x3e, 0x59, 0x5f, 0x6d, 0x5b, 0x1e, 0xaf, 0x6d, 0xa1, 0x0c, 0xd8, 0xe5, + 0xd8, 0xc9, 0xaa, 0x2c, 0x57, 0x62, 0x70, 0x42, 0x28, 0x45, 0xb6, 0x25, 0xc7, 0x96, 0x2d, 0xc6, + 0x4e, 0x28, 0x83, 0x81, 0xea, 0x9d, 0x6d, 0xed, 0x76, 0x34, 0x1f, 0xed, 0x99, 0x1e, 0x05, 0xb9, + 0x8a, 0x0b, 0x50, 0x5c, 0xb8, 0x73, 0xe0, 0xca, 0x6f, 0xa0, 0x38, 0x72, 0xa0, 0x28, 0x38, 0x52, + 0x5c, 0xb8, 0x50, 0x05, 0xe5, 0x5f, 0x42, 0xf5, 0xc7, 0x7c, 0xee, 0xec, 0x4a, 0x61, 0x6d, 0x05, + 0xb8, 0x48, 0xd3, 0xaf, 0x5f, 0xbf, 0xf7, 0xfa, 0x7d, 0xf5, 0x7b, 0xdd, 0x0b, 0x57, 0x02, 0xc2, + 0xfc, 0x90, 0x04, 0x07, 0x24, 0x58, 0x93, 0x9f, 0x94, 0xfb, 0xc1, 0x61, 0xe6, 0xb3, 0xc3, 0x02, + 0x9f, 0xfb, 0x08, 0x52, 0x48, 0xfb, 0x61, 0x9f, 0xf2, 0x41, 0xd4, 0xed, 0xd8, 0xbe, 0xbb, 0x86, + 0x83, 0xbe, 0xcf, 0x02, 0xff, 0x73, 0xf9, 0xf1, 0xae, 0xdd, 0x5b, 0x3b, 0x58, 0x5f, 0x63, 0xfb, + 0xfd, 0x35, 0xcc, 0x68, 0xb8, 0x86, 0x19, 0x73, 0xa8, 0x8d, 0x39, 0xf5, 0xbd, 0xb5, 0x83, 0x1b, + 0xd8, 0x61, 0x03, 0x7c, 0x63, 0xad, 0x4f, 0x3c, 0x12, 0x60, 0x4e, 0x7a, 0x8a, 0x72, 0xfb, 0x42, + 0xdf, 0xf7, 0xfb, 0x0e, 0x59, 0x93, 0xa3, 0x6e, 0xb4, 0xb7, 0x46, 0x5c, 0xc6, 0x35, 0x5b, 0xf3, + 0x1f, 0x73, 0xb0, 0xb0, 0x83, 0x3d, 0xba, 0x47, 0x42, 0x6e, 0x91, 0x17, 0x11, 0x09, 0x39, 0x7a, + 0x0e, 0x75, 0x21, 0x8c, 0x51, 0x59, 0xad, 0x5c, 0x9d, 0x5d, 0xdf, 0xee, 0xa4, 0xd2, 0x74, 0x62, + 0x69, 0xe4, 0xc7, 0x8f, 0xed, 0x5e, 0xe7, 0x60, 0xbd, 0xc3, 0xf6, 0xfb, 0x1d, 0x21, 0x4d, 0x27, + 0x23, 0x4d, 0x27, 0x96, 0xa6, 0x63, 0x25, 0xdb, 0xb2, 0x24, 0x55, 0xd4, 0x86, 0x66, 0x40, 0x0e, + 0x68, 0x48, 0x7d, 0xcf, 0xa8, 0xae, 0x56, 0xae, 0xb6, 0xac, 0x64, 0x8c, 0x0c, 0x98, 0xf1, 0xfc, + 0x4d, 0x6c, 0x0f, 0x88, 0x51, 0x5b, 0xad, 0x5c, 0x6d, 0x5a, 0xf1, 0x10, 0xad, 0xc2, 0x2c, 0x66, + 0xec, 0x21, 0xee, 0x12, 0xe7, 0x01, 0x39, 0x34, 0xea, 0x72, 0x61, 0x16, 0x24, 0xd6, 0x62, 0xc6, + 0x1e, 0x61, 0x97, 0x18, 0x0d, 0x39, 0x1b, 0x0f, 0xd1, 0x45, 0x68, 0x79, 0xd8, 0x25, 0x21, 0xc3, + 0x36, 0x31, 0x9a, 0x72, 0x2e, 0x05, 0xa0, 0x9f, 0xc2, 0x52, 0x46, 0xf0, 0x27, 0x7e, 0x14, 0xd8, + 0xc4, 0x00, 0xb9, 0xf5, 0xc7, 0x93, 0x6d, 0x7d, 0xa3, 0x48, 0xd6, 0x1a, 0xe6, 0x84, 0x7e, 0x04, + 0x0d, 0x69, 0x79, 0x63, 0x76, 0xb5, 0xf6, 0x5a, 0xb5, 0xad, 0xc8, 0x22, 0x0f, 0x66, 0x98, 0x13, + 0xf5, 0xa9, 0x17, 0x1a, 0xa7, 0x24, 0x87, 0xa7, 0x93, 0x71, 0xd8, 0xf4, 0xbd, 0x3d, 0xda, 0xdf, + 0xc1, 0x1e, 0xee, 0x13, 0x97, 0x78, 0x7c, 0x57, 0x12, 0xb7, 0x62, 0x26, 0xe8, 0x25, 0x2c, 0xee, + 0x47, 0x21, 0xf7, 0x5d, 0xfa, 0x92, 0x3c, 0x66, 0x62, 0x6d, 0x68, 0xcc, 0x49, 0x6d, 0x3e, 0x9a, + 0x8c, 0xf1, 0x83, 0x02, 0x55, 0x6b, 0x88, 0x8f, 0x70, 0x92, 0xfd, 0xa8, 0x4b, 0x3e, 0x23, 0x81, + 0xf4, 0xae, 0x79, 0xe5, 0x24, 0x19, 0x90, 0x72, 0x23, 0xaa, 0x47, 0xa1, 0xb1, 0xb0, 0x5a, 0x53, + 0x6e, 0x94, 0x80, 0xd0, 0x55, 0x58, 0x38, 0x20, 0x01, 0xdd, 0x3b, 0x7c, 0x42, 0xfb, 0x1e, 0xe6, + 0x51, 0x40, 0x8c, 0x45, 0xe9, 0x8a, 0x45, 0x30, 0x72, 0x61, 0x6e, 0x40, 0x1c, 0x57, 0xa8, 0x7c, + 0x33, 0x20, 0xbd, 0xd0, 0x58, 0x92, 0xfa, 0xdd, 0x9a, 0xdc, 0x82, 0x92, 0x9c, 0x95, 0xa7, 0x2e, + 0x04, 0xf3, 0x7c, 0x4b, 0x47, 0x8a, 0x8a, 0x11, 0xa4, 0x04, 0x2b, 0x80, 0xd1, 0x15, 0x98, 0xe7, + 0x01, 0xb6, 0xf7, 0xa9, 0xd7, 0xdf, 0x21, 0x7c, 0xe0, 0xf7, 0x8c, 0xd3, 0x52, 0x13, 0x05, 0x28, + 0xb2, 0x01, 0x11, 0x0f, 0x77, 0x1d, 0xd2, 0x53, 0xbe, 0xf8, 0xf4, 0x90, 0x91, 0xd0, 0x38, 0x23, + 0x77, 0x71, 0xb3, 0x93, 0xc9, 0x50, 0x85, 0x04, 0xd1, 0xb9, 0x3b, 0xb4, 0xea, 0xae, 0xc7, 0x83, + 0x43, 0xab, 0x84, 0x1c, 0xda, 0x87, 0x59, 0xb1, 0x8f, 0xd8, 0x15, 0xce, 0x4a, 0x57, 0xb8, 0x3f, + 0x99, 0x8e, 0xb6, 0x53, 0x82, 0x56, 0x96, 0x3a, 0xea, 0x00, 0x1a, 0xe0, 0x70, 0x27, 0x72, 0x38, + 0x65, 0x0e, 0x51, 0x62, 0x84, 0xc6, 0xb2, 0x54, 0x53, 0xc9, 0x0c, 0x7a, 0x00, 0x10, 0x90, 0xbd, + 0x18, 0xef, 0x9c, 0xdc, 0xf9, 0xf5, 0x71, 0x3b, 0xb7, 0x12, 0x6c, 0xb5, 0xe3, 0xcc, 0x72, 0xc1, + 0x5c, 0x6c, 0x83, 0xd8, 0x5c, 0x47, 0xbb, 0x0c, 0x6b, 0x43, 0xba, 0x58, 0xc9, 0x8c, 0xf0, 0x45, + 0x0d, 0x95, 0x49, 0xeb, 0xbc, 0xf2, 0xd6, 0x0c, 0x08, 0x6d, 0xc3, 0xd7, 0xb0, 0xe7, 0xf9, 0x5c, + 0x6e, 0x3f, 0x16, 0x65, 0x4b, 0xa7, 0xf7, 0x5d, 0xcc, 0x07, 0xa1, 0xd1, 0x96, 0xab, 0x8e, 0x42, + 0x13, 0x2e, 0x41, 0xbd, 0x90, 0x63, 0xc7, 0x91, 0x48, 0xf7, 0xef, 0x18, 0x17, 0x94, 0x4b, 0xe4, + 0xa1, 0xed, 0xbb, 0x70, 0x6e, 0x84, 0x71, 0xd1, 0x22, 0xd4, 0xf6, 0xc9, 0xa1, 0x3c, 0x14, 0x5a, + 0x96, 0xf8, 0x44, 0x67, 0xa0, 0x71, 0x80, 0x9d, 0x88, 0xc8, 0x34, 0xde, 0xb4, 0xd4, 0xe0, 0x76, + 0xf5, 0x9b, 0x95, 0xf6, 0x2f, 0x2b, 0xb0, 0x50, 0x50, 0x55, 0xc9, 0xfa, 0x1f, 0x66, 0xd7, 0xbf, + 0x86, 0xc0, 0xd9, 0x7b, 0x8a, 0x83, 0x3e, 0xe1, 0x19, 0x41, 0xcc, 0xbf, 0x55, 0xc0, 0x28, 0xd8, + 0xf0, 0x7b, 0x94, 0x0f, 0xee, 0x51, 0x87, 0x84, 0xe8, 0x16, 0xcc, 0x04, 0x0a, 0xa6, 0x8f, 0xba, + 0x0b, 0x63, 0x4c, 0xbf, 0x3d, 0x65, 0xc5, 0xd8, 0xe8, 0x23, 0x68, 0xba, 0x84, 0xe3, 0x1e, 0xe6, + 0x58, 0xcb, 0xbe, 0x5a, 0xb6, 0x52, 0x70, 0xd9, 0xd1, 0x78, 0xdb, 0x53, 0x56, 0xb2, 0x06, 0xbd, + 0x07, 0x0d, 0x7b, 0x10, 0x79, 0xfb, 0xf2, 0x90, 0x9b, 0x5d, 0xbf, 0x34, 0x6a, 0xf1, 0xa6, 0x40, + 0xda, 0x9e, 0xb2, 0x14, 0xf6, 0xc7, 0xd3, 0x50, 0x67, 0x38, 0xe0, 0xe6, 0x3d, 0x38, 0x53, 0xc6, + 0x42, 0x9c, 0xac, 0xf6, 0x80, 0xd8, 0xfb, 0x61, 0xe4, 0x6a, 0x35, 0x27, 0x63, 0x84, 0xa0, 0x1e, + 0xd2, 0x97, 0x4a, 0xd5, 0x35, 0x4b, 0x7e, 0x9b, 0x6f, 0xc3, 0xd2, 0x10, 0x37, 0x61, 0x54, 0x25, + 0x9b, 0xa0, 0x70, 0x4a, 0xb3, 0x36, 0x23, 0x38, 0xfb, 0x54, 0xea, 0x22, 0x39, 0x5e, 0x4e, 0xa2, + 0x56, 0x30, 0xb7, 0x61, 0xb9, 0xc8, 0x36, 0x64, 0xbe, 0x17, 0x12, 0x11, 0x6c, 0x32, 0x1f, 0x53, + 0xd2, 0x4b, 0x67, 0xa5, 0x14, 0x4d, 0xab, 0x64, 0xc6, 0xfc, 0x6d, 0x15, 0x96, 0x2d, 0x12, 0xfa, + 0xce, 0x01, 0x89, 0x93, 0xe5, 0xc9, 0x94, 0x3b, 0x3f, 0x80, 0x1a, 0x66, 0x4c, 0xbb, 0xc9, 0xfd, + 0xd7, 0x56, 0x50, 0x58, 0x82, 0x2a, 0x7a, 0x07, 0x96, 0xb0, 0xdb, 0xa5, 0xfd, 0xc8, 0x8f, 0xc2, + 0x78, 0x5b, 0xd2, 0xa9, 0x5a, 0xd6, 0xf0, 0x84, 0x48, 0x38, 0xa1, 0x8c, 0xc8, 0xfb, 0x5e, 0x8f, + 0xfc, 0x44, 0xd6, 0x50, 0x35, 0x2b, 0x0b, 0x32, 0x6d, 0x38, 0x37, 0xa4, 0x24, 0xad, 0xf0, 0x6c, + 0xd9, 0x56, 0x29, 0x94, 0x6d, 0xa5, 0x62, 0x54, 0x47, 0x88, 0x61, 0xbe, 0xaa, 0xc0, 0x62, 0x1a, + 0x5c, 0x9a, 0xfc, 0x45, 0x68, 0xb9, 0x1a, 0x16, 0x1a, 0x15, 0x99, 0x33, 0x53, 0x40, 0xbe, 0x82, + 0xab, 0x16, 0x2b, 0xb8, 0x65, 0x98, 0x56, 0x05, 0xb6, 0xde, 0xba, 0x1e, 0xe5, 0x44, 0xae, 0x17, + 0x44, 0x5e, 0x01, 0x08, 0x93, 0x0c, 0x67, 0x4c, 0xcb, 0xd9, 0x0c, 0x04, 0x99, 0x70, 0x4a, 0x9d, + 0xf7, 0x16, 0x09, 0x23, 0x87, 0x1b, 0x33, 0x12, 0x23, 0x07, 0x93, 0xf1, 0xe6, 0xbb, 0x2e, 0xf6, + 0x7a, 0xa1, 0xd1, 0x94, 0x22, 0x27, 0x63, 0xd3, 0x87, 0x85, 0x87, 0x54, 0xec, 0x6f, 0x2f, 0x3c, + 0x99, 0x50, 0x79, 0x1f, 0xea, 0x82, 0x99, 0x10, 0xaa, 0x1b, 0x60, 0xcf, 0x1e, 0x90, 0x58, 0x8f, + 0xc9, 0x58, 0x24, 0x01, 0x8e, 0xfb, 0xa1, 0x51, 0x95, 0x70, 0xf9, 0x6d, 0xfe, 0xbe, 0xaa, 0x24, + 0xdd, 0x60, 0x2c, 0xfc, 0xea, 0x1b, 0x80, 0xf2, 0x92, 0xa4, 0x36, 0x5c, 0x92, 0x14, 0x44, 0xfe, + 0x32, 0x25, 0xc9, 0x6b, 0x3a, 0xe4, 0xcc, 0x08, 0x66, 0x36, 0x18, 0x13, 0x82, 0xa0, 0x1b, 0x50, + 0xc7, 0x8c, 0x29, 0x85, 0x17, 0xf2, 0xb9, 0x46, 0x11, 0xff, 0xb5, 0x48, 0x12, 0xb5, 0x7d, 0x0b, + 0x5a, 0x09, 0xe8, 0x28, 0xb6, 0xad, 0x2c, 0xdb, 0x55, 0x00, 0x55, 0x73, 0xdf, 0xf7, 0xf6, 0x7c, + 0x61, 0x52, 0x11, 0x08, 0x7a, 0xa9, 0xfc, 0x36, 0x6f, 0xc7, 0x18, 0x52, 0xb6, 0x77, 0xa0, 0x41, + 0x39, 0x71, 0x63, 0xe1, 0x96, 0xb3, 0xc2, 0xa5, 0x84, 0x2c, 0x85, 0x64, 0xfe, 0xb9, 0x09, 0xe7, + 0x85, 0xc5, 0x9e, 0xc8, 0x10, 0xda, 0x60, 0xec, 0x0e, 0xe1, 0x98, 0x3a, 0xe1, 0x77, 0x23, 0x12, + 0x1c, 0xbe, 0x61, 0xc7, 0xe8, 0xc3, 0xb4, 0x8a, 0x40, 0x9d, 0x2d, 0x5f, 0x7b, 0xfb, 0xa5, 0xc9, + 0xa7, 0x3d, 0x57, 0xed, 0xcd, 0xf4, 0x5c, 0x65, 0x3d, 0x50, 0xfd, 0x84, 0x7a, 0xa0, 0xd1, 0x6d, + 0x70, 0xa6, 0xb9, 0x9e, 0xce, 0x37, 0xd7, 0x25, 0xad, 0xc5, 0xcc, 0x71, 0x5b, 0x8b, 0x66, 0x69, + 0x6b, 0xe1, 0x96, 0xc6, 0x71, 0x4b, 0xaa, 0xfb, 0xdb, 0x59, 0x0f, 0x1c, 0xe9, 0x6b, 0x93, 0x34, + 0x19, 0xf0, 0x46, 0x9b, 0x8c, 0x4f, 0x73, 0x4d, 0x83, 0x6a, 0xdb, 0xdf, 0x3b, 0xde, 0x9e, 0xc6, + 0xb4, 0x0f, 0xff, 0x77, 0xa5, 0xf7, 0x2f, 0x64, 0xc5, 0xc5, 0xfc, 0x54, 0x07, 0xc9, 0x61, 0x2f, + 0xce, 0x21, 0x71, 0xec, 0xea, 0xa4, 0x25, 0xbe, 0xd1, 0x75, 0xa8, 0x0b, 0x25, 0xeb, 0x92, 0xf8, + 0x5c, 0x56, 0x9f, 0xc2, 0x12, 0x1b, 0x8c, 0x3d, 0x61, 0xc4, 0xb6, 0x24, 0x12, 0xba, 0x0d, 0xad, + 0xc4, 0xf1, 0x75, 0x64, 0x5d, 0xcc, 0xae, 0x48, 0xe2, 0x24, 0x5e, 0x96, 0xa2, 0x8b, 0xb5, 0x3d, + 0x1a, 0x10, 0x5b, 0x16, 0x8c, 0x8d, 0xe1, 0xb5, 0x77, 0xe2, 0xc9, 0x64, 0x6d, 0x82, 0x8e, 0x6e, + 0xc0, 0xb4, 0xba, 0xe7, 0x90, 0x11, 0x34, 0xbb, 0x7e, 0x7e, 0x38, 0x99, 0xc6, 0xab, 0x34, 0xa2, + 0xf9, 0xa7, 0x0a, 0xbc, 0x95, 0x3a, 0x44, 0x1c, 0x4d, 0x71, 0xcd, 0xfe, 0xd5, 0x9f, 0xb8, 0x57, + 0x60, 0x5e, 0x36, 0x09, 0xe9, 0x75, 0x87, 0xba, 0x79, 0x2b, 0x40, 0xcd, 0xdf, 0x55, 0xe0, 0xf2, + 0xf0, 0x3e, 0x36, 0x07, 0x38, 0xe0, 0x89, 0x79, 0x4f, 0x62, 0x2f, 0xf1, 0x81, 0x57, 0x4d, 0x0f, + 0xbc, 0xdc, 0xfe, 0x6a, 0xf9, 0xfd, 0x99, 0x7f, 0xa8, 0xc2, 0x6c, 0xc6, 0x81, 0xca, 0x0e, 0x4c, + 0x51, 0x0c, 0x4a, 0xbf, 0x95, 0x6d, 0xa1, 0x3c, 0x14, 0x5a, 0x56, 0x06, 0x82, 0xf6, 0x01, 0x18, + 0x0e, 0xb0, 0x4b, 0x38, 0x09, 0x44, 0x26, 0x17, 0x11, 0xff, 0x60, 0xf2, 0xec, 0xb2, 0x1b, 0xd3, + 0xb4, 0x32, 0xe4, 0x45, 0x35, 0x2b, 0x59, 0x87, 0x3a, 0x7f, 0xeb, 0x11, 0xfa, 0x02, 0xe6, 0xf7, + 0xa8, 0x43, 0x76, 0x53, 0x41, 0xa6, 0xa5, 0x20, 0x8f, 0x27, 0x17, 0xe4, 0x5e, 0x96, 0xae, 0x55, + 0x60, 0x63, 0x5e, 0x83, 0xc5, 0x62, 0x3c, 0x09, 0x21, 0xa9, 0x8b, 0xfb, 0x89, 0xb6, 0xf4, 0xc8, + 0x44, 0xb0, 0x58, 0x8c, 0x1f, 0xf3, 0x9f, 0x55, 0x38, 0x9b, 0x90, 0xdb, 0xf0, 0x3c, 0x3f, 0xf2, + 0x6c, 0x79, 0x75, 0x58, 0x6a, 0x8b, 0x33, 0xd0, 0xe0, 0x94, 0x3b, 0x49, 0xe1, 0x23, 0x07, 0xe2, + 0xec, 0xe2, 0xbe, 0xef, 0x70, 0xca, 0xb4, 0x81, 0xe3, 0xa1, 0xb2, 0xfd, 0x8b, 0x88, 0x06, 0xa4, + 0x27, 0x33, 0x41, 0xd3, 0x4a, 0xc6, 0x62, 0x4e, 0x54, 0x35, 0xb2, 0xc4, 0x57, 0xca, 0x4c, 0xc6, + 0xd2, 0xef, 0x7d, 0xc7, 0x21, 0xb6, 0x50, 0x47, 0xa6, 0x09, 0x28, 0x40, 0x65, 0x73, 0xc1, 0x03, + 0xea, 0xf5, 0x75, 0x0b, 0xa0, 0x47, 0x42, 0x4e, 0x1c, 0x04, 0xf8, 0x50, 0x57, 0xfe, 0x6a, 0x80, + 0x3e, 0x84, 0x9a, 0x8b, 0x99, 0x3e, 0xe8, 0xae, 0xe5, 0xb2, 0x43, 0x99, 0x06, 0x3a, 0x3b, 0x98, + 0xa9, 0x93, 0x40, 0x2c, 0x6b, 0xbf, 0x0f, 0xcd, 0x18, 0xf0, 0xa5, 0x4a, 0xc2, 0xcf, 0x61, 0x2e, + 0x97, 0x7c, 0xd0, 0x33, 0x58, 0x4e, 0x3d, 0x2a, 0xcb, 0x50, 0x17, 0x81, 0x6f, 0x1d, 0x29, 0x99, + 0x35, 0x82, 0x80, 0xf9, 0x02, 0x96, 0x84, 0xcb, 0xc8, 0xc0, 0x3f, 0xa1, 0xd6, 0xe6, 0x03, 0x68, + 0x25, 0x2c, 0x4b, 0x7d, 0xa6, 0x0d, 0xcd, 0x83, 0xf8, 0x4a, 0x57, 0xf5, 0x36, 0xc9, 0xd8, 0xdc, + 0x00, 0x94, 0x95, 0x57, 0x9f, 0x40, 0xd7, 0xf3, 0x45, 0xf1, 0xd9, 0xe2, 0x71, 0x23, 0xd1, 0xe3, + 0x9a, 0xf8, 0xef, 0x55, 0x58, 0xd8, 0xa2, 0xf2, 0x8e, 0xe4, 0x84, 0x92, 0xdc, 0x35, 0x58, 0x0c, + 0xa3, 0xae, 0xeb, 0xf7, 0x22, 0x87, 0xe8, 0xa2, 0x40, 0x9f, 0xf4, 0x43, 0xf0, 0x71, 0xc9, 0x4f, + 0x28, 0x8b, 0x61, 0x3e, 0xd0, 0xdd, 0xaf, 0xfc, 0x46, 0x1f, 0xc2, 0xf9, 0x47, 0xe4, 0x0b, 0xbd, + 0x9f, 0x2d, 0xc7, 0xef, 0x76, 0xa9, 0xd7, 0x8f, 0x99, 0x34, 0x24, 0x93, 0xd1, 0x08, 0x65, 0xa5, + 0xe2, 0x74, 0x79, 0xa9, 0x98, 0x74, 0xd0, 0x9b, 0xbe, 0xeb, 0x52, 0xae, 0x2b, 0xca, 0x1c, 0xcc, + 0xfc, 0x79, 0x05, 0x16, 0x53, 0xcd, 0x6a, 0xdb, 0xdc, 0x52, 0x31, 0xa4, 0x2c, 0x73, 0x39, 0x6b, + 0x99, 0x22, 0xea, 0x7f, 0x1e, 0x3e, 0xa7, 0xb2, 0xe1, 0xf3, 0xab, 0x2a, 0x9c, 0xdd, 0xa2, 0x3c, + 0x4e, 0x5c, 0xf4, 0x7f, 0xcd, 0xca, 0x25, 0x36, 0xa9, 0x1f, 0xcf, 0x26, 0x8d, 0x12, 0x9b, 0x74, + 0x60, 0xb9, 0xa8, 0x0c, 0x6d, 0x98, 0x33, 0xd0, 0x60, 0xf2, 0xd2, 0x59, 0xdd, 0x2b, 0xa8, 0x81, + 0xf9, 0xb3, 0x19, 0xb8, 0xf4, 0x29, 0xeb, 0x61, 0x9e, 0xdc, 0x19, 0xdd, 0xf3, 0x03, 0x79, 0xeb, + 0x7c, 0x32, 0x5a, 0x2c, 0xbc, 0x0c, 0x56, 0xc7, 0xbe, 0x0c, 0xd6, 0xc6, 0xbc, 0x0c, 0xd6, 0x8f, + 0xf5, 0x32, 0xd8, 0x38, 0xb1, 0x97, 0xc1, 0xe1, 0x5e, 0x6b, 0xba, 0xb4, 0xd7, 0x7a, 0x96, 0xeb, + 0x47, 0x66, 0x64, 0xd8, 0x7c, 0x2b, 0x1b, 0x36, 0x63, 0xad, 0x33, 0xf6, 0x49, 0xa3, 0xf0, 0xa0, + 0xd6, 0x3c, 0xf2, 0x41, 0xad, 0x35, 0xfc, 0xa0, 0x56, 0xfe, 0x26, 0x03, 0x23, 0xdf, 0x64, 0xae, + 0xc0, 0x7c, 0x78, 0xe8, 0xd9, 0xa4, 0x97, 0xdc, 0x24, 0xce, 0xaa, 0x6d, 0xe7, 0xa1, 0xb9, 0x88, + 0x38, 0x55, 0x88, 0x88, 0xc4, 0x53, 0xe7, 0x32, 0x9e, 0x5a, 0x16, 0x27, 0xf3, 0x23, 0xdb, 0xdc, + 0xc2, 0x73, 0xc9, 0x42, 0xe9, 0x73, 0xc9, 0x7f, 0x4d, 0xb3, 0xf5, 0x19, 0xac, 0x8c, 0xb2, 0xb2, + 0x0e, 0x5e, 0x03, 0x66, 0xec, 0x01, 0xf6, 0xfa, 0xf2, 0x5a, 0x50, 0x76, 0xff, 0x7a, 0x38, 0xae, + 0x3b, 0x58, 0xff, 0x23, 0xc0, 0x52, 0x5a, 0xf5, 0x8b, 0xbf, 0xd4, 0x26, 0xe8, 0x31, 0x2c, 0xc6, + 0xcf, 0x4b, 0xf1, 0x45, 0x2e, 0x1a, 0xf7, 0x76, 0xd2, 0xbe, 0x58, 0x3e, 0xa9, 0x44, 0x33, 0xa7, + 0x90, 0x0d, 0xe7, 0x8b, 0x04, 0xd3, 0x67, 0x9a, 0x6f, 0x8c, 0xa1, 0x9c, 0x60, 0x1d, 0xc5, 0xe2, + 0x6a, 0x05, 0x3d, 0x83, 0xf9, 0xfc, 0x63, 0x02, 0xca, 0x95, 0x41, 0xa5, 0xef, 0x1b, 0x6d, 0x73, + 0x1c, 0x4a, 0x22, 0xff, 0x73, 0xe1, 0x06, 0xb9, 0x7b, 0x73, 0x64, 0xe6, 0x6f, 0x04, 0xca, 0x5e, + 0x1e, 0xda, 0x5f, 0x1f, 0x8b, 0x93, 0x50, 0xff, 0x00, 0x9a, 0xf1, 0x5d, 0x72, 0x5e, 0xcd, 0x85, + 0x1b, 0xe6, 0xf6, 0x62, 0x9e, 0xde, 0x5e, 0x68, 0x4e, 0xa1, 0x8f, 0xd4, 0xe2, 0x0d, 0xc6, 0x4a, + 0x16, 0x67, 0x6e, 0x50, 0xdb, 0xa7, 0x4b, 0x6e, 0x2d, 0xcd, 0x29, 0xf4, 0x1d, 0x98, 0x15, 0x5f, + 0xbb, 0xfa, 0x79, 0x7f, 0xb9, 0xa3, 0x7e, 0x4d, 0xd2, 0x89, 0x7f, 0x4d, 0xd2, 0xb9, 0xeb, 0x32, + 0x7e, 0xd8, 0x2e, 0xb9, 0x56, 0xd4, 0x04, 0x9e, 0xc3, 0xdc, 0x16, 0xe1, 0xe9, 0x2d, 0x00, 0xba, + 0x7c, 0xac, 0xbb, 0x92, 0xb6, 0x59, 0x44, 0x1b, 0xbe, 0x48, 0x30, 0xa7, 0xd0, 0xaf, 0x2b, 0x70, + 0x7a, 0x8b, 0xf0, 0x62, 0x5f, 0x8d, 0xde, 0x2d, 0x67, 0x32, 0xa2, 0xff, 0x6e, 0x3f, 0x9a, 0x34, + 0x26, 0xf3, 0x64, 0xcd, 0x29, 0xf4, 0x9b, 0x0a, 0x9c, 0xcb, 0x08, 0x96, 0x6d, 0x94, 0xd1, 0x8d, + 0xf1, 0xc2, 0x95, 0x34, 0xd5, 0xed, 0x4f, 0x26, 0xfc, 0xd5, 0x46, 0x86, 0xa4, 0x39, 0x85, 0x76, + 0xa5, 0x4d, 0xd2, 0xba, 0x18, 0x5d, 0x2a, 0x2d, 0x80, 0x13, 0xee, 0x2b, 0xa3, 0xa6, 0x13, 0x3b, + 0x7c, 0x02, 0xb3, 0x5b, 0x84, 0xc7, 0x05, 0x5a, 0xde, 0xd3, 0x0a, 0xb5, 0x73, 0x3e, 0x54, 0x8b, + 0x35, 0x9d, 0xf4, 0x98, 0x25, 0x45, 0x2b, 0x53, 0x84, 0xe4, 0x63, 0xb5, 0xb4, 0x5a, 0xcb, 0x7b, + 0x4c, 0x79, 0x0d, 0x63, 0x4e, 0xa1, 0x17, 0xb0, 0x5c, 0x9e, 0x2a, 0xd1, 0xdb, 0xc7, 0x3e, 0x34, + 0xdb, 0xd7, 0x8e, 0x83, 0x1a, 0xb3, 0xfc, 0x78, 0xe3, 0x2f, 0xaf, 0x56, 0x2a, 0x7f, 0x7d, 0xb5, + 0x52, 0xf9, 0xd7, 0xab, 0x95, 0xca, 0xf7, 0x6f, 0x1e, 0xf1, 0xeb, 0xae, 0xcc, 0x0f, 0xc6, 0x30, + 0xa3, 0xb6, 0x43, 0x89, 0xc7, 0xbb, 0xd3, 0x32, 0xde, 0x6e, 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, + 0xa5, 0xe0, 0xaa, 0x70, 0x4f, 0x26, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -3243,6 +3262,15 @@ func (m *ManifestRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.InstallationID) > 0 { + i -= len(m.InstallationID) + copy(dAtA[i:], m.InstallationID) + i = encodeVarintRepository(dAtA, i, uint64(len(m.InstallationID))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xda + } if len(m.AnnotationManifestGeneratePaths) > 0 { i -= len(m.AnnotationManifestGeneratePaths) copy(dAtA[i:], m.AnnotationManifestGeneratePaths) @@ -5276,6 +5304,13 @@ func (m *UpdateRevisionForPathsRequest) MarshalToSizedBuffer(dAtA []byte) (int, i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.InstallationID) > 0 { + i -= len(m.InstallationID) + copy(dAtA[i:], m.InstallationID) + i = encodeVarintRepository(dAtA, i, uint64(len(m.InstallationID))) + i-- + dAtA[i] = 0x7a + } if m.NoRevisionCache { i-- if m.NoRevisionCache { @@ -5588,6 +5623,10 @@ func (m *ManifestRequest) Size() (n int) { if l > 0 { n += 2 + l + sovRepository(uint64(l)) } + l = len(m.InstallationID) + if l > 0 { + n += 2 + l + sovRepository(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -6447,6 +6486,10 @@ func (m *UpdateRevisionForPathsRequest) Size() (n int) { if m.NoRevisionCache { n += 2 } + l = len(m.InstallationID) + if l > 0 { + n += 1 + l + sovRepository(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -7397,6 +7440,38 @@ func (m *ManifestRequest) Unmarshal(dAtA []byte) error { } m.AnnotationManifestGeneratePaths = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 27: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InstallationID", 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.InstallationID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRepository(dAtA[iNdEx:]) @@ -12733,6 +12808,38 @@ func (m *UpdateRevisionForPathsRequest) Unmarshal(dAtA []byte) error { } } m.NoRevisionCache = bool(v != 0) + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InstallationID", 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.InstallationID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRepository(dAtA[iNdEx:]) diff --git a/reposerver/askpass/server.go b/reposerver/askpass/server.go index 2eb9f898697764..b6a1bbfc48de24 100644 --- a/reposerver/askpass/server.go +++ b/reposerver/askpass/server.go @@ -22,6 +22,20 @@ type Server interface { Run(path string) error } +// server is a gRPC server that provides a way for an external process (usually git) to access credentials without those +// credentials being set directly in the git process's environment. Before invoking git, the caller invokes Add to add a +// new credential, which returns a unique id. The caller then sets the GIT_ASKPASS environment variable to the path of +// the argocd-git-ask-pass binary and sets the ASKPASS_NONCE environment variable to the id. When git needs credentials, +// it will invoke the argocd-git-ask-pass binary, which will use the ASKPASS_NONCE to look up the credentials and return +// them to git. After the git process completes, the caller should invoke Remove to remove the credential. +// +// This is meant to solve a class of problems that was demonstrated by an old bug in Kustomize. We needed to enable +// Kustomize to invoke git to fetch a private repository. But Kustomize had a bug that allowed a user to dump the +// environment variables of the process into manifests, which would expose the credentials. Kustomize eventually fixed +// the bug. But to prevent this from happening again, we now only set the ASKPASS_NONCE environment variable instead of +// directly passing the git credentials via environment variables. Even if the nonce leaks, 1) the user probably doesn't +// have access to the server to look up the corresponding git credentials, and 2) the nonce should be deleted from +// the server before the user even sees the manifests. type server struct { lock sync.Mutex creds map[string]Creds diff --git a/reposerver/cache/cache.go b/reposerver/cache/cache.go index fde5a81748ab0b..cdc16ea4ebb825 100644 --- a/reposerver/cache/cache.go +++ b/reposerver/cache/cache.go @@ -290,13 +290,17 @@ func (c *Cache) UnlockGitReferences(repo string, lockId string) error { // refSourceCommitSHAs is a list of resolved revisions for each ref source. This allows us to invalidate the cache // when someone pushes a commit to a source which is referenced from the main source (the one referred to by `revision`). -func manifestCacheKey(revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, namespace string, trackingMethod string, appLabelKey string, appName string, info ClusterRuntimeInfo, refSourceCommitSHAs ResolvedRevisions) string { +func manifestCacheKey(revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, namespace string, trackingMethod string, appLabelKey string, appName string, info ClusterRuntimeInfo, refSourceCommitSHAs ResolvedRevisions, installationID string) string { // TODO: this function is getting unwieldy. We should probably consolidate some of this stuff into a struct. For // example, revision could be part of ResolvedRevisions. And srcRefs is probably redundant now that // refSourceCommitSHAs has been added. We don't need to know the _target_ revisions of the referenced sources // when the _resolved_ revisions are already part of the key. trackingKey := trackingKey(appLabelKey, trackingMethod) - return fmt.Sprintf("mfst|%s|%s|%s|%s|%d", trackingKey, appName, revision, namespace, appSourceKey(appSrc, srcRefs, refSourceCommitSHAs)+clusterRuntimeInfoKey(info)) + key := fmt.Sprintf("mfst|%s|%s|%s|%s|%d", trackingKey, appName, revision, namespace, appSourceKey(appSrc, srcRefs, refSourceCommitSHAs)+clusterRuntimeInfoKey(info)) + if installationID != "" { + key = fmt.Sprintf("%s|%s", key, installationID) + } + return key } func trackingKey(appLabelKey string, trackingMethod string) string { @@ -323,14 +327,14 @@ func LogDebugManifestCacheKeyFields(message string, reason string, revision stri } } -func (c *Cache) SetNewRevisionManifests(newRevision string, revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, clusterInfo ClusterRuntimeInfo, namespace string, trackingMethod string, appLabelKey string, appName string, refSourceCommitSHAs ResolvedRevisions) error { - oldKey := manifestCacheKey(revision, appSrc, srcRefs, namespace, trackingMethod, appLabelKey, appName, clusterInfo, refSourceCommitSHAs) - newKey := manifestCacheKey(newRevision, appSrc, srcRefs, namespace, trackingMethod, appLabelKey, appName, clusterInfo, refSourceCommitSHAs) +func (c *Cache) SetNewRevisionManifests(newRevision string, revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, clusterInfo ClusterRuntimeInfo, namespace string, trackingMethod string, appLabelKey string, appName string, refSourceCommitSHAs ResolvedRevisions, installationID string) error { + oldKey := manifestCacheKey(revision, appSrc, srcRefs, namespace, trackingMethod, appLabelKey, appName, clusterInfo, refSourceCommitSHAs, installationID) + newKey := manifestCacheKey(newRevision, appSrc, srcRefs, namespace, trackingMethod, appLabelKey, appName, clusterInfo, refSourceCommitSHAs, installationID) return c.cache.RenameItem(oldKey, newKey, c.repoCacheExpiration) } -func (c *Cache) GetManifests(revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, clusterInfo ClusterRuntimeInfo, namespace string, trackingMethod string, appLabelKey string, appName string, res *CachedManifestResponse, refSourceCommitSHAs ResolvedRevisions) error { - err := c.cache.GetItem(manifestCacheKey(revision, appSrc, srcRefs, namespace, trackingMethod, appLabelKey, appName, clusterInfo, refSourceCommitSHAs), res) +func (c *Cache) GetManifests(revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, clusterInfo ClusterRuntimeInfo, namespace string, trackingMethod string, appLabelKey string, appName string, res *CachedManifestResponse, refSourceCommitSHAs ResolvedRevisions, installationID string) error { + err := c.cache.GetItem(manifestCacheKey(revision, appSrc, srcRefs, namespace, trackingMethod, appLabelKey, appName, clusterInfo, refSourceCommitSHAs, installationID), res) if err != nil { return err } @@ -346,7 +350,7 @@ func (c *Cache) GetManifests(revision string, appSrc *appv1.ApplicationSource, s LogDebugManifestCacheKeyFields("deleting manifests cache", "manifest hash did not match or cached response is empty", revision, appSrc, srcRefs, clusterInfo, namespace, trackingMethod, appLabelKey, appName, refSourceCommitSHAs) - err = c.DeleteManifests(revision, appSrc, srcRefs, clusterInfo, namespace, trackingMethod, appLabelKey, appName, refSourceCommitSHAs) + err = c.DeleteManifests(revision, appSrc, srcRefs, clusterInfo, namespace, trackingMethod, appLabelKey, appName, refSourceCommitSHAs, installationID) if err != nil { return fmt.Errorf("Unable to delete manifest after hash mismatch, %w", err) } @@ -366,7 +370,7 @@ func (c *Cache) GetManifests(revision string, appSrc *appv1.ApplicationSource, s return nil } -func (c *Cache) SetManifests(revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, clusterInfo ClusterRuntimeInfo, namespace string, trackingMethod string, appLabelKey string, appName string, res *CachedManifestResponse, refSourceCommitSHAs ResolvedRevisions) error { +func (c *Cache) SetManifests(revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, clusterInfo ClusterRuntimeInfo, namespace string, trackingMethod string, appLabelKey string, appName string, res *CachedManifestResponse, refSourceCommitSHAs ResolvedRevisions, installationID string) error { // Generate and apply the cache entry hash, before writing if res != nil { res = res.shallowCopy() @@ -378,7 +382,7 @@ func (c *Cache) SetManifests(revision string, appSrc *appv1.ApplicationSource, s } return c.cache.SetItem( - manifestCacheKey(revision, appSrc, srcRefs, namespace, trackingMethod, appLabelKey, appName, clusterInfo, refSourceCommitSHAs), + manifestCacheKey(revision, appSrc, srcRefs, namespace, trackingMethod, appLabelKey, appName, clusterInfo, refSourceCommitSHAs, installationID), res, &cacheutil.CacheActionOpts{ Expiration: c.repoCacheExpiration, @@ -386,9 +390,9 @@ func (c *Cache) SetManifests(revision string, appSrc *appv1.ApplicationSource, s }) } -func (c *Cache) DeleteManifests(revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, clusterInfo ClusterRuntimeInfo, namespace, trackingMethod, appLabelKey, appName string, refSourceCommitSHAs ResolvedRevisions) error { +func (c *Cache) DeleteManifests(revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, clusterInfo ClusterRuntimeInfo, namespace, trackingMethod, appLabelKey, appName string, refSourceCommitSHAs ResolvedRevisions, installationID string) error { return c.cache.SetItem( - manifestCacheKey(revision, appSrc, srcRefs, namespace, trackingMethod, appLabelKey, appName, clusterInfo, refSourceCommitSHAs), + manifestCacheKey(revision, appSrc, srcRefs, namespace, trackingMethod, appLabelKey, appName, clusterInfo, refSourceCommitSHAs, installationID), "", &cacheutil.CacheActionOpts{Delete: true}) } diff --git a/reposerver/cache/cache_test.go b/reposerver/cache/cache_test.go index 82e7fd556ad16b..1715a094573314 100644 --- a/reposerver/cache/cache_test.go +++ b/reposerver/cache/cache_test.go @@ -94,43 +94,43 @@ func TestCache_GetManifests(t *testing.T) { // cache miss q := &apiclient.ManifestRequest{} value := &CachedManifestResponse{} - err := cache.GetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", value, nil) + err := cache.GetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", value, nil, "") assert.Equal(t, ErrCacheMiss, err) // populate cache res := &CachedManifestResponse{ManifestResponse: &apiclient.ManifestResponse{SourceType: "my-source-type"}} - err = cache.SetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", res, nil) + err = cache.SetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", res, nil, "") require.NoError(t, err) t.Run("expect cache miss because of changed revision", func(t *testing.T) { - err = cache.GetManifests("other-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", value, nil) + err = cache.GetManifests("other-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", value, nil, "") assert.Equal(t, ErrCacheMiss, err) }) t.Run("expect cache miss because of changed path", func(t *testing.T) { - err = cache.GetManifests("my-revision", &ApplicationSource{Path: "other-path"}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", value, nil) + err = cache.GetManifests("my-revision", &ApplicationSource{Path: "other-path"}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", value, nil, "") assert.Equal(t, ErrCacheMiss, err) }) t.Run("expect cache miss because of changed namespace", func(t *testing.T) { - err = cache.GetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "other-namespace", "", "my-app-label-key", "my-app-label-value", value, nil) + err = cache.GetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "other-namespace", "", "my-app-label-key", "my-app-label-value", value, nil, "") assert.Equal(t, ErrCacheMiss, err) }) t.Run("expect cache miss because of changed app label key", func(t *testing.T) { - err = cache.GetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "other-app-label-key", "my-app-label-value", value, nil) + err = cache.GetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "other-app-label-key", "my-app-label-value", value, nil, "") assert.Equal(t, ErrCacheMiss, err) }) t.Run("expect cache miss because of changed app label value", func(t *testing.T) { - err = cache.GetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "other-app-label-value", value, nil) + err = cache.GetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "other-app-label-value", value, nil, "") assert.Equal(t, ErrCacheMiss, err) }) t.Run("expect cache miss because of changed referenced source", func(t *testing.T) { - err = cache.GetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "other-app-label-value", value, map[string]string{"my-referenced-source": "my-referenced-revision"}) + err = cache.GetManifests("my-revision", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "other-app-label-value", value, map[string]string{"my-referenced-source": "my-referenced-revision"}, "") assert.Equal(t, ErrCacheMiss, err) }) t.Run("expect cache hit", func(t *testing.T) { err = cache.SetManifests( "my-revision1", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", - &CachedManifestResponse{ManifestResponse: &apiclient.ManifestResponse{SourceType: "my-source-type", Revision: "my-revision2"}}, nil) + &CachedManifestResponse{ManifestResponse: &apiclient.ManifestResponse{SourceType: "my-source-type", Revision: "my-revision2"}}, nil, "") require.NoError(t, err) - err = cache.GetManifests("my-revision1", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", value, nil) + err = cache.GetManifests("my-revision1", &ApplicationSource{}, q.RefSources, q, "my-namespace", "", "my-app-label-key", "my-app-label-value", value, nil, "") require.NoError(t, err) assert.Equal(t, "my-source-type", value.ManifestResponse.SourceType) @@ -199,7 +199,7 @@ func TestCachedManifestResponse_HashBehavior(t *testing.T) { NumberOfConsecutiveFailures: 0, } q := &apiclient.ManifestRequest{} - err := repoCache.SetManifests(response.Revision, appSrc, q.RefSources, q, response.Namespace, "", appKey, appValue, store, nil) + err := repoCache.SetManifests(response.Revision, appSrc, q.RefSources, q, response.Namespace, "", appKey, appValue, store, nil, "") if err != nil { t.Fatal(err) } @@ -229,7 +229,7 @@ func TestCachedManifestResponse_HashBehavior(t *testing.T) { // Retrieve the value using 'GetManifests' and confirm it works retrievedVal := &CachedManifestResponse{} - err = repoCache.GetManifests(response.Revision, appSrc, q.RefSources, q, response.Namespace, "", appKey, appValue, retrievedVal, nil) + err = repoCache.GetManifests(response.Revision, appSrc, q.RefSources, q, response.Namespace, "", appKey, appValue, retrievedVal, nil, "") if err != nil { t.Fatal(err) } @@ -251,7 +251,7 @@ func TestCachedManifestResponse_HashBehavior(t *testing.T) { // Retrieve the value using GetManifests and confirm it returns a cache miss retrievedVal = &CachedManifestResponse{} - err = repoCache.GetManifests(response.Revision, appSrc, q.RefSources, q, response.Namespace, "", appKey, appValue, retrievedVal, nil) + err = repoCache.GetManifests(response.Revision, appSrc, q.RefSources, q, response.Namespace, "", appKey, appValue, retrievedVal, nil, "") assert.Equal(t, err, cacheutil.ErrCacheMiss) @@ -570,8 +570,7 @@ func TestUnlockGitReferences(t *testing.T) { t.Run("Test not locked", func(t *testing.T) { err := cache.UnlockGitReferences("test-repo", "") - require.Error(t, err) - assert.Contains(t, err.Error(), "key is missing") + assert.ErrorContains(t, err, "key is missing") }) t.Run("Test unlock", func(t *testing.T) { diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go index 7115c1bedd9aa9..71fa431d557bc3 100644 --- a/reposerver/repository/repository.go +++ b/reposerver/repository/repository.go @@ -827,7 +827,7 @@ func (s *Service) runManifestGenAsync(ctx context.Context, repoRoot, commitSHA, // Retrieve a new copy (if available) of the cached response: this ensures we are updating the latest copy of the cache, // rather than a copy of the cache that occurred before (a potentially lengthy) manifest generation. innerRes := &cache.CachedManifestResponse{} - cacheErr := s.cache.GetManifests(cacheKey, appSourceCopy, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, innerRes, refSourceCommitSHAs) + cacheErr := s.cache.GetManifests(cacheKey, appSourceCopy, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, innerRes, refSourceCommitSHAs, q.InstallationID) if cacheErr != nil && !errors.Is(cacheErr, cache.ErrCacheMiss) { logCtx.Warnf("manifest cache get error %s: %v", appSourceCopy.String(), cacheErr) ch.errCh <- cacheErr @@ -845,7 +845,7 @@ func (s *Service) runManifestGenAsync(ctx context.Context, repoRoot, commitSHA, // Update the cache to include failure information innerRes.NumberOfConsecutiveFailures++ innerRes.MostRecentError = err.Error() - cacheErr = s.cache.SetManifests(cacheKey, appSourceCopy, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, innerRes, refSourceCommitSHAs) + cacheErr = s.cache.SetManifests(cacheKey, appSourceCopy, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, innerRes, refSourceCommitSHAs, q.InstallationID) if cacheErr != nil { logCtx.Warnf("manifest cache set error %s: %v", appSourceCopy.String(), cacheErr) @@ -869,7 +869,7 @@ func (s *Service) runManifestGenAsync(ctx context.Context, repoRoot, commitSHA, } manifestGenResult.Revision = commitSHA manifestGenResult.VerifyResult = opContext.verificationResult - err = s.cache.SetManifests(cacheKey, appSourceCopy, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, &manifestGenCacheEntry, refSourceCommitSHAs) + err = s.cache.SetManifests(cacheKey, appSourceCopy, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, &manifestGenCacheEntry, refSourceCommitSHAs, q.InstallationID) if err != nil { log.Warnf("manifest cache set error %s/%s: %v", appSourceCopy.String(), cacheKey, err) } @@ -886,7 +886,7 @@ func (s *Service) getManifestCacheEntry(cacheKey string, q *apiclient.ManifestRe cache.LogDebugManifestCacheKeyFields("getting manifests cache", "GenerateManifest API call", cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, refSourceCommitSHAs) res := cache.CachedManifestResponse{} - err := s.cache.GetManifests(cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, &res, refSourceCommitSHAs) + err := s.cache.GetManifests(cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, &res, refSourceCommitSHAs, q.InstallationID) if err == nil { // The cache contains an existing value @@ -903,7 +903,7 @@ func (s *Service) getManifestCacheEntry(cacheKey string, q *apiclient.ManifestRe cache.LogDebugManifestCacheKeyFields("deleting manifests cache", "manifest hash did not match or cached response is empty", cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, refSourceCommitSHAs) // We can now try again, so reset the cache state and run the operation below - err = s.cache.DeleteManifests(cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, refSourceCommitSHAs) + err = s.cache.DeleteManifests(cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, refSourceCommitSHAs, q.InstallationID) if err != nil { log.Warnf("manifest cache set error %s/%s: %v", q.ApplicationSource.String(), cacheKey, err) } @@ -918,7 +918,7 @@ func (s *Service) getManifestCacheEntry(cacheKey string, q *apiclient.ManifestRe cache.LogDebugManifestCacheKeyFields("deleting manifests cache", "reset after paused generation count", cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, refSourceCommitSHAs) // We can now try again, so reset the error cache state and run the operation below - err = s.cache.DeleteManifests(cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, refSourceCommitSHAs) + err = s.cache.DeleteManifests(cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, refSourceCommitSHAs, q.InstallationID) if err != nil { log.Warnf("manifest cache set error %s/%s: %v", q.ApplicationSource.String(), cacheKey, err) } @@ -938,7 +938,7 @@ func (s *Service) getManifestCacheEntry(cacheKey string, q *apiclient.ManifestRe // Increment the number of returned cached responses and push that new value to the cache // (if we have not already done so previously in this function) res.NumberOfCachedResponsesReturned++ - err = s.cache.SetManifests(cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, &res, refSourceCommitSHAs) + err = s.cache.SetManifests(cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, &res, refSourceCommitSHAs, q.InstallationID) if err != nil { log.Warnf("manifest cache set error %s/%s: %v", q.ApplicationSource.String(), cacheKey, err) } @@ -1189,6 +1189,7 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie } passCredentials = appHelm.PassCredentials templateOpts.SkipCrds = appHelm.SkipCrds + templateOpts.SkipTests = appHelm.SkipTests } if templateOpts.Name == "" { templateOpts.Name = q.AppName @@ -1500,7 +1501,7 @@ func GenerateManifests(ctx context.Context, appPath, repoRoot, revision string, for _, target := range targets { if q.AppLabelKey != "" && q.AppName != "" && !kube.IsCRD(target) { - err = resourceTracking.SetAppInstance(target, q.AppLabelKey, q.AppName, q.Namespace, v1alpha1.TrackingMethod(q.TrackingMethod)) + err = resourceTracking.SetAppInstance(target, q.AppLabelKey, q.AppName, q.Namespace, v1alpha1.TrackingMethod(q.TrackingMethod), q.InstallationID) if err != nil { return nil, fmt.Errorf("failed to set app instance tracking info on manifest: %w", err) } @@ -2881,7 +2882,7 @@ func (s *Service) updateCachedRevision(logCtx *log.Entry, oldRev string, newRev } } - err := s.cache.SetNewRevisionManifests(newRev, oldRev, request.ApplicationSource, request.RefSources, request, request.Namespace, request.TrackingMethod, request.AppLabelKey, request.AppName, repoRefs) + err := s.cache.SetNewRevisionManifests(newRev, oldRev, request.ApplicationSource, request.RefSources, request, request.Namespace, request.TrackingMethod, request.AppLabelKey, request.AppName, repoRefs, request.InstallationID) if err != nil { if errors.Is(err, cache.ErrCacheMiss) { logCtx.Debugf("manifest cache miss during comparison for application %s in repo %s from revision %s", request.AppName, request.GetRepo().Repo, oldRev) diff --git a/reposerver/repository/repository.proto b/reposerver/repository/repository.proto index 631ab2787171a9..2f45007d0e8842 100644 --- a/reposerver/repository/repository.proto +++ b/reposerver/repository/repository.proto @@ -39,7 +39,9 @@ message ManifestRequest { // This is used to surface "source not permitted" errors for Helm repositories string projectName = 25; // argocd.argoproj.io/manifest-generate-paths annotation value of the Application to allow optimize which resources propagated to cmpserver - string AnnotationManifestGeneratePaths = 26; + string annotationManifestGeneratePaths = 26; + // Holds instance installation id + string installationID = 27; } message ManifestRequestWithFiles { @@ -283,6 +285,7 @@ message UpdateRevisionForPathsRequest { repeated string paths = 13; bool noRevisionCache = 14; + string installationID = 15; } message UpdateRevisionForPathsResponse { diff --git a/reposerver/repository/repository_test.go b/reposerver/repository/repository_test.go index 0c11553e5d7f4d..dd6f528d1d21aa 100644 --- a/reposerver/repository/repository_test.go +++ b/reposerver/repository/repository_test.go @@ -280,7 +280,7 @@ func Test_GenerateManifests_NoOutOfBoundsAccess(t *testing.T) { res, err := GenerateManifests(context.Background(), repoDir, "", "", &q, false, &git.NoopCredsStore{}, resource.MustParse("0"), nil) require.Error(t, err) assert.NotContains(t, err.Error(), mustNotContain) - assert.Contains(t, err.Error(), "illegal filepath") + require.ErrorContains(t, err, "illegal filepath") assert.Nil(t, res) }) } @@ -313,7 +313,7 @@ func TestGenerateManifests_K8SAPIResetCache(t *testing.T) { cachedFakeResponse := &apiclient.ManifestResponse{Manifests: []string{"Fake"}, Revision: mock.Anything} - err := service.cache.SetManifests(mock.Anything, &src, q.RefSources, &q, "", "", "", "", &cache.CachedManifestResponse{ManifestResponse: cachedFakeResponse}, nil) + err := service.cache.SetManifests(mock.Anything, &src, q.RefSources, &q, "", "", "", "", &cache.CachedManifestResponse{ManifestResponse: cachedFakeResponse}, nil, "") require.NoError(t, err) res, err := service.GenerateManifest(context.Background(), &q) @@ -338,7 +338,7 @@ func TestGenerateManifests_EmptyCache(t *testing.T) { ProjectSourceRepos: []string{"*"}, } - err := service.cache.SetManifests(mock.Anything, &src, q.RefSources, &q, "", "", "", "", &cache.CachedManifestResponse{ManifestResponse: nil}, nil) + err := service.cache.SetManifests(mock.Anything, &src, q.RefSources, &q, "", "", "", "", &cache.CachedManifestResponse{ManifestResponse: nil}, nil, "") require.NoError(t, err) res, err := service.GenerateManifest(context.Background(), &q) @@ -684,8 +684,7 @@ func TestInvalidMetadata(t *testing.T) { src := argoappv1.ApplicationSource{Path: "./testdata/invalid-metadata", Directory: &argoappv1.ApplicationSourceDirectory{Recurse: true}} q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src, AppLabelKey: "test", AppName: "invalid-metadata", TrackingMethod: "annotation+label"} _, err := service.GenerateManifest(context.Background(), &q) - require.Error(t, err) - assert.Contains(t, err.Error(), "contains non-string value in the map under key \"invalid\"") + assert.ErrorContains(t, err, "contains non-string value in the map under key \"invalid\"") } func TestNilMetadataAccessors(t *testing.T) { @@ -763,8 +762,7 @@ func TestGenerateJsonnetLibOutside(t *testing.T) { ProjectSourceRepos: []string{"*"}, } _, err := service.GenerateManifest(context.Background(), &q) - require.Error(t, err) - require.Contains(t, err.Error(), "file '../../../testdata/jsonnet/vendor' resolved to outside repository root") + require.ErrorContains(t, err, "file '../../../testdata/jsonnet/vendor' resolved to outside repository root") } func TestManifestGenErrorCacheByNumRequests(t *testing.T) { @@ -774,7 +772,7 @@ func TestManifestGenErrorCacheByNumRequests(t *testing.T) { assert.NotNil(t, manifestRequest) cachedManifestResponse := &cache.CachedManifestResponse{} - err := service.cache.GetManifests(mock.Anything, manifestRequest.ApplicationSource, manifestRequest.RefSources, manifestRequest, manifestRequest.Namespace, "", manifestRequest.AppLabelKey, manifestRequest.AppName, cachedManifestResponse, nil) + err := service.cache.GetManifests(mock.Anything, manifestRequest.ApplicationSource, manifestRequest.RefSources, manifestRequest, manifestRequest.Namespace, "", manifestRequest.AppLabelKey, manifestRequest.AppName, cachedManifestResponse, nil, "") require.NoError(t, err) return cachedManifestResponse } @@ -1141,8 +1139,7 @@ func TestHelmWithMissingValueFiles(t *testing.T) { // Should fail since we're passing a non-existent values file, and error should indicate that _, err := service.GenerateManifest(context.Background(), req) - require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("%s: no such file or directory", missingValuesFile)) + require.ErrorContains(t, err, fmt.Sprintf("%s: no such file or directory", missingValuesFile)) // Should template without error even if defining a non-existent values file req.ApplicationSource.Helm.IgnoreMissingValueFiles = true @@ -1330,8 +1327,7 @@ func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) { ProjectName: "something", ProjectSourceRepos: []string{"*"}, }) - require.Error(t, err) - assert.Contains(t, err.Error(), "outside repository root") + assert.ErrorContains(t, err, "outside repository root") }) t.Run("Values file with relative path pointing inside repo root", func(t *testing.T) { @@ -1385,8 +1381,7 @@ func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) { ProjectName: "something", ProjectSourceRepos: []string{"*"}, }) - require.Error(t, err) - assert.Contains(t, err.Error(), "outside repository root") + assert.ErrorContains(t, err, "outside repository root") }) t.Run("Remote values file from forbidden protocol", func(t *testing.T) { @@ -1404,8 +1399,7 @@ func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) { ProjectName: "something", ProjectSourceRepos: []string{"*"}, }) - require.Error(t, err) - assert.Contains(t, err.Error(), "is not allowed") + assert.ErrorContains(t, err, "is not allowed") }) t.Run("Remote values file from custom allowed protocol", func(t *testing.T) { @@ -1423,8 +1417,7 @@ func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) { ProjectName: "something", ProjectSourceRepos: []string{"*"}, }) - require.Error(t, err) - assert.Contains(t, err.Error(), "s3://my-bucket/my-chart-values.yaml: no such file or directory") + assert.ErrorContains(t, err, "s3://my-bucket/my-chart-values.yaml: no such file or directory") }) } @@ -2114,7 +2107,7 @@ func TestGenerateManifestsWithAppParameterFile(t *testing.T) { // Try to pull from the cache with a `source` that does not include any overrides. Overrides should not be // part of the cache key, because you can't get the overrides without a repo operation. And avoiding repo // operations is the point of the cache. - err = service.cache.GetManifests(mock.Anything, source, argoappv1.RefTargetRevisionMapping{}, &argoappv1.ClusterInfo{}, "", "", "", "test", res, nil) + err = service.cache.GetManifests(mock.Anything, source, argoappv1.RefTargetRevisionMapping{}, &argoappv1.ClusterInfo{}, "", "", "", "test", res, nil, "") require.NoError(t, err) }) }) @@ -2857,8 +2850,7 @@ func TestTestRepoOCI(t *testing.T) { EnableOCI: true, }, }) - require.Error(t, err) - assert.Contains(t, err.Error(), "OCI Helm repository URL should include hostname and port only") + assert.ErrorContains(t, err, "OCI Helm repository URL should include hostname and port only") } func Test_getHelmDependencyRepos(t *testing.T) { diff --git a/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/action_test.yaml b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/action_test.yaml new file mode 100644 index 00000000000000..13a1e7cdffc9ff --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/action_test.yaml @@ -0,0 +1,7 @@ +actionTests: +- action: pause + inputPath: testdata/rollout.yaml + expectedOutputPath: testdata/rollout-paused.yaml +- action: unpause + inputPath: testdata/rollout-paused.yaml + expectedOutputPath: testdata/rollout-running.yaml \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/discovery.lua b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/discovery.lua new file mode 100644 index 00000000000000..2961869dbdcc08 --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/discovery.lua @@ -0,0 +1,14 @@ +local actions = {} +actions["pause"] = {["disabled"] = true} +actions["unpause"] = {["disabled"] = true} + +local paused = false +if obj.spec.monoVertex.spec.lifecycle ~= nil and obj.spec.monoVertex.spec.lifecycle.desiredPhase ~= nil and obj.spec.monoVertex.spec.lifecycle.desiredPhase == "Paused" then + paused = true +end +if paused then + actions["unpause"]["disabled"] = false +else + actions["pause"]["disabled"] = false +end +return actions \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/pause/action.lua b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/pause/action.lua new file mode 100644 index 00000000000000..6e86a8dfd29e6b --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/pause/action.lua @@ -0,0 +1,5 @@ +if obj.spec.monoVertex.spec.lifecycle == nil then + obj.spec.monoVertex.spec.lifecycle = {} +end +obj.spec.monoVertex.spec.lifecycle.desiredPhase = "Paused" +return obj \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/testdata/rollout-paused.yaml b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/testdata/rollout-paused.yaml new file mode 100644 index 00000000000000..2035d668963ccd --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/testdata/rollout-paused.yaml @@ -0,0 +1,49 @@ +apiVersion: numaplane.numaproj.io/v1alpha1 +kind: MonoVertexRollout +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: > + {"apiVersion":"numaplane.numaproj.io/v1alpha1","kind":"MonoVertexRollout","metadata":{"annotations":{},"labels":{"argocd.argoproj.io/instance":"demo-app"},"name":"my-monovertex","namespace":"example-namespace"},"spec":{"monoVertex":{"spec":{"sink":{"udsink":{"container":{"image":"quay.io/numaio/numaflow-java/simple-sink:stable"}}},"source":{"transformer":{"container":{"image":"quay.io/numaio/numaflow-rs/source-transformer-now:stable"}},"udsource":{"container":{"image":"quay.io/numaio/numaflow-java/source-simple-source:stable"}}}}}}} + creationTimestamp: '2024-08-21T20:44:18Z' + finalizers: + - numaplane.numaproj.io/numaplane-controller + generation: 1 + labels: + argocd.argoproj.io/instance: demo-app + name: my-monovertex + namespace: example-namespace + resourceVersion: '947414' + uid: a63f377e-1500-437e-9267-579f4a790518 +spec: + monoVertex: + spec: + lifecycle: + desiredPhase: Paused + sink: + udsink: + container: + image: 'quay.io/numaio/numaflow-java/simple-sink:stable' + source: + transformer: + container: + image: 'quay.io/numaio/numaflow-rs/source-transformer-now:stable' + udsource: + container: + image: 'quay.io/numaio/numaflow-java/source-simple-source:stable' +status: + conditions: + - lastTransitionTime: '2024-08-21T20:44:18Z' + message: Successful + observedGeneration: 1 + reason: Successful + status: 'True' + type: ChildResourceDeployed + - lastTransitionTime: '2024-08-22T21:10:23Z' + message: Successful + observedGeneration: 1 + reason: Successful + status: 'True' + type: ChildResourcesHealthy + message: Deployed + observedGeneration: 1 + phase: Deployed \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/testdata/rollout-running.yaml b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/testdata/rollout-running.yaml new file mode 100644 index 00000000000000..e1f47e521846ea --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/testdata/rollout-running.yaml @@ -0,0 +1,49 @@ +apiVersion: numaplane.numaproj.io/v1alpha1 +kind: MonoVertexRollout +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: > + {"apiVersion":"numaplane.numaproj.io/v1alpha1","kind":"MonoVertexRollout","metadata":{"annotations":{},"labels":{"argocd.argoproj.io/instance":"demo-app"},"name":"my-monovertex","namespace":"example-namespace"},"spec":{"monoVertex":{"spec":{"sink":{"udsink":{"container":{"image":"quay.io/numaio/numaflow-java/simple-sink:stable"}}},"source":{"transformer":{"container":{"image":"quay.io/numaio/numaflow-rs/source-transformer-now:stable"}},"udsource":{"container":{"image":"quay.io/numaio/numaflow-java/source-simple-source:stable"}}}}}}} + creationTimestamp: '2024-08-21T20:44:18Z' + finalizers: + - numaplane.numaproj.io/numaplane-controller + generation: 1 + labels: + argocd.argoproj.io/instance: demo-app + name: my-monovertex + namespace: example-namespace + resourceVersion: '947414' + uid: a63f377e-1500-437e-9267-579f4a790518 +spec: + monoVertex: + spec: + lifecycle: + desiredPhase: Running + sink: + udsink: + container: + image: 'quay.io/numaio/numaflow-java/simple-sink:stable' + source: + transformer: + container: + image: 'quay.io/numaio/numaflow-rs/source-transformer-now:stable' + udsource: + container: + image: 'quay.io/numaio/numaflow-java/source-simple-source:stable' +status: + conditions: + - lastTransitionTime: '2024-08-21T20:44:18Z' + message: Successful + observedGeneration: 1 + reason: Successful + status: 'True' + type: ChildResourceDeployed + - lastTransitionTime: '2024-08-22T21:10:23Z' + message: Successful + observedGeneration: 1 + reason: Successful + status: 'True' + type: ChildResourcesHealthy + message: Deployed + observedGeneration: 1 + phase: Deployed \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/testdata/rollout.yaml b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/testdata/rollout.yaml new file mode 100644 index 00000000000000..ee9d76c826dc40 --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/testdata/rollout.yaml @@ -0,0 +1,47 @@ +apiVersion: numaplane.numaproj.io/v1alpha1 +kind: MonoVertexRollout +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: > + {"apiVersion":"numaplane.numaproj.io/v1alpha1","kind":"MonoVertexRollout","metadata":{"annotations":{},"labels":{"argocd.argoproj.io/instance":"demo-app"},"name":"my-monovertex","namespace":"example-namespace"},"spec":{"monoVertex":{"spec":{"sink":{"udsink":{"container":{"image":"quay.io/numaio/numaflow-java/simple-sink:stable"}}},"source":{"transformer":{"container":{"image":"quay.io/numaio/numaflow-rs/source-transformer-now:stable"}},"udsource":{"container":{"image":"quay.io/numaio/numaflow-java/source-simple-source:stable"}}}}}}} + creationTimestamp: '2024-08-21T20:44:18Z' + finalizers: + - numaplane.numaproj.io/numaplane-controller + generation: 1 + labels: + argocd.argoproj.io/instance: demo-app + name: my-monovertex + namespace: example-namespace + resourceVersion: '947414' + uid: a63f377e-1500-437e-9267-579f4a790518 +spec: + monoVertex: + spec: + sink: + udsink: + container: + image: 'quay.io/numaio/numaflow-java/simple-sink:stable' + source: + transformer: + container: + image: 'quay.io/numaio/numaflow-rs/source-transformer-now:stable' + udsource: + container: + image: 'quay.io/numaio/numaflow-java/source-simple-source:stable' +status: + conditions: + - lastTransitionTime: '2024-08-21T20:44:18Z' + message: Successful + observedGeneration: 1 + reason: Successful + status: 'True' + type: ChildResourceDeployed + - lastTransitionTime: '2024-08-22T21:10:23Z' + message: Successful + observedGeneration: 1 + reason: Successful + status: 'True' + type: ChildResourcesHealthy + message: Deployed + observedGeneration: 1 + phase: Deployed \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/unpause/action.lua b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/unpause/action.lua new file mode 100644 index 00000000000000..c5aa23b6905860 --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/MonoVertexRollout/actions/unpause/action.lua @@ -0,0 +1,2 @@ +obj.spec.monoVertex.spec.lifecycle.desiredPhase = "Running" +return obj \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/action_test.yaml b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/action_test.yaml new file mode 100644 index 00000000000000..13a1e7cdffc9ff --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/action_test.yaml @@ -0,0 +1,7 @@ +actionTests: +- action: pause + inputPath: testdata/rollout.yaml + expectedOutputPath: testdata/rollout-paused.yaml +- action: unpause + inputPath: testdata/rollout-paused.yaml + expectedOutputPath: testdata/rollout-running.yaml \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/discovery.lua b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/discovery.lua new file mode 100644 index 00000000000000..7b692ccef05fcb --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/discovery.lua @@ -0,0 +1,14 @@ +local actions = {} +actions["pause"] = {["disabled"] = true} +actions["unpause"] = {["disabled"] = true} + +local paused = false +if obj.spec.pipeline.spec.lifecycle ~= nil and obj.spec.pipeline.spec.lifecycle.desiredPhase ~= nil and obj.spec.pipeline.spec.lifecycle.desiredPhase == "Paused" then + paused = true +end +if paused then + actions["unpause"]["disabled"] = false +else + actions["pause"]["disabled"] = false +end +return actions \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/pause/action.lua b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/pause/action.lua new file mode 100644 index 00000000000000..d3d378a853527e --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/pause/action.lua @@ -0,0 +1,5 @@ +if obj.spec.pipeline.spec.lifecycle == nil then + obj.spec.pipeline.spec.lifecycle = {} +end +obj.spec.pipeline.spec.lifecycle.desiredPhase = "Paused" +return obj \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/testdata/rollout-paused.yaml b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/testdata/rollout-paused.yaml new file mode 100644 index 00000000000000..ac89952fbca549 --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/testdata/rollout-paused.yaml @@ -0,0 +1,63 @@ +apiVersion: numaplane.numaproj.io/v1alpha1 +kind: PipelineRollout +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"numaplane.numaproj.io/v1alpha1","kind":"PipelineRollout","metadata":{"annotations":{},"name":"my-pipeline","namespace":"example-namespace"},"spec":{"pipeline":{"spec":{"edges":[{"from":"in","to":"cat"},{"from":"cat","to":"out"}],"interStepBufferServiceName":"my-isbsvc","vertices":[{"name":"in","source":{"generator":{"duration":"1s","rpu":5}}},{"name":"cat","udf":{"builtin":{"name":"cat"}}},{"name":"out","sink":{"log":{}}}]}}}} + creationTimestamp: "2024-09-26T20:54:55Z" + finalizers: + - numaplane.numaproj.io/numaplane-controller + generation: 1 + name: my-pipeline + namespace: example-namespace + resourceVersion: "14008" + uid: ab9286a1-f453-433e-846e-48900ab2068a +spec: + pipeline: + spec: + lifecycle: + desiredPhase: Paused + edges: + - from: in + to: cat + - from: cat + to: out + interStepBufferServiceName: my-isbsvc + vertices: + - name: in + source: + generator: + duration: 1s + rpu: 5 + - name: cat + udf: + builtin: + name: cat + - name: out + sink: + log: {} +status: + conditions: + - lastTransitionTime: "2024-09-26T20:54:55Z" + message: Successful + observedGeneration: 1 + reason: Successful + status: "True" + type: ChildResourceDeployed + - lastTransitionTime: "2024-09-26T20:55:07Z" + message: Pipeline Phase=Failed + observedGeneration: 1 + reason: PipelineFailed + status: "False" + type: ChildResourcesHealthy + - lastTransitionTime: "2024-09-26T20:54:55Z" + message: Pipeline unpaused + observedGeneration: 1 + reason: Unpaused + status: "False" + type: PipelinePausingOrPaused + message: Deployed + nameCount: 0 + observedGeneration: 1 + pauseStatus: {} + phase: Deployed \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/testdata/rollout-running.yaml b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/testdata/rollout-running.yaml new file mode 100644 index 00000000000000..81504a82da4df3 --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/testdata/rollout-running.yaml @@ -0,0 +1,63 @@ +apiVersion: numaplane.numaproj.io/v1alpha1 +kind: PipelineRollout +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"numaplane.numaproj.io/v1alpha1","kind":"PipelineRollout","metadata":{"annotations":{},"name":"my-pipeline","namespace":"example-namespace"},"spec":{"pipeline":{"spec":{"edges":[{"from":"in","to":"cat"},{"from":"cat","to":"out"}],"interStepBufferServiceName":"my-isbsvc","vertices":[{"name":"in","source":{"generator":{"duration":"1s","rpu":5}}},{"name":"cat","udf":{"builtin":{"name":"cat"}}},{"name":"out","sink":{"log":{}}}]}}}} + creationTimestamp: "2024-09-26T20:54:55Z" + finalizers: + - numaplane.numaproj.io/numaplane-controller + generation: 1 + name: my-pipeline + namespace: example-namespace + resourceVersion: "14008" + uid: ab9286a1-f453-433e-846e-48900ab2068a +spec: + pipeline: + spec: + lifecycle: + desiredPhase: Running + edges: + - from: in + to: cat + - from: cat + to: out + interStepBufferServiceName: my-isbsvc + vertices: + - name: in + source: + generator: + duration: 1s + rpu: 5 + - name: cat + udf: + builtin: + name: cat + - name: out + sink: + log: {} +status: + conditions: + - lastTransitionTime: "2024-09-26T20:54:55Z" + message: Successful + observedGeneration: 1 + reason: Successful + status: "True" + type: ChildResourceDeployed + - lastTransitionTime: "2024-09-26T20:55:07Z" + message: Pipeline Phase=Failed + observedGeneration: 1 + reason: PipelineFailed + status: "False" + type: ChildResourcesHealthy + - lastTransitionTime: "2024-09-26T20:54:55Z" + message: Pipeline unpaused + observedGeneration: 1 + reason: Unpaused + status: "False" + type: PipelinePausingOrPaused + message: Deployed + nameCount: 0 + observedGeneration: 1 + pauseStatus: {} + phase: Deployed \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/testdata/rollout.yaml b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/testdata/rollout.yaml new file mode 100644 index 00000000000000..7011e9fd73bad6 --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/testdata/rollout.yaml @@ -0,0 +1,61 @@ +apiVersion: numaplane.numaproj.io/v1alpha1 +kind: PipelineRollout +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"numaplane.numaproj.io/v1alpha1","kind":"PipelineRollout","metadata":{"annotations":{},"name":"my-pipeline","namespace":"example-namespace"},"spec":{"pipeline":{"spec":{"edges":[{"from":"in","to":"cat"},{"from":"cat","to":"out"}],"interStepBufferServiceName":"my-isbsvc","vertices":[{"name":"in","source":{"generator":{"duration":"1s","rpu":5}}},{"name":"cat","udf":{"builtin":{"name":"cat"}}},{"name":"out","sink":{"log":{}}}]}}}} + creationTimestamp: "2024-09-26T20:54:55Z" + finalizers: + - numaplane.numaproj.io/numaplane-controller + generation: 1 + name: my-pipeline + namespace: example-namespace + resourceVersion: "14008" + uid: ab9286a1-f453-433e-846e-48900ab2068a +spec: + pipeline: + spec: + edges: + - from: in + to: cat + - from: cat + to: out + interStepBufferServiceName: my-isbsvc + vertices: + - name: in + source: + generator: + duration: 1s + rpu: 5 + - name: cat + udf: + builtin: + name: cat + - name: out + sink: + log: {} +status: + conditions: + - lastTransitionTime: "2024-09-26T20:54:55Z" + message: Successful + observedGeneration: 1 + reason: Successful + status: "True" + type: ChildResourceDeployed + - lastTransitionTime: "2024-09-26T20:55:07Z" + message: Pipeline Phase=Failed + observedGeneration: 1 + reason: PipelineFailed + status: "False" + type: ChildResourcesHealthy + - lastTransitionTime: "2024-09-26T20:54:55Z" + message: Pipeline unpaused + observedGeneration: 1 + reason: Unpaused + status: "False" + type: PipelinePausingOrPaused + message: Deployed + nameCount: 0 + observedGeneration: 1 + pauseStatus: {} + phase: Deployed \ No newline at end of file diff --git a/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/unpause/action.lua b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/unpause/action.lua new file mode 100644 index 00000000000000..5f0802bc9b743b --- /dev/null +++ b/resource_customizations/numaplane.numaproj.io/PipelineRollout/actions/unpause/action.lua @@ -0,0 +1,2 @@ +obj.spec.pipeline.spec.lifecycle.desiredPhase = "Running" +return obj \ No newline at end of file diff --git a/resource_customizations/policy.open-cluster-management.io/Policy/health.lua b/resource_customizations/policy.open-cluster-management.io/Policy/health.lua index 9b43c04c4b5e75..b969c367e121e3 100644 --- a/resource_customizations/policy.open-cluster-management.io/Policy/health.lua +++ b/resource_customizations/policy.open-cluster-management.io/Policy/health.lua @@ -14,10 +14,10 @@ if obj.status.status ~= nil then -- "root" policy for i, entry in ipairs(obj.status.status) do if entry.compliant ~= "Compliant" then - noncompliants[i] = entry.clustername + table.insert(noncompliants, entry.clustername) end end - if table.getn(noncompliants) == 0 then + if #noncompliants == 0 then hs.message = "All clusters are compliant" else hs.message = "NonCompliant clusters: " .. table.concat(noncompliants, ", ") @@ -26,10 +26,10 @@ elseif obj.status.details ~= nil then -- "replicated" policy for i, entry in ipairs(obj.status.details) do if entry.compliant ~= "Compliant" then - noncompliants[i] = entry.templateMeta.name + table.insert(noncompliants, entry.templateMeta.name) end end - if table.getn(noncompliants) == 0 then + if #noncompliants == 0 then hs.message = "All templates are compliant" else hs.message = "NonCompliant templates: " .. table.concat(noncompliants, ", ") diff --git a/resource_customizations/policy.open-cluster-management.io/Policy/testdata/degraded_replicated_compliant_before_noncompliant.yaml b/resource_customizations/policy.open-cluster-management.io/Policy/testdata/degraded_replicated_compliant_before_noncompliant.yaml new file mode 100644 index 00000000000000..d0c3c9aebe558f --- /dev/null +++ b/resource_customizations/policy.open-cluster-management.io/Policy/testdata/degraded_replicated_compliant_before_noncompliant.yaml @@ -0,0 +1,88 @@ +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: open-cluster-management-global-set.argo-example + namespace: local-cluster + labels: + policy.open-cluster-management.io/cluster-name: local-cluster + policy.open-cluster-management.io/cluster-namespace: local-cluster + policy.open-cluster-management.io/root-policy: open-cluster-management-global-set.argo-example +spec: + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: example-namespace + spec: + object-templates: + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: Namespace + metadata: + name: example + remediationAction: inform + severity: low + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: example-pod + spec: + namespaceSelector: + exclude: + - kube-* + include: + - default + object-templates: + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: Pod + metadata: + name: foobar + spec: + containers: + - image: 'registry.redhat.io/rhel9/httpd-24:latest' + name: httpd + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + runAsNonRoot: true + remediationAction: enforce + severity: low +status: + compliant: NonCompliant + details: + - compliant: Compliant + history: + - eventName: open-cluster-management-global-set.argo-example.17e7034c879045a3 + lastTimestamp: '2024-07-30T14:16:49Z' + message: 'Compliant; notification - pods [foobar] was created successfully in namespace default' + templateMeta: + creationTimestamp: null + name: example-foo + - compliant: NonCompliant + history: + - eventName: open-cluster-management-global-set.argo-example.17e701cc5101e3a4 + lastTimestamp: '2024-07-30T13:49:19Z' + message: 'NonCompliant; violation - namespaces [example] not found' + templateMeta: + creationTimestamp: null + name: example-namespace + - compliant: Compliant + history: + - eventName: open-cluster-management-global-set.argo-example.17e7034c879045a3 + lastTimestamp: '2024-07-30T14:16:49Z' + message: 'Compliant; notification - pods [foobar] was created successfully in namespace default' + - eventName: open-cluster-management-global-set.argo-example.17e7020b47782ddc + lastTimestamp: '2024-07-30T13:53:49Z' + message: 'NonCompliant; violation - pods [foobar] not found in namespace default' + templateMeta: + creationTimestamp: null + name: example-pod diff --git a/resource_customizations/serving.kserve.io/InferenceService/health.lua b/resource_customizations/serving.kserve.io/InferenceService/health.lua index 85da1161f315fc..94959de841d597 100644 --- a/resource_customizations/serving.kserve.io/InferenceService/health.lua +++ b/resource_customizations/serving.kserve.io/InferenceService/health.lua @@ -1,50 +1,59 @@ --- isInferenceServiceInRawDeploymentMode determines if the inference service deployed in RawDeployment mode --- KServe v12 and above supports Rawdeployment for Inference graphs. For Inference services, KServe has supported RawDeployment model since [v0.7.0](https://github.com/kserve/kserve/releases/tag/v0.7.0). -function isInferenceServiceInRawDeploymentMode(obj) - if obj.metadata.annotations == nil then - return false - end - local deploymentMode = obj.metadata.annotations["serving.kserve.io/deploymentMode"] - return deploymentMode ~= nil and deploymentMode == "RawDeployment" -end - local health_status = {} + health_status.status = "Progressing" -health_status.message = "Waiting for status update." -if obj.status ~= nil and obj.status.conditions ~= nil then - local status_true = 0 +health_status.message = "Waiting for InferenceService to report status..." + +if obj.status ~= nil then + + local progressing = false + local degraded = false local status_false = 0 local status_unknown = 0 - health_status.message = "" - for i, condition in pairs(obj.status.conditions) do - if condition.status == "True" and (condition.type == "IngressReady" or condition.type == "PredictorConfigurationReady" or condition.type == "PredictorReady" or condition.type == "PredictorRouteReady" or condition.type == "Ready") then - status_true = status_true + 1 - elseif condition.status == "False" or condition.status == "Unknown" then - msg = condition.type .. " is " .. condition.status - if condition.reason ~= nil and condition.reason ~= "" then - msg = msg .. ", since " .. condition.reason .. "." - end - if condition.message ~= nil and condition.message ~= "" then - msg = msg .. " " .. condition.message - end - health_status.message = health_status.message .. msg .. "\n" - if condition.status == "False" then - status_false = status_false + 1 + local msg = "" + + if obj.status.modelStatus ~= nil then + if obj.status.modelStatus.transitionStatus ~= "UpToDate" then + if obj.status.modelStatus.transitionStatus == "InProgress" then + progressing = true else - status_unknown = status_unknown + 1 + degraded = true end + msg = msg .. "0: transitionStatus | " .. obj.status.modelStatus.transitionStatus end end - if ((isInferenceServiceInRawDeploymentMode(obj) and status_true == 3) or status_true == 5) and status_false == 0 and status_unknown == 0 then - health_status.message = "Inference Service is healthy." - health_status.status = "Healthy" - return health_status - elseif status_false > 0 then - health_status.status = "Degraded" - return health_status - else - health_status.status = "Progressing" - return health_status + + if obj.status.conditions ~= nil then + for i, condition in pairs(obj.status.conditions) do + + if condition.status == "Unknown" then + status_unknown = status_unknown + 1 + elseif condition.status == "False" then + status_false = status_false + 1 + end + + if condition.status ~= "True" then + msg = msg .. " | " .. i .. ": " .. condition.type .. " | " .. condition.status + if condition.reason ~= nil and condition.reason ~= "" then + msg = msg .. " | " .. condition.reason + end + if condition.message ~= nil and condition.message ~= "" then + msg = msg .. " | " .. condition.message + end + end + + end + + if progressing == false and degraded == false and status_unknown == 0 and status_false == 0 then + health_status.status = "Healthy" + msg = "InferenceService is healthy." + elseif degraded == false and status_unknown >= 0 then + health_status.status = "Progressing" + else + health_status.status = "Degraded" + end + + health_status.message = msg end end -return health_status \ No newline at end of file + +return health_status diff --git a/resource_customizations/serving.kserve.io/InferenceService/health_test.yaml b/resource_customizations/serving.kserve.io/InferenceService/health_test.yaml index 1dc5576f93f3af..670b194f79d415 100644 --- a/resource_customizations/serving.kserve.io/InferenceService/health_test.yaml +++ b/resource_customizations/serving.kserve.io/InferenceService/health_test.yaml @@ -1,17 +1,41 @@ tests: - healthStatus: status: Progressing - message: "PredictorConfigurationReady is Unknown\nPredictorReady is Unknown, since RevisionMissing. Configuration \"hello-world-predictor-default\" is waiting for a Revision to become ready.\nPredictorRouteReady is Unknown, since RevisionMissing. Configuration \"hello-world-predictor-default\" is waiting for a Revision to become ready.\nReady is Unknown, since RevisionMissing. Configuration \"hello-world-predictor-default\" is waiting for a Revision to become ready.\n" + message: ' | 1: PredictorConfigurationReady | Unknown | 2: PredictorReady | Unknown | RevisionMissing | Configuration "hello-world-predictor-default" is waiting for a Revision to become ready. | 3: PredictorRouteReady | Unknown | RevisionMissing | Configuration "hello-world-predictor-default" is waiting for a Revision to become ready. | 4: Ready | Unknown | RevisionMissing | Configuration "hello-world-predictor-default" is waiting for a Revision to become ready.' inputPath: testdata/progressing.yaml +- healthStatus: + status: Progressing + message: '0: transitionStatus | InProgress | 1: LatestDeploymentReady | Unknown | PredictorConfigurationReady not ready | 2: PredictorConfigurationReady | Unknown | 3: PredictorReady | Unknown | RevisionMissing | Configuration "helloworld-predictor" is waiting for a Revision to become ready. | 4: PredictorRouteReady | Unknown | RevisionMissing | Configuration "helloworld-predictor" is waiting for a Revision to become ready. | 5: Ready | Unknown | RevisionMissing | Configuration "helloworld-predictor" is waiting for a Revision to become ready. | 6: RoutesReady | Unknown | PredictorRouteReady not ready' + inputPath: testdata/progressing_ocp.yaml +- healthStatus: + status: Progressing + message: "0: transitionStatus | InProgress | 1: PredictorReady | False | 2: Ready | False" + inputPath: testdata/progressing_modelmesh.yaml - healthStatus: status: Degraded - message: "IngressReady is False, since Predictor ingress not created.\nPredictorConfigurationReady is False, since RevisionFailed. Revision \"helloworld-00002\" failed with message: Container failed with: container exited with no error.\nPredictorReady is False, since RevisionFailed. Revision \"helloworld-00002\" failed with message: Container failed with: container exited with no error.\nReady is False, since Predictor ingress not created.\n" + message: '0: transitionStatus | BlockedByFailedLoad | 1: IngressReady | False | Predictor ingress not created | 2: PredictorConfigurationReady | False | RevisionFailed | Revision "helloworld-00002" failed with message: Container failed with: container exited with no error. | 3: PredictorReady | False | RevisionFailed | Revision "helloworld-00002" failed with message: Container failed with: container exited with no error. | 5: Ready | False | Predictor ingress not created' inputPath: testdata/degraded.yaml +- healthStatus: + status: Degraded + message: '0: transitionStatus | BlockedByFailedLoad | 1: LatestDeploymentReady | False | PredictorConfigurationReady not ready | 2: PredictorConfigurationReady | False | RevisionFailed | Revision "helloworld-predictor-00002" failed with message: . | 3: PredictorReady | False | RevisionMissing | Configuration "helloworld-predictor" does not have any ready Revision. | 4: PredictorRouteReady | False | RevisionMissing | Configuration "helloworld-predictor" does not have any ready Revision. | 5: Ready | False | RevisionMissing | Configuration "helloworld-predictor" does not have any ready Revision. | 6: RoutesReady | False | PredictorRouteReady not ready' + inputPath: testdata/degraded_ocp.yaml +- healthStatus: + status: Degraded + message: "0: transitionStatus | BlockedByFailedLoad" + inputPath: testdata/degraded_modelmesh.yaml - healthStatus: status: Healthy - message: Inference Service is healthy. + message: InferenceService is healthy. inputPath: testdata/healthy.yaml - healthStatus: status: Healthy - message: Inference Service is healthy. + message: InferenceService is healthy. + inputPath: testdata/healthy_ocp.yaml +- healthStatus: + status: Healthy + message: InferenceService is healthy. + inputPath: testdata/healthy_modelmesh.yaml +- healthStatus: + status: Healthy + message: InferenceService is healthy. inputPath: testdata/healthy_raw.yaml diff --git a/resource_customizations/serving.kserve.io/InferenceService/testdata/degraded.yaml b/resource_customizations/serving.kserve.io/InferenceService/testdata/degraded.yaml index 0cd337860c670d..291e4392f59f85 100644 --- a/resource_customizations/serving.kserve.io/InferenceService/testdata/degraded.yaml +++ b/resource_customizations/serving.kserve.io/InferenceService/testdata/degraded.yaml @@ -28,3 +28,5 @@ status: reason: Predictor ingress not created status: "False" type: Ready + modelStatus: + transitionStatus: BlockedByFailedLoad \ No newline at end of file diff --git a/resource_customizations/serving.kserve.io/InferenceService/testdata/degraded_modelmesh.yaml b/resource_customizations/serving.kserve.io/InferenceService/testdata/degraded_modelmesh.yaml new file mode 100644 index 00000000000000..54ac46fa593562 --- /dev/null +++ b/resource_customizations/serving.kserve.io/InferenceService/testdata/degraded_modelmesh.yaml @@ -0,0 +1,16 @@ +apiVersion: serving.kserve.io/v1beta1 +kind: InferenceService +metadata: + name: helloworld + namespace: default +spec: {} +status: + conditions: + - lastTransitionTime: '2024-05-30T22:43:16Z' + status: 'True' + type: PredictorReady + - lastTransitionTime: '2024-05-30T22:43:16Z' + status: 'True' + type: Ready + modelStatus: + transitionStatus: BlockedByFailedLoad diff --git a/resource_customizations/serving.kserve.io/InferenceService/testdata/degraded_ocp.yaml b/resource_customizations/serving.kserve.io/InferenceService/testdata/degraded_ocp.yaml new file mode 100644 index 00000000000000..d85c755dea51be --- /dev/null +++ b/resource_customizations/serving.kserve.io/InferenceService/testdata/degraded_ocp.yaml @@ -0,0 +1,42 @@ +apiVersion: serving.kserve.io/v1beta1 +kind: InferenceService +metadata: + name: helloworld + namespace: default +spec: {} +status: + conditions: + - lastTransitionTime: '2024-05-30T23:03:45Z' + reason: PredictorConfigurationReady not ready + severity: Info + status: 'False' + type: LatestDeploymentReady + - lastTransitionTime: '2024-05-30T23:03:45Z' + message: 'Revision "helloworld-predictor-00002" failed with message: .' + reason: RevisionFailed + severity: Info + status: 'False' + type: PredictorConfigurationReady + - lastTransitionTime: '2024-05-30T23:03:45Z' + message: Configuration "helloworld-predictor" does not have any ready Revision. + reason: RevisionMissing + status: 'False' + type: PredictorReady + - lastTransitionTime: '2024-05-30T23:03:45Z' + message: Configuration "helloworld-predictor" does not have any ready Revision. + reason: RevisionMissing + severity: Info + status: 'False' + type: PredictorRouteReady + - lastTransitionTime: '2024-05-30T23:03:45Z' + message: Configuration "helloworld-predictor" does not have any ready Revision. + reason: RevisionMissing + status: 'False' + type: Ready + - lastTransitionTime: '2024-05-30T23:03:45Z' + reason: PredictorRouteReady not ready + severity: Info + status: 'False' + type: RoutesReady + modelStatus: + transitionStatus: BlockedByFailedLoad diff --git a/resource_customizations/serving.kserve.io/InferenceService/testdata/healthy_modelmesh.yaml b/resource_customizations/serving.kserve.io/InferenceService/testdata/healthy_modelmesh.yaml new file mode 100644 index 00000000000000..290171afe2cdd8 --- /dev/null +++ b/resource_customizations/serving.kserve.io/InferenceService/testdata/healthy_modelmesh.yaml @@ -0,0 +1,16 @@ +apiVersion: serving.kserve.io/v1beta1 +kind: InferenceService +metadata: + name: helloworld + namespace: default +spec: {} +status: + conditions: + - lastTransitionTime: '2024-05-30T22:43:16Z' + status: 'True' + type: PredictorReady + - lastTransitionTime: '2024-05-30T22:43:16Z' + status: 'True' + type: Ready + modelStatus: + transitionStatus: UpToDate diff --git a/resource_customizations/serving.kserve.io/InferenceService/testdata/healthy_ocp.yaml b/resource_customizations/serving.kserve.io/InferenceService/testdata/healthy_ocp.yaml new file mode 100644 index 00000000000000..9d65c2b379e055 --- /dev/null +++ b/resource_customizations/serving.kserve.io/InferenceService/testdata/healthy_ocp.yaml @@ -0,0 +1,35 @@ +apiVersion: serving.kserve.io/v1beta1 +kind: InferenceService +metadata: + name: helloworld + namespace: default +spec: {} +status: + conditions: + - lastTransitionTime: '2024-05-30T22:14:31Z' + status: 'True' + type: IngressReady + - lastTransitionTime: '2024-05-30T22:14:30Z' + severity: Info + status: 'True' + type: LatestDeploymentReady + - lastTransitionTime: '2024-05-30T22:14:30Z' + severity: Info + status: 'True' + type: PredictorConfigurationReady + - lastTransitionTime: '2024-05-30T22:14:31Z' + status: 'True' + type: PredictorReady + - lastTransitionTime: '2024-05-30T22:14:31Z' + severity: Info + status: 'True' + type: PredictorRouteReady + - lastTransitionTime: '2024-05-30T22:14:31Z' + status: 'True' + type: Ready + - lastTransitionTime: '2024-05-30T22:14:31Z' + severity: Info + status: 'True' + type: RoutesReady + modelStatus: + transitionStatus: UpToDate diff --git a/resource_customizations/serving.kserve.io/InferenceService/testdata/progressing_modelmesh.yaml b/resource_customizations/serving.kserve.io/InferenceService/testdata/progressing_modelmesh.yaml new file mode 100644 index 00000000000000..1edb429504e33f --- /dev/null +++ b/resource_customizations/serving.kserve.io/InferenceService/testdata/progressing_modelmesh.yaml @@ -0,0 +1,16 @@ +apiVersion: serving.kserve.io/v1beta1 +kind: InferenceService +metadata: + name: helloworld + namespace: default +spec: {} +status: + conditions: + - lastTransitionTime: '2024-05-30T22:43:16Z' + status: 'False' + type: PredictorReady + - lastTransitionTime: '2024-05-30T22:43:16Z' + status: 'False' + type: Ready + modelStatus: + transitionStatus: InProgress diff --git a/resource_customizations/serving.kserve.io/InferenceService/testdata/progressing_ocp.yaml b/resource_customizations/serving.kserve.io/InferenceService/testdata/progressing_ocp.yaml new file mode 100644 index 00000000000000..aa476e80cebb4b --- /dev/null +++ b/resource_customizations/serving.kserve.io/InferenceService/testdata/progressing_ocp.yaml @@ -0,0 +1,40 @@ +apiVersion: serving.kserve.io/v1beta1 +kind: InferenceService +metadata: + name: helloworld + namespace: default +spec: {} +status: + conditions: + - lastTransitionTime: '2024-05-30T22:29:46Z' + reason: PredictorConfigurationReady not ready + severity: Info + status: Unknown + type: LatestDeploymentReady + - lastTransitionTime: '2024-05-30T22:29:46Z' + severity: Info + status: Unknown + type: PredictorConfigurationReady + - lastTransitionTime: '2024-05-30T22:29:46Z' + message: Configuration "helloworld-predictor" is waiting for a Revision to become ready. + reason: RevisionMissing + status: Unknown + type: PredictorReady + - lastTransitionTime: '2024-05-30T22:29:46Z' + message: Configuration "helloworld-predictor" is waiting for a Revision to become ready. + reason: RevisionMissing + severity: Info + status: Unknown + type: PredictorRouteReady + - lastTransitionTime: '2024-05-30T22:29:46Z' + message: Configuration "helloworld-predictor" is waiting for a Revision to become ready. + reason: RevisionMissing + status: Unknown + type: Ready + - lastTransitionTime: '2024-05-30T22:29:46Z' + reason: PredictorRouteReady not ready + severity: Info + status: Unknown + type: RoutesReady + modelStatus: + transitionStatus: InProgress diff --git a/server/account/account_test.go b/server/account/account_test.go index 03290ad3692c4c..2e7f9ab669e9df 100644 --- a/server/account/account_test.go +++ b/server/account/account_test.go @@ -163,16 +163,14 @@ func TestUpdatePassword_DoesNotHavePermissions(t *testing.T) { }) ctx := adminContext(context.Background()) _, err := accountServer.UpdatePassword(ctx, &account.UpdatePasswordRequest{CurrentPassword: "oldpassword", NewPassword: "newpassword", Name: "anotherUser"}) - require.Error(t, err) - assert.Contains(t, err.Error(), "permission denied") + assert.ErrorContains(t, err, "permission denied") }) t.Run("SSOAccountWithTheSameName", func(t *testing.T) { accountServer, _ := newTestAccountServerExt(context.Background(), enforcer) ctx := ssoAdminContext(context.Background(), time.Now()) _, err := accountServer.UpdatePassword(ctx, &account.UpdatePasswordRequest{CurrentPassword: "oldpassword", NewPassword: "newpassword", Name: "admin"}) - require.Error(t, err) - assert.Contains(t, err.Error(), "permission denied") + assert.ErrorContains(t, err, "permission denied") }) } @@ -182,8 +180,7 @@ func TestUpdatePassword_ProjectToken(t *testing.T) { }) ctx := projTokenContext(context.Background()) _, err := accountServer.UpdatePassword(ctx, &account.UpdatePasswordRequest{CurrentPassword: "oldpassword", NewPassword: "newpassword"}) - require.Error(t, err) - assert.Contains(t, err.Error(), "password can only be changed for local users") + assert.ErrorContains(t, err, "password can only be changed for local users") } func TestUpdatePassword_OldSSOToken(t *testing.T) { @@ -291,9 +288,8 @@ func TestCreateToken_UserSpecifiedID(t *testing.T) { require.NoError(t, err) _, err = accountServer.CreateToken(ctx, &account.CreateTokenRequest{Name: "account1", Id: "test"}) - require.Error(t, err) - assert.Contains(t, err.Error(), "failed to update account with new token:") - assert.Contains(t, err.Error(), "account already has token with id 'test'") + require.ErrorContains(t, err, "failed to update account with new token:") + assert.ErrorContains(t, err, "account already has token with id 'test'") } func TestDeleteToken_SuccessfullyRemoved(t *testing.T) { diff --git a/server/application/application.go b/server/application/application.go index 08a8ab19d008bd..3d67ea2601f809 100644 --- a/server/application/application.go +++ b/server/application/application.go @@ -510,6 +510,10 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan if err != nil { return fmt.Errorf("error getting kustomize settings options: %w", err) } + installationID, err := s.settingsMgr.GetInstallationID() + if err != nil { + return fmt.Errorf("error getting installation ID: %w", err) + } manifestInfo, err := client.GenerateManifest(ctx, &apiclient.ManifestRequest{ Repo: repo, @@ -531,6 +535,7 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan HasMultipleSources: a.Spec.HasMultipleSources(), RefSources: refSources, AnnotationManifestGeneratePaths: a.GetAnnotation(v1alpha1.AnnotationKeyManifestGeneratePaths), + InstallationID: installationID, }) if err != nil { return fmt.Errorf("error generating manifests: %w", err) @@ -1284,7 +1289,11 @@ func (s *Server) getApplicationClusterConfig(ctx context.Context, a *appv1.Appli if err != nil { return nil, fmt.Errorf("error getting cluster: %w", err) } - config := clst.RESTConfig() + config, err := clst.RESTConfig() + if err != nil { + return nil, fmt.Errorf("error getting cluster REST config: %w", err) + } + return config, err } diff --git a/server/application/application_test.go b/server/application/application_test.go index c182829fa19bdb..00631baa1b296d 100644 --- a/server/application/application_test.go +++ b/server/application/application_test.go @@ -2007,7 +2007,7 @@ func TestServer_GetApplicationSyncWindowsState(t *testing.T) { appServer := newTestAppServer(t, testApp) active, err := appServer.GetApplicationSyncWindows(context.Background(), &application.ApplicationSyncWindowsQuery{Name: &testApp.Name}) - assert.Contains(t, err.Error(), "not exist") + require.ErrorContains(t, err, "not exist") assert.Nil(t, active) }) } @@ -2718,7 +2718,6 @@ func TestAppNamespaceRestrictions(t *testing.T) { Name: ptr.To("test-app"), AppNamespace: ptr.To("argocd-1"), }) - require.Error(t, err) require.ErrorContains(t, err, "permission denied") require.Nil(t, app) }) diff --git a/server/application/terminal.go b/server/application/terminal.go index e6ddc6d832df3f..46884ce2ffa5ed 100644 --- a/server/application/terminal.go +++ b/server/application/terminal.go @@ -70,7 +70,11 @@ func (s *terminalHandler) getApplicationClusterRawConfig(ctx context.Context, a if err != nil { return nil, err } - return clst.RawRestConfig(), nil + rawConfig, err := clst.RawRestConfig() + if err != nil { + return nil, err + } + return rawConfig, nil } type GetSettingsFunc func() (*settings.ArgoCDSettings, error) diff --git a/server/cluster/cluster.go b/server/cluster/cluster.go index c92600448ed75f..8ffa787437f62a 100644 --- a/server/cluster/cluster.go +++ b/server/cluster/cluster.go @@ -146,7 +146,12 @@ func (s *Server) Create(ctx context.Context, q *cluster.ClusterCreateRequest) (* return nil, err } c := q.Cluster - serverVersion, err := s.kubectl.GetServerVersion(c.RESTConfig()) + clusterRESTConfig, err := c.RESTConfig() + if err != nil { + return nil, err + } + + serverVersion, err := s.kubectl.GetServerVersion(clusterRESTConfig) if err != nil { return nil, err } @@ -313,9 +318,13 @@ func (s *Server) Update(ctx context.Context, q *cluster.ClusterUpdateRequest) (* } q.Cluster = c } + clusterRESTConfig, err := q.Cluster.RESTConfig() + if err != nil { + return nil, err + } // Test the token we just created before persisting it - serverVersion, err := s.kubectl.GetServerVersion(q.Cluster.RESTConfig()) + serverVersion, err := s.kubectl.GetServerVersion(clusterRESTConfig) if err != nil { return nil, err } @@ -406,7 +415,10 @@ func (s *Server) RotateAuth(ctx context.Context, q *cluster.ClusterQuery) (*clus for _, server := range servers { logCtx := log.WithField("cluster", server) logCtx.Info("Rotating auth") - restCfg := clust.RESTConfig() + restCfg, err := clust.RESTConfig() + if err != nil { + return nil, err + } if restCfg.BearerToken == "" { return nil, status.Errorf(codes.InvalidArgument, "Cluster '%s' does not use bearer token authentication", server) } @@ -428,8 +440,12 @@ func (s *Server) RotateAuth(ctx context.Context, q *cluster.ClusterQuery) (*clus clust.Config.CertData = nil clust.Config.BearerToken = string(newSecret.Data["token"]) + clusterRESTConfig, err := clust.RESTConfig() + if err != nil { + return nil, err + } // Test the token we just created before persisting it - serverVersion, err := s.kubectl.GetServerVersion(clust.RESTConfig()) + serverVersion, err := s.kubectl.GetServerVersion(clusterRESTConfig) if err != nil { return nil, err } diff --git a/server/cluster/cluster_test.go b/server/cluster/cluster_test.go index 567de3a661901f..e54ecbfb6e92ab 100644 --- a/server/cluster/cluster_test.go +++ b/server/cluster/cluster_test.go @@ -39,6 +39,74 @@ import ( "github.com/argoproj/argo-cd/v2/util/settings" ) +const ( + rootCACert = `-----BEGIN CERTIFICATE----- +MIIC4DCCAcqgAwIBAgIBATALBgkqhkiG9w0BAQswIzEhMB8GA1UEAwwYMTAuMTMu +MTI5LjEwNkAxNDIxMzU5MDU4MB4XDTE1MDExNTIxNTczN1oXDTE2MDExNTIxNTcz +OFowIzEhMB8GA1UEAwwYMTAuMTMuMTI5LjEwNkAxNDIxMzU5MDU4MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunDRXGwsiYWGFDlWH6kjGun+PshDGeZX +xtx9lUnL8pIRWH3wX6f13PO9sktaOWW0T0mlo6k2bMlSLlSZgG9H6og0W6gLS3vq +s4VavZ6DbXIwemZG2vbRwsvR+t4G6Nbwelm6F8RFnA1Fwt428pavmNQ/wgYzo+T1 +1eS+HiN4ACnSoDSx3QRWcgBkB1g6VReofVjx63i0J+w8Q/41L9GUuLqquFxu6ZnH +60vTB55lHgFiDLjA1FkEz2dGvGh/wtnFlRvjaPC54JH2K1mPYAUXTreoeJtLJKX0 +ycoiyB24+zGCniUmgIsmQWRPaOPircexCp1BOeze82BT1LCZNTVaxQIDAQABoyMw +ITAOBgNVHQ8BAf8EBAMCAKQwDwYDVR0TAQH/BAUwAwEB/zALBgkqhkiG9w0BAQsD +ggEBADMxsUuAFlsYDpF4fRCzXXwrhbtj4oQwcHpbu+rnOPHCZupiafzZpDu+rw4x +YGPnCb594bRTQn4pAu3Ac18NbLD5pV3uioAkv8oPkgr8aUhXqiv7KdDiaWm6sbAL +EHiXVBBAFvQws10HMqMoKtO8f1XDNAUkWduakR/U6yMgvOPwS7xl0eUTqyRB6zGb +K55q2dejiFWaFqB/y78txzvz6UlOZKE44g2JAVoJVM6kGaxh33q8/FmrL4kuN3ut +W+MmJCVDvd4eEqPwbp7146ZWTqpIJ8lvA6wuChtqV8lhAPka2hD/LMqY8iXNmfXD +uml0obOEy+ON91k+SWTJ3ggmF/U= +-----END CERTIFICATE-----` + + certData = `-----BEGIN CERTIFICATE----- +MIIC6jCCAdSgAwIBAgIBCzALBgkqhkiG9w0BAQswIzEhMB8GA1UEAwwYMTAuMTMu +MTI5LjEwNkAxNDIxMzU5MDU4MB4XDTE1MDExNTIyMDEzMVoXDTE2MDExNTIyMDEz +MlowGzEZMBcGA1UEAxMQb3BlbnNoaWZ0LWNsaWVudDCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKtdhz0+uCLXw5cSYns9rU/XifFSpb/x24WDdrm72S/v +b9BPYsAStiP148buylr1SOuNi8sTAZmlVDDIpIVwMLff+o2rKYDicn9fjbrTxTOj +lI4pHJBH+JU3AJ0tbajupioh70jwFS0oYpwtneg2zcnE2Z4l6mhrj2okrc5Q1/X2 +I2HChtIU4JYTisObtin10QKJX01CLfYXJLa8upWzKZ4/GOcHG+eAV3jXWoXidtjb +1Usw70amoTZ6mIVCkiu1QwCoa8+ycojGfZhvqMsAp1536ZcCul+Na+AbCv4zKS7F +kQQaImVrXdUiFansIoofGlw/JNuoKK6ssVpS5Ic3pgcCAwEAAaM1MDMwDgYDVR0P +AQH/BAQDAgCgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJ +KoZIhvcNAQELA4IBAQCKLREH7bXtXtZ+8vI6cjD7W3QikiArGqbl36bAhhWsJLp/ +p/ndKz39iFNaiZ3GlwIURWOOKx3y3GA0x9m8FR+Llthf0EQ8sUjnwaknWs0Y6DQ3 +jjPFZOpV3KPCFrdMJ3++E3MgwFC/Ih/N2ebFX9EcV9Vcc6oVWMdwT0fsrhu683rq +6GSR/3iVX1G/pmOiuaR0fNUaCyCfYrnI4zHBDgSfnlm3vIvN2lrsR/DQBakNL8DJ +HBgKxMGeUPoneBv+c8DMXIL0EhaFXRlBv9QW45/GiAIOuyFJ0i6hCtGZpJjq4OpQ +BRjCI+izPzFTjsxD4aORE+WOkyWFCGPWKfNejfw0 +-----END CERTIFICATE-----` + + keyData = `-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAq12HPT64ItfDlxJiez2tT9eJ8VKlv/HbhYN2ubvZL+9v0E9i +wBK2I/Xjxu7KWvVI642LyxMBmaVUMMikhXAwt9/6jaspgOJyf1+NutPFM6OUjikc +kEf4lTcAnS1tqO6mKiHvSPAVLShinC2d6DbNycTZniXqaGuPaiStzlDX9fYjYcKG +0hTglhOKw5u2KfXRAolfTUIt9hcktry6lbMpnj8Y5wcb54BXeNdaheJ22NvVSzDv +RqahNnqYhUKSK7VDAKhrz7JyiMZ9mG+oywCnXnfplwK6X41r4BsK/jMpLsWRBBoi +ZWtd1SIVqewiih8aXD8k26gorqyxWlLkhzemBwIDAQABAoIBAD2XYRs3JrGHQUpU +FkdbVKZkvrSY0vAZOqBTLuH0zUv4UATb8487anGkWBjRDLQCgxH+jucPTrztekQK +aW94clo0S3aNtV4YhbSYIHWs1a0It0UdK6ID7CmdWkAj6s0T8W8lQT7C46mWYVLm +5mFnCTHi6aB42jZrqmEpC7sivWwuU0xqj3Ml8kkxQCGmyc9JjmCB4OrFFC8NNt6M +ObvQkUI6Z3nO4phTbpxkE1/9dT0MmPIF7GhHVzJMS+EyyRYUDllZ0wvVSOM3qZT0 +JMUaBerkNwm9foKJ1+dv2nMKZZbJajv7suUDCfU44mVeaEO+4kmTKSGCGjjTBGkr +7L1ySDECgYEA5ElIMhpdBzIivCuBIH8LlUeuzd93pqssO1G2Xg0jHtfM4tz7fyeI +cr90dc8gpli24dkSxzLeg3Tn3wIj/Bu64m2TpZPZEIlukYvgdgArmRIPQVxerYey +OkrfTNkxU1HXsYjLCdGcGXs5lmb+K/kuTcFxaMOs7jZi7La+jEONwf8CgYEAwCs/ +rUOOA0klDsWWisbivOiNPII79c9McZCNBqncCBfMUoiGe8uWDEO4TFHN60vFuVk9 +8PkwpCfvaBUX+ajvbafIfHxsnfk1M04WLGCeqQ/ym5Q4sQoQOcC1b1y9qc/xEWfg +nIUuia0ukYRpl7qQa3tNg+BNFyjypW8zukUAC/kCgYB1/Kojuxx5q5/oQVPrx73k +2bevD+B3c+DYh9MJqSCNwFtUpYIWpggPxoQan4LwdsmO0PKzocb/ilyNFj4i/vII +NToqSc/WjDFpaDIKyuu9oWfhECye45NqLWhb/6VOuu4QA/Nsj7luMhIBehnEAHW+ +GkzTKM8oD1PxpEG3nPKXYQKBgQC6AuMPRt3XBl1NkCrpSBy/uObFlFaP2Enpf39S +3OZ0Gv0XQrnSaL1kP8TMcz68rMrGX8DaWYsgytstR4W+jyy7WvZwsUu+GjTJ5aMG +77uEcEBpIi9CBzivfn7hPccE8ZgqPf+n4i6q66yxBJflW5xhvafJqDtW2LcPNbW/ +bvzdmQKBgExALRUXpq+5dbmkdXBHtvXdRDZ6rVmrnjy4nI5bPw+1GqQqk6uAR6B/ +F6NmLCQOO4PDG/cuatNHIr2FrwTmGdEL6ObLUGWn9Oer9gJhHVqqsY5I4sEPo4XX +stR0Yiw0buV6DL/moUO0HIM9Bjh96HJp+LxiIS6UCdIhMPp5HoQa +-----END RSA PRIVATE KEY-----` +) + func newServerInMemoryCache() *servercache.Cache { return servercache.NewCache( appstatecache.NewCache( @@ -238,6 +306,42 @@ func TestGetCluster_NameWithUrlEncodingButShouldNotBeUnescaped(t *testing.T) { assert.Equal(t, "test%2fing", cluster.Name) } +func TestGetCluster_CannotSetCADataAndInsecureTrue(t *testing.T) { + testNamespace := "default" + cluster := &v1alpha1.Cluster{ + Name: "my-cluster-name", + Server: "https://my-cluster-server", + Namespaces: []string{testNamespace}, + Config: v1alpha1.ClusterConfig{ + TLSClientConfig: v1alpha1.TLSClientConfig{ + Insecure: true, + CAData: []byte(rootCACert), + CertData: []byte(certData), + KeyData: []byte(keyData), + }, + }, + } + clientset := getClientset(nil, testNamespace) + db := db.NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset) + server := NewServer(db, newNoopEnforcer(), newServerInMemoryCache(), &kubetest.MockKubectlCmd{}) + + t.Run("Create Fails When CAData is Set and Insecure is True", func(t *testing.T) { + _, err := server.Create(context.Background(), &clusterapi.ClusterCreateRequest{ + Cluster: cluster, + }) + + assert.EqualError(t, err, `Unable to apply K8s REST config defaults: specifying a root certificates file with the insecure flag is not allowed`) + }) + + cluster.Config.TLSClientConfig.CAData = nil + t.Run("Create Succeeds When CAData is nil and Insecure is True", func(t *testing.T) { + _, err := server.Create(context.Background(), &clusterapi.ClusterCreateRequest{ + Cluster: cluster, + }) + require.NoError(t, err) + }) +} + func TestUpdateCluster_NoFieldsPaths(t *testing.T) { db := &dbmocks.ArgoDB{} var updated *v1alpha1.Cluster @@ -471,8 +575,7 @@ func TestRotateAuth(t *testing.T) { Name: "my-cluster-name", }) - require.Error(t, err) - assert.Contains(t, err.Error(), "Get \"https://my-cluster-name/") + assert.ErrorContains(t, err, "Get \"https://my-cluster-name/") }) t.Run("RotateAuth by Server - Error from no such host", func(t *testing.T) { @@ -480,8 +583,7 @@ func TestRotateAuth(t *testing.T) { Server: "https://my-cluster-name", }) - require.Error(t, err) - assert.Contains(t, err.Error(), "Get \"https://my-cluster-name/") + assert.ErrorContains(t, err, "Get \"https://my-cluster-name/") }) } diff --git a/server/project/project_test.go b/server/project/project_test.go index 41b8af9241e39c..cd5a8de5fee531 100644 --- a/server/project/project_test.go +++ b/server/project/project_test.go @@ -583,7 +583,7 @@ p, role:admin, projects, update, *, allow`) projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList) request := &project.ProjectUpdateRequest{Project: projWithRole} _, err := projectServer.Update(context.Background(), request) - assert.Contains(t, err.Error(), "object must be of form 'test/*', 'test[/]/' or 'test/'") + assert.ErrorContains(t, err, "object must be of form 'test/*', 'test[/]/' or 'test/'") }) t.Run("TestValidateProjectIncorrectProjectInRoleFailure", func(t *testing.T) { @@ -602,7 +602,7 @@ p, role:admin, projects, update, *, allow`) projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList) request := &project.ProjectUpdateRequest{Project: projWithRole} _, err := projectServer.Update(context.Background(), request) - assert.Contains(t, err.Error(), "policy subject must be: 'proj:test:testRole'") + assert.ErrorContains(t, err, "policy subject must be: 'proj:test:testRole'") }) t.Run("TestValidateProjectIncorrectTokenInRoleFailure", func(t *testing.T) { @@ -621,7 +621,7 @@ p, role:admin, projects, update, *, allow`) projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList) request := &project.ProjectUpdateRequest{Project: projWithRole} _, err := projectServer.Update(context.Background(), request) - assert.Contains(t, err.Error(), "policy subject must be: 'proj:test:testRole'") + assert.ErrorContains(t, err, "policy subject must be: 'proj:test:testRole'") }) t.Run("TestValidateProjectInvalidEffectFailure", func(t *testing.T) { @@ -639,7 +639,7 @@ p, role:admin, projects, update, *, allow`) projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList) request := &project.ProjectUpdateRequest{Project: projWithRole} _, err := projectServer.Update(context.Background(), request) - assert.Contains(t, err.Error(), "effect must be: 'allow' or 'deny'") + assert.ErrorContains(t, err, "effect must be: 'allow' or 'deny'") }) t.Run("TestNormalizeProjectRolePolicies", func(t *testing.T) { @@ -685,7 +685,7 @@ p, role:admin, projects, update, *, allow`) argoDB := db.NewDB("default", settingsMgr, kubeclientset) projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithSyncWindows), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB, testEnableEventList) res, err := projectServer.GetSyncWindowsState(ctx, &project.SyncWindowsQuery{Name: "incorrect"}) - assert.Contains(t, err.Error(), "not found") + require.ErrorContains(t, err, "not found") assert.Nil(t, res) }) diff --git a/server/settings/settings.proto b/server/settings/settings.proto index 4b2396d5a22a4d..943aea41cd2076 100644 --- a/server/settings/settings.proto +++ b/server/settings/settings.proto @@ -43,6 +43,7 @@ message Settings { string controllerNamespace = 23; bool appsInAnyNamespaceEnabled = 24; bool impersonationEnabled = 25; + string installationID = 26; } message GoogleAnalyticsConfig { diff --git a/test/container/Dockerfile b/test/container/Dockerfile index ad22c720bbb81f..5a372b46baf2de 100644 --- a/test/container/Dockerfile +++ b/test/container/Dockerfile @@ -6,13 +6,13 @@ FROM docker.io/library/redis:7.4.0@sha256:eadf354977d428e347d93046bb1a5569d701e8 RUN ln -s /usr/lib/$(uname -m)-linux-gnu /usr/lib/linux-gnu # Please make sure to also check the contained yarn version and update the references below when upgrading this image's version -FROM docker.io/library/node:22.9.0@sha256:cbe2d5f94110cea9817dd8c5809d05df49b4bd1aac5203f3594d88665ad37988 as node +FROM docker.io/library/node:22.9.0@sha256:69e667a79aa41ec0db50bc452a60e705ca16f35285eaf037ebe627a65a5cdf52 as node -FROM docker.io/library/golang:1.23@sha256:2fe82a3f3e006b4f2a316c6a21f62b66e1330ae211d039bb8d1128e12ed57bf1 as golang +FROM docker.io/library/golang:1.23.1@sha256:4f063a24d429510e512cc730c3330292ff49f3ade3ae79bda8f84a24fa25ecb0 as golang FROM docker.io/library/registry:2.8@sha256:ac0192b549007e22998eb74e8d8488dcfe70f1489520c3b144a6047ac5efbe90 as registry -FROM docker.io/bitnami/kubectl:1.31@sha256:da4a9868e20d941636087cb8624a4bb441f5249d69e8f3d27e53c7d4d280a5f3 as kubectl +FROM docker.io/bitnami/kubectl:1.31@sha256:b509ab6000477ebe788df3509a8c4177e91238ee3003f33edea0931be3794340 as kubectl FROM docker.io/library/ubuntu:24.04@sha256:3f85b7caad41a95462cf5b787d8a04604c8262cdcdf9a472b8c52ef83375fe15 diff --git a/test/e2e/app_deletion_test.go b/test/e2e/app_deletion_test.go index 9158dddffa06a0..bb8704a0ca07c7 100644 --- a/test/e2e/app_deletion_test.go +++ b/test/e2e/app_deletion_test.go @@ -58,7 +58,7 @@ func TestDeletingAppByLabel(t *testing.T) { // delete is unsuccessful since no selector match AndCLIOutput( func(output string, err error) { - assert.Contains(t, err.Error(), "no apps match selector foo=baz") + assert.ErrorContains(t, err, "no apps match selector foo=baz") }, ). When(). diff --git a/test/e2e/app_management_ns_test.go b/test/e2e/app_management_ns_test.go index d4717f57d0f7ff..9df081e68376d1 100644 --- a/test/e2e/app_management_ns_test.go +++ b/test/e2e/app_management_ns_test.go @@ -91,8 +91,7 @@ func TestNamespacedGetLogsDenySwitchOn(t *testing.T) { Expect(HealthIs(health.HealthStatusHealthy)). And(func(app *Application) { _, err := RunCliWithRetry(5, "app", "logs", ctx.AppQualifiedName(), "--kind", "Deployment", "--group", "", "--name", "guestbook-ui") - require.Error(t, err) - assert.Contains(t, err.Error(), "permission denied") + assert.ErrorContains(t, err, "permission denied") }) } @@ -667,8 +666,7 @@ func TestNamespacedAppWithSecrets(t *testing.T) { _, err = RunCli("app", "patch-resource", ctx.AppQualifiedName(), "--resource-name", "test-secret", "--kind", "Secret", "--patch", `{"op": "add", "path": "/data", "value": "hello"}'`, "--patch-type", "application/json-patch+json") - require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("failed to patch Secret %s/test-secret", DeploymentNamespace())) + require.ErrorContains(t, err, fmt.Sprintf("failed to patch Secret %s/test-secret", DeploymentNamespace())) assert.NotContains(t, err.Error(), "username") assert.NotContains(t, err.Error(), "password") @@ -973,8 +971,7 @@ func TestNamespacedSyncResourceByLabel(t *testing.T) { Expect(SyncStatusIs(SyncStatusCodeSynced)). And(func(app *Application) { _, err := RunCli("app", "sync", ctx.AppQualifiedName(), "--label", "this-label=does-not-exist") - require.Error(t, err) - assert.Contains(t, err.Error(), "level=fatal") + assert.ErrorContains(t, err, "level=fatal") }) } @@ -1045,8 +1042,7 @@ func TestNamespacedNoLocalSyncWithAutosyncEnabled(t *testing.T) { require.NoError(t, err) _, err = RunCli("app", "sync", app.QualifiedName(), "--local", guestbookPathLocal) - require.Error(t, err) - assert.Contains(t, err.Error(), "Cannot use local sync") + assert.ErrorContains(t, err, "Cannot use local sync") }) } @@ -1093,8 +1089,7 @@ func assertNSResourceActions(t *testing.T, appName string, successful bool) { if successful { require.NoError(t, err) } else { - require.Error(t, err) - assert.Contains(t, err.Error(), message) + assert.ErrorContains(t, err, message) } } diff --git a/test/e2e/app_management_test.go b/test/e2e/app_management_test.go index 67e1b4b03397cd..edc2fb045e6128 100644 --- a/test/e2e/app_management_test.go +++ b/test/e2e/app_management_test.go @@ -99,8 +99,7 @@ func TestGetLogsDenySwitchOn(t *testing.T) { Expect(HealthIs(health.HealthStatusHealthy)). And(func(app *Application) { _, err := RunCliWithRetry(appLogsRetryCount, "app", "logs", app.Name, "--kind", "Deployment", "--group", "", "--name", "guestbook-ui") - require.Error(t, err) - assert.Contains(t, err.Error(), "permission denied") + assert.ErrorContains(t, err, "permission denied") }) } @@ -818,8 +817,7 @@ func TestAppWithSecrets(t *testing.T) { _, err = RunCli("app", "patch-resource", "test-app-with-secrets", "--resource-name", "test-secret", "--kind", "Secret", "--patch", `{"op": "add", "path": "/data", "value": "hello"}'`, "--patch-type", "application/json-patch+json") - require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("failed to patch Secret %s/test-secret", DeploymentNamespace())) + require.ErrorContains(t, err, fmt.Sprintf("failed to patch Secret %s/test-secret", DeploymentNamespace())) assert.NotContains(t, err.Error(), "username") assert.NotContains(t, err.Error(), "password") @@ -1324,8 +1322,7 @@ func TestSyncResourceByLabel(t *testing.T) { Expect(SyncStatusIs(SyncStatusCodeSynced)). And(func(app *Application) { _, err := RunCli("app", "sync", app.Name, "--label", "this-label=does-not-exist") - require.Error(t, err) - assert.Contains(t, err.Error(), "level=fatal") + assert.ErrorContains(t, err, "level=fatal") }) } @@ -1342,8 +1339,7 @@ func TestSyncResourceByProject(t *testing.T) { Expect(SyncStatusIs(SyncStatusCodeSynced)). And(func(app *Application) { _, err := RunCli("app", "sync", app.Name, "--project", "this-project-does-not-exist") - require.Error(t, err) - assert.Contains(t, err.Error(), "level=fatal") + assert.ErrorContains(t, err, "level=fatal") }) } @@ -1450,8 +1446,7 @@ func assertResourceActions(t *testing.T, appName string, successful bool) { if successful { require.NoError(t, err) } else { - require.Error(t, err) - assert.Contains(t, err.Error(), message) + assert.ErrorContains(t, err, message) } } @@ -2246,8 +2241,7 @@ func TestNamespaceAutoCreation(t *testing.T) { And(func(app *Application) { // Make sure the namespace we are about to update to does not exist _, err := Run("", "kubectl", "get", "namespace", updatedNamespace) - require.Error(t, err) - assert.Contains(t, err.Error(), "not found") + assert.ErrorContains(t, err, "not found") }). When(). AppSet("--dest-namespace", updatedNamespace). @@ -2923,3 +2917,49 @@ data: Expect(ResourceHealthWithNamespaceIs("ConfigMap", "yet-another-map", DeploymentNamespace(), health.HealthStatusHealthy)). Expect(ResourceSyncStatusWithNamespaceIs("ConfigMap", "yet-another-map", DeploymentNamespace(), SyncStatusCodeSynced)) } + +func TestInstallationID(t *testing.T) { + ctx := Given(t) + ctx. + SetTrackingMethod(string(argo.TrackingMethodAnnotation)). + And(func() { + _, err := fixture.KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create( + context.Background(), &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-configmap", + Annotations: map[string]string{ + common.AnnotationKeyAppInstance: fmt.Sprintf("%s:/ConfigMap:%s/test-configmap", ctx.AppName(), DeploymentNamespace()), + }, + }, + }, metav1.CreateOptions{}) + require.NoError(t, err) + }). + Path(guestbookPath). + Prune(false). + When().IgnoreErrors().CreateApp().Sync(). + Then().Expect(OperationPhaseIs(OperationSucceeded)).Expect(SyncStatusIs(SyncStatusCodeOutOfSync)). + And(func(app *Application) { + var cm *ResourceStatus + for i := range app.Status.Resources { + if app.Status.Resources[i].Kind == "ConfigMap" && app.Status.Resources[i].Name == "test-configmap" { + cm = &app.Status.Resources[i] + break + } + } + require.NotNil(t, cm) + assert.Equal(t, SyncStatusCodeOutOfSync, cm.Status) + }). + When().SetInstallationID("test").Sync(). + Then(). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + And(func(app *Application) { + require.Len(t, app.Status.Resources, 2) + svc, err := fixture.KubeClientset.CoreV1().Services(DeploymentNamespace()).Get(context.Background(), "guestbook-ui", metav1.GetOptions{}) + require.NoError(t, err) + require.Equal(t, "test", svc.Annotations[common.AnnotationInstallationID]) + + deploy, err := fixture.KubeClientset.AppsV1().Deployments(DeploymentNamespace()).Get(context.Background(), "guestbook-ui", metav1.GetOptions{}) + require.NoError(t, err) + require.Equal(t, "test", deploy.Annotations[common.AnnotationInstallationID]) + }) +} diff --git a/test/e2e/cluster_generator_test.go b/test/e2e/cluster_generator_test.go index aa73e36aea7962..558d5c9c84ef59 100644 --- a/test/e2e/cluster_generator_test.go +++ b/test/e2e/cluster_generator_test.go @@ -494,3 +494,107 @@ func TestSimpleClusterGeneratorDeletingCluster(t *testing.T) { When(). Delete().Then().Expect(ApplicationsDoNotExist([]argov1alpha1.Application{expectedAppCluster1})) } + +func TestClusterGeneratorWithFlatListMode(t *testing.T) { + expectedAppTemplate := argov1alpha1.Application{ + TypeMeta: metav1.TypeMeta{ + Kind: application.ApplicationKind, + APIVersion: "argoproj.io/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "flat-clusters", + Namespace: fixture.TestNamespace(), + Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + }, + Spec: argov1alpha1.ApplicationSpec{ + Project: "default", + Source: &argov1alpha1.ApplicationSource{ + RepoURL: "https://github.com/argoproj/argocd-example-apps.git", + TargetRevision: "HEAD", + Path: "helm-guestbook", + }, + Destination: argov1alpha1.ApplicationDestination{ + Name: "cluster1", + Namespace: fixture.TestNamespace(), + }, + SyncPolicy: &argov1alpha1.SyncPolicy{ + Automated: &argov1alpha1.SyncPolicyAutomated{}, + }, + }, + } + + expectedAppCluster1 := *expectedAppTemplate.DeepCopy() + expectedAppCluster1.Spec.Source.Helm = &argov1alpha1.ApplicationSourceHelm{ + Values: `clusters: + - name: cluster1 +`, + } + + expectedAppCluster2 := *expectedAppTemplate.DeepCopy() + expectedAppCluster2.Spec.Source.Helm = &argov1alpha1.ApplicationSourceHelm{ + Values: `clusters: + - name: cluster1 + - name: cluster2 +`, + } + + Given(t). + // Create a ClusterGenerator-based ApplicationSet + When(). + CreateClusterSecret("my-secret", "cluster1", "https://kubernetes.default.svc"). + Create(v1alpha1.ApplicationSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "simple-cluster-generator", + }, + Spec: v1alpha1.ApplicationSetSpec{ + GoTemplate: true, + Template: v1alpha1.ApplicationSetTemplate{ + ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "flat-clusters"}, + Spec: argov1alpha1.ApplicationSpec{ + Project: "default", + Source: &argov1alpha1.ApplicationSource{ + RepoURL: "https://github.com/argoproj/argocd-example-apps.git", + TargetRevision: "HEAD", + Path: "helm-guestbook", + Helm: &argov1alpha1.ApplicationSourceHelm{ + Values: `clusters: +{{- range .clusters }} + - name: {{ .name }} +{{- end }} +`, + }, + }, + Destination: argov1alpha1.ApplicationDestination{ + Name: "cluster1", + Namespace: fixture.TestNamespace(), + }, + SyncPolicy: &argov1alpha1.SyncPolicy{ + Automated: &argov1alpha1.SyncPolicyAutomated{}, + }, + }, + }, + Generators: []v1alpha1.ApplicationSetGenerator{ + { + Clusters: &v1alpha1.ClusterGenerator{ + Selector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "argocd.argoproj.io/secret-type": "cluster", + }, + }, + FlatList: true, + }, + }, + }, + }, + }).Then().Expect(ApplicationsExist([]argov1alpha1.Application{expectedAppCluster1})). + + // Update the ApplicationSet template namespace, and verify it updates the Applications + When(). + CreateClusterSecret("my-secret2", "cluster2", "https://kubernetes.default.svc"). + Then(). + Expect(ApplicationsExist([]argov1alpha1.Application{expectedAppCluster2})). + + // Delete the ApplicationSet, and verify it deletes the Applications + When(). + Delete().Then().Expect(ApplicationsDoNotExist([]argov1alpha1.Application{expectedAppCluster2})) +} diff --git a/test/e2e/cluster_test.go b/test/e2e/cluster_test.go index d09df7d0cc8129..66c5e8e0787e41 100644 --- a/test/e2e/cluster_test.go +++ b/test/e2e/cluster_test.go @@ -90,7 +90,7 @@ func TestClusterAddPermissionDenied(t *testing.T) { Create(). Then(). AndCLIOutput(func(output string, err error) { - assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied") + assert.ErrorContains(t, err, "PermissionDenied desc = permission denied") }) } @@ -255,7 +255,7 @@ func TestClusterDeleteDenied(t *testing.T) { DeleteByName(). Then(). AndCLIOutput(func(output string, err error) { - assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied") + assert.ErrorContains(t, err, "PermissionDenied desc = permission denied") }) // Attempt to remove cluster creds by server @@ -269,7 +269,7 @@ func TestClusterDeleteDenied(t *testing.T) { DeleteByServer(). Then(). AndCLIOutput(func(output string, err error) { - assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied") + assert.ErrorContains(t, err, "PermissionDenied desc = permission denied") }) } diff --git a/test/e2e/fixture/app/actions.go b/test/e2e/fixture/app/actions.go index 1d013b66289636..71b633deffb7b5 100644 --- a/test/e2e/fixture/app/actions.go +++ b/test/e2e/fixture/app/actions.go @@ -269,6 +269,9 @@ func (a *Actions) prepareCreateAppArgs(args []string) []string { if a.context.helmSkipCrds { args = append(args, "--helm-skip-crds") } + if a.context.helmSkipTests { + args = append(args, "--helm-skip-tests") + } return args } @@ -469,6 +472,11 @@ func (a *Actions) SetTrackingMethod(trackingMethod string) *Actions { return a } +func (a *Actions) SetInstallationID(installationID string) *Actions { + fixture.SetInstallationID(installationID) + return a +} + func (a *Actions) SetTrackingLabel(trackingLabel string) *Actions { fixture.SetTrackingLabel(trackingLabel) return a diff --git a/test/e2e/fixture/app/consequences.go b/test/e2e/fixture/app/consequences.go index 9ee99fec6ca6d6..ff64dee0de4b8c 100644 --- a/test/e2e/fixture/app/consequences.go +++ b/test/e2e/fixture/app/consequences.go @@ -42,6 +42,31 @@ func (c *Consequences) Expect(e Expectation) *Consequences { return c } +// ExpectConsistently will continuously evaluate a condition, and it must be true each time it is evaluated, otherwise the test is failed. The condition will be repeatedly evaluated until 'expirationDuration' is met, waiting 'waitDuration' after each success. +func (c *Consequences) ExpectConsistently(e Expectation, waitDuration time.Duration, expirationDuration time.Duration) *Consequences { + // this invocation makes sure this func is not reported as the cause of the failure - we are a "test helper" + c.context.t.Helper() + + expiration := time.Now().Add(expirationDuration) + for time.Now().Before(expiration) { + state, message := e(c) + switch state { + case succeeded: + log.Infof("expectation succeeded: %s", message) + case failed: + c.context.t.Fatalf("failed expectation: %s", message) + return c + } + + // On condition success: wait, then retry + log.Infof("Expectation '%s' passes, repeating to ensure consistency", message) + time.Sleep(waitDuration) + } + + // If the condition never failed before expiring, it is a pass. + return c +} + func (c *Consequences) And(block func(app *Application)) *Consequences { c.context.t.Helper() block(c.app()) diff --git a/test/e2e/fixture/app/context.go b/test/e2e/fixture/app/context.go index 2225cac54c61d2..ad892796cdbdf7 100644 --- a/test/e2e/fixture/app/context.go +++ b/test/e2e/fixture/app/context.go @@ -43,6 +43,7 @@ type Context struct { replace bool helmPassCredentials bool helmSkipCrds bool + helmSkipTests bool trackingMethod v1alpha1.TrackingMethod sources []v1alpha1.ApplicationSource } @@ -357,11 +358,21 @@ func (c *Context) HelmSkipCrds() *Context { return c } +func (c *Context) HelmSkipTests() *Context { + c.helmSkipTests = true + return c +} + func (c *Context) SetTrackingMethod(trackingMethod string) *Context { fixture.SetTrackingMethod(trackingMethod) return c } +func (c *Context) SetInstallationID(installationID string) *Context { + fixture.SetTrackingMethod(installationID) + return c +} + func (c *Context) GetTrackingMethod() v1alpha1.TrackingMethod { return c.trackingMethod } diff --git a/test/e2e/fixture/fixture.go b/test/e2e/fixture/fixture.go index 24d0e4ce74d71d..e44d9b8ca90fa2 100644 --- a/test/e2e/fixture/fixture.go +++ b/test/e2e/fixture/fixture.go @@ -46,6 +46,9 @@ const ( ArgoCDNamespace = "argocd-e2e" ArgoCDAppNamespace = "argocd-e2e-external" + // notifications controller, metrics server port + defaultNotificationServer = "localhost:9001" + // ensure all repos are in one directory tree, so we can easily clean them up TmpDir = "/tmp/argo-e2e" repoDir = "testdata.git" @@ -403,6 +406,13 @@ func SetResourceOverrides(overrides map[string]v1alpha1.ResourceOverride) { SetResourceOverridesSplitKeys(overrides) } +func SetInstallationID(installationID string) { + updateSettingConfigMap(func(cm *corev1.ConfigMap) error { + cm.Data["installationID"] = installationID + return nil + }) +} + func SetTrackingMethod(trackingMethod string) { updateSettingConfigMap(func(cm *corev1.ConfigMap) error { cm.Data["application.resourceTrackingMethod"] = trackingMethod @@ -1020,6 +1030,10 @@ func GetApiServerAddress() string { return apiServerAddress } +func GetNotificationServerAddress() string { + return defaultNotificationServer +} + func GetToken() string { return token } diff --git a/test/e2e/fixture/http.go b/test/e2e/fixture/http.go index 00c123ab5d893c..68e674f9f8b36c 100644 --- a/test/e2e/fixture/http.go +++ b/test/e2e/fixture/http.go @@ -12,13 +12,17 @@ import ( ) // DoHttpRequest executes a http request against the Argo CD API server -func DoHttpRequest(method string, path string, data ...byte) (*http.Response, error) { +func DoHttpRequest(method string, path string, host string, data ...byte) (*http.Response, error) { reqUrl, err := url.Parse(path) if err != nil { return nil, err } reqUrl.Scheme = "http" - reqUrl.Host = apiServerAddress + if host != "" { + reqUrl.Host = host + } else { + reqUrl.Host = apiServerAddress + } var body io.Reader if data != nil { body = bytes.NewReader(data) @@ -41,7 +45,7 @@ func DoHttpRequest(method string, path string, data ...byte) (*http.Response, er // DoHttpJsonRequest executes a http request against the Argo CD API server and unmarshals the response body as JSON func DoHttpJsonRequest(method string, path string, result interface{}, data ...byte) error { - resp, err := DoHttpRequest(method, path, data...) + resp, err := DoHttpRequest(method, path, "", data...) if err != nil { return err } diff --git a/test/e2e/fixture/notification/actions.go b/test/e2e/fixture/notification/actions.go index 4b3c328f7ed295..622032441ee750 100644 --- a/test/e2e/fixture/notification/actions.go +++ b/test/e2e/fixture/notification/actions.go @@ -12,6 +12,8 @@ import ( // using the Then() type Actions struct { context *Context + + healthy bool } func (a *Actions) SetParamInNotificationConfigMap(key, value string) *Actions { @@ -25,3 +27,12 @@ func (a *Actions) Then() *Consequences { time.Sleep(1 * time.Second) return &Consequences{a.context, a} } + +func (a *Actions) Healthcheck() *Actions { + a.context.t.Helper() + _, err := fixture.DoHttpRequest("GET", + "/metrics", + fixture.GetNotificationServerAddress()) + a.healthy = err == nil + return a +} diff --git a/test/e2e/fixture/notification/consequences.go b/test/e2e/fixture/notification/consequences.go index bfc4b4b0e0988f..46e09a4249327e 100644 --- a/test/e2e/fixture/notification/consequences.go +++ b/test/e2e/fixture/notification/consequences.go @@ -19,6 +19,12 @@ func (c *Consequences) Services(block func(services *notification.ServiceList, e return c } +func (c *Consequences) Healthy(block func(healthy bool)) *Consequences { + c.context.t.Helper() + block(c.actions.healthy) + return c +} + func (c *Consequences) Triggers(block func(services *notification.TriggerList, err error)) *Consequences { c.context.t.Helper() block(c.listTriggers()) diff --git a/test/e2e/multiarch-container/Dockerfile b/test/e2e/multiarch-container/Dockerfile index ad49d66dc585cd..62cd7fef56e04f 100644 --- a/test/e2e/multiarch-container/Dockerfile +++ b/test/e2e/multiarch-container/Dockerfile @@ -1,2 +1,2 @@ -FROM docker.io/library/busybox@sha256:c230832bd3b0be59a6c47ed64294f9ce71e91b327957920b6929a0caa8353140 +FROM docker.io/library/busybox@sha256:768e5c6f5cb6db0794eec98dc7a967f40631746c32232b78a3105fb946f3ab83 CMD exec sh -c "trap : TERM INT; echo 'Hi' && tail -f /dev/null" diff --git a/test/e2e/notification_test.go b/test/e2e/notification_test.go index e4dd855a107e38..11ed412a39dcad 100644 --- a/test/e2e/notification_test.go +++ b/test/e2e/notification_test.go @@ -40,3 +40,13 @@ func TestNotificationsListTriggers(t *testing.T) { assert.Equal(t, []*notification.Trigger{{Name: ptr.To("on-created")}}, triggers.Items) }) } + +func TestNotificationsHealthcheck(t *testing.T) { + ctx := notifFixture.Given(t) + ctx.When(). + Healthcheck(). + Then(). + Healthy(func(healthy bool) { + assert.True(t, healthy) + }) +} diff --git a/test/e2e/project_management_test.go b/test/e2e/project_management_test.go index f00c4e3eeba625..19222319693d1b 100644 --- a/test/e2e/project_management_test.go +++ b/test/e2e/project_management_test.go @@ -163,22 +163,19 @@ func TestAddProjectDestination(t *testing.T) { "https://192.168.99.100:8443", "test1", ) - require.Error(t, err) - assert.Contains(t, err.Error(), "already defined") + require.ErrorContains(t, err, "already defined") _, err = fixture.RunCli("proj", "add-destination", projectName, "!*", "test1", ) - require.Error(t, err) - assert.Contains(t, err.Error(), "server has an invalid format, '!*'") + require.ErrorContains(t, err, "server has an invalid format, '!*'") _, err = fixture.RunCli("proj", "add-destination", projectName, "https://192.168.99.100:8443", "!*", ) - require.Error(t, err) - assert.Contains(t, err.Error(), "namespace has an invalid format, '!*'") + require.ErrorContains(t, err, "namespace has an invalid format, '!*'") proj, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.TestNamespace()).Get(context.Background(), projectName, metav1.GetOptions{}) require.NoError(t, err) @@ -249,8 +246,7 @@ func TestRemoveProjectDestination(t *testing.T) { "https://192.168.99.100:8443", "test1", ) - require.Error(t, err) - assert.Contains(t, err.Error(), "does not exist") + require.ErrorContains(t, err, "does not exist") proj, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.TestNamespace()).Get(context.Background(), projectName, metav1.GetOptions{}) if err != nil { @@ -419,8 +415,7 @@ func TestAddOrphanedIgnore(t *testing.T) { "--name", "name", ) - require.Error(t, err) - assert.Contains(t, err.Error(), "already defined") + require.ErrorContains(t, err, "already defined") proj, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.TestNamespace()).Get(context.Background(), projectName, metav1.GetOptions{}) require.NoError(t, err) @@ -466,8 +461,7 @@ func TestRemoveOrphanedIgnore(t *testing.T) { "--name", "name", ) - require.Error(t, err) - assert.Contains(t, err.Error(), "does not exist") + require.ErrorContains(t, err, "does not exist") proj, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.TestNamespace()).Get(context.Background(), projectName, metav1.GetOptions{}) if err != nil { @@ -612,10 +606,217 @@ func TestGetVirtualProjectMatch(t *testing.T) { // App trying to sync a resource which is not blacked listed anywhere _, err = fixture.RunCli("app", "sync", fixture.Name(), "--resource", "apps:Deployment:guestbook-ui", "--timeout", fmt.Sprintf("%v", 10)) - require.Error(t, err) - assert.Contains(t, err.Error(), "blocked by sync window") + require.ErrorContains(t, err, "blocked by sync window") // app trying to sync a resource which is black listed by global project _, err = fixture.RunCli("app", "sync", fixture.Name(), "--resource", ":Service:guestbook-ui", "--timeout", fmt.Sprintf("%v", 10)) - assert.Contains(t, err.Error(), "blocked by sync window") + assert.ErrorContains(t, err, "blocked by sync window") +} + +func TestAddProjectDestinationServiceAccount(t *testing.T) { + fixture.EnsureCleanState(t) + + projectName := "proj-" + strconv.FormatInt(time.Now().Unix(), 10) + _, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.TestNamespace()).Create( + context.Background(), &v1alpha1.AppProject{ObjectMeta: metav1.ObjectMeta{Name: projectName}}, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("Unable to create project %v", err) + } + + // Given, an existing project + // When, a default destination service account with all valid fields is added to it, + // Then, there is no error. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "test-ns", + "test-sa", + ) + if err != nil { + t.Fatalf("Unable to add project destination service account %v", err) + } + + // Given, an existing project + // When, a default destination service account with empty namespace is added to it, + // Then, there is no error. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "", + "test-sa", + ) + if err != nil { + t.Fatalf("Unable to add project destination service account %v", err) + } + + // Given, an existing project, + // When, a default destination service account is added with a custom service account namespace, + // Then, there is no error. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "test-ns1", + "test-sa", + "--service-account-namespace", + "default", + ) + if err != nil { + t.Fatalf("Unable to add project destination service account %v", err) + } + + // Given, an existing project, + // When, a duplicate default destination service account is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "test-ns", + "test-sa", + ) + require.ErrorContains(t, err, "already defined") + + // Given, an existing project, + // When, a duplicate default destination service account is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "test-ns", + "asdf", + ) + require.ErrorContains(t, err, "already added") + + // Given, an existing project, + // When, a default destination service account with negation glob pattern for server is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "!*", + "test-ns", + "test-sa", + ) + require.ErrorContains(t, err, "server has an invalid format, '!*'") + + // Given, an existing project, + // When, a default destination service account with negation glob pattern for server is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "!abc", + "test-ns", + "test-sa", + ) + require.ErrorContains(t, err, "server has an invalid format, '!abc'") + + // Given, an existing project, + // When, a default destination service account with negation glob pattern for namespace is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "!*", + "test-sa", + ) + require.ErrorContains(t, err, "namespace has an invalid format, '!*'") + + // Given, an existing project, + // When, a default destination service account with negation glob pattern for namespace is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "!abc", + "test-sa", + ) + require.ErrorContains(t, err, "namespace has an invalid format, '!abc'") + + // Given, an existing project, + // When, a default destination service account with empty service account is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "test-ns", + "", + ) + require.ErrorContains(t, err, "defaultServiceAccount has an invalid format, ''") + + // Given, an existing project, + // When, a default destination service account with service account having just white spaces is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "test-ns", + " ", + ) + require.ErrorContains(t, err, "defaultServiceAccount has an invalid format, ' '") + + // Given, an existing project, + // When, a default destination service account with service account having backwards slash char is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "test-ns", + "test\\sa", + ) + require.ErrorContains(t, err, "defaultServiceAccount has an invalid format, 'test\\\\sa'") + + // Given, an existing project, + // When, a default destination service account with service account having forward slash char is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "test-ns", + "test/sa", + ) + require.ErrorContains(t, err, "defaultServiceAccount has an invalid format, 'test/sa'") + + // Given, an existing project, + // When, a default destination service account with service account having square braces char is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "test-ns", + "[test-sa]", + ) + require.ErrorContains(t, err, "defaultServiceAccount has an invalid format, '[test-sa]'") + + // Given, an existing project, + // When, a default destination service account with service account having curly braces char is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "test-ns", + "{test-sa}", + ) + require.ErrorContains(t, err, "defaultServiceAccount has an invalid format, '{test-sa}'") + + // Given, an existing project, + // When, a default destination service account with service account having curly braces char is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "[[ech*", + "test-ns", + "test-sa", + ) + require.ErrorContains(t, err, "server has an invalid format, '[[ech*'") + + // Given, an existing project, + // When, a default destination service account with service account having curly braces char is added, + // Then, there is an error with appropriate message. + _, err = fixture.RunCli("proj", "add-destination-service-account", projectName, + "https://192.168.99.100:8443", + "[[ech*", + "test-sa", + ) + require.ErrorContains(t, err, "namespace has an invalid format, '[[ech*'") + + proj, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.TestNamespace()).Get(context.Background(), projectName, metav1.GetOptions{}) + require.NoError(t, err) + assert.Equal(t, projectName, proj.Name) + assert.Len(t, proj.Spec.DestinationServiceAccounts, 3) + + assert.Equal(t, "https://192.168.99.100:8443", proj.Spec.DestinationServiceAccounts[0].Server) + assert.Equal(t, "test-ns", proj.Spec.DestinationServiceAccounts[0].Namespace) + assert.Equal(t, "test-sa", proj.Spec.DestinationServiceAccounts[0].DefaultServiceAccount) + + assert.Equal(t, "https://192.168.99.100:8443", proj.Spec.DestinationServiceAccounts[1].Server) + assert.Equal(t, "", proj.Spec.DestinationServiceAccounts[1].Namespace) + assert.Equal(t, "test-sa", proj.Spec.DestinationServiceAccounts[1].DefaultServiceAccount) + + assert.Equal(t, "https://192.168.99.100:8443", proj.Spec.DestinationServiceAccounts[2].Server) + assert.Equal(t, "test-ns1", proj.Spec.DestinationServiceAccounts[2].Namespace) + assert.Equal(t, "default:test-sa", proj.Spec.DestinationServiceAccounts[2].DefaultServiceAccount) + + assertProjHasEvent(t, proj, "update", argo.EventReasonResourceUpdated) } diff --git a/test/e2e/scoped_repository_test.go b/test/e2e/scoped_repository_test.go index d1da08b0a434d5..8578f2fa909329 100644 --- a/test/e2e/scoped_repository_test.go +++ b/test/e2e/scoped_repository_test.go @@ -56,7 +56,7 @@ func TestCreateRepositoryNonAdminUserPermissionDenied(t *testing.T) { Create(). Then(). AndCLIOutput(func(output string, err error) { - assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied: repositories, create") + assert.ErrorContains(t, err, "PermissionDenied desc = permission denied: repositories, create") }) } @@ -83,7 +83,7 @@ func TestCreateRepositoryNonAdminUserWithWrongProject(t *testing.T) { Create(). Then(). AndCLIOutput(func(output string, err error) { - assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied: repositories, create") + assert.ErrorContains(t, err, "PermissionDenied desc = permission denied: repositories, create") }) } @@ -170,7 +170,7 @@ func TestDeleteRepositoryRbacDenied(t *testing.T) { Delete(). Then(). AndCLIOutput(func(output string, err error) { - assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied: repositories, delete") + assert.ErrorContains(t, err, "PermissionDenied desc = permission denied: repositories, delete") }) } diff --git a/test/e2e/sync_with_impersonate_test.go b/test/e2e/sync_with_impersonate_test.go index 7bb57af1156d33..4c7cf166f4a090 100644 --- a/test/e2e/sync_with_impersonate_test.go +++ b/test/e2e/sync_with_impersonate_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "testing" + "time" "github.com/stretchr/testify/require" v1 "k8s.io/api/core/v1" @@ -16,32 +17,27 @@ import ( . "github.com/argoproj/argo-cd/v2/test/e2e/fixture/app" ) -func TestSyncWithImpersonateDisable(t *testing.T) { - Given(t). - Path("guestbook"). - When(). - SetParamInSettingConfigMap("application.sync.impersonation.enabled", "false"). - CreateFromFile(func(app *v1alpha1.Application) { - app.Spec.SyncPolicy = &v1alpha1.SyncPolicy{Automated: &v1alpha1.SyncPolicyAutomated{}} - }). - Then(). - Expect(SyncStatusIs(v1alpha1.SyncStatusCodeSynced)) -} +const ( + WaitDuration = time.Second + TimeoutDuration = time.Second * 3 +) -func TestSyncWithImpersonateDefaultNamespaceServiceAccountNoRBAC(t *testing.T) { +func TestSyncWithFeatureDisabled(t *testing.T) { Given(t). Path("guestbook"). When(). - SetParamInSettingConfigMap("application.sync.impersonation.enabled", "true"). + SetParamInSettingConfigMap("application.sync.impersonation.enabled", "false"). CreateFromFile(func(app *v1alpha1.Application) { app.Spec.SyncPolicy = &v1alpha1.SyncPolicy{Automated: &v1alpha1.SyncPolicyAutomated{}} }). Then(). - Expect(SyncStatusIs(v1alpha1.SyncStatusCodeOutOfSync)) + // With the impersonation feature disabled, Application sync should continue to use + // the control plane service account for the sync operation and the sync should succeed. + ExpectConsistently(SyncStatusIs(v1alpha1.SyncStatusCodeSynced), WaitDuration, TimeoutDuration). + Expect(OperationMessageContains("successfully synced")) } -func TestSyncWithImpersonateDefaultNamespaceServiceAccountWithRBAC(t *testing.T) { - roleName := "default-sa-role" +func TestSyncWithNoDestinationServiceAccountsInProject(t *testing.T) { Given(t). Path("guestbook"). When(). @@ -49,25 +45,11 @@ func TestSyncWithImpersonateDefaultNamespaceServiceAccountWithRBAC(t *testing.T) CreateFromFile(func(app *v1alpha1.Application) { app.Spec.SyncPolicy = &v1alpha1.SyncPolicy{Automated: &v1alpha1.SyncPolicyAutomated{}} }). - And(func() { - err := createTestRole(roleName, fixture.DeploymentNamespace(), []rbac.PolicyRule{ - { - APIGroups: []string{"apps", ""}, - Resources: []string{"deployments"}, - Verbs: []string{"*"}, - }, - { - APIGroups: []string{""}, - Resources: []string{"services"}, - Verbs: []string{"*"}, - }, - }) - require.NoError(t, err) - err = createTestRoleBinding(roleName, "default", fixture.DeploymentNamespace()) - require.NoError(t, err) - }). Then(). - Expect(SyncStatusIs(v1alpha1.SyncStatusCodeOutOfSync)) + // With the impersonation feature enabled, Application sync must fail + // when there are no destination service accounts configured in AppProject + ExpectConsistently(SyncStatusIs(v1alpha1.SyncStatusCodeOutOfSync), WaitDuration, TimeoutDuration). + Expect(OperationMessageContains("failed to find a matching service account to impersonate")) } func TestSyncWithImpersonateWithSyncServiceAccount(t *testing.T) { @@ -89,7 +71,7 @@ func TestSyncWithImpersonateWithSyncServiceAccount(t *testing.T) { { Server: "*", Namespace: fixture.DeploymentNamespace(), - DefaultServiceAccount: "false-serviceAccount", + DefaultServiceAccount: "missing-serviceAccount", }, } err := createTestServiceAccount(serviceAccountName, fixture.DeploymentNamespace()) @@ -118,10 +100,13 @@ func TestSyncWithImpersonateWithSyncServiceAccount(t *testing.T) { app.Spec.Project = projectName }). Then(). - Expect(SyncStatusIs(v1alpha1.SyncStatusCodeSynced)) + // With the impersonation feature enabled, Application sync should succeed + // as there is a valid match found in the available destination service accounts configured in AppProject + ExpectConsistently(SyncStatusIs(v1alpha1.SyncStatusCodeSynced), WaitDuration, TimeoutDuration). + Expect(OperationMessageContains("successfully synced")) } -func TestSyncWithImpersonateWithFalseServiceAccount(t *testing.T) { +func TestSyncWithMissingServiceAccount(t *testing.T) { projectName := "false-test-project" serviceAccountName := "test-account" roleName := "test-account-sa-role" @@ -135,7 +120,7 @@ func TestSyncWithImpersonateWithFalseServiceAccount(t *testing.T) { { Server: "*", Namespace: fixture.DeploymentNamespace(), - DefaultServiceAccount: "false-serviceAccount", + DefaultServiceAccount: "missing-serviceAccount", }, { Server: "*", @@ -169,11 +154,15 @@ func TestSyncWithImpersonateWithFalseServiceAccount(t *testing.T) { app.Spec.Project = projectName }). Then(). - Expect(SyncStatusIs(v1alpha1.SyncStatusCodeOutOfSync)) + // With the impersonation feature enabled, Application sync must fail + // when there is a valid match found in the available destination service accounts configured in AppProject, + // but the matching service account is missing. + ExpectConsistently(SyncStatusIs(v1alpha1.SyncStatusCodeOutOfSync), WaitDuration, TimeoutDuration). + Expect(OperationMessageContains("one or more objects failed to apply")) } -func TestSyncWithNegationApplicationDestinationNamespace(t *testing.T) { - projectName := "nagation-test-project" +func TestSyncWithValidSAButDisallowedDestination(t *testing.T) { + projectName := "negation-test-project" serviceAccountName := "test-account" roleName := "test-account-sa-role" Given(t). @@ -217,6 +206,7 @@ func TestSyncWithNegationApplicationDestinationNamespace(t *testing.T) { Expect(SyncStatusIs(v1alpha1.SyncStatusCodeSynced)). When(). And(func() { + // Patch destination to disallow target destination namespace patch := []byte(fmt.Sprintf(`{"spec": {"destinations": [{"namespace": "%s"}]}}`, "!"+fixture.DeploymentNamespace())) _, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.TestNamespace()).Patch(context.Background(), projectName, types.MergePatchType, patch, metav1.PatchOptions{}) @@ -224,7 +214,10 @@ func TestSyncWithNegationApplicationDestinationNamespace(t *testing.T) { }). Refresh(v1alpha1.RefreshTypeNormal). Then(). - Expect(SyncStatusIs(v1alpha1.SyncStatusCodeUnknown)) + // With the impersonation feature enabled, Application sync must fail + // as there is a valid match found in the available destination service accounts configured in AppProject + // but the destination namespace is now disallowed. + ExpectConsistently(SyncStatusIs(v1alpha1.SyncStatusCodeUnknown), WaitDuration, TimeoutDuration) } // createTestAppProject creates a test AppProject resource. diff --git a/test/remote/Dockerfile b/test/remote/Dockerfile index fa649805767ccd..035f51917f9572 100644 --- a/test/remote/Dockerfile +++ b/test/remote/Dockerfile @@ -1,6 +1,6 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:24.04@sha256:3f85b7caad41a95462cf5b787d8a04604c8262cdcdf9a472b8c52ef83375fe15 -FROM docker.io/library/golang:1.23.1@sha256:2fe82a3f3e006b4f2a316c6a21f62b66e1330ae211d039bb8d1128e12ed57bf1 AS go +FROM docker.io/library/golang:1.23.1@sha256:4f063a24d429510e512cc730c3330292ff49f3ade3ae79bda8f84a24fa25ecb0 AS go RUN go install github.com/mattn/goreman@latest && \ go install github.com/kisielk/godepgraph@latest diff --git a/ui-test/Dockerfile b/ui-test/Dockerfile index c0fbd1be9b7112..edbd2becbdf00f 100644 --- a/ui-test/Dockerfile +++ b/ui-test/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/library/node:22.9.0@sha256:cbe2d5f94110cea9817dd8c5809d05df49b4bd1aac5203f3594d88665ad37988 as node +FROM docker.io/library/node:22.9.0@sha256:69e667a79aa41ec0db50bc452a60e705ca16f35285eaf037ebe627a65a5cdf52 as node RUN apt-get update && apt-get install --no-install-recommends -y \ software-properties-common diff --git a/ui-test/package.json b/ui-test/package.json index ca168b60c92cf2..6343568c71bad6 100644 --- a/ui-test/package.json +++ b/ui-test/package.json @@ -14,8 +14,8 @@ "dependencies": { "@types/selenium-webdriver": "^4.1.26", "assert": "^2.1.0", - "chromedriver": "^129.0.0", - "selenium-webdriver": "^4.24.1" + "chromedriver": "^129.0.2", + "selenium-webdriver": "^4.25.0" }, "devDependencies": { "@types/mocha": "^10.0.8", diff --git a/ui-test/yarn.lock b/ui-test/yarn.lock index aee54d23e13bd6..3b00628624d15a 100644 --- a/ui-test/yarn.lock +++ b/ui-test/yarn.lock @@ -267,10 +267,10 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -chromedriver@^129.0.0: - version "129.0.0" - resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-129.0.0.tgz#28d7ede5ab372b868ac0db5efff7036646b4d603" - integrity sha512-B1ccqD6hDjNrw94FeqdynIotn1ZV/TnFrkRz2Rync2kzSnq6D6IrSkN1w5Pnuvnc98QhN2xujxDXxkqEqy/PWg== +chromedriver@^129.0.2: + version "129.0.2" + resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-129.0.2.tgz#950bb0a7d1095bc9c7a6f61e5f18e02e27875477" + integrity sha512-rUEFCJAmAwOdFfaDFtveT97fFeA7NOxlkgyPyN+G09Ws4qGW39aLDxMQBbS9cxQQHhTihqZZobgF5CLVYXnmGA== dependencies: "@testim/chrome-version" "^1.1.4" axios "^1.7.4" @@ -1272,10 +1272,10 @@ safe-buffer@^5.1.0, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -selenium-webdriver@^4.24.1: - version "4.24.1" - resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.24.1.tgz#4315214420cc26dddaa21ae26863dd452aec2829" - integrity sha512-fcK5BTI/54cSqIhiVtrd9li1YL6LW109yIwuVw6V+FlVE6y4riGiX2qdZxVzHq+sm2TJyps+D2sjzXrpDZe1Og== +selenium-webdriver@^4.25.0: + version "4.25.0" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.25.0.tgz#3562b49668817974bb1d13d25a50e8bc0264fcf3" + integrity sha512-zl9IX93caOT8wbcCpZzAkEtYa+hNgJ4C5GUN8uhpzggqRLvsg1asfKi0p1uNZC8buYVvsBZbx8S+9MjVAjs4oA== dependencies: "@bazel/runfiles" "^5.8.1" jszip "^3.10.1" diff --git a/ui/.nvmrc b/ui/.nvmrc index a8d3ff91fa10d4..728f7de5c2da0d 100644 --- a/ui/.nvmrc +++ b/ui/.nvmrc @@ -1 +1 @@ -v21.6.1 +22.9.0 diff --git a/ui/src/app/app.tsx b/ui/src/app/app.tsx index 7a9bfb21635bb3..7b73bc50ac70c3 100644 --- a/ui/src/app/app.tsx +++ b/ui/src/app/app.tsx @@ -8,7 +8,7 @@ import applications from './applications'; import help from './help'; import login from './login'; import settings from './settings'; -import {Layout} from './shared/components/layout/layout'; +import {Layout, ThemeWrapper} from './shared/components/layout/layout'; import {Page} from './shared/components/page/page'; import {VersionPanel} from './shared/components/version-info/version-info-panel'; import {AuthSettingsCtx, Provider} from './shared/context'; @@ -194,7 +194,7 @@ export class App extends React.Component< services.viewPreferences.getPreferences()}> - {pref =>
                                          {this.state.popupProps && }
                                          } + {pref => {this.state.popupProps && }}
                                          diff --git a/ui/src/app/applications/components/resource-details/resource-details.tsx b/ui/src/app/applications/components/resource-details/resource-details.tsx index 59774fa4598728..79bbce2c133ae4 100644 --- a/ui/src/app/applications/components/resource-details/resource-details.tsx +++ b/ui/src/app/applications/components/resource-details/resource-details.tsx @@ -284,7 +284,8 @@ export const ResourceDetails = (props: ResourceDetailsProps) => { const logsAllowed = await services.accounts.canI('logs', 'get', application.spec.project + '/' + application.metadata.name); const execAllowed = execEnabled && (await services.accounts.canI('exec', 'create', application.spec.project + '/' + application.metadata.name)); const links = await services.applications.getResourceLinks(application.metadata.name, application.metadata.namespace, selectedNode).catch(() => null); - return {controlledState, liveState, events, podState, execEnabled, execAllowed, logsAllowed, links, childResources}; + const resourceActionsMenuItems = await AppUtils.getResourceActionsMenuItems(selectedNode, application.metadata, appContext); + return {controlledState, liveState, events, podState, execEnabled, execAllowed, logsAllowed, links, childResources, resourceActionsMenuItems}; }}> {data => ( @@ -314,15 +315,17 @@ export const ResourceDetails = (props: ResourceDetailsProps) => { className='argo-button argo-button--base'> DELETE - ( - - )}> - {() => AppUtils.renderResourceActionMenu(selectedNode, application, appContext)} - + {data.resourceActionsMenuItems?.length > 0 && ( + ( + + )}> + {() => AppUtils.renderResourceActionMenu(data.resourceActionsMenuItems)} + + )}
                                          { +export function getResourceActionsMenuItems(resource: ResourceTreeNode, metadata: models.ObjectMeta, apis: ContextApis): Promise { return services.applications .getResourceActions(metadata.name, metadata.namespace, resource) .then(actions => { @@ -683,30 +683,24 @@ export function renderResourceMenu( ); } -export function renderResourceActionMenu(resource: ResourceTreeNode, application: appModels.Application, apis: ContextApis): React.ReactNode { - const menuItems = getResourceActionsMenuItems(resource, application.metadata, apis); - +export function renderResourceActionMenu(menuItems: ActionMenuItem[]): React.ReactNode { return ( - menuItems}> - {items => ( -
                                            - {items.map((item, i) => ( -
                                          • { - e.stopPropagation(); - if (!item.disabled) { - item.action(); - document.body.click(); - } - }}> - {item.iconClassName && } {item.title} -
                                          • - ))} -
                                          - )} -
                                          +
                                            + {menuItems.map((item, i) => ( +
                                          • { + e.stopPropagation(); + if (!item.disabled) { + item.action(); + document.body.click(); + } + }}> + {item.iconClassName && } {item.title} +
                                          • + ))} +
                                          ); } diff --git a/ui/src/app/settings/components/appearance-list/appearance-list.scss b/ui/src/app/settings/components/appearance-list/appearance-list.scss index dc70dcd77696cd..44c8be678f60fa 100644 --- a/ui/src/app/settings/components/appearance-list/appearance-list.scss +++ b/ui/src/app/settings/components/appearance-list/appearance-list.scss @@ -13,11 +13,13 @@ } border-radius: 4px; box-shadow: 1px 2px 3px rgba(#000, 0.1); - } + & .row { + justify-content: space-between; + align-items: center; - &__button { - position: absolute; - top: 25%; - right: 30px; + .select { + min-width: 160px; + } + } } -} \ No newline at end of file +} diff --git a/ui/src/app/settings/components/appearance-list/appearance-list.tsx b/ui/src/app/settings/components/appearance-list/appearance-list.tsx index 5e6fb06502f84c..493f8bcf69ce71 100644 --- a/ui/src/app/settings/components/appearance-list/appearance-list.tsx +++ b/ui/src/app/settings/components/appearance-list/appearance-list.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import {DataLoader, Page} from '../../../shared/components'; import {services} from '../../../shared/services'; +import {Select, SelectOption} from 'argo-ui'; require('./appearance-list.scss'); @@ -16,16 +17,16 @@ export const AppearanceList = () => {
                                          -
                                          Dark Theme
                                          -
                                          - +
                                          + Dark Theme +
                                          diff --git a/ui/src/app/settings/components/repo-details/repo-details.tsx b/ui/src/app/settings/components/repo-details/repo-details.tsx index 017d87bede789a..613d469c816124 100644 --- a/ui/src/app/settings/components/repo-details/repo-details.tsx +++ b/ui/src/app/settings/components/repo-details/repo-details.tsx @@ -17,6 +17,11 @@ export const RepoDetails = (props: {repo: models.Repository; save?: (params: New title: 'Repository URL', view: repository.repo }, + { + title: 'Name', + view: repository.name || '', + edit: (formApi: FormApi) => + }, { title: 'Username (optional)', view: repository.username || '', @@ -29,13 +34,6 @@ export const RepoDetails = (props: {repo: models.Repository; save?: (params: New } ]; - if (repository.name) { - items.splice(1, 0, { - title: 'NAME', - view: repository.name - }); - } - if (repository.project) { items.splice(repository.name ? 2 : 1, 0, { title: 'Project', @@ -86,6 +84,7 @@ export const RepoDetails = (props: {repo: models.Repository; save?: (params: New })} save={async input => { const params: NewHTTPSRepoParams = {...newRepo}; + params.name = input.name || ''; params.username = input.username || ''; params.password = input.password || ''; save(params); diff --git a/ui/src/app/settings/components/repos-list/repos-list.tsx b/ui/src/app/settings/components/repos-list/repos-list.tsx index 6b79ab490e3593..876bf5378f957c 100644 --- a/ui/src/app/settings/components/repos-list/repos-list.tsx +++ b/ui/src/app/settings/components/repos-list/repos-list.tsx @@ -470,9 +470,14 @@ export class ReposList extends React.Component<
                                          - {formApi.getFormState().values.type === 'helm' && ( + {(formApi.getFormState().values.type === 'helm' || formApi.getFormState().values.type === 'git') && (
                                          - +
                                          )}
                                          diff --git a/ui/src/app/shared/components/layout/layout.tsx b/ui/src/app/shared/components/layout/layout.tsx index e08297cb4e9e62..215120f9d83806 100644 --- a/ui/src/app/shared/components/layout/layout.tsx +++ b/ui/src/app/shared/components/layout/layout.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import {Sidebar} from '../../../sidebar/sidebar'; import {ViewPreferences} from '../../services'; +import {useTheme} from '../../utils'; require('./layout.scss'); @@ -13,15 +14,23 @@ export interface LayoutProps { const getBGColor = (theme: string): string => (theme === 'light' ? '#dee6eb' : '#100f0f'); +export const ThemeWrapper = (props: {children: React.ReactNode; theme: string}) => { + const [systemTheme] = useTheme({ + theme: props.theme + }); + return
                                          {props.children}
                                          ; +}; + export const Layout = (props: LayoutProps) => { + const [theme] = useTheme({theme: props.pref.theme}); React.useEffect(() => { - if (props.pref.theme) { - document.body.style.background = getBGColor(props.pref.theme); + if (theme) { + document.body.style.background = getBGColor(theme); } - }, [props.pref.theme]); + }, [theme]); return ( -
                                          +
                                          diff --git a/ui/src/app/shared/components/monaco-editor.tsx b/ui/src/app/shared/components/monaco-editor.tsx index a30381638f0b5c..e0a34a06e94404 100644 --- a/ui/src/app/shared/components/monaco-editor.tsx +++ b/ui/src/app/shared/components/monaco-editor.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import * as monacoEditor from 'monaco-editor'; import {services} from '../services'; +import {getTheme, useSystemTheme} from '../utils'; export interface EditorInput { text: string; @@ -28,10 +29,25 @@ const MonacoEditorLazy = React.lazy(() => import('monaco-editor').then(monaco => { const Component = (props: MonacoProps) => { const [height, setHeight] = React.useState(0); + const [theme, setTheme] = React.useState('dark'); + + React.useEffect(() => { + const destroySystemThemeListener = useSystemTheme(systemTheme => { + if (theme === 'auto') { + monaco.editor.setTheme(systemTheme === 'dark' ? 'vs-dark' : 'vs'); + } + }); + + return () => { + destroySystemThemeListener(); + }; + }, [theme]); React.useEffect(() => { const subscription = services.viewPreferences.getPreferences().subscribe(preferences => { - monaco.editor.setTheme(preferences.theme === 'dark' ? 'vs-dark' : 'vs'); + setTheme(preferences.theme); + + monaco.editor.setTheme(getTheme(preferences.theme) === 'dark' ? 'vs-dark' : 'vs'); }); return () => { diff --git a/ui/src/app/shared/components/version-info/version-info-panel.tsx b/ui/src/app/shared/components/version-info/version-info-panel.tsx index 8622b762c8a5ab..15edf463aae73c 100644 --- a/ui/src/app/shared/components/version-info/version-info-panel.tsx +++ b/ui/src/app/shared/components/version-info/version-info-panel.tsx @@ -2,6 +2,7 @@ import {DataLoader, SlidingPanel, Tooltip} from 'argo-ui'; import * as React from 'react'; import {VersionMessage} from '../../models'; import {services} from '../../services'; +import {ThemeWrapper} from '../layout/layout'; interface VersionPanelProps { isShown: boolean; @@ -26,14 +27,14 @@ export class VersionPanel extends React.Component this.props.version}> {version => { return ( -
                                          + this.props.onClose()} hasCloseButton={true} isNarrow={true}>
                                          {this.buildVersionTable(version)}
                                          {this.getCopyButton(version)}
                                          -
                                          + ); }} diff --git a/ui/src/app/shared/utils.ts b/ui/src/app/shared/utils.ts index c57715a8f933db..129b8e769a9513 100644 --- a/ui/src/app/shared/utils.ts +++ b/ui/src/app/shared/utils.ts @@ -1,3 +1,5 @@ +import React from 'react'; + export function hashCode(str: string) { let hash = 0; for (let i = 0; i < str.length; i++) { @@ -34,3 +36,71 @@ export function isValidURL(url: string): boolean { } } } + +export const colorSchemes = { + light: '(prefers-color-scheme: light)', + dark: '(prefers-color-scheme: dark)' +}; + +/** + * quick method to check system theme + * @param theme auto, light, dark + * @returns dark or light + */ +export function getTheme(theme: string) { + if (theme !== 'auto') { + return theme; + } + + const dark = window.matchMedia(colorSchemes.dark); + + return dark.matches ? 'dark' : 'light'; +} + +/** + * create a listener for system theme + * @param cb callback for theme change + * @returns destroy listener + */ +export const useSystemTheme = (cb: (theme: string) => void) => { + const dark = window.matchMedia(colorSchemes.dark); + const light = window.matchMedia(colorSchemes.light); + + const listener = () => { + cb(dark.matches ? 'dark' : 'light'); + }; + + dark.addEventListener('change', listener); + light.addEventListener('change', listener); + + return () => { + dark.removeEventListener('change', listener); + light.removeEventListener('change', listener); + }; +}; + +export const useTheme = (props: {theme: string}) => { + const [theme, setTheme] = React.useState(getTheme(props.theme)); + + React.useEffect(() => { + let destroyListener: (() => void) | undefined; + + // change theme by system, only register listener when theme is auto + if (props.theme === 'auto') { + destroyListener = useSystemTheme(systemTheme => { + setTheme(systemTheme); + }); + } + + // change theme manually + if (props.theme !== theme) { + setTheme(getTheme(props.theme)); + } + + return () => { + destroyListener?.(); + }; + }, [props.theme]); + + return [theme]; +}; diff --git a/util/app/discovery/discovery.go b/util/app/discovery/discovery.go index df80e3bf987c2e..580e4cd06935db 100644 --- a/util/app/discovery/discovery.go +++ b/util/app/discovery/discovery.go @@ -173,9 +173,12 @@ func cmpSupports(ctx context.Context, pluginSockFilePath, appPath, repoPath, fil return nil, nil, false } - // if discovery is not configured, return the client without further checks if !cfg.IsDiscoveryConfigured { - return conn, cmpClient, true + // If discovery isn't configured but the plugin is named, then the plugin supports the repo. + if namedPlugin { + return conn, cmpClient, true + } + return nil, nil, false } isSupported, isDiscoveryEnabled, err := matchRepositoryCMP(ctx, appPath, repoPath, cmpClient, env, tarExcludedGlobs) diff --git a/util/argo/argo.go b/util/argo/argo.go index 2c5b1326678798..8fb4eba2f34308 100644 --- a/util/argo/argo.go +++ b/util/argo/argo.go @@ -329,7 +329,10 @@ func ValidateRepo( }) return conditions, nil } - config := cluster.RESTConfig() + config, err := cluster.RESTConfig() + if err != nil { + return nil, fmt.Errorf("error getting cluster REST config: %w", err) + } // nolint:staticcheck cluster.ServerVersion, err = kubectl.GetServerVersion(config) if err != nil { @@ -749,6 +752,14 @@ func verifyGenerateManifests( }) continue } + installationID, err := settingsMgr.GetInstallationID() + if err != nil { + conditions = append(conditions, argoappv1.ApplicationCondition{ + Type: argoappv1.ApplicationConditionInvalidSpecError, + Message: fmt.Sprintf("Error getting installation ID: %v", err), + }) + continue + } req := apiclient.ManifestRequest{ Repo: &argoappv1.Repository{ Repo: source.RepoURL, @@ -775,6 +786,7 @@ func verifyGenerateManifests( ProjectName: proj.Name, ProjectSourceRepos: proj.Spec.SourceRepos, AnnotationManifestGeneratePaths: app.GetAnnotation(argoappv1.AnnotationKeyManifestGeneratePaths), + InstallationID: installationID, } req.Repo.CopyCredentialsFromRepo(repoRes) req.Repo.CopySettingsFrom(repoRes) diff --git a/util/argo/argo_test.go b/util/argo/argo_test.go index b2c684c660c1f7..74db80a0c198c4 100644 --- a/util/argo/argo_test.go +++ b/util/argo/argo_test.go @@ -893,8 +893,7 @@ func TestSetAppOperations(t *testing.T) { } appIf := appclientset.NewSimpleClientset(&a).ArgoprojV1alpha1().Applications("default") app, err := SetAppOperation(appIf, "someapp", &argoappv1.Operation{Sync: &argoappv1.SyncOperation{Revision: "aaa"}}) - require.Error(t, err) - assert.Contains(t, err.Error(), "operation is already in progress") + require.ErrorContains(t, err, "operation is already in progress") assert.Nil(t, app) }) @@ -907,8 +906,7 @@ func TestSetAppOperations(t *testing.T) { } appIf := appclientset.NewSimpleClientset(&a).ArgoprojV1alpha1().Applications("default") app, err := SetAppOperation(appIf, "someapp", &argoappv1.Operation{Sync: nil}) - require.Error(t, err) - assert.Contains(t, err.Error(), "Operation unspecified") + require.ErrorContains(t, err, "Operation unspecified") assert.Nil(t, app) }) @@ -973,7 +971,7 @@ func TestValidateDestination(t *testing.T) { db.On("GetClusterServersByName", context.Background(), mock.Anything).Return(nil, fmt.Errorf("an error occurred")) err := ValidateDestination(context.Background(), &dest, db) - assert.Contains(t, err.Error(), "an error occurred") + require.ErrorContains(t, err, "an error occurred") assert.False(t, dest.IsServerInferred()) }) diff --git a/util/argo/resource_tracking.go b/util/argo/resource_tracking.go index e904f2aa1d4667..bd951ebb29d9c5 100644 --- a/util/argo/resource_tracking.go +++ b/util/argo/resource_tracking.go @@ -29,9 +29,9 @@ var ( // ResourceTracking defines methods which allow setup and retrieve tracking information to resource type ResourceTracking interface { - GetAppName(un *unstructured.Unstructured, key string, trackingMethod v1alpha1.TrackingMethod) string - GetAppInstance(un *unstructured.Unstructured, key string, trackingMethod v1alpha1.TrackingMethod) *AppInstanceValue - SetAppInstance(un *unstructured.Unstructured, key, val, namespace string, trackingMethod v1alpha1.TrackingMethod) error + GetAppName(un *unstructured.Unstructured, key string, trackingMethod v1alpha1.TrackingMethod, installationID string) string + GetAppInstance(un *unstructured.Unstructured, key string, trackingMethod v1alpha1.TrackingMethod, installationID string) *AppInstanceValue + SetAppInstance(un *unstructured.Unstructured, key, val, namespace string, trackingMethod v1alpha1.TrackingMethod, instanceID string) error BuildAppInstanceValue(value AppInstanceValue) string ParseAppInstanceValue(value string) (*AppInstanceValue, error) Normalize(config, live *unstructured.Unstructured, labelKey, trackingMethod string) error @@ -65,7 +65,10 @@ func IsOldTrackingMethod(trackingMethod string) bool { return trackingMethod == "" || trackingMethod == string(TrackingMethodLabel) } -func (rt *resourceTracking) getAppInstanceValue(un *unstructured.Unstructured) *AppInstanceValue { +func (rt *resourceTracking) getAppInstanceValue(un *unstructured.Unstructured, installationID string) *AppInstanceValue { + if installationID != "" && un.GetAnnotations() == nil || un.GetAnnotations()[common.AnnotationInstallationID] != installationID { + return nil + } appInstanceAnnotation, err := argokube.GetAppInstanceAnnotation(un, common.AnnotationKeyAppInstance) if err != nil { return nil @@ -78,9 +81,9 @@ func (rt *resourceTracking) getAppInstanceValue(un *unstructured.Unstructured) * } // GetAppName retrieve application name base on tracking method -func (rt *resourceTracking) GetAppName(un *unstructured.Unstructured, key string, trackingMethod v1alpha1.TrackingMethod) string { +func (rt *resourceTracking) GetAppName(un *unstructured.Unstructured, key string, trackingMethod v1alpha1.TrackingMethod, instanceID string) string { retrieveAppInstanceValue := func() string { - value := rt.getAppInstanceValue(un) + value := rt.getAppInstanceValue(un, instanceID) if value != nil { return value.ApplicationName } @@ -109,10 +112,10 @@ func (rt *resourceTracking) GetAppName(un *unstructured.Unstructured, key string // GetAppInstance returns the representation of the app instance annotation. // If the tracking method does not support metadata, or the annotation could // not be parsed, it returns nil. -func (rt *resourceTracking) GetAppInstance(un *unstructured.Unstructured, key string, trackingMethod v1alpha1.TrackingMethod) *AppInstanceValue { +func (rt *resourceTracking) GetAppInstance(un *unstructured.Unstructured, key string, trackingMethod v1alpha1.TrackingMethod, instanceID string) *AppInstanceValue { switch trackingMethod { case TrackingMethodAnnotation, TrackingMethodAnnotationAndLabel: - return rt.getAppInstanceValue(un) + return rt.getAppInstanceValue(un, instanceID) default: return nil } @@ -138,9 +141,18 @@ func UnstructuredToAppInstanceValue(un *unstructured.Unstructured, appName, name } // SetAppInstance set label/annotation base on tracking method -func (rt *resourceTracking) SetAppInstance(un *unstructured.Unstructured, key, val, namespace string, trackingMethod v1alpha1.TrackingMethod) error { +func (rt *resourceTracking) SetAppInstance(un *unstructured.Unstructured, key, val, namespace string, trackingMethod v1alpha1.TrackingMethod, instanceID string) error { setAppInstanceAnnotation := func() error { appInstanceValue := UnstructuredToAppInstanceValue(un, val, namespace) + if instanceID != "" { + if err := argokube.SetAppInstanceAnnotation(un, common.AnnotationInstallationID, instanceID); err != nil { + return err + } + } else { + if err := argokube.RemoveAnnotation(un, common.AnnotationInstallationID); err != nil { + return err + } + } return argokube.SetAppInstanceAnnotation(un, common.AnnotationKeyAppInstance, rt.BuildAppInstanceValue(appInstanceValue)) } switch trackingMethod { diff --git a/util/argo/resource_tracking_test.go b/util/argo/resource_tracking_test.go index 3c747edf69fcb5..bdac7930427a48 100644 --- a/util/argo/resource_tracking_test.go +++ b/util/argo/resource_tracking_test.go @@ -24,9 +24,9 @@ func TestSetAppInstanceLabel(t *testing.T) { resourceTracking := NewResourceTracking() - err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel) + err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel, "") require.NoError(t, err) - app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodLabel) + app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodLabel, "") assert.Equal(t, "my-app", app) } @@ -40,10 +40,10 @@ func TestSetAppInstanceAnnotation(t *testing.T) { resourceTracking := NewResourceTracking() - err = resourceTracking.SetAppInstance(&obj, common.AnnotationKeyAppInstance, "my-app", "", TrackingMethodAnnotation) + err = resourceTracking.SetAppInstance(&obj, common.AnnotationKeyAppInstance, "my-app", "", TrackingMethodAnnotation, "") require.NoError(t, err) - app := resourceTracking.GetAppName(&obj, common.AnnotationKeyAppInstance, TrackingMethodAnnotation) + app := resourceTracking.GetAppName(&obj, common.AnnotationKeyAppInstance, TrackingMethodAnnotation, "") assert.Equal(t, "my-app", app) } @@ -56,10 +56,10 @@ func TestSetAppInstanceAnnotationAndLabel(t *testing.T) { resourceTracking := NewResourceTracking() - err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodAnnotationAndLabel) + err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodAnnotationAndLabel, "") require.NoError(t, err) - app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel) + app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel, "") assert.Equal(t, "my-app", app) } @@ -72,11 +72,11 @@ func TestSetAppInstanceAnnotationAndLabelLongName(t *testing.T) { resourceTracking := NewResourceTracking() - err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app-with-an-extremely-long-name-that-is-over-sixty-three-characters", "", TrackingMethodAnnotationAndLabel) + err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app-with-an-extremely-long-name-that-is-over-sixty-three-characters", "", TrackingMethodAnnotationAndLabel, "") require.NoError(t, err) // the annotation should still work, so the name from GetAppName should not be truncated - app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel) + app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel, "") assert.Equal(t, "my-app-with-an-extremely-long-name-that-is-over-sixty-three-characters", app) // the label should be truncated to 63 characters @@ -92,11 +92,11 @@ func TestSetAppInstanceAnnotationAndLabelLongNameBadEnding(t *testing.T) { resourceTracking := NewResourceTracking() - err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "the-very-suspicious-name-with-precisely-sixty-three-characters-with-hyphen", "", TrackingMethodAnnotationAndLabel) + err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "the-very-suspicious-name-with-precisely-sixty-three-characters-with-hyphen", "", TrackingMethodAnnotationAndLabel, "") require.NoError(t, err) // the annotation should still work, so the name from GetAppName should not be truncated - app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel) + app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel, "") assert.Equal(t, "the-very-suspicious-name-with-precisely-sixty-three-characters-with-hyphen", app) // the label should be truncated to 63 characters, AND the hyphen should be removed @@ -112,7 +112,7 @@ func TestSetAppInstanceAnnotationAndLabelOutOfBounds(t *testing.T) { resourceTracking := NewResourceTracking() - err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "----------------------------------------------------------------", "", TrackingMethodAnnotationAndLabel) + err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "----------------------------------------------------------------", "", TrackingMethodAnnotationAndLabel, "") // this should error because it can't truncate to a valid value assert.EqualError(t, err, "failed to set app instance label: unable to truncate label to not end with a special character") } @@ -127,7 +127,7 @@ func TestSetAppInstanceAnnotationNotFound(t *testing.T) { resourceTracking := NewResourceTracking() - app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotation) + app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotation, "") assert.Equal(t, "", app) } @@ -185,12 +185,12 @@ func TestResourceIdNormalizer_Normalize(t *testing.T) { // live object is a resource that has old style tracking label liveObj := sampleResource(t) - err := rt.SetAppInstance(liveObj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel) + err := rt.SetAppInstance(liveObj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel, "") require.NoError(t, err) // config object is a resource that has new style tracking annotation configObj := sampleResource(t) - err = rt.SetAppInstance(configObj, common.AnnotationKeyAppInstance, "my-app2", "", TrackingMethodAnnotation) + err = rt.SetAppInstance(configObj, common.AnnotationKeyAppInstance, "my-app2", "", TrackingMethodAnnotation, "") require.NoError(t, err) _ = rt.Normalize(configObj, liveObj, common.LabelKeyAppInstance, string(TrackingMethodAnnotation)) @@ -208,14 +208,14 @@ func TestResourceIdNormalizer_Normalize_ConfigHasOldLabel(t *testing.T) { // live object is a resource that has old style tracking label liveObj := sampleResource(t) - err := rt.SetAppInstance(liveObj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel) + err := rt.SetAppInstance(liveObj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel, "") require.NoError(t, err) // config object is a resource that has new style tracking annotation configObj := sampleResource(t) - err = rt.SetAppInstance(configObj, common.AnnotationKeyAppInstance, "my-app2", "", TrackingMethodAnnotation) + err = rt.SetAppInstance(configObj, common.AnnotationKeyAppInstance, "my-app2", "", TrackingMethodAnnotation, "") require.NoError(t, err) - err = rt.SetAppInstance(configObj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel) + err = rt.SetAppInstance(configObj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel, "") require.NoError(t, err) _ = rt.Normalize(configObj, liveObj, common.LabelKeyAppInstance, string(TrackingMethodAnnotation)) diff --git a/util/cache/cache_test.go b/util/cache/cache_test.go index 0a156cedeeb0df..921b2b1dc1b9ba 100644 --- a/util/cache/cache_test.go +++ b/util/cache/cache_test.go @@ -74,11 +74,9 @@ func TestCacheClient(t *testing.T) { }) t.Run("Check for nil items", func(t *testing.T) { err := cache.SetItem("foo", nil, &CacheActionOpts{Expiration: 0, Delete: true}) - require.Error(t, err) - assert.Contains(t, err.Error(), "cannot set nil item") + require.ErrorContains(t, err, "cannot set nil item") err = cache.GetItem("foo", nil) - require.Error(t, err) - assert.Contains(t, err.Error(), "cannot get item") + assert.ErrorContains(t, err, "cannot get item") }) } } diff --git a/util/cache/redis_test.go b/util/cache/redis_test.go index e0314cefaf63a7..d60c7ea268e2cb 100644 --- a/util/cache/redis_test.go +++ b/util/cache/redis_test.go @@ -90,8 +90,7 @@ func TestRedisSetCache(t *testing.T) { var res string client := NewRedisCache(redis.NewClient(&redis.Options{Addr: mr.Addr()}), 10*time.Second, RedisCompressionNone) err = client.Get("foo", &res) - require.Error(t, err) - assert.Contains(t, err.Error(), "cache: key is missing") + assert.ErrorContains(t, err, "cache: key is missing") }) } diff --git a/util/cert/cert_test.go b/util/cert/cert_test.go index a9fb4c4810eb27..cfc4b4385dd07c 100644 --- a/util/cert/cert_test.go +++ b/util/cert/cert_test.go @@ -505,7 +505,7 @@ func TestGetCertificateForConnect(t *testing.T) { certs, err := GetCertificateForConnect("127.0.0.1") require.Error(t, err) assert.Empty(t, certs) - assert.Contains(t, err.Error(), "no certificates found") + assert.ErrorContains(t, err, "no certificates found") }) } diff --git a/util/db/db_test.go b/util/db/db_test.go index 38d56a4bceac10..2e8560459c4b24 100644 --- a/util/db/db_test.go +++ b/util/db/db_test.go @@ -628,13 +628,13 @@ func TestFuzzyEquivalence(t *testing.T) { repo, err = db.CreateRepository(ctx, &v1alpha1.Repository{ Repo: "https://github.com/argoproj/argocd-example-apps.git", }) - assert.Contains(t, err.Error(), "already exists") + require.ErrorContains(t, err, "already exists") assert.Nil(t, repo) repo, err = db.CreateRepository(ctx, &v1alpha1.Repository{ Repo: "https://github.com/argoproj/argocd-example-APPS", }) - assert.Contains(t, err.Error(), "already exists") + require.ErrorContains(t, err, "already exists") assert.Nil(t, repo) repo, err = db.GetRepository(ctx, "https://github.com/argoproj/argocd-example-APPS", "") diff --git a/util/exec/exec_test.go b/util/exec/exec_test.go index a3ae4888f2cf44..4597b7213ef23e 100644 --- a/util/exec/exec_test.go +++ b/util/exec/exec_test.go @@ -52,7 +52,7 @@ func TestRunWithExecRunOpts(t *testing.T) { }, } _, err := RunWithExecRunOpts(exec.Command("sh", "-c", "trap 'trap - 15 && echo captured && exit' 15 && sleep 2"), opts) - assert.Contains(t, err.Error(), "failed timeout after 200ms") + assert.ErrorContains(t, err, "failed timeout after 200ms") } func Test_getCommandArgsToLog(t *testing.T) { diff --git a/util/git/client.go b/util/git/client.go index 3b9c6d42450a58..80ec7060628018 100644 --- a/util/git/client.go +++ b/util/git/client.go @@ -631,14 +631,9 @@ func (m *nativeGitClient) lsRemote(revision string) (string, error) { revision = "HEAD" } - // Check if the revision is a valid semver constraint before attempting to resolve it - if constraint, err := semver.NewConstraint(revision); err == nil { - semverSha := m.resolveSemverRevision(constraint, refs) - if semverSha != "" { - return semverSha, nil - } - } else { - log.Debugf("Revision '%s' is not a valid semver constraint, skipping semver resolution.", revision) + semverSha := m.resolveSemverRevision(revision, refs) + if semverSha != "" { + return semverSha, nil } // refToHash keeps a maps of remote refs to their hash @@ -684,18 +679,31 @@ func (m *nativeGitClient) lsRemote(revision string) (string, error) { // If we get here, revision string had non hexadecimal characters (indicating its a branch, tag, // or symbolic ref) and we were unable to resolve it to a commit SHA. - return "", fmt.Errorf("Unable to resolve '%s' to a commit SHA", revision) + return "", fmt.Errorf("unable to resolve '%s' to a commit SHA", revision) } // resolveSemverRevision is a part of the lsRemote method workflow. -// When the user configure correctly the Git repository revision and the revision is a valid semver constraint -// only the for loop in this function will run, otherwise the lsRemote loop will try to resolve the revision. -// Some examples to illustrate the actual behavior, if: -// * The revision is "v0.1.*"/"0.1.*" or "v0.1.2"/"0.1.2" and there's a tag matching that constraint only this function loop will run; -// * The revision is "v0.1.*"/"0.1.*" or "0.1.2"/"0.1.2" and there is no tag matching that constraint this function loop and lsRemote loop will run for backward compatibility; -// * The revision is "custom-tag" only the lsRemote loop will run because that revision is an invalid semver; -// * The revision is "master-branch" only the lsRemote loop will run because that revision is an invalid semver; -func (m *nativeGitClient) resolveSemverRevision(constraint *semver.Constraints, refs []*plumbing.Reference) string { +// When the user correctly configures the Git repository revision, and that revision is a valid semver constraint, we +// use this logic path rather than the standard lsRemote revision resolution loop. +// Some examples to illustrate the actual behavior - if the revision is: +// * "v0.1.2"/"0.1.2" or "v0.1"/"0.1", then this is not a constraint, it's a pinned version - so we fall back to the standard tag matching in the lsRemote loop. +// * "v0.1.*"/"0.1.*", and there's a tag matching that constraint, then we find the latest matching version and return its commit hash. +// * "v0.1.*"/"0.1.*", and there is *no* tag matching that constraint, then we fall back to the standard tag matching in the lsRemote loop. +// * "custom-tag", only the lsRemote loop will run - because that revision is an invalid semver; +// * "master-branch", only the lsRemote loop will run because that revision is an invalid semver; +func (m *nativeGitClient) resolveSemverRevision(revision string, refs []*plumbing.Reference) string { + if _, err := semver.NewVersion(revision); err == nil { + // If the revision is a valid version, then we know it isn't a constraint; it's just a pin. + // In which case, we should use standard tag resolution mechanisms. + return "" + } + + constraint, err := semver.NewConstraint(revision) + if err != nil { + log.Debugf("Revision '%s' is not a valid semver constraint, skipping semver resolution.", revision) + return "" + } + maxVersion := semver.New(0, 0, 0, "", "") maxVersionHash := plumbing.ZeroHash for _, ref := range refs { @@ -723,6 +731,7 @@ func (m *nativeGitClient) resolveSemverRevision(constraint *semver.Constraints, return "" } + log.Debugf("Semver constraint '%s' resolved to tag '%s', at reference '%s'", revision, maxVersion.Original(), maxVersionHash.String()) return maxVersionHash.String() } diff --git a/util/git/client_test.go b/util/git/client_test.go index c2f8061a1c2f0e..207aebe9e34a0f 100644 --- a/util/git/client_test.go +++ b/util/git/client_test.go @@ -173,6 +173,148 @@ func Test_ChangedFiles(t *testing.T) { assert.ElementsMatch(t, []string{"README"}, changedFiles) } +func Test_SemverTags(t *testing.T) { + tempDir := t.TempDir() + + client, err := NewClientExt(fmt.Sprintf("file://%s", tempDir), tempDir, NopCreds{}, true, false, "", "") + require.NoError(t, err) + + err = client.Init() + require.NoError(t, err) + + mapTagRefs := map[string]string{} + for _, tag := range []string{ + "v1.0.0-rc1", + "v1.0.0-rc2", + "v1.0.0", + "v1.0", + "v1.0.1", + "v1.1.0", + "2024-apple", + "2024-banana", + } { + err = runCmd(client.Root(), "git", "commit", "-m", tag+" commit", "--allow-empty") + require.NoError(t, err) + + // Create an rc semver tag + err = runCmd(client.Root(), "git", "tag", tag) + require.NoError(t, err) + + sha, err := client.LsRemote("HEAD") + require.NoError(t, err) + + mapTagRefs[tag] = sha + } + + for _, tc := range []struct { + name string + ref string + expected string + error bool + }{{ + name: "pinned rc version", + ref: "v1.0.0-rc1", + expected: mapTagRefs["v1.0.0-rc1"], + }, { + name: "lt rc constraint", + ref: "< v1.0.0-rc3", + expected: mapTagRefs["v1.0.0-rc2"], + }, { + name: "pinned major version", + ref: "v1.0.0", + expected: mapTagRefs["v1.0.0"], + }, { + name: "pinned patch version", + ref: "v1.0.1", + expected: mapTagRefs["v1.0.1"], + }, { + name: "pinned minor version", + ref: "v1.1.0", + expected: mapTagRefs["v1.1.0"], + }, { + name: "patch wildcard constraint", + ref: "v1.0.*", + expected: mapTagRefs["v1.0.1"], + }, { + name: "patch tilde constraint", + ref: "~v1.0.0", + expected: mapTagRefs["v1.0.1"], + }, { + name: "minor wildcard constraint", + ref: "v1.*", + expected: mapTagRefs["v1.1.0"], + }, { + // The semver library allows for using both * and x as the wildcard modifier. + name: "alternative minor wildcard constraint", + ref: "v1.x", + expected: mapTagRefs["v1.1.0"], + }, { + name: "minor gte constraint", + ref: ">= v1.0.0", + expected: mapTagRefs["v1.1.0"], + }, { + name: "multiple constraints", + ref: "> v1.0.0 < v1.1.0", + expected: mapTagRefs["v1.0.1"], + }, { + // We treat non-specific semver versions as regular tags, rather than constraints. + name: "non-specific version", + ref: "v1.0", + expected: mapTagRefs["v1.0"], + }, { + // Which means a missing tag will raise an error. + name: "missing non-specific version", + ref: "v1.1", + error: true, + }, { + // This is NOT a semver constraint, so it should always resolve to itself - because specifying a tag should + // return the commit for that tag. + // semver/v3 has the unfortunate semver-ish behaviour where any tag starting with a number is considered to be + // "semver-ish", where that number is the semver major version, and the rest then gets coerced into a beta + // version string. This can cause unexpected behaviour with constraints logic. + // In this case, if the tag is being incorrectly coerced into semver (for being semver-ish), it will incorrectly + // return the commit for the 2024-banana tag; which we want to avoid. + name: "apple non-semver tag", + ref: "2024-apple", + expected: mapTagRefs["2024-apple"], + }, { + name: "banana non-semver tag", + ref: "2024-banana", + expected: mapTagRefs["2024-banana"], + }, { + // A semver version (without constraints) should ONLY match itself. + // We do not want "2024-apple" to get "semver-ish'ed" into matching "2024.0.0-apple"; they're different tags. + name: "no semver tag coercion", + ref: "2024.0.0-apple", + error: true, + }, { + // No minor versions are specified, so we would expect a major version of 2025 or more. + // This is because if we specify > 11 in semver, we would not expect 11.1.0 to pass; it should be 12.0.0 or more. + // Similarly, if we were to specify > 11.0, we would expect 11.1.0 or more. + name: "semver constraints on non-semver tags", + ref: "> 2024-apple", + error: true, + }, { + // However, if one specifies the minor/patch versions, semver constraints can be used to match non-semver tags. + // 2024-banana is considered as "2024.0.0-banana" in semver-ish, and banana > apple, so it's a match. + // Note: this is more for documentation and future reference than real testing, as it seems like quite odd behaviour. + name: "semver constraints on non-semver tags", + ref: "> 2024.0.0-apple", + expected: mapTagRefs["2024-banana"], + }} { + t.Run(tc.name, func(t *testing.T) { + commitSHA, err := client.LsRemote(tc.ref) + if tc.error { + require.Error(t, err) + return + } + require.NoError(t, err) + assert.True(t, IsCommitSHA(commitSHA)) + assert.Equal(t, tc.expected, commitSHA) + }) + } +} + func Test_nativeGitClient_Submodule(t *testing.T) { tempDir, err := os.MkdirTemp("", "") require.NoError(t, err) diff --git a/util/git/git_test.go b/util/git/git_test.go index bfa2905e7f5189..d507c728c0fdef 100644 --- a/util/git/git_test.go +++ b/util/git/git_test.go @@ -233,15 +233,10 @@ func TestLsRemote(t *testing.T) { expectedCommit: "ff87d8cb9e669d3738434733ecba3c6dd2c64d70", }, { - name: "should resolve a pined tag with semantic versioning", + name: "should resolve a pinned tag with semantic versioning", revision: "v0.8.0", expectedCommit: "d7c04ae24c16f8ec611b0331596fbc595537abe9", }, - { - name: "should resolve a pined tag with semantic versioning without the 'v' prefix", - revision: "0.8.0", - expectedCommit: "d7c04ae24c16f8ec611b0331596fbc595537abe9", - }, { name: "should resolve a range tag with semantic versioning", revision: "v0.8.*", // it should resolve to v0.8.2 @@ -299,7 +294,7 @@ func TestLsRemote(t *testing.T) { for _, revision := range xfail { _, err := clnt.LsRemote(revision) - assert.ErrorContains(t, err, "Unable to resolve") + assert.ErrorContains(t, err, "unable to resolve") } }) } diff --git a/util/glob/glob.go b/util/glob/glob.go index 0ef7cda28635ac..c96681b2aed936 100644 --- a/util/glob/glob.go +++ b/util/glob/glob.go @@ -5,6 +5,7 @@ import ( log "github.com/sirupsen/logrus" ) +// Match tries to match a text with a given glob pattern. func Match(pattern, text string, separators ...rune) bool { compiledGlob, err := glob.Compile(pattern, separators...) if err != nil { @@ -13,3 +14,13 @@ func Match(pattern, text string, separators ...rune) bool { } return compiledGlob.Match(text) } + +// MatchWithError tries to match a text with a given glob pattern. +// returns error if the glob pattern fails to compile. +func MatchWithError(pattern, text string, separators ...rune) (bool, error) { + compiledGlob, err := glob.Compile(pattern, separators...) + if err != nil { + return false, err + } + return compiledGlob.Match(text), nil +} diff --git a/util/glob/glob_test.go b/util/glob/glob_test.go index a0a3995382c929..201fac2acfaff5 100644 --- a/util/glob/glob_test.go +++ b/util/glob/glob_test.go @@ -3,7 +3,7 @@ package glob import ( "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_Match(t *testing.T) { @@ -24,7 +24,7 @@ func Test_Match(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { res := Match(tt.pattern, tt.input) - assert.Equal(t, tt.result, res) + require.Equal(t, tt.result, res) }) } } @@ -53,7 +53,36 @@ func Test_MatchList(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { res := MatchStringInList(tt.list, tt.input, tt.patternMatch) - assert.Equal(t, tt.result, res) + require.Equal(t, tt.result, res) + }) + } +} + +func Test_MatchWithError(t *testing.T) { + tests := []struct { + name string + input string + pattern string + result bool + expectedErr string + }{ + {"Exact match", "hello", "hello", true, ""}, + {"Non-match exact", "hello", "hell", false, ""}, + {"Long glob match", "hello", "hell*", true, ""}, + {"Short glob match", "hello", "h*", true, ""}, + {"Glob non-match", "hello", "e*", false, ""}, + {"Invalid pattern", "e[[a*", "e[[a*", false, "unexpected end of input"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res, err := MatchWithError(tt.pattern, tt.input) + require.Equal(t, tt.result, res) + if tt.expectedErr == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, tt.expectedErr) + } }) } } diff --git a/util/gpg/gpg_test.go b/util/gpg/gpg_test.go index 377de31f0260bb..f33947dfdcea8f 100644 --- a/util/gpg/gpg_test.go +++ b/util/gpg/gpg_test.go @@ -98,8 +98,7 @@ func Test_GPG_InitializeGnuPG(t *testing.T) { // we need to error out t.Setenv(common.EnvGnuPGHome, f.Name()) err = InitializeGnuPG() - require.Error(t, err) - assert.Contains(t, err.Error(), "does not point to a directory") + assert.ErrorContains(t, err, "does not point to a directory") }) t.Run("Unaccessible GNUPGHOME", func(t *testing.T) { diff --git a/util/grpc/useragent_test.go b/util/grpc/useragent_test.go index bcc3930bec285d..6520acf005221b 100644 --- a/util/grpc/useragent_test.go +++ b/util/grpc/useragent_test.go @@ -35,8 +35,7 @@ func Test_UserAgentEnforcer(t *testing.T) { md := metadata.New(map[string]string{"user-agent": "argo-cd/3.0"}) ctx := metadata.NewIncomingContext(context.Background(), md) err := userAgentEnforcer(ctx, clientName, constraintStr, semverConstraint) - require.Error(t, err) - require.Contains(t, err.Error(), "unsatisfied client version constraint") + require.ErrorContains(t, err, "unsatisfied client version constraint") }) t.Run("Test legacy user-agent", func(t *testing.T) { clientName := "argo-cd" @@ -45,8 +44,7 @@ func Test_UserAgentEnforcer(t *testing.T) { md := metadata.New(map[string]string{"user-agent": "grpc-go/1.15.0"}) ctx := metadata.NewIncomingContext(context.Background(), md) err := userAgentEnforcer(ctx, clientName, constraintStr, semverConstraint) - require.Error(t, err) - require.Contains(t, err.Error(), "unsatisfied client version constraint") + require.ErrorContains(t, err, "unsatisfied client version constraint") }) t.Run("Test invalid version", func(t *testing.T) { clientName := "argo-cd" @@ -55,7 +53,6 @@ func Test_UserAgentEnforcer(t *testing.T) { md := metadata.New(map[string]string{"user-agent": "argo-cd/super"}) ctx := metadata.NewIncomingContext(context.Background(), md) err := userAgentEnforcer(ctx, clientName, constraintStr, semverConstraint) - require.Error(t, err) - require.Contains(t, err.Error(), "could not parse version") + require.ErrorContains(t, err, "could not parse version") }) } diff --git a/util/helm/cmd.go b/util/helm/cmd.go index 6b0e30ed2fe75b..9a5ba948c37797 100644 --- a/util/helm/cmd.go +++ b/util/helm/cmd.go @@ -340,21 +340,39 @@ type TemplateOpts struct { // spec.source.helm.values/valuesObject. ExtraValues pathutil.ResolvedFilePath SkipCrds bool + SkipTests bool } -var ( - re = regexp.MustCompile(`([^\\]),`) - apiVersionsRemover = regexp.MustCompile(`(--api-versions [^ ]+ )+`) -) - func cleanSetParameters(val string) string { // `{}` equal helm list parameters format, so don't escape `,`. if strings.HasPrefix(val, `{`) && strings.HasSuffix(val, `}`) { return val } - return re.ReplaceAllString(val, `$1\,`) + + val = replaceAllWithLookbehind(val, ',', `\,`, '\\') + return val +} + +func replaceAllWithLookbehind(val string, old rune, new string, lookbehind rune) string { + var result strings.Builder + var prevR rune + for _, r := range val { + if r == old { + if prevR != lookbehind { + result.WriteString(new) + } else { + result.WriteRune(old) + } + } else { + result.WriteRune(r) + } + prevR = r + } + return result.String() } +var apiVersionsRemover = regexp.MustCompile(`(--api-versions [^ ]+ )+`) + func (c *Cmd) template(chartPath string, opts *TemplateOpts) (string, string, error) { if callback, err := cleanupChartLockFile(filepath.Clean(path.Join(c.WorkDir, chartPath))); err == nil { defer callback() @@ -391,6 +409,9 @@ func (c *Cmd) template(chartPath string, opts *TemplateOpts) (string, string, er if !opts.SkipCrds { args = append(args, "--include-crds") } + if opts.SkipTests { + args = append(args, "--skip-tests") + } out, command, err := c.run(args...) if err != nil { diff --git a/util/helm/helm_test.go b/util/helm/helm_test.go index 8468b9f36624b7..2d72a87745f253 100644 --- a/util/helm/helm_test.go +++ b/util/helm/helm_test.go @@ -166,6 +166,8 @@ func TestHelmArgCleaner(t *testing.T) { `not, clean`: `not\, clean`, `a\,b,c`: `a\,b\,c`, `{a,b,c}`: `{a,b,c}`, + `,,,,,\,`: `\,\,\,\,\,\,`, + `\,,\\,,`: `\,\,\\,\,`, } { cleaned := cleanSetParameters(input) assert.Equal(t, expected, cleaned) @@ -233,3 +235,20 @@ func TestSkipCrds(t *testing.T) { require.NoError(t, err) require.Empty(t, objs) } + +func TestSkipTests(t *testing.T) { + h, err := NewHelmApp("./testdata/tests", nil, false, "", "", "", false) + require.NoError(t, err) + + objs, err := template(h, &TemplateOpts{SkipTests: false}) + require.NoError(t, err) + require.Len(t, objs, 1) + + objs, err = template(h, &TemplateOpts{}) + require.NoError(t, err) + require.Len(t, objs, 1) + + objs, err = template(h, &TemplateOpts{SkipTests: true}) + require.NoError(t, err) + require.Empty(t, objs) +} diff --git a/util/helm/testdata/tests/Chart.yaml b/util/helm/testdata/tests/Chart.yaml new file mode 100644 index 00000000000000..2b93d488735d10 --- /dev/null +++ b/util/helm/testdata/tests/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v1 +version: 1.0.0 +name: tests diff --git a/util/helm/testdata/tests/templates/tests/test-pod.yaml b/util/helm/testdata/tests/templates/tests/test-pod.yaml new file mode 100644 index 00000000000000..ea9fb339f101dd --- /dev/null +++ b/util/helm/testdata/tests/templates/tests/test-pod.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: busybox + command: ['sh', '-c', 'echo Test'] \ No newline at end of file diff --git a/util/io/files/tar_test.go b/util/io/files/tar_test.go index f8b140b5dc6582..a9bb9edb5250c9 100644 --- a/util/io/files/tar_test.go +++ b/util/io/files/tar_test.go @@ -195,8 +195,7 @@ func TestUntgz(t *testing.T) { err := files.Untgz(destDir, tgzFile, math.MaxInt64, false) // then - require.Error(t, err) - assert.Contains(t, err.Error(), "illegal filepath in symlink") + assert.ErrorContains(t, err, "illegal filepath in symlink") }) t.Run("preserves file mode", func(t *testing.T) { diff --git a/util/io/path/resolved_test.go b/util/io/path/resolved_test.go index deecbec31055a9..36472e8788716c 100644 --- a/util/io/path/resolved_test.go +++ b/util/io/path/resolved_test.go @@ -111,8 +111,7 @@ func Test_resolveFilePath(t *testing.T) { }) t.Run("Error on path resolving outside repository root", func(t *testing.T) { p, remote, err := ResolveValueFilePathOrUrl("/foo/bar", "/foo", "baz/../../../bim.yaml", allowedRemoteProtocols) - require.Error(t, err) - assert.Contains(t, err.Error(), "outside repository root") + require.ErrorContains(t, err, "outside repository root") assert.False(t, remote) assert.Equal(t, "", string(p)) }) @@ -152,29 +151,25 @@ func Test_resolveFilePath(t *testing.T) { }) t.Run("Overlapping root prefix without trailing slash", func(t *testing.T) { p, remote, err := ResolveValueFilePathOrUrl(".", "/foo", "../foo2/baz.yaml", allowedRemoteProtocols) - require.Error(t, err) - assert.Contains(t, err.Error(), "outside repository root") + require.ErrorContains(t, err, "outside repository root") assert.False(t, remote) assert.Equal(t, "", string(p)) }) t.Run("Overlapping root prefix with trailing slash", func(t *testing.T) { p, remote, err := ResolveValueFilePathOrUrl(".", "/foo/", "../foo2/baz.yaml", allowedRemoteProtocols) - require.Error(t, err) - assert.Contains(t, err.Error(), "outside repository root") + require.ErrorContains(t, err, "outside repository root") assert.False(t, remote) assert.Equal(t, "", string(p)) }) t.Run("Garbage input as values file", func(t *testing.T) { p, remote, err := ResolveValueFilePathOrUrl(".", "/foo/", "kfdj\\ks&&&321209.,---e32908923%$ยง!\"", allowedRemoteProtocols) - require.Error(t, err) - assert.Contains(t, err.Error(), "outside repository root") + require.ErrorContains(t, err, "outside repository root") assert.False(t, remote) assert.Equal(t, "", string(p)) }) t.Run("NUL-byte path input as values file", func(t *testing.T) { p, remote, err := ResolveValueFilePathOrUrl(".", "/foo/", "\000", allowedRemoteProtocols) - require.Error(t, err) - assert.Contains(t, err.Error(), "outside repository root") + require.ErrorContains(t, err, "outside repository root") assert.False(t, remote) assert.Equal(t, "", string(p)) }) diff --git a/util/kube/kube.go b/util/kube/kube.go index a982460e331e62..aa96dfc4d3fff6 100644 --- a/util/kube/kube.go +++ b/util/kube/kube.go @@ -161,6 +161,30 @@ func RemoveLabel(un *unstructured.Unstructured, key string) error { return nil } +// RemoveAnnotation removes annotation with the specified name +func RemoveAnnotation(un *unstructured.Unstructured, key string) error { + annotations, err := nestedNullableStringMap(un.Object, "metadata", "annotations") + if err != nil { + return fmt.Errorf("failed to get annotations for %s %s/%s: %w", un.GroupVersionKind().String(), un.GetNamespace(), un.GetName(), err) + } + if annotations == nil { + return nil + } + + for k := range annotations { + if k == key { + delete(annotations, k) + if len(annotations) == 0 { + un.SetAnnotations(nil) + } else { + un.SetAnnotations(annotations) + } + break + } + } + return nil +} + // nestedNullableStringMap returns a copy of map[string]string value of a nested field. // Returns false if value is not found and an error if not one of map[string]interface{} or nil, or contains non-string values in the map. func nestedNullableStringMap(obj map[string]interface{}, fields ...string) (map[string]string, error) { diff --git a/util/lua/lua.go b/util/lua/lua.go index b255836b5434e5..2832025c79bca8 100644 --- a/util/lua/lua.go +++ b/util/lua/lua.go @@ -141,13 +141,11 @@ func (vm VM) GetHealthScript(obj *unstructured.Unstructured) (string, bool, erro return script.HealthLua, script.UseOpenLibs, nil } - // if not found as is, perhaps it matches wildcard entries in the configmap - wildcardKey := GetWildcardConfigMapKey(vm, obj.GroupVersionKind()) + // if not found as is, perhaps it matches a wildcard entry in the configmap + getWildcardHealthOverride, useOpenLibs := getWildcardHealthOverrideLua(vm.ResourceOverrides, obj.GroupVersionKind()) - if wildcardKey != "" { - if wildcardScript, ok := vm.ResourceOverrides[wildcardKey]; ok && wildcardScript.HealthLua != "" { - return wildcardScript.HealthLua, wildcardScript.UseOpenLibs, nil - } + if getWildcardHealthOverride != "" { + return getWildcardHealthOverride, useOpenLibs, nil } // if not found in the ResourceOverrides at all, search it as is in the built-in scripts @@ -426,15 +424,18 @@ func GetConfigMapKey(gvk schema.GroupVersionKind) string { return fmt.Sprintf("%s/%s", gvk.Group, gvk.Kind) } -func GetWildcardConfigMapKey(vm VM, gvk schema.GroupVersionKind) string { +// getWildcardHealthOverrideLua returns the first encountered resource override which matches the wildcard and has a +// non-empty health script. Having multiple wildcards with non-empty health checks that can match the GVK is +// non-deterministic. +func getWildcardHealthOverrideLua(overrides map[string]appv1.ResourceOverride, gvk schema.GroupVersionKind) (string, bool) { gvkKeyToMatch := GetConfigMapKey(gvk) - for key := range vm.ResourceOverrides { - if glob.Match(key, gvkKeyToMatch) { - return key + for key, override := range overrides { + if glob.Match(key, gvkKeyToMatch) && override.HealthLua != "" { + return override.HealthLua, override.UseOpenLibs } } - return "" + return "", false } func (vm VM) getPredefinedLuaScripts(objKey string, scriptFile string) (string, error) { diff --git a/util/lua/lua_test.go b/util/lua/lua_test.go index 4686d58ac128ec..40cbfa9688f780 100644 --- a/util/lua/lua_test.go +++ b/util/lua/lua_test.go @@ -684,8 +684,7 @@ func TestExecuteNewStyleActionMixedOperationsFailure(t *testing.T) { testObj := StrToUnstructured(cronJobObjYaml) vm := VM{} _, err := vm.ExecuteResourceAction(testObj, createMixedOperationActionLuaFailing) - require.Error(t, err) - assert.Contains(t, err.Error(), "unsupported operation") + assert.ErrorContains(t, err, "unsupported operation") } func TestExecuteResourceActionNonTableReturn(t *testing.T) { @@ -787,6 +786,11 @@ return hs` const healthWildcardOverrideScript = ` hs = {} hs.status = "Healthy" + return hs` + + const healthWildcardOverrideScriptUnhealthy = ` + hs = {} + hs.status = "UnHealthy" return hs` getHealthOverride := func(openLibs bool) ResourceHealthOverrides { @@ -804,6 +808,21 @@ return hs` }, } + getMultipleWildcardHealthOverrides := ResourceHealthOverrides{ + "*.aws.crossplane.io/*": appv1.ResourceOverride{ + HealthLua: "", + }, + "*.aws*": appv1.ResourceOverride{ + HealthLua: healthWildcardOverrideScriptUnhealthy, + }, + } + + getBaseWildcardHealthOverrides := ResourceHealthOverrides{ + "*/*": appv1.ResourceOverride{ + HealthLua: "", + }, + } + t.Run("Enable Lua standard lib", func(t *testing.T) { testObj := StrToUnstructured(testSA) overrides := getHealthOverride(true) @@ -837,6 +856,23 @@ return hs` assert.Equal(t, expectedStatus, status) }) + t.Run("Get resource health for wildcard override with non-empty health.lua", func(t *testing.T) { + testObj := StrToUnstructured(ec2AWSCrossplaneObjJson) + overrides := getMultipleWildcardHealthOverrides + status, err := overrides.GetResourceHealth(testObj) + require.NoError(t, err) + expectedStatus := &health.HealthStatus{Status: "Unknown", Message: "Lua returned an invalid health status"} + assert.Equal(t, expectedStatus, status) + }) + + t.Run("Get resource health for */* override with empty health.lua", func(t *testing.T) { + testObj := StrToUnstructured(ec2AWSCrossplaneObjJson) + overrides := getBaseWildcardHealthOverrides + status, err := overrides.GetResourceHealth(testObj) + require.NoError(t, err) + assert.Nil(t, status) + }) + t.Run("Resource health for wildcard override not found", func(t *testing.T) { testObj := StrToUnstructured(testSA) overrides := getWildcardHealthOverride diff --git a/util/session/sessionmanager_test.go b/util/session/sessionmanager_test.go index 7a3d5a65f5f5a1..7ff3aa93aeba6f 100644 --- a/util/session/sessionmanager_test.go +++ b/util/session/sessionmanager_test.go @@ -160,8 +160,7 @@ func TestSessionManager_AdminToken_Deactivated(t *testing.T) { } _, _, err = mgr.Parse(token) - require.Error(t, err) - assert.Contains(t, err.Error(), "account admin is disabled") + assert.ErrorContains(t, err, "account admin is disabled") } func TestSessionManager_AdminToken_LoginCapabilityDisabled(t *testing.T) { @@ -174,8 +173,7 @@ func TestSessionManager_AdminToken_LoginCapabilityDisabled(t *testing.T) { } _, _, err = mgr.Parse(token) - require.Error(t, err) - assert.Contains(t, err.Error(), "account admin does not have 'apiKey' capability") + assert.ErrorContains(t, err, "account admin does not have 'apiKey' capability") } func TestSessionManager_ProjectToken(t *testing.T) { @@ -218,9 +216,7 @@ func TestSessionManager_ProjectToken(t *testing.T) { require.NoError(t, err) _, _, err = mgr.Parse(jwtToken) - require.Error(t, err) - - assert.Contains(t, err.Error(), "does not exist in project 'default'") + assert.ErrorContains(t, err, "does not exist in project 'default'") }) } @@ -538,8 +534,7 @@ func TestMaxUsernameLength(t *testing.T) { settingsMgr := settings.NewSettingsManager(context.Background(), getKubeClient("password", true), "argocd") mgr := newSessionManager(settingsMgr, getProjLister(), NewUserStateStorage(nil)) err := mgr.VerifyUsernamePassword(username, "password") - require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf(usernameTooLongError, maxUsernameLength)) + assert.ErrorContains(t, err, fmt.Sprintf(usernameTooLongError, maxUsernameLength)) } func TestMaxCacheSize(t *testing.T) { diff --git a/util/settings/settings.go b/util/settings/settings.go index 7d192d9cb9461f..754bc29cb55ae5 100644 --- a/util/settings/settings.go +++ b/util/settings/settings.go @@ -451,6 +451,8 @@ const ( settingsApplicationInstanceLabelKey = "application.instanceLabelKey" // settingsResourceTrackingMethodKey is the key to configure tracking method for application resources settingsResourceTrackingMethodKey = "application.resourceTrackingMethod" + // settingsInstallationID holds the key for the instance installation ID + settingsInstallationID = "installationID" // resourcesCustomizationsKey is the key to the map of resource overrides resourceCustomizationsKey = "resource.customizations" // resourceExclusions is the key to the list of excluded resources @@ -535,6 +537,9 @@ const ( const ( // default max webhook payload size is 1GB defaultMaxWebhookPayloadSize = int64(1) * 1024 * 1024 * 1024 + + // application sync with impersonation feature is disabled by default. + defaultImpersonationEnabledFlag = false ) var sourceTypeToEnableGenerationKey = map[v1alpha1.ApplicationSourceType]string{ @@ -792,6 +797,14 @@ func (mgr *SettingsManager) GetTrackingMethod() (string, error) { return argoCDCM.Data[settingsResourceTrackingMethodKey], nil } +func (mgr *SettingsManager) GetInstallationID() (string, error) { + argoCDCM, err := mgr.getConfigMap() + if err != nil { + return "", err + } + return argoCDCM.Data[settingsInstallationID], nil +} + func (mgr *SettingsManager) GetPasswordPattern() (string, error) { argoCDCM, err := mgr.getConfigMap() if err != nil { @@ -2336,11 +2349,11 @@ func (mgr *SettingsManager) GetMaxWebhookPayloadSize() int64 { return maxPayloadSizeMB * 1024 * 1024 } -// GetIsImpersonationEnabled returns true if application sync with impersonation feature is enabled in argocd-cm configmap -func (mgr *SettingsManager) IsImpersonationEnabled() bool { +// IsImpersonationEnabled returns true if application sync with impersonation feature is enabled in argocd-cm configmap +func (mgr *SettingsManager) IsImpersonationEnabled() (bool, error) { cm, err := mgr.getConfigMap() if err != nil { - return false + return defaultImpersonationEnabledFlag, fmt.Errorf("error checking %s property in configmap: %w", impersonationEnabledKey, err) } - return cm.Data[impersonationEnabledKey] == "true" + return cm.Data[impersonationEnabledKey] == "true", nil } diff --git a/util/settings/settings_test.go b/util/settings/settings_test.go index 94d5eeccf80215..9391ac5458137f 100644 --- a/util/settings/settings_test.go +++ b/util/settings/settings_test.go @@ -1221,8 +1221,7 @@ func Test_GetTLSConfiguration(t *testing.T) { ) settingsManager := NewSettingsManager(context.Background(), kubeClient, "default") settings, err := settingsManager.GetSettings() - require.Error(t, err) - assert.Contains(t, err.Error(), "could not read from secret") + require.ErrorContains(t, err, "could not read from secret") assert.NotNil(t, settings) }) t.Run("No external TLS secret", func(t *testing.T) { @@ -1725,3 +1724,46 @@ func TestRedirectAdditionalURLs(t *testing.T) { }) } } + +func TestIsImpersonationEnabled(t *testing.T) { + // When there is no argocd-cm itself, + // Then IsImpersonationEnabled() must return false (default value) and an error with appropriate error message. + kubeClient := fake.NewSimpleClientset() + settingsManager := NewSettingsManager(context.Background(), kubeClient, "default") + featureFlag, err := settingsManager.IsImpersonationEnabled() + require.False(t, featureFlag, + "with no argocd-cm config map, IsImpersonationEnabled() must return return false (default value)") + require.ErrorContains(t, err, "configmap \"argocd-cm\" not found", + "with no argocd-cm config map, IsImpersonationEnabled() must return an error") + + // When there is no impersonation feature flag present in the argocd-cm, + // Then IsImpersonationEnabled() must return false (default value) and nil error. + _, settingsManager = fixtures(map[string]string{}) + featureFlag, err = settingsManager.IsImpersonationEnabled() + require.False(t, featureFlag, + "with empty argocd-cm config map, IsImpersonationEnabled() must return false (default value)") + require.NoError(t, err, + "with empty argocd-cm config map, IsImpersonationEnabled() must not return any error") + + // When user disables the feature explicitly, + // Then IsImpersonationEnabled() must return false and nil error. + _, settingsManager = fixtures(map[string]string{ + "application.sync.impersonation.enabled": "false", + }) + featureFlag, err = settingsManager.IsImpersonationEnabled() + require.False(t, featureFlag, + "when user enables the flag in argocd-cm config map, IsImpersonationEnabled() must return user set value") + require.NoError(t, err, + "when user enables the flag in argocd-cm config map, IsImpersonationEnabled() must not return any error") + + // When user enables the feature explicitly, + // Then IsImpersonationEnabled() must return true and nil error. + _, settingsManager = fixtures(map[string]string{ + "application.sync.impersonation.enabled": "true", + }) + featureFlag, err = settingsManager.IsImpersonationEnabled() + require.True(t, featureFlag, + "when user enables the flag in argocd-cm config map, IsImpersonationEnabled() must return user set value") + require.NoError(t, err, + "when user enables the flag in argocd-cm config map, IsImpersonationEnabled() must not return any error") +} diff --git a/util/tls/tls_test.go b/util/tls/tls_test.go index 69f7f7f60ef7f9..d164c68b233f13 100644 --- a/util/tls/tls_test.go +++ b/util/tls/tls_test.go @@ -187,22 +187,19 @@ func TestGenerate(t *testing.T) { t.Run("Invalid: No hosts specified", func(t *testing.T) { opts := CertOptions{Hosts: []string{}, Organization: "Acme", ValidFrom: time.Now(), ValidFor: 10 * time.Hour} _, _, err := generate(opts) - require.Error(t, err) - assert.Contains(t, err.Error(), "hosts not supplied") + assert.ErrorContains(t, err, "hosts not supplied") }) t.Run("Invalid: No organization specified", func(t *testing.T) { opts := CertOptions{Hosts: []string{"localhost"}, Organization: "", ValidFrom: time.Now(), ValidFor: 10 * time.Hour} _, _, err := generate(opts) - require.Error(t, err) - assert.Contains(t, err.Error(), "organization not supplied") + assert.ErrorContains(t, err, "organization not supplied") }) t.Run("Invalid: Unsupported curve specified", func(t *testing.T) { opts := CertOptions{Hosts: []string{"localhost"}, Organization: "Acme", ECDSACurve: "Curve?", ValidFrom: time.Now(), ValidFor: 10 * time.Hour} _, _, err := generate(opts) - require.Error(t, err) - assert.Contains(t, err.Error(), "Unrecognized elliptic curve") + assert.ErrorContains(t, err, "Unrecognized elliptic curve") }) for _, curve := range []string{"P224", "P256", "P384", "P521"} { diff --git a/util/webhook/webhook.go b/util/webhook/webhook.go index 5f18a650eb97d9..df5c1fecc12735 100644 --- a/util/webhook/webhook.go +++ b/util/webhook/webhook.go @@ -36,6 +36,7 @@ import ( type settingsSource interface { GetAppInstanceLabelKey() (string, error) GetTrackingMethod() (string, error) + GetInstallationID() (string, error) } // https://www.rfc-editor.org/rfc/rfc3986#section-3.2.1 @@ -273,6 +274,11 @@ func (a *ArgoCDWebhookHandler) HandleEvent(payload interface{}) { return } + installationID, err := a.settingsSrc.GetInstallationID() + if err != nil { + log.Warnf("Failed to get installation ID: %v", err) + return + } trackingMethod, err := a.settingsSrc.GetTrackingMethod() if err != nil { log.Warnf("Failed to get trackingMethod: %v", err) @@ -313,7 +319,7 @@ func (a *ArgoCDWebhookHandler) HandleEvent(payload interface{}) { // No need to refresh multiple times if multiple sources match. break } else if change.shaBefore != "" && change.shaAfter != "" { - if err := a.storePreviouslyCachedManifests(&app, change, trackingMethod, appInstanceLabelKey); err != nil { + if err := a.storePreviouslyCachedManifests(&app, change, trackingMethod, appInstanceLabelKey, installationID); err != nil { log.Warnf("Failed to store cached manifests of previous revision for app '%s': %v", app.Name, err) } } @@ -343,7 +349,7 @@ func getWebUrlRegex(webURL string) (*regexp.Regexp, error) { return repoRegexp, nil } -func (a *ArgoCDWebhookHandler) storePreviouslyCachedManifests(app *v1alpha1.Application, change changeInfo, trackingMethod string, appInstanceLabelKey string) error { +func (a *ArgoCDWebhookHandler) storePreviouslyCachedManifests(app *v1alpha1.Application, change changeInfo, trackingMethod string, appInstanceLabelKey string, installationID string) error { err := argo.ValidateDestination(context.Background(), &app.Spec.Destination, a.db) if err != nil { return fmt.Errorf("error validating destination: %w", err) @@ -369,7 +375,7 @@ func (a *ArgoCDWebhookHandler) storePreviouslyCachedManifests(app *v1alpha1.Appl source := app.Spec.GetSource() cache.LogDebugManifestCacheKeyFields("moving manifests cache", "webhook app revision changed", change.shaBefore, &source, refSources, &clusterInfo, app.Spec.Destination.Namespace, trackingMethod, appInstanceLabelKey, app.Name, nil) - if err := a.repoCache.SetNewRevisionManifests(change.shaAfter, change.shaBefore, &source, refSources, &clusterInfo, app.Spec.Destination.Namespace, trackingMethod, appInstanceLabelKey, app.Name, nil); err != nil { + if err := a.repoCache.SetNewRevisionManifests(change.shaAfter, change.shaBefore, &source, refSources, &clusterInfo, app.Spec.Destination.Namespace, trackingMethod, appInstanceLabelKey, app.Name, nil, installationID); err != nil { return fmt.Errorf("error setting new revision manifests: %w", err) } diff --git a/util/webhook/webhook_test.go b/util/webhook/webhook_test.go index 82cc353a8364c6..61f348f4d9a723 100644 --- a/util/webhook/webhook_test.go +++ b/util/webhook/webhook_test.go @@ -49,6 +49,10 @@ func (f fakeSettingsSrc) GetTrackingMethod() (string, error) { return "", nil } +func (f fakeSettingsSrc) GetInstallationID() (string, error) { + return "", nil +} + type reactorDef struct { verb string resource string