Skip to content

Commit 3db7275

Browse files
committed
set proper file permission for projected service account volume
1 parent fbacb6e commit 3db7275

File tree

13 files changed

+511
-73
lines changed

13 files changed

+511
-73
lines changed

pkg/securitycontext/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ go_test(
3232
"//pkg/apis/core:go_default_library",
3333
"//staging/src/k8s.io/api/core/v1:go_default_library",
3434
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
35+
"//vendor/k8s.io/utils/pointer:go_default_library",
3536
],
3637
)
3738

pkg/securitycontext/util.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ limitations under the License.
1717
package securitycontext
1818

1919
import (
20-
"k8s.io/api/core/v1"
20+
v1 "k8s.io/api/core/v1"
2121
)
2222

2323
// HasPrivilegedRequest returns the value of SecurityContext.Privileged, taking into account
@@ -124,6 +124,25 @@ func DetermineEffectiveSecurityContext(pod *v1.Pod, container *v1.Container) *v1
124124
return effectiveSc
125125
}
126126

127+
// DetermineEffectiveRunAsUser returns a pointer of UID from the provided pod's
128+
// and container's security context and a bool value to indicate if it is absent.
129+
// Container's runAsUser take precedence in cases where both are set.
130+
func DetermineEffectiveRunAsUser(pod *v1.Pod, container *v1.Container) (*int64, bool) {
131+
var runAsUser *int64
132+
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.RunAsUser != nil {
133+
runAsUser = new(int64)
134+
*runAsUser = *pod.Spec.SecurityContext.RunAsUser
135+
}
136+
if container.SecurityContext != nil && container.SecurityContext.RunAsUser != nil {
137+
runAsUser = new(int64)
138+
*runAsUser = *container.SecurityContext.RunAsUser
139+
}
140+
if runAsUser == nil {
141+
return nil, false
142+
}
143+
return runAsUser, true
144+
}
145+
127146
func securityContextFromPodSecurityContext(pod *v1.Pod) *v1.SecurityContext {
128147
if pod.Spec.SecurityContext == nil {
129148
return nil

pkg/securitycontext/util_test.go

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ import (
2020
"reflect"
2121
"testing"
2222

23-
"k8s.io/api/core/v1"
23+
v1 "k8s.io/api/core/v1"
24+
utilptr "k8s.io/utils/pointer"
2425
)
2526

2627
func TestAddNoNewPrivileges(t *testing.T) {
@@ -120,3 +121,92 @@ func TestConvertToRuntimeReadonlyPaths(t *testing.T) {
120121
}
121122
}
122123
}
124+
125+
func TestDetermineEffectiveRunAsUser(t *testing.T) {
126+
tests := []struct {
127+
desc string
128+
pod *v1.Pod
129+
container *v1.Container
130+
wantRunAsUser *int64
131+
}{
132+
{
133+
desc: "no securityContext in pod, no securityContext in container",
134+
pod: &v1.Pod{
135+
Spec: v1.PodSpec{},
136+
},
137+
container: &v1.Container{},
138+
wantRunAsUser: nil,
139+
},
140+
{
141+
desc: "no runAsUser in pod, no runAsUser in container",
142+
pod: &v1.Pod{
143+
Spec: v1.PodSpec{
144+
SecurityContext: &v1.PodSecurityContext{},
145+
},
146+
},
147+
container: &v1.Container{
148+
SecurityContext: &v1.SecurityContext{},
149+
},
150+
wantRunAsUser: nil,
151+
},
152+
{
153+
desc: "runAsUser in pod, no runAsUser in container",
154+
pod: &v1.Pod{
155+
Spec: v1.PodSpec{
156+
SecurityContext: &v1.PodSecurityContext{
157+
RunAsUser: new(int64),
158+
},
159+
},
160+
},
161+
container: &v1.Container{
162+
SecurityContext: &v1.SecurityContext{},
163+
},
164+
wantRunAsUser: new(int64),
165+
},
166+
{
167+
desc: "no runAsUser in pod, runAsUser in container",
168+
pod: &v1.Pod{
169+
Spec: v1.PodSpec{
170+
SecurityContext: &v1.PodSecurityContext{},
171+
},
172+
},
173+
container: &v1.Container{
174+
SecurityContext: &v1.SecurityContext{
175+
RunAsUser: new(int64),
176+
},
177+
},
178+
wantRunAsUser: new(int64),
179+
},
180+
{
181+
desc: "no runAsUser in pod, runAsUser in container",
182+
pod: &v1.Pod{
183+
Spec: v1.PodSpec{
184+
SecurityContext: &v1.PodSecurityContext{
185+
RunAsUser: new(int64),
186+
},
187+
},
188+
},
189+
container: &v1.Container{
190+
SecurityContext: &v1.SecurityContext{
191+
RunAsUser: utilptr.Int64Ptr(1),
192+
},
193+
},
194+
wantRunAsUser: utilptr.Int64Ptr(1),
195+
},
196+
}
197+
198+
for _, test := range tests {
199+
t.Run(test.desc, func(t *testing.T) {
200+
runAsUser, ok := DetermineEffectiveRunAsUser(test.pod, test.container)
201+
if !ok && test.wantRunAsUser != nil {
202+
t.Errorf("DetermineEffectiveRunAsUser(%v, %v) = %v, want %d", test.pod, test.container, runAsUser, *test.wantRunAsUser)
203+
}
204+
if ok && test.wantRunAsUser == nil {
205+
t.Errorf("DetermineEffectiveRunAsUser(%v, %v) = %d, want %v", test.pod, test.container, *runAsUser, test.wantRunAsUser)
206+
}
207+
if ok && test.wantRunAsUser != nil && *runAsUser != *test.wantRunAsUser {
208+
t.Errorf("DetermineEffectiveRunAsUser(%v, %v) = %d, want %d", test.pod, test.container, *runAsUser, *test.wantRunAsUser)
209+
}
210+
})
211+
}
212+
}

pkg/volume/projected/BUILD

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@ go_test(
2222
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
2323
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
2424
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
25-
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
2625
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
2726
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
2827
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
2928
"//staging/src/k8s.io/client-go/testing:go_default_library",
29+
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
30+
"//vendor/k8s.io/utils/pointer:go_default_library",
3031
],
3132
)
3233

