Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugins): update kubernetes iac polices #240

Merged
merged 2 commits into from May 17, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions plugins/go/veinmind-iac/go.sum
Expand Up @@ -284,8 +284,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chaitin/libveinmind v1.5.2/go.mod h1:TXLYL6GeSAQ7pQ5IxPG4Tp0DuB1QvPPFhqdOjyiWxVU=
github.com/chaitin/libveinmind v1.5.5 h1:cd3aAc4v+p4ZTuzVPQQMqAgq4aboDoa1XAUxyl35hWg=
github.com/chaitin/libveinmind v1.5.5/go.mod h1:TXLYL6GeSAQ7pQ5IxPG4Tp0DuB1QvPPFhqdOjyiWxVU=
github.com/chaitin/libveinmind v1.5.6 h1:fyNq142a+uOfYZ68GTzElFXVB0dtEXvs+ffwk24+Vfg=
github.com/chaitin/libveinmind v1.5.6/go.mod h1:TXLYL6GeSAQ7pQ5IxPG4Tp0DuB1QvPPFhqdOjyiWxVU=
github.com/chaitin/veinmind-common-go v1.4.2 h1:+AK2lt/OI7/kGQpt3rkp1gVJvoxfosnxxFaBfi6nbGw=
github.com/chaitin/veinmind-common-go v1.4.2/go.mod h1:+dshrlmHiBtRV7ATyObBIg3SZoffpNCr1PdahT1LUQo=
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
Expand Down
1 change: 1 addition & 0 deletions plugins/go/veinmind-iac/pkg/parser/parser.go
Expand Up @@ -101,6 +101,7 @@ type KubernetesInput struct {
Spec interface{} `yaml:"spec" json:"spec"`
RoleRef interface{} `yaml:"roleRef" json:"roleRef"`
Status interface{} `yaml:"status" json:"status"`
Subjects interface{} `yaml:"subjects" json:"subjects"`
Authentication interface{} `yaml:"authentication" json:"authentication"`
Authorization interface{} `yaml:"authorization" json:"authorization"`
Template interface{} `yaml:"template" json:"template"`
Expand Down
@@ -1,9 +1,6 @@
package brightMirror.kubernetes

import data.common
import future.keywords.in
import future.keywords.contains
import future.keywords.if

risks[res]{
input.authentication.anonymous.enabled==true
Expand Down
@@ -1,12 +1,10 @@
package brightMirror.kubernetes

import data.common
import future.keywords.in
import future.keywords.contains
import future.keywords.if

risks[res]{
input.metadata.name=="system:anonymous"
input.kind=="ClusterRoleBinding"
input.roleRef.name=="cluster-admin"
input.subjects[i].name=="system:anonymous"
res := common.result({"original":"UnSafeSettings:`metadata.name`,`roleRef.name`", "Path": input.Path}, "KN-006")
}
Expand Up @@ -9,10 +9,11 @@ risks[res]{
input.spec.containers[i].command[i]=="kube-apiserver"
version:=input.spec.containers[i].image
contains(version,"v1.1")
inner:=input.spec.containers[i].command
not contains(version,"v1.19")
inner:=input.spec.containers[i].args
some val in inner
contains(val,"insecure-port")
not contains(val,"insecure-port=0")
code:=val
res := common.result({"original":"UnSafeSettings:`spec.containers.command`", "Path": input.Path}, "KN-005")
}
}
@@ -1,11 +1,14 @@
package brightMirror.kubernetes

import data.common
import future.keywords.in
import future.keywords.contains
import future.keywords.if

risks[res]{
contains(input.spec.containers[0].args[i],"enable-skip-login")
contains(input.spec.containers[_].args[i],"enable-skip-login")
ek1ng marked this conversation as resolved.
Show resolved Hide resolved
res := common.result({"original":"UnSafeSettings:`spec.containers.args`", "Path": input.Path}, "KN-008")
}

risks[res]{
contains(input.spec.template.spec.containers[_].args[i],"enable-skip-login")
res := common.result({"original":"UnSafeSettings:`spec.containers.args`", "Path": input.Path}, "KN-008")
}
Expand Up @@ -9,7 +9,7 @@ import future.keywords.if

risks[res]{
input.spec.containers[i].command[i]=="etcd"
every val in input.spec.containers[i].command{
every val in input.spec.containers[i].args{
not contains(val,"--client-cert-auth=true")
}
res := common.result({"original":"UnSafeSettings:`spec.containers.command missing --client-cert-auth=true`", "Path": input.Path}, "KN-009")
Expand Down
Expand Up @@ -9,7 +9,7 @@ import future.keywords.if

risks[res]{
input.spec.containers[i].command[i]=="etcd"
every val in input.spec.containers[i].command{
every val in input.spec.containers[i].args{
not contains(val,"--peer-client-cert-auth=true")
}
res := common.result({"original":"UnSafeSettings:`spec.containers.command missing --peer-client-cert-auth=true", "Path": input.Path}, "KN-010")
Expand Down
Expand Up @@ -3,7 +3,6 @@ package brightMirror.kubernetes
import data.common
import future.keywords.in


risks[res]{
inner := input.spec.containers[i].securityContext.capabilities.add
some val in inner
Expand Down
Expand Up @@ -3,9 +3,8 @@ package brightMirror.kubernetes
import data.common
import future.keywords.in


risks[res]{
input.spec.hostPID==true
input.spec.hostPID==true
inner := input.spec.containers[i].securityContext.capabilities.add
some val in inner
upper(val) == "SYS_PTRACE"
Expand Down
Expand Up @@ -3,8 +3,6 @@ package brightMirror.kubernetes
import data.common
import future.keywords.in



risks[res]{
inner := input.spec.containers[i].securityContext.capabilities.add
some val in inner
Expand All @@ -14,5 +12,4 @@ risks[res]{
Names=[Name]
Combine:=array.concat(Hints,Names)
res := common.result({"original":concat(":",Combine), "Path": input.Path}, "KN-012")

}
Expand Up @@ -3,9 +3,9 @@ package brightMirror.kubernetes
import data.common

risks[res] {
name := containers[_].name
key := sprintf("%s/%s", ["container.apparmor.security.beta.kubernetes.io", name])
val := annotations[i][key]
val != "runtime/default"
res := common.result({"original": val,"Path": input[i].Path}, "KN-003")
inner:= input.spec.containers[i]
key := sprintf("%s/%s", ["container.apparmor.security.beta.kubernetes.io", inner.name])
annotations:=input.metadata.annotations
annotations[key]!="runtime/default"
res := common.result({"original": annotations[key],"Path": input.Path}, "KN-003")
}
Expand Up @@ -3,14 +3,9 @@ package brightMirror.kubernetes
import data.common

risks[res] {
count(securityContexts) > 0
count(allowPrivilegeEscalations) > 0
allowPrivilegeEscalations[i] == true
res := common.result({"original": allowPrivilegeEscalations[i], "Path": input[i].Path}, "KN-002")
containers := input.spec.containers
securityContexts := containers[_].securityContext
allowPrivilegeEscalations := securityContexts.allowPrivilegeEscalations
allowPrivilegeEscalations == true
res := common.result({"original": "UnSafeSettings:set allowPrivilegeEscalation=true", "Path": input.Path}, "KN-002")
}

risks[res] {
count(securityContexts) > 0
count(allowPrivilegeEscalations) < 1
res := common.result({"original":"UnSafeSettings:`unset allowPrivilegeEscalation=false`", "Path": input[i].Path}, "KN-002")
}
Expand Up @@ -3,14 +3,14 @@ package brightMirror.kubernetes
import data.common

risks[res] {
image := containers[_].image
contains(image, "latest")
res := common.result({"original":image, "Path": input[i].Path}, "KN-001")
image := input.spec.containers[_].image
contains(image, "latest")
res := common.result({"original":input.spec.containers[_].image, "Path": input.Path}, "KN-001")
}

risks[res] {
image := containers[_].image
image := input.spec.containers[_].image
not contains(image, ":")
not equal(image, "scratch")
res := common.result({"original":image, "Path": input[i].Path}, "KN-001")
res := common.result({"original":input.spec.containers[_].image, "Path": input.Path}, "KN-001")
}
Expand Up @@ -13,5 +13,4 @@ risks[res]{
b=[d]
c:=array.concat(a,b)
res := common.result({"original":concat(":",c), "Path": input.Path}, "KN-011")

}
@@ -1,8 +1,17 @@
package brightMirror.kubernetes

import data.common
import future.keywords.every

#risks[res] {
# securityContexts
# res := kubernetes.result(securityContexts, "KN-004")
#}
default allow=false

allowValuesSeLinuxOptionsType:=["container_t","container_init_t","container_kvm_t"]

risks[res]{
inner := input.spec.containers[i]
type := inner.securityContext.seLinuxOptions.type
every val in allowValuesSeLinuxOptionsType {
val != type
}
res:= common.result({"original":"UnSafeSettings:`spec.containers.securityContext.seLinuxOptions.type`", "Path": input.Path},"KN-004")
}
8 changes: 8 additions & 0 deletions plugins/go/veinmind-iac/rules/test/kubernetes/KN-001.yaml
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx-container
image: nginx:latest
20 changes: 20 additions & 0 deletions plugins/go/veinmind-iac/rules/test/kubernetes/KN-002.yaml
@@ -0,0 +1,20 @@
apiVersion: v1
kind: Pod
metadata:
name: hello-privileged
spec:
containers:
- command:
- sh
- "-c"
- echo 'Hello' && sleep 1h
image: busybox:v1.26.0
name: hello
securityContext:
seccompProfile:
type: Localhost
runAsNonRoot: true
capabilities:
drop:
- ALL
allowPrivilegeEscalations: true
21 changes: 21 additions & 0 deletions plugins/go/veinmind-iac/rules/test/kubernetes/KN-003.yaml
@@ -0,0 +1,21 @@
apiVersion: v1
kind: Pod
metadata:
annotations:
container.apparmor.security.beta.kubernetes.io/hello: custom
name: hello-apparmor
spec:
containers:
- command:
- sh
- "-c"
- echo 'Hello AppArmor!' && sleep 1h
image: busybox:v1.26.0
name: hello
securityContext:
seccompProfile:
type: Localhost
runAsNonRoot: true
capabilities:
drop:
- ALL
21 changes: 21 additions & 0 deletions plugins/go/veinmind-iac/rules/test/kubernetes/KN-004.yaml
@@ -0,0 +1,21 @@
apiVersion: v1
kind: Pod
metadata:
name: hello-selinux
spec:
containers:
- command:
- sh
- "-c"
- echo 'Hello' && sleep 1h
image: busybox:v1.26.0
name: hello
securityContext:
seccompProfile:
type: Localhost
runAsNonRoot: true
capabilities:
drop:
- ALL
seLinuxOptions:
type: custom
13 changes: 13 additions & 0 deletions plugins/go/veinmind-iac/rules/test/kubernetes/KN-005.yaml
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
spec:
containers:
- name: kube-apiserver
image: k8s.gcr.io/kube-apiserver:v1.17.0
command:
- kube-apiserver
args:
- --insecure-port=8080
- --insecure-bind-address=0.0.0.0
12 changes: 12 additions & 0 deletions plugins/go/veinmind-iac/rules/test/kubernetes/KN-006.yaml
@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: anonymous-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: system:anonymous
11 changes: 11 additions & 0 deletions plugins/go/veinmind-iac/rules/test/kubernetes/KN-007.yaml
@@ -0,0 +1,11 @@
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: true
webhook:
enabled: false
x509:
clientCAFile: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
authorization:
mode: AlwaysAllow
33 changes: 33 additions & 0 deletions plugins/go/veinmind-iac/rules/test/kubernetes/KN-008.yaml
@@ -0,0 +1,33 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.2.0
args:
- --enable-skip-login
ports:
- containerPort: 8443
name: dashboard
protocol: TCP
volumeMounts:
- mountPath: /certs
name: kubernetes-dashboard-certs
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
26 changes: 26 additions & 0 deletions plugins/go/veinmind-iac/rules/test/kubernetes/KN-009.yaml
@@ -0,0 +1,26 @@
apiVersion: v1
kind: Pod
metadata:
name: etcd
namespace: kube-system
spec:
containers:
- name: etcd
image: quay.io/coreos/etcd:v3.4.15
command:
- etcd
args:
- --name=etcd-node
- --listen-client-urls=http://0.0.0.0:2379
- --advertise-client-urls=http://localhost:2379
- --listen-peer-urls=http://0.0.0.0:2380
- --initial-advertise-peer-urls=http://localhost:2380
- --initial-cluster=etcd-node=http://localhost:2380
- --initial-cluster-token=etcd-cluster
- --initial-cluster-state=new
- --peer-client-cert-auth=true
ports:
- containerPort: 2379
name: client
- containerPort: 2380
name: peer