1
0
mirror of https://github.com/aquasecurity/kube-bench.git synced 2025-05-29 12:18:55 +00:00

add alternative method to identify AKS specific cluster

This commit is contained in:
LaibaBareera 2025-05-27 15:56:47 +05:00
parent 754c462d54
commit b446c25c3c
3 changed files with 131 additions and 6 deletions

View File

@ -10,7 +10,16 @@ groups:
checks:
- id: 4.1.1
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: |
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.
@ -21,7 +30,34 @@ groups:
- id: 4.1.2
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: |
Where possible, remove get, list and watch access to secret objects in the cluster.
scored: false
@ -45,14 +81,44 @@ groups:
- id: 4.1.4
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: |
Where possible, remove create access to pod objects in the cluster.
scored: false
- id: 4.1.5
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: |
Create explicit service accounts wherever a Kubernetes workload requires specific access
to the Kubernetes API server.
@ -62,7 +128,16 @@ groups:
- id: 4.1.6
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: |
Modify the definition of pods and service accounts which do not need to mount service
account tokens to disable it.
@ -258,7 +333,16 @@ groups:
- id: 4.6.3
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: |
Ensure that namespaces are created to allow for appropriate segregation of Kubernetes
resources and that all new resources are created in a specific namespace.

View File

@ -300,6 +300,7 @@ func getKubeVersion() (*KubeVersion, error) {
glog.V(3).Infof("Error fetching cluster config: %s", err)
}
isRKE := false
isAKS := false // Variable to track AKS detection
if err == nil && kubeConfig != nil {
k8sClient, err := kubernetes.NewForConfig(kubeConfig)
if err != nil {
@ -311,7 +312,12 @@ func getKubeVersion() (*KubeVersion, error) {
if err != nil {
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 {
@ -319,6 +325,9 @@ func getKubeVersion() (*KubeVersion, error) {
if isRKE {
k8sVer.GitVersion = k8sVer.GitVersion + "-rancher1"
}
if isAKS {
k8sVer.GitVersion = k8sVer.GitVersion + "-aks1" // Mark it as AKS in the version
}
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, its 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 {
glog.V(3).Infof("getPlatformBenchmarkVersion platform: %s", platform)
switch platform.Name {

View File

@ -627,6 +627,11 @@ func Test_getPlatformNameFromKubectlOutput(t *testing.T) {
args: args{s: "v1.27.6+rke2r1"},
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 {
t.Run(tt.name, func(t *testing.T) {
@ -729,6 +734,13 @@ func Test_getPlatformBenchmarkVersion(t *testing.T) {
},
want: "rke2-cis-1.7",
},
{
name: "aks",
args: args{
platform: Platform{Name: "aks", Version: "1.27"},
},
want: "aks-1.7",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {