mirror of
https://github.com/aquasecurity/kube-bench.git
synced 2025-06-05 07:38:50 +00:00
add alternative method to identify AKS specific cluster
This commit is contained in:
parent
754c462d54
commit
b446c25c3c
@ -10,7 +10,16 @@ groups:
|
|||||||
checks:
|
checks:
|
||||||
- id: 4.1.1
|
- id: 4.1.1
|
||||||
text: "Ensure that the cluster-admin role is only used where required (Automated)"
|
text: "Ensure that the cluster-admin role is only used where required (Automated)"
|
||||||
type: "manual"
|
audit: "kubectl get clusterrolebindings -o=custom-columns=NAME:.metadata.name,ROLE:.roleRef.name,SUBJECT:.subjects[*].name"
|
||||||
|
audit_config: "kubectl get clusterrolebindings"
|
||||||
|
tests:
|
||||||
|
test_items:
|
||||||
|
- flag: cluster-admin
|
||||||
|
path: '{.roleRef.name}'
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: eq
|
||||||
|
value: "cluster-admin"
|
||||||
remediation: |
|
remediation: |
|
||||||
Identify all clusterrolebindings to the cluster-admin role. Check if they are used and
|
Identify all clusterrolebindings to the cluster-admin role. Check if they are used and
|
||||||
if they need this role or if they could use a role with fewer privileges.
|
if they need this role or if they could use a role with fewer privileges.
|
||||||
@ -21,7 +30,34 @@ groups:
|
|||||||
|
|
||||||
- id: 4.1.2
|
- id: 4.1.2
|
||||||
text: "Minimize access to secrets (Automated)"
|
text: "Minimize access to secrets (Automated)"
|
||||||
type: "manual"
|
audit: "kubectl get roles,rolebindings --all-namespaces -o=custom-columns=NAME:.metadata.name,ROLE:.rules[*].resources,SUBJECT:.subjects[*].name"
|
||||||
|
audit_config: "kubectl get roles --all-namespaces"
|
||||||
|
tests:
|
||||||
|
test_items:
|
||||||
|
- flag: secrets
|
||||||
|
path: '{.rules[*].resources}'
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: eq
|
||||||
|
value: "secrets"
|
||||||
|
- flag: get
|
||||||
|
path: '{.rules[*].verbs}'
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: contains
|
||||||
|
value: "get"
|
||||||
|
- flag: list
|
||||||
|
path: '{.rules[*].verbs}'
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: contains
|
||||||
|
value: "list"
|
||||||
|
- flag: watch
|
||||||
|
path: '{.rules[*].verbs}'
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: contains
|
||||||
|
value: "watch"
|
||||||
remediation: |
|
remediation: |
|
||||||
Where possible, remove get, list and watch access to secret objects in the cluster.
|
Where possible, remove get, list and watch access to secret objects in the cluster.
|
||||||
scored: false
|
scored: false
|
||||||
@ -45,14 +81,44 @@ groups:
|
|||||||
|
|
||||||
- id: 4.1.4
|
- id: 4.1.4
|
||||||
text: "Minimize access to create pods (Automated)"
|
text: "Minimize access to create pods (Automated)"
|
||||||
type: "manual"
|
audit: "kubectl get roles,rolebindings --all-namespaces -o=custom-columns=NAME:.metadata.name,ROLE:.rules[*].resources,SUBJECT:.subjects[*].name"
|
||||||
|
audit_config: "kubectl get roles --all-namespaces"
|
||||||
|
tests:
|
||||||
|
test_items:
|
||||||
|
- flag: pods
|
||||||
|
path: '{.rules[*].resources}'
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: eq
|
||||||
|
value: "pods"
|
||||||
|
- flag: create
|
||||||
|
path: '{.rules[*].verbs}'
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: contains
|
||||||
|
value: "create"
|
||||||
remediation: |
|
remediation: |
|
||||||
Where possible, remove create access to pod objects in the cluster.
|
Where possible, remove create access to pod objects in the cluster.
|
||||||
scored: false
|
scored: false
|
||||||
|
|
||||||
- id: 4.1.5
|
- id: 4.1.5
|
||||||
text: "Ensure that default service accounts are not actively used (Automated)"
|
text: "Ensure that default service accounts are not actively used (Automated)"
|
||||||
type: "manual"
|
audit: "kubectl get serviceaccounts --all-namespaces -o custom-columns=NAME:.metadata.name,NAMESPACE:.metadata.namespace,TOKEN:.automountServiceAccountToken"
|
||||||
|
audit_config: "kubectl get serviceaccounts --all-namespaces"
|
||||||
|
tests:
|
||||||
|
test_items:
|
||||||
|
- flag: default
|
||||||
|
path: '{.metadata.name}'
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: eq
|
||||||
|
value: "default"
|
||||||
|
- flag: automountServiceAccountToken
|
||||||
|
path: '{.automountServiceAccountToken}'
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: eq
|
||||||
|
value: "false"
|
||||||
remediation: |
|
remediation: |
|
||||||
Create explicit service accounts wherever a Kubernetes workload requires specific access
|
Create explicit service accounts wherever a Kubernetes workload requires specific access
|
||||||
to the Kubernetes API server.
|
to the Kubernetes API server.
|
||||||
@ -62,7 +128,16 @@ groups:
|
|||||||
|
|
||||||
- id: 4.1.6
|
- id: 4.1.6
|
||||||
text: "Ensure that Service Account Tokens are only mounted where necessary (Automated)"
|
text: "Ensure that Service Account Tokens are only mounted where necessary (Automated)"
|
||||||
type: "manual"
|
audit: "kubectl get pods --all-namespaces -o custom-columns=NAME:.metadata.name,NAMESPACE:.metadata.namespace,SERVICE_ACCOUNT:.spec.serviceAccountName,MOUNT_TOKEN:.spec.automountServiceAccountToken"
|
||||||
|
audit_config: "kubectl get pods --all-namespaces"
|
||||||
|
tests:
|
||||||
|
test_items:
|
||||||
|
- flag: automountServiceAccountToken
|
||||||
|
path: '{.spec.automountServiceAccountToken}'
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: eq
|
||||||
|
value: "false"
|
||||||
remediation: |
|
remediation: |
|
||||||
Modify the definition of pods and service accounts which do not need to mount service
|
Modify the definition of pods and service accounts which do not need to mount service
|
||||||
account tokens to disable it.
|
account tokens to disable it.
|
||||||
@ -258,7 +333,16 @@ groups:
|
|||||||
|
|
||||||
- id: 4.6.3
|
- id: 4.6.3
|
||||||
text: "The default namespace should not be used (Automated)"
|
text: "The default namespace should not be used (Automated)"
|
||||||
type: "manual"
|
audit: "kubectl get all -n default"
|
||||||
|
audit_config: "kubectl get all -n default"
|
||||||
|
tests:
|
||||||
|
test_items:
|
||||||
|
- flag: "namespace"
|
||||||
|
path: "{.metadata.namespace}"
|
||||||
|
set: true
|
||||||
|
compare:
|
||||||
|
op: eq
|
||||||
|
value: "default"
|
||||||
remediation: |
|
remediation: |
|
||||||
Ensure that namespaces are created to allow for appropriate segregation of Kubernetes
|
Ensure that namespaces are created to allow for appropriate segregation of Kubernetes
|
||||||
resources and that all new resources are created in a specific namespace.
|
resources and that all new resources are created in a specific namespace.
|
||||||
|
29
cmd/util.go
29
cmd/util.go
@ -300,6 +300,7 @@ func getKubeVersion() (*KubeVersion, error) {
|
|||||||
glog.V(3).Infof("Error fetching cluster config: %s", err)
|
glog.V(3).Infof("Error fetching cluster config: %s", err)
|
||||||
}
|
}
|
||||||
isRKE := false
|
isRKE := false
|
||||||
|
isAKS := false // Variable to track AKS detection
|
||||||
if err == nil && kubeConfig != nil {
|
if err == nil && kubeConfig != nil {
|
||||||
k8sClient, err := kubernetes.NewForConfig(kubeConfig)
|
k8sClient, err := kubernetes.NewForConfig(kubeConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -311,7 +312,12 @@ func getKubeVersion() (*KubeVersion, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(3).Infof("Error detecting RKE cluster: %s", err)
|
glog.V(3).Infof("Error detecting RKE cluster: %s", err)
|
||||||
}
|
}
|
||||||
|
isAKS, err = IsAKS(context.Background(), k8sClient)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(3).Infof("Error detecting AKS cluster: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if k8sVer, err := getKubeVersionFromRESTAPI(); err == nil {
|
if k8sVer, err := getKubeVersionFromRESTAPI(); err == nil {
|
||||||
@ -319,6 +325,9 @@ func getKubeVersion() (*KubeVersion, error) {
|
|||||||
if isRKE {
|
if isRKE {
|
||||||
k8sVer.GitVersion = k8sVer.GitVersion + "-rancher1"
|
k8sVer.GitVersion = k8sVer.GitVersion + "-rancher1"
|
||||||
}
|
}
|
||||||
|
if isAKS {
|
||||||
|
k8sVer.GitVersion = k8sVer.GitVersion + "-aks1" // Mark it as AKS in the version
|
||||||
|
}
|
||||||
return k8sVer, nil
|
return k8sVer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,6 +494,26 @@ func getPlatformInfoFromVersion(s string) Platform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsAKS(ctx context.Context, k8sClient kubernetes.Interface) (bool, error) {
|
||||||
|
// Query the nodes for any annotations that indicate AKS (Azure Kubernetes Service)
|
||||||
|
nodes, err := k8sClient.CoreV1().Nodes().List(ctx, metav1.ListOptions{Limit: 1})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the cluster contains nodes with specific AKS annotations, it’s likely AKS
|
||||||
|
if len(nodes.Items) == 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
annotations := nodes.Items[0].Annotations
|
||||||
|
if _, exists := annotations["azure-identity-binding"]; exists { // "azure-identity-binding" is one possible AKS-specific annotation
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getPlatformBenchmarkVersion(platform Platform) string {
|
func getPlatformBenchmarkVersion(platform Platform) string {
|
||||||
glog.V(3).Infof("getPlatformBenchmarkVersion platform: %s", platform)
|
glog.V(3).Infof("getPlatformBenchmarkVersion platform: %s", platform)
|
||||||
switch platform.Name {
|
switch platform.Name {
|
||||||
|
@ -627,6 +627,11 @@ func Test_getPlatformNameFromKubectlOutput(t *testing.T) {
|
|||||||
args: args{s: "v1.27.6+rke2r1"},
|
args: args{s: "v1.27.6+rke2r1"},
|
||||||
want: Platform{Name: "rke2r", Version: "1.27"},
|
want: Platform{Name: "rke2r", Version: "1.27"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "aks",
|
||||||
|
args: args{s: "v1.27.6+aks1"},
|
||||||
|
want: Platform{Name: "aks", Version: "1.27"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
@ -729,6 +734,13 @@ func Test_getPlatformBenchmarkVersion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
want: "rke2-cis-1.7",
|
want: "rke2-cis-1.7",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "aks",
|
||||||
|
args: args{
|
||||||
|
platform: Platform{Name: "aks", Version: "1.27"},
|
||||||
|
},
|
||||||
|
want: "aks-1.7",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user