-
Notifications
You must be signed in to change notification settings - Fork 5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: diff against application manifest (#4706) #12813
base: master
Are you sure you want to change the base?
Conversation
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## master #12813 +/- ##
==========================================
- Coverage 47.77% 47.69% -0.08%
==========================================
Files 246 246
Lines 41985 42073 +88
==========================================
+ Hits 20057 20066 +9
- Misses 19929 20008 +79
Partials 1999 1999
... and 2 files with indirect coverage changes Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report in Codecov by Sentry. |
@crenshaw-dev, I'm not too sure I'm in line with requiring
As for this, I'm not too sure I follow whatyou mean by determining fields to be set and enabling them one-by-one. |
@MeNsaaH very fair, I don't love it either.
So, here's an example of a problem that I think makes it unsafe to enable diffing with just apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
spec:
source:
repoURL: https://github.com/argoproj/argocd-example-apps.git
plugin:
env:
- name: POST_PROCESSOR_CMD
value: "sed 's/:<tag>/:1.2.3/'" The plugin designer uses an env var to run some arbitrary command after generating manifests. That's safe, as long as users aren't allowed to But if I allow the user to send an arbitrary application.yaml for diffing, they could provide a malicious command in that env var. So I think So instead of accepting What do you think? It's possible I'm being too paranoid, but I want to be very careful about code that runs on the repo-server. |
Alternatively, we could allow-list certain fields. The API server could ignore any out-of-bounds fields and return a warning to the user, "Hey, we ignored the changes you made to field X because it's unsafe to let you set that." |
Oh, I see now what direction you're coming from. And agree that it might need elevated permissions. I'm however not sure for most people, but for me this is mostly just basic diffs, but yeah I see the vulnerability here.
I think it's a valid concern. |
For better DX, I think we could go with this. And maybe an option in the settings file to show these changes. I'm just curious how argocd will know what changes are safe to display and what changes aren't |
This would be my initial allow-list proposal: spec:
source:
targetRevision: # could let you poke around git
helm:
parameters: # gets env-substituted, so you could get the destination k8s API version and versions of all CRDs on the k8s API - maybe not important?
releaseName:
ignoreMissingValueFiles:
values:
skipCrds:
version:
kustomize:
version:
namePrefix:
nameSuffix:
commonLabels:
forceCommonLabels:
commonAnnotations:
commonAnnotationsEnvsubst:
forceCommonAnnotations:
images:
namespace:
replicas:
destination:
namespace: I'm a bit hesitant about So these fields would be blocked: spec:
project:
source:
repoURL:
path:
chart:
helm:
passCredentials:
fileParameters: # would let you poke around git - arbitrary file types
valueFiles: # would let you poke around git - yaml/json files
directory:
recurse: # would let you poke around git
jsonnet: # idk anything about jsonnet, so assuming it's all unsafe
extVars:
tlas:
exclude: # would let you poke around git - manifest files
include: # would let you poke around git - manifest files
plugin: # who knows what plugins do, block it all
name:
env:
parameters:
destination:
server:
# none of the rest is even relevant for manifest generation
syncPolicy:
automated:
prune:
selfHeal:
allowEmpty:
syncOptions:
managedNamespaceMetadata:
labels:
annotations:
retry:
limit:
backoff:
duration:
factor:
maxDuration:
ignoreDifferences:
revisionHistoryLimit:
info: Do any of those seem particularly problematic to block? |
I see alot of people using |
How do you feel about this more permissive allow-list? spec:
source:
targetRevision:
path:
helm:
parameters:
releaseName:
ignoreMissingValueFiles:
values:
fileParameters:
valueFiles:
skipCrds:
version:
kustomize:
version:
namePrefix:
nameSuffix:
commonLabels:
forceCommonLabels:
commonAnnotations:
commonAnnotationsEnvsubst:
forceCommonAnnotations:
images:
namespace:
replicas:
directory:
recurse:
exclude:
include:
plugin: # who knows what plugins do, block it all
name:
env:
parameters:
destination:
namespace: Deny-list: spec:
project:
source:
repoURL:
chart:
helm:
passCredentials:
directory:
jsonnet: # idk anything about jsonnet, so assuming it's all unsafe
extVars:
tlas:
destination:
server:
# none of the rest is even relevant for manifest generation
syncPolicy:
automated:
prune:
selfHeal:
allowEmpty:
syncOptions:
managedNamespaceMetadata:
labels:
annotations:
retry:
limit:
backoff:
duration:
factor:
maxDuration:
ignoreDifferences:
revisionHistoryLimit:
info: I think in this case we'd want to offer an off-by-default feature flag. # By enabling this, you allow users with `applications, get` access to use the "Application diff API" (e.g.
# `argocd app diff --app my-app.yaml`).
# IMPORTANT:
# This effectively gives those users full read access to the applications' source repositories, because they
# can run manifest generation with modified source fields such as `path` and `helm.fileParameters`.
# If you use Config Management Plugins, this also gives users with `applications, get` access to run
# manifest generation with modified plugin parameters. Make sure it is safe for these users to pass
# arbitrary parameters to your plugins before enabling this feature.
server.enable.full.application.diff: "false" |
We could also do a pre-check for |
I'm in for this. Sounds concrete. |
I'd love to see this feature. My feedback: This approach still means we need to find the updated apps manifests and run this diff command for each. It would be amazing if we could pass an option to the original (e.g. if I have an Application object pointing at my repo, currently I do an |
Makes sense. And I agree, this will probably be the case for most users.
I think for the first implementation, we'd leave that to the user to implement in BASH or similar. But does sound like a useful tool to add once the first iteration is done. |
Just planned out my 2.8 time, and I don't think I'll be able to squeeze this in. If someone wants to pick up the PR, I'd be happy to help guide the implementation and do a review! |
@crenshaw-dev I'd try and see if I can pick out time this week to work on this. |
@MeNsaaH just lmk if you need any help! |
This change allows diffing a live application manifests vs. what the manifests would look like if some arbitrary app manifests were applied.
One major limitation is that the user must have "update" permissions for the target application in order to get this diff. It seems possible that an Argo CD operator might give someone "get" permission on an application with the belief that the user can't do certain potentially-sensitive actions (like change the source's path to reveal contents of another directory, or set a sensitive env var in a plugin).
I understand that one main use case for this command is in CI pipelines to predict the result of a given change. This limitation would force users to set an update-capable token in their CI, even though their CI doesn't really need to update anything.
If this limitation is too problematic, I suggest we tackle the problem from the other direction: instead of allowing users to pass a full, new application spec, we should determine which fields we want to set and enable them one-by-one as we determine their safety (as we did for
--revision
).Looking forward to everyone's thoughts!
Closes #4706