-
Notifications
You must be signed in to change notification settings - Fork 6k
feat: Additional audit log information for updating argocd applications (resolves #23130) #23131
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
base: master
Are you sure you want to change the base?
feat: Additional audit log information for updating argocd applications (resolves #23130) #23131
Conversation
🔴 Preview Environment stopped on BunnyshellSee: Environment Details | Pipeline Logs Available commands (reply to this comment):
|
a9b7183
to
f3b95b8
Compare
8736a80
to
6b89a71
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #23131 +/- ##
==========================================
+ Coverage 59.98% 60.04% +0.05%
==========================================
Files 343 343
Lines 57890 57992 +102
==========================================
+ Hits 34727 34819 +92
- Misses 20381 20384 +3
- Partials 2782 2789 +7 ☔ View full report in Codecov by Sentry. |
server/application/application.go
Outdated
@@ -987,6 +991,23 @@ func (s *Server) updateApp(ctx context.Context, app *v1alpha1.Application, newAp | |||
return nil, status.Errorf(codes.Internal, "Failed to update application. Too many conflicts") | |||
} | |||
|
|||
func diffBetweenApplicationSpecs(a *v1alpha1.ApplicationSpec, b *v1alpha1.ApplicationSpec) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple suggestions:
- I'd unmarshal the patch into a map[any]any and log it as its own field, so it's parseable by log tools
- I'd exclude the patch from the event: some people put huge stuff in their app spec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @crenshaw-dev - thanks for the review.
I've pushed changes based on my understanding of your feedback, if you wouldn't mind another look.
I've pushed logFields right up to the top of logAppEvent so future audit context can be added more easily.
@@ -2028,16 +2053,16 @@ func (s *Server) Sync(ctx context.Context, syncReq *application.ApplicationSyncR | |||
if len(syncReq.Resources) > 0 { | |||
partial = "partial " | |||
} | |||
var reason string | |||
var action string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is an "action", not a "reason".
argo.EventReasonOperationStarted is the reason, so makes sense to update this.
6ed819b
to
600ffc3
Compare
@@ -68,7 +68,7 @@ func (l *AuditLogger) logEvent(objMeta ObjectRef, gvk schema.GroupVersionKind, i | |||
ObjectMeta: metav1.ObjectMeta{ | |||
Name: fmt.Sprintf("%v.%x", objMeta.Name, t.UnixNano()), | |||
Labels: eventLabels, | |||
Annotations: logFields, | |||
Annotations: eventAnnotations, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to start adding information into logFields which won't make their way into the event, we need to split this parameter into two.
This is why the PR has exploded in size.
server/application/application.go
Outdated
@@ -956,6 +956,10 @@ func (s *Server) waitSync(app *v1alpha1.Application) { | |||
} | |||
|
|||
func (s *Server) updateApp(ctx context.Context, app *v1alpha1.Application, newApp *v1alpha1.Application, merge bool) (*v1alpha1.Application, error) { | |||
applicationPatch, err := diffBetweenApplicationSpecs(&app.Spec, &newApp.Spec) | |||
if err != nil { | |||
return nil, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's wrap this error for easier debugging.
server/application/application.go
Outdated
@@ -956,6 +956,10 @@ func (s *Server) waitSync(app *v1alpha1.Application) { | |||
} | |||
|
|||
func (s *Server) updateApp(ctx context.Context, app *v1alpha1.Application, newApp *v1alpha1.Application, merge bool) (*v1alpha1.Application, error) { | |||
applicationPatch, err := diffBetweenApplicationSpecs(&app.Spec, &newApp.Spec) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the spec enough? Should we also get metadata?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added metadata, I didn't really care about it for my purposes but I think adding metadata is helpful as annotations might be set on the application which affects behaviour.
server/application/application.go
Outdated
logFields := make(map[string]string) | ||
logFields["patch"] = applicationPatch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can probably initialize the map inline. Not a big deal, might just look nicer. :-)
server/application/application.go
Outdated
if err != nil { | ||
return "", fmt.Errorf("failed to create json diff between applications: %w", err) | ||
} | ||
return string(patch), nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to unmarshal the patch into a map[string]any so log tools aren't forced to parse a JSON string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made this change
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Signed-off-by: Tom Hellier <[email protected]>
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Signed-off-by: Tom Hellier <[email protected]>
268938a
to
88859e0
Compare
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Signed-off-by: Tom Hellier <[email protected]>
88859e0
to
6a44c05
Compare
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Signed-off-by: Tom Hellier <[email protected]>
6a44c05
to
7ccfff1
Compare
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Signed-off-by: Tom Hellier <[email protected]>
7ccfff1
to
7e4ec0b
Compare
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Signed-off-by: Tom Hellier <[email protected]>
7e4ec0b
to
7e406e0
Compare
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Also support the diff on updates to ApplicationSpecs. Signed-off-by: Tom Hellier <[email protected]>
7e406e0
to
fc255a6
Compare
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Also support the diff on updates to ApplicationSpecs. Signed-off-by: Tom Hellier <[email protected]>
fc255a6
to
f1c4d4a
Compare
I've marked as a draft as I haven't had a chance to test the latest changes with a real Argo CD deployment, with some logging tool (like loki), and the kubernetes event log. I'll probably be able to do this early next week and upload some screenshots. I've also extended the diff logging to include ApplicationSets. I've copied the |
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Also support the diff on updates to ApplicationSpecs. Signed-off-by: Tom Hellier <[email protected]>
f1c4d4a
to
32e4e65
Compare
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Also support the diff on updates to ApplicationSpecs. Signed-off-by: Tom Hellier <[email protected]>
32e4e65
to
2341772
Compare
Hey @crenshaw-dev, please could I get another review at your convenience, thanks. |
… be clear about what was changed in the application spec. This change allows auditors to understand the difference in an update. For example, if a user sets a helm parameter override, or points the application at a branch in the webui. Auditing should reflect that. This information will also get included in the kubernetes event log, but I think that is ok as I wouldn't expect very large differences between applications. Signed-off-by: Tom Hellier <[email protected]>
…what are annotations vs logs It looks like logFields were previously being dual used as annotations on the event, so splitting logFields into logFields and eventAnnotations, as we want to start using logFields to log additional information in the audit log. This could be expanded in future PRs to add more context to the audit logs. Signed-off-by: Tom Hellier <[email protected]>
…as logFields Addressing code review comments as part of argoproj#23131, also added the error to the logFields for appcontroller to stop unparam lint. It makes sense to keep the logFields in that function call despite nothing using it at the moment, so may as well pass in the error string. Converted the json string into a map[string]any as that is what sirupsen/logrus expects for the WithField api. Also support the diff on updates to ApplicationSpecs. Signed-off-by: Tom Hellier <[email protected]>
The logfield for patch has changed from a json style to a go `map[string]interface{}`. Signed-off-by: Tom Hellier <[email protected]>
d3363b2
to
5e51f31
Compare
When users update applications in the argocd ui, the audit log should be clear about what was changed in the application/applicationset. This change allows auditors to understand the difference in an update.
For example, if a user sets a helm parameter override, or points the application at a branch in the webui. Auditing should reflect that.
This information will not get included in the kubernetes event log, you can include very large differences in a
spec.source.helm.values
field, and it would clutter the kubernetes event log.This change also adds logFields to the various calls to logAppEvent to allow future developers to add arbitrary contents to the audit logs.
Log Output (changed)

Kubernetes Event Output (unchanged)


Closes [ISSUE #23130]
Checklist: