@@ -24,6 +24,7 @@ import (
2424 "errors"
2525 "fmt"
2626 "io"
27+ "io/fs"
2728 "net/http"
2829 "os"
2930 "os/exec"
@@ -35,6 +36,8 @@ import (
3536 "testing"
3637 "time"
3738
39+ "github.com/stretchr/testify/require"
40+
3841 "vitess.io/vitess/go/constants/sidecar"
3942 "vitess.io/vitess/go/mysql"
4043 "vitess.io/vitess/go/sqltypes"
@@ -711,6 +714,63 @@ func (vttablet *VttabletProcess) IsShutdown() bool {
711714 return vttablet .proc == nil
712715}
713716
717+ // ConfirmDataDirHasNoGlobalPerms confirms that no files in the tablet's data directory
718+ // have any global/world/other permissions enabled.
719+ func (vttablet * VttabletProcess ) ConfirmDataDirHasNoGlobalPerms (t * testing.T ) {
720+ datadir := vttablet .Directory
721+ if _ , err := os .Stat (datadir ); errors .Is (err , os .ErrNotExist ) {
722+ t .Logf ("Data directory %s no longer exists, skipping permissions check" , datadir )
723+ return
724+ }
725+
726+ var allowedFiles = []string {
727+ // These are intentionally created with the world/other read bit set by mysqld itself
728+ // during the --initialize[-insecure] step.
729+ // See: https://dev.mysql.com/doc/mysql-security-excerpt/en/creating-ssl-rsa-files-using-mysql.html
730+ // "On Unix and Unix-like systems, the file access mode is 644 for certificate files
731+ // (that is, world readable) and 600 for key files (that is, accessible only by the
732+ // account that runs the server)."
733+ path .Join ("data" , "ca.pem" ),
734+ path .Join ("data" , "client-cert.pem" ),
735+ path .Join ("data" , "public_key.pem" ),
736+ path .Join ("data" , "server-cert.pem" ),
737+ // The domain socket must have global perms for anyone to use it.
738+ "mysql.sock" ,
739+ // These files are created by xtrabackup.
740+ path .Join ("tmp" , "xtrabackup_checkpoints" ),
741+ path .Join ("tmp" , "xtrabackup_info" ),
742+ }
743+
744+ var matches []string
745+ fsys := os .DirFS (datadir )
746+ err := fs .WalkDir (fsys , "." , func (p string , d fs.DirEntry , _ error ) error {
747+ // first check if the file should be skipped
748+ for _ , name := range allowedFiles {
749+ if strings .HasSuffix (p , name ) {
750+ return nil
751+ }
752+ }
753+
754+ info , err := d .Info ()
755+ if err != nil {
756+ return err
757+ }
758+
759+ // check if any global bit is on the filemode
760+ if info .Mode ()& 0007 != 0 {
761+ matches = append (matches , fmt .Sprintf (
762+ "%s (%s)" ,
763+ path .Join (datadir , p ),
764+ info .Mode (),
765+ ))
766+ }
767+ return nil
768+ })
769+
770+ require .NoError (t , err , "Error walking directory" )
771+ require .Empty (t , matches , "Found files with global permissions: %s\n " , strings .Join (matches , "\n " ))
772+ }
773+
714774// VttabletProcessInstance returns a VttabletProcess handle for vttablet process
715775// configured with the given Config.
716776// The process must be manually started by calling setup()
0 commit comments