-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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 permissions for config files used in tests #42914
base: main
Are you sure you want to change the base?
Conversation
This pull request does not have a backport label.
To fixup this pull request, you need to add the backport labels for the needed
|
The tests which rely on reading config from disk did not correctly set the permissions. The beats require the config files must be writable only by the owner, now the tests explicitly set the permissions accordingly. A new `testcfg` package provides `NewFileWith644Perm` and `CopyDirectoryWithOwnerWriteOnly` as helper functions for tests to create a temporary copy of the files committed to the repo to use in the test. The test framework was also adjusted to save the config file with the correct permission.
0151d2e
to
dc61260
Compare
Pinging @elastic/elastic-agent-data-plane (Team:Elastic-Agent-Data-Plane) |
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'm not convinced we need an entire package with helpers. Especially copying files just to change permissions does not seem justified.
Instead I think we should fix permissions on the existing files use for testing. Or assert permissions as a part of the tests.
If we create files we have full control over permissions, so we just need to fix these occurrences.
filebeat/fileset/fileset_test.go
Outdated
@@ -41,17 +42,24 @@ func makeTestInfo(version string) beat.Info { | |||
} | |||
} | |||
|
|||
func getModuleForTesting(t *testing.T, module, fileset string) *Fileset { | |||
func getModuleForTesting(t *testing.T, module, fileset string, filesetCfg *FilesetConfig) *Fileset { |
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.
Why filesetCfg *FilesetConfig
was introduced if it's always nil
in all usages? Can't we just always pass nil
to the New
function?
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.
it's not always nil:
- https://github.com/AndersonQ/beats/blob/dc6126016cfa68a6c8b6b86e1506b6b803d7477f/filebeat/fileset/fileset_test.go#L107
- https://github.com/AndersonQ/beats/blob/dc6126016cfa68a6c8b6b86e1506b6b803d7477f/filebeat/fileset/fileset_test.go#L243
that's why it was introduced as a parameter. getModuleForTesting
ensures the configuration files will have the correct permissions, thus I changed TestEvaluateVarsNginxOverride
and TestGetInputConfigNginxOverrides
to call it instead of calling New
directly
filebeat/fileset/modules_test.go
Outdated
fixedModulesPath := testcfg.CopyDirectoryWithOwnerWriteOnly(t, modulesPath, "") | ||
reg, err := newModuleRegistry(fixedModulesPath, configs, nil, beat.Info{Version: "5.2.0"}, FilesetOverrides{}) |
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.
Why do we need copy? Why can't we assert permissions and change them on the existing files?
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 don't think tests should be doing permanent changes on the repo, that's why I took this approach of copying the files as it isn't possible to commit the full file permission to git.
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 don't think tests should be doing permanent changes on the repo, that's why I took this approach of copying the files as it isn't possible to commit the full file permission to git.
This is not entirely true, git stores permissions but only 2 possible values 644 and 755 which you can set/switch with git update-index --chmod=+x
.
So, unless you switch the executable flag, git would not detect permission changes and for git the repository remains untouched.
I still don't think that copying files is a good idea, it increases the load on CI for no reason and complicates our tests.
We should create files with right permissions and assert files to be with right permissions without copying files. The only exception is when the test data is supposed to be changed by the test.
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 don't think tests should be doing permanent changes on the repo, that's why I took this approach of copying the files as it isn't possible to commit the full file permission to git.
I don't see it as a permanent change, it's a part of the test setup to make sure that the permissions on the test files are correct. We would not commit these changes to the repository, so I'm confused about "permanent" here.
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.
"permanent" as in after the test run the original state of the files won't be restored.
it increases the load on CI for no reason and complicates our tests.
I don't think there is concrete evidence this overhead will be significant. We probably have other things that can be improved if we want to make CI performance better.
I still don't think that copying files is a good idea
I don't see why it's a problem, given as I said above I don't believe the overhead is any issue. Much more problematic is the unit tests making permanent changes to files. That's why I don't see as a good solution a "single function Ensure644
that walks the directory, and sets 644 permission to every file".
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.
Rather than writing a bunch of code to solve this, my thought would be to just relax the permissions checks in the beats during these tests.
It turns out we have had this problem before and there is already a flag that does this, --strict-perms. It is also available as the BEAT_STRICT_PERMS environment variable:
beats/libbeat/common/config.go
Lines 37 to 44 in f1e42fc
// IsStrictPerms returns true if strict permission checking on config files is | |
// enabled. | |
func IsStrictPerms() bool { | |
if !*flagStrictPerms || os.Getenv("BEAT_STRICT_PERMS") == "false" { | |
return false | |
} | |
return true | |
} |
It turns off exactly the error we are seeing:
beats/libbeat/common/config.go
Lines 79 to 84 in f1e42fc
func LoadFile(path string) (*config.C, error) { | |
if IsStrictPerms() { | |
if err := OwnerHasExclusiveWritePerms(path); err != nil { | |
return nil, err | |
} | |
} |
Pretty much every metricbeat module test already sets this. It is very widely used in our other tests. https://github.com/search?q=repo%3Aelastic%2Fbeats%20BEAT_STRICT_PERMS&type=code
Can we make this problem go away by using --strict.perms=false
or BEAT_STRICT_PERMS=false
in the new framework instead?
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.
@AndersonQ FYI: we already set permissions to a Filebeat configuration file in another test
beats/libbeat/cmd/instance/beat_test.go
Lines 91 to 97 in ca4ad40
const configPath = "../test/filebeat_test.yml" | |
// Ensure that the config has owner-exclusive write permissions. | |
// This is necessary on some systems which have a default umask | |
// of 0o002, meaning that files are checked out by git with mode | |
// 0o664. This would cause cfgfile.Load to fail. | |
err = os.Chmod(configPath, 0o644) |
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.
It turns out we have had this problem before and there is already a flag that does this, --strict-perms. It is also available as the BEAT_STRICT_PERMS environment variable:
that's interesting. I'll set it them
I confess I wonder why we have this strict permission requirement in place.
Git does not save the full set of permissions, it only saves if the file is executable or not. So we can't just fix the permissions on the git repo. Also having the test permanently changing the files does not seems a good approach.
If we do it in runtime, yes, I just believe the current approach is better than changing all the affected tests to create the files in runtime.
as I said above, the alternative would be to make all the tests to create the files in runtime. It's an option, but I think the current approach is less intrusive. |
@AndersonQ can we just create a single function As I explained #42914 (comment) git should not detect changes unless the executable flag is flipped. |
Considering this is only fixing tests, shouldn't we backport this to all active branches? |
set `strict.perms` flag to false on test that load config files committed to the repo. By default beats require the config files to be writable only by the file owner, so tests reading config files committed do the repo might fail depending on how the host system is configured. For those tests the permission check is relaxed.
done |
I followed Craig's suggestion and relaxed the permission check instead. |
Proposed commit message
Checklist
[ ] I have made corresponding changes to the documentation[ ] I have made corresponding change to the default configuration filesCHANGELOG.next.asciidoc
orCHANGELOG-developer.next.asciidoc
.Disruptive User Impact
How to test this PR locally
tl;dr: no unit/system test should fail due to a configuration file with the wrong permissions.
Related issues