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

fix(cmp): discover plugins relative to app path (#13940) #13946

Merged
Show file tree
Hide file tree
Changes from 3 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
20 changes: 14 additions & 6 deletions cmpserver/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func getTempDirMustCleanup(baseDir string) (workDir string, cleanup func(), err
if err := os.RemoveAll(workDir); err != nil {
log.WithFields(map[string]interface{}{
common.SecurityField: common.SecurityHigh,
common.SecurityCWEField: 459,
common.SecurityCWEField: common.SecurityCWEIncompleteCleanup,
}).Errorf("Failed to clean up temp directory: %s", err)
}
}
Expand Down Expand Up @@ -302,7 +302,7 @@ func (s *Service) matchRepositoryGeneric(stream MatchRepositoryStream) error {
return fmt.Errorf("match repository error receiving stream: %w", err)
}

isSupported, isDiscoveryEnabled, err := s.matchRepository(bufferedCtx, workDir, metadata.GetEnv())
isSupported, isDiscoveryEnabled, err := s.matchRepository(bufferedCtx, workDir, metadata.GetEnv(), metadata.GetAppRelPath())
if err != nil {
return fmt.Errorf("match repository error: %w", err)
}
Expand All @@ -315,12 +315,20 @@ func (s *Service) matchRepositoryGeneric(stream MatchRepositoryStream) error {
return nil
}

func (s *Service) matchRepository(ctx context.Context, workdir string, envEntries []*apiclient.EnvEntry) (isSupported bool, isDiscoveryEnabled bool, err error) {
func (s *Service) matchRepository(ctx context.Context, workdir string, envEntries []*apiclient.EnvEntry, appRelPath string) (isSupported bool, isDiscoveryEnabled bool, err error) {
config := s.initConstants.PluginConfig

appPath, err := securejoin.SecureJoin(workdir, appRelPath)
if err != nil {
log.WithFields(map[string]interface{}{
common.SecurityField: common.SecurityHigh,
common.SecurityCWEField: common.SecurityCWEIncompleteCleanup,
}).Errorf("error joining workdir %q and appRelPath %q: %v", workdir, appRelPath, err)
}

if config.Spec.Discover.FileName != "" {
log.Debugf("config.Spec.Discover.FileName is provided")
pattern := filepath.Join(workdir, config.Spec.Discover.FileName)
pattern := filepath.Join(appPath, config.Spec.Discover.FileName)
matches, err := filepath.Glob(pattern)
if err != nil {
e := fmt.Errorf("error finding filename match for pattern %q: %w", pattern, err)
Expand All @@ -332,7 +340,7 @@ func (s *Service) matchRepository(ctx context.Context, workdir string, envEntrie

if config.Spec.Discover.Find.Glob != "" {
log.Debugf("config.Spec.Discover.Find.Glob is provided")
pattern := filepath.Join(workdir, config.Spec.Discover.Find.Glob)
pattern := filepath.Join(appPath, config.Spec.Discover.Find.Glob)
// filepath.Glob doesn't have '**' support hence selecting third-party lib
// https://github.com/golang/go/issues/11862
matches, err := zglob.Glob(pattern)
Expand All @@ -348,7 +356,7 @@ func (s *Service) matchRepository(ctx context.Context, workdir string, envEntrie
if len(config.Spec.Discover.Find.Command.Command) > 0 {
log.Debugf("Going to try runCommand.")
env := append(os.Environ(), environ(envEntries)...)
find, err := runCommand(ctx, config.Spec.Discover.Find.Command, workdir, env)
find, err := runCommand(ctx, config.Spec.Discover.Find.Command, appPath, env)
if err != nil {
return false, true, fmt.Errorf("error running find command: %w", err)
}
Expand Down
24 changes: 12 additions & 12 deletions cmpserver/plugin/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env)
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.NoError(t, err)
Expand All @@ -115,7 +115,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env)
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.NoError(t, err)
Expand All @@ -130,7 +130,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
_, _, err := f.service.matchRepository(context.Background(), f.path, f.env)
_, _, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.ErrorContains(t, err, "syntax error")
Expand All @@ -145,7 +145,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env)
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.NoError(t, err)
Expand All @@ -162,7 +162,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env)
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.NoError(t, err)
Expand All @@ -179,7 +179,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
_, _, err := f.service.matchRepository(context.Background(), f.path, f.env)
_, _, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.ErrorContains(t, err, "error finding glob match for pattern")
Expand All @@ -196,7 +196,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env)
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.NoError(t, err)
Expand All @@ -215,7 +215,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env)
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")
// then
assert.NoError(t, err)
assert.False(t, match)
Expand All @@ -233,7 +233,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env)
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.NoError(t, err)
Expand All @@ -253,7 +253,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env)
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.NoError(t, err)
Expand All @@ -272,7 +272,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env)
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.Error(t, err)
Expand All @@ -285,7 +285,7 @@ func TestMatchRepository(t *testing.T) {
f := setup(t, withDiscover(d))

// when
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env)
match, discovery, err := f.service.matchRepository(context.Background(), f.path, f.env, ".")

// then
assert.NoError(t, err)
Expand Down
16 changes: 9 additions & 7 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,13 +321,15 @@ const (

// Security severity logging
const (
SecurityField = "security"
SecurityCWEField = "CWE"
SecurityEmergency = 5 // Indicates unmistakably malicious events that should NEVER occur accidentally and indicates an active attack (i.e. brute forcing, DoS)
SecurityCritical = 4 // Indicates any malicious or exploitable event that had a side effect (i.e. secrets being left behind on the filesystem)
SecurityHigh = 3 // Indicates likely malicious events but one that had no side effects or was blocked (i.e. out of bounds symlinks in repos)
SecurityMedium = 2 // Could indicate malicious events, but has a high likelihood of being user/system error (i.e. access denied)
SecurityLow = 1 // Unexceptional entries (i.e. successful access logs)
SecurityField = "security"
SecurityCWEField = "CWE"
SecurityCWEIncompleteCleanup = 459
SecurityCWEMissingReleaseOfFileDescriptor = 775
SecurityEmergency = 5 // Indicates unmistakably malicious events that should NEVER occur accidentally and indicates an active attack (i.e. brute forcing, DoS)
SecurityCritical = 4 // Indicates any malicious or exploitable event that had a side effect (i.e. secrets being left behind on the filesystem)
SecurityHigh = 3 // Indicates likely malicious events but one that had no side effects or was blocked (i.e. out of bounds symlinks in repos)
SecurityMedium = 2 // Could indicate malicious events, but has a high likelihood of being user/system error (i.e. access denied)
SecurityLow = 1 // Unexceptional entries (i.e. successful access logs)
)

// TokenVerificationError is a generic error message for a failure to verify a JWT
Expand Down
4 changes: 2 additions & 2 deletions docs/operator-manual/config-management-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ spec:
# Only one of fileName, find.glob, or find.command should be specified. If multiple are specified then only the
# first (in that order) is evaluated.
discover:
# fileName is a glob pattern (https://pkg.go.dev/path/filepath#Glob) that is applied to the repository's root
# directory (not the Application source directory). If there is a match, this plugin may be used for the repository.
# fileName is a glob pattern (https://pkg.go.dev/path/filepath#Glob) that is applied to the Application's source
# directory. If there is a match, this plugin may be used for the Application.
fileName: "./subdir/s*.yaml"
find:
# This does the same thing as fileName, but it supports double-start (nested directory) glob patterns.
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/bradleyfalzon/ghinstallation/v2 v2.4.0
github.com/casbin/casbin/v2 v2.69.1
github.com/coreos/go-oidc/v3 v3.6.0
github.com/cyphar/filepath-securejoin v0.2.3
github.com/dustin/go-humanize v1.0.1
github.com/evanphx/json-patch v5.6.0+incompatible
github.com/fsnotify/fsnotify v1.6.0
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/testdata/cmp-fileName/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ spec:
generate:
command: [sh, -c, 'echo "{\"kind\": \"ConfigMap\", \"apiVersion\": \"v1\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"Foo\": \"$FOO\", \"KubeVersion\": \"$KUBE_VERSION\", \"KubeApiVersion\": \"$KUBE_API_VERSIONS\",\"Bar\": \"baz\"}}}"']
discover:
fileName: "cmp-fileName/subdir/s*.yaml"
fileName: "subdir/s*.yaml"
8 changes: 4 additions & 4 deletions util/app/discovery/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func DetectConfigManagementPlugin(ctx context.Context, appPath, repoPath, plugin
pluginSockFilePath := common.GetPluginSockFilePath()
log.WithFields(log.Fields{
common.SecurityField: common.SecurityLow,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Debugf("pluginSockFilePath is: %s", pluginSockFilePath)

if pluginName != "" {
Expand Down Expand Up @@ -160,7 +160,7 @@ func cmpSupports(ctx context.Context, pluginSockFilePath, appPath, repoPath, fil
if err != nil {
log.WithFields(log.Fields{
common.SecurityField: common.SecurityMedium,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Errorf("error dialing to cmp-server for plugin %s, %v", fileName, err)
return nil, nil, false
}
Expand All @@ -169,7 +169,7 @@ func cmpSupports(ctx context.Context, pluginSockFilePath, appPath, repoPath, fil
if err != nil {
log.WithFields(log.Fields{
common.SecurityField: common.SecurityMedium,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Errorf("repository %s is not the match because %v", repoPath, err)
io.Close(conn)
return nil, nil, false
Expand All @@ -182,7 +182,7 @@ func cmpSupports(ctx context.Context, pluginSockFilePath, appPath, repoPath, fil
}
log.WithFields(log.Fields{
common.SecurityField: common.SecurityLow,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Debugf("Reponse from socket file %s does not support %v", fileName, repoPath)
io.Close(conn)
return nil, nil, false
Expand Down
4 changes: 2 additions & 2 deletions util/cert/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func ParseTLSCertificatesFromPath(sourceFile string) ([]string, error) {
if err = fileHandle.Close(); err != nil {
log.WithFields(log.Fields{
common.SecurityField: common.SecurityMedium,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Errorf("error closing file %q: %v", fileHandle.Name(), err)
}
}()
Expand Down Expand Up @@ -199,7 +199,7 @@ func ParseSSHKnownHostsFromPath(sourceFile string) ([]string, error) {
if err = fileHandle.Close(); err != nil {
log.WithFields(log.Fields{
common.SecurityField: common.SecurityMedium,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Errorf("error closing file %q: %v", fileHandle.Name(), err)
}
}()
Expand Down
2 changes: 1 addition & 1 deletion util/git/creds.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ func (c SSHCreds) Environ() (io.Closer, []string, error) {
if err = file.Close(); err != nil {
log.WithFields(log.Fields{
common.SecurityField: common.SecurityMedium,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Errorf("error closing file %q: %v", file.Name(), err)
}
}()
Expand Down
8 changes: 4 additions & 4 deletions util/gpg/gpg.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func writeKeyToFile(keyData string) (string, error) {
if err != nil {
log.WithFields(log.Fields{
common.SecurityField: common.SecurityMedium,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Errorf("error closing file %q: %v", f.Name(), err)
}
}()
Expand Down Expand Up @@ -275,7 +275,7 @@ func InitializeGnuPG() error {
if err != nil {
log.WithFields(log.Fields{
common.SecurityField: common.SecurityMedium,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Errorf("error closing file %q: %v", f.Name(), err)
}
}()
Expand All @@ -302,7 +302,7 @@ func ImportPGPKeysFromString(keyData string) ([]*appsv1.GnuPGPublicKey, error) {
if err != nil {
log.WithFields(log.Fields{
common.SecurityField: common.SecurityMedium,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Errorf("error closing file %q: %v", f.Name(), err)
}
}()
Expand Down Expand Up @@ -430,7 +430,7 @@ func SetPGPTrustLevel(pgpKeys []*appsv1.GnuPGPublicKey, trustLevel string) error
if err != nil {
log.WithFields(log.Fields{
common.SecurityField: common.SecurityMedium,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Errorf("error closing file %q: %v", f.Name(), err)
}
}()
Expand Down
2 changes: 1 addition & 1 deletion util/helm/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func writeToTmp(data []byte) (string, argoio.Closer, error) {
if err = file.Close(); err != nil {
log.WithFields(log.Fields{
common.SecurityField: common.SecurityMedium,
common.SecurityCWEField: 775,
common.SecurityCWEField: common.SecurityCWEMissingReleaseOfFileDescriptor,
}).Errorf("error closing file %q: %v", file.Name(), err)
}
}()
Expand Down