-
Notifications
You must be signed in to change notification settings - Fork 215
/
Copy pathuserutil.go
107 lines (91 loc) · 2.9 KB
/
userutil.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT
//go:build linux || darwin
// +build linux darwin
package user
import (
"fmt"
"log"
"os"
"path/filepath"
)
var (
agentLogDir = "/opt/aws/amazon-cloudwatch-agent/logs"
agentVarDir = "/opt/aws/amazon-cloudwatch-agent/var"
agentEtcDir = "/opt/aws/amazon-cloudwatch-agent/etc"
)
type ChownFunc func(name string, uid, gid int) error
var chown ChownFunc = os.Chown
// DetectRunAsUser get the user name from toml config. It runs on all platforms except windows.
func DetectRunAsUser(configMap map[string]any) (string, error) {
fmt.Printf("I! Detecting run_as_user...\n")
if agentSection, ok := configMap["agent"]; ok {
agent := agentSection.(map[string]any)
if user, ok := agent["run_as_user"]; ok {
if runAsUser, ok := user.(string); ok {
return runAsUser, nil
}
log.Panicf("E! run_as_user is not string %v", user)
}
// agent section exists, but "run_as_user" does not exist, then use "root"
return "root", nil
}
// no agent section, it means no run_as_user, use "root"
return "root", nil
}
// changeFileOwner changes both user and group of a directory.
func changeFileOwner(uid, gid int) error {
dirs := []string{agentLogDir, agentEtcDir, agentVarDir}
log.Printf("I! Changing ownership of %v to %v:%v", dirs, uid, gid)
for _, d := range dirs {
if err := chownRecursive(uid, gid, d); err != nil {
return err
}
}
return nil
}
// chownRecursive would recursively change the ownership of the directory
// similar to `chown -R <dir>`, except it will ignore any files that are:
// - Executable
// - With SUID or SGID bit set
// - Allow anyone to write to
// - Symbolic links
//
// This would prevent any accidental ownership change to files that are executable
// or with special purpose to be changed to be owned by root when run_as_user option
// is removed from the configuration
func chownRecursive(uid, gid int, dir string) error {
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
fmode := info.Mode()
if fmode.IsRegular() {
// Do not change ownership of files with SUID or SGID
if fmode&os.ModeSetuid != 0 || fmode&os.ModeSetgid != 0 {
return nil
}
// Do not change ownership of executable files
// Perm() returns the lower 7 bit of permission of file, which represents rwxrwxrws
// 0111 maps to --x--x--x, so it would check any user have the execution right
if fmode.Perm()&0111 != 0 {
return nil
}
// No need to change ownership of files that allow anyone to write to
if fmode.Perm()&0002 != 0 {
return nil
}
}
if fmode&os.ModeSymlink != 0 {
return nil
}
if err = chown(path, uid, gid); err != nil {
return err
}
return nil
})
if err != nil {
return fmt.Errorf("error change owner of dir %s to %v:%v due to error: %w", dir, uid, gid, err)
}
return nil
}