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
b622acf8
Unverified
Commit
b622acf8
authored
Aug 24, 2018
by
Marko Mudrinić
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
admission/exec: externalize exec admission controller
parent
963adda7
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
58 additions
and
64 deletions
+58
-64
BUILD
plugin/pkg/admission/exec/BUILD
+5
-4
admission.go
plugin/pkg/admission/exec/admission.go
+37
-41
admission_test.go
plugin/pkg/admission/exec/admission_test.go
+16
-19
No files found.
plugin/pkg/admission/exec/BUILD
View file @
b622acf8
...
...
@@ -11,11 +11,11 @@ go_library(
srcs = ["admission.go"],
importpath = "k8s.io/kubernetes/plugin/pkg/admission/exec",
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
],
)
...
...
@@ -25,10 +25,11 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//
pkg/client/clientset_generated/internalclientset/fake
:go_default_library",
"//
staging/src/k8s.io/api/core/v1
:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library",
],
)
...
...
plugin/pkg/admission/exec/admission.go
View file @
b622acf8
...
...
@@ -20,11 +20,11 @@ import (
"fmt"
"io"
corev1
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
kubeapiserveradmission
"k8s.io/kubernetes/pkg/kubeapiserver/admission"
genericadmissioninitializer
"k8s.io/apiserver/pkg/admission/initializer"
"k8s.io/client-go/kubernetes"
)
const
(
...
...
@@ -52,7 +52,7 @@ func Register(plugins *admission.Plugins) {
// a pod using host based configurations.
type
DenyExec
struct
{
*
admission
.
Handler
client
internalclientset
.
Interface
client
kubernetes
.
Interface
// these flags control which items will be checked to deny exec/attach
hostNetwork
bool
...
...
@@ -62,8 +62,20 @@ type DenyExec struct {
}
var
_
admission
.
ValidationInterface
=
&
DenyExec
{}
var
_
=
genericadmissioninitializer
.
WantsExternalKubeClientSet
(
&
DenyExec
{})
var
_
=
kubeapiserveradmission
.
WantsInternalKubeClientSet
(
&
DenyExec
{})
// NewDenyExecOnPrivileged creates a new admission controller that is only checking the privileged
// option. This is for legacy support of the DenyExecOnPrivileged admission controller.
// Most of the time NewDenyEscalatingExec should be preferred.
func
NewDenyExecOnPrivileged
()
*
DenyExec
{
return
&
DenyExec
{
Handler
:
admission
.
NewHandler
(
admission
.
Connect
),
hostNetwork
:
false
,
hostIPC
:
false
,
hostPID
:
false
,
privileged
:
true
,
}
}
// NewDenyEscalatingExec creates a new admission controller that denies an exec operation on a pod
// using host based configurations.
...
...
@@ -77,17 +89,17 @@ func NewDenyEscalatingExec() *DenyExec {
}
}
// NewDenyExecOnPrivileged creates a new admission controller that is only checking the privileged
// option. This is for legacy support of the DenyExecOnPrivileged admission controller.
// Most of the time NewDenyEscalatingExec should be preferred.
func
NewDenyExecOnPrivileged
()
*
DenyExec
{
return
&
DenyExec
{
Handler
:
admission
.
NewHandler
(
admission
.
Connect
),
hostNetwork
:
false
,
hostIPC
:
false
,
hostPID
:
false
,
privileged
:
true
,
// SetExternalKubeClientSet implements the WantsInternalKubeClientSet interface.
func
(
d
*
DenyExec
)
SetExternalKubeClientSet
(
client
kubernetes
.
Interface
)
{
d
.
client
=
client
}
// ValidateInitialization implements the InitializationValidator interface.
func
(
d
*
DenyExec
)
ValidateInitialization
()
error
{
if
d
.
client
==
nil
{
return
fmt
.
Errorf
(
"missing client"
)
}
return
nil
}
// Validate makes an admission decision based on the request attributes
...
...
@@ -100,24 +112,21 @@ func (d *DenyExec) Validate(a admission.Attributes) (err error) {
if
path
!=
"pods/exec"
&&
path
!=
"pods/attach"
{
return
nil
}
pod
,
err
:=
d
.
client
.
Core
()
.
Pods
(
a
.
GetNamespace
())
.
Get
(
a
.
GetName
(),
metav1
.
GetOptions
{})
pod
,
err
:=
d
.
client
.
Core
V1
()
.
Pods
(
a
.
GetNamespace
())
.
Get
(
a
.
GetName
(),
metav1
.
GetOptions
{})
if
err
!=
nil
{
return
admission
.
NewForbidden
(
a
,
err
)
}
if
pod
.
Spec
.
SecurityContext
!=
nil
{
securityContext
:=
pod
.
Spec
.
SecurityContext
if
d
.
hostNetwork
&&
securityContext
.
HostNetwork
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"cannot exec into or attach to a container using host network"
))
}
if
d
.
hostNetwork
&&
pod
.
Spec
.
HostNetwork
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"cannot exec into or attach to a container using host network"
))
}
if
d
.
hostPID
&&
securityContext
.
HostPID
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"cannot exec into or attach to a container using host pid"
))
}
if
d
.
hostPID
&&
pod
.
Spec
.
HostPID
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"cannot exec into or attach to a container using host pid"
))
}
if
d
.
hostIPC
&&
securityContext
.
HostIPC
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"cannot exec into or attach to a container using host ipc"
))
}
if
d
.
hostIPC
&&
pod
.
Spec
.
HostIPC
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"cannot exec into or attach to a container using host ipc"
))
}
if
d
.
privileged
&&
isPrivileged
(
pod
)
{
...
...
@@ -128,7 +137,7 @@ func (d *DenyExec) Validate(a admission.Attributes) (err error) {
}
// isPrivileged will return true a pod has any privileged containers
func
isPrivileged
(
pod
*
api
.
Pod
)
bool
{
func
isPrivileged
(
pod
*
corev1
.
Pod
)
bool
{
for
_
,
c
:=
range
pod
.
Spec
.
InitContainers
{
if
c
.
SecurityContext
==
nil
||
c
.
SecurityContext
.
Privileged
==
nil
{
continue
...
...
@@ -147,16 +156,3 @@ func isPrivileged(pod *api.Pod) bool {
}
return
false
}
// SetInternalKubeClientSet implements the WantsInternalKubeClientSet interface.
func
(
d
*
DenyExec
)
SetInternalKubeClientSet
(
client
internalclientset
.
Interface
)
{
d
.
client
=
client
}
// ValidateInitialization implements the InitializationValidator interface.
func
(
d
*
DenyExec
)
ValidateInitialization
()
error
{
if
d
.
client
==
nil
{
return
fmt
.
Errorf
(
"missing client"
)
}
return
nil
}
plugin/pkg/admission/exec/admission_test.go
View file @
b622acf8
...
...
@@ -19,12 +19,13 @@ package exec
import
(
"testing"
corev1
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
"k8s.io/client-go/kubernetes/fake"
core
"k8s.io/client-go/testing"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
)
// newAllowEscalatingExec returns `admission.Interface` that allows execution on
...
...
@@ -41,20 +42,18 @@ func newAllowEscalatingExec() *DenyExec {
func
TestAdmission
(
t
*
testing
.
T
)
{
privPod
:=
validPod
(
"privileged"
)
priv
:=
true
privPod
.
Spec
.
Containers
[
0
]
.
SecurityContext
=
&
api
.
SecurityContext
{
privPod
.
Spec
.
Containers
[
0
]
.
SecurityContext
=
&
corev1
.
SecurityContext
{
Privileged
:
&
priv
,
}
hostPIDPod
:=
validPod
(
"hostPID"
)
hostPIDPod
.
Spec
.
SecurityContext
=
&
api
.
PodSecurityContext
{}
hostPIDPod
.
Spec
.
SecurityContext
.
HostPID
=
true
hostPIDPod
.
Spec
.
HostPID
=
true
hostIPCPod
:=
validPod
(
"hostIPC"
)
hostIPCPod
.
Spec
.
SecurityContext
=
&
api
.
PodSecurityContext
{}
hostIPCPod
.
Spec
.
SecurityContext
.
HostIPC
=
true
hostIPCPod
.
Spec
.
HostIPC
=
true
testCases
:=
map
[
string
]
struct
{
pod
*
api
.
Pod
pod
*
corev1
.
Pod
shouldAccept
bool
}{
"priv"
:
{
...
...
@@ -106,7 +105,7 @@ func TestAdmission(t *testing.T) {
}
}
func
testAdmission
(
t
*
testing
.
T
,
pod
*
api
.
Pod
,
handler
*
DenyExec
,
shouldAccept
bool
)
{
func
testAdmission
(
t
*
testing
.
T
,
pod
*
corev1
.
Pod
,
handler
*
DenyExec
,
shouldAccept
bool
)
{
mockClient
:=
&
fake
.
Clientset
{}
mockClient
.
AddReactor
(
"get"
,
"pods"
,
func
(
action
core
.
Action
)
(
bool
,
runtime
.
Object
,
error
)
{
if
action
.
(
core
.
GetAction
)
.
GetName
()
==
pod
.
Name
{
...
...
@@ -116,7 +115,7 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b
return
true
,
nil
,
nil
})
handler
.
Set
In
ternalKubeClientSet
(
mockClient
)
handler
.
Set
Ex
ternalKubeClientSet
(
mockClient
)
admission
.
ValidateInitialization
(
handler
)
// pods/exec
...
...
@@ -146,20 +145,18 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b
func
TestDenyExecOnPrivileged
(
t
*
testing
.
T
)
{
privPod
:=
validPod
(
"privileged"
)
priv
:=
true
privPod
.
Spec
.
Containers
[
0
]
.
SecurityContext
=
&
api
.
SecurityContext
{
privPod
.
Spec
.
Containers
[
0
]
.
SecurityContext
=
&
corev1
.
SecurityContext
{
Privileged
:
&
priv
,
}
hostPIDPod
:=
validPod
(
"hostPID"
)
hostPIDPod
.
Spec
.
SecurityContext
=
&
api
.
PodSecurityContext
{}
hostPIDPod
.
Spec
.
SecurityContext
.
HostPID
=
true
hostPIDPod
.
Spec
.
HostPID
=
true
hostIPCPod
:=
validPod
(
"hostIPC"
)
hostIPCPod
.
Spec
.
SecurityContext
=
&
api
.
PodSecurityContext
{}
hostIPCPod
.
Spec
.
SecurityContext
.
HostIPC
=
true
hostIPCPod
.
Spec
.
HostIPC
=
true
testCases
:=
map
[
string
]
struct
{
pod
*
api
.
Pod
pod
*
corev1
.
Pod
shouldAccept
bool
}{
"priv"
:
{
...
...
@@ -195,11 +192,11 @@ func TestDenyExecOnPrivileged(t *testing.T) {
}
}
func
validPod
(
name
string
)
*
api
.
Pod
{
return
&
api
.
Pod
{
func
validPod
(
name
string
)
*
corev1
.
Pod
{
return
&
corev1
.
Pod
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
name
,
Namespace
:
"test"
},
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
Spec
:
corev1
.
PodSpec
{
Containers
:
[]
corev1
.
Container
{
{
Name
:
"ctr1"
,
Image
:
"image"
},
{
Name
:
"ctr2"
,
Image
:
"image2"
},
},
...
...
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