Compare commits

...

7 Commits

Author SHA1 Message Date
github-actions[bot]
f5d63a5c77 Bump version to 2.10.4 (#17557)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2024-03-18 04:03:42 -04:00
Dan Garfield
ce04dc5c6f Merge pull request from GHSA-6v85-wr92-q4p7
* fix: Fix concurrency issue in session manager

Signed-off-by: jannfis <jann@mistrust.net>

* Add note that modification to the map must be done in a thread safe manner

* chore: fix linter issues

Signed-off-by: pashakostohrys <pavel@codefresh.io>

---------

Signed-off-by: jannfis <jann@mistrust.net>
Signed-off-by: pashakostohrys <pavel@codefresh.io>
Co-authored-by: jannfis <jann@mistrust.net>
Co-authored-by: pashakostohrys <pavel@codefresh.io>
2024-03-18 03:59:06 -04:00
pasha-codefresh
cebb6538f7 Merge pull request from GHSA-2vgg-9h6w-m454
* feat: pick random user and exclude admin user and current user from deletion candidates

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: increase default max cache size

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* add nil protection

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* Update util/session/sessionmanager.go

Signed-off-by: Dan Garfield <dan@codefresh.io>

Signed-off-by: Dan Garfield <dan@codefresh.io>

* chore: fix linter issues

Signed-off-by: pashakostohrys <pavel@codefresh.io>

---------

Signed-off-by: pashakostohrys <pavel@codefresh.io>
Signed-off-by: Dan Garfield <dan@codefresh.io>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2024-03-18 03:58:18 -04:00
gcp-cherry-pick-bot[bot]
ab7e45da13 fix(notifications): Helm.GetParameterValueByName should take helm.parametes first (#17472) (#17512)
* fix: Helm.GetParameterValueByName should take helm.parametes first



* fix linters



---------

Signed-off-by: pashakostohrys <pavel@codefresh.io>
Co-authored-by: pasha-codefresh <pavel@codefresh.io>
2024-03-16 20:52:45 +02:00
gcp-cherry-pick-bot[bot]
a8ae929d55 fix: registry argument to be only the host instead full URL (#17381) (#17534)
Signed-off-by: Pablo Aguilar <pablo.aguilar@outlook.com.br>
Co-authored-by: Pablo Aguilar <pablo.aguilar@outlook.com.br>
2024-03-15 17:32:04 -04:00
gcp-cherry-pick-bot[bot]
f3fdaa7eab fix(ui): add confirmation box in resource summary delete action (#17485) (#17545)
Signed-off-by: ashutosh16 <11219262+ashutosh16@users.noreply.github.com>
Co-authored-by: AS <11219262+ashutosh16@users.noreply.github.com>
2024-03-15 12:06:55 -04:00
gcp-cherry-pick-bot[bot]
0b4659c046 chore(deps): upgrade helm to 3.14.3 (#17531) (#17533)
* chore(deps): upgrade helm to 3.14.3



* chore(deps): upgrade helm to 3.14.3



---------

Signed-off-by: David Bunn <david.bunn@prodigygame.com>
Co-authored-by: David Bunn <david.bunn@prodigygame.com>
2024-03-14 14:04:55 -04:00
28 changed files with 304 additions and 102 deletions

View File

@@ -1 +1 @@
2.10.3
2.10.4

View File

@@ -13,4 +13,4 @@ before enabling `managedNamespaceMetadata` on an existing namespace.
## Upgraded Helm Version
Note that bundled Helm version has been upgraded from 3.13.2 to 3.14.2.
Note that bundled Helm version has been upgraded from 3.13.2 to 3.14.3.

View File

@@ -0,0 +1 @@
4d5d01a94c7d6b07e71690dc1988bf3229680284c87f4242d28c6f1cc99653be helm-v3.14.3-darwin-amd64.tar.gz

View File

@@ -0,0 +1 @@
dff794152b62b7c1a9ff615d510f8657bcd7a3727c668e0d9d4955f70d5f7573 helm-v3.14.3-darwin-arm64.tar.gz

View File

@@ -0,0 +1 @@
3c90f24e180f8c207b8a18e5ec82cb0fa49858a7a0a86e4ed52a98398681e00b helm-v3.14.3-linux-amd64.tar.gz

View File

@@ -0,0 +1 @@
85e1573e76fa60af14ba7e9ec75db2129b6884203be866893fa0b3f7e41ccd5e helm-v3.14.3-linux-arm64.tar.gz

View File

@@ -0,0 +1 @@
aab121ca470e2a502cda849a9b3e92eeb9a32e213b0f0a79a95a04e375d26ce7 helm-v3.14.3-linux-ppc64le.tar.gz

View File

@@ -0,0 +1 @@
d64fa8aced3244b549377741dc4e2db8109e5270c0723c11b547a9da5f99ad43 helm-v3.14.3-linux-s390x.tar.gz

View File

@@ -11,7 +11,7 @@
# Use ./hack/installers/checksums/add-helm-checksums.sh and
# add-kustomize-checksums.sh to help download checksums.
###############################################################################
helm3_version=3.14.2
helm3_version=3.14.3
kubectl_version=1.17.8
kubectx_version=0.6.3
kustomize5_version=5.2.1

View File

@@ -5,7 +5,7 @@ kind: Kustomization
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.10.3
newTag: v2.10.4
resources:
- ./application-controller
- ./dex

View File

@@ -21026,7 +21026,7 @@ spec:
key: applicationsetcontroller.enable.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -21350,7 +21350,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -21402,7 +21402,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -21663,7 +21663,7 @@ spec:
key: controller.diff.server.side
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -12,4 +12,4 @@ resources:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.10.3
newTag: v2.10.4

View File

@@ -12,7 +12,7 @@ patches:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.10.3
newTag: v2.10.4
resources:
- ../../base/application-controller
- ../../base/applicationset-controller

View File

@@ -22389,7 +22389,7 @@ spec:
key: applicationsetcontroller.enable.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -22512,7 +22512,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -22594,7 +22594,7 @@ spec:
key: notificationscontroller.selfservice.enabled
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -22949,7 +22949,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -23001,7 +23001,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -23320,7 +23320,7 @@ spec:
key: server.api.content.types
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -23608,7 +23608,7 @@ spec:
key: controller.diff.server.side
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -1668,7 +1668,7 @@ spec:
key: applicationsetcontroller.enable.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1791,7 +1791,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1873,7 +1873,7 @@ spec:
key: notificationscontroller.selfservice.enabled
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -2228,7 +2228,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2280,7 +2280,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2599,7 +2599,7 @@ spec:
key: server.api.content.types
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2887,7 +2887,7 @@ spec:
key: controller.diff.server.side
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -21484,7 +21484,7 @@ spec:
key: applicationsetcontroller.enable.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -21607,7 +21607,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -21689,7 +21689,7 @@ spec:
key: notificationscontroller.selfservice.enabled
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -21995,7 +21995,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -22047,7 +22047,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -22364,7 +22364,7 @@ spec:
key: server.api.content.types
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -22652,7 +22652,7 @@ spec:
key: controller.diff.server.side
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -763,7 +763,7 @@ spec:
key: applicationsetcontroller.enable.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -886,7 +886,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -968,7 +968,7 @@ spec:
key: notificationscontroller.selfservice.enabled
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1274,7 +1274,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1326,7 +1326,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -1643,7 +1643,7 @@ spec:
key: server.api.content.types
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -1931,7 +1931,7 @@ spec:
key: controller.diff.server.side
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.10.3
image: quay.io/argoproj/argocd:v2.10.4
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -38,12 +38,12 @@ type terminalHandler struct {
allowedShells []string
namespace string
enabledNamespaces []string
sessionManager util_session.SessionManager
sessionManager *util_session.SessionManager
}
// NewHandler returns a new terminal handler.
func NewHandler(appLister applisters.ApplicationLister, namespace string, enabledNamespaces []string, db db.ArgoDB, enf *rbac.Enforcer, cache *servercache.Cache,
appResourceTree AppResourceTreeFn, allowedShells []string, sessionManager util_session.SessionManager) *terminalHandler {
appResourceTree AppResourceTreeFn, allowedShells []string, sessionManager *util_session.SessionManager) *terminalHandler {
return &terminalHandler{
appLister: appLister,
db: db,

View File

@@ -37,7 +37,7 @@ type terminalSession struct {
tty bool
readLock sync.Mutex
writeLock sync.Mutex
sessionManager util_session.SessionManager
sessionManager *util_session.SessionManager
token *string
}
@@ -48,7 +48,7 @@ func getToken(r *http.Request) (string, error) {
}
// newTerminalSession create terminalSession
func newTerminalSession(w http.ResponseWriter, r *http.Request, responseHeader http.Header, sessionManager util_session.SessionManager) (*terminalSession, error) {
func newTerminalSession(w http.ResponseWriter, r *http.Request, responseHeader http.Header, sessionManager *util_session.SessionManager) (*terminalSession, error) {
token, err := getToken(r)
if err != nil {
return nil, err

View File

@@ -997,7 +997,7 @@ func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int, grpcWebHandl
}
mux.Handle("/api/", handler)
terminal := application.NewHandler(a.appLister, a.Namespace, a.ApplicationNamespaces, a.db, a.enf, a.Cache, appResourceTreeFn, a.settings.ExecShells, *a.sessionMgr).
terminal := application.NewHandler(a.appLister, a.Namespace, a.ApplicationNamespaces, a.db, a.enf, a.Cache, appResourceTreeFn, a.settings.ExecShells, a.sessionMgr).
WithFeatureFlagMiddleware(a.settingsMgr.GetSettings)
th := util_session.WithAuthMiddleware(a.DisableAuth, a.sessionMgr, terminal)
mux.Handle("/terminal", th)

View File

@@ -325,7 +325,12 @@ export const deletePodAction = async (pod: appModels.Pod, appContext: AppContext
};
export const deletePopup = async (ctx: ContextApis, resource: ResourceTreeNode, application: appModels.Application, appChanged?: BehaviorSubject<appModels.Application>) => {
const isManaged = !!resource.status;
function isTopLevelResource(res: ResourceTreeNode, app: appModels.Application): boolean {
const uniqRes = `/${res.namespace}/${res.group}/${res.kind}/${res.name}`;
return app.status.resources.some(resStatus => `/${resStatus.namespace}/${resStatus.group}/${resStatus.kind}/${resStatus.name}` === uniqRes);
}
const isManaged = isTopLevelResource(resource, application);
const deleteOptions = {
option: 'foreground'
};

View File

@@ -8,7 +8,6 @@ import (
"encoding/json"
"errors"
"fmt"
executil "github.com/argoproj/argo-cd/v2/util/exec"
"io"
"net/http"
"net/url"
@@ -19,6 +18,8 @@ import (
"strings"
"time"
executil "github.com/argoproj/argo-cd/v2/util/exec"
"github.com/argoproj/pkg/sync"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
@@ -34,6 +35,8 @@ import (
var (
globalLock = sync.NewKeyLock()
indexLock = sync.NewKeyLock()
OCINotEnabledErr = errors.New("could not perform the action when oci is not enabled")
)
type Creds struct {
@@ -401,6 +404,10 @@ func getIndexURL(rawURL string) (string, error) {
}
func (c *nativeHelmChart) GetTags(chart string, noCache bool) (*TagsList, error) {
if !c.enableOci {
return nil, OCINotEnabledErr
}
tagsURL := strings.Replace(fmt.Sprintf("%s/%s", c.repoURL, chart), "https://", "", 1)
indexLock.Lock(tagsURL)
defer indexLock.Unlock(tagsURL)
@@ -428,10 +435,12 @@ func (c *nativeHelmChart) GetTags(chart string, noCache bool) (*TagsList, error)
TLSClientConfig: tlsConf,
DisableKeepAlives: true,
}}
repoHost, _, _ := strings.Cut(tagsURL, "/")
repo.Client = &auth.Client{
Client: client,
Cache: nil,
Credential: auth.StaticCredential(c.repoURL, auth.Credential{
Credential: auth.StaticCredential(repoHost, auth.Credential{
Username: c.creds.Username,
Password: c.creds.Password,
}),

View File

@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"math"
"net/url"
"os"
"strings"
"testing"
@@ -159,41 +160,129 @@ func TestGetIndexURL(t *testing.T) {
}
func TestGetTagsFromUrl(t *testing.T) {
t.Run("should return tags correctly while following the link header", func(t *testing.T) {
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
t.Logf("called %s", r.URL.Path)
responseTags := TagsList{}
w.Header().Set("Content-Type", "application/json")
if !strings.Contains(r.URL.String(), "token") {
w.Header().Set("Link", fmt.Sprintf("<https://%s%s?token=next-token>; rel=next", r.Host, r.URL.Path))
responseTags.Tags = []string{"first"}
} else {
responseTags.Tags = []string{
"second",
"2.8.0",
"2.8.0-prerelease",
"2.8.0_build",
"2.8.0-prerelease_build",
"2.8.0-prerelease.1_build.1234",
}
}
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(responseTags)
if err != nil {
t.Fatal(err)
}
}))
client := NewClient(server.URL, Creds{InsecureSkipVerify: true}, true, "")
tags, err := client.GetTags("mychart", true)
assert.NoError(t, err)
assert.ElementsMatch(t, tags.Tags, []string{
"first",
"second",
"2.8.0",
"2.8.0-prerelease",
"2.8.0+build",
"2.8.0-prerelease+build",
"2.8.0-prerelease.1+build.1234",
})
})
t.Run("should return an error not when oci is not enabled", func(t *testing.T) {
client := NewClient("example.com", Creds{}, false, "")
_, err := client.GetTags("my-chart", true)
assert.ErrorIs(t, OCINotEnabledErr, err)
})
}
func TestGetTagsFromURLPrivateRepoAuthentication(t *testing.T) {
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
t.Logf("called %s", r.URL.Path)
responseTags := TagsList{}
w.Header().Set("Content-Type", "application/json")
if !strings.Contains(r.URL.String(), "token") {
w.Header().Set("Link", fmt.Sprintf("<https://%s%s?token=next-token>; rel=next", r.Host, r.URL.Path))
responseTags.Tags = []string{"first"}
} else {
responseTags.Tags = []string{
"second",
authorization := r.Header.Get("Authorization")
if authorization == "" {
w.Header().Set("WWW-Authenticate", `Basic realm="helm repo to get tags"`)
w.WriteHeader(http.StatusUnauthorized)
return
}
t.Logf("authorization received %s", authorization)
responseTags := TagsList{
Tags: []string{
"2.8.0",
"2.8.0-prerelease",
"2.8.0_build",
"2.8.0-prerelease_build",
"2.8.0-prerelease.1_build.1234",
}
},
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(responseTags)
if err != nil {
t.Fatal(err)
}
}))
t.Cleanup(server.Close)
client := NewClient(server.URL, Creds{InsecureSkipVerify: true}, true, "")
tags, err := client.GetTags("mychart", true)
serverURL, err := url.Parse(server.URL)
assert.NoError(t, err)
assert.ElementsMatch(t, tags.Tags, []string{
"first",
"second",
"2.8.0",
"2.8.0-prerelease",
"2.8.0+build",
"2.8.0-prerelease+build",
"2.8.0-prerelease.1+build.1234",
})
testCases := []struct {
name string
repoURL string
}{
{
name: "should login correctly when the repo path is in the server root with http scheme",
repoURL: server.URL,
},
{
name: "should login correctly when the repo path is not in the server root with http scheme",
repoURL: fmt.Sprintf("%s/my-repo", server.URL),
},
{
name: "should login correctly when the repo path is in the server root without http scheme",
repoURL: serverURL.Host,
},
{
name: "should login correctly when the repo path is not in the server root without http scheme",
repoURL: fmt.Sprintf("%s/my-repo", serverURL.Host),
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
client := NewClient(testCase.repoURL, Creds{
InsecureSkipVerify: true,
Username: "my-username",
Password: "my-password",
}, true, "")
tags, err := client.GetTags("mychart", true)
assert.NoError(t, err)
assert.ElementsMatch(t, tags.Tags, []string{
"2.8.0",
"2.8.0-prerelease",
"2.8.0+build",
"2.8.0-prerelease+build",
"2.8.0-prerelease.1+build.1234",
})
})
}
}

View File

@@ -107,11 +107,14 @@ func (svc *argoCDService) GetAppDetails(ctx context.Context, appSource *v1alpha1
var has *shared.CustomHelmAppSpec
if appDetail.Helm != nil {
has = &shared.CustomHelmAppSpec{
Name: appDetail.Helm.Name,
ValueFiles: appDetail.Helm.ValueFiles,
Parameters: appDetail.Helm.Parameters,
Values: appDetail.Helm.Values,
FileParameters: appDetail.Helm.FileParameters,
HelmAppSpec: apiclient.HelmAppSpec{
Name: appDetail.Helm.Name,
ValueFiles: appDetail.Helm.ValueFiles,
Parameters: appDetail.Helm.Parameters,
Values: appDetail.Helm.Values,
FileParameters: appDetail.Helm.FileParameters,
},
HelmParameterOverrides: appSource.Helm.Parameters,
}
}
return &shared.AppDetail{

View File

@@ -1,6 +1,7 @@
package shared
import (
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"time"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
@@ -28,24 +29,32 @@ type AppDetail struct {
Directory *apiclient.DirectoryAppSpec
}
type CustomHelmAppSpec apiclient.HelmAppSpec
type CustomHelmAppSpec struct {
HelmAppSpec apiclient.HelmAppSpec
HelmParameterOverrides []v1alpha1.HelmParameter
}
func (has CustomHelmAppSpec) GetParameterValueByName(Name string) string {
var value string
for i := range has.Parameters {
if has.Parameters[i].Name == Name {
value = has.Parameters[i].Value
break
// Check in overrides first
for i := range has.HelmParameterOverrides {
if has.HelmParameterOverrides[i].Name == Name {
return has.HelmParameterOverrides[i].Value
}
}
return value
for i := range has.HelmAppSpec.Parameters {
if has.HelmAppSpec.Parameters[i].Name == Name {
return has.HelmAppSpec.Parameters[i].Value
}
}
return ""
}
func (has CustomHelmAppSpec) GetFileParameterPathByName(Name string) string {
var path string
for i := range has.FileParameters {
if has.FileParameters[i].Name == Name {
path = has.FileParameters[i].Path
for i := range has.HelmAppSpec.FileParameters {
if has.HelmAppSpec.FileParameters[i].Name == Name {
path = has.HelmAppSpec.FileParameters[i].Path
break
}
}

View File

@@ -0,0 +1,30 @@
package shared
import (
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/stretchr/testify/assert"
"testing"
)
func TestGetParameterValueByName(t *testing.T) {
helmAppSpec := CustomHelmAppSpec{
HelmAppSpec: apiclient.HelmAppSpec{
Parameters: []*v1alpha1.HelmParameter{
{
Name: "param1",
Value: "value1",
},
},
},
HelmParameterOverrides: []v1alpha1.HelmParameter{
{
Name: "param1",
Value: "value-override",
},
},
}
value := helmAppSpec.GetParameterValueByName("param1")
assert.Equal(t, "value-override", value)
}

View File

@@ -10,6 +10,7 @@ import (
"net/http"
"os"
"strings"
"sync"
"time"
"github.com/coreos/go-oidc/v3/oidc"
@@ -41,6 +42,7 @@ type SessionManager struct {
storage UserStateStorage
sleep func(d time.Duration)
verificationDelayNoiseEnabled bool
failedLock sync.RWMutex
}
// LoginAttempts is a timestamped counter for failed login attempts
@@ -69,7 +71,7 @@ const (
// Maximum length of username, too keep the cache's memory signature low
maxUsernameLength = 32
// The default maximum session cache size
defaultMaxCacheSize = 1000
defaultMaxCacheSize = 10000
// The default number of maximum login failures before delay kicks in
defaultMaxLoginFailures = 5
// The default time in seconds for the failure window
@@ -284,7 +286,7 @@ func (mgr *SessionManager) Parse(tokenString string) (jwt.Claims, string, error)
return token.Claims, newToken, nil
}
// GetLoginFailures retrieves the login failure information from the cache
// GetLoginFailures retrieves the login failure information from the cache. Any modifications to the LoginAttemps map must be done in a thread-safe manner.
func (mgr *SessionManager) GetLoginFailures() map[string]LoginAttempts {
// Get failures from the cache
var failures map[string]LoginAttempts
@@ -299,25 +301,43 @@ func (mgr *SessionManager) GetLoginFailures() map[string]LoginAttempts {
return failures
}
func expireOldFailedAttempts(maxAge time.Duration, failures *map[string]LoginAttempts) int {
func expireOldFailedAttempts(maxAge time.Duration, failures map[string]LoginAttempts) int {
expiredCount := 0
for key, attempt := range *failures {
for key, attempt := range failures {
if time.Since(attempt.LastFailed) > maxAge*time.Second {
expiredCount += 1
delete(*failures, key)
delete(failures, key)
}
}
return expiredCount
}
// Protect admin user from login attempt reset caused by attempts to overflow cache in a brute force attack. Instead remove random non-admin to make room in cache.
func pickRandomNonAdminLoginFailure(failures map[string]LoginAttempts, username string) *string {
idx := rand.Intn(len(failures) - 1)
i := 0
for key := range failures {
if i == idx {
if key == common.ArgoCDAdminUsername || key == username {
return pickRandomNonAdminLoginFailure(failures, username)
}
return &key
}
i++
}
return nil
}
// Updates the failure count for a given username. If failed is true, increases the counter. Otherwise, sets counter back to 0.
func (mgr *SessionManager) updateFailureCount(username string, failed bool) {
mgr.failedLock.Lock()
defer mgr.failedLock.Unlock()
failures := mgr.GetLoginFailures()
// Expire old entries in the cache if we have a failure window defined.
if window := getLoginFailureWindow(); window > 0 {
count := expireOldFailedAttempts(window, &failures)
count := expireOldFailedAttempts(window, failures)
if count > 0 {
log.Infof("Expired %d entries from session cache due to max age reached", count)
}
@@ -327,23 +347,13 @@ func (mgr *SessionManager) updateFailureCount(username string, failed bool) {
// prevent overbloating the cache with fake entries, as this could lead to
// memory exhaustion and ultimately in a DoS. We remove a single entry to
// replace it with the new one.
//
// Chances are that we remove the one that is under active attack, but this
// chance is low (1:cache_size)
if failed && len(failures) >= getMaximumCacheSize() {
log.Warnf("Session cache size exceeds %d entries, removing random entry", getMaximumCacheSize())
idx := rand.Intn(len(failures) - 1)
var rmUser string
i := 0
for key := range failures {
if i == idx {
rmUser = key
delete(failures, key)
break
}
i++
rmUser := pickRandomNonAdminLoginFailure(failures, username)
if rmUser != nil {
delete(failures, *rmUser)
log.Infof("Deleted entry for user %s from cache", *rmUser)
}
log.Infof("Deleted entry for user %s from cache", rmUser)
}
attempt, ok := failures[username]
@@ -374,6 +384,8 @@ func (mgr *SessionManager) updateFailureCount(username string, failed bool) {
// Get the current login failure attempts for given username
func (mgr *SessionManager) getFailureCount(username string) LoginAttempts {
mgr.failedLock.RLock()
defer mgr.failedLock.RUnlock()
failures := mgr.GetLoginFailures()
attempt, ok := failures[username]
if !ok {

View File

@@ -1173,3 +1173,42 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
assert.ErrorIs(t, err, common.TokenVerificationErr)
})
}
func Test_PickFailureAttemptWhenOverflowed(t *testing.T) {
t.Run("Not pick admin user from the queue", func(t *testing.T) {
failures := map[string]LoginAttempts{
"admin": {
FailCount: 1,
},
"test2": {
FailCount: 1,
},
}
// inside pickRandomNonAdminLoginFailure, it uses random, so we need to test it multiple times
for i := 0; i < 1000; i++ {
user := pickRandomNonAdminLoginFailure(failures, "test")
assert.Equal(t, "test2", *user)
}
})
t.Run("Not pick admin user and current user from the queue", func(t *testing.T) {
failures := map[string]LoginAttempts{
"test": {
FailCount: 1,
},
"admin": {
FailCount: 1,
},
"test2": {
FailCount: 1,
},
}
// inside pickRandomNonAdminLoginFailure, it uses random, so we need to test it multiple times
for i := 0; i < 1000; i++ {
user := pickRandomNonAdminLoginFailure(failures, "test")
assert.Equal(t, "test2", *user)
}
})
}