#!/bin/bash

[[ $CCI_SRC ]] || CCI_SRC=/c/cbs

server_ip=$(ip route get 1.2.3.4 | awk '{print $7; exit}')

umount_account_token()
{
        serviceaccount_yaml=$CCI_SRC/container/serviceaccount.yaml
        kubectl get serviceaccount default -n development -o yaml > $serviceaccount_yaml
        echo "automountServiceAccountToken: false" >> $serviceaccount_yaml
        kubectl apply -f $serviceaccount_yaml
}

del_3des()
{
        kube_yaml=(
                        /etc/kubernetes/manifests/kube-controller-manager.yaml
                        /etc/kubernetes/manifests/kube-scheduler.yaml
        )

        for i in ${kube_yaml[@]}
        do
		[ -f "$i" ] || continue
                cat $i | grep -q "^    - --tls-cipher-suites="
                [ $? = 0 ] || {
                        sed -i '/- --bind-address=127.0.0.1/a\    - --tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384' $i
                }
        done

	etcd_conf=/etc/systemd/system/etcd.service
	[ -f "$etcd_conf" ] && {
		grep -q "\--cipher-suites=" $etcd_conf || {
			sed -i '/--name=etcd-k8s-master-1/a\  --cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 \\' $etcd_conf
			systemctl daemon-reload
			systemctl restart etcd
		}
	}

	kubelet_conf=/var/lib/kubelet/config.yaml
	[ -f "$kubelet_conf" ] && {
		grep -q "tlsCipherSuites: " /var/lib/kubelet/config.yaml || {
			echo "tlsCipherSuites: ['TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256','TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384','TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305','TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256','TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384','TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305','TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256','TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA','TLS_RSA_WITH_AES_128_CBC_SHA','TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA','TLS_RSA_WITH_AES_128_GCM_SHA256','TLS_RSA_WITH_AES_256_CBC_SHA','TLS_RSA_WITH_AES_256_GCM_SHA384']">> $kubelet_conf
			systemctl daemon-reload
			systemctl restart kubelet
		}
	}
}

del_ingress_nginx_controller()
{
        kubectl delete daemonset ingress-nginx-controller -n kube-system >/dev/null 2>&1
}

set_rpcbind_listen_address()
{
        rpcbind_conf=/etc/systemd/system/sockets.target.wants/rpcbind.socket
        cat $rpcbind_conf | grep -q "^ListenStream=$server_ip:111"
        [ $? = 0 ] || {
                sed -i "/^ListenStream=\/run\/rpcbind.sock/a\ListenStream=$server_ip:111" $rpcbind_conf
                systemctl daemon-reload
                systemctl restart rpcbind.socket
        }
}

set_sshd_listen_address()
{
        sshd_conf=/etc/ssh/sshd_config
        cat $sshd_conf | grep -q "^ListenAddress $server_ip"
        [ $? = 0 ] || {
                sed -i "/^#ListenAddress 0.0.0.0/a\ListenAddress $server_ip" $sshd_conf
                systemctl daemon-reload
                systemctl restart sshd
        }
}

set_kubelet_pid_limit()
{
        kubelet_conf=/etc/sysconfig/kubelet
        conf_val=`cat $kubelet_conf`
        [[ $conf_val == *"pod-max-pids"* ]] || {
                sed -i "s/$conf_val/$conf_val --pod-max-pids=1024 --feature-gates=\\\\\"SupportPodPidsLimit=true\\\\\"/g" $kubelet_conf
                systemctl daemon-reload
                systemctl restart kubelet
        }
}

set_kube_apiserver()
{
	kube_apiserver_yaml=/etc/kubernetes/manifests/kube-apiserver.yaml
	[ -f "$kube_apiserver_yaml" ] || return

	ps -ef | grep kube-apiserver| grep -q tls-cipher-suite
	[ $? = 0 ] || {
		sed -i '/- --etcd-cafile=\/etc\/kubernetes\/pki\/etcd\/ca.crt/a\    - --tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384' $kube_apiserver_yaml
	}
}

remove_suid()
{
	sh $CCI_SRC/sparrow/9-clear/remove-suid
	grep -q "remove-suid" /etc/rc.d/rc.local || {
		echo "$CCI_SRC/sparrow/9-clear/remove-suid" >> /etc/rc.d/rc.local
		chmod +x /etc/rc.d/rc.local
	}
}

start_component()
{
        local type=$1
        local name=$2
        local yaml=$3

        kubectl delete $type $name -n kube-system
        kubectl create -f $yaml 2> /dev/null
}

has_set()
{
        local field=$1
        local yaml=$2

        cat $yaml | grep -q "$field"
}

set_readonly_rootfs_and_seccomp()
{
        [ "$(ls -A /etc/kubernetes/manifests)" = "" ] || {
                yaml=/etc/kubernetes/manifests/*.yaml
                has_set "readOnlyRootFilesystem" "$yaml" || {
                        sed -i '/imagePullPolicy:/a\    securityContext:\n      readOnlyRootFilesystem: true\n      seccompProfile:\n        type: RuntimeDefault' $yaml
                        systemctl restart kubelet
                        sleep 120
                }
        }

        [ -d "/etc/kubernetes/plugins/metrics-server" ] && {
                yaml=/etc/kubernetes/plugins/metrics-server/metrics-server.yaml
                has_set "seccompProfile" "$yaml" || {
                        sed -i '/readOnlyRootFilesystem: true/a\          seccompProfile:\n            type: RuntimeDefault' $yaml

                        start_component "deployment" "metrics-server" "$yaml"
                }
        }

        [ "$(ls -A /etc/kubernetes/plugins/network-plugin)" = "" ] || {
                yaml=/etc/kubernetes/plugins/network-plugin/calico-typha.yaml
                has_set "srv-calico-kube-controllers" "$yaml" || {
                        sed -i \
                            -e '/allowPrivilegeEscalation: false/a\          readOnlyRootFilesystem: true\n          seccompProfile:\n            type: RuntimeDefault' \
                            -e '/serviceAccountName: calico-kube-controllers/i\      volumes:\n      - name: srv-calico-kube-controllers\n        hostPath:\n          path: /srv/calico-kube-controllers/status' \
                            -e '/image: registry.kubeoperator.io:8082\/calico\/kube-controllers:v3.21.4/a\          securityContext:\n            readOnlyRootFilesystem: true\n            seccompProfile:\n              type: RuntimeDefault\n          volumeMounts:\n          - mountPath: \/status\n            name: srv-calico-kube-controllers' \
                            $yaml

                        start_component "deployment" "calico-kube-controllers" "$yaml"
                        start_component "deployment" "calico-typha" "$yaml"
                        start_component "daemonset" "calico-node" "$yaml"
                }
        }

        kubectl get deploy coredns -n kube-system -o yaml>$CCI_SRC/container/kube-system-coredns.yaml
        has_set "seccompProfile" "$CCI_SRC/container/kube-system-coredns.yaml" || {
                yaml=$CCI_SRC/container/kube-system-coredns.yaml
                sed -i '/readOnlyRootFilesystem: true/a\          seccompProfile:\n            type: RuntimeDefault' $yaml

                start_component "deployment" "coredns" "$yaml"
        }
        rm -f $CCI_SRC/container/kube-system-coredns.yaml

        kubectl get daemonset kube-proxy -n kube-system -o yaml>$CCI_SRC/container/kube-system-kube-proxy.yaml
        has_set "seccompProfile" "$CCI_SRC/container/kube-system-kube-proxy.yaml" || {
                yaml=$CCI_SRC/container/kube-system-kube-proxy.yaml
                sed -i '/privileged: true/a\          readOnlyRootFilesystem: true\n          seccompProfile:\n            type: RuntimeDefault' $yaml

                start_component "daemonset" "kube-proxy" "$yaml"
        }
        rm -f $CCI_SRC/container/kube-system-kube-proxy.yaml

        [ -d "/etc/kubernetes/plugins/dns-cache" ] && {
                yaml=/etc/kubernetes/plugins/dns-cache/nodelocaldns.yaml
                has_set "seccompProfile" "$yaml" || {
                        sed -i \
                            -e "s/\/etc\/Corefile/\/etc\/node-local-dns\/Corefile" \
                            -e "/privileged: true/a\          readOnlyRootFilesystem: true\n          seccompProfile:\n            type: RuntimeDefault" \
                            -e "/Corefile.base/a\      - name: node-local-dns\n        hostPath:\n          path: \/etc\/node-local-dns"  -e "/mountPath: \/etc\/kube-dns/a\        - name: node-local-dns\n          mountPath: /etc/node-local-dns" \
                            $yaml

                        start_component "daemonset" "node-local-dns" "$yaml"
                }
        }
}

add_audit_rules()
{
        echo "-w /usr/bin/dockerd -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-w /etc/docker -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-a exit,always -F path=/run/containerd -F perm=war -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-a exit,always -F path=/var/lib/docker -F perm=war -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-w /usr/lib/systemd/system/docker.service -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-w /var/run/docker.sock -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-w /etc/docker/daemon.json -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-w /etc/sysconfig/docker -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-w /usr/bin/containerd -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-w /usr/bin/containerd-shim -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-w /usr/bin/containerd-shim-runc-v1 -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-w /usr/bin/containerd-shim-runc-v2 -k docker" >> /etc/audit/rules.d/audit.rules
        echo "-w /usr/bin/runc -k docker" >> /etc/audit/rules.d/audit.rules
        service auditd restart
}

set_daemon_and_content_trust()
{
        export DOCKER_CONTENT_TRUST=1

        if [ ! -f /etc/docker/daemon.json ]; then
            echo "The /etc/docker/daemon.json file does not exist."
        else
            chmod 600 /etc/docker/daemon.json
        fi    
}

set_readonly_rootfs_and_seccomp
umount_account_token
del_3des
del_ingress_nginx_controller
set_rpcbind_listen_address
set_sshd_listen_address
set_kubelet_pid_limit
set_kube_apiserver
add_audit_rules
remove_suid
set_daemon_and_content_trust
