Skip to content

Commit 101d3e7

Browse files
authored
logging: Customize log file permissions (#6314)
Adding a "mode" option to overwrite the default logfile permissions. Default remains "0600" which is the one currently used by lumberjack.
1 parent 3f1add6 commit 101d3e7

File tree

3 files changed

+426
-2
lines changed

3 files changed

+426
-2
lines changed

modules/logging/filewriter.go

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package logging
1616

1717
import (
18+
"encoding/json"
1819
"fmt"
1920
"io"
2021
"math"
@@ -33,6 +34,43 @@ func init() {
3334
caddy.RegisterModule(FileWriter{})
3435
}
3536

37+
// fileMode is a string made of 1 to 4 octal digits representing
38+
// a numeric mode as specified with the `chmod` unix command.
39+
// `"0777"` and `"777"` are thus equivalent values.
40+
type fileMode os.FileMode
41+
42+
// UnmarshalJSON satisfies json.Unmarshaler.
43+
func (m *fileMode) UnmarshalJSON(b []byte) error {
44+
if len(b) == 0 {
45+
return io.EOF
46+
}
47+
48+
var s string
49+
if err := json.Unmarshal(b, &s); err != nil {
50+
return err
51+
}
52+
53+
mode, err := parseFileMode(s)
54+
if err != nil {
55+
return err
56+
}
57+
58+
*m = fileMode(mode)
59+
return err
60+
}
61+
62+
// parseFileMode parses a file mode string,
63+
// adding support for `chmod` unix command like
64+
// 1 to 4 digital octal values.
65+
func parseFileMode(s string) (os.FileMode, error) {
66+
modeStr := fmt.Sprintf("%04s", s)
67+
mode, err := strconv.ParseUint(modeStr, 8, 32)
68+
if err != nil {
69+
return 0, err
70+
}
71+
return os.FileMode(mode), nil
72+
}
73+
3674
// FileWriter can write logs to files. By default, log files
3775
// are rotated ("rolled") when they get large, and old log
3876
// files get deleted, to ensure that the process does not
@@ -41,6 +79,10 @@ type FileWriter struct {
4179
// Filename is the name of the file to write.
4280
Filename string `json:"filename,omitempty"`
4381

82+
// The file permissions mode.
83+
// 0600 by default.
84+
Mode fileMode `json:"mode,omitempty"`
85+
4486
// Roll toggles log rolling or rotation, which is
4587
// enabled by default.
4688
Roll *bool `json:"roll,omitempty"`
@@ -100,6 +142,10 @@ func (fw FileWriter) WriterKey() string {
100142

101143
// OpenWriter opens a new file writer.
102144
func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
145+
if fw.Mode == 0 {
146+
fw.Mode = 0o600
147+
}
148+
103149
// roll log files by default
104150
if fw.Roll == nil || *fw.Roll {
105151
if fw.RollSizeMB == 0 {
@@ -116,6 +162,9 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
116162
fw.RollKeepDays = 90
117163
}
118164

165+
f_tmp, _ := os.OpenFile(fw.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(fw.Mode))
166+
f_tmp.Close()
167+
119168
return &lumberjack.Logger{
120169
Filename: fw.Filename,
121170
MaxSize: fw.RollSizeMB,
@@ -127,12 +176,13 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
127176
}
128177

129178
// otherwise just open a regular file
130-
return os.OpenFile(fw.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o666)
179+
return os.OpenFile(fw.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(fw.Mode))
131180
}
132181

133182
// UnmarshalCaddyfile sets up the module from Caddyfile tokens. Syntax:
134183
//
135184
// file <filename> {
185+
// mode <mode>
136186
// roll_disabled
137187
// roll_size <size>
138188
// roll_uncompressed
@@ -150,7 +200,7 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
150200
// The roll_keep_for duration has day resolution.
151201
// Fractional values are rounded up to the next whole number of days.
152202
//
153-
// If any of the roll_size, roll_keep, or roll_keep_for subdirectives are
203+
// If any of the mode, roll_size, roll_keep, or roll_keep_for subdirectives are
154204
// omitted or set to a zero value, then Caddy's default value for that
155205
// subdirective is used.
156206
func (fw *FileWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
@@ -165,6 +215,17 @@ func (fw *FileWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
165215

166216
for d.NextBlock(0) {
167217
switch d.Val() {
218+
case "mode":
219+
var modeStr string
220+
if !d.AllArgs(&modeStr) {
221+
return d.ArgErr()
222+
}
223+
mode, err := parseFileMode(modeStr)
224+
if err != nil {
225+
return d.Errf("parsing mode: %v", err)
226+
}
227+
fw.Mode = fileMode(mode)
228+
168229
case "roll_disabled":
169230
var f bool
170231
fw.Roll = &f

0 commit comments

Comments
 (0)