Skip to content
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: Add ability to hide certain annotations on secret resources #18216

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion controller/appcontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ func (ctrl *ApplicationController) hideSecretData(app *appv1.Application, compar
resDiff := res.Diff
if res.Kind == kube.SecretKind && res.Group == "" {
var err error
target, live, err = diff.HideSecretData(res.Target, res.Live)
target, live, err = diff.HideSecretData(res.Target, res.Live, ctrl.settingsMgr.GetSensitiveAnnotations())
if err != nil {
return nil, fmt.Errorf("error hiding secret data: %w", err)
}
Expand Down
5 changes: 4 additions & 1 deletion docs/operator-manual/argocd-cm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ data:
clusters:
- "*.local"
# An optional comma-separated list of annotation keys to mask in UI/CLI on secret resources
resource.sensitive.mask.annotations: openshift.io/token-secret.value,api-key

# An optional comma-separated list of metadata.labels to observe in the UI.
resource.customLabels: tier

Expand Down Expand Up @@ -428,4 +431,4 @@ data:
webhook.maxPayloadSizeMB: 1024

# application.sync.impersonation.enabled indicates whether the application sync can be decoupled from control plane service account using impersonation.
application.sync.impersonation.enabled: "false"
application.sync.impersonation.enabled: "false"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt you want to remove the end of line from the end of the file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops! My bad. Must have removed it while cleaning up the code. Will fix it.

2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/argoproj/argo-cd/v2

go 1.22.0

replace github.com/argoproj/gitops-engine => github.com/svghadi/gitops-engine v0.0.0-20240924111555-916f64e5c445

require (
code.gitea.io/sdk/gitea v0.19.0
github.com/Azure/kubelogin v0.0.20
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ github.com/antonmedv/expr v1.15.1/go.mod h1:0E/6TxnOlRNp81GMzX9QfDPAmHo2Phg00y4J
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/appscode/go v0.0.0-20191119085241-0887d8ec2ecc/go.mod h1:OawnOmAL4ZX3YaPdN+8HTNwBveT1jMsqP74moa9XUbE=
github.com/argoproj/gitops-engine v0.7.1-0.20240917171920-72bcdda3f0a5 h1:K/e+NsNmE4BccRu21QpqUxkTHxU9YWjU3M775Ck+V/E=
github.com/argoproj/gitops-engine v0.7.1-0.20240917171920-72bcdda3f0a5/go.mod h1:b1vuwkyMUszyUK+USUJqC8vJijnQsEPNDpC+sDdDLtM=
github.com/argoproj/notifications-engine v0.4.1-0.20240606074338-0802cd427621 h1:Yg1nt+D2uDK1SL2jSlfukA4yc7db184TTN7iWy3voRE=
github.com/argoproj/notifications-engine v0.4.1-0.20240606074338-0802cd427621/go.mod h1:N0A4sEws2soZjEpY4hgZpQS8mRIEw6otzwfkgc3g9uQ=
github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1 h1:qsHwwOJ21K2Ao0xPju1sNuqphyMnMYkyB3ZLoLtxWpo=
Expand Down Expand Up @@ -931,6 +929,8 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/svghadi/gitops-engine v0.0.0-20240924111555-916f64e5c445 h1:PkAFzTdKNs1jwwBfIivNj3mUufwjKPvzANiVEgctmsw=
github.com/svghadi/gitops-engine v0.0.0-20240924111555-916f64e5c445/go.mod h1:b1vuwkyMUszyUK+USUJqC8vJijnQsEPNDpC+sDdDLtM=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
Expand Down
14 changes: 7 additions & 7 deletions server/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
return nil, fmt.Errorf("error unmarshaling manifest into unstructured: %w", err)
}
if obj.GetKind() == kube.SecretKind && obj.GroupVersionKind().Group == "" {
obj, _, err = diff.HideSecretData(obj, nil)
obj, _, err = diff.HideSecretData(obj, nil, s.settingsMgr.GetSensitiveAnnotations())
if err != nil {
return nil, fmt.Errorf("error hiding secret data: %w", err)
}
Expand Down Expand Up @@ -677,7 +677,7 @@ func (s *Server) GetManifestsWithFiles(stream application.ApplicationService_Get
return fmt.Errorf("error unmarshaling manifest into unstructured: %w", err)
}
if obj.GetKind() == kube.SecretKind && obj.GroupVersionKind().Group == "" {
obj, _, err = diff.HideSecretData(obj, nil)
obj, _, err = diff.HideSecretData(obj, nil, s.settingsMgr.GetSensitiveAnnotations())
if err != nil {
return fmt.Errorf("error hiding secret data: %w", err)
}
Expand Down Expand Up @@ -1362,7 +1362,7 @@ func (s *Server) GetResource(ctx context.Context, q *application.ApplicationReso
if err != nil {
return nil, fmt.Errorf("error getting resource: %w", err)
}
obj, err = replaceSecretValues(obj)
obj, err = s.replaceSecretValues(obj)
if err != nil {
return nil, fmt.Errorf("error replacing secret values: %w", err)
}
Expand All @@ -1374,9 +1374,9 @@ func (s *Server) GetResource(ctx context.Context, q *application.ApplicationReso
return &application.ApplicationResourceResponse{Manifest: &manifest}, nil
}

func replaceSecretValues(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
func (s *Server) replaceSecretValues(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
if obj.GetKind() == kube.SecretKind && obj.GroupVersionKind().Group == "" {
_, obj, err := diff.HideSecretData(nil, obj)
_, obj, err := diff.HideSecretData(nil, obj, s.settingsMgr.GetSensitiveAnnotations())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1413,7 +1413,7 @@ func (s *Server) PatchResource(ctx context.Context, q *application.ApplicationRe
if manifest == nil {
return nil, fmt.Errorf("failed to patch resource: manifest was nil")
}
manifest, err = replaceSecretValues(manifest)
manifest, err = s.replaceSecretValues(manifest)
if err != nil {
return nil, fmt.Errorf("error replacing secret values: %w", err)
}
Expand Down Expand Up @@ -2169,7 +2169,7 @@ func (s *Server) ListResourceLinks(ctx context.Context, req *application.Applica
return nil, fmt.Errorf("failed to read application deep links from configmap: %w", err)
}

obj, err = replaceSecretValues(obj)
obj, err = s.replaceSecretValues(obj)
if err != nil {
return nil, fmt.Errorf("error replacing secret values: %w", err)
}
Expand Down
24 changes: 24 additions & 0 deletions util/settings/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ const (
resourceInclusionsKey = "resource.inclusions"
// resourceIgnoreResourceUpdatesEnabledKey is the key to a boolean determining whether the resourceIgnoreUpdates feature is enabled
resourceIgnoreResourceUpdatesEnabledKey = "resource.ignoreResourceUpdatesEnabled"
// resourceSensitiveAnnotationsKey is the key to list of annotations to mask in secret resource
resourceSensitiveAnnotationsKey = "resource.sensitive.mask.annotations"
// resourceCustomLabelKey is the key to a custom label to show in node info, if present
resourceCustomLabelsKey = "resource.customLabels"
// resourceIncludeEventLabelKeys is the key to labels to be added onto Application k8s events if present on an Application or it's AppProject. Supports wildcard.
Expand Down Expand Up @@ -2317,6 +2319,28 @@ func (mgr *SettingsManager) GetExcludeEventLabelKeys() []string {
return labelKeys
}

func (mgr *SettingsManager) GetSensitiveAnnotations() map[string]bool {
annotationKeys := make(map[string]bool)

argoCDCM, err := mgr.getConfigMap()
if err != nil {
log.Error(fmt.Errorf("failed getting configmap: %w", err))
return annotationKeys
}

value, ok := argoCDCM.Data[resourceSensitiveAnnotationsKey]
if !ok || value == "" {
return annotationKeys
}

value = strings.ReplaceAll(value, " ", "")
keys := strings.Split(value, ",")
for _, k := range keys {
annotationKeys[k] = true
}
return annotationKeys
}

func (mgr *SettingsManager) GetMaxWebhookPayloadSize() int64 {
argoCDCM, err := mgr.getConfigMap()
if err != nil {
Expand Down
34 changes: 34 additions & 0 deletions util/settings/settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1725,3 +1725,37 @@ func TestRedirectAdditionalURLs(t *testing.T) {
})
}
}

func TestSettingsManager_GetSensitiveAnnotations(t *testing.T) {
tests := []struct {
name string
input string
output map[string]bool
}{
{
name: "Empty input",
input: "",
output: map[string]bool{},
},
{
name: "Comma separated data",
input: "example.com/token-secret.value,token,key",
output: map[string]bool{"example.com/token-secret.value": true, "token": true, "key": true},
},
{
name: "Comma separated data with space",
input: "example.com/token-secret.value, token, key",
output: map[string]bool{"example.com/token-secret.value": true, "token": true, "key": true},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, settingsManager := fixtures(map[string]string{
resourceSensitiveAnnotationsKey: tt.input,
})
keys := settingsManager.GetSensitiveAnnotations()
assert.Equal(t, len(tt.output), len(keys))
assert.Equal(t, tt.output, keys)
})
}
}