pkg/volume/projected/projected.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func (s *projectedVolumeMounter) SetUpAt(dir string, mounterArgs volume.MounterA
196196
return err
197197
}
198198

199-
data, err := s.collectData()
199+
data, err := s.collectData(mounterArgs)
200200
if err != nil {
201201
klog.Errorf("Error preparing data for projected volume %v for pod %v/%v: %s", s.volName, s.pod.Namespace, s.pod.Name, err.Error())
202202
return err
@@ -248,7 +248,7 @@ func (s *projectedVolumeMounter) SetUpAt(dir string, mounterArgs volume.MounterA
248248
return nil
249249
}
250250

251-
func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjection, error) {
251+
func (s *projectedVolumeMounter) collectData(mounterArgs volume.MounterArgs) (map[string]volumeutil.FileProjection, error) {
252252
if s.source.DefaultMode == nil {
253253
return nil, fmt.Errorf("No defaultMode used, not even the default value for it")
254254
}
@@ -328,6 +328,13 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec
328328
}
329329
tp := source.ServiceAccountToken
330330

331+
// When FsGroup is set, we depend on SetVolumeOwnership to
332+
// change from 0600 to 0640.
333+
mode := *s.source.DefaultMode
334+
if mounterArgs.FsUser != nil || mounterArgs.FsGroup != nil {
335+
mode = 0600
336+
}
337+
331338
var auds []string
332339
if len(tp.Audience) != 0 {
333340
auds = []string{tp.Audience}
@@ -349,8 +356,9 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec
349356
continue
350357
}
351358
payload[tp.Path] = volumeutil.FileProjection{
352-
Data: []byte(tr.Status.Token),
353-
Mode: 0600,
359+
Data: []byte(tr.Status.Token),
360+
Mode: mode,
361+
FsUser: mounterArgs.FsUser,
354362
}
355363
}
356364
}

0 commit comments

Comments
 (0)