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