diff --git a/README.md b/README.md index 55dca6c..1a2b0f5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Build Your Own DevSecOps using SUSE Rancher 2.6 +# Build Your Own DevSecOps using SUSE Rancher 2.7 ![SUSE Rancher - DevSecOps Scenario](./overview.png) diff --git a/helm-v3.18.4-linux-amd64.tar.gz b/helm-v3.18.4-linux-amd64.tar.gz new file mode 100644 index 0000000..947f0a2 Binary files /dev/null and b/helm-v3.18.4-linux-amd64.tar.gz differ diff --git a/rancher-install.sh b/rancher-install.sh new file mode 100644 index 0000000..701bccd --- /dev/null +++ b/rancher-install.sh @@ -0,0 +1,96 @@ +#! /bin/bash -e + +# Install Kubernetes tools +echo "Installing Kubernetes Client Tools - kubectl and helm ..." + +# Install kubectl +curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" +sudo chmod +x kubectl +sudo mv kubectl /usr/local/bin/ +sudo kubectl version --client + +# Install helm +curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 +sudo chmod 700 get_helm.sh +sudo ./get_helm.sh +sudo helm version + +#! /bin/bash -e + +# install rancher server +echo "Install Rancher Server using helm chart on RKE2 ..." + +echo "Install RKE2 v1.32 ..." +sudo bash -c 'curl -sfL https://get.rke2.io | INSTALL_RKE2_CHANNEL="v1.32" sh -' +sudo mkdir -p /etc/rancher/rke2 +sudo bash -c 'echo "write-kubeconfig-mode: \"0644\"" > /etc/rancher/rke2/config.yaml' +sudo systemctl enable --now rke2-server.service + +mkdir -p $HOME/.kube +ln -s /etc/rancher/rke2/rke2.yaml $HOME/.kube/config +export KUBECONFIG=$HOME/.kube/config + +# Wait until the RKE2 is ready +echo "Initializing RKE2 cluster ..." +while [ `kubectl get deploy -n kube-system | grep 1/1 | wc -l` -ne 4 ] +do + sleep 5 + kubectl get po -n kube-system +done +echo "Your RKE2 cluster is ready!" +kubectl get node + +echo "Install Cert Manager v1.18.2 ..." +kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.18.2/cert-manager.crds.yaml +helm repo add jetstack https://charts.jetstack.io +helm install \ + cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --create-namespace + +kubectl -n cert-manager rollout status deploy/cert-manager + +# Wait until cert-manager deployment complete +echo "Wait until cert-manager deployment finish ..." +while [ `kubectl get deploy -n cert-manager | grep 1/1 | wc -l` -ne 3 ] +do + sleep 5 + kubectl get po -n cert-manager +done + + +# Install Rancher with helm chart +echo "Install Rancher ${RANCHER_VERSION} ..." +RANCHER_IP=`curl -qs http://checkip.amazonaws.com` +RANCHER_FQDN=rancher.$RANCHER_IP.sslip.io +RANCHER_VERSION=v2.11.3 + +helm repo add rancher-stable https://releases.rancher.com/server-charts/stable +helm repo update + +helm upgrade --install rancher rancher-stable/rancher \ + --namespace cattle-system \ + --set hostname=$RANCHER_FQDN \ + --set replicas=1 \ + --set global.cattle.psp.enabled=false \ + --version ${RANCHER_VERSION} \ + --create-namespace + +echo "Wait until cattle-system deployment finish ..." +while [ `kubectl get deploy -n cattle-system | grep 1/1 | wc -l` -ne 1 ] +do + sleep 5 + kubectl get po -n cattle-system +done + +RANCHER_BOOTSTRAP_PWD=`kubectl get secret --namespace cattle-system bootstrap-secret -o go-template='{{.data.bootstrapPassword|base64decode}}{{ "\n" }}'` + + +echo +echo "---------------------------------------------------------" +echo "Your Rancher Server is ready." +echo +echo "Your Rancher Server URL: https://${RANCHER_FQDN}" > rancher-url.txt +echo "Bootstrap Password: ${RANCHER_BOOTSTRAP_PWD}" >> rancher-url.txt +cat rancher-url.txt +echo "---------------------------------------------------------" diff --git a/setup/anchore/99-one-step-install-anchore.sh b/setup/anchore/99-one-step-install-anchore.sh index 5c3b49c..5f92116 100755 --- a/setup/anchore/99-one-step-install-anchore.sh +++ b/setup/anchore/99-one-step-install-anchore.sh @@ -15,9 +15,10 @@ fi helm repo add anchore https://charts.anchore.io helm repo update +helm search repo anchore helm install anchore anchore/anchore-engine \ - --version 1.19.8 \ + --version 1.24.2 \ --create-namespace \ -n anchore \ --set postgresql.persistence.accessMode='ReadWriteMany' @@ -39,3 +40,25 @@ echo "URL: http://anchore-anchore-engine-api.anchore.svc.cluster.local:8228/v1/" echo "User: admin" >> $HOME/myanchore.txt echo "Password: $ANCHORE_PWD" >> $HOME/myanchore.txt cat $HOME/myanchore.txt + + +ANCHORE_CLI_USER=admin +ANCHORE_CLI_PASS=$(kubectl get secret --namespace anchore anchore-anchore-engine-admin-pass -o jsonpath="{.data.ANCHORE_ADMIN_PASSWORD}" | base64 --decode; echo) +ANCHORE_CLI_URL=http://anchore-anchore-engine-api.anchore.svc.cluster.local:8228/v1/ + +kubectl run -i --tty anchore-cli \ + --restart=Always \ + --image anchore/engine-cli \ + --env ANCHORE_CLI_USER=${ANCHORE_CLI_USER} \ + --env ANCHORE_CLI_PASS=${ANCHORE_CLI_PASS} \ + --env ANCHORE_CLI_URL=${ANCHORE_CLI_URL} \ + -n anchore + + +kubectl exec -it anchore-cli -n anchore -- bash + + +anchore-cli policy list +# anchore-cli policy get 2c53a13c-1765-11e8-82ef-23527761d060 --detail > policybundle.json +anchore-cli policy add policybundle.json +anchore-cli policy activate 2c53a13c-1765-11e8-82ef-23527761d060 \ No newline at end of file diff --git a/setup/anchore/anchore_whitelist.json b/setup/anchore/anchore_whitelist.json index a2c6862..4f138e2 100644 --- a/setup/anchore/anchore_whitelist.json +++ b/setup/anchore/anchore_whitelist.json @@ -153,6 +153,11 @@ "gate": "vulnerabilities", "trigger_id": "CVE-2022-23221+*", "id": "rule13" + }, + { + "gate": "vulnerabilities", + "trigger_id": "GHSA-3x8x-79m2-3w2w+*", + "id": "rule14" } ], "name": "Global Whitelist", diff --git a/setup/harbor/99-one-step-install-harbor.sh b/setup/harbor/99-one-step-install-harbor.sh index 84022d1..55e0b20 100755 --- a/setup/harbor/99-one-step-install-harbor.sh +++ b/setup/harbor/99-one-step-install-harbor.sh @@ -64,7 +64,7 @@ export HARBOR_IP=`curl -sq http://checkip.amazonaws.com` export HARBOR_ADMIN_PWD=`tr -cd '[:alnum:]' < /dev/urandom | fold -w30 | head -n1` export HARBOR_NODEPORT=30443 -helm install harbor-registry harbor/harbor --version 1.10.2 \ +helm install harbor-registry harbor/harbor --version 1.12.0 \ -n harbor \ --set expose.type=nodePort \ --set expose.nodePort.ports.https.nodePort=${HARBOR_NODEPORT} \ @@ -95,6 +95,12 @@ do kubectl get deploy -n harbor done + +#export HARBOR_IP=`harbor.example.com` +#export HARBOR_ADMIN_PWD=`Suse123!` +#export HARBOR_NODEPORT=30443 + + # save the harbor credential for use at later stage echo "export HARBOR_URL=${HARBOR_IP}:${HARBOR_NODEPORT}" > myharbor.sh echo "export HARBOR_USR=admin" >> myharbor.sh diff --git a/setup/jenkins/99-one-step-install-jenkins.sh b/setup/jenkins/99-one-step-install-jenkins.sh index 86879bf..eab5852 100755 --- a/setup/jenkins/99-one-step-install-jenkins.sh +++ b/setup/jenkins/99-one-step-install-jenkins.sh @@ -60,7 +60,7 @@ helm search repo jenkinsci echo Customize jenkins-values.yaml sed "s/HARBOR_URL/$HARBOR_URL/g" jenkins-values-template.yaml > my-jenkins-values.yaml -helm install jenkins jenkinsci/jenkins --version 4.2.17 -n jenkins -f my-jenkins-values.yaml +helm install jenkins jenkinsci/jenkins --version 4.3.22 -n jenkins -f my-jenkins-values.yaml echo "Your Jenkins instance is provisioning...." while [ `kubectl get sts -n jenkins | grep 1/1 | wc -l` -ne 1 ] diff --git a/setup/jenkins/jenkins-values-template-smee.yaml b/setup/jenkins/jenkins-values-template-smee.yaml new file mode 100644 index 0000000..70d82c2 --- /dev/null +++ b/setup/jenkins/jenkins-values-template-smee.yaml @@ -0,0 +1,53 @@ +serviceAccount: + create: false + name: jenkins +controller: + image: "HARBOR_URL/library/myjenkins" + tag: "v1.0" + imagePullPolicy: "Always" + installPlugins: false + serviceType: NodePort + # jenkinsUrl: jenkins.suse.lab + # jenkinsUrlProtocol: https + resources: + requests: + cpu: "250m" + memory: "1024Mi" + limits: + cpu: "2000m" + memory: "2048Mi" + sidecars: + configAutoReload: + enabled: false + other: + - name: smee + image: docker.io/twalter/smee-client:1.0.2 + args: ["--port", "{{ .Values.controller.servicePort }}", "--path", "/github-webhook/", "--url", "https://smee.io/FqIskMikN91QAv7"] + resources: + limits: + cpu: 50m + memory: 128Mi + requests: + cpu: 10m + memory: 32Mi + prometheus: + enabled: false + # Additional labels to add to the ServiceMonitor object + serviceMonitorAdditionalLabels: {} + # Set a custom namespace where to deploy ServiceMonitor resource + # serviceMonitorNamespace: monitoring + scrapeInterval: 60s + # This is the default endpoint used by the prometheus plugin + scrapeEndpoint: /prometheus + # Additional labels to add to the PrometheusRule object + alertingRulesAdditionalLabels: {} + # An array of prometheus alerting rules + # See here: https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/ + # The `groups` root object is added by default, simply add the rule entries + alertingrules: [] + # Set a custom namespace where to deploy PrometheusRule resource + prometheusRuleNamespace: "" +persistence: + accessMode: "ReadWriteMany" + storageClass: "longhorn" + diff --git a/setup/jenkins/jenkins-values-template.yaml b/setup/jenkins/jenkins-values-template.yaml index 8f18e36..bb92a28 100644 --- a/setup/jenkins/jenkins-values-template.yaml +++ b/setup/jenkins/jenkins-values-template.yaml @@ -50,4 +50,3 @@ controller: persistence: accessMode: "ReadWriteMany" storageClass: "longhorn" - diff --git a/setup/jenkins/plugins.txt b/setup/jenkins/plugins.txt index 4e4bc42..fa3ba72 100644 --- a/setup/jenkins/plugins.txt +++ b/setup/jenkins/plugins.txt @@ -15,6 +15,6 @@ prometheus blueocean sonar jacoco -anchore-container-scanner +neuvector-vulnerability-scanner pipeline-maven junit diff --git a/setup/longhorn/99-one-step-install-longhorn.sh b/setup/longhorn/99-one-step-install-longhorn.sh index 4f93eaf..b4c3f37 100755 --- a/setup/longhorn/99-one-step-install-longhorn.sh +++ b/setup/longhorn/99-one-step-install-longhorn.sh @@ -10,10 +10,10 @@ export KUBECONFIG=$HOME/.kube/devsecops.cfg helm repo add longhorn https://charts.longhorn.io helm repo update -helm install longhorn longhorn/longhorn \ +helm upgrade --install longhorn longhorn/longhorn \ --set persistence.defaultClassReplicaCount=1 \ --set persistence.reclaimPolicy=Delete \ - --version=1.4.0 \ + --version=1.4.1 \ --namespace longhorn-system \ --create-namespace diff --git a/setup/neuvector/99-one-step-install-neuvector.sh b/setup/neuvector/99-one-step-install-neuvector.sh new file mode 100644 index 0000000..f0d9536 --- /dev/null +++ b/setup/neuvector/99-one-step-install-neuvector.sh @@ -0,0 +1,52 @@ +#! /bin/bash + +# Check if devsecops.cfg file exists +if [ ! -f $HOME/.kube/devsecops.cfg ]; then + echo "Please copy the kubeconfig file of Rancher devsecops cluster into $HOME/kube/devsecops.cfg file before running this script." + exit +fi +export KUBECONFIG=$HOME/.kube/devsecops.cfg + +# check if the longhorn has been installed +if [ `kubectl get sc | grep default | wc -l` -ne 1 ]; then + echo "Please deploy longhorn on devsecops cluster before running this script." + exit +fi + +helm repo add neuvector https://neuvector.github.io/neuvector-helm/ +helm repo update +helm search repo neuvector/core + + +helm install neuvector neuvector/core \ + --create-namespace \ + -n neuvector \ + --set tag=5.1.2 \ + --set k3s.enabled=true \ + --set manager.svc.type='NodePort' + + +echo "Your NeuVector instance is provisioning...." +while [ `kubectl get deploy -n neuvector | grep 1/1 | wc -l` -ne 6 ] +do + sleep 10 + echo "Wait while neuvector is still provisioning..." + kubectl get deploy -n neuvector +done + +# Get initial password for anchore +ANCHORE_PWD=$(kubectl get secret --namespace anchore anchore-anchore-engine-admin-pass -o jsonpath="{.data.ANCHORE_ADMIN_PASSWORD}" | base64 --decode; echo) + +echo +echo "Your neuvector is now successfully provisioned." > $HOME/myanchore.txt +echo "URL: http://anchore-anchore-engine-api.anchore.svc.cluster.local:8228/v1/" >> $HOME/myanchore.txt +echo "User: admin" >> $HOME/myanchore.txt +echo "Password: $ANCHORE_PWD" >> $HOME/myanchore.txt +cat $HOME/myanchore.txt + + +ANCHORE_CLI_USER=admin +ANCHORE_CLI_PASS=admin +ANCHORE_CLI_URL=http://anchore-anchore-engine-api.anchore.svc.cluster.local:8228/v1/ + + diff --git a/setup/rancher/01-install-k8s-tools.sh b/setup/rancher/01-install-k8s-tools.sh index ae8f1c3..26e6c7d 100755 --- a/setup/rancher/01-install-k8s-tools.sh +++ b/setup/rancher/01-install-k8s-tools.sh @@ -3,9 +3,7 @@ # Install Kubernetes tools echo "Installing Kubernetes Client Tools - kubectl and helm ..." -curl -sLS https://dl.get-arkade.dev | sh -sudo mv arkade /usr/local/bin/arkade -sudo ln -sf /usr/local/bin/arkade /usr/local/bin/ark +curl -sLS https://get.arkade.dev | sudo sh ark get helm sudo mv /home/ec2-user/.arkade/bin/helm /usr/local/bin/ diff --git a/setup/rancher/99-one-step-install-rancher.sh b/setup/rancher/99-one-step-install-rancher.sh index 0385bcc..79b7a3f 100755 --- a/setup/rancher/99-one-step-install-rancher.sh +++ b/setup/rancher/99-one-step-install-rancher.sh @@ -3,9 +3,7 @@ # Install Kubernetes tools echo "Installing Kubernetes Client Tools - kubectl and helm ..." -curl -sLS https://dl.get-arkade.dev | sh -sudo mv arkade /usr/local/bin/arkade -sudo ln -sf /usr/local/bin/arkade /usr/local/bin/ark +curl -sLS https://get.arkade.dev | sudo sh ark get helm sudo mv /home/ec2-user/.arkade/bin/helm /usr/local/bin/ @@ -21,8 +19,8 @@ echo "Install Rancher Server using helm chart on RKE2 ..." source $HOME/mylab_rancher_version.sh -echo "Install RKE2 v1.24 ..." -sudo bash -c 'curl -sfL https://get.rke2.io | INSTALL_RKE2_CHANNEL="v1.24" sh -' +echo "Install RKE2 v1.25 ..." +sudo bash -c 'curl -sfL https://get.rke2.io | INSTALL_RKE2_CHANNEL="v1.25" sh -' sudo mkdir -p /etc/rancher/rke2 sudo bash -c 'echo "write-kubeconfig-mode: \"0644\"" > /etc/rancher/rke2/config.yaml' sudo systemctl enable rke2-server.service @@ -80,6 +78,7 @@ helm install rancher rancher-latest/rancher \ --namespace cattle-system \ --set hostname=$RANCHER_FQDN \ --set replicas=1 \ + --set global.cattle.psp.enabled=false \ --version ${RANCHER_VERSION} --devel \ --create-namespace diff --git a/setup/sonarqube/sonarqube-values.yaml b/setup/sonarqube/sonarqube-values.yaml index 3e0a378..a7f4fb1 100644 --- a/setup/sonarqube/sonarqube-values.yaml +++ b/setup/sonarqube/sonarqube-values.yaml @@ -1,6 +1,6 @@ image: repository: sonarqube - tag: 8.9.9-community + tag: lts-community pullPolicy: IfNotPresent # If using a private repository, the name of the imagePullSecret to use # pullSecret: my-repo-secret diff --git a/startlab.sh b/startlab.sh index 37ff52a..6ce881a 100755 --- a/startlab.sh +++ b/startlab.sh @@ -60,7 +60,7 @@ check_sysreq; export VM_PREFIX=suse0908 echo "export VM_PREFIX=$VM_PREFIX" > mylab_vm_prefix.sh -export RANCHER_VERSION=v2.6.9 +export RANCHER_VERSION=v2.7.3 echo "export RANCHER_VERSION=$RANCHER_VERSION" > mylab_rancher_version.sh title="Select Your Preferred AWS Environment to run your lab:" @@ -197,12 +197,13 @@ done # upload files to be deployed onto devsecops cluster echo "Upload files to be executed onto devsecops cluster into harbor instance ..." HARBOR_IP=`get-vm-public-ip $VM_PREFIX-harbor` -ssh $SSH_OPTS -i mylab.key ec2-user@$HARBOR_IP mkdir -p devsecops/{jenkins,sonarqube,anchore,longhorn} +ssh $SSH_OPTS -i mylab.key ec2-user@$HARBOR_IP mkdir -p devsecops/{jenkins,sonarqube,neuvector,longhorn} scp $SSH_OPTS -i mylab.key mylab_vm_list.txt ec2-user@$HARBOR_IP:~ scp $SSH_OPTS -i mylab.key mylab_vm_prefix.sh ec2-user@$HARBOR_IP:~ scp $SSH_OPTS -i mylab.key setup/jenkins/*.* ec2-user@$HARBOR_IP:~/devsecops/jenkins scp $SSH_OPTS -i mylab.key setup/sonarqube/*.* ec2-user@$HARBOR_IP:~/devsecops/sonarqube -scp $SSH_OPTS -i mylab.key setup/anchore/*.* ec2-user@$HARBOR_IP:~/devsecops/anchore +#scp $SSH_OPTS -i mylab.key setup/anchore/*.* ec2-user@$HARBOR_IP:~/devsecops/anchore +scp $SSH_OPTS -i mylab.key setup/neuvector/*.* ec2-user@$HARBOR_IP:~/devsecops/neuvector scp $SSH_OPTS -i mylab.key setup/longhorn/*.* ec2-user@$HARBOR_IP:~/devsecops/longhorn