Skip to content

Commit

Permalink
Run livenessprobe as nonroot - 5.1 (#197)
Browse files Browse the repository at this point in the history
* Run livenessprobe as nonroot - 5.1

* updated copyright
  • Loading branch information
prankulmahajan authored Sep 6, 2024
1 parent 9b87440 commit 1aec869
Show file tree
Hide file tree
Showing 6 changed files with 424 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ spec:
securityContext:
runAsNonRoot: true
runAsUser: 2121
runAsGroup: 2121
containers:
- name: csi-snapshotter
image: MUSTPATCHWITHKUSTOMIZE
Expand Down
14 changes: 12 additions & 2 deletions deploy/kubernetes/driver/kubernetes/manifests/node-server.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ spec:
securityContext:
runAsNonRoot: false
runAsUser: 0
runAsGroup: 0
privileged: false
args:
- "--v=5"
Expand Down Expand Up @@ -60,6 +61,7 @@ spec:
securityContext:
runAsNonRoot: false
runAsUser: 0
runAsGroup: 0
privileged: true
image: MUSTPATCHWITHKUSTOMIZE
imagePullPolicy: Always
Expand All @@ -71,6 +73,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: IS_NODE_SERVER
value: "true"
- name: SIDECAR_GROUP_ID
value: "2121"
envFrom:
- configMapRef:
name: ibm-vpc-block-csi-configmap
Expand Down Expand Up @@ -115,9 +121,13 @@ spec:
- name: liveness-probe
image: MUSTPATCHWITHKUSTOMIZE
securityContext:
runAsNonRoot: false
runAsUser: 0
runAsNonRoot: true
runAsUser: 2121
runAsGroup: 2121
privileged: false
seLinuxOptions: # seLinux label is set as a precaution for accessing csi socket
type: spc_t
level: s0
args:
- --csi-address=/csi/csi.sock
resources:
Expand Down
83 changes: 83 additions & 0 deletions pkg/ibmcsidriver/fileOps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package ibmcsidriver ...
package ibmcsidriver

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate

import (
"os"
"strconv"

"go.uber.org/zap"
)

const (
filePermission = 0660
)

//counterfeiter:generate . socketPermission

// socketPermission represents file system operations
type socketPermission interface {
Chown(name string, uid, gid int) error
Chmod(name string, mode os.FileMode) error
}

// realSocketPermission implements socketPermission
type opsSocketPermission struct{}

func (f *opsSocketPermission) Chown(name string, uid, gid int) error {
return os.Chown(name, uid, gid)
}

func (f *opsSocketPermission) Chmod(name string, mode os.FileMode) error {
return os.Chmod(name, mode)
}

// setupSidecar updates owner/group and permission of the file given(addr)
func setupSidecar(addr string, ops socketPermission, logger *zap.Logger) error {
groupSt := os.Getenv("SIDECAR_GROUP_ID")

logger.Info("Setting owner and permissions of csi socket file. SIDECAR_GROUP_ID env must match the 'livenessprobe' sidecar container groupID for csi socket connection.")

// If env is not set, set default to 0
if groupSt == "" {
logger.Warn("Unable to fetch SIDECAR_GROUP_ID environment variable. Sidecar container(s) might fail...")
groupSt = "0"
}

group, err := strconv.Atoi(groupSt)
if err != nil {
return err
}

// Change group of csi socket to non-root user for enabling the csi sidecar
if err := ops.Chown(addr, -1, group); err != nil {
return err
}

// Modify permissions of csi socket
// Only the users and the group owners will have read/write access to csi socket
if err := ops.Chmod(addr, filePermission); err != nil {
return err
}

logger.Info("Successfully set owner and permissions of csi socket file.")

return nil
}
124 changes: 124 additions & 0 deletions pkg/ibmcsidriver/fileOps_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package ibmcsidriver

import (
"errors"
"os"
"testing"

cloudProvider "github.com/IBM/ibm-csi-common/pkg/ibmcloudprovider"
"github.com/kubernetes-sigs/ibm-vpc-block-csi-driver/pkg/ibmcsidriver/ibmcsidriverfakes"
"github.com/stretchr/testify/assert"
)

func TestSetupSidecar(t *testing.T) {
tests := []struct {
name string
groupID string
expectedErr bool
chownErr error
chmodErr error
expectedChownCalls int
expectedChmodCalls int
expectedGroupID int
}{
{
name: "ValidGroupID",
groupID: "2121",
expectedErr: false,
chownErr: nil,
chmodErr: nil,
expectedChownCalls: 1,
expectedChmodCalls: 1,
expectedGroupID: 2121,
},
{
name: "EmptyGroupID",
groupID: "",
expectedErr: false,
chownErr: nil,
chmodErr: nil,
expectedChownCalls: 1,
expectedChmodCalls: 1,
expectedGroupID: 0, // Default to 0 if SIDECAR_GROUP_ID is empty
},
{
name: "ChownError",
groupID: "1000",
expectedErr: true,
chownErr: errors.New("chown error"),
chmodErr: nil,
expectedChownCalls: 1,
expectedChmodCalls: 0, // No chmod expected if chown fails
expectedGroupID: 1000,
},
{
name: "ChmodError",
groupID: "1000",
expectedErr: true,
chownErr: nil,
chmodErr: errors.New("chmod error"),
expectedChownCalls: 1,
expectedChmodCalls: 1,
expectedGroupID: 1000,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// Set SIDECAR_GROUP_ID environment variable
if tc.groupID != "" {
os.Setenv("SIDECAR_GROUP_ID", tc.groupID)
} else {
os.Unsetenv("SIDECAR_GROUP_ID")
}
defer os.Unsetenv("SIDECAR_GROUP_ID")

// Create the fake object generated by counterfeiter
fakeSocketPermission := new(ibmcsidriverfakes.FakeSocketPermission)

// Set return values for chown and chmod methods
fakeSocketPermission.ChownReturns(tc.chownErr)
fakeSocketPermission.ChmodReturns(tc.chmodErr)

// Creating test logger
logger, teardown := cloudProvider.GetTestLogger(t)
defer teardown()

// Call the function under test
err := setupSidecar("/path/to/socket", fakeSocketPermission, logger)

// Verify the result
if tc.expectedErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}

// Verify the number of times Chown and Chmod were called
assert.Equal(t, tc.expectedChownCalls, fakeSocketPermission.ChownCallCount())
assert.Equal(t, tc.expectedChmodCalls, fakeSocketPermission.ChmodCallCount())

// Verify the group ID passed to chown
if tc.expectedChownCalls > 0 {
_, _, actualGroupID := fakeSocketPermission.ChownArgsForCall(0)
assert.Equal(t, tc.expectedGroupID, actualGroupID)
}
})
}
}
Loading

0 comments on commit 1aec869

Please sign in to comment.