name: Tomcat HTTPS with default settings

on: workflow_call

env:
  NAMESPACE: ${{ vars.REGISTRY_NAMESPACE || 'dogtagpki' }}

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    env:
      SHARED: /tmp/workdir/pki
    steps:
      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get -y install xmlstarlet

      - name: Clone repository
        uses: actions/checkout@v4

      - name: Retrieve JSS images
        uses: actions/cache@v4
        with:
          key: jss-images-${{ github.sha }}
          path: jss-images.tar

      - name: Load JSS images
        run: docker load --input jss-images.tar

      - name: Create network
        run: docker network create example

      - name: Set up JSS container
        run: |
          tests/bin/runner-init.sh \
              --hostname=server.example.com \
              --network=example \
              --network-alias=server.example.com \
              server

          # get Fedora version
          FEDORA_VERSION=$(docker exec server sed -n 's/^VERSION_ID=//p' /etc/os-release)
          echo "FEDORA_VERSION=$FEDORA_VERSION" >> $GITHUB_ENV

      - name: Import LDAP SDK packages
        run: |
          docker create --name=ldapjdk-dist quay.io/$NAMESPACE/ldapjdk-dist:5.6
          docker cp ldapjdk-dist:/root/RPMS/. /tmp/RPMS/
          docker rm -f ldapjdk-dist

      - name: Import PKI packages
        run: |
          docker create --name=pki-dist quay.io/$NAMESPACE/pki-dist:11.9
          docker cp pki-dist:/root/RPMS/. /tmp/RPMS/
          docker rm -f pki-dist

      - name: Install packages
        run: |
          docker cp /tmp/RPMS/. server:/root/RPMS/
          docker exec server bash -c "dnf install -y /root/RPMS/*"

      - name: Create Tomcat
        run: |
          docker exec server pki-server create -v

      - name: Create NSS database in Tomcat
        run: |
          docker exec server pki-server nss-create --no-password

      - name: Create SSL server cert
        run: |
          docker exec server pki \
              -d /var/lib/pki/pki-tomcat/alias \
              nss-cert-request \
              --subject "CN=server.example.com" \
              --ext /usr/share/pki/server/certs/sslserver.conf \
              --csr sslserver.csr

          docker exec server pki \
              -d /var/lib/pki/pki-tomcat/alias \
              nss-cert-issue \
              --csr sslserver.csr \
              --ext /usr/share/pki/server/certs/sslserver.conf \
              --cert sslserver.crt

          docker exec server pki \
              -d /var/lib/pki/pki-tomcat/alias \
              nss-cert-import \
              --cert sslserver.crt \
              sslserver

      - name: Create HTTPS connector
        run: |
          docker exec server pki-server jss-enable

          docker exec server pki-server http-connector-add \
              --port 8443 \
              --scheme https \
              --secure true \
              --sslEnabled true \
              --sslProtocol SSL \
              --sslImpl org.dogtagpki.jss.tomcat.JSSImplementation \
              Secure

          docker exec server pki-server http-connector-cert-add \
              --keyAlias sslserver \
              --keystoreType pkcs11 \
              --keystoreProvider Mozilla-JSS

          docker exec server cat /etc/pki/pki-tomcat/server.xml

      - name: Start Tomcat
        run: |
          docker exec server pki-server start --wait -v

      - name: Set up client container
        run: |
          tests/bin/runner-init.sh \
              --hostname=client.example.com \
              --network=example \
              --network-alias=client.example.com \
              client

      - name: Install dependencies
        run: docker exec client dnf install -y sslscan

      - name: Run sslscan
        run: |
          docker exec client sslscan \
              --xml=$SHARED/sslscan.xml \
              server.example.com:8443
          cat sslscan.xml

      - name: Check protocols
        run: |
          # only TLS1.2 and TLS 1.3 protocols should be enabled
          cat > expected << EOF
          <?xml version="1.0" encoding="UTF-8"?>
          <document>
            <ssltest host="server.example.com" sniname="server.example.com" port="8443">
              <protocol type="ssl" version="2" enabled="0"/>
              <protocol type="ssl" version="3" enabled="0"/>
              <protocol type="tls" version="1.0" enabled="0"/>
              <protocol type="tls" version="1.1" enabled="0"/>
              <protocol type="tls" version="1.2" enabled="1"/>
              <protocol type="tls" version="1.3" enabled="1"/>
            </ssltest>
          </document>
          EOF

          xmlstarlet ed \
              -d '/document/@*' \
              -d '/document/ssltest/*[not(self::protocol)]' \
              sslscan.xml | tee actual

          diff expected actual

      - name: Check ciphers
        if: ${{ fromJSON(env.FEDORA_VERSION) < 43 }}
        run: |
          # only TLS 1.2 and TLS 1.3 ciphers should be supported
          cat > expected << EOF
          <?xml version="1.0" encoding="UTF-8"?>
          <document>
            <ssltest host="server.example.com" sniname="server.example.com" port="8443">
              <cipher status="preferred" sslversion="TLSv1.3" bits="128" cipher="TLS_AES_128_GCM_SHA256" id="0x1301" strength="strong" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.3" bits="256" cipher="TLS_CHACHA20_POLY1305_SHA256" id="0x1303" strength="strong" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.3" bits="256" cipher="TLS_AES_256_GCM_SHA384" id="0x1302" strength="strong" curve="25519" ecdhebits="253"/>
              <cipher status="preferred" sslversion="TLSv1.2" bits="128" cipher="ECDHE-RSA-AES128-GCM-SHA256" id="0xC02F" strength="strong" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="ECDHE-RSA-CHACHA20-POLY1305" id="0xCCA8" strength="strong" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="ECDHE-RSA-AES256-GCM-SHA384" id="0xC030" strength="strong" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="128" cipher="ECDHE-RSA-AES128-SHA" id="0xC013" strength="medium" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="128" cipher="ECDHE-RSA-AES128-SHA256" id="0xC027" strength="acceptable" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="ECDHE-RSA-AES256-SHA" id="0xC014" strength="medium" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="ECDHE-RSA-AES256-SHA384" id="0xC028" strength="acceptable" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="128" cipher="DHE-RSA-AES128-GCM-SHA256" id="0x009E" strength="strong" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="DHE-RSA-CHACHA20-POLY1305" id="0xCCAA" strength="strong" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="DHE-RSA-AES256-GCM-SHA384" id="0x009F" strength="strong" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="128" cipher="DHE-RSA-AES128-SHA" id="0x0033" strength="medium" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="128" cipher="DHE-RSA-AES128-SHA256" id="0x0067" strength="acceptable" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="DHE-RSA-AES256-SHA" id="0x0039" strength="medium" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="DHE-RSA-AES256-SHA256" id="0x006B" strength="acceptable" dhebits="2048"/>
            </ssltest>
          </document>
          EOF

          xmlstarlet ed \
              -d '/document/@*' \
              -d '/document/ssltest/*[not(self::cipher)]' \
              sslscan.xml | tee actual

          diff expected actual

      - name: Check ciphers
        if: ${{ fromJSON(env.FEDORA_VERSION) >= 43 }}
        run: |
          # only TLS 1.2 and TLS 1.3 ciphers should be supported
          cat > expected << EOF
          <?xml version="1.0" encoding="UTF-8"?>
          <document>
            <ssltest host="server.example.com" sniname="server.example.com" port="8443">
              <cipher status="preferred" sslversion="TLSv1.3" bits="128" cipher="TLS_AES_128_GCM_SHA256" id="0x1301" strength="strong"/>
              <cipher status="accepted" sslversion="TLSv1.3" bits="256" cipher="TLS_CHACHA20_POLY1305_SHA256" id="0x1303" strength="strong"/>
              <cipher status="accepted" sslversion="TLSv1.3" bits="256" cipher="TLS_AES_256_GCM_SHA384" id="0x1302" strength="strong"/>
              <cipher status="preferred" sslversion="TLSv1.2" bits="128" cipher="ECDHE-RSA-AES128-GCM-SHA256" id="0xC02F" strength="strong" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="ECDHE-RSA-CHACHA20-POLY1305" id="0xCCA8" strength="strong" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="ECDHE-RSA-AES256-GCM-SHA384" id="0xC030" strength="strong" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="128" cipher="ECDHE-RSA-AES128-SHA" id="0xC013" strength="medium" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="128" cipher="ECDHE-RSA-AES128-SHA256" id="0xC027" strength="acceptable" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="ECDHE-RSA-AES256-SHA" id="0xC014" strength="medium" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="ECDHE-RSA-AES256-SHA384" id="0xC028" strength="acceptable" curve="25519" ecdhebits="253"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="128" cipher="DHE-RSA-AES128-GCM-SHA256" id="0x009E" strength="strong" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="DHE-RSA-CHACHA20-POLY1305" id="0xCCAA" strength="strong" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="DHE-RSA-AES256-GCM-SHA384" id="0x009F" strength="strong" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="128" cipher="DHE-RSA-AES128-SHA" id="0x0033" strength="medium" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="128" cipher="DHE-RSA-AES128-SHA256" id="0x0067" strength="acceptable" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="DHE-RSA-AES256-SHA" id="0x0039" strength="medium" dhebits="2048"/>
              <cipher status="accepted" sslversion="TLSv1.2" bits="256" cipher="DHE-RSA-AES256-SHA256" id="0x006B" strength="acceptable" dhebits="2048"/>
            </ssltest>
          </document>
          EOF

          xmlstarlet ed \
              -d '/document/@*' \
              -d '/document/ssltest/*[not(self::cipher)]' \
              sslscan.xml | tee actual

          diff expected actual

      - name: Check key exchange groups
        if: ${{ fromJSON(env.FEDORA_VERSION) < 43 }}
        run: |
          # only TLS 1.2 and TLS 1.3 key exchange groups should be supported
          cat > expected << EOF
          <?xml version="1.0" encoding="UTF-8"?>
          <document>
            <ssltest host="server.example.com" sniname="server.example.com" port="8443">
              <group sslversion="TLSv1.3" bits="128" name="secp256r1 (NIST P-256)" id="0x0017" strength="good"/>
              <group sslversion="TLSv1.3" bits="192" name="secp384r1 (NIST P-384)" id="0x0018" strength="good"/>
              <group sslversion="TLSv1.3" bits="260" name="secp521r1 (NIST P-521)" id="0x0019" strength="good"/>
              <group sslversion="TLSv1.3" bits="128" name="x25519" id="0x001d" strength="good"/>
              <group sslversion="TLSv1.3" bits="112" name="ffdhe2048" id="0x0100" strength="medium"/>
              <group sslversion="TLSv1.3" bits="128" name="ffdhe3072" id="0x0101" strength="good"/>
              <group sslversion="TLSv1.3" bits="150" name="ffdhe4096" id="0x0102" strength="good"/>
              <group sslversion="TLSv1.3" bits="175" name="ffdhe6144" id="0x0103" strength="good"/>
              <group sslversion="TLSv1.3" bits="192" name="ffdhe8192" id="0x0104" strength="good"/>
              <group sslversion="TLSv1.2" bits="128" name="secp256r1 (NIST P-256)" id="0x0017" strength="good"/>
              <group sslversion="TLSv1.2" bits="192" name="secp384r1 (NIST P-384)" id="0x0018" strength="good"/>
              <group sslversion="TLSv1.2" bits="260" name="secp521r1 (NIST P-521)" id="0x0019" strength="good"/>
              <group sslversion="TLSv1.2" bits="128" name="x25519" id="0x001d" strength="good"/>
            </ssltest>
          </document>
          EOF

          xmlstarlet ed \
              -d '/document/@*' \
              -d '/document/ssltest/*[not(self::group)]' \
              sslscan.xml | tee actual

          diff expected actual

      - name: Check key exchange groups
        if: ${{ fromJSON(env.FEDORA_VERSION) >= 43 }}
        run: |
          # only TLS 1.2 and TLS 1.3 key exchange groups should be supported
          cat > expected << EOF
          <?xml version="1.0" encoding="UTF-8"?>
          <document>
            <ssltest host="server.example.com" sniname="server.example.com" port="8443">
              <group sslversion="TLSv1.3" bits="128" name="secp256r1 (NIST P-256)" id="0x0017" strength="good"/>
              <group sslversion="TLSv1.3" bits="192" name="secp384r1 (NIST P-384)" id="0x0018" strength="good"/>
              <group sslversion="TLSv1.3" bits="260" name="secp521r1 (NIST P-521)" id="0x0019" strength="good"/>
              <group sslversion="TLSv1.3" bits="128" name="x25519" id="0x001d" strength="good"/>
              <group sslversion="TLSv1.3" bits="112" name="ffdhe2048" id="0x0100" strength="medium"/>
              <group sslversion="TLSv1.3" bits="128" name="ffdhe3072" id="0x0101" strength="good"/>
              <group sslversion="TLSv1.3" bits="150" name="ffdhe4096" id="0x0102" strength="good"/>
              <group sslversion="TLSv1.3" bits="175" name="ffdhe6144" id="0x0103" strength="good"/>
              <group sslversion="TLSv1.3" bits="192" name="ffdhe8192" id="0x0104" strength="good"/>
              <group sslversion="TLSv1.3" bits="192" name="X25519MLKEM768" id="0x11ec" strength="good"/>
              <group sslversion="TLSv1.2" bits="128" name="secp256r1 (NIST P-256)" id="0x0017" strength="good"/>
              <group sslversion="TLSv1.2" bits="192" name="secp384r1 (NIST P-384)" id="0x0018" strength="good"/>
              <group sslversion="TLSv1.2" bits="260" name="secp521r1 (NIST P-521)" id="0x0019" strength="good"/>
              <group sslversion="TLSv1.2" bits="128" name="x25519" id="0x001d" strength="good"/>
            </ssltest>
          </document>
          EOF

          xmlstarlet ed \
              -d '/document/@*' \
              -d '/document/ssltest/*[not(self::group)]' \
              sslscan.xml | tee actual

          diff expected actual

      - name: Check SSL server cert
        run: |
          cat > expected << EOF
          <?xml version="1.0" encoding="UTF-8"?>
          <document>
            <ssltest host="server.example.com" sniname="server.example.com" port="8443">
              <certificates>
                <certificate type="short">
                  <signature-algorithm>sha256WithRSAEncryption</signature-algorithm>
                  <pk error="false" type="RSA" bits="2048"/>
                  <subject><![CDATA[server.example.com]]></subject>
                  <altnames><![CDATA[DNS:server.example.com]]></altnames>
                  <issuer><![CDATA[server.example.com]]></issuer>
                  <self-signed>true</self-signed>
                  <not-yet-valid>false</not-yet-valid>
                  <expired>false</expired>
                </certificate>
              </certificates>
            </ssltest>
          </document>
          EOF

          xmlstarlet ed \
              -d '/document/@*' \
              -d '/document/ssltest/*[not(self::certificates)]' \
              -d '/document/ssltest/certificates/certificate/*[self::not-valid-before or self::not-valid-after]' \
              sslscan.xml | tee actual

          diff expected actual

      - name: Stop Tomcat
        run: |
          docker exec server pki-server stop --wait -v

      - name: Remove Tomcat
        run: |
          docker exec server pki-server remove -v

      - name: Check PKI server systemd journal
        if: always()
        run: |
          docker exec server journalctl -x --no-pager -u pki-tomcatd@pki-tomcat.service
