Closed jarppiko closed 1 year ago
Thanks @jarppiko for the analysis. Here I may have missed something because I tried to generalize a behavior that we implemented on some, but not all packages.
Are you saying this: https://github.com/crowdsecurity/crowdsec/blob/master/pkg/types/utils.go#L43
is not required anymore? I am asking because you said the issue has been fixed 4 years ago, and CrowdSec did not exist back then.
If you mean we can set umask in the systemd service, I'm not sure we want to do it for every file that is created. Or we can always add a configuration setting.
what do you think @buixor
Hi @mmetc ,
How lumberjack
works is that it creates a new file (and the required directory tree) by itself during the first Logger.write()
call. So there is no need to create the log file by an application, just to give filename. This can be seen see in lumberjack.go lines 146-150:
func (l *Logger) Write(p []byte) (n int, err error) {
l.mu.Lock()
defer l.mu.Unlock()
writeLen := int64(len(p))
if writeLen > l.max() {
return 0, fmt.Errorf(
"write length %d exceeds maximum file size %d", writeLen, l.max(),
)
}
// ----------------------- beef is here @jarppiko -------------
if l.file == nil {
if err = l.openExistingOrNew(len(p)); err != nil {
return 0, err
}
}
// -------------------------------------------------------------
if l.size+writeLen > l.max() {
if err := l.rotate(); err != nil {
return 0, err
}
}
n, err = l.file.Write(p)
l.size += int64(n)
return n, err
}
By default, lumberjack
sets file permissions to 0600
:
Logger.write()
calls openExistingOrNew()
openExistingOrNew()
calls openNew()
if the file does not existsopenNew()
creates dir tree if needed (0755
❗) and the file (0600
)Hello @mmetc,
My comments:
Are you saying this: https://github.com/crowdsecurity/crowdsec/blob/master/pkg/types/utils.go#L43
is not required anymore?
The file you referred to relates to crowdsec
, not cs-firewall-bouncer
. But the same comment applies - I do not think the file creation needed there (lines 49-52) since lumberjack
will create the file in the first write if it does not exist. However, otherwise the function mentioned just sets the default parameters for (crowdsec
) log file and thus is required still.
If you mean we can set umask in the systemd service, I'm not sure we want to do it for every file that is created. Or we can always add a configuration setting.
I was more thinking aloud options how to provide configurability of log file permissions to admins. These are the options, IMHO:
crowdsec
modules (crowdsec
, bouncers) need to create the log file first with set permissions and lumberjack
will retain those. lumberjack
to preserve existing file permissions (PR #294). This option is simpler and does not require a config file option. It just should be documented somewhere (other than source code) 😉 umask
. Allow the underlying Unix OS to apply to process-specific umask. This however, would require tweaking lumberjack
since it applies to hard-coded 0600
permissions to a new file created. In log file rotation it preserves the old file's permissions. Out of these only options 1 and 2 make sense, IMO.
Thanks, closing as fixed
I was confused at first because I was sure I had replicated the issue, but it was before updating the lumberjack dependency
Summary
crowdsec-firewall-bouncer
does not provide admins options to configure log files access permissions, but log file permissions are hard-coded to0600
.crowdsec-firewall-bouncer
does not respect processumask
either which prevents admins to usesystemd
'sUMask=
option. The underlying lumberjack log roller library actually respects existing log file permissions, butcrowdsec-firewall bouncer
disables this functionality. The current behavior resets the log file permissions to0600
in every restart.While hard-coded
0600
log file permission is secure, it also prevents admins to change the log file permissions if needed. If other tools (e.g.promtail
) requiring access to the log files run in rootless mode (a good security practice), the tools cannot read Crowdsec bouncer log files.Technical details
It seems this "feature" was created as a response to upstream issue natefinch/lumberjack#82, but this issue has been fixed more than 4 years ago.
The code responsible for setting the access rights resides in
LoggerForFile()
in pkg/cfg/logging.go. It callslogtools.fileperms.SetLogFilePermissions()
to hard-reset log file permissions to0600
. OtherwiseSetLogFilePermissions()
seems a copy-paste fromlumberjack
.See pkg/logtools/fileperms.go in crowdsecurity/go-cs-lib:
Proposal
Proposal is to remove disabling of
lumberjack
's built-in behavior and thus to give admins option to change log file permissions if needed. I will submit a PR shortly.As an added-bonus 🏅, the whole logtools/fileperms.go in crowdsecurity/go-cs-lib could be removed if the change was implemented to the three other bouncers using the same function 😃