Created
May 28, 2022 16:03
-
-
Save diyinfosec/e33709d0cc9321822d2038fa260c3374 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#- Script to setup Docker, Minikube, Kubectl, Helm on Ubuntu. | |
#- On the K8s cluster install - Vault, Consul, Datadog agent. | |
#- Access to K8s dashboard is provided through nginx on port 5000. http://<host_ip>:5000 | |
#- Acess to Vault UI is provided through kubectl port-forward. http://<host_ip>:8200 | |
#- I use multipass for the VMs, so rebuild a VM the following steps are applicable. | |
#- For the first time, the first two commands can be ignored. | |
# multipass delete ktest | |
# multipass purge | |
# multipass launch -n ktest -m 4G -d 20G -c 2 | |
# multipass transfer ./manage.sh ktest:/home/ubuntu/manage.sh | |
# multipass exec ktest -- chmod +x /home/ubuntu/manage.sh | |
# multipass exec ktest -- /home/ubuntu/manage.sh -t auto | |
# multipass shell ktest | |
#=================================================================== | |
#- Runs a command and returns true/false based on exec status. | |
#=================================================================== | |
function check_install() | |
{ | |
$1 > /dev/null 2>&1 | |
status=$? | |
#echo "status is "$status | |
if test $status -eq 0 | |
then | |
true | |
else | |
false | |
fi | |
} | |
#=================================================================== | |
#- Check if the current user can sudo, else exit | |
#=================================================================== | |
function check_sudo() | |
{ | |
if ! check_install 'sudo touch /dev/null' | |
then | |
echo "User "$USER "cannot run sudo. Exiting..." | |
exit 1 | |
fi | |
} | |
#=================================================================== | |
#- Setup some useful aliases in bashrc | |
#=================================================================== | |
function setup_aliases() | |
{ | |
#- Basic aliases | |
tee -a $HOME/.bashrc <<EOF | |
alias rc='source ~/.bashrc' | |
alias l='ls -rlat' | |
alias m='$HOME/manage.sh -t menu' | |
alias c='clear' | |
alias k='kubectl' | |
alias kl='kubectl logs kube-apiserver-minikube -n kube-system | grep audit.k8s.io/v1' | |
sudo chown $USER /var/run/docker.sock | |
function dds() | |
{ | |
echo "This function prints the status of the Datadog agent" | |
sleep 2; | |
export AGENT_POD=\$(kubectl get pods -l app.kubernetes.io/component=agent,app=datadog-agent -o name); | |
echo \$AGENT_POD | |
if test "x"\$AGENT_POD != "x" | |
then | |
kubectl exec -it \$AGENT_POD -c agent -- agent status; | |
else | |
echo "Datadog agent pod is not running." | |
fi | |
} | |
EOF | |
. $HOME/.bashrc | |
} | |
#=================================================================== | |
#- Install docker, conntrack, jq, net-tools | |
#=================================================================== | |
function install_basics() | |
{ | |
#- Installing docker | |
if ! check_install 'docker --version' | |
then | |
echo "Installing docker" | |
curl -fsSL https://get.docker.com | bash | |
#- Permissions for docker.sock | |
#- You can also do, sudo chmod 666 /var/run/docker.sock but it stays only till restart! | |
#- Ref: https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user | |
echo "Fixing the docker permissions" | |
#trap 'sudo groupadd docker' EXIT | |
#trap 'sudo usermod -aG docker $USER' EXIT | |
sudo gpasswd -a $USER docker | |
echo 'User:'$USER 'is member of '$(groups $USER) | |
#sleep 5 | |
#- Login to the docker group | |
#newgrp docker | |
#trap 'sudo systemctl restart docker' EXIT | |
#- Final solution I came up with was to change ownership of docker.sock to Ubuntu. Add this line to .bashrc | |
sudo chown $USER /var/run/docker.sock | |
else | |
echo "Docker is already installed" | |
fi | |
#- Installing jq and net-tools | |
if ! check_install 'jq --version' | |
then | |
echo "Installing jq" | |
sudo -E sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends jq > /dev/null' | |
else | |
echo "jq is already installed" | |
fi | |
if ! check_install 'netstat -V' | |
then | |
echo "Installing net-tools" | |
sudo -E sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends net-tools > /dev/null' | |
else | |
echo "net-tools is already installed" | |
fi | |
} | |
#======================================================================== | |
#- Install minikube | |
#- Ref: https://minikube.sigs.k8s.io/docs/start/ | |
#- Install kubectl | |
#- Ref: https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/ | |
#======================================================================== | |
function install_kube_stuff() | |
{ | |
#- Install conntrack (dependency for minikube) | |
if ! check_install 'conntrack --version' | |
then | |
echo "Installing conntrack" | |
sudo -E sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends conntrack > /dev/null' | |
else | |
echo "conntrack is already installed" | |
fi | |
#- Install minikube | |
if ! check_install 'minikube version' | |
then | |
echo "Downloading and installing minikube" | |
curl -sLO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 | |
sudo install minikube-linux-amd64 /usr/local/bin/minikube | |
else | |
echo "minikube is already installed" | |
fi | |
#- Install kubectl | |
if ! check_install 'kubectl version' | |
then | |
echo "Installing kubectl" | |
curl -sLO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 | |
curl -sLO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" | |
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl | |
else | |
echo "kubectl is already installed" | |
fi | |
#- Install helm | |
if ! check_install 'helm version' | |
then | |
echo "Installing helm with snap" | |
sudo snap install helm --classic | |
else | |
echo "helm is already installed" | |
fi | |
} | |
#=================================================================== | |
#- Install nginx - for port forwarding (minikube dashboard) | |
#- Ref: https://www.hostinger.com/tutorials/how-to-set-up-nginx-reverse-proxy/ | |
#=================================================================== | |
function install_nginx() | |
{ | |
if check_install 'nginx -v' | |
then | |
echo "nginx is already installed" | |
return | |
fi | |
echo "Installing nginx" | |
sudo apt-get update -qq > /dev/null | |
sudo apt-get -y install nginx -qq > /dev/null | |
#- Clean up from previous installs. | |
echo "Attempting clean-up of conf files" | |
sudo unlink /etc/nginx/sites-enabled/default 2>/dev/null | |
sudo rm /etc/nginx/sites-enabled/k8s-dashboard-proxy.conf 2>/dev/null | |
sudo rm /etc/nginx/sites-available/k8s-dashboard-proxy.conf 2>/dev/null | |
echo "Creating proxy config for K8s dashboard" | |
sudo tee /etc/nginx/sites-available/k8s-dashboard-proxy.conf <<EOF | |
server { | |
listen 5000; | |
location / { | |
proxy_pass http://127.0.0.1:5001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/; | |
} | |
} | |
EOF | |
echo "Linking config to sites-enabled" | |
sudo ln -s /etc/nginx/sites-available/k8s-dashboard-proxy.conf /etc/nginx/sites-enabled/k8s-dashboard-proxy.conf | |
echo "Restarting nginx" | |
sudo nginx -t | |
sudo service nginx restart | |
} | |
#======================================================= | |
#- Audit policy for minikube and start it | |
#- https://minikube.sigs.k8s.io/docs/tutorials/audit-policy/ | |
#======================================================= | |
function minikube_start_audit() | |
{ | |
echo "Creating directory for minikube audit config" | |
mkdir -p ~/.minikube/files/etc/ssl/certs | |
echo "Downloading config from Gist" | |
sudo curl -s https://gist.githubusercontent.com/diyinfosec/7acadaea47a71c82b68f06e13213dd1d/raw/fc02e5823628dd5e9fe794daf84193ee2cb00cb9/k8s-audit-policy.yaml -o ~/.minikube/files/etc/ssl/certs/audit-policy.yaml | |
#- Looks like we can start minikube over and over, without having to verify if it's running. | |
echo "Starting minikube with audit enabled" | |
#- For log rotation, ref: https://sudo-bmitch.github.io/presentations/dc2019/tips-and-tricks-of-the-captains.html#17 | |
minikube start \ | |
--docker-opt=log-driver=json-file --docker-opt=log-opt=max-size=10M --docker-opt=log-opt=max-file=3 \ | |
--extra-config=apiserver.audit-policy-file=/etc/ssl/certs/audit-policy.yaml \ | |
--extra-config=apiserver.audit-log-path=- | |
status=$? | |
echo "Minikube command status is "$status | |
if test $status -ne 0 | |
then | |
echo "minikube did not start. Aborting installation" | |
exit 1; | |
fi | |
} | |
#=================================================================== | |
#- Bring up kubernetes dashboard on port 5000 | |
#=================================================================== | |
function minikube_start_dashboard() | |
{ | |
DASHBOARD_STATUS=$(sudo netstat -tlnp | grep ":5001" | awk '{print $NF}') | |
if test "x"$DASHBOARD_STATUS != "x" | |
then | |
echo "Dashboard seems to be running already. "$DASHBOARD_STATUS | |
killpid=$(echo $DASHBOARD_STATUS | cut -f1 -d"/") | |
echo "PID to kill is " $killpid | |
sudo kill $killpid | |
minikube_start_dashboard | |
else | |
echo "Enabling kubernetes dashboard on port 5001" | |
nohup minikube dashboard --port=5001 --url=false & | |
sudo systemctl restart nginx | |
fi | |
} | |
#=================================================================== | |
#- Minikube clear audit log | |
#=================================================================== | |
function minikube_clear_audit() | |
{ | |
sudo tee clear_k8s_audit.sh <<EOF | |
#- Get the name of the api server container | |
export CONTAINER_NAME=\$(docker ps --filter "name=k8s_kube-apiserver" --format '{{.Names}}') | |
#- Clear the log file | |
echo ""> \$(docker inspect --format='{{.LogPath}}' \$CONTAINER_NAME) | |
EOF | |
minikube cp clear_k8s_audit.sh /tmp/1.sh | |
minikube ssh -- /bin/sh sudo /tmp/1.sh | |
} | |
#=================================================================== | |
#- Install Consul and Vault using helm | |
#- Ref: https://learn.hashicorp.com/tutorials/vault/kubernetes-minikube-consul?in=vault/kubernetes | |
#=================================================================== | |
function install_vault_consul() | |
{ | |
if check_install 'helm status vault' && check_install 'helm status consul' | |
then | |
echo "Vault and Consul are already installed" | |
return; | |
fi | |
tee $HOME/helm-consul-values.yml <<EOF | |
global: | |
datacenter: vault-kubernetes-tutorial | |
client: | |
enabled: true | |
server: | |
replicas: 1 | |
bootstrapExpect: 1 | |
disruptionBudget: | |
maxUnavailable: 0 | |
EOF | |
helm repo add hashicorp https://helm.releases.hashicorp.com 2>/dev/null | |
helm repo update | |
helm install consul hashicorp/consul --values ./helm-consul-values.yml | |
#- Values given in: https://github.com/hashicorp/vault-helm/blob/main/values.yaml | |
#- Theoretically we can enable audit logging here but if I do it then the vault-0 pod doesn't spin up. So I am doing it separately, after this pod has been created | |
helm install vault hashicorp/vault \ | |
--set server.dev.enabled='true' \ | |
--set ui.enabled='true' | |
} | |
#=================================================================== | |
#- Install Consul and Vault using helm | |
#- Ref: https://learn.hashicorp.com/tutorials/vault/kubernetes-minikube-consul?in=vault/kubernetes | |
#=================================================================== | |
function remove_vault_consul() | |
{ | |
read -p "Are you sure you want to continue? <y/N> " prompt | |
if [[ $prompt =~ [yY](es)* ]] | |
then | |
helm uninstall vault | |
helm uninstall consul | |
fi | |
} | |
#=================================================================== | |
#- Vault - enable k8s auth | |
#=================================================================== | |
function vault_enable_k8s_auth() | |
{ | |
tee $HOME/vault_k8s_auth.sh <<FOF | |
#- Commented because dev server does not need tokens for CLI | |
# vault login $VAULT_TOKEN | |
vault auth enable kubernetes | |
vault write auth/kubernetes/config \\ | |
kubernetes_host="https://\$KUBERNETES_PORT_443_TCP_ADDR:443" | |
vault policy write webapp - <<EOF | |
path "secret/data/webapp/config" { | |
capabilities = ["read"] | |
} | |
EOF | |
vault write auth/kubernetes/role/webapp \\ | |
bound_service_account_names=vault \\ | |
bound_service_account_namespaces=default \\ | |
policies=webapp \\ | |
ttl=24h | |
exit | |
FOF | |
kubectl cp vault_k8s_auth.sh default/vault-0:/tmp/ | |
kubectl exec --stdin=true --tty=true vault-0 -- /bin/sh /tmp/vault_k8s_auth.sh | |
} | |
#=================================================================== | |
#- Vault - enable audit logging | |
#- https://www.vaultproject.io/docs/audit/file#examples | |
#=================================================================== | |
function vault_enable_audit_logs() | |
{ | |
while [[ $(kubectl get pods -l app.kubernetes.io/instance=vault,app.kubernetes.io/name=vault,component=server -o 'jsonpath={..status.conditions[?(@.type=="Ready")].status}') != "True" ]]; do echo "waiting for vault-0 pod to run." && sleep 5; done | |
kubectl exec --stdin=true --tty=true vault-0 -- vault audit enable file file_path=stdout | |
} | |
#==================== | |
#- Install DD Agent | |
#==================== | |
function install_dd_agent() | |
{ | |
if check_install 'helm status datadog-agent' | |
then | |
echo "Datadog agent is already installed" | |
return | |
fi | |
helm repo add datadog https://helm.datadoghq.com | |
helm repo update | |
#- This file is not being used currently used | |
tee -a $HOME/helm-ddagent-values.yml <<EOF | |
datadog: | |
logs: | |
enabled: true | |
containerCollectAll: true | |
EOF | |
while true | |
do | |
echo "Enter a valid DD API Key": | |
read key | |
response=$(curl -sX GET "https://api.datadoghq.com/api/v1/validate" \ | |
-H "Content-Type: application/json" \ | |
-H "DD-API-KEY: ${key}" | grep valid) | |
if test "x"$response != "x" | |
then | |
echo "Key is valid" | |
echo "Installing datadog-agent using Helm" | |
#- RELEASE_NAME can be anything you decide, In this example it is: datadog-agent | |
#helm install datadog-agent -f helm-ddagent-values.yml --set datadog.site='datadoghq.com' --set datadog.apiKey=$key datadog/datadog | |
# - You can provide values from a config file: | |
# curl -s https://raw.githubusercontent.com/DataDog/helm-charts/main/charts/datadog/values.yaml -o datadog-values.yaml | |
# helm install datadog-agent -f helm-ddagent-values.yml | |
# - You can also set individual values with --set option: https://github.com/Datadog/helm-charts/tree/main/charts/datadog#values | |
# helm install datadog-agent --set datadog.site='datadoghq.com' --set datadog.apiKey=$key datadog/datadog | |
# - You can also combine them both | |
#- helm upgrade datadog-agent -f datadog-values.yaml --set datadog.kubelet.tlsVerify='false' datadog/datadog | |
helm install datadog-agent \ | |
--set datadog.site='datadoghq.com' \ | |
--set datadog.apiKey=$key \ | |
--set datadog.kubelet.tlsVerify='false' \ | |
--set clusterAgent.enabled='true' \ | |
--set datadog.kubeStateMetricsCore.enabled='true' \ | |
--set datadog.logs.enabled='true' \ | |
--set datadog.logs.containerCollectAll='true' \ | |
datadog/datadog | |
echo "To test if everything's working fine use: kubectl exec -it datadog-agent-qkmkp -c agent -- agent status" | |
break | |
fi | |
done | |
} | |
#=================================================================== | |
#- Datadog Agent - Remove | |
#=================================================================== | |
function remove_dd_agent() | |
{ | |
helm uninstall datadog-agent | |
} | |
#=================================================================== | |
#- Vault UI - Port forward to 8200 | |
#=================================================================== | |
function vault_ui_port_forward() | |
{ | |
VAULT_UI_STATUS=$(sudo netstat -tlnp | grep ":8200" | awk '{print $NF}') | |
if test "x"$VAULT_UI_STATUS != "x" | |
then | |
echo "Vault UI seems to be up already."$VAULT_UI_STATUS ". Killing this first..." | |
killpid=$(echo $VAULT_UI_STATUS | cut -f1 -d"/") | |
echo "PID to kill is " $killpid | |
sudo kill $killpid | |
vault_ui_port_forward | |
else | |
echo "Enabling port forward for Vault UI" | |
nohup kubectl port-forward --address 0.0.0.0 vault-0 8200:8200 & | |
fi | |
} | |
#=================================================================== | |
#- Remove docker completely | |
#- https://docs.docker.com/engine/install/ubuntu/#uninstall-docker-engine | |
#=================================================================== | |
function remove_docker() | |
{ | |
sudo -E sh -c 'DEBIAN_FRONTEND=noninteractive apt-get purge -y -qq purge docker-ce docker-ce-cli containerd.io docker-compose-plugin' | |
sudo rm -rf /var/lib/docker | |
sudo rm -rf /var/lib/containerd | |
} | |
#=================================================================== | |
#- Selection Menu | |
#- Ref: https://askubuntu.com/questions/1705/how-can-i-create-a-select-menu-in-a-shell-script | |
#=================================================================== | |
function show_menu() | |
{ | |
check_sudo | |
while true | |
do | |
clear | |
echo "select the Operation:" | |
echo " 0) Setup aliases" | |
echo " 1) Install docker, jq, net-tools" | |
echo " 2) Install minikube, kubectl and helm" | |
echo " 3) Install and configure nginx (for minikube dashboard)" | |
echo " 4) minikube - Start with audit" | |
echo " 5) minikube - Start dashboard" | |
echo " 6) minikube clear audit log (experimental)" | |
echo " 7) Install Vault and Consul with Helm" | |
echo " 8) Vault - Enable K8s auth" | |
echo " 9) Vault - Port forward UI to port 8200" | |
echo " 10) Vault - Enable Audit logs" | |
echo " 11) Datadog - Install Agent with Helm" | |
echo " 12) Remove Vault and Consul" | |
echo " 13) Remove DD Agent" | |
echo " 14) Remove Docker" | |
echo " x) Exit" | |
read n | |
case $n in | |
0) setup_aliases; echo "Press enter to continue..."; read;; | |
1) install_basics; echo "Press enter to continue..."; read;; | |
2) install_kube_stuff; echo "Press enter to continue..."; read;; | |
3) install_nginx; echo "Press enter to continue..."; read;; | |
4) minikube_start_audit; echo "Press enter to continue..."; read;; | |
5) minikube_start_dashboard; echo "Press enter to continue..."; read;; | |
6) echo "Not doing it"; echo "Press enter to continue..."; read;; #minikube_clear_audit;; | |
7) install_vault_consul; echo "Press enter to continue..."; read;; | |
8) vault_enable_k8s_auth; echo "Press enter to continue..."; read;; | |
9) vault_ui_port_forward; echo "Press enter to continue..."; read;; | |
10) vault_enable_audit_logs; echo "Press enter to continue..."; read;; | |
11) install_dd_agent; echo "Press enter to continue..."; read;; | |
12) remove_vault_consul; echo "Press enter to continue..."; read;; | |
13) remove_dd_agent; echo "Press enter to continue..."; read;; | |
14) remove_docker; echo "Press enter to continue..."; read;; | |
x) exit 0;; | |
*) echo "invalid option"; echo "Press enter to continue..."; read;; | |
esac | |
done | |
} | |
function auto_install() | |
{ | |
check_sudo; | |
setup_aliases; | |
install_basics; | |
install_kube_stuff; | |
install_nginx; | |
minikube_start_audit; | |
install_dd_agent; | |
minikube_start_dashboard; | |
install_vault_consul; | |
vault_enable_audit_logs; | |
vault_enable_k8s_auth; | |
vault_ui_port_forward; | |
} | |
#- Basically these are the two functions: | |
#show_menu | |
#auto_install | |
ERR_MSG="Script Usage: $(basename $0) -t <Type can be 'auto' for automatic or 'menu' for menu based>. Example: $(basename $0) -t auto" | |
#- Ref: https://linuxconfig.org/bash-script-flags-usage-with-arguments-examples | |
while getopts 't:' OPTION; do | |
case "$OPTION" in | |
t) | |
echo "Value provided is " $OPTARG | |
if [ $OPTARG != "auto" -a $OPTARG != "menu" ]; then | |
echo $ERR_MSG >&2 | |
elif [ $OPTARG == "auto" ]; then | |
echo "Auto install" | |
auto_install; | |
elif [ $OPTARG == "menu" ]; then | |
echo "Menu based" | |
show_menu; | |
fi | |
;; | |
?) | |
echo $ERR_MSG >&2 | |
exit 1 | |
;; | |
esac | |
done | |
shift "$(($OPTIND -1))" | |
if [ $OPTIND -eq 1 ]; then echo $ERR_MSG; fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment