Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
588f1584
Unverified
Commit
588f1584
authored
May 18, 2016
by
Clayton Coleman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add init container support to other admission controllers
parent
e2afc975
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
210 additions
and
4 deletions
+210
-4
admission.go
plugin/pkg/admission/alwayspullimages/admission.go
+4
-0
admission_test.go
plugin/pkg/admission/alwayspullimages/admission_test.go
+11
-0
admission.go
plugin/pkg/admission/exec/admission.go
+8
-0
admission_test.go
plugin/pkg/admission/exec/admission_test.go
+30
-0
admission.go
plugin/pkg/admission/securitycontext/scdeny/admission.go
+11
-0
admission_test.go
...in/pkg/admission/securitycontext/scdeny/admission_test.go
+18
-4
admission.go
plugin/pkg/admission/serviceaccount/admission.go
+24
-0
admission_test.go
plugin/pkg/admission/serviceaccount/admission_test.go
+104
-0
No files found.
plugin/pkg/admission/alwayspullimages/admission.go
View file @
588f1584
...
...
@@ -56,6 +56,10 @@ func (a *alwaysPullImages) Admit(attributes admission.Attributes) (err error) {
return
apierrors
.
NewBadRequest
(
"Resource was marked with kind Pod but was unable to be converted"
)
}
for
i
:=
range
pod
.
Spec
.
InitContainers
{
pod
.
Spec
.
InitContainers
[
i
]
.
ImagePullPolicy
=
api
.
PullAlways
}
for
i
:=
range
pod
.
Spec
.
Containers
{
pod
.
Spec
.
Containers
[
i
]
.
ImagePullPolicy
=
api
.
PullAlways
}
...
...
plugin/pkg/admission/alwayspullimages/admission_test.go
View file @
588f1584
...
...
@@ -32,6 +32,12 @@ func TestAdmission(t *testing.T) {
pod
:=
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
Spec
:
api
.
PodSpec
{
InitContainers
:
[]
api
.
Container
{
{
Name
:
"init1"
,
Image
:
"image"
},
{
Name
:
"init2"
,
Image
:
"image"
,
ImagePullPolicy
:
api
.
PullNever
},
{
Name
:
"init3"
,
Image
:
"image"
,
ImagePullPolicy
:
api
.
PullIfNotPresent
},
{
Name
:
"init4"
,
Image
:
"image"
,
ImagePullPolicy
:
api
.
PullAlways
},
},
Containers
:
[]
api
.
Container
{
{
Name
:
"ctr1"
,
Image
:
"image"
},
{
Name
:
"ctr2"
,
Image
:
"image"
,
ImagePullPolicy
:
api
.
PullNever
},
...
...
@@ -44,6 +50,11 @@ func TestAdmission(t *testing.T) {
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error returned from admission handler"
)
}
for
_
,
c
:=
range
pod
.
Spec
.
InitContainers
{
if
c
.
ImagePullPolicy
!=
api
.
PullAlways
{
t
.
Errorf
(
"Container %v: expected pull always, got %v"
,
c
,
c
.
ImagePullPolicy
)
}
}
for
_
,
c
:=
range
pod
.
Spec
.
Containers
{
if
c
.
ImagePullPolicy
!=
api
.
PullAlways
{
t
.
Errorf
(
"Container %v: expected pull always, got %v"
,
c
,
c
.
ImagePullPolicy
)
...
...
plugin/pkg/admission/exec/admission.go
View file @
588f1584
...
...
@@ -108,6 +108,14 @@ func (d *denyExec) Admit(a admission.Attributes) (err error) {
// isPrivileged will return true a pod has any privileged containers
func
isPrivileged
(
pod
*
api
.
Pod
)
bool
{
for
_
,
c
:=
range
pod
.
Spec
.
InitContainers
{
if
c
.
SecurityContext
==
nil
{
continue
}
if
*
c
.
SecurityContext
.
Privileged
{
return
true
}
}
for
_
,
c
:=
range
pod
.
Spec
.
Containers
{
if
c
.
SecurityContext
==
nil
{
continue
...
...
plugin/pkg/admission/exec/admission_test.go
View file @
588f1584
...
...
@@ -85,6 +85,29 @@ func TestAdmission(t *testing.T) {
for
_
,
tc
:=
range
testCases
{
testAdmission
(
t
,
tc
.
pod
,
handler
,
true
)
}
// run against an init container
handler
=
&
denyExec
{
Handler
:
admission
.
NewHandler
(
admission
.
Connect
),
hostIPC
:
true
,
hostPID
:
true
,
privileged
:
true
,
}
for
_
,
tc
:=
range
testCases
{
tc
.
pod
.
Spec
.
InitContainers
=
tc
.
pod
.
Spec
.
Containers
tc
.
pod
.
Spec
.
Containers
=
nil
testAdmission
(
t
,
tc
.
pod
,
handler
,
tc
.
shouldAccept
)
}
// run with a permissive config and all cases should pass
handler
.
privileged
=
false
handler
.
hostPID
=
false
handler
.
hostIPC
=
false
for
_
,
tc
:=
range
testCases
{
testAdmission
(
t
,
tc
.
pod
,
handler
,
true
)
}
}
func
testAdmission
(
t
*
testing
.
T
,
pod
*
api
.
Pod
,
handler
*
denyExec
,
shouldAccept
bool
)
{
...
...
@@ -173,6 +196,13 @@ func TestDenyExecOnPrivileged(t *testing.T) {
for
_
,
tc
:=
range
testCases
{
testAdmission
(
t
,
tc
.
pod
,
handler
,
tc
.
shouldAccept
)
}
// test init containers
for
_
,
tc
:=
range
testCases
{
tc
.
pod
.
Spec
.
InitContainers
=
tc
.
pod
.
Spec
.
Containers
tc
.
pod
.
Spec
.
Containers
=
nil
testAdmission
(
t
,
tc
.
pod
,
handler
,
tc
.
shouldAccept
)
}
}
func
validPod
(
name
string
)
*
api
.
Pod
{
...
...
plugin/pkg/admission/securitycontext/scdeny/admission.go
View file @
588f1584
...
...
@@ -74,6 +74,17 @@ func (p *plugin) Admit(a admission.Attributes) (err error) {
return
apierrors
.
NewForbidden
(
a
.
GetResource
()
.
GroupResource
(),
pod
.
Name
,
fmt
.
Errorf
(
"SecurityContext.FSGroup is forbidden"
))
}
for
_
,
v
:=
range
pod
.
Spec
.
InitContainers
{
if
v
.
SecurityContext
!=
nil
{
if
v
.
SecurityContext
.
SELinuxOptions
!=
nil
{
return
apierrors
.
NewForbidden
(
a
.
GetResource
()
.
GroupResource
(),
pod
.
Name
,
fmt
.
Errorf
(
"SecurityContext.SELinuxOptions is forbidden"
))
}
if
v
.
SecurityContext
.
RunAsUser
!=
nil
{
return
apierrors
.
NewForbidden
(
a
.
GetResource
()
.
GroupResource
(),
pod
.
Name
,
fmt
.
Errorf
(
"SecurityContext.RunAsUser is forbidden"
))
}
}
}
for
_
,
v
:=
range
pod
.
Spec
.
Containers
{
if
v
.
SecurityContext
!=
nil
{
if
v
.
SecurityContext
.
SELinuxOptions
!=
nil
{
...
...
plugin/pkg/admission/securitycontext/scdeny/admission_test.go
View file @
588f1584
...
...
@@ -78,11 +78,25 @@ func TestAdmission(t *testing.T) {
}
for
_
,
tc
:=
range
cases
{
p
od
:=
pod
()
p
od
.
Spec
.
SecurityContext
=
tc
.
podSc
p
od
.
Spec
.
Containers
[
0
]
.
SecurityContext
=
tc
.
sc
p
:=
pod
()
p
.
Spec
.
SecurityContext
=
tc
.
podSc
p
.
Spec
.
Containers
[
0
]
.
SecurityContext
=
tc
.
sc
err
:=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
pod
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"foo"
,
"name"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
"ignored"
,
nil
))
err
:=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
p
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"foo"
,
"name"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
"ignored"
,
nil
))
if
err
!=
nil
&&
!
tc
.
expectError
{
t
.
Errorf
(
"%v: unexpected error: %v"
,
tc
.
name
,
err
)
}
else
if
err
==
nil
&&
tc
.
expectError
{
t
.
Errorf
(
"%v: expected error"
,
tc
.
name
)
}
// verify init containers are also checked
p
=
pod
()
p
.
Spec
.
SecurityContext
=
tc
.
podSc
p
.
Spec
.
Containers
[
0
]
.
SecurityContext
=
tc
.
sc
p
.
Spec
.
InitContainers
=
p
.
Spec
.
Containers
p
.
Spec
.
Containers
=
nil
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
p
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
"foo"
,
"name"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
"ignored"
,
nil
))
if
err
!=
nil
&&
!
tc
.
expectError
{
t
.
Errorf
(
"%v: unexpected error: %v"
,
tc
.
name
,
err
)
}
else
if
err
==
nil
&&
tc
.
expectError
{
...
...
plugin/pkg/admission/serviceaccount/admission.go
View file @
588f1584
...
...
@@ -324,6 +324,16 @@ func (s *serviceAccount) limitSecretReferences(serviceAccount *api.ServiceAccoun
}
}
for
_
,
container
:=
range
pod
.
Spec
.
InitContainers
{
for
_
,
env
:=
range
container
.
Env
{
if
env
.
ValueFrom
!=
nil
&&
env
.
ValueFrom
.
SecretKeyRef
!=
nil
{
if
!
mountableSecrets
.
Has
(
env
.
ValueFrom
.
SecretKeyRef
.
Name
)
{
return
fmt
.
Errorf
(
"Init container %s with envVar %s referencing secret.secretName=
\"
%s
\"
is not allowed because service account %s does not reference that secret"
,
container
.
Name
,
env
.
Name
,
env
.
ValueFrom
.
SecretKeyRef
.
Name
,
serviceAccount
.
Name
)
}
}
}
}
for
_
,
container
:=
range
pod
.
Spec
.
Containers
{
for
_
,
env
:=
range
container
.
Env
{
if
env
.
ValueFrom
!=
nil
&&
env
.
ValueFrom
.
SecretKeyRef
!=
nil
{
...
...
@@ -394,6 +404,20 @@ func (s *serviceAccount) mountServiceAccountToken(serviceAccount *api.ServiceAcc
// Ensure every container mounts the APISecret volume
needsTokenVolume
:=
false
for
i
,
container
:=
range
pod
.
Spec
.
InitContainers
{
existingContainerMount
:=
false
for
_
,
volumeMount
:=
range
container
.
VolumeMounts
{
// Existing mounts at the default mount path prevent mounting of the API token
if
volumeMount
.
MountPath
==
DefaultAPITokenMountPath
{
existingContainerMount
=
true
break
}
}
if
!
existingContainerMount
{
pod
.
Spec
.
InitContainers
[
i
]
.
VolumeMounts
=
append
(
pod
.
Spec
.
InitContainers
[
i
]
.
VolumeMounts
,
volumeMount
)
needsTokenVolume
=
true
}
}
for
i
,
container
:=
range
pod
.
Spec
.
Containers
{
existingContainerMount
:=
false
for
_
,
volumeMount
:=
range
container
.
VolumeMounts
{
...
...
plugin/pkg/admission/serviceaccount/admission_test.go
View file @
588f1584
...
...
@@ -290,6 +290,33 @@ func TestAutomountsAPIToken(t *testing.T) {
if
!
reflect
.
DeepEqual
(
expectedVolumeMount
,
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
[
0
])
{
t
.
Fatalf
(
"Expected
\n\t
%#v
\n
got
\n\t
%#v"
,
expectedVolumeMount
,
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
[
0
])
}
pod
=
&
api
.
Pod
{
Spec
:
api
.
PodSpec
{
InitContainers
:
[]
api
.
Container
{
{},
},
},
}
attrs
=
admission
.
NewAttributesRecord
(
pod
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
ns
,
"myname"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
)
if
err
:=
admit
.
Admit
(
attrs
);
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
if
pod
.
Spec
.
ServiceAccountName
!=
DefaultServiceAccountName
{
t
.
Errorf
(
"Expected service account %s assigned, got %s"
,
DefaultServiceAccountName
,
pod
.
Spec
.
ServiceAccountName
)
}
if
len
(
pod
.
Spec
.
Volumes
)
!=
1
{
t
.
Fatalf
(
"Expected 1 volume, got %d"
,
len
(
pod
.
Spec
.
Volumes
))
}
if
!
reflect
.
DeepEqual
(
expectedVolume
,
pod
.
Spec
.
Volumes
[
0
])
{
t
.
Fatalf
(
"Expected
\n\t
%#v
\n
got
\n\t
%#v"
,
expectedVolume
,
pod
.
Spec
.
Volumes
[
0
])
}
if
len
(
pod
.
Spec
.
InitContainers
[
0
]
.
VolumeMounts
)
!=
1
{
t
.
Fatalf
(
"Expected 1 volume mount, got %d"
,
len
(
pod
.
Spec
.
InitContainers
[
0
]
.
VolumeMounts
))
}
if
!
reflect
.
DeepEqual
(
expectedVolumeMount
,
pod
.
Spec
.
InitContainers
[
0
]
.
VolumeMounts
[
0
])
{
t
.
Fatalf
(
"Expected
\n\t
%#v
\n
got
\n\t
%#v"
,
expectedVolumeMount
,
pod
.
Spec
.
InitContainers
[
0
]
.
VolumeMounts
[
0
])
}
}
func
TestRespectsExistingMount
(
t
*
testing
.
T
)
{
...
...
@@ -366,6 +393,35 @@ func TestRespectsExistingMount(t *testing.T) {
if
!
reflect
.
DeepEqual
(
expectedVolumeMount
,
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
[
0
])
{
t
.
Fatalf
(
"Expected
\n\t
%#v
\n
got
\n\t
%#v"
,
expectedVolumeMount
,
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
[
0
])
}
// check init containers
pod
=
&
api
.
Pod
{
Spec
:
api
.
PodSpec
{
InitContainers
:
[]
api
.
Container
{
{
VolumeMounts
:
[]
api
.
VolumeMount
{
expectedVolumeMount
,
},
},
},
},
}
attrs
=
admission
.
NewAttributesRecord
(
pod
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
ns
,
"myname"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
)
if
err
:=
admit
.
Admit
(
attrs
);
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
if
pod
.
Spec
.
ServiceAccountName
!=
DefaultServiceAccountName
{
t
.
Errorf
(
"Expected service account %s assigned, got %s"
,
DefaultServiceAccountName
,
pod
.
Spec
.
ServiceAccountName
)
}
if
len
(
pod
.
Spec
.
Volumes
)
!=
0
{
t
.
Fatalf
(
"Expected 0 volumes (shouldn't create a volume for a secret we don't need), got %d"
,
len
(
pod
.
Spec
.
Volumes
))
}
if
len
(
pod
.
Spec
.
InitContainers
[
0
]
.
VolumeMounts
)
!=
1
{
t
.
Fatalf
(
"Expected 1 volume mount, got %d"
,
len
(
pod
.
Spec
.
InitContainers
[
0
]
.
VolumeMounts
))
}
if
!
reflect
.
DeepEqual
(
expectedVolumeMount
,
pod
.
Spec
.
InitContainers
[
0
]
.
VolumeMounts
[
0
])
{
t
.
Fatalf
(
"Expected
\n\t
%#v
\n
got
\n\t
%#v"
,
expectedVolumeMount
,
pod
.
Spec
.
InitContainers
[
0
]
.
VolumeMounts
[
0
])
}
}
func
TestAllowsReferencedSecret
(
t
*
testing
.
T
)
{
...
...
@@ -421,6 +477,30 @@ func TestAllowsReferencedSecret(t *testing.T) {
if
err
:=
admit
.
Admit
(
attrs
);
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
pod2
=
&
api
.
Pod
{
Spec
:
api
.
PodSpec
{
InitContainers
:
[]
api
.
Container
{
{
Name
:
"container-1"
,
Env
:
[]
api
.
EnvVar
{
{
Name
:
"env-1"
,
ValueFrom
:
&
api
.
EnvVarSource
{
SecretKeyRef
:
&
api
.
SecretKeySelector
{
LocalObjectReference
:
api
.
LocalObjectReference
{
Name
:
"foo"
},
},
},
},
},
},
},
},
}
attrs
=
admission
.
NewAttributesRecord
(
pod2
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
ns
,
"myname"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
)
if
err
:=
admit
.
Admit
(
attrs
);
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
}
func
TestRejectsUnreferencedSecretVolumes
(
t
*
testing
.
T
)
{
...
...
@@ -473,6 +553,30 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) {
if
err
:=
admit
.
Admit
(
attrs
);
err
==
nil
||
!
strings
.
Contains
(
err
.
Error
(),
"with envVar"
)
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
pod2
=
&
api
.
Pod
{
Spec
:
api
.
PodSpec
{
InitContainers
:
[]
api
.
Container
{
{
Name
:
"container-1"
,
Env
:
[]
api
.
EnvVar
{
{
Name
:
"env-1"
,
ValueFrom
:
&
api
.
EnvVarSource
{
SecretKeyRef
:
&
api
.
SecretKeySelector
{
LocalObjectReference
:
api
.
LocalObjectReference
{
Name
:
"foo"
},
},
},
},
},
},
},
},
}
attrs
=
admission
.
NewAttributesRecord
(
pod2
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
ns
,
"myname"
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
)
if
err
:=
admit
.
Admit
(
attrs
);
err
==
nil
||
!
strings
.
Contains
(
err
.
Error
(),
"with envVar"
)
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
}
func
TestAllowUnreferencedSecretVolumesForPermissiveSAs
(
t
*
testing
.
T
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment