#
# Copyright (C) 2020-2026 Lin Song <linsongui@gmail.com>
#
# This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
# Unported License: http://creativecommons.org/licenses/by-sa/3.0/
#
# Attribution required: please include my name in any derivative and let me
# know how you have improved it!

name: test_set_1

on: workflow_call

jobs:
  test_set_1:
    runs-on: ubuntu-22.04
    if: github.repository_owner == 'hwdsl2'
    strategy:
      matrix:
        os_version: ["centos:10s", "centos:9s", "rockylinux:8", "almalinux:10", "almalinux:9", "almalinux:8", "oraclelinux:10", "oraclelinux:9", "oraclelinux:8"]
      fail-fast: false
    env:
      OS_VERSION: ${{ matrix.os_version }}
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false
      - name: Build
        run: |
          mkdir -p "$GITHUB_WORKSPACE/testing/${OS_VERSION//:}"
          cd "$GITHUB_WORKSPACE/testing/${OS_VERSION//:}"

          mkdir -p scripts/extras
          ls -ld "$GITHUB_WORKSPACE/vpnsetup.sh"
          cp -f "$GITHUB_WORKSPACE"/*.sh scripts/
          cp -f "$GITHUB_WORKSPACE"/extras/*.sh scripts/extras/

          cat > run.sh <<'EOF'
          #!/bin/bash
          set -eEx

          log1=/var/log/secure
          log2=/var/log/messages

          trap 'catch $? $LINENO' ERR

          catch() {
            echo "Error $1 occurred on line $2."
            cat -n -- "$0" | tail -n+"$(($2 - 3))" | head -n7
            exit 1
          }

          restart_ipsec() {
            if [ -f /etc/oracle-release ]; then
              sleep 3
            fi
            systemctl restart ipsec
            if grep -qs -i stream /etc/redhat-release \
              && grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
              sleep 5
              return 0
            fi
            echo "Waiting for IPsec to restart."
            count=0
            while ! grep -q "pluto\[$(cat /var/run/pluto/pluto.pid)\]: listening for IKE messages" "$log1"; do
              [ "$count" -ge "30" ] && { echo "IPsec failed to start."; exit 1; }
              count=$((count+1))
              printf '%s' '.'
              sleep 0.5
            done
            echo
          }

          restart_fail2ban() {
            rm -f /var/log/fail2ban.log
            systemctl restart fail2ban
            echo "Waiting for Fail2ban to restart."
            count=0
            while ! grep -qs -E "Jail '(sshd?|ssh-iptables)' started" /var/log/fail2ban.log; do
              [ "$count" -ge "30" ] && { echo "Fail2ban failed to start."; exit 1; }
              count=$((count+1))
              printf '%s' '.'
              sleep 0.5
            done
            echo
          }

          cd /opt/src
          if grep -qs -i rocky /etc/redhat-release; then
            yum -y -q update
          fi
          yum -y -q install wget rsyslog
          if grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
            if grep -qs -i rocky /etc/redhat-release \
              || grep -qs -i alma /etc/redhat-release; then
              yum -y -q install diffutils
            fi
          fi
          if ! grep -qs -i stream /etc/redhat-release \
            || ! grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
            systemctl start rsyslog
          fi

          cp -f /opt/src/scripts/vpnsetup.sh .
          cp -f /opt/src/scripts/extras/vpnuninstall.sh ./vpnunst.sh
          sed -i -e '/curl /a sed -i "/swan_ver_latest=/s/^/#/" "$tmpdir/vpn.sh"' \
            -e '/curl /a sed -i \x27/status=0/a sed -i "/swan_ver_latest=/s/^/#/" /opt/src/ikev2.sh\x27 "$tmpdir/vpn.sh"' \
            vpnsetup.sh

          sh vpnsetup.sh

          systemctl restart xl2tpd
          restart_ipsec
          if ! grep -qsE 'release (9|1[0-9])' /etc/oracle-release; then
            if ! grep -qs -i stream /etc/redhat-release \
              || ! grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
              restart_fail2ban
              cat /var/log/fail2ban.log
            fi
          fi

          netstat -anpu | grep pluto
          netstat -anpu | grep xl2tpd
          if grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
            nft list ruleset
            nft list ruleset | grep -q '192\.168\.42\.0/24'
            nft list ruleset | grep -q '192\.168\.43\.0/24'
          else
            iptables -nvL
            iptables -nvL | grep -q 'ppp+'
            iptables -nvL | grep -q '192\.168\.43\.0/24'
            iptables -nvL -t nat
            iptables -nvL -t nat | grep -q '192\.168\.42\.0/24'
            iptables -nvL -t nat | grep -q '192\.168\.43\.0/24'
          fi
          if ! grep -qs -i stream /etc/redhat-release \
            || ! grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
            grep pluto "$log1"
            grep xl2tpd "$log2"
          fi
          ipsec status
          ipsec status | grep -q l2tp-psk
          ipsec status | grep -q xauth-psk
          ipsec status | grep -q ikev2-cp

          ls -ld /etc/ipsec.d/vpnclient.mobileconfig
          ls -ld /etc/ipsec.d/vpnclient.sswan
          ls -ld /etc/ipsec.d/vpnclient.p12

          ls -l /usr/bin/ikev2.sh
          ls -l /usr/bin/addvpnuser.sh
          ls -l /usr/bin/delvpnuser.sh
          ls -l /opt/src/ikev2.sh
          ls -l /opt/src/addvpnuser.sh
          ls -l /opt/src/delvpnuser.sh

          bash vpnunst.sh <<ANSWERS
          y
          ANSWERS
          rm -f /etc/ipsec.d/vpnclient*
          if grep -qs -i stream /etc/redhat-release \
            || grep -qsE 'release (8|9|1[0-9])' /etc/oracle-release; then
            mkdir /etc/xl2tpd
          fi
          if grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
            if grep -qs -i rocky /etc/redhat-release \
              || grep -qs -i alma /etc/redhat-release; then
              mkdir /etc/xl2tpd
            fi
          fi

          cp -f /opt/src/scripts/vpnsetup_centos.sh ./vpnsetup.sh
          sed -i -e '/swan_ver_latest=/s/^/#/' \
            -e '/status=0/a sed -i "/swan_ver_latest=/s/^/#/" /opt/src/ikev2.sh' \
            vpnsetup.sh

          bash vpnsetup.sh

          VPN_IPSEC_PSK='your_ipsec_pre_shared_key' \
          VPN_USER='your_vpn_username' \
          VPN_PASSWORD='your_vpn_password' \
          VPN_DNS_SRV1='1.1.1.1' \
          VPN_DNS_SRV2='1.0.0.1' \
          bash vpnsetup.sh

          systemctl restart xl2tpd
          restart_ipsec

          netstat -anpu | grep pluto
          netstat -anpu | grep xl2tpd
          if grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
            nft list ruleset
            nft list ruleset | grep -q '192\.168\.42\.0/24'
            nft list ruleset | grep -q '192\.168\.43\.0/24'
          else
            iptables -nvL
            iptables -nvL | grep -q 'ppp+'
            iptables -nvL | grep -q '192\.168\.43\.0/24'
            iptables -nvL -t nat
            iptables -nvL -t nat | grep -q '192\.168\.42\.0/24'
            iptables -nvL -t nat | grep -q '192\.168\.43\.0/24'
          fi
          ipsec status
          ipsec status | grep -q l2tp-psk
          ipsec status | grep -q xauth-psk
          ipsec status | grep -q ikev2-cp

          grep -q "your_ipsec_pre_shared_key" /etc/ipsec.secrets
          grep -q "your_vpn_username" /etc/ppp/chap-secrets
          grep -q "your_vpn_password" /etc/ppp/chap-secrets
          grep -q "your_vpn_username" /etc/ipsec.d/passwd
          grep -q 'modecfgdns="1.1.1.1 1.0.0.1"' /etc/ipsec.conf
          grep -q 'ms-dns 1.1.1.1' /etc/ppp/options.xl2tpd
          grep -q 'ms-dns 1.0.0.1' /etc/ppp/options.xl2tpd

          ls -ld /etc/ipsec.d/vpnclient.mobileconfig
          ls -ld /etc/ipsec.d/vpnclient.sswan
          ls -ld /etc/ipsec.d/vpnclient.p12

          ls -l /usr/bin/ikev2.sh
          ls -l /usr/bin/addvpnuser.sh
          ls -l /usr/bin/delvpnuser.sh
          ls -l /opt/src/ikev2.sh
          ls -l /opt/src/addvpnuser.sh
          ls -l /opt/src/delvpnuser.sh

          rm -f /usr/bin/ikev2.sh /opt/src/ikev2.sh
          rm -f /etc/ipsec.d/vpnclient*

          cp -f /opt/src/scripts/extras/ikev2setup.sh ./ikev2.sh # hwdsl2
          sed -i '/swan_ver_latest=/s/^/#/' ikev2.sh

          bash ikev2.sh --removeikev2 <<ANSWERS
          y
          ANSWERS

          restart_ipsec

          bash ikev2.sh <<ANSWERS







          ANSWERS

          grep -q 'modecfgdns="8.8.8.8 8.8.4.4"' /etc/ipsec.d/ikev2.conf
          ls -ld /etc/ipsec.d/vpnclient.mobileconfig
          ls -ld /etc/ipsec.d/vpnclient.sswan
          ls -ld /etc/ipsec.d/vpnclient.p12
          pk12util -W "" -l /etc/ipsec.d/vpnclient.p12
          pk12util -W "" -l /etc/ipsec.d/vpnclient.p12 | grep AES-256 && exit 1

          restart_ipsec
          if ! grep -qs -i stream /etc/redhat-release \
            || ! grep -qsE 'release (9|1[0-9])' /etc/redhat-release; then
            grep pluto "$log1" | tail -n 20
          fi
          ipsec status | grep -q ikev2-cp

          bash ikev2.sh <<ANSWERS
          1
          invalidclient:
          vpnclient
          vpnclient2

          ANSWERS

          ls -ld /etc/ipsec.d/vpnclient2.mobileconfig
          ls -ld /etc/ipsec.d/vpnclient2.sswan
          ls -ld /etc/ipsec.d/vpnclient2.p12
          pk12util -W "" -l /etc/ipsec.d/vpnclient2.p12
          pk12util -W "" -l /etc/ipsec.d/vpnclient2.p12 | grep AES-256 && exit 1

          rm -f /etc/ipsec.d/vpnclient2*
          bash ikev2.sh <<ANSWERS
          2
          nonexistclient
          vpnclient2
          ANSWERS

          ls -ld /etc/ipsec.d/vpnclient2.mobileconfig
          ls -ld /etc/ipsec.d/vpnclient2.sswan
          ls -ld /etc/ipsec.d/vpnclient2.p12
          pk12util -W "" -l /etc/ipsec.d/vpnclient2.p12
          pk12util -W "" -l /etc/ipsec.d/vpnclient2.p12 | grep AES-256 && exit 1

          bash ikev2.sh <<ANSWERS
          3
          ANSWERS

          bash ikev2.sh <<ANSWERS | grep -i "2 clients"
          3
          ANSWERS

          bash ikev2.sh <<ANSWERS
          4
          nonexistclient
          vpnclient2
          y
          ANSWERS

          bash ikev2.sh <<ANSWERS 2>&1 | grep -i "abort"
          4
          vpnclient2

          ANSWERS

          bash ikev2.sh <<ANSWERS
          5
          vpnclient2
          y
          ANSWERS

          bash ikev2.sh <<ANSWERS | grep -i "1 client"
          3
          ANSWERS

          bash ikev2.sh <<ANSWERS 2>&1 | grep -i "abort"
          2
          vpnclient2

          ANSWERS

          bash ikev2.sh <<ANSWERS
          100
          7
          ANSWERS

          bash ikev2.sh <<ANSWERS 2>&1 | grep -i "abort"
          6

          ANSWERS

          bash ikev2.sh <<ANSWERS
          6
          y
          ANSWERS

          restart_ipsec
          ls -ld /etc/ipsec.d/ikev2.conf && exit 1
          ipsec status | grep -q l2tp-psk
          ipsec status | grep -q xauth-psk
          ipsec status | grep -q ikev2-cp && exit 1
          certutil -L -d sql:/etc/ipsec.d

          rm -f /etc/ipsec.d/vpnclient*

          VPN_DNS_SRV1=invaliddns \
          bash ikev2.sh --auto 2>&1 | grep -i "invalid"

          sed -i '/^include /d' /etc/ipsec.conf

          VPN_CLIENT_NAME=vpnclient1 \
          VPN_DNS_NAME=vpn.example.com \
          VPN_DNS_SRV1=1.1.1.1 \
          VPN_DNS_SRV2=1.0.0.1 \
          bash ikev2.sh --auto

          grep -q 'leftid=@vpn.example.com' /etc/ipsec.d/ikev2.conf
          grep -q 'modecfgdns="1.1.1.1 1.0.0.1"' /etc/ipsec.d/ikev2.conf
          ls -ld /etc/ipsec.d/vpnclient1.mobileconfig
          ls -ld /etc/ipsec.d/vpnclient1.sswan
          ls -ld /etc/ipsec.d/vpnclient1.p12
          grep -q 'vpn.example.com' /etc/ipsec.d/vpnclient1.mobileconfig
          grep -q 'vpn.example.com' /etc/ipsec.d/vpnclient1.sswan

          restart_ipsec
          ipsec status | grep -q ikev2-cp

          bash ikev2.sh --addclient invalidclient: 2>&1 | grep -i "invalid"
          bash ikev2.sh --addclient vpnclient1 2>&1 | grep -i "already exists"

          bash ikev2.sh --addclient vpnclient2

          ls -ld /etc/ipsec.d/vpnclient2.mobileconfig
          ls -ld /etc/ipsec.d/vpnclient2.sswan
          ls -ld /etc/ipsec.d/vpnclient2.p12

          bash ikev2.sh --exportclient nonexistclient 2>&1 | grep -i "does not exist"

          rm -f /etc/ipsec.d/vpnclient2*
          bash ikev2.sh --exportclient vpnclient2

          ls -ld /etc/ipsec.d/vpnclient2.mobileconfig
          ls -ld /etc/ipsec.d/vpnclient2.sswan
          ls -ld /etc/ipsec.d/vpnclient2.p12

          bash ikev2.sh --addclient vpnclient2 --exportclient vpnclient2 2>&1 | grep -i "invalid"

          bash ikev2.sh --listclients | grep "vpnclient1 \+valid"
          bash ikev2.sh --listclients | grep "vpnclient2 \+valid"
          bash ikev2.sh --listclients | grep "2 clients"

          bash ikev2.sh --revokeclient nonexistclient 2>&1 | grep -i "does not exist"
          bash ikev2.sh --revokeclient vpnclient2 <<ANSWERS
          y
          ANSWERS

          bash ikev2.sh --listclients | grep "vpnclient2 \+revoked"
          ls -ld /etc/ipsec.d/vpnclient2.mobileconfig && exit 1
          ls -ld /etc/ipsec.d/vpnclient2.sswan && exit 1
          ls -ld /etc/ipsec.d/vpnclient2.p12 && exit 1

          bash ikev2.sh --revokeclient vpnclient2 2>&1 | grep -i "already been revoked"
          bash ikev2.sh --exportclient vpnclient2 2>&1 | grep -i "revoked"

          bash ikev2.sh --deleteclient nonexistclient 2>&1 | grep -i "does not exist"
          bash ikev2.sh --deleteclient vpnclient1 <<ANSWERS
          y
          ANSWERS

          bash ikev2.sh --listclients | grep "1 client"
          ls -ld /etc/ipsec.d/vpnclient1.mobileconfig && exit 1
          ls -ld /etc/ipsec.d/vpnclient1.sswan && exit 1
          ls -ld /etc/ipsec.d/vpnclient1.p12 && exit 1

          bash ikev2.sh -h 2>&1 | grep -i "usage:"
          bash ikev2.sh --invalidoption 2>&1 | grep -i "usage:"

          bash ikev2.sh --removeikev2 --exportclient vpnclient1 2>&1 | grep -i "invalid"
          bash ikev2.sh --removeikev2 <<ANSWERS
          y
          ANSWERS

          restart_ipsec
          rm -f /etc/ipsec.d/vpnclient*

          bash ikev2.sh <<ANSWERS
          y
          invalidfqdn
          vpn.example.com


          y
          invaliddns
          1.1.1.1
          invaliddns
          1.0.0.1
          y

          ANSWERS

          grep -q 'leftid=@vpn.example.com' /etc/ipsec.d/ikev2.conf
          grep -q 'modecfgdns="1.1.1.1 1.0.0.1"' /etc/ipsec.d/ikev2.conf
          restart_ipsec
          ipsec status | grep -q ikev2-cp

          config_file="/etc/ipsec.d/.vpnconfig"
          p12_pw=$(grep -s '^IKEV2_CONFIG_PASSWORD=.\+' "$config_file" | tail -n 1 | cut -f2- -d= | sed -e "s/^'//" -e "s/'$//")
          pk12util -W "$p12_pw" -l /etc/ipsec.d/vpnclient.p12
          pk12util -W "$p12_pw" -l /etc/ipsec.d/vpnclient.p12 | grep AES-256 && exit 1

          bash ikev2.sh --addclient vpnclient2
          pk12util -W "$p12_pw" -l /etc/ipsec.d/vpnclient2.p12
          pk12util -W "$p12_pw" -l /etc/ipsec.d/vpnclient2.p12 | grep AES-256 && exit 1

          bash ikev2.sh --exportclient vpnclient2
          pk12util -W "$p12_pw" -l /etc/ipsec.d/vpnclient2.p12
          pk12util -W "$p12_pw" -l /etc/ipsec.d/vpnclient2.p12 | grep AES-256 && exit 1

          bash ikev2.sh --removeikev2 <<ANSWERS
          y
          ANSWERS

          grep -qs '^IKEV2_CONFIG_PASSWORD=.\+' "$config_file" && exit 1
          restart_ipsec
          bash ikev2.sh <<ANSWERS

          invalidip
          1.2.3.4
          invalidclient:
          vpnclient1
          1000
          12
          y
          1.1.1.1



          ANSWERS

          grep -q 'leftid=1.2.3.4' /etc/ipsec.d/ikev2.conf
          grep -q 'modecfgdns=1.1.1.1' /etc/ipsec.d/ikev2.conf
          restart_ipsec
          ipsec status | grep -q ikev2-cp

          bash ikev2.sh --removeikev2 <<ANSWERS
          y
          ANSWERS

          restart_ipsec
          VPN_DNS_SRV1=1.1.1.1 \
          bash ikev2.sh --auto

          grep -q 'modecfgdns=1.1.1.1' /etc/ipsec.d/ikev2.conf
          restart_ipsec
          ipsec status | grep -q ikev2-cp

          bash ikev2.sh --removeikev2 <<ANSWERS
          y
          ANSWERS

          restart_ipsec
          bash ikev2.sh --auto

          grep -qs '^IKEV2_CONFIG_PASSWORD=.\+' "$config_file" && exit 1
          grep -q 'modecfgdns="8.8.8.8 8.8.4.4"' /etc/ipsec.d/ikev2.conf
          restart_ipsec
          ipsec status | grep -q ikev2-cp

          cp -f /opt/src/scripts/extras/vpnupgrade.sh ./vpnup.sh
          sed -i '/curl /a sed -i "/swan_ver_latest=/s/^/#/" "$tmpdir/vpnup.sh"' vpnup.sh

          ver=5.2
          sed -i "s/^SWAN_VER=.*/SWAN_VER=$ver/" vpnup.sh
          bash vpnup.sh <<ANSWERS

          ANSWERS
          restart_ipsec
          ipsec --version | grep "$ver"
          ipsec status | grep -q l2tp-psk
          ipsec status | grep -q xauth-psk
          ipsec status | grep -q ikev2-cp

          cp -f /opt/src/scripts/extras/vpnupgrade_centos.sh ./vpnup.sh
          sed -i '/swan_ver_latest=/s/^/#/' vpnup.sh

          ver=5.3
          bash vpnup.sh <<ANSWERS

          ANSWERS
          restart_ipsec
          ipsec --version | grep "$ver"
          ipsec status | grep -q l2tp-psk
          ipsec status | grep -q xauth-psk
          ipsec status | grep -q ikev2-cp

          bash ikev2.sh --removeikev2 <<ANSWERS
          y
          ANSWERS

          restart_ipsec
          ls -ld /etc/ipsec.d/ikev2.conf && exit 1
          ipsec status | grep -q l2tp-psk
          ipsec status | grep -q xauth-psk
          ipsec status | grep -q ikev2-cp && exit 1
          certutil -L -d sql:/etc/ipsec.d

          exit 0
          EOF

          if [ "$OS_VERSION" = "centos:9s" ]; then
            echo "FROM quay.io/centos/centos:stream9" > Dockerfile
          elif [ "$OS_VERSION" = "centos:10s" ]; then
            echo "FROM quay.io/centos/centos:stream10" > Dockerfile
          else
            echo "FROM $OS_VERSION" > Dockerfile
          fi

          cat >> Dockerfile <<'EOF'

          ENV container=docker
          WORKDIR /opt/src
          EOF

          if [ "$OS_VERSION" = "centos:9s" ] || [ "$OS_VERSION" = "centos:10s" ]; then
            echo "RUN yum -y -q install systemd" >> Dockerfile
          fi

          cat >> Dockerfile <<'EOF'
          RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ "$i" = \
          systemd-tmpfiles-setup.service ] || rm -f "$i"; done); \
          rm -f /lib/systemd/system/multi-user.target.wants/*; \
          rm -f /etc/systemd/system/*.wants/*; \
          rm -f /lib/systemd/system/local-fs.target.wants/*; \
          rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
          rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
          rm -f /lib/systemd/system/basic.target.wants/*; \
          rm -f /lib/systemd/system/anaconda.target.wants/*;

          COPY scripts/ /opt/src/scripts/
          COPY ./run.sh /opt/src/run.sh
          RUN chmod 755 /opt/src/run.sh

          VOLUME [ "/sys/fs/cgroup" ]

          CMD ["/sbin/init"]
          EOF
          cat Dockerfile
          cat run.sh
          docker build -t "${OS_VERSION//:}-test" .

      - name: Test
        run: |
          docker run -d --name "${OS_VERSION//:}-test-1" -v /sys/fs/cgroup:/sys/fs/cgroup:rw \
            --cgroupns=host --privileged "${OS_VERSION//:}-test"
          sleep 5
          docker exec "${OS_VERSION//:}-test-1" /opt/src/run.sh "${OS_VERSION::6}"

      - name: Clear
        if: always()
        run: |
          rm -rf "$GITHUB_WORKSPACE/testing/${OS_VERSION//:}"
          docker rm -f "${OS_VERSION//:}-test-1" || true
          docker rmi "${OS_VERSION//:}-test" || true
