test_pki() {
    if [ ! -d "/usr/share/easy-rsa/" ]; then
        echo "==> SKIP: The pki test requires easy-rsa to be installed"
        return
    fi

    # Setup the PKI.
    cp -R /usr/share/easy-rsa "${TEST_DIR}/pki"
    (
        set -e
        cd "${TEST_DIR}/pki"
        export EASYRSA_KEY_SIZE=4096

        # shellcheck disable=SC1091
        if [ -e pkitool ]; then
            . ./vars
            ./clean-all
            ./pkitool --initca
            ./pkitool incus-client
            ./pkitool incus-client-revoked
            # This will revoke the certificate but fail in the end as it tries to then verify the revoked certificate.
            ./revoke-full incus-client-revoked || true
        else
            ./easyrsa init-pki
            echo "incus" | ./easyrsa build-ca nopass
            ./easyrsa gen-crl
            echo "yes" | ./easyrsa build-client-full incus-client nopass
            echo "yes" | ./easyrsa build-client-full incus-client-revoked nopass
            mkdir keys
            cp pki/private/* keys/
            cp pki/issued/* keys/
            cp pki/ca.crt keys/
            echo "yes" | ./easyrsa revoke incus-client-revoked
            ./easyrsa gen-crl
            cp pki/crl.pem keys/
        fi
    )

    # Setup the daemon in normal mode
    INCUS5_DIR=$(mktemp -d -p "${TEST_DIR}" XXX)
    chmod +x "${INCUS5_DIR}"
    spawn_incus "${INCUS5_DIR}" true
    INCUS5_ADDR=$(cat "${INCUS5_DIR}/incus.addr")

    # Generate, trust and test a client certificate
    openssl req -x509 -newkey rsa:4096 -sha384 -keyout "${INCUS_CONF}/simple-client.key" -nodes -out "${INCUS_CONF}/simple-client.crt" -days 1 -subj "/CN=test.local"
    INCUS_DIR="${INCUS5_DIR}" incus config trust add-certificate "${INCUS_CONF}/simple-client.crt"
    INCUS_DIR="${INCUS5_DIR}" incus config set user.test foo
    curl -k -s --cert "${INCUS_CONF}/simple-client.crt" --key "${INCUS_CONF}/simple-client.key" "https://${INCUS5_ADDR}/1.0" | grep -q "user.test.*foo" || false

    # Restart the daemon in PKI mode
    shutdown_incus "${INCUS5_DIR}"
    cp "${TEST_DIR}/pki/keys/ca.crt" "${INCUS5_DIR}/server.ca"
    cp "${TEST_DIR}/pki/keys/crl.pem" "${INCUS5_DIR}/ca.crl"
    respawn_incus "${INCUS5_DIR}" true

    # Setup the client.
    INC5_DIR=$(mktemp -d -p "${TEST_DIR}" XXX)
    cp "${TEST_DIR}/pki/keys/incus-client.crt" "${INC5_DIR}/client.crt"
    cp "${TEST_DIR}/pki/keys/incus-client.key" "${INC5_DIR}/client.key"
    cp "${TEST_DIR}/pki/keys/ca.crt" "${INC5_DIR}/client.ca"

    # Re-test the regular client certificate
    curl -k -s --cert "${INCUS_CONF}/simple-client.crt" --key "${INCUS_CONF}/simple-client.key" "https://${INCUS5_ADDR}/1.0" incus/1.0 | grep -q "user.test.*foo" && false
    fingerprint="$(INCUS_DIR="${INCUS5_DIR}" incus config trust list -cf -fcsv)"
    INCUS_DIR="${INCUS5_DIR}" incus config trust remove "${fingerprint}"

    # Confirm that a valid client certificate works.
    (
        set -e
        export INCUS_CONF="${INC5_DIR}"

        # Try adding remote using an incorrect token.
        # This should fail, as if the certificate is unknown and token is wrong then no access should be allowed.
        ! incus_remote remote add pki-incus "${INCUS5_ADDR}" --accept-certificate --token=bar || false

        # Add remote using the correct token.
        # This should work because the client certificate is signed by the CA.
        token="$(INCUS_DIR=${INCUS5_DIR} incus config trust add foo -q)"
        incus_remote remote add pki-incus "${INCUS5_ADDR}" --accept-certificate --token "${token}"
        incus_remote config trust list pki-incus: -cc -fcsv | grep incus-client
        fingerprint="$(incus_remote config trust list pki-incus: -cf -fcsv)"
        incus_remote config trust remove pki-incus:"${fingerprint}"
        incus_remote remote remove pki-incus

        # Add remote using a CA-signed client certificate, and not providing a token.
        # This should succeed and tests that the CA trust is working, as adding the client certificate to the trust
        # store without a token would normally fail.
        INCUS_DIR=${INCUS5_DIR} incus config set core.trust_ca_certificates true
        incus_remote remote add pki-incus "${INCUS5_ADDR}" --accept-certificate
        ! incus_remote config trust list pki-incus: -cc -fcsv | grep incus-client || false
        incus_remote remote remove pki-incus

        # Add remote using a CA-signed client certificate, and providing an incorrect token.
        # This should succeed as is the same as the test above but with an incorrect token rather than no token.
        incus_remote remote add pki-incus "${INCUS5_ADDR}" --accept-certificate --token=bar
        ! incus_remote config trust list pki-incus: -cc -fcsv | grep incus-client || false
        incus_remote remote remove pki-incus

        # Replace the client certificate with a revoked certificate in the CRL.
        cp "${TEST_DIR}/pki/keys/incus-client-revoked.crt" "${INC5_DIR}/client.crt"
        cp "${TEST_DIR}/pki/keys/incus-client-revoked.key" "${INC5_DIR}/client.key"

        # Try adding a remote using a revoked client certificate, and the correct token.
        # This should fail, as although revoked certificates can be added to the trust store, they will not be usable.
        token="$(INCUS_DIR=${INCUS5_DIR} incus config trust add foo -q)"
        ! incus_remote remote add pki-incus "${INCUS5_ADDR}" --accept-certificate --token "${token}" || false

        # Try adding a remote using a revoked client certificate, and an incorrect token.
        # This should fail, as if the certificate is revoked and token is wrong then no access should be allowed.
        ! incus_remote remote add pki-incus "${INCUS5_ADDR}" --accept-certificate --token=incorrect || false
    )

    # Confirm that a normal, non-PKI certificate doesn't.
    # As INCUS_CONF is not set to INC5_DIR where the CA signed client certs are, this will cause the incus command to
    # generate a new certificate that isn't trusted by the CA certificate and thus will not be allowed, even with a
    # correct token. This is because the Incus TLS listener in CA mode will not consider a client cert that
    # is not signed by the CA as valid.
    token="$(INCUS_DIR=${INCUS5_DIR} incus config trust add foo -q)"
    ! incus_remote remote add pki-incus "${INCUS5_ADDR}" --accept-certificate --token "${token}" || false

    kill_incus "${INCUS5_DIR}"
}
