Start adding tests for verifying correct modes
Add an example for permission bits checking
This commit is contained in:
@@ -19,12 +19,17 @@ limitations under the License.
|
||||
package volume
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utiltesting "k8s.io/client-go/util/testing"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
type localFakeMounter struct {
|
||||
@@ -57,8 +62,8 @@ func (l *localFakeMounter) GetMetrics() (*Metrics, error) {
|
||||
}
|
||||
|
||||
func TestSkipPermissionChange(t *testing.T) {
|
||||
always := v1.AlwaysChangeVolumePermission
|
||||
onrootMismatch := v1.OnRootMismatch
|
||||
always := v1.FSGroupChangeAlways
|
||||
onrootMismatch := v1.FSGroupChangeOnRootMismatch
|
||||
tests := []struct {
|
||||
description string
|
||||
fsGroupChangePolicy *v1.PodFSGroupChangePolicy
|
||||
@@ -76,6 +81,18 @@ func TestSkipPermissionChange(t *testing.T) {
|
||||
fsGroupChangePolicy: &always,
|
||||
skipPermssion: false,
|
||||
},
|
||||
{
|
||||
description: "skippermission=false, policy=always, gidmatch=true",
|
||||
fsGroupChangePolicy: &always,
|
||||
skipPermssion: false,
|
||||
gidOwnerMatch: true,
|
||||
},
|
||||
{
|
||||
description: "skippermission=false, policy=nil, gidmatch=true",
|
||||
fsGroupChangePolicy: nil,
|
||||
skipPermssion: false,
|
||||
gidOwnerMatch: true,
|
||||
},
|
||||
{
|
||||
description: "skippermission=false, policy=onrootmismatch, gidmatch=false",
|
||||
fsGroupChangePolicy: &onrootMismatch,
|
||||
@@ -158,5 +175,173 @@ func TestSkipPermissionChange(t *testing.T) {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSetVolumeOwnership(t *testing.T) {
|
||||
always := v1.FSGroupChangeAlways
|
||||
onrootMismatch := v1.FSGroupChangeOnRootMismatch
|
||||
expectedMask := rwMask | os.ModeSetgid | execMask
|
||||
|
||||
tests := []struct {
|
||||
description string
|
||||
fsGroupChangePolicy *v1.PodFSGroupChangePolicy
|
||||
setupFunc func(path string) error
|
||||
assertFunc func(path string) error
|
||||
featureGate bool
|
||||
}{
|
||||
{
|
||||
description: "featuregate=on, fsgroupchangepolicy=always",
|
||||
fsGroupChangePolicy: &always,
|
||||
featureGate: true,
|
||||
setupFunc: func(path string) error {
|
||||
info, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// change mode of root folder to be right
|
||||
err = os.Chmod(path, info.Mode()|expectedMask)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create a subdirectory with invalid permissions
|
||||
rogueDir := filepath.Join(path, "roguedir")
|
||||
err = os.Mkdir(rogueDir, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
assertFunc: func(path string) error {
|
||||
rogueDir := filepath.Join(path, "roguedir")
|
||||
hasCorrectPermissions := verifyDirectoryPermission(rogueDir, false /*readOnly*/)
|
||||
if !hasCorrectPermissions {
|
||||
return fmt.Errorf("invalid permissions on %s", rogueDir)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "featuregate=on, fsgroupchangepolicy=onrootmismatch,rootdir=validperm",
|
||||
fsGroupChangePolicy: &onrootMismatch,
|
||||
featureGate: true,
|
||||
setupFunc: func(path string) error {
|
||||
info, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// change mode of root folder to be right
|
||||
err = os.Chmod(path, info.Mode()|expectedMask)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create a subdirectory with invalid permissions
|
||||
rogueDir := filepath.Join(path, "roguedir")
|
||||
err = os.Mkdir(rogueDir, rwMask)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
assertFunc: func(path string) error {
|
||||
rogueDir := filepath.Join(path, "roguedir")
|
||||
hasCorrectPermissions := verifyDirectoryPermission(rogueDir, false /*readOnly*/)
|
||||
if hasCorrectPermissions {
|
||||
return fmt.Errorf("invalid permissions on %s", rogueDir)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "featuregate=on, fsgroupchangepolicy=onrootmismatch,rootdir=invalidperm",
|
||||
fsGroupChangePolicy: &onrootMismatch,
|
||||
featureGate: true,
|
||||
setupFunc: func(path string) error {
|
||||
// change mode of root folder to be right
|
||||
err := os.Chmod(path, 0770)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create a subdirectory with invalid permissions
|
||||
rogueDir := filepath.Join(path, "roguedir")
|
||||
err = os.Mkdir(rogueDir, rwMask)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
assertFunc: func(path string) error {
|
||||
rogueDir := filepath.Join(path, "roguedir")
|
||||
hasCorrectPermissions := verifyDirectoryPermission(rogueDir, false /*readOnly*/)
|
||||
if !hasCorrectPermissions {
|
||||
return fmt.Errorf("invalid permissions on %s", rogueDir)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ConfigurableFSGroupPolicy, test.featureGate)()
|
||||
tmpDir, err := utiltesting.MkTmpdir("volume_linux_ownership")
|
||||
if err != nil {
|
||||
t.Fatalf("error creating temp dir: %v", err)
|
||||
}
|
||||
|
||||
defer os.RemoveAll(tmpDir)
|
||||
info, err := os.Lstat(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("error reading permission of tmpdir: %v", err)
|
||||
}
|
||||
|
||||
stat, ok := info.Sys().(*syscall.Stat_t)
|
||||
if !ok || stat == nil {
|
||||
t.Fatalf("error reading permission stats for tmpdir: %s", tmpDir)
|
||||
}
|
||||
|
||||
var expectedGid int64 = int64(stat.Gid)
|
||||
err = test.setupFunc(tmpDir)
|
||||
if err != nil {
|
||||
t.Errorf("for %s error running setup with: %v", test.description, err)
|
||||
}
|
||||
|
||||
mounter := &localFakeMounter{path: tmpDir}
|
||||
err = SetVolumeOwnership(mounter, &expectedGid, test.fsGroupChangePolicy)
|
||||
if err != nil {
|
||||
t.Errorf("for %s error changing ownership with: %v", test.description, err)
|
||||
}
|
||||
err = test.assertFunc(tmpDir)
|
||||
if err != nil {
|
||||
t.Errorf("for %s error verifying permissions with: %v", test.description, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// verifyDirectoryPermission checks if given path has directory permissions
|
||||
// that is expected by k8s. If returns true if it does otherwise false
|
||||
func verifyDirectoryPermission(path string, readonly bool) bool {
|
||||
info, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
stat, ok := info.Sys().(*syscall.Stat_t)
|
||||
if !ok || stat == nil {
|
||||
return false
|
||||
}
|
||||
unixPerms := rwMask
|
||||
|
||||
if readonly {
|
||||
unixPerms = roMask
|
||||
}
|
||||
|
||||
unixPerms |= execMask
|
||||
filePerm := info.Mode().Perm()
|
||||
if (unixPerms&filePerm == unixPerms) && (info.Mode()&os.ModeSetgid != 0) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
Reference in New Issue
Block a user