Skip to content

Commit

Permalink
Add rules for encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
dorukozturk committed Dec 10, 2022
1 parent 824cd50 commit 07e1342
Show file tree
Hide file tree
Showing 68 changed files with 30,456 additions and 24 deletions.
5 changes: 4 additions & 1 deletion config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ rules:
- check_vpc_flow_logs
- check_awspca_exists
- check_default_deny_policy_exists
encryption_secrets:
- use_encryption_with_ebs
- use_encryption_with_efs
- use_efs_access_points
security:
iam:
- disable_anonymous_access_for_roles
Expand All @@ -37,7 +41,6 @@ rules:
- check_read_only_root_file_system
network_security:
- use_encryption_with_aws_load_balancers
# encryption_secrets:
# infrastructure_security:
# cluster_autoscaling:
# karpenter:
Expand Down
54 changes: 54 additions & 0 deletions hardeneks/cluster_wide/encryption_secrets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from ..resources import Resources
from ..report import print_storage_class_table, print_persistent_volume_table


def use_encryption_with_ebs(resources: Resources):
offenders = []

for storage_class in resources.storage_classes:
if storage_class.provisioner == "ebs.csi.aws.com":
encrypted = storage_class.parameters.get("encrypted")
if not encrypted:
offenders.append(storage_class)
elif encrypted == "false":
offenders.append(storage_class)

if offenders:
print_storage_class_table(
offenders, "EBS Storage Classes should have encryption parameter"
)
return offenders


def use_encryption_with_efs(resources: Resources):
offenders = []

for persistent_volume in resources.persistent_volumes:
if persistent_volume.spec.csi.driver == "efs.csi.aws.com":
mount_options = persistent_volume.spec.mount_options
if not mount_options:
offenders.append(persistent_volume)
else:
if "tls" not in mount_options:
offenders.append(persistent_volume)

if offenders:
print_persistent_volume_table(
offenders, "EFS Persistent volumes should have tls mount option"
)
return offenders


def use_efs_access_points(resources: Resources):
offenders = []

for persistent_volume in resources.persistent_volumes:
if persistent_volume.spec.csi.driver == "efs.csi.aws.com":
if "::" not in persistent_volume.spec.csi.volume_handle:
offenders.append(persistent_volume)

if offenders:
print_persistent_volume_table(
offenders, "EFS Persistent volumes should leverage access points"
)
return offenders
12 changes: 6 additions & 6 deletions hardeneks/cluster_wide/iam.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
from kubernetes import client
from rich.console import Console

from ..resources import NamespacedResources
from ..resources import Resources
from ..report import print_role_table, print_instance_table

console = Console()


def restrict_wildcard_for_cluster_roles(resources: NamespacedResources):
def restrict_wildcard_for_cluster_roles(resources: Resources):
offenders = []

for role in resources.cluster_roles:
Expand All @@ -27,7 +27,7 @@ def restrict_wildcard_for_cluster_roles(resources: NamespacedResources):
return offenders


def check_endpoint_public_access(resources: NamespacedResources):
def check_endpoint_public_access(resources: Resources):
client = boto3.client("eks", region_name=resources.region)
cluster_metadata = client.describe_cluster(name=resources.cluster)
endpoint_access = cluster_metadata["cluster"]["resourcesVpcConfig"][
Expand All @@ -41,7 +41,7 @@ def check_endpoint_public_access(resources: NamespacedResources):
return True


def check_aws_node_daemonset_service_account(resources: NamespacedResources):
def check_aws_node_daemonset_service_account(resources: Resources):
daemonset = client.AppsV1Api().read_namespaced_daemon_set(
name="aws-node", namespace="kube-system"
)
Expand All @@ -54,7 +54,7 @@ def check_aws_node_daemonset_service_account(resources: NamespacedResources):
return True


def check_access_to_instance_profile(resources: NamespacedResources):
def check_access_to_instance_profile(resources: Resources):
client = boto3.client("ec2", region_name=resources.region)
offenders = []

Expand Down Expand Up @@ -86,7 +86,7 @@ def check_access_to_instance_profile(resources: NamespacedResources):
return offenders


def disable_anonymous_access_for_cluster_roles(resources: NamespacedResources):
def disable_anonymous_access_for_cluster_roles(resources: Resources):
offenders = []

for cluster_role_binding in resources.cluster_role_bindings:
Expand Down
35 changes: 34 additions & 1 deletion hardeneks/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ def print_workload_table(workloads, message, kind):
)
console.print(table)
console.print()
console.print("*" * 100)


