mirror of
https://github.com/status-im/consul.git
synced 2025-02-02 08:56:43 +00:00
agent: use interface for file permissions
This commit is contained in:
parent
782b0ddd88
commit
b1dae530d4
@ -188,7 +188,7 @@ func TestSetupAgent_RPCUnixSocket_FileExists(t *testing.T) {
|
|||||||
conf.Addresses.RPC = "unix://" + socketPath
|
conf.Addresses.RPC = "unix://" + socketPath
|
||||||
|
|
||||||
// Custom mode for socket file
|
// Custom mode for socket file
|
||||||
conf.UnixSockets = map[string]string{"mode": "0777"}
|
conf.UnixSockets.Perms = "0777"
|
||||||
|
|
||||||
shutdownCh := make(chan struct{})
|
shutdownCh := make(chan struct{})
|
||||||
defer close(shutdownCh)
|
defer close(shutdownCh)
|
||||||
|
@ -345,7 +345,27 @@ type Config struct {
|
|||||||
WatchPlans []*watch.WatchPlan `mapstructure:"-" json:"-"`
|
WatchPlans []*watch.WatchPlan `mapstructure:"-" json:"-"`
|
||||||
|
|
||||||
// UnixSockets is a map of socket configuration data
|
// UnixSockets is a map of socket configuration data
|
||||||
UnixSockets map[string]string `mapstructure:"unix_sockets"`
|
UnixSockets UnixSocketConfig `mapstructure:"unix_sockets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnixSocketConfig contains information about a unix socket, and
|
||||||
|
// implements the FilePermissions interface.
|
||||||
|
type UnixSocketConfig struct {
|
||||||
|
Usr string `mapstructure:"user"`
|
||||||
|
Grp string `mapstructure:"group"`
|
||||||
|
Perms string `mapstructure:"mode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u UnixSocketConfig) User() string {
|
||||||
|
return u.Usr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u UnixSocketConfig) Group() string {
|
||||||
|
return u.Grp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u UnixSocketConfig) Mode() string {
|
||||||
|
return u.Perms
|
||||||
}
|
}
|
||||||
|
|
||||||
// unixSocketAddr tests if a given address describes a domain socket,
|
// unixSocketAddr tests if a given address describes a domain socket,
|
||||||
@ -886,6 +906,15 @@ func MergeConfig(a, b *Config) *Config {
|
|||||||
if b.DisableAnonymousSignature {
|
if b.DisableAnonymousSignature {
|
||||||
result.DisableAnonymousSignature = true
|
result.DisableAnonymousSignature = true
|
||||||
}
|
}
|
||||||
|
if b.UnixSockets.Usr != "" {
|
||||||
|
result.UnixSockets.Usr = b.UnixSockets.Usr
|
||||||
|
}
|
||||||
|
if b.UnixSockets.Grp != "" {
|
||||||
|
result.UnixSockets.Grp = b.UnixSockets.Grp
|
||||||
|
}
|
||||||
|
if b.UnixSockets.Perms != "" {
|
||||||
|
result.UnixSockets.Perms = b.UnixSockets.Perms
|
||||||
|
}
|
||||||
|
|
||||||
if len(b.HTTPAPIResponseHeaders) != 0 {
|
if len(b.HTTPAPIResponseHeaders) != 0 {
|
||||||
if result.HTTPAPIResponseHeaders == nil {
|
if result.HTTPAPIResponseHeaders == nil {
|
||||||
@ -896,15 +925,6 @@ func MergeConfig(a, b *Config) *Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(b.UnixSockets) != 0 {
|
|
||||||
if result.UnixSockets == nil {
|
|
||||||
result.UnixSockets = make(map[string]string)
|
|
||||||
}
|
|
||||||
for field, value := range b.UnixSockets {
|
|
||||||
result.UnixSockets[field] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the start join addresses
|
// Copy the start join addresses
|
||||||
result.StartJoin = make([]string, 0, len(a.StartJoin)+len(b.StartJoin))
|
result.StartJoin = make([]string, 0, len(a.StartJoin)+len(b.StartJoin))
|
||||||
result.StartJoin = append(result.StartJoin, a.StartJoin...)
|
result.StartJoin = append(result.StartJoin, a.StartJoin...)
|
||||||
|
@ -595,12 +595,14 @@ func TestDecodeConfig(t *testing.T) {
|
|||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(config.UnixSockets, map[string]string{
|
if config.UnixSockets.Usr != "500" {
|
||||||
"user": "500",
|
t.Fatalf("bad: %#v", config)
|
||||||
"group": "500",
|
}
|
||||||
"mode": "0700",
|
if config.UnixSockets.Grp != "500" {
|
||||||
}) {
|
t.Fatalf("bad: %#v", config)
|
||||||
t.Fatalf("bad: %v", config.UnixSockets)
|
}
|
||||||
|
if config.UnixSockets.Perms != "0700" {
|
||||||
|
t.Fatalf("bad: %#v", config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable updates
|
// Disable updates
|
||||||
@ -1013,10 +1015,10 @@ func TestMergeConfig(t *testing.T) {
|
|||||||
HTTPAPIResponseHeaders: map[string]string{
|
HTTPAPIResponseHeaders: map[string]string{
|
||||||
"Access-Control-Allow-Origin": "*",
|
"Access-Control-Allow-Origin": "*",
|
||||||
},
|
},
|
||||||
UnixSockets: map[string]string{
|
UnixSockets: UnixSocketConfig{
|
||||||
"user": "500",
|
Usr: "500",
|
||||||
"group": "500",
|
Grp: "500",
|
||||||
"mode": "0700",
|
Perms: "0700",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ func TestHTTPServer_UnixSocket(t *testing.T) {
|
|||||||
|
|
||||||
// Only testing mode, since uid/gid might not be settable
|
// Only testing mode, since uid/gid might not be settable
|
||||||
// from test environment.
|
// from test environment.
|
||||||
c.UnixSockets = map[string]string{"mode": "0777"}
|
c.UnixSockets = UnixSocketConfig{Perms: "0777"}
|
||||||
})
|
})
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
defer srv.Shutdown()
|
defer srv.Shutdown()
|
||||||
|
@ -100,34 +100,47 @@ func stringHash(s string) string {
|
|||||||
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
|
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilePermissions is an interface which allows a struct to set
|
||||||
|
// ownership and permissions easily on a file it describes.
|
||||||
|
type FilePermissions interface {
|
||||||
|
// User returns a user ID or user name
|
||||||
|
User() string
|
||||||
|
|
||||||
|
// Group returns a group ID. Group names are not supported.
|
||||||
|
Group() string
|
||||||
|
|
||||||
|
// Mode returns a string of file mode bits e.g. "0644"
|
||||||
|
Mode() string
|
||||||
|
}
|
||||||
|
|
||||||
// setFilePermissions handles configuring ownership and permissions settings
|
// setFilePermissions handles configuring ownership and permissions settings
|
||||||
// on a given file. It takes a map, which defines the permissions to be set.
|
// on a given file. It takes a path and any struct implementing the
|
||||||
// All permission/ownership settings are optional. If no user or group is
|
// FilePermissions interface. All permission/ownership settings are optional.
|
||||||
// specified, the current user/group will be used. Mode is optional, and has
|
// If no user or group is specified, the current user/group will be used. Mode
|
||||||
// no default (the operation is not performed if absent). User may be
|
// is optional, and has no default (the operation is not performed if absent).
|
||||||
// specified by name or ID, but group may only be specified by ID.
|
// User may be specified by name or ID, but group may only be specified by ID.
|
||||||
func setFilePermissions(path string, perms map[string]string) error {
|
func setFilePermissions(path string, p FilePermissions) error {
|
||||||
var err error
|
var err error
|
||||||
uid, gid := os.Getuid(), os.Getgid()
|
uid, gid := os.Getuid(), os.Getgid()
|
||||||
|
|
||||||
if _, ok := perms["user"]; ok {
|
if p.User() != "" {
|
||||||
if uid, err = strconv.Atoi(perms["user"]); err == nil {
|
if uid, err = strconv.Atoi(p.User()); err == nil {
|
||||||
goto GROUP
|
goto GROUP
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try looking up the user by name
|
// Try looking up the user by name
|
||||||
if u, err := user.Lookup(perms["user"]); err == nil {
|
if u, err := user.Lookup(p.User()); err == nil {
|
||||||
uid, _ = strconv.Atoi(u.Uid)
|
uid, _ = strconv.Atoi(u.Uid)
|
||||||
goto GROUP
|
goto GROUP
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("invalid user specified: %v", perms["user"])
|
return fmt.Errorf("invalid user specified: %v", p.User())
|
||||||
}
|
}
|
||||||
|
|
||||||
GROUP:
|
GROUP:
|
||||||
if _, ok := perms["group"]; ok {
|
if p.Group() != "" {
|
||||||
if gid, err = strconv.Atoi(perms["group"]); err != nil {
|
if gid, err = strconv.Atoi(p.Group()); err != nil {
|
||||||
return fmt.Errorf("invalid group specified: %v", perms["group"])
|
return fmt.Errorf("invalid group specified: %v", p.Group())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := os.Chown(path, uid, gid); err != nil {
|
if err := os.Chown(path, uid, gid); err != nil {
|
||||||
@ -135,10 +148,10 @@ GROUP:
|
|||||||
uid, gid, path, err)
|
uid, gid, path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := perms["mode"]; ok {
|
if p.Mode() != "" {
|
||||||
mode, err := strconv.ParseUint(perms["mode"], 8, 32)
|
mode, err := strconv.ParseUint(p.Mode(), 8, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid mode specified: %v", perms["mode"])
|
return fmt.Errorf("invalid mode specified: %v", p.Mode())
|
||||||
}
|
}
|
||||||
if err := os.Chmod(path, os.FileMode(mode)); err != nil {
|
if err := os.Chmod(path, os.FileMode(mode)); err != nil {
|
||||||
return fmt.Errorf("failed setting permissions to %d on %q: %s",
|
return fmt.Errorf("failed setting permissions to %d on %q: %s",
|
||||||
|
@ -51,22 +51,22 @@ func TestSetFilePermissions(t *testing.T) {
|
|||||||
defer os.Remove(path)
|
defer os.Remove(path)
|
||||||
|
|
||||||
// Bad UID fails
|
// Bad UID fails
|
||||||
if err := setFilePermissions(path, map[string]string{"user": "%"}); err == nil {
|
if err := setFilePermissions(path, UnixSocketConfig{Usr: "%"}); err == nil {
|
||||||
t.Fatalf("should fail")
|
t.Fatalf("should fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bad GID fails
|
// Bad GID fails
|
||||||
if err := setFilePermissions(path, map[string]string{"group": "%"}); err == nil {
|
if err := setFilePermissions(path, UnixSocketConfig{Grp: "%"}); err == nil {
|
||||||
t.Fatalf("should fail")
|
t.Fatalf("should fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bad mode fails
|
// Bad mode fails
|
||||||
if err := setFilePermissions(path, map[string]string{"mode": "%"}); err == nil {
|
if err := setFilePermissions(path, UnixSocketConfig{Perms: "%"}); err == nil {
|
||||||
t.Fatalf("should fail")
|
t.Fatalf("should fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allows omitting user/group/mode
|
// Allows omitting user/group/mode
|
||||||
if err := setFilePermissions(path, map[string]string{}); err != nil {
|
if err := setFilePermissions(path, UnixSocketConfig{}); err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ func TestSetFilePermissions(t *testing.T) {
|
|||||||
if err := os.Chmod(path, 0700); err != nil {
|
if err := os.Chmod(path, 0700); err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
if err := setFilePermissions(path, map[string]string{}); err != nil {
|
if err := setFilePermissions(path, UnixSocketConfig{}); err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
fi, err := os.Stat(path)
|
fi, err := os.Stat(path)
|
||||||
@ -86,7 +86,7 @@ func TestSetFilePermissions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Changes mode if given
|
// Changes mode if given
|
||||||
if err := setFilePermissions(path, map[string]string{"mode": "0777"}); err != nil {
|
if err := setFilePermissions(path, UnixSocketConfig{Perms: "0777"}); err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
fi, err = os.Stat(path)
|
fi, err = os.Stat(path)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user