[lxc-devel] [lxd/master] Log username on unix queries
stgraber on Github
lxc-bot at linuxcontainers.org
Tue Oct 27 23:11:21 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201027/53cf85c0/attachment.bin>
-------------- next part --------------
From f3c4805b2267aa6e8af890499ee8c72673522b77 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 27 Oct 2020 18:56:45 -0400
Subject: [PATCH 1/5] shared: Drop GroupId and UserId
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
shared/util_linux_cgo.go | 97 ----------------------------------------
1 file changed, 97 deletions(-)
diff --git a/shared/util_linux_cgo.go b/shared/util_linux_cgo.go
index 72d0794953..155975d265 100644
--- a/shared/util_linux_cgo.go
+++ b/shared/util_linux_cgo.go
@@ -6,7 +6,6 @@ package shared
import (
"fmt"
"os"
- "unsafe"
// Used by cgo
_ "github.com/lxc/lxd/lxd/include"
@@ -58,102 +57,6 @@ import "C"
const ABSTRACT_UNIX_SOCK_LEN int = C.ABSTRACT_UNIX_SOCK_LEN
-// UserId is an adaption from https://codereview.appspot.com/4589049.
-func UserId(name string) (int, error) {
- var pw C.struct_passwd
- var result *C.struct_passwd
-
- bufSize := C.sysconf(C._SC_GETPW_R_SIZE_MAX)
- if bufSize < 0 {
- bufSize = 4096
- }
-
- buf := C.malloc(C.size_t(bufSize))
- if buf == nil {
- return -1, fmt.Errorf("allocation failed")
- }
- defer C.free(buf)
-
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
-
-again:
- rv, errno := C.getpwnam_r(cname,
- &pw,
- (*C.char)(buf),
- C.size_t(bufSize),
- &result)
- if rv < 0 {
- // OOM killer will take care of us if we end up doing this too
- // often.
- if errno == unix.ERANGE {
- bufSize *= 2
- tmp := C.realloc(buf, C.size_t(bufSize))
- if tmp == nil {
- return -1, fmt.Errorf("allocation failed")
- }
- buf = tmp
- goto again
- }
- return -1, fmt.Errorf("failed user lookup: %s", unix.Errno(rv))
- }
-
- if result == nil {
- return -1, fmt.Errorf("unknown user %s", name)
- }
-
- return int(C.int(result.pw_uid)), nil
-}
-
-// GroupId is an adaption from https://codereview.appspot.com/4589049.
-func GroupId(name string) (int, error) {
- var grp C.struct_group
- var result *C.struct_group
-
- bufSize := C.sysconf(C._SC_GETGR_R_SIZE_MAX)
- if bufSize < 0 {
- bufSize = 4096
- }
-
- buf := C.malloc(C.size_t(bufSize))
- if buf == nil {
- return -1, fmt.Errorf("allocation failed")
- }
-
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
-
-again:
- rv, errno := C.getgrnam_r(cname,
- &grp,
- (*C.char)(buf),
- C.size_t(bufSize),
- &result)
- if rv != 0 {
- // OOM killer will take care of us if we end up doing this too
- // often.
- if errno == unix.ERANGE {
- bufSize *= 2
- tmp := C.realloc(buf, C.size_t(bufSize))
- if tmp == nil {
- return -1, fmt.Errorf("allocation failed")
- }
- buf = tmp
- goto again
- }
-
- C.free(buf)
- return -1, fmt.Errorf("failed group lookup: %s", unix.Errno(rv))
- }
- C.free(buf)
-
- if result == nil {
- return -1, fmt.Errorf("unknown group %s", name)
- }
-
- return int(C.int(result.gr_gid)), nil
-}
-
func ReadPid(r *os.File) int {
return int(C.read_pid(C.int(r.Fd())))
}
From 30e814b42b0a19355c2bad3a2e971c7bf44c5f5b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 27 Oct 2020 18:57:23 -0400
Subject: [PATCH 2/5] lxd: Port to os/user
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/endpoints/socket.go | 14 ++++++++++----
lxd/sys/os.go | 24 ++++++++++++++++++------
2 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/lxd/endpoints/socket.go b/lxd/endpoints/socket.go
index 6eeccba3fc..98a81a2646 100644
--- a/lxd/endpoints/socket.go
+++ b/lxd/endpoints/socket.go
@@ -6,6 +6,7 @@ import (
"fmt"
"net"
"os"
+ "os/user"
"strconv"
"github.com/lxc/lxd/client"
@@ -86,14 +87,19 @@ func socketUnixSetPermissions(path string, mode os.FileMode) error {
}
// Change the ownership of the given unix socket file,
-func socketUnixSetOwnership(path string, group string) error {
+func socketUnixSetOwnership(path string, groupName string) error {
var gid int
var err error
- if group != "" {
- gid, err = shared.GroupId(group)
+ if groupName != "" {
+ g, err := user.LookupGroup(groupName)
if err != nil {
- return fmt.Errorf("cannot get group ID of '%s': %v", group, err)
+ return fmt.Errorf("cannot get group ID of '%s': %v", groupName, err)
+ }
+
+ gid, err = strconv.Atoi(g.Gid)
+ if err != nil {
+ return err
}
} else {
gid = os.Getgid()
diff --git a/lxd/sys/os.go b/lxd/sys/os.go
index 61cdf47394..0ab6d8f281 100644
--- a/lxd/sys/os.go
+++ b/lxd/sys/os.go
@@ -3,7 +3,9 @@
package sys
import (
+ "os/user"
"path/filepath"
+ "strconv"
"sync"
log "github.com/lxc/lxd/shared/log15"
@@ -115,24 +117,34 @@ func (s *OS) Init() error {
}
// Detect if it is possible to run daemons as an unprivileged user and group.
- for _, user := range []string{"lxd", "nobody"} {
- uid, err := shared.UserId(user)
+ for _, userName := range []string{"lxd", "nobody"} {
+ u, err := user.Lookup(userName)
if err != nil {
continue
}
- s.UnprivUser = user
+ uid, err := strconv.ParseUint(u.Uid, 10, 32)
+ if err != nil {
+ return err
+ }
+
+ s.UnprivUser = userName
s.UnprivUID = uint32(uid)
break
}
- for _, group := range []string{"lxd", "nogroup"} {
- gid, err := shared.GroupId(group)
+ for _, groupName := range []string{"lxd", "nogroup"} {
+ g, err := user.LookupGroup(groupName)
if err != nil {
continue
}
- s.UnprivGroup = group
+ gid, err := strconv.ParseUint(g.Gid, 10, 32)
+ if err != nil {
+ return err
+ }
+
+ s.UnprivGroup = groupName
s.UnprivGID = uint32(gid)
break
}
From a38f4092d40c68c77a704353776bf7edce98edd2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 27 Oct 2020 19:07:58 -0400
Subject: [PATCH 3/5] lxd/daemon: Log protocol
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/daemon.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/daemon.go b/lxd/daemon.go
index 52308da8c3..1de4938c70 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -425,7 +425,7 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c APIEndpoint) {
untrustedOk := (r.Method == "GET" && c.Get.AllowUntrusted) || (r.Method == "POST" && c.Post.AllowUntrusted)
if trusted {
- logger.Debug("Handling", log.Ctx{"method": r.Method, "url": r.URL.RequestURI(), "ip": r.RemoteAddr, "user": username})
+ logger.Debug("Handling", log.Ctx{"method": r.Method, "url": r.URL.RequestURI(), "ip": r.RemoteAddr, "username": username, "protocol": protocol})
r = r.WithContext(context.WithValue(context.WithValue(r.Context(), "username", username), "protocol", protocol))
} else if untrustedOk && r.Header.Get("X-LXD-authenticated") == "" {
logger.Debug(fmt.Sprintf("Allowing untrusted %s", r.Method), log.Ctx{"url": r.URL.RequestURI(), "ip": r.RemoteAddr})
From 1694cfd678f4eadeddda4831f3103a1d3aaed439 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 27 Oct 2020 19:08:35 -0400
Subject: [PATCH 4/5] lxd/daemon: Pass writer to Authenticate
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/certificates.go | 2 +-
lxd/daemon.go | 6 +++---
lxd/images.go | 2 +-
lxd/operations.go | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/lxd/certificates.go b/lxd/certificates.go
index 917f5d1178..673ae5a386 100644
--- a/lxd/certificates.go
+++ b/lxd/certificates.go
@@ -125,7 +125,7 @@ func certificatesPost(d *Daemon, r *http.Request) response.Response {
return response.SmartError(err)
}
- trusted, _, protocol, err := d.Authenticate(r)
+ trusted, _, protocol, err := d.Authenticate(nil, r)
if err != nil {
return response.SmartError(err)
}
diff --git a/lxd/daemon.go b/lxd/daemon.go
index 1de4938c70..94f6728b1c 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -241,7 +241,7 @@ func allowProjectPermission(feature string, permission string) func(d *Daemon, r
// Convenience function around Authenticate
func (d *Daemon) checkTrustedClient(r *http.Request) error {
- trusted, _, _, err := d.Authenticate(r)
+ trusted, _, _, err := d.Authenticate(nil, r)
if !trusted || err != nil {
if err != nil {
return err
@@ -258,7 +258,7 @@ func (d *Daemon) checkTrustedClient(r *http.Request) error {
// will validate the TLS certificate or Macaroon.
//
// This does not perform authorization, only validates authentication
-func (d *Daemon) Authenticate(r *http.Request) (bool, string, string, error) {
+func (d *Daemon) Authenticate(w http.ResponseWriter, r *http.Request) (bool, string, string, error) {
// Allow internal cluster traffic
if r.TLS != nil {
cert, _ := x509.ParseCertificate(d.endpoints.NetworkCert().KeyPair().Certificate[0])
@@ -403,7 +403,7 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c APIEndpoint) {
}
// Authentication
- trusted, username, protocol, err := d.Authenticate(r)
+ trusted, username, protocol, err := d.Authenticate(w, r)
if err != nil {
// If not a macaroon discharge request, return the error
_, ok := err.(*bakery.DischargeRequiredError)
diff --git a/lxd/images.go b/lxd/images.go
index d97e759408..4fb55b9087 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -696,7 +696,7 @@ func imageCreateInPool(d *Daemon, info *api.Image, storagePool string) error {
}
func imagesPost(d *Daemon, r *http.Request) response.Response {
- trusted, _, _, _ := d.Authenticate(r)
+ trusted, _, _, _ := d.Authenticate(nil, r)
secret := r.Header.Get("X-LXD-secret")
fingerprint := r.Header.Get("X-LXD-fingerprint")
diff --git a/lxd/operations.go b/lxd/operations.go
index e5d934c9ed..b46427f1cf 100644
--- a/lxd/operations.go
+++ b/lxd/operations.go
@@ -372,7 +372,7 @@ func operationWaitGet(d *Daemon, r *http.Request) response.Response {
id := mux.Vars(r)["id"]
secret := r.FormValue("secret")
- trusted, _, _, _ := d.Authenticate(r)
+ trusted, _, _, _ := d.Authenticate(nil, r)
if !trusted && secret == "" {
return response.Forbidden(nil)
}
From e5a01555ba6d1e25ce859be84a5b9b9d4a88b8ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 27 Oct 2020 19:08:53 -0400
Subject: [PATCH 5/5] lxd/daemon: Record username on unix queries
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #8012
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/daemon.go | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/lxd/daemon.go b/lxd/daemon.go
index 94f6728b1c..8e8cd12c20 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -11,6 +11,7 @@ import (
"net/http"
"net/url"
"os"
+ "os/user"
"path/filepath"
"strings"
"sync"
@@ -37,6 +38,7 @@ import (
"github.com/lxc/lxd/lxd/events"
"github.com/lxc/lxd/lxd/firewall"
"github.com/lxc/lxd/lxd/instance"
+ "github.com/lxc/lxd/lxd/ucred"
// Import instance/drivers without name so init() runs.
_ "github.com/lxc/lxd/lxd/instance/drivers"
@@ -273,6 +275,21 @@ func (d *Daemon) Authenticate(w http.ResponseWriter, r *http.Request) (bool, str
// Local unix socket queries
if r.RemoteAddr == "@" {
+ if w != nil {
+ conn := extractUnderlyingConn(w)
+ cred, err := ucred.GetCred(conn)
+ if err != nil {
+ return false, "", "", err
+ }
+
+ u, err := user.LookupId(fmt.Sprintf("%d", cred.Uid))
+ if err != nil {
+ return true, fmt.Sprintf("uid=%d", cred.Uid), "unix", nil
+ }
+
+ return true, u.Username, "unix", nil
+ }
+
return true, "", "unix", nil
}
More information about the lxc-devel
mailing list