Skip to content

Commit

Permalink
feat: Add Support to find Exposed ports in AWS EKS
Browse files Browse the repository at this point in the history
Signed-off-by: Anurag Rajawat <anuragsinghrajawat22@gmail.com>
  • Loading branch information
anurag-rajawat committed Dec 15, 2024
1 parent 738668d commit 03fb3ef
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 25 deletions.
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
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)
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

0 comments on commit 03fb3ef

Please sign in to comment.