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(apiserver): new 9 Kubernetes ApiServer checks #3288
Changes from all commits
5a40b07
cc76a42
3632aaf
8294284
86e12bf
2b5d78e
7bb9c5e
f743551
718ca84
e4f6e5e
df31032
f67ed53
08aa1d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"Provider": "kubernetes", | ||
"CheckID": "apiserver_always_pull_images_plugin", | ||
"CheckTitle": "Ensure that the admission control plugin AlwaysPullImages is set", | ||
"CheckType": [ | ||
"Security", | ||
"Configuration" | ||
], | ||
"ServiceName": "apiserver", | ||
"SubServiceName": "Admission Control", | ||
"ResourceIdTemplate": "", | ||
"Severity": "medium", | ||
"ResourceType": "KubernetesAPIServer", | ||
"Description": "This check verifies that the AlwaysPullImages admission control plugin is enabled in the Kubernetes API server. This plugin ensures that every new pod always pulls the required images, enforcing image access control and preventing the use of possibly outdated or altered images.", | ||
"Risk": "Without AlwaysPullImages, once an image is pulled to a node, any pod can use it without any authorization check, potentially leading to security risks.", | ||
"RelatedUrl": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages", | ||
"Remediation": { | ||
"Code": { | ||
"CLI": "Edit the kube-apiserver configuration to include AlwaysPullImages in the --enable-admission-plugins argument. Example: --enable-admission-plugins=...,AlwaysPullImages,...", | ||
"NativeIaC": "", | ||
"Other": "", | ||
"Terraform": "" | ||
}, | ||
"Recommendation": { | ||
"Text": "Configure the API server to use the AlwaysPullImages admission control plugin to ensure image security and integrity.", | ||
"Url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers" | ||
} | ||
}, | ||
"Categories": [ | ||
"Image Security", | ||
"Cluster Security" | ||
], | ||
"DependsOn": [], | ||
"RelatedTo": [], | ||
"Notes": "Enabling AlwaysPullImages can increase network and registry load and decrease container startup speed. It may not be suitable for all environments." | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from prowler.lib.check.models import Check, Check_Report_Kubernetes | ||
from prowler.providers.kubernetes.services.apiserver.apiserver_client import ( | ||
apiserver_client, | ||
) | ||
|
||
|
||
class apiserver_always_pull_images_plugin(Check): | ||
def execute(self) -> Check_Report_Kubernetes: | ||
findings = [] | ||
for pod in apiserver_client.apiserver_pods: | ||
report = Check_Report_Kubernetes(self.metadata()) | ||
report.namespace = pod.namespace | ||
report.resource_name = pod.name | ||
report.resource_id = pod.uid | ||
report.status = "PASS" | ||
report.status_extended = ( | ||
f"AlwaysPullImages admission control plugin is set in pod {pod.name}." | ||
) | ||
plugin_set = False | ||
for container in pod.containers.values(): | ||
plugin_set = False | ||
for command in container.command: | ||
if command.startswith("--enable-admission-plugins"): | ||
if "AlwaysPullImages" in command: | ||
plugin_set = True | ||
if not plugin_set: | ||
break | ||
if not plugin_set: | ||
report.status = "FAIL" | ||
report.status_extended = f"AlwaysPullImages admission control plugin is not set in pod {pod.name}." | ||
findings.append(report) | ||
return findings |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"Provider": "kubernetes", | ||
"CheckID": "apiserver_audit_log_maxage_set", | ||
"CheckTitle": "Ensure that the --audit-log-maxage argument is set to 30 or as appropriate", | ||
"CheckType": [ | ||
"Security", | ||
"Configuration" | ||
], | ||
"ServiceName": "apiserver", | ||
"SubServiceName": "Auditing", | ||
"ResourceIdTemplate": "", | ||
"Severity": "medium", | ||
"ResourceType": "KubernetesAPIServer", | ||
"Description": "This check ensures that the Kubernetes API server is configured with an appropriate audit log retention period. Setting --audit-log-maxage to 30 or as per business requirements helps in maintaining logs for sufficient time to investigate past events.", | ||
"Risk": "Without an adequate log retention period, there may be insufficient audit history to investigate and analyze past events or security incidents.", | ||
"RelatedUrl": "https://kubernetes.io/docs/concepts/cluster-administration/audit/", | ||
"Remediation": { | ||
"Code": { | ||
"CLI": "Edit the kube-apiserver configuration to set the --audit-log-maxage argument to 30 or an appropriate number of days. Example: --audit-log-maxage=30", | ||
"NativeIaC": "", | ||
"Other": "", | ||
"Terraform": "" | ||
}, | ||
"Recommendation": { | ||
"Text": "Configure the API server audit log retention period to retain logs for at least 30 days or as per your organization's requirements.", | ||
"Url": "https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/" | ||
} | ||
}, | ||
"Categories": [ | ||
"Logging", | ||
"Compliance" | ||
], | ||
"DependsOn": [], | ||
"RelatedTo": [], | ||
"Notes": "Ensure the audit log retention period is set appropriately to balance between storage constraints and the need for historical data." | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
from prowler.lib.check.models import Check, Check_Report_Kubernetes | ||
from prowler.providers.kubernetes.services.apiserver.apiserver_client import ( | ||
apiserver_client, | ||
) | ||
|
||
|
||
class apiserver_audit_log_maxage_set(Check): | ||
def execute(self) -> Check_Report_Kubernetes: | ||
findings = [] | ||
for pod in apiserver_client.apiserver_pods: | ||
report = Check_Report_Kubernetes(self.metadata()) | ||
report.namespace = pod.namespace | ||
report.resource_name = pod.name | ||
report.resource_id = pod.uid | ||
report.status = "PASS" | ||
report.status_extended = f"Audit log max age is set appropriately in the API server in pod {pod.name}." | ||
audit_log_maxage_set = False | ||
for container in pod.containers.values(): | ||
audit_log_maxage_set = False | ||
# Check if "--audit-log-maxage" is set to 30 or as appropriate | ||
for command in container.command: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we need to check if all the containers in the pod has the flag enabled. |
||
if command.startswith("--audit-log-maxage"): | ||
if int( | ||
command.split("=")[1] | ||
) == apiserver_client.audit_config.get("audit_log_maxage", 30): | ||
audit_log_maxage_set = True | ||
break | ||
if not audit_log_maxage_set: | ||
break | ||
|
||
if not audit_log_maxage_set: | ||
report.status = "FAIL" | ||
report.status_extended = f"Audit log max age is not set to 30 or as appropriate in pod {pod.name}." | ||
|
||
findings.append(report) | ||
return findings |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"Provider": "kubernetes", | ||
"CheckID": "apiserver_audit_log_maxbackup_set", | ||
"CheckTitle": "Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate", | ||
"CheckType": [ | ||
"Security", | ||
"Configuration" | ||
], | ||
"ServiceName": "apiserver", | ||
"SubServiceName": "Auditing", | ||
"ResourceIdTemplate": "", | ||
"Severity": "medium", | ||
"ResourceType": "KubernetesAPIServer", | ||
"Description": "This check ensures that the Kubernetes API server is configured with an appropriate number of audit log backups. Setting --audit-log-maxbackup to 10 or as per business requirements helps maintain a sufficient log backup for investigations or analysis.", | ||
"Risk": "Without an adequate number of audit log backups, there may be insufficient log history to investigate past events or security incidents.", | ||
"RelatedUrl": "https://kubernetes.io/docs/concepts/cluster-administration/audit/", | ||
"Remediation": { | ||
"Code": { | ||
"CLI": "Edit the kube-apiserver configuration to set the --audit-log-maxbackup argument to 10 or an appropriate number. Example: --audit-log-maxbackup=10", | ||
"NativeIaC": "", | ||
"Other": "", | ||
"Terraform": "" | ||
}, | ||
"Recommendation": { | ||
"Text": "Configure the API server audit log backup retention to 10 or as per your organization's requirements.", | ||
"Url": "https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/" | ||
} | ||
}, | ||
"Categories": [ | ||
"Logging", | ||
"Compliance" | ||
], | ||
"DependsOn": [], | ||
"RelatedTo": [], | ||
"Notes": "Ensure the audit log backup retention period is set appropriately to balance between storage constraints and the need for historical data." | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from prowler.lib.check.models import Check, Check_Report_Kubernetes | ||
from prowler.providers.kubernetes.services.apiserver.apiserver_client import ( | ||
apiserver_client, | ||
) | ||
|
||
|
||
class apiserver_audit_log_maxbackup_set(Check): | ||
def execute(self) -> Check_Report_Kubernetes: | ||
findings = [] | ||
for pod in apiserver_client.apiserver_pods: | ||
report = Check_Report_Kubernetes(self.metadata()) | ||
report.namespace = pod.namespace | ||
report.resource_name = pod.name | ||
report.resource_id = pod.uid | ||
report.status = "PASS" | ||
report.status_extended = f"Audit log max backup is set appropriately in the API server in pod {pod.name}." | ||
audit_log_maxbackup_set = False | ||
for container in pod.containers.values(): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we need to check if all the containers in the pod has the flag enabled. |
||
audit_log_maxbackup_set = False | ||
# Check if "--audit-log-maxbackup" is set to 10 or as appropriate | ||
for command in container.command: | ||
if command.startswith("--audit-log-maxbackup"): | ||
if int( | ||
command.split("=")[1] | ||
) == apiserver_client.audit_config.get( | ||
"audit_log_maxbackup", 10 | ||
): | ||
audit_log_maxbackup_set = True | ||
break | ||
if not audit_log_maxbackup_set: | ||
break | ||
|
||
if not audit_log_maxbackup_set: | ||
report.status = "FAIL" | ||
report.status_extended = f"Audit log max backup is not set to 10 or as appropriate in pod {pod.name}." | ||
|
||
findings.append(report) | ||
return findings |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"Provider": "kubernetes", | ||
"CheckID": "apiserver_audit_log_maxsize_set", | ||
"CheckTitle": "Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate", | ||
"CheckType": [ | ||
"Security", | ||
"Configuration" | ||
], | ||
"ServiceName": "apiserver", | ||
"SubServiceName": "Auditing", | ||
"ResourceIdTemplate": "", | ||
"Severity": "medium", | ||
"ResourceType": "KubernetesAPIServer", | ||
"Description": "This check ensures that the Kubernetes API server is configured with an appropriate audit log file size limit. Setting --audit-log-maxsize to 100 MB or as per business requirements helps manage the size of log files and prevents them from growing excessively large.", | ||
"Risk": "Without an appropriate audit log file size limit, log files can grow excessively large, potentially leading to storage issues and difficulty in log analysis.", | ||
"RelatedUrl": "https://kubernetes.io/docs/concepts/cluster-administration/audit/", | ||
"Remediation": { | ||
"Code": { | ||
"CLI": "Edit the kube-apiserver configuration to set the --audit-log-maxsize argument to 100 MB or an appropriate size. Example: --audit-log-maxsize=100", | ||
"NativeIaC": "", | ||
"Other": "", | ||
"Terraform": "" | ||
}, | ||
"Recommendation": { | ||
"Text": "Configure the API server audit log file size limit to 100 MB or as per your organization's requirements.", | ||
"Url": "https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/" | ||
} | ||
}, | ||
"Categories": [ | ||
"Logging", | ||
"Compliance" | ||
], | ||
"DependsOn": [], | ||
"RelatedTo": [], | ||
"Notes": "Adjust the audit log file size limit based on your organization's storage capabilities and logging requirements." | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from prowler.lib.check.models import Check, Check_Report_Kubernetes | ||
from prowler.providers.kubernetes.services.apiserver.apiserver_client import ( | ||
apiserver_client, | ||
) | ||
|
||
|
||
class apiserver_audit_log_maxsize_set(Check): | ||
def execute(self) -> Check_Report_Kubernetes: | ||
findings = [] | ||
for pod in apiserver_client.apiserver_pods: | ||
report = Check_Report_Kubernetes(self.metadata()) | ||
report.namespace = pod.namespace | ||
report.resource_name = pod.name | ||
report.resource_id = pod.uid | ||
report.status = "PASS" | ||
report.status_extended = f"Audit log max size is set appropriately in the API server in pod {pod.name}." | ||
audit_log_maxsize_set = False | ||
for container in pod.containers.values(): | ||
audit_log_maxsize_set = False | ||
# Check if "--audit-log-maxsize" is set to 100 MB or as appropriate | ||
for command in container.command: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we need to check if all the containers in the pod has the flag enabled. |
||
if command.startswith("--audit-log-maxsize"): | ||
if int( | ||
command.split("=")[1] | ||
) == apiserver_client.audit_config.get( | ||
"audit_log_maxsize", 100 | ||
): | ||
audit_log_maxsize_set = True | ||
break | ||
if not audit_log_maxsize_set: | ||
break | ||
|
||
if not audit_log_maxsize_set: | ||
report.status = "FAIL" | ||
report.status_extended = f"Audit log max size is not set to 100 MB or as appropriate in pod {pod.name}." | ||
|
||
findings.append(report) | ||
return findings |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"Provider": "kubernetes", | ||
"CheckID": "apiserver_audit_log_path_set", | ||
"CheckTitle": "Ensure that the --audit-log-path argument is set", | ||
"CheckType": [ | ||
"Security", | ||
"Configuration" | ||
], | ||
"ServiceName": "apiserver", | ||
"SubServiceName": "Auditing", | ||
"ResourceIdTemplate": "", | ||
"Severity": "high", | ||
"ResourceType": "KubernetesAPIServer", | ||
"Description": "This check verifies that the Kubernetes API server is configured with an audit log path. Enabling audit logs helps in maintaining a chronological record of all activities and operations which can be critical for security analysis and troubleshooting.", | ||
"Risk": "Without audit logs, it becomes difficult to track changes and activities within the cluster, potentially obscuring the detection of malicious activities or operational issues.", | ||
"RelatedUrl": "https://kubernetes.io/docs/concepts/cluster-administration/audit/", | ||
"Remediation": { | ||
"Code": { | ||
"CLI": "Edit the kube-apiserver configuration to set the --audit-log-path argument to a valid log path. Example: --audit-log-path=/var/log/apiserver/audit.log", | ||
"NativeIaC": "", | ||
"Other": "", | ||
"Terraform": "" | ||
}, | ||
"Recommendation": { | ||
"Text": "Enable audit logging in the API server by specifying a valid path for --audit-log-path to ensure comprehensive activity logging within the cluster.", | ||
"Url": "https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/" | ||
} | ||
}, | ||
"Categories": [ | ||
"Logging", | ||
"Compliance" | ||
], | ||
"DependsOn": [], | ||
"RelatedTo": [], | ||
"Notes": "Audit logs are not enabled by default in Kubernetes. Configuring them is essential for security monitoring and forensic analysis." | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from prowler.lib.check.models import Check, Check_Report_Kubernetes | ||
from prowler.providers.kubernetes.services.apiserver.apiserver_client import ( | ||
apiserver_client, | ||
) | ||
|
||
|
||
class apiserver_audit_log_path_set(Check): | ||
def execute(self) -> Check_Report_Kubernetes: | ||
findings = [] | ||
for pod in apiserver_client.apiserver_pods: | ||
report = Check_Report_Kubernetes(self.metadata()) | ||
report.namespace = pod.namespace | ||
report.resource_name = pod.name | ||
report.resource_id = pod.uid | ||
report.status = "PASS" | ||
report.status_extended = ( | ||
f"Audit log path is set in the API server in pod {pod.name}." | ||
) | ||
audit_log_path_set = False | ||
for container in pod.containers.values(): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we need to check if all the containers in the pod has the flag enabled. |
||
audit_log_path_set = False | ||
# Check if "--audit-log-path" is set | ||
if "--audit-log-path" in str(container.command): | ||
audit_log_path_set = True | ||
break | ||
if not audit_log_path_set: | ||
break | ||
|
||
if not audit_log_path_set: | ||
report.status = "FAIL" | ||
report.status_extended = f"Audit log path is not set in pod {pod.name}." | ||
|
||
findings.append(report) | ||
return findings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we need to check if all the containers in the pod has the flag enabled.