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: Add Support to find Exposed ports in AWS EKS #47

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ LABEL name="k8tls" \
description="Tool to scan/verify the TLS connection parameters and the certificates usage on the target server ports. The tool does not inject a proxy/sidecar to do this scanning."

RUN microdnf -y update && \
microdnf -y install --nodocs --setopt=install_weak_deps=0 --setopt=keepcache=0 shadow-utils openssl ca-certificates nmap jq tar gzip util-linux && \
microdnf clean all
microdnf -y install --nodocs --setopt=install_weak_deps=0 --setopt=keepcache=0 shadow-utils openssl ca-certificates nmap jq tar unzip gzip util-linux && \
microdnf clean all && \
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
unzip awscliv2.zip && \
./aws/install

# Determine architecture and download the appropriate binaries
RUN ARCH=$(uname -m) && \
Expand Down
50 changes: 36 additions & 14 deletions k8s/job.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ kind: ClusterRole
metadata:
name: k8tls-cr
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list"]
- apiGroups: [ "" ]
resources: [ "services" ]
verbs: [ "get", "list" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
Expand All @@ -27,9 +27,9 @@ roleRef:
kind: ClusterRole
name: k8tls-cr
subjects:
- kind: ServiceAccount
name: k8tls-serviceact
namespace: k8tls
- kind: ServiceAccount
name: k8tls-serviceact
namespace: k8tls
---
apiVersion: v1
kind: ConfigMap
Expand Down Expand Up @@ -131,6 +131,16 @@ data:
]
}
---
apiVersion: v1
kind: Secret
metadata:
name: aws-credentials
namespace: k8tls
data:
credentials: |
<access-key-in-base64-encoded-format>
<secret-key-in-base64-encoded-format>
---
apiVersion: batch/v1
kind: Job
metadata:
Expand All @@ -141,17 +151,29 @@ spec:
spec:
serviceAccountName: k8tls-serviceact
containers:
- name: k8tls
image: kubearmor/k8tls:latest
command: ["./k8s_tlsscan"]
volumeMounts:
- mountPath: /home/k8tls/config/
name: config
readOnly: true
- name: k8tls
image: kubearmor/k8tls:latest
imagePullPolicy: Always
command:
- "./main_k8s_tlsscan"
securityContext:
runAsUser: 0
nyrahul marked this conversation as resolved.
Show resolved Hide resolved
volumeMounts:
- mountPath: /home/k8tls/config/
name: config
readOnly: true

- mountPath: /home/k8tls/.aws/credentials
subPath: credentials
name: aws-credentials
readOnly: true
restartPolicy: Never
volumes:
- name: config
configMap:
name: k8tls-cm
- name: aws-credentials
secret:
secretName: aws-credentials
defaultMode: 0400
backoffLimit: 4
---
51 changes: 50 additions & 1 deletion src/findings_tls
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash

set -o pipefail

opensslscan()
{
tmp=/tmp/tls.out
Expand All @@ -24,7 +26,7 @@ tls_csvreport()
{
[[ "$csvout" == "" ]] && return
cat << EOF >> $csvout
"$SVC_Name","$SVC_Address","$TLS_Status","$TLS_Protocol_version","$TLS_Ciphersuite","$TLS_Hash_used","$TLS_Signature_type","$TLS_Verification","$FIPS_140_3_Compliant"
"$SVC_Name","$SVC_Address","$SVC_Type","$TLS_Status","$TLS_Protocol_version","$TLS_Ciphersuite","$TLS_Hash_used","$TLS_Signature_type","$TLS_Verification","$FIPS_140_3_Compliant"
EOF
}

Expand Down Expand Up @@ -192,6 +194,53 @@ fips_compliance_check()
appendSpec
}

k8tls_tls_03exposedPorts() {
if [ "$SVC_Type" == "NodePort" ]; then
status="PASS"
clusterName=$(curl -s http://169.254.169.254/latest/user-data | grep -E '^/etc/eks/bootstrap\.sh\s+([^\s]+)' | cut -d' ' -f2 2> /dev/null)
nyrahul marked this conversation as resolved.
Show resolved Hide resolved
securityGroups=$(curl -s http://169.254.169.254/latest/meta-data/security-groups 2> /dev/null)
MAC=$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/ | head -n 1 2> /dev/null)
securityGroupId=$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC}/security-group-ids 2> /dev/null)
vpcId=$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC}/vpc-id 2> /dev/null)
subNet=$(curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/${MAC}/subnet-id 2> /dev/null)

if [[ -z "$clusterName" || -z "$securityGroups" || -z "$MAC" || -z "$securityGroupId" || -z "$vpcId" || -z "$subNet" ]]; then
echo "One or more fields are empty. Skipping exposedPorts check..."
return
# exit 1
fi

# Use parameter expansion to split the SVC_Name
namespace="${SVC_Name%%/*}"
name="${SVC_Name##*/}"

