Compare commits

...

26 Commits

Author SHA1 Message Date
argo-bot
8b9ff390e8 Bump version to 2.3.8 2022-10-03 20:49:52 +00:00
argo-bot
437b0554ed Bump version to 2.3.8 2022-10-03 20:49:39 +00:00
Michael Crenshaw
c4e7326aad chore: upgrade Dex to 2.35.0 (#10775)
* chore: upgrade dex to v2.35.0

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* upgrade github workflow too

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-03 15:46:12 -04:00
Michael Crenshaw
919582de89 chore: upgrade dex to v2.32.1-distroless (#10746)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-09-30 18:55:54 -04:00
JesseBot
5940e56c8b docs: Add "Create Namespace" to sync options doc (#3490) (#10326)
* Add create namespace to the sync options doc

Signed-off-by: JesseBot <jessebot@linux.com>

* Update docs/user-guide/sync-options.md

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>

Signed-off-by: JesseBot <jessebot@linux.com>
Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
2022-08-17 15:12:18 -04:00
Michael Crenshaw
4a299a2f2e docs: clusterResources in declarative cluster config (#10219)
* docs: clusterResources in declarative cluster config

Signed-off-by: CI <michael@crenshaw.dev>

* add article

Signed-off-by: CI <michael@crenshaw.dev>

Signed-off-by: CI <michael@crenshaw.dev>
2022-08-11 13:49:59 -04:00
argo-bot
402da6f64c Bump version to 2.3.7 2022-07-29 14:48:08 +00:00
argo-bot
89c600a6fe Bump version to 2.3.7 2022-07-29 14:47:55 +00:00
jannfis
76cd161e0a test: Remove cluster e2e tests not intended for release-2.3
Signed-off-by: jannfis <jann@mistrust.net>
2022-07-29 07:51:33 +00:00
jannfis
4b8b5918f8 test: Remove circular symlinks from testdata (#9886)
* test: Remove circular symlinks from testdata

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

* Another test case

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

* Use defer for changing back to original workdir

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

* Abort the test on error in defer

Signed-off-by: jannfis <jann@mistrust.net>
2022-07-28 20:25:30 +00:00
Michael Crenshaw
6d0b9caed5 fix: skip redirect url validation when it's the base href (#10058) (#10116)
* fix: skip redirect url validation when it's the base href (#10058)

Signed-off-by: CI <michael@crenshaw.dev>

nicer way of doing it

Signed-off-by: CI <michael@crenshaw.dev>

* fix missin arg

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-27 16:38:24 -04:00
dependabot[bot]
4bb00bade6 chore(deps): bump moment from 2.29.3 to 2.29.4 in /ui (#9897)
Bumps [moment](https://github.com/moment/moment) from 2.29.3 to 2.29.4.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.3...2.29.4)

Signed-off-by: CI <michael@crenshaw.dev>

---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-27 16:28:30 -04:00
Snyk bot
14424c58b2 fix: upgrade moment from 2.29.2 to 2.29.3 (#9330)
Snyk has created this PR to upgrade moment from 2.29.2 to 2.29.3.

See this package in npm:

See this project in Snyk:
https://app.snyk.io/org/argoproj/project/d2931792-eef9-4d7c-b9d6-c0cbd2bd4dbe?utm_source=github&utm_medium=referral&page=upgrade-pr

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-27 16:22:59 -04:00
Alexander Matyushentsev
c0d2e13b42 chore: upgrade moment to latest version to fix CVE (#9005)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-07-27 16:04:37 -04:00
Michael Crenshaw
6de0d9dced chore: move dependencies to dev dependencies (#8541)
chore: move dependencies to dev dependencies (#8541)

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-07-27 15:37:49 -04:00
Michael Crenshaw
5c31b47517 docs: add OpenSSH breaking change notes (#10104)
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-27 15:28:23 -04:00
Michael Crenshaw
92d26b55bd fix: avoid CVE-2022-28948 (#10093)
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-27 15:08:17 -04:00
Michael Crenshaw
a25a6dcfe3 chore: update parse-url (#10101)
* chore: upgrade parse-url

Signed-off-by: CI <michael@crenshaw.dev>

* edit a generated file, because that's smart

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-27 15:00:13 -04:00
Michael Crenshaw
fe6c0f1a38 chore: upgrade base image to 22.04 (#10103)
Signed-off-by: douhunt <douhunt@protonmail.com>

Co-authored-by: douhunt <douhunt@protonmail.com>
Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

chore: update Kex-Algorithms (#9561)

* chore: update Kex-Algorithms

Signed-off-by: douhunt <douhunt@protonmail.com>

* sorted kex-algorithms

Signed-off-by: 34FathomBelow <34fathombelow@protonmail.com>

Co-authored-by: douhunt <douhunt@protonmail.com>
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

chore upgrade base image for test containers Ubuntu:22.04 (#9563)

Signed-off-by: 34FathomBelow <34fathombelow@protonmail.com>

Co-authored-by: 34FathomBelow <34fathombelow@protonmail.com>
2022-07-26 14:49:06 -04:00
Michael Crenshaw
0851ea54b8 docs: simplify Docker toolchain docs (#9966) (#10006)
* docs: simplify Docker toolchain docs (#9966)

Signed-off-by: CI <michael@crenshaw.dev>

* to be or not to be

Signed-off-by: CI <michael@crenshaw.dev>

* pin dependencies to avoid absurdity

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-26 14:06:27 -04:00
34FathomBelow
3e920bf3b6 chore: update redis to 6.2.7 avoid CVE-2022-30065/CVE-2022-2097 (#10062)
Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-07-25 14:24:45 -04:00
Michael Crenshaw
a606b0ab01 chore: upgrade Dex to 2.32.0 (#10036) (#10042)
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-20 10:45:44 -04:00
34FathomBelow
e4074454c6 chore: update haproxy to 2.0.29 for redis-ha (#10045)
Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-07-19 15:05:54 -04:00
Daniel Helfand
d0e30d961a fix: use serviceaccount name instead of struct (#9614)
* fix: use serviceaccount name instead of struct

Signed-off-by: Daniel Helfand <helfand.4@gmail.com>

* fix: change name of param from sa to serviceAccount

Signed-off-by: Daniel Helfand <helfand.4@gmail.com>
2022-07-13 16:29:39 -04:00
Daniel Helfand
98aadc7dc1 fix: create serviceaccount token for v1.24 clusters (#9546)
* fix: create serviceaccount token for v1.24 clusters

Signed-off-by: Daniel Helfand <helfand.4@gmail.com>

* change create to get in err

Signed-off-by: Daniel Helfand <helfand.4@gmail.com>
2022-07-13 16:29:03 -04:00
Michael Crenshaw
efdec2888e test: check for error messages from CI env (#9953)
test: check for error messages from CI env (#9953)

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-12 15:20:20 -04:00
43 changed files with 701 additions and 179 deletions

View File

@@ -392,9 +392,9 @@ jobs:
git config --global user.email "john.doe@example.com"
- name: Pull Docker image required for tests
run: |
docker pull quay.io/dexidp/dex:v2.25.0
docker pull ghcr.io/dexidp/dex:v2.35.0-distroless
docker pull argoproj/argo-cd-ci-builder:v1.0.0
docker pull redis:6.2.6-alpine
docker pull redis:6.2.7-alpine
- name: Create target directory for binaries in the build-process
run: |
mkdir -p dist

View File

@@ -1,4 +1,4 @@
ARG BASE_IMAGE=docker.io/library/ubuntu:21.10
ARG BASE_IMAGE=docker.io/library/ubuntu:22.04
####################################################################################################
# Builder image
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
@@ -69,7 +69,7 @@ RUN ln -s /usr/local/aws-cli/v2/current/dist/aws /usr/local/bin/aws
# support for mounting configuration from a configmap
RUN mkdir -p /app/config/ssh && \
touch /app/config/ssh/ssh_known_hosts && \
ln -s /app/config/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts
ln -s /app/config/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts
RUN mkdir -p /app/config/tls
RUN mkdir -p /app/config/gpg/source && \

View File

@@ -1,7 +1,7 @@
controller: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-application-controller $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081}"
api-server: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-server $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth=${ARGOCD_E2E_DISABLE_AUTH:-'true'} --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} "
dex: sh -c "ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/v2/cmd gendexcfg -o `pwd`/dist/dex.yaml && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml ghcr.io/dexidp/dex:v2.30.2 dex serve /dex.yaml"
redis: bash -c "if [ \"$ARGOCD_REDIS_LOCAL\" == 'true' ]; then redis-server --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; else docker run --rm --name argocd-redis -i -p ${ARGOCD_E2E_REDIS_PORT:-6379}:${ARGOCD_E2E_REDIS_PORT:-6379} redis:6.2.6-alpine --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; fi"
redis: bash -c "if [ \"$ARGOCD_REDIS_LOCAL\" == 'true' ]; then redis-server --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; else docker run --rm --name argocd-redis -i -p ${ARGOCD_E2E_REDIS_PORT:-6379}:${ARGOCD_E2E_REDIS_PORT:-6379} redis:6.2.7-alpine --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; fi"
repo-server: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_GNUPGHOME=${ARGOCD_GNUPGHOME:-/tmp/argocd-local/gpg/keys} ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-/tmp/argo-e2e/app/config/plugin} ARGOCD_GPG_DATA_PATH=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-repo-server ARGOCD_GPG_ENABLED=${ARGOCD_GPG_ENABLED:-false} $COMMAND --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379}"
ui: sh -c 'cd ui && ${ARGOCD_E2E_YARN_CMD:-yarn} start'
git-server: test/fixture/testrepos/start-git.sh

View File

@@ -1 +1 @@
2.3.6
2.3.8

View File

@@ -609,7 +609,7 @@ func GenerateToken(clusterOpts cmdutil.ClusterOptions, conf *rest.Config) (strin
clientset, err := kubernetes.NewForConfig(conf)
errors.CheckError(err)
bearerToken, err := clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount)
bearerToken, err := clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount, common.BearerTokenTimeout)
if err != nil {
return "", err
}

View File

@@ -113,7 +113,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
clientset, err := kubernetes.NewForConfig(conf)
errors.CheckError(err)
if clusterOpts.ServiceAccount != "" {
managerBearerToken, err = clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount)
managerBearerToken, err = clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount, common.BearerTokenTimeout)
} else {
isTerminal := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
@@ -123,7 +123,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
os.Exit(1)
}
}
managerBearerToken, err = clusterauth.InstallClusterManagerRBAC(clientset, clusterOpts.SystemNamespace, clusterOpts.Namespaces)
managerBearerToken, err = clusterauth.InstallClusterManagerRBAC(clientset, clusterOpts.SystemNamespace, clusterOpts.Namespaces, common.BearerTokenTimeout)
}
errors.CheckError(err)
}

View File

@@ -212,6 +212,12 @@ const (
CacheVersion = "1.8.3"
)
// Constants used by util/clusterauth package
const (
ClusterAuthRequestTimeout = 10 * time.Second
BearerTokenTimeout = 30 * time.Second
)
const (
DefaultGitRetryMaxDuration time.Duration = time.Second * 5 // 5s
DefaultGitRetryDuration time.Duration = time.Millisecond * 250 // 0.25s

View File

@@ -24,8 +24,7 @@ You will need at least the following things in your toolchain in order to develo
* A Kubernetes cluster. You won't need a fully blown multi-master, multi-node cluster, but you will need something like K3S, Minikube or microk8s. You will also need a working Kubernetes client (`kubectl`) configuration in your development environment. The configuration must reside in `~/.kube/config` and the API server URL must point to the IP address of your local machine (or VM), and **not** to `localhost` or `127.0.0.1` if you are using the virtualized development toolchain (see below)
* You will also need a working Docker runtime environment, to be able to build and run images.
The Docker version must be fairly recent, and support multi-stage builds. You should not work as root. Make your local user a member of the `docker` group to be able to control the Docker service on your machine.
* You will also need a working Docker runtime environment, to be able to build and run images. The Docker version must be 17.05.0 or higher, to support multi-stage builds.
* Obviously, you will need a `git` client for pulling source code and pushing back your changes.

View File

@@ -483,6 +483,7 @@ The secret data must include following fields:
* `name` - cluster name
* `server` - cluster api server url
* `namespaces` - optional comma-separated list of namespaces which are accessible in that cluster. Cluster level resources would be ignored if namespace list is not empty.
* `clusterResources` - optional boolean string (`"true"` or `"false"`) determining whether Argo CD can manage cluster-level resources on this cluster. This setting is used only if the list of managed namespaces is not empty.
* `config` - JSON representation of following data structure:
```yaml

View File

@@ -14,3 +14,76 @@ Note that bundled Helm has been upgraded from 3.6.0 to v3.7+. This includes foll
- Experimental OCI support has been rewritten.
More information in the [Helm v3.7.0 release notes](https://github.com/helm/helm/releases/tag/v3.7.0).
## Support for private repo SSH keys using the SHA-1 signature hash algorithm is removed in 2.2.12
Argo CD 2.2.12 upgraded its base image from Ubuntu 21.10 to Ubuntu 22.04, which upgraded OpenSSH to 8.9. OpenSSH starting
with 8.8 [dropped support for the `ssh-rsa` SHA-1 key signature algorithm](https://www.openssh.com/txt/release-8.8).
The signature algorithm is _not_ the same as the algorithm used when generating the key. There is no need to update
keys.
The signature algorithm is negotiated with the SSH server when the connection is being set up. The client offers its
list of accepted signature algorithms, and if the server has a match, the connection proceeds. For most SSH servers on
up-to-date git providers, acceptable algorithms other than `ssh-rsa` should be available.
Before upgrading to Argo CD 2.2.12, check whether your git provider(s) using SSH authentication support algorithms newer
than `rsa-ssh`.
1. Make sure your version of SSH >= 8.9 (the version used by Argo CD). If not, upgrade it before proceeding.
```shell
ssh -V
```
Example output: `OpenSSH_8.9p1 Ubuntu-3, OpenSSL 3.0.2 15 Mar 2022`
2. Once you have a recent version of OpenSSH, follow the directions from the [OpenSSH 8.8 release notes](https://www.openssh.com/txt/release-8.7):
> To check whether a server is using the weak ssh-rsa public key
> algorithm, for host authentication, try to connect to it after
> removing the ssh-rsa algorithm from ssh(1)'s allowed list:
>
> ```shell
> ssh -oHostKeyAlgorithms=-ssh-rsa user@host
> ```
>
> If the host key verification fails and no other supported host key
> types are available, the server software on that host should be
> upgraded.
If the server does not support an acceptable version, you will get an error similar to this;
```
$ ssh -oHostKeyAlgorithms=-ssh-rsa vs-ssh.visualstudio.com
Unable to negotiate with 20.42.134.1 port 22: no matching host key type found. Their offer: ssh-rsa
```
This indicates that the server needs to update its supported key signature algorithms, and Argo CD will not connect
to it.
### Workaround
The [OpenSSH 8.8 release notes](https://www.openssh.com/txt/release-8.8) describe a workaround if you cannot change the
server's key signature algorithms configuration.
> Incompatibility is more likely when connecting to older SSH
> implementations that have not been upgraded or have not closely tracked
> improvements in the SSH protocol. For these cases, it may be necessary
> to selectively re-enable RSA/SHA1 to allow connection and/or user
> authentication via the HostkeyAlgorithms and PubkeyAcceptedAlgorithms
> options. For example, the following stanza in ~/.ssh/config will enable
> RSA/SHA1 for host and user authentication for a single destination host:
>
> ```
> Host old-host
> HostkeyAlgorithms +ssh-rsa
> PubkeyAcceptedAlgorithms +ssh-rsa
> ```
>
> We recommend enabling RSA/SHA1 only as a stopgap measure until legacy
> implementations can be upgraded or reconfigured with another key type
> (such as ECDSA or Ed25519).
To apply this to Argo CD, you could create a ConfigMap with the desired ssh config file and then mount it at
`/home/argocd/.ssh/config`.

View File

@@ -6,12 +6,15 @@ The Argo CD Notifications and ApplicationSet are part of Argo CD now. You no lon
The Notifications and ApplicationSet components are bundled into default Argo CD installation manifests.
The bundled manifests are drop-in replacements for the previous versions. If you are using Kustomize to bundle the manifests together then just
remove references to https://github.com/argoproj-labs/argocd-notifications and https://github.com/argoproj-labs/applicationset. No action is required
if you are using `kubectl apply`.
remove references to https://github.com/argoproj-labs/argocd-notifications and https://github.com/argoproj-labs/applicationset.
## Configure Additional ArgoCD Binaries
If you are using [the argocd-notifications helm chart](https://github.com/argoproj/argo-helm/tree/argocd-notifications-1.8.1/charts/argocd-notifications), you can move the chart [values](https://github.com/argoproj/argo-helm/blob/argocd-notifications-1.8.1/charts/argocd-notifications/values.yaml) to the `notifications` section of the argo-cd chart [values](https://github.com/argoproj/argo-helm/blob/main/charts/argo-cd/values.yaml#L2152). Although most values remain as is, for details please look up the values that are relevant to you.
We have removed non-Linux ArgoCD binaries (Darwin amd64 and Windows amd64) from the image ([#7668](https://github.com/argoproj/argo-cd/pull/7668)) and the associated download buttons in the help page in the UI.
No action is required if you are using `kubectl apply`.
## Configure Additional Argo CD Binaries
We have removed non-Linux Argo CD binaries (Darwin amd64 and Windows amd64) from the image ([#7668](https://github.com/argoproj/argo-cd/pull/7668)) and the associated download buttons in the help page in the UI.
Those removed binaries will still be included in the release assets and we made those configurable in [#7755](https://github.com/argoproj/argo-cd/pull/7755). You can add download buttons for other OS architectures by adding the following to your `argocd-cm` ConfigMap:
@@ -31,10 +34,89 @@ data:
help.download.windows-amd64: "path-or-url-to-download"
```
## Removed Python from the base image
If you are using a [Config Management Plugin](../../user-guide/config-management-plugins.md) that relies on Python, you
will need to build a custom image on the Argo CD base to install Python.
## Upgraded Kustomize Version
Note that bundled Kustomize version has been upgraded from 4.2.0 to 4.4.1.
## Upgrade Helm Version
## Upgraded Helm Version
Note that bundled Helm version has been upgraded from 3.7.1 to 3.8.0.
## Support for private repo SSH keys using the SHA-1 signature hash algorithm is removed in 2.3.7
Argo CD 2.3.7 upgraded its base image from Ubuntu 21.04 to Ubuntu 22.04, which upgraded OpenSSH to 8.9. OpenSSH starting
with 8.8 [dropped support for the `ssh-rsa` SHA-1 key signature algorithm](https://www.openssh.com/txt/release-8.8).
The signature algorithm is _not_ the same as the algorithm used when generating the key. There is no need to update
keys.
The signature algorithm is negotiated with the SSH server when the connection is being set up. The client offers its
list of accepted signature algorithms, and if the server has a match, the connection proceeds. For most SSH servers on
up-to-date git providers, acceptable algorithms other than `ssh-rsa` should be available.
Before upgrading to Argo CD 2.3.7, check whether your git provider(s) using SSH authentication support algorithms newer
than `rsa-ssh`.
1. Make sure your version of SSH >= 8.9 (the version used by Argo CD). If not, upgrade it before proceeding.
```shell
ssh -V
```
Example output: `OpenSSH_8.9p1 Ubuntu-3, OpenSSL 3.0.2 15 Mar 2022`
2. Once you have a recent version of OpenSSH, follow the directions from the [OpenSSH 8.8 release notes](https://www.openssh.com/txt/release-8.7):
> To check whether a server is using the weak ssh-rsa public key
> algorithm, for host authentication, try to connect to it after
> removing the ssh-rsa algorithm from ssh(1)'s allowed list:
>
> ```shell
> ssh -oHostKeyAlgorithms=-ssh-rsa user@host
> ```
>
> If the host key verification fails and no other supported host key
> types are available, the server software on that host should be
> upgraded.
If the server does not support an acceptable version, you will get an error similar to this;
```
$ ssh -oHostKeyAlgorithms=-ssh-rsa vs-ssh.visualstudio.com
Unable to negotiate with 20.42.134.1 port 22: no matching host key type found. Their offer: ssh-rsa
```
This indicates that the server needs to update its supported key signature algorithms, and Argo CD will not connect
to it.
### Workaround
The [OpenSSH 8.8 release notes](https://www.openssh.com/txt/release-8.8) describe a workaround if you cannot change the
server's key signature algorithms configuration.
> Incompatibility is more likely when connecting to older SSH
> implementations that have not been upgraded or have not closely tracked
> improvements in the SSH protocol. For these cases, it may be necessary
> to selectively re-enable RSA/SHA1 to allow connection and/or user
> authentication via the HostkeyAlgorithms and PubkeyAcceptedAlgorithms
> options. For example, the following stanza in ~/.ssh/config will enable
> RSA/SHA1 for host and user authentication for a single destination host:
>
> ```
> Host old-host
> HostkeyAlgorithms +ssh-rsa
> PubkeyAcceptedAlgorithms +ssh-rsa
> ```
>
> We recommend enabling RSA/SHA1 only as a stopgap measure until legacy
> implementations can be upgraded or reconfigured with another key type
> (such as ECDSA or Ed25519).
To apply this to Argo CD, you could create a ConfigMap with the desired ssh config file and then mount it at
`/home/argocd/.ssh/config`.
Note that bundled Helm version has been upgraded from 3.7.1 to 3.8.0.

View File

@@ -2,4 +2,5 @@ mkdocs==1.2.3
mkdocs-material==7.1.7
markdown_include==0.6.0
pygments==2.7.4
jinja2===3.0.3
jinja2==3.0.3
markdown==3.3.7

View File

@@ -187,3 +187,17 @@ spec:
```
The example above shows how an ArgoCD Application can be configured so it will ignore the `spec.replicas` field from the desired state (git) during the sync stage. This is achieve by calculating and pre-patching the desired state before applying it in the cluster. Note that the `RespectIgnoreDifferences` sync option is only effective when the resource is already created in the cluster. If the Application is being created and no live state exists, the desired state is applied as-is.
## Create Namespace
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
namespace: test
spec:
syncPolicy:
syncOptions:
- CreateNamespace=true
```
The example above shows how an Argo CD Application can be configured so it will create namespaces for the Application resources if the namespaces don't exist already. Without this either declared in the Application manifest or passed in the cli via `--sync-option CreateNamespace=true`, the Application will fail to sync if the resources' namespaces do not exist.

7
go.mod
View File

@@ -66,7 +66,7 @@ require (
github.com/stretchr/testify v1.7.0
github.com/whilp/git-urls v0.0.0-20191001220047-6db9661140c0
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
golang.org/x/net v0.0.0-20211209124913-491a49abca63
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
@@ -203,7 +203,7 @@ require (
gopkg.in/square/go-jose.v2 v2.2.2 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/apiserver v0.23.1 // indirect
k8s.io/apiserver v0.23.1
k8s.io/cli-runtime v0.23.1 // indirect
k8s.io/component-base v0.23.1 // indirect
k8s.io/component-helpers v0.23.1 // indirect
@@ -226,6 +226,9 @@ replace (
google.golang.org/grpc => google.golang.org/grpc v1.15.0
// Avoid CVE-2022-28948
gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1
k8s.io/api => k8s.io/api v0.23.1
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.23.1
k8s.io/apimachinery => k8s.io/apimachinery v0.23.1

10
go.sum
View File

@@ -1073,8 +1073,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1179,6 +1180,7 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1547,10 +1549,8 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=

View File

@@ -28,7 +28,7 @@ spec:
name: dexconfig
containers:
- name: dex
image: ghcr.io/dexidp/dex:v2.30.2
image: ghcr.io/dexidp/dex:v2.35.0-distroless
imagePullPolicy: Always
command: [/shared/argocd-dex, rundex]
securityContext:

View File

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

View File

@@ -21,7 +21,7 @@ spec:
serviceAccountName: argocd-redis
containers:
- name: redis
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: Always
args:
- "--save"

View File

@@ -9564,7 +9564,7 @@ spec:
- ""
- --appendonly
- "no"
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: Always
name: redis
ports:
@@ -9698,7 +9698,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -9747,7 +9747,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
name: copyutil
volumeMounts:
- mountPath: /var/run/argocd
@@ -9912,7 +9912,7 @@ spec:
key: controller.default.cache.expiration
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -11,4 +11,4 @@ resources:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.3.6
newTag: v2.3.8

View File

@@ -11,7 +11,7 @@ patchesStrategicMerge:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.3.6
newTag: v2.3.8
resources:
- ../../base/application-controller
- ../../base/dex

View File

@@ -770,7 +770,7 @@ spec:
topologyKey: kubernetes.io/hostname
initContainers:
- name: config-init
image: haproxy:2.0.25-alpine
image: haproxy:2.0.29-alpine
imagePullPolicy: IfNotPresent
resources:
{}
@@ -790,7 +790,7 @@ spec:
runAsUser: 1000
containers:
- name: haproxy
image: haproxy:2.0.25-alpine
image: haproxy:2.0.29-alpine
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
@@ -878,7 +878,7 @@ spec:
automountServiceAccountToken: false
initContainers:
- name: config-init
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: IfNotPresent
resources:
{}
@@ -906,7 +906,7 @@ spec:
containers:
- name: redis
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: IfNotPresent
command:
- redis-server
@@ -947,7 +947,7 @@ spec:
lifecycle:
{}
- name: sentinel
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: IfNotPresent
command:
- redis-sentinel

View File

@@ -9,12 +9,12 @@ redis-ha:
haproxy:
enabled: true
image:
tag: 2.0.25-alpine
tag: 2.0.29-alpine
timeout:
server: 6m
client: 6m
checkInterval: 3s
image:
tag: 6.2.6-alpine
tag: 6.2.7-alpine
sentinel:
bind: "0.0.0.0"

View File

@@ -10494,7 +10494,7 @@ spec:
- command:
- /shared/argocd-dex
- rundex
image: ghcr.io/dexidp/dex:v2.30.2
image: ghcr.io/dexidp/dex:v2.35.0-distroless
imagePullPolicy: Always
name: dex
ports:
@@ -10516,7 +10516,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -10549,7 +10549,7 @@ spec:
containers:
- command:
- argocd-notifications
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -10612,7 +10612,7 @@ spec:
app.kubernetes.io/name: argocd-redis-ha-haproxy
topologyKey: kubernetes.io/hostname
containers:
- image: haproxy:2.0.25-alpine
- image: haproxy:2.0.29-alpine
imagePullPolicy: IfNotPresent
lifecycle: {}
livenessProbe:
@@ -10641,7 +10641,7 @@ spec:
- /readonly/haproxy_init.sh
command:
- sh
image: haproxy:2.0.25-alpine
image: haproxy:2.0.29-alpine
imagePullPolicy: IfNotPresent
name: config-init
volumeMounts:
@@ -10788,7 +10788,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -10837,7 +10837,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
name: copyutil
volumeMounts:
- mountPath: /var/run/argocd
@@ -11064,7 +11064,7 @@ spec:
key: server.http.cookie.maxnumber
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -11260,7 +11260,7 @@ spec:
key: controller.default.cache.expiration
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -11342,7 +11342,7 @@ spec:
- /data/conf/redis.conf
command:
- redis-server
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: IfNotPresent
lifecycle: {}
livenessProbe:
@@ -11380,7 +11380,7 @@ spec:
- /data/conf/sentinel.conf
command:
- redis-sentinel
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: IfNotPresent
lifecycle: {}
livenessProbe:
@@ -11426,7 +11426,7 @@ spec:
value: 40000915ab58c3fa8fd888fb8b24711944e6cbb4
- name: SENTINEL_ID_2
value: 2bbec7894d954a8af3bb54d13eaec53cb024e2ca
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: IfNotPresent
name: config-init
volumeMounts:

View File

@@ -7790,7 +7790,7 @@ spec:
- command:
- /shared/argocd-dex
- rundex
image: ghcr.io/dexidp/dex:v2.30.2
image: ghcr.io/dexidp/dex:v2.35.0-distroless
imagePullPolicy: Always
name: dex
ports:
@@ -7812,7 +7812,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -7845,7 +7845,7 @@ spec:
containers:
- command:
- argocd-notifications
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -7908,7 +7908,7 @@ spec:
app.kubernetes.io/name: argocd-redis-ha-haproxy
topologyKey: kubernetes.io/hostname
containers:
- image: haproxy:2.0.25-alpine
- image: haproxy:2.0.29-alpine
imagePullPolicy: IfNotPresent
lifecycle: {}
livenessProbe:
@@ -7937,7 +7937,7 @@ spec:
- /readonly/haproxy_init.sh
command:
- sh
image: haproxy:2.0.25-alpine
image: haproxy:2.0.29-alpine
imagePullPolicy: IfNotPresent
name: config-init
volumeMounts:
@@ -8084,7 +8084,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -8133,7 +8133,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
name: copyutil
volumeMounts:
- mountPath: /var/run/argocd
@@ -8360,7 +8360,7 @@ spec:
key: server.http.cookie.maxnumber
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -8556,7 +8556,7 @@ spec:
key: controller.default.cache.expiration
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -8638,7 +8638,7 @@ spec:
- /data/conf/redis.conf
command:
- redis-server
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: IfNotPresent
lifecycle: {}
livenessProbe:
@@ -8676,7 +8676,7 @@ spec:
- /data/conf/sentinel.conf
command:
- redis-sentinel
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: IfNotPresent
lifecycle: {}
livenessProbe:
@@ -8722,7 +8722,7 @@ spec:
value: 40000915ab58c3fa8fd888fb8b24711944e6cbb4
- name: SENTINEL_ID_2
value: 2bbec7894d954a8af3bb54d13eaec53cb024e2ca
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: IfNotPresent
name: config-init
volumeMounts:

View File

@@ -9864,7 +9864,7 @@ spec:
- command:
- /shared/argocd-dex
- rundex
image: ghcr.io/dexidp/dex:v2.30.2
image: ghcr.io/dexidp/dex:v2.35.0-distroless
imagePullPolicy: Always
name: dex
ports:
@@ -9886,7 +9886,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -9919,7 +9919,7 @@ spec:
containers:
- command:
- argocd-notifications
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -9988,7 +9988,7 @@ spec:
- ""
- --appendonly
- "no"
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: Always
name: redis
ports:
@@ -10122,7 +10122,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -10171,7 +10171,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
name: copyutil
volumeMounts:
- mountPath: /var/run/argocd
@@ -10394,7 +10394,7 @@ spec:
key: server.http.cookie.maxnumber
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -10584,7 +10584,7 @@ spec:
key: controller.default.cache.expiration
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -7160,7 +7160,7 @@ spec:
- command:
- /shared/argocd-dex
- rundex
image: ghcr.io/dexidp/dex:v2.30.2
image: ghcr.io/dexidp/dex:v2.35.0-distroless
imagePullPolicy: Always
name: dex
ports:
@@ -7182,7 +7182,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -7215,7 +7215,7 @@ spec:
containers:
- command:
- argocd-notifications
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -7284,7 +7284,7 @@ spec:
- ""
- --appendonly
- "no"
image: redis:6.2.6-alpine
image: redis:6.2.7-alpine
imagePullPolicy: Always
name: redis
ports:
@@ -7418,7 +7418,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -7467,7 +7467,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
name: copyutil
volumeMounts:
- mountPath: /var/run/argocd
@@ -7690,7 +7690,7 @@ spec:
key: server.http.cookie.maxnumber
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -7880,7 +7880,7 @@ spec:
key: controller.default.cache.expiration
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.3.6
image: quay.io/argoproj/argocd:v2.3.8
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -133,6 +133,31 @@ func newServiceWithCommitSHA(root, revision string) *Service {
return service
}
// createSymlink creates a symlink with name linkName to file destName in
// workingDir
func createSymlink(t *testing.T, workingDir, destName, linkName string) error {
oldWorkingDir, err := os.Getwd()
if err != nil {
return err
}
if workingDir != "" {
err = os.Chdir(workingDir)
if err != nil {
return err
}
defer func() {
if err := os.Chdir(oldWorkingDir); err != nil {
t.Fatal(err.Error())
}
}()
}
err = os.Symlink(destName, linkName)
if err != nil {
return err
}
return nil
}
func TestGenerateYamlManifestInDir(t *testing.T) {
service := newService("../..")
@@ -1999,7 +2024,12 @@ func Test_getPotentiallyValidManifests(t *testing.T) {
})
t.Run("circular link should throw an error", func(t *testing.T) {
require.DirExists(t, "./testdata/circular-link")
const testDir = "./testdata/circular-link"
require.DirExists(t, testDir)
require.NoError(t, createSymlink(t, testDir, "a.json", "b.json"))
defer os.Remove(path.Join(testDir, "a.json"))
require.NoError(t, createSymlink(t, testDir, "b.json", "a.json"))
defer os.Remove(path.Join(testDir, "b.json"))
manifests, err := getPotentiallyValidManifests(logCtx, "./testdata/circular-link", "./testdata/circular-link", false, "", "", resource.MustParse("0"))
assert.Empty(t, manifests)
assert.Error(t, err)
@@ -2094,7 +2124,12 @@ func Test_findManifests(t *testing.T) {
})
t.Run("circular link should throw an error", func(t *testing.T) {
require.DirExists(t, "./testdata/circular-link")
const testDir = "./testdata/circular-link"
require.DirExists(t, testDir)
require.NoError(t, createSymlink(t, testDir, "a.json", "b.json"))
defer os.Remove(path.Join(testDir, "a.json"))
require.NoError(t, createSymlink(t, testDir, "b.json", "a.json"))
defer os.Remove(path.Join(testDir, "b.json"))
manifests, err := findManifests(logCtx, "./testdata/circular-link", "./testdata/circular-link", nil, noRecurse, nil, resource.MustParse("0"))
assert.Empty(t, manifests)
assert.Error(t, err)

View File

View File

@@ -1 +0,0 @@
b.json

View File

@@ -1 +0,0 @@
a.json

View File

@@ -1,4 +1,4 @@
FROM redis:6.2.6 as redis
FROM redis:6.2.7 as redis
FROM node:12.18.4 as node
@@ -6,7 +6,7 @@ FROM golang:1.17 as golang
FROM registry:2.7.1 as registry
FROM ubuntu:21.10
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install --fix-missing -y \
@@ -66,6 +66,11 @@ COPY ./test/fixture/testrepos/ssh_host_*_key* /etc/ssh/
# Copy redis binaries to the image
COPY --from=redis /usr/local/bin/* /usr/local/bin/
# Copy redis dependencies/shared libraries
# Ubuntu 22.04+ has moved to OpenSSL3 and no longer provides these libraries
COPY --from=redis /usr/lib/x86_64-linux-gnu/libssl.so.1.1 /usr/lib/x86_64-linux-gnu/
COPY --from=redis /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 /usr/lib/x86_64-linux-gnu/
# Copy registry binaries to the image
COPY --from=registry /bin/registry /usr/local/bin/
COPY --from=registry /etc/docker/registry/config.yml /etc/docker/registry/config.yml

View File

@@ -182,3 +182,4 @@ func TestClusterURLInRestAPI(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, map[string]string{"test": "val"}, cluster.Labels)
}

View File

@@ -6,7 +6,11 @@ import (
"fmt"
"log"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/clusterauth"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
clusterpkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/cluster"
"github.com/argoproj/argo-cd/v2/test/e2e/fixture"
@@ -63,6 +67,30 @@ func (a *Actions) Create(args ...string) *Actions {
return a
}
func (a *Actions) CreateWithRBAC(args ...string) *Actions {
pathOpts := clientcmd.NewDefaultPathOptions()
config, err := pathOpts.GetStartingConfig()
if err != nil {
a.lastError = err
return a
}
clientConfig := clientcmd.NewDefaultClientConfig(*config, &clientcmd.ConfigOverrides{})
conf, err := clientConfig.ClientConfig()
if err != nil {
a.lastError = err
return a
}
client := kubernetes.NewForConfigOrDie(conf)
_, err = clusterauth.InstallClusterManagerRBAC(client, "kube-system", []string{}, common.BearerTokenTimeout)
if err != nil {
a.lastError = err
return a
}
return a.Create()
}
func (a *Actions) List() *Actions {
a.context.t.Helper()
a.runCli("cluster", "list")
@@ -75,6 +103,20 @@ func (a *Actions) Get() *Actions {
return a
}
func (a *Actions) DeleteByName() *Actions {
a.context.t.Helper()
a.runCli("cluster", "rm", a.context.name)
return a
}
func (a *Actions) DeleteByServer() *Actions {
a.context.t.Helper()
a.runCli("cluster", "rm", a.context.server)
return a
}
func (a *Actions) Then() *Consequences {
a.context.t.Helper()
return &Consequences{a.context, a}

View File

@@ -3,7 +3,7 @@ FROM golang:1.17 AS go
RUN go install github.com/mattn/goreman@latest && \
go install github.com/kisielk/godepgraph@latest
FROM ubuntu:21.10
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \

View File

@@ -10,45 +10,22 @@
"test": "jest"
},
"dependencies": {
"@types/classnames": "^2.2.3",
"@types/cookie": "^0.3.1",
"@types/dagre": "^0.7.40",
"@types/deepmerge": "^2.2.0",
"@types/git-url-parse": "^9.0.0",
"@types/js-yaml": "^3.11.2",
"@types/minimatch": "^3.0.3",
"@types/prop-types": "^15.5.2",
"@types/react": "^16.8.5",
"@types/react-autocomplete": "^1.8.4",
"@types/react-dom": "^16.9.14",
"@types/react-form": "^2.16.0",
"@types/react-helmet": "^5.0.17",
"@types/react-paginate": "^6.2.0",
"@types/react-router": "^4.0.27",
"@types/react-router-dom": "^4.2.3",
"@types/superagent": "^3.5.7",
"ansi-to-react": "^6.1.6",
"argo-ui": "git+https://github.com/argoproj/argo-ui.git",
"classnames": "^2.2.5",
"color": "^3.1.0",
"cookie": "^0.3.1",
"copy-webpack-plugin": "^6.1.1",
"dagre": "^0.8.2",
"deepmerge": "^3.2.0",
"foundation-sites": "^6.4.3",
"git-url-parse": "^11.1.2",
"html-webpack-plugin": "^3.2.0",
"jest-junit": "^6.4.0",
"js-yaml": "^3.13.1",
"json-merge-patch": "^0.2.3",
"lodash-es": "^4.17.21",
"minimatch": "^3.0.4",
"moment": "^2.24.0",
"moment": "^2.29.4",
"monaco-editor": "^0.27.0",
"monaco-editor-webpack-plugin": "^6.0.0",
"node-sass": "^6.0.1",
"prop-types": "^15.6.0",
"raw-loader": "^0.5.1",
"react": "^16.9.3",
"react-autocomplete": "^1.8.1",
"react-diff-view": "^2.4.7",
@@ -64,21 +41,10 @@
"react-svg-piechart": "^2.1.1",
"redoc": "^2.0.0-rc.64",
"rxjs": "^6.6.6",
"sass-loader": "^6.0.6",
"source-map-loader": "^0.2.3",
"style-loader": "^0.20.1",
"superagent": "^3.8.2",
"superagent-promise": "^1.1.0",
"timezones-list": "3.0.1",
"ts-loader": "^6.0.4",
"ts-node": "^4.1.0",
"tslint": "^6.1.3",
"tslint-react": "^3.4.0",
"typescript": "^4.0.3",
"unidiff": "^1.0.2",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
"unidiff": "^1.0.2"
},
"resolutions": {
"@types/react": "^16.9.3",
@@ -90,23 +56,57 @@
"@babel/preset-env": "^7.7.1",
"@babel/preset-react": "^7.7.0",
"@babel/preset-typescript": "^7.7.2",
"@types/classnames": "^2.2.3",
"@types/cookie": "^0.3.1",
"@types/dagre": "^0.7.40",
"@types/deepmerge": "^2.2.0",
"@types/git-url-parse": "^9.0.0",
"@types/jest": "^24.0.13",
"@types/js-yaml": "^3.11.2",
"@types/lodash-es": "^4.17.5",
"@types/minimatch": "^3.0.3",
"@types/prop-types": "^15.5.2",
"@types/react": "^16.8.5",
"@types/react-autocomplete": "^1.8.4",
"@types/react-dom": "^16.9.14",
"@types/react-form": "^2.16.0",
"@types/react-helmet": "^5.0.17",
"@types/react-paginate": "^6.2.0",
"@types/react-router": "^4.0.27",
"@types/react-router-dom": "^4.2.3",
"@types/react-test-renderer": "^16.8.3",
"@types/superagent": "^3.5.7",
"add": "^2.0.6",
"babel-jest": "^24.9.0",
"babel-loader": "^8.0.6",
"codecov": "^3.7.2",
"copy-webpack-plugin": "^6.1.1",
"esbuild-loader": "^2.15.1",
"html-webpack-plugin": "^3.2.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^24.9.0",
"jest-junit": "^6.4.0",
"jest-transform-css": "^2.0.0",
"monaco-editor-webpack-plugin": "^6.0.0",
"node-sass": "^6.0.1",
"postcss": "^8.2.13",
"prettier": "1.19",
"raw-loader": "^0.5.1",
"react-test-renderer": "16.8.3",
"sass-loader": "^6.0.6",
"source-map-loader": "^0.2.3",
"style-loader": "^0.20.1",
"ts-jest": "^24.1.0",
"ts-loader": "^6.0.4",
"ts-node": "^4.1.0",
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0",
"tslint-plugin-prettier": "^2.0.1",
"tslint-react": "^3.4.0",
"typescript": "^4.0.3",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0",
"yarn": "^1.22.10"
}
}

View File

@@ -6159,6 +6159,11 @@ moment-timezone@^0.5.33:
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
moment@^2.29.4:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
monaco-editor-webpack-plugin@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-6.0.0.tgz#628956ce1851afa2a5f6c88d0ecbb24e9a444898"
@@ -6788,9 +6793,9 @@ parse-path@^4.0.0:
query-string "^6.13.8"
parse-url@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-6.0.0.tgz#f5dd262a7de9ec00914939220410b66cff09107d"
integrity sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==
version "6.0.5"
resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-6.0.5.tgz#4acab8982cef1846a0f8675fa686cef24b2f6f9b"
integrity sha512-e35AeLTSIlkw/5GFq70IN7po8fmDUjpDPY1rIK+VubRfsUvBonjQ+PBZG+vWMACnQSmNlvl524IucoDmcioMxA==
dependencies:
is-ssh "^1.3.0"
normalize-url "^6.1.0"

View File

@@ -2,16 +2,19 @@ package clusterauth
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/argoproj/argo-cd/v2/common"
jwt "github.com/golang-jwt/jwt/v4"
log "github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
)
@@ -173,7 +176,7 @@ func upsertRoleBinding(clientset kubernetes.Interface, name string, roleName str
}
// InstallClusterManagerRBAC installs RBAC resources for a cluster manager to operate a cluster. Returns a token
func InstallClusterManagerRBAC(clientset kubernetes.Interface, ns string, namespaces []string) (string, error) {
func InstallClusterManagerRBAC(clientset kubernetes.Interface, ns string, namespaces []string, bearerTokenTimeout time.Duration) (string, error) {
err := CreateServiceAccount(clientset, ArgoCDManagerServiceAccount, ns)
if err != nil {
@@ -212,42 +215,123 @@ func InstallClusterManagerRBAC(clientset kubernetes.Interface, ns string, namesp
}
}
return GetServiceAccountBearerToken(clientset, ns, ArgoCDManagerServiceAccount)
return GetServiceAccountBearerToken(clientset, ns, ArgoCDManagerServiceAccount, bearerTokenTimeout)
}
// GetServiceAccountBearerToken will attempt to get the provided service account until it
// exists, iterate the secrets associated with it looking for one of type
// kubernetes.io/service-account-token, and return it's token if found.
func GetServiceAccountBearerToken(clientset kubernetes.Interface, ns string, sa string) (string, error) {
var serviceAccount *corev1.ServiceAccount
// GetServiceAccountBearerToken determines if a ServiceAccount has a
// bearer token secret to use or if a secret should be created. It then
// waits for the secret to have a bearer token if a secret needs to
// be created and returns the token in encoded base64.
func GetServiceAccountBearerToken(clientset kubernetes.Interface, ns string, sa string, timeout time.Duration) (string, error) {
secretName, err := getOrCreateServiceAccountTokenSecret(clientset, sa, ns)
if err != nil {
return "", err
}
var secret *corev1.Secret
var err error
err = wait.Poll(500*time.Millisecond, 30*time.Second, func() (bool, error) {
serviceAccount, err = clientset.CoreV1().ServiceAccounts(ns).Get(context.Background(), sa, metav1.GetOptions{})
err = wait.PollImmediate(500*time.Millisecond, timeout, func() (bool, error) {
ctx, cancel := context.WithTimeout(context.Background(), common.ClusterAuthRequestTimeout)
defer cancel()
secret, err = clientset.CoreV1().Secrets(ns).Get(ctx, secretName, metav1.GetOptions{})
if err != nil {
return false, err
return false, fmt.Errorf("failed to get secret %q for serviceaccount %q: %w", secretName, sa, err)
}
// Scan all secrets looking for one of the correct type:
for _, oRef := range serviceAccount.Secrets {
var getErr error
secret, err = clientset.CoreV1().Secrets(ns).Get(context.Background(), oRef.Name, metav1.GetOptions{})
if err != nil {
return false, fmt.Errorf("Failed to retrieve secret %q: %v", oRef.Name, getErr)
}
if secret.Type == corev1.SecretTypeServiceAccountToken {
return true, nil
}
_, ok := secret.Data["token"]
if !ok {
return false, nil
}
return false, nil
return true, nil
})
if err != nil {
return "", fmt.Errorf("Failed to wait for service account secret: %v", err)
return "", fmt.Errorf("failed to get token for serviceaccount %q: %w", sa, err)
}
token, ok := secret.Data["token"]
if !ok {
return "", fmt.Errorf("Secret %q for service account %q did not have a token", secret.Name, serviceAccount)
return string(secret.Data["token"]), nil
}
// getOrCreateServiceAccountTokenSecret will check if a ServiceAccount
// already has a kubernetes.io/service-account-token secret associated
// with it or creates one if the ServiceAccount doesn't have one. This
// was added to help add k8s v1.24+ clusters.
func getOrCreateServiceAccountTokenSecret(clientset kubernetes.Interface, sa, ns string) (string, error) {
// Wait for sa to have secret, but don't wait too
// long for 1.24+ clusters
var serviceAccount *corev1.ServiceAccount
err := wait.PollImmediate(500*time.Millisecond, 5*time.Second, func() (bool, error) {
ctx, cancel := context.WithTimeout(context.Background(), common.ClusterAuthRequestTimeout)
defer cancel()
var getErr error
serviceAccount, getErr = clientset.CoreV1().ServiceAccounts(ns).Get(ctx, sa, metav1.GetOptions{})
if getErr != nil {
return false, fmt.Errorf("failed to get serviceaccount %q: %w", sa, getErr)
}
if len(serviceAccount.Secrets) == 0 {
return false, nil
}
return true, nil
})
if err != nil && err != wait.ErrWaitTimeout {
return "", fmt.Errorf("failed to get serviceaccount token secret: %w", err)
}
return string(token), nil
if serviceAccount == nil {
log.Errorf("Unexpected nil serviceaccount '%s/%s' with no error returned", ns, sa)
return "", fmt.Errorf("failed to create serviceaccount token secret: nil serviceaccount returned for '%s/%s' with no error", ns, sa)
}
outerCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
for _, s := range serviceAccount.Secrets {
innerCtx, cancel := context.WithTimeout(outerCtx, common.ClusterAuthRequestTimeout)
defer cancel()
existingSecret, err := clientset.CoreV1().Secrets(ns).Get(innerCtx, s.Name, metav1.GetOptions{})
if err != nil {
return "", fmt.Errorf("failed to retrieve secret %q: %w", s.Name, err)
}
if existingSecret.Type == corev1.SecretTypeServiceAccountToken {
return existingSecret.Name, nil
}
}
return createServiceAccountToken(clientset, serviceAccount)
}
func createServiceAccountToken(clientset kubernetes.Interface, serviceAccount *corev1.ServiceAccount) (string, error) {
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
GenerateName: serviceAccount.Name + "-token-",
Namespace: serviceAccount.Namespace,
Annotations: map[string]string{
corev1.ServiceAccountNameKey: serviceAccount.Name,
},
},
Type: corev1.SecretTypeServiceAccountToken,
}
ctx, cancel := context.WithTimeout(context.Background(), common.ClusterAuthRequestTimeout)
defer cancel()
secret, err := clientset.CoreV1().Secrets(serviceAccount.Namespace).Create(ctx, secret, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("failed to create secret for serviceaccount %q: %w", serviceAccount.Name, err)
}
log.Infof("Created bearer token secret for ServiceAccount %q", serviceAccount.Name)
serviceAccount.Secrets = []corev1.ObjectReference{{
Name: secret.Name,
Namespace: secret.Namespace,
}}
patch, err := json.Marshal(serviceAccount)
if err != nil {
return "", fmt.Errorf("failed marshaling patch for serviceaccount %q: %w", serviceAccount.Name, err)
}
_, err = clientset.CoreV1().ServiceAccounts(serviceAccount.Namespace).Patch(ctx, serviceAccount.Name, types.StrategicMergePatchType, patch, metav1.PatchOptions{})
if err != nil {
return "", fmt.Errorf("failed to patch serviceaccount %q with bearer token secret: %w", serviceAccount.Name, err)
}
return secret.Name, nil
}
// UninstallClusterManagerRBAC removes RBAC resources for a cluster manager to operate a cluster

View File

@@ -4,21 +4,24 @@ import (
"context"
"io/ioutil"
"testing"
"time"
"github.com/argoproj/argo-cd/v2/util/errors"
"github.com/ghodss/yaml"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/client-go/kubernetes/fake"
kubetesting "k8s.io/client-go/testing"
"github.com/argoproj/argo-cd/v2/util/errors"
)
const (
testToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhcmdvY2QtbWFuYWdlci10b2tlbi10ajc5ciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhcmdvY2QtbWFuYWdlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjkxZGQzN2NmLThkOTItMTFlOS1hMDkxLWQ2NWYyYWU3ZmE4ZCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTphcmdvY2QtbWFuYWdlciJ9.ytZjt2pDV8-A7DBMR06zQ3wt9cuVEfq262TQw7sdra-KRpDpMPnziMhc8bkwvgW-LGhTWUh5iu1y-1QhEx6mtbCt7vQArlBRxfvM5ys6ClFkplzq5c2TtZ7EzGSD0Up7tdxuG9dvR6TGXYdfFcG779yCdZo2H48sz5OSJfdEriduMEY1iL5suZd3ebOoVi1fGflmqFEkZX6SvxkoArl5mtNP6TvZ1eTcn64xh4ws152hxio42E-eSnl_CET4tpB5vgP5BVlSKW2xB7w2GJxqdETA5LJRI_OilY77dTOp8cMr_Ck3EOeda3zHfh4Okflg8rZFEeAuJYahQNeAILLkcA"
testToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhcmdvY2QtbWFuYWdlci10b2tlbi10ajc5ciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhcmdvY2QtbWFuYWdlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjkxZGQzN2NmLThkOTItMTFlOS1hMDkxLWQ2NWYyYWU3ZmE4ZCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTphcmdvY2QtbWFuYWdlciJ9.ytZjt2pDV8-A7DBMR06zQ3wt9cuVEfq262TQw7sdra-KRpDpMPnziMhc8bkwvgW-LGhTWUh5iu1y-1QhEx6mtbCt7vQArlBRxfvM5ys6ClFkplzq5c2TtZ7EzGSD0Up7tdxuG9dvR6TGXYdfFcG779yCdZo2H48sz5OSJfdEriduMEY1iL5suZd3ebOoVi1fGflmqFEkZX6SvxkoArl5mtNP6TvZ1eTcn64xh4ws152hxio42E-eSnl_CET4tpB5vgP5BVlSKW2xB7w2GJxqdETA5LJRI_OilY77dTOp8cMr_Ck3EOeda3zHfh4Okflg8rZFEeAuJYahQNeAILLkcA"
testBearerTokenTimeout = 5 * time.Second
)
var (
@@ -132,7 +135,7 @@ func TestInstallClusterManagerRBAC(t *testing.T) {
Namespace: "test",
},
Secrets: []corev1.ObjectReference{
corev1.ObjectReference{
{
Kind: secret.GetObjectKind().GroupVersionKind().Kind,
APIVersion: secret.APIVersion,
Name: secret.GetName(),
@@ -145,7 +148,7 @@ func TestInstallClusterManagerRBAC(t *testing.T) {
t.Run("Cluster Scope - Success", func(t *testing.T) {
cs := fake.NewSimpleClientset(ns, secret, sa)
token, err := InstallClusterManagerRBAC(cs, "test", nil)
token, err := InstallClusterManagerRBAC(cs, "test", nil, testBearerTokenTimeout)
assert.NoError(t, err)
assert.Equal(t, "foobar", token)
})
@@ -154,14 +157,14 @@ func TestInstallClusterManagerRBAC(t *testing.T) {
nsecret := secret.DeepCopy()
nsecret.Data = make(map[string][]byte)
cs := fake.NewSimpleClientset(ns, nsecret, sa)
token, err := InstallClusterManagerRBAC(cs, "test", nil)
token, err := InstallClusterManagerRBAC(cs, "test", nil, testBearerTokenTimeout)
assert.Error(t, err)
assert.Empty(t, token)
})
t.Run("Namespace Scope - Success", func(t *testing.T) {
cs := fake.NewSimpleClientset(ns, secret, sa)
token, err := InstallClusterManagerRBAC(cs, "test", []string{"nsa"})
token, err := InstallClusterManagerRBAC(cs, "test", []string{"nsa"}, testBearerTokenTimeout)
assert.NoError(t, err)
assert.Equal(t, "foobar", token)
})
@@ -170,7 +173,7 @@ func TestInstallClusterManagerRBAC(t *testing.T) {
nsecret := secret.DeepCopy()
nsecret.Data = make(map[string][]byte)
cs := fake.NewSimpleClientset(ns, nsecret, sa)
token, err := InstallClusterManagerRBAC(cs, "test", []string{"nsa"})
token, err := InstallClusterManagerRBAC(cs, "test", []string{"nsa"}, testBearerTokenTimeout)
assert.Error(t, err)
assert.Empty(t, token)
})
@@ -254,7 +257,108 @@ func TestGetServiceAccountBearerToken(t *testing.T) {
}
kubeclientset := fake.NewSimpleClientset(sa, dockercfgSecret, tokenSecret)
token, err := GetServiceAccountBearerToken(kubeclientset, "kube-system", sa.Name)
token, err := GetServiceAccountBearerToken(kubeclientset, "kube-system", sa.Name, testBearerTokenTimeout)
assert.NoError(t, err)
assert.Equal(t, testToken, token)
}
func Test_getOrCreateServiceAccountTokenSecret_NoSecretForSA(t *testing.T) {
ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "kube-system",
},
}
saWithoutSecret := &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: ArgoCDManagerServiceAccount,
Namespace: ns.Name,
},
}
cs := fake.NewSimpleClientset(ns, saWithoutSecret)
cs.PrependReactor("create", "secrets",
func(a kubetesting.Action) (handled bool, ret runtime.Object, err error) {
s, ok := a.(kubetesting.CreateAction).GetObject().(*corev1.Secret)
if !ok {
return
}
if s.Name == "" && s.GenerateName != "" {
s.SetName(names.SimpleNameGenerator.GenerateName(s.GenerateName))
}
s.Data = make(map[string][]byte)
s.Data["token"] = []byte("fake-token")
return
})
got, err := getOrCreateServiceAccountTokenSecret(cs, ArgoCDManagerServiceAccount, ns.Name)
assert.NoError(t, err)
assert.Contains(t, got, "argocd-manager-token-")
obj, err := cs.Tracker().Get(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"},
ns.Name, ArgoCDManagerServiceAccount)
if err != nil {
t.Errorf("ServiceAccount %s not found but was expected to be found: %s", ArgoCDManagerServiceAccount, err.Error())
}
sa := obj.(*corev1.ServiceAccount)
assert.Equal(t, 1, len(sa.Secrets))
}
func Test_getOrCreateServiceAccountTokenSecret_SAHasSecret(t *testing.T) {
ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "kube-system",
},
}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "sa-secret",
Namespace: ns.Name,
},
Type: corev1.SecretTypeServiceAccountToken,
Data: map[string][]byte{
"token": []byte("foobar"),
},
}
saWithSecret := &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: ArgoCDManagerServiceAccount,
Namespace: ns.Name,
},
Secrets: []corev1.ObjectReference{
{
Kind: secret.GetObjectKind().GroupVersionKind().Kind,
APIVersion: secret.APIVersion,
Name: secret.GetName(),
Namespace: secret.GetNamespace(),
UID: secret.GetUID(),
ResourceVersion: secret.GetResourceVersion(),
},
},
}
cs := fake.NewSimpleClientset(ns, saWithSecret, secret)
got, err := getOrCreateServiceAccountTokenSecret(cs, ArgoCDManagerServiceAccount, ns.Name)
assert.NoError(t, err)
assert.Equal(t, "sa-secret", got)
obj, err := cs.Tracker().Get(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"},
ns.Name, ArgoCDManagerServiceAccount)
if err != nil {
t.Errorf("ServiceAccount %s not found but was expected to be found: %s", ArgoCDManagerServiceAccount, err.Error())
}
sa := obj.(*corev1.ServiceAccount)
assert.Equal(t, 1, len(sa.Secrets))
// Adding if statement to prevent case where secret not found
// since accessing name by first index.
if len(sa.Secrets) != 0 {
assert.Equal(t, "sa-secret", sa.Secrets[0].Name)
}
}

View File

@@ -11,14 +11,14 @@ import (
// Unfortunately, crypto/ssh does not offer public constants or list for
// this.
var SupportedSSHKeyExchangeAlgorithms = []string{
"diffie-hellman-group1-sha1",
"diffie-hellman-group14-sha1",
"curve25519-sha256",
"curve25519-sha256@libssh.org",
"ecdh-sha2-nistp256",
"ecdh-sha2-nistp384",
"ecdh-sha2-nistp521",
"curve25519-sha256@libssh.org",
"diffie-hellman-group-exchange-sha1",
"diffie-hellman-group-exchange-sha256",
"diffie-hellman-group14-sha256",
"diffie-hellman-group14-sha1",
}
// List of default key exchange algorithms to use. We use those that are

View File

@@ -190,7 +190,7 @@ func (a *ClientApp) verifyAppState(r *http.Request, w http.ResponseWriter, state
redirectURL := a.baseHRef
parts := strings.SplitN(cookieVal, ":", 2)
if len(parts) == 2 && parts[1] != "" {
if !isValidRedirectURL(parts[1], []string{a.settings.URL}) {
if !isValidRedirectURL(parts[1], []string{a.settings.URL, a.baseHRef}) {
sanitizedUrl := parts[1]
if len(sanitizedUrl) > 100 {
sanitizedUrl = sanitizedUrl[:100]

View File

@@ -9,6 +9,7 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
gooidc "github.com/coreos/go-oidc"
@@ -133,7 +134,9 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
app.HandleLogin(w, req)
assert.Contains(t, w.Body.String(), "certificate is not trusted")
if !strings.Contains(w.Body.String(), "certificate signed by unknown authority") && !strings.Contains(w.Body.String(), "certificate is not trusted") {
t.Fatal("did not receive expected certificate verification failure error")
}
cdSettings.OIDCTLSInsecureSkipVerify = true
@@ -145,6 +148,7 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
app.HandleLogin(w, req)
assert.NotContains(t, w.Body.String(), "certificate is not trusted")
assert.NotContains(t, w.Body.String(), "certificate signed by unknown authority")
})
t.Run("dex certificate checking during login should toggle on config", func(t *testing.T) {
@@ -170,7 +174,9 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
app.HandleLogin(w, req)
assert.Contains(t, w.Body.String(), "certificate signed by unknown authority")
if !strings.Contains(w.Body.String(), "certificate signed by unknown authority") && !strings.Contains(w.Body.String(), "certificate is not trusted") {
t.Fatal("did not receive expected certificate verification failure error")
}
cdSettings.OIDCTLSInsecureSkipVerify = true
@@ -181,10 +187,57 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
app.HandleLogin(w, req)
assert.NotContains(t, w.Body.String(), "certificate is not trusted")
assert.NotContains(t, w.Body.String(), "certificate signed by unknown authority")
})
}
func Test_Login_Flow(t *testing.T) {
// Show that SSO login works when no redirect URL is provided, and we fall back to the configured base href for the
// Argo CD instance.
oidcTestServer := test.GetOIDCTestServer(t)
t.Cleanup(oidcTestServer.Close)
cdSettings := &settings.ArgoCDSettings{
URL: "https://argocd.example.com",
OIDCConfigRAW: fmt.Sprintf(`
name: Test
issuer: %s
clientID: xxx
clientSecret: yyy
requestedScopes: ["oidc"]`, oidcTestServer.URL),
OIDCTLSInsecureSkipVerify: true,
}
// The base href (the last argument for NewClientApp) is what HandleLogin will fall back to when no explicit
// redirect URL is given.
app, err := NewClientApp(cdSettings, "", "/")
require.NoError(t, err)
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "https://argocd.example.com/auth/login", nil)
app.HandleLogin(w, req)
redirectUrl, err := w.Result().Location()
require.NoError(t, err)
state := redirectUrl.Query()["state"]
req = httptest.NewRequest("GET", fmt.Sprintf("https://argocd.example.com/auth/callback?state=%s&code=abc", state), nil)
for _, cookie := range w.Result().Cookies() {
req.AddCookie(cookie)
}
w = httptest.NewRecorder()
app.HandleCallback(w, req)
assert.NotContains(t, w.Body.String(), InvalidRedirectURLError.Error())
}
func TestClientApp_HandleCallback(t *testing.T) {
oidcTestServer := test.GetOIDCTestServer(t)
t.Cleanup(oidcTestServer.Close)
@@ -211,7 +264,9 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
app.HandleCallback(w, req)
assert.Contains(t, w.Body.String(), "certificate is not trusted")
if !strings.Contains(w.Body.String(), "certificate signed by unknown authority") && !strings.Contains(w.Body.String(), "certificate is not trusted") {
t.Fatal("did not receive expected certificate verification failure error")
}
cdSettings.OIDCTLSInsecureSkipVerify = true
@@ -223,6 +278,7 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
app.HandleCallback(w, req)
assert.NotContains(t, w.Body.String(), "certificate is not trusted")
assert.NotContains(t, w.Body.String(), "certificate signed by unknown authority")
})
t.Run("dex certificate checking during oidc callback should toggle on config", func(t *testing.T) {
@@ -248,7 +304,9 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
app.HandleCallback(w, req)
assert.Contains(t, w.Body.String(), "certificate signed by unknown authority")
if !strings.Contains(w.Body.String(), "certificate signed by unknown authority") && !strings.Contains(w.Body.String(), "certificate is not trusted") {
t.Fatal("did not receive expected certificate verification failure error")
}
cdSettings.OIDCTLSInsecureSkipVerify = true
@@ -259,6 +317,7 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
app.HandleCallback(w, req)
assert.NotContains(t, w.Body.String(), "certificate is not trusted")
assert.NotContains(t, w.Body.String(), "certificate signed by unknown authority")
})
}

View File

@@ -521,8 +521,10 @@ rootCA: |
require.NoError(t, err)
_, _, err = mgr.VerifyToken(tokenString)
// If the root CA is being respected, we won't get this error.
// If the root CA is being respected, we won't get this error. The error message is environment-dependent, so
// we check for either of the error messages associated with a failed cert check.
assert.NotContains(t, err.Error(), "certificate is not trusted")
assert.NotContains(t, err.Error(), "certificate signed by unknown authority")
})
t.Run("OIDC provider is Dex, TLS is configured", func(t *testing.T) {
@@ -556,8 +558,10 @@ rootCA: |
require.NoError(t, err)
_, _, err = mgr.VerifyToken(tokenString)
assert.Error(t, err)
assert.Contains(t, err.Error(), "certificate signed by unknown authority")
require.Error(t, err)
if !strings.Contains(err.Error(), "certificate signed by unknown authority") && !strings.Contains(err.Error(), "certificate is not trusted") {
t.Fatal("did not receive expected certificate verification failure error")
}
})
t.Run("OIDC provider is external, TLS is configured", func(t *testing.T) {
@@ -591,8 +595,10 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
require.NoError(t, err)
_, _, err = mgr.VerifyToken(tokenString)
assert.Error(t, err)
assert.Contains(t, err.Error(), "certificate is not trusted")
require.Error(t, err)
if !strings.Contains(err.Error(), "certificate signed by unknown authority") && !strings.Contains(err.Error(), "certificate is not trusted") {
t.Fatal("did not receive expected certificate verification failure error")
}
})
t.Run("OIDC provider is Dex, TLS is configured", func(t *testing.T) {
@@ -626,8 +632,10 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
require.NoError(t, err)
_, _, err = mgr.VerifyToken(tokenString)
assert.Error(t, err)
assert.Contains(t, err.Error(), "certificate signed by unknown authority")
require.Error(t, err)
if !strings.Contains(err.Error(), "certificate signed by unknown authority") && !strings.Contains(err.Error(), "certificate is not trusted") {
t.Fatal("did not receive expected certificate verification failure error")
}
})
t.Run("OIDC provider is external, TLS is configured, OIDCTLSInsecureSkipVerify is true", func(t *testing.T) {
@@ -662,6 +670,7 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
require.NoError(t, err)
_, _, err = mgr.VerifyToken(tokenString)
assert.NotContains(t, err.Error(), "certificate is not trusted")
assert.NotContains(t, err.Error(), "certificate signed by unknown authority")
})
@@ -692,5 +701,6 @@ requestedScopes: ["oidc"]`, oidcTestServer.URL),
_, _, err = mgr.VerifyToken(tokenString)
// This is the error thrown when the test server's certificate _is_ being verified.
assert.NotContains(t, err.Error(), "certificate is not trusted")
assert.NotContains(t, err.Error(), "certificate signed by unknown authority")
})
}