Start adding tests for verifying correct modes

Add an example for permission bits checking
This commit is contained in:
Hemant Kumar
2020-02-28 12:23:31 -05:00
parent c52d4bf32f
commit b132959687
8 changed files with 205 additions and 15 deletions

View File

@@ -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
}