def print_namespace_table(namespaces, message):
Expand Down Expand Up @@ -118,3 +117,37 @@ def print_service_table(services, message):
)
console.print(table)
console.print()


def print_storage_class_table(storage_classes, message):
table = Table()

table.add_column("StorageClass", style="cyan")
table.add_column("Encyrpted", style="magenta")

for storage_class in storage_classes:
table.add_row(storage_class.metadata.name, "false")

console.print(
message,
style="red",
)
console.print(table)
console.print()


def print_persistent_volume_table(persistent_volumes, message):
table = Table()

table.add_column("PersistentVolume", style="cyan")
table.add_column("Encrypted", style="magenta")

for persistent_volume in persistent_volumes:
table.add_row(persistent_volume.metadata.name, "false")

console.print(
message,
style="red",
)
console.print(table)
console.print()
4 changes: 4 additions & 0 deletions hardeneks/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def set_resources(self):
.list_network_policy_for_all_namespaces()
.items
)
self.storage_classes = client.StorageV1Api().list_storage_class().items
self.persistent_volumes = (
client.CoreV1Api().list_persistent_volume().items
)


class NamespacedResources:
Expand Down
4 changes: 3 additions & 1 deletion scripts/create_k8s_test_data.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ kubectl create namespace $NAMESPACE
kubectl apply -f "$TEST_DATA_DIRECTORY/good.yaml"
kubectl apply -f "$TEST_DATA_DIRECTORY/bad.yaml"
kubectl get namespace -o json > "$TEST_DATA_DIRECTORY/cluster/namespaces_api_response.json"
kubectl get resourcequota -n $NAMESPACE -o json > "$TEST_DATA_DIRECTORY/cluster/resource_quotas_api_response.json"
kubectl get resourcequota -A -o json > "$TEST_DATA_DIRECTORY/cluster/resource_quotas_api_response.json"
kubectl get pv -o json > "$TEST_DATA_DIRECTORY/cluster/persistent_volumes_api_response.json"
kubectl get pod -o json -n $NAMESPACE > "$TEST_DATA_DIRECTORY/cluster/pods_api_response.json"
kubectl get service -o json -n $NAMESPACE > "$TEST_DATA_DIRECTORY/cluster/services_api_response.json"
kubectl get role -o json -n $NAMESPACE > "$TEST_DATA_DIRECTORY/cluster/roles_api_response.json"
Expand All @@ -19,6 +20,7 @@ kubectl get statefulset -o json -n "$NAMESPACE" > "$TEST_DATA_DIRECTORY/cluster/
kubectl get deployment -o json -n "$NAMESPACE" > "$TEST_DATA_DIRECTORY/cluster/deployments_api_response.json"
kubectl get networkpolicy -o json -n "$NAMESPACE" > "$TEST_DATA_DIRECTORY/cluster/network_policies_api_response.json"
kubectl get hpa -o json -n "$NAMESPACE" > "$TEST_DATA_DIRECTORY/cluster/horizontal_pod_autoscaler_api_response.json"
kubectl get storageclass -o json > "$TEST_DATA_DIRECTORY/cluster/storage_classes_api_response.json"

kubectl delete namespace $NAMESPACE --force
kubectl get namespace $NAMESPACE -o json | jq 'del(.spec.finalizers[0])' | kubectl replace --raw "/api/v1/namespaces/$NAMESPACE/finalize" -f -
10 changes: 10 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ def resources(request):
os.path.join(data_directory, "network_policies_api_response.json"),
"V1NetworkPolicyList",
).items
resources.storage_classes = get_response(
client.StorageV1Api,
os.path.join(data_directory, "storage_classes_api_response.json"),
"V1StorageClassList",
).items
resources.persistent_volumes = get_response(
client.CoreV1Api,
os.path.join(data_directory, "persistent_volumes_api_response.json"),
"V1PersistentVolumeList",
).items
return resources


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
{
"apiVersion": "v1",
"items": [
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"bad\"}}\n"
},
"creationTimestamp": "2022-11-16T15:35:06Z",
"labels": {
"kubernetes.io/metadata.name": "bad"
},
"name": "bad",
"resourceVersion": "8149233",
"uid": "fe5aa925-b0a0-4e55-b747-8ffe602aa6ac"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
},
{
"apiVersion": "v1",
"kind": "Namespace",
Expand All @@ -22,6 +46,30 @@
"phase": "Active"
}
},
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"good\"}}\n"
},
"creationTimestamp": "2022-11-16T15:35:06Z",
"labels": {
"kubernetes.io/metadata.name": "good"
},
"name": "good",
"resourceVersion": "8149223",
"uid": "8f2abb3c-b0a7-4ab4-9389-9a2e78db40dd"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
},
{
"apiVersion": "v1",
"kind": "Namespace",
Expand Down Expand Up @@ -89,13 +137,13 @@
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"creationTimestamp": "2022-11-14T16:13:17Z",
"creationTimestamp": "2022-11-16T15:35:25Z",
"labels": {
"kubernetes.io/metadata.name": "test-namespace"
},
"name": "test-namespace",
"resourceVersion": "7672335",
"uid": "6b564ac3-d790-4568-8968-af76938b4b49"
"resourceVersion": "8149290",
"uid": "6450d7c1-ebf7-4e14-bb9c-d7667902666d"
},
"spec": {
"finalizers": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"apiVersion": "v1",
"items": [
{
"apiVersion": "v1",
"kind": "PersistentVolume",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"PersistentVolume\",\"metadata\":{\"annotations\":{},\"name\":\"bad\"},\"spec\":{\"accessModes\":[\"ReadWriteOnce\"],\"capacity\":{\"storage\":\"5Gi\"},\"csi\":{\"driver\":\"efs.csi.aws.com\",\"volumeHandle\":\"some_id\"},\"persistentVolumeReclaimPolicy\":\"Retain\",\"storageClassName\":\"efs-sc\",\"volumeMode\":\"Filesystem\"}}\n"
},
"creationTimestamp": "2022-11-16T17:32:05Z",
"finalizers": [
"kubernetes.io/pv-protection"
],
"name": "bad",
"resourceVersion": "8168926",
"uid": "01035bf3-4216-4ac5-89ba-6a476d8493d6"
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"capacity": {
"storage": "5Gi"
},
"csi": {
"driver": "efs.csi.aws.com",
"volumeHandle": "some_id"
},
"persistentVolumeReclaimPolicy": "Retain",
"storageClassName": "efs-sc",
"volumeMode": "Filesystem"
},
"status": {
"phase": "Available"
}
},
{
"apiVersion": "v1",
"kind": "PersistentVolume",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"PersistentVolume\",\"metadata\":{\"annotations\":{},\"name\":\"good\"},\"spec\":{\"accessModes\":[\"ReadWriteOnce\"],\"capacity\":{\"storage\":\"5Gi\"},\"csi\":{\"driver\":\"efs.csi.aws.com\",\"volumeHandle\":\"some_id\"},\"mountOptions\":[\"tls\"],\"persistentVolumeReclaimPolicy\":\"Retain\",\"storageClassName\":\"efs-sc\",\"volumeMode\":\"Filesystem\"}}\n"
},
"creationTimestamp": "2022-11-16T17:32:05Z",
"finalizers": [
"kubernetes.io/pv-protection"
],
"name": "good",
"resourceVersion": "8168922",
"uid": "0e61bf80-4a32-470b-8a29-23df698bab78"
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"capacity": {
"storage": "5Gi"
},
"csi": {
"driver": "efs.csi.aws.com",
"volumeHandle": "some_id"
},
"mountOptions": [
"tls"
],
"persistentVolumeReclaimPolicy": "Retain",
"storageClassName": "efs-sc",
"volumeMode": "Filesystem"
},
"status": {
"phase": "Available"
}
}
],
"kind": "List",
"metadata": {
"resourceVersion": ""
}
}
Loading

0 comments on commit 07e1342

Please sign in to comment.