nodePortValue=$(kubectl -n "${namespace}" get svc "${name}" -o=custom-columns='NODEPORT:.spec.ports[*].nodePort' | tail -1)
isExposedPort=$(aws ec2 describe-security-group-rules | jq ".SecurityGroupRules[] | select(.IsEgress == false and .ToPort == $nodePortValue)")
if [[ -z "${isExposedPort}" ]]; then
return
fi

cat << EOF >> $TMPJSONSEC
{
"plugin": "exposed-ports",
"title": "Publicly exposed ports",
"description": "Publicly exposed ports increase security risks. Disable unnecessary ports to protect systems from unauthorized access."
"severity": "critical",
"remediationEstEffort": "medium",
"solution": "Disable publicly exposed ports",
"status": "$status",
"clusterName": "$clusterName",
"securityGroups": "$securityGroups",
"securityGroupId": "$securityGroupId",
"vpcId": "$vpcId",
"subNet": "$subNet",
"serviceNamespaceAndName": "$SVC_Name",
"exposedPort": "$nodePortValue"
}
EOF
fi
}

appendSpec()
{
cat << EOF >> $TMPJSONSEC
Expand Down
13 changes: 7 additions & 6 deletions src/k8s_tlsscan
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ while read -r line; do
IFS=' ' list=($(echo $line))
ns=${list[0]}
svc=${list[1]}
clusterip=${list[2]}
svcType=${list[2]}
clusterip=${list[3]}
! [[ $clusterip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] && continue
IFS=',' pnames=($(echo "${list[3]}"))
IFS=',' ports=($(echo "${list[4]}"))
IFS=',' prots=($(echo "${list[5]}"))
IFS=',' pnames=($(echo "${list[4]}"))
IFS=',' ports=($(echo "${list[5]}"))
IFS=',' prots=($(echo "${list[6]}"))
for ((i=0;i<5;i++)); do
pname="${pnames[$i]}"
tport="${ports[$i]}"
Expand All @@ -37,9 +38,9 @@ while read -r line; do
[[ "$prot" != "TCP" ]] && echo "unsupported protocol $prot" && continue
[[ "$pname" == "<none>" ]] && pname=""
[[ "$pname" != "" ]] && pname="[$pname]"
echo "$clusterip:$tport $ns/$svc$pname" >> $ADDRLIST
echo "$clusterip:$tport $ns/$svc$pname $svcType" >> $ADDRLIST
done
IFS=' '
done < <(kubectl get svc --no-headers -A -o=custom-columns='NS:.metadata.namespace,NAME:.metadata.name,ClusterIP:.spec.clusterIP,PORTNAME:.spec.ports[*].name,PORT:.spec.ports[*].port,PROTOCOL:.spec.ports[*].protocol,TGTPORT:.spec.ports[*].targetPort')
done < <(kubectl get svc --no-headers -A -o=custom-columns='NS:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,ClusterIP:.spec.clusterIP,PORTNAME:.spec.ports[*].name,PORT:.spec.ports[*].port,PROTOCOL:.spec.ports[*].protocol,TGTPORT:.spec.ports[*].targetPort')

$BDIR/tlsscan --infile $ADDRLIST --compact-json
8 changes: 8 additions & 0 deletions src/main_k8s_tlsscan
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash

aws configure set aws_access_key_id "$(head -1 /home/k8tls/.aws/credentials)" && \
aws configure set aws_secret_access_key "$(tail -1 /home/k8tls/.aws/credentials)"

./k8s_tlsscan && \
printf "\nJSON Report: \n" && \
cat /tmp/report.json
8 changes: 6 additions & 2 deletions src/tlsscan
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ csvheader()
{
[[ "$csvout" == "" ]] && return
if [ ! -f "$csvout" ]; then
echo "Name,Address,Status,Version,Ciphersuite,Hash,Signature,Verification,FIPS_140_3_Compliant" > $csvout
echo "Name,Address,Type,Status,Version,Ciphersuite,Hash,Signature,Verification,FIPS_140_3_Compliant" > $csvout
fi
}

Expand All @@ -87,6 +87,7 @@ jsonendpoint_hdr()
"svc": "$SVC_Name",
"host": "$SVC_Host",
"port": "$SVC_Port",
"type": "$SVC_Type",
"finding": [
EOF
}
Expand Down Expand Up @@ -187,7 +188,10 @@ main()
SVC_Host=${SVC_Address/:*}
SVC_Port=${SVC_Address/*:}
SVC_Name=${arr[1]}
SVC_Scanners=${arr[2]}
SVC_Type=${arr[2]}
# Service type is only applicable for Kubernetes
[[ "$SVC_Type" == "" ]] && SVC_Type="NA"
SVC_Scanners=${arr[3]}
[[ "$SVC_Scanners" == "" ]] && SVC_Scanners="tls"
scansvc
((endpoint_cnt++))
Expand Down