.gitea/workflows/delpoy.yml aktualisiert
Deploy / security_scan (push) Failing after 19s
Deploy / code_scan (push) Failing after 19s
Deploy / deploy (push) Has been skipped

This commit is contained in:
2026-05-20 17:27:09 +00:00
parent 11d26dfe8b
commit 7a7e0bd185
+426 -19
View File
@@ -2,15 +2,243 @@ name: Deploy
on:
push:
branches: [main]
branches:
- main
jobs:
security_scan:
runs-on: ubuntu-latest
env:
GIT_REPO: jakach/jakach-login
GIT_BRANCH: main
GIT_USER: ${{ vars.GIT_USER }}
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
SECURITY_SCAN_ENABLED: ${{ vars.SECURITY_SCAN_ENABLED }}
TRIVY_SEVERITY: HIGH,CRITICAL
steps:
- name: Scan Docker images for vulnerabilities
run: |
set -Eeuo pipefail
case "${SECURITY_SCAN_ENABLED:-true}" in
false|False|FALSE|0|no|No|NO|off|Off|OFF)
echo "Security scan disabled by SECURITY_SCAN_ENABLED=${SECURITY_SCAN_ENABLED}"
exit 0
;;
esac
: "${GIT_USER:?GIT_USER is required}"
: "${GIT_TOKEN:?GIT_TOKEN is required}"
if command -v apk >/dev/null 2>&1; then
apk add --no-cache ca-certificates curl git
elif command -v apt-get >/dev/null 2>&1; then
apt-get update
apt-get install -y ca-certificates curl git
elif command -v dnf >/dev/null 2>&1; then
dnf install -y ca-certificates curl git
elif command -v yum >/dev/null 2>&1; then
yum install -y ca-certificates curl git
else
echo "Unsupported package manager"
exit 1
fi
if ! command -v trivy >/dev/null 2>&1; then
mkdir -p "$HOME/.local/bin"
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
| sh -s -- -b "$HOME/.local/bin"
export PATH="$HOME/.local/bin:$PATH"
fi
GIT_HOST="${GIT_HOST:-git.jakach.ch}"
REPO_URL="https://${GIT_USER}:${GIT_TOKEN}@${GIT_HOST}/${GIT_REPO}"
git clone \
--branch "$GIT_BRANCH" \
"$REPO_URL" \
source
cd source
COMPOSE_FILE=""
for file in docker-compose.yml compose.yml compose.yaml; do
if [ -f "$file" ]; then
COMPOSE_FILE="$file"
break
fi
done
if [ -z "$COMPOSE_FILE" ]; then
echo "No docker compose file found"
exit 0
fi
if docker compose version >/dev/null 2>&1; then
docker compose -f "$COMPOSE_FILE" config --images > images.txt
else
awk '
/^[[:space:]]*image:[[:space:]]*/ {
sub(/^[[:space:]]*image:[[:space:]]*/, "")
gsub(/["\047]/, "")
print
}
' "$COMPOSE_FILE" > images.txt
fi
sort -u images.txt -o images.txt
if [ ! -s images.txt ]; then
echo "No Docker images found to scan"
exit 0
fi
TRIVY_IGNORE_ARGS=""
if [ -f cve_blacklist.txt ]; then
awk '
/^[[:space:]]*($|#)/ {
next
}
{
print $1
}
' cve_blacklist.txt > .trivyignore
if [ -s .trivyignore ]; then
TRIVY_IGNORE_ARGS="--ignorefile .trivyignore"
echo "Using CVE blacklist from cve_blacklist.txt"
fi
fi
echo "Scanning Docker images for ${TRIVY_SEVERITY} vulnerabilities:"
cat images.txt
failed=0
while IFS= read -r image; do
[ -n "$image" ] || continue
echo ""
echo "Scanning ${image}"
if ! trivy \
image \
--exit-code 1 \
--severity "${TRIVY_SEVERITY}" \
--ignore-unfixed \
${TRIVY_IGNORE_ARGS} \
--no-progress \
"${image}"; then
failed=1
fi
done < images.txt
if [ "$failed" -ne 0 ]; then
echo "WARNING: High or critical vulnerabilities were found in one or more Docker images. Deployment stopped."
exit 1
fi
echo "No high or critical vulnerabilities found"
code_scan:
runs-on: ubuntu-latest
env:
GIT_REPO: jakach/jakach-login
GIT_BRANCH: main
GIT_USER: ${{ vars.GIT_USER }}
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
CODE_SCAN_ENABLED: ${{ vars.CODE_SCAN_ENABLED }}
steps:
- name: Scan source code
run: |
set -Eeuo pipefail
case "${CODE_SCAN_ENABLED:-true}" in
false|False|FALSE|0|no|No|NO|off|Off|OFF)
echo "Code scan disabled by CODE_SCAN_ENABLED=${CODE_SCAN_ENABLED}"
exit 0
;;
esac
: "${GIT_USER:?GIT_USER is required}"
: "${GIT_TOKEN:?GIT_TOKEN is required}"
if command -v apk >/dev/null 2>&1; then
apk add --no-cache ca-certificates curl git python3 py3-pip
elif command -v apt-get >/dev/null 2>&1; then
apt-get update
apt-get install -y ca-certificates curl git python3 python3-pip python3-venv
elif command -v dnf >/dev/null 2>&1; then
dnf install -y ca-certificates curl git python3 python3-pip
elif command -v yum >/dev/null 2>&1; then
yum install -y ca-certificates curl git python3 python3-pip
else
echo "Unsupported package manager"
exit 1
fi
if ! command -v semgrep >/dev/null 2>&1; then
python3 -m venv "$HOME/.semgrep-venv"
. "$HOME/.semgrep-venv/bin/activate"
python3 -m pip install --upgrade pip
python3 -m pip install semgrep
fi
if ! command -v trivy >/dev/null 2>&1; then
mkdir -p "$HOME/.local/bin"
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
| sh -s -- -b "$HOME/.local/bin"
export PATH="$HOME/.local/bin:$PATH"
fi
GIT_HOST="${GIT_HOST:-git.jakach.ch}"
REPO_URL="https://${GIT_USER}:${GIT_TOKEN}@${GIT_HOST}/${GIT_REPO}"
git clone \
--branch "$GIT_BRANCH" \
"$REPO_URL" \
source
cd source
semgrep scan \
--config p/default \
--error \
--metrics=off
trivy fs \
--scanners vuln,misconfig,secret \
--exit-code 1 \
--severity HIGH,CRITICAL \
--ignore-unfixed \
--no-progress \
.
deploy:
runs-on: ubuntu-latest
needs:
- security_scan
- code_scan
env:
GIT_REPO: jakach/jakach-login
GIT_BRANCH: main
APP_NAME: template
APP_DOMAIN: auth.jakach.ch
APP_PORT: 447
steps:
- name: Install SSH client
- name: Install dependencies
run: |
set -e
if command -v apk >/dev/null 2>&1; then
apk add --no-cache openssh-client git bash
elif command -v apt-get >/dev/null 2>&1; then
@@ -21,55 +249,234 @@ jobs:
elif command -v yum >/dev/null 2>&1; then
yum install -y openssh-clients git bash
else
echo "No supported package manager found"
echo "Unsupported package manager"
exit 1
fi
- name: Run deploy
- name: Deploy application
env:
SSH_KEY: ${{ secrets.SSH_KEY }}
SSH_USER: ${{ vars.SSH_USER }}
SSH_IP: ${{ vars.SSH_IP }}
GIT_USER: ${{ vars.GIT_USER }}
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
APP_DIR: /home/deploy/my-app
GIT_REPO: Jakach/my-app.git
GIT_BRANCH: main
run: |
cat > deploy.sh <<'EOF'
cat > deploy.sh <<'OUTER_EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
: "${SSH_KEY:?SSH_KEY is required}"
: "${SSH_USER:?SSH_USER is required}"
: "${SSH_IP:?SSH_IP is required}"
: "${GIT_USER:?GIT_USER is required}"
: "${GIT_TOKEN:?GIT_TOKEN is required}"
APP_DIR="/srv/systems/jakach-login"
GIT_HOST="${GIT_HOST:-git.jakach.ch}"
GIT_REPO="jakach/jakach-login.git"
GIT_BRANCH="${GIT_BRANCH:-main}"
REPO_NAME="$(basename "$GIT_REPO")"
APP_DIR="/srv/systems/${REPO_NAME}"
mkdir -p ~/.ssh
chmod 700 ~/.ssh
printf '%s\n' "$SSH_KEY" | tr -d '\r' > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H "$SSH_IP" >> ~/.ssh/known_hosts 2>/dev/null || true
ssh -i ~/.ssh/deploy_key \
ssh \
-i ~/.ssh/deploy_key \
-o StrictHostKeyChecking=yes \
-o IdentitiesOnly=yes \
"$SSH_USER@$SSH_IP" \
"export APP_DIR='$APP_DIR' GIT_HOST='$GIT_HOST' GIT_REPO='$GIT_REPO' GIT_BRANCH='$GIT_BRANCH' GIT_USER='$GIT_USER' GIT_TOKEN='$GIT_TOKEN'; bash -s" <<'REMOTE'
"
export \
APP_NAME='${APP_NAME}' \
APP_DOMAIN='${APP_DOMAIN}' \
APP_PORT='${APP_PORT}' \
APP_DIR='${APP_DIR}' \
GIT_HOST='${GIT_HOST}' \
GIT_REPO='${GIT_REPO}' \
GIT_BRANCH='${GIT_BRANCH}' \
GIT_USER='${GIT_USER}' \
GIT_TOKEN='${GIT_TOKEN}';
bash -s
" <<'REMOTE_EOF'
set -Eeuo pipefail
REPO_URL="https://${GIT_USER}:${GIT_TOKEN}@${GIT_HOST}/${GIT_REPO}"
PROXY_DIR="/srv/systems/proxy"
NGINX_CONF="${PROXY_DIR}/nginx_conf/nginx.conf"
GET_CERT_SCRIPT="${PROXY_DIR}/get_cert.sh"
RENEW_SCRIPT="${PROXY_DIR}/renew_cert.sh"
FIRST_DEPLOY=0
PROXY_RESTART_REQUIRED=0
# --------------------------------------------------
# Clone repository if missing
# --------------------------------------------------
if [ ! -d "$APP_DIR/.git" ]; then
echo "Repository missing, cloning..."
FIRST_DEPLOY=1
mkdir -p "$(dirname "$APP_DIR")"
git clone \
--branch "$GIT_BRANCH" \
"$REPO_URL" \
"$APP_DIR"
fi
# --------------------------------------------------
# Update repository
# --------------------------------------------------
cd "$APP_DIR"
git remote set-url origin "https://${GIT_USER}:${GIT_TOKEN}@${GIT_HOST}/${GIT_REPO}"
git remote set-url origin "$REPO_URL"
git fetch origin "$GIT_BRANCH"
git checkout "$GIT_BRANCH"
git pull origin "$GIT_BRANCH"
docker compose down
docker compose up -d --build
REMOTE
EOF
# --------------------------------------------------
# Create nginx reverse proxy entry
# --------------------------------------------------
if [ "$FIRST_DEPLOY" -eq 1 ]; then
if ! grep -q "proxy_pass http://192.168.1.109:${APP_PORT}/;" "$NGINX_CONF"; then
echo "Creating nginx entry..."
PROXY_RESTART_REQUIRED=1
cat >> "$NGINX_CONF" <<NGINXEOF
# ---------------------
# ${APP_NAME} Service
# ---------------------
server {
server_tokens off;
listen 443 ssl;
server_name ${APP_DOMAIN};
ssl_certificate /etc/nginx/certs/${APP_NAME}.fullchain.pem;
ssl_certificate_key /etc/nginx/certs/${APP_NAME}.privkey.pem;
if (\$allowed_country = no) {
return 403;
}
location / {
proxy_pass http://192.168.1.109:${APP_PORT}/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
}
}
NGINXEOF
else
echo "Nginx entry already exists"
fi
# --------------------------------------------------
# Add domain to get_cert.sh
# --------------------------------------------------
if ! grep -q "\"${APP_DOMAIN}\"" "$GET_CERT_SCRIPT"; then
echo "Adding domain to get_cert.sh"
sed -i "/DOMAINS=(/a\ \"${APP_DOMAIN}\"" "$GET_CERT_SCRIPT"
PROXY_RESTART_REQUIRED=1
fi
# --------------------------------------------------
# Create certificate if missing
# --------------------------------------------------
if [ ! -d "/etc/letsencrypt/live/${APP_DOMAIN}" ]; then
echo "Creating certificate..."
sudo certbot certonly \
--standalone \
--non-interactive \
--agree-tos \
-m admin@jakach.ch \
-d "${APP_DOMAIN}"
PROXY_RESTART_REQUIRED=1
else
echo "Certificate already exists"
fi
# --------------------------------------------------
# Update renew_cert.sh
# --------------------------------------------------
if ! grep -q "${APP_DOMAIN}/privkey.pem" "$RENEW_SCRIPT"; then
echo "Updating renew_cert.sh"
cat >> "$RENEW_SCRIPT" <<CERTEOF
cp /etc/letsencrypt/live/${APP_DOMAIN}/privkey.pem certs/${APP_NAME}.privkey.pem
cp /etc/letsencrypt/live/${APP_DOMAIN}/fullchain.pem certs/${APP_NAME}.fullchain.pem
CERTEOF
PROXY_RESTART_REQUIRED=1
fi
chmod +x "$RENEW_SCRIPT"
# --------------------------------------------------
# Make renew non-interactive
# --------------------------------------------------
sed -i 's/certbot renew$/certbot renew -n/' "$RENEW_SCRIPT" || true
# --------------------------------------------------
# Renew certs + restart proxy
# --------------------------------------------------
if [ "$PROXY_RESTART_REQUIRED" -eq 1 ]; then
cd "$PROXY_DIR"
sudo bash /srv/systems/proxy/renew_cert.sh
docker compose down || true
docker compose up -d --build
else
echo "Proxy already configured, skipping certificate renewal and proxy restart"
fi
else
echo "Existing deployment, skipping proxy setup, certificate renewal and proxy restart"
fi
# --------------------------------------------------
# Deploy app
# --------------------------------------------------
cd "$APP_DIR"
if [ -f docker-compose.yml ] || [ -f compose.yml ] || [ -f compose.yaml ]; then
echo "Deploying docker stack..."
docker compose down || true
docker compose up -d --build
else
echo "No docker compose file found"
fi
echo "Deployment complete"
REMOTE_EOF
OUTER_EOF
chmod +x deploy.sh
./deploy.sh
./deploy.sh