diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d8a4c81..ecbfa3d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,6 +4,9 @@ on: push: branches: - main + pull_request: + branches: + - main jobs: type-check: diff --git a/.gitignore b/.gitignore index c94d426..8c8e78b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ node_modules/ /playwright/.auth/ .vscode .env +*.keytab diff --git a/docker/.dockerignore b/docker/.dockerignore new file mode 100644 index 0000000..6b7dd3d --- /dev/null +++ b/docker/.dockerignore @@ -0,0 +1,12 @@ +.gitignore +*.md +.git +.vscode +.github +.husky +test-results +playwright-report +user.json +Dockerfile +node_modules +.env diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..957d607 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,48 @@ +FROM registry.redhat.io/ubi9/ubi:9.5 as base + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 +ENV KRB5CCNAME=/tmp/cache + +COPY docker/krb5.conf /etc/krb5.conf +COPY docker/install-certs.sh /install-certs.sh +COPY docker/auth.sh /auth.sh + +RUN ./install-certs.sh $RH_CERT_URL \ + && yum update -y \ + && yum install -y wget git krb5-workstation \ + # Playwright dependencies + libxcb libXdamage libXcursor libXext libXcomposite libXrandr \ + libXi pango cairo cairo-gobject libXrender gtk3 atk gdk-pixbuf2 \ + # NodeJS + && yum module install -y nodejs:20/common \ + && yum clean all \ + && npm install -g yarn \ + && mkdir -p /krb5 \ + && chmod 755 /krb5 \ + && mkdir -p /var/lib/sss/pubconf/krb5.include.d \ + && chmod 755 /etc/krb5.conf.d \ + && chown -R 1001:0 /etc/krb5.conf.d \ + && chown 1001:0 /etc/krb5.conf \ + && chown -R 1001:0 /krb5 + +FROM base as build + +WORKDIR /app +ENV PLAYWRIGHT_BROWSERS_PATH=0 + +COPY --chown=1001 package.json /app/package.json +COPY --chown=1001 yarn.lock /app/yarn.lock +COPY --chown=1001 playwright.config.ts /app/playwright.config.ts +COPY --chown=1001 tsconfig.json /app/tsconfig.json +COPY --chown=1001 docker/krb5.conf.d /etc/krb5.conf.d +COPY --chown=1001 docker/krb5.keytab /krb5/krb5.keytab + +RUN yarn install --frozen-lockfile \ + && yarn playwright install chromium firefox + +COPY --chown=1001 . /app + +USER 1001 + +CMD ["/bin/sh"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..41417b3 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,62 @@ +# OSIM UI + Kerberos Tests Container + +This is the container that is used to run the tests on the CI/CD pipeline. It is based on redhat's ubi9 image and has the necessary dependencies to run the tests. + +## Building the container +Before building the container, you need to prepare some files. + +1. Create a `krb5.keytab` file in the `docker` directory. This file is used to authenticate with kerberos. +```bash +$ ktutil +ktutil: addent -password -p -k 1 -e aes256-cts-hmac-sha1-96 -f +ktutil: wkt krb5.keytab +ktutil: quit +``` +2. Create a `crypto-policies` file in the `krb5.conf.d` directory. You should have this file in `/etc/krb5.conf.d/` or `/usr/bin/krb5-conf/` on your machine. + + +3. Provide the correct realm configuration in a file inside the `krb5.conf.d` directory. You should have this file in `/etc/krb5.conf` on your machine. + + +That should look like this: +```bash +|-- docker +| |-- krb5.conf.d +| | |-- crypto-policies +| | |-- realm # name of the file is not important +| |-- krb5.keytab +| |-- krb5.conf +| |-- Dockerfile +``` + +After preparing the files, you can build the container using the following command: + +> [!IMPORTANT] +> Make sure to run the command from the root of the project. +> (outside of the docker folder) + +```bash +podman build -t osim-ui-tests -f docker/Dockerfile --ignorefile docker/.dockerignore . +# to install RH certificates add --env RH_CERT_URL= to the command +``` + +## Running the container +Make sure to provide the required [environment variables](/README.md#required-environment-variables) when running the container: + +```bash +podman run --rm -it --env-file .env osim-ui-tests +``` + +## Running the tests + +You need to authenticate with kerberos before running the tests. You can do this by running the script **inside the container**: + +```bash +sh /auth.sh +``` + +After authenticating, you can run the tests using the following command: + +```bash +yarn test +``` diff --git a/docker/auth.sh b/docker/auth.sh new file mode 100755 index 0000000..b1ddf00 --- /dev/null +++ b/docker/auth.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +principal="$( klist -kt /krb5/krb5.keytab | grep -Eo -m1 '\w+@[A-Z.]+' )" + +kinit -k -t /krb5/krb5.keytab $principal +klist -c /tmp/cache diff --git a/docker/install-certs.sh b/docker/install-certs.sh new file mode 100755 index 0000000..5528c1d --- /dev/null +++ b/docker/install-certs.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +if [[ -z "${1}" ]]; then + echo -e "\e[1;33mWARNING: RH_CERT_URL environment variable not set, internal RH resources won't be accessible\e[0m" +else + curl "${1}/certs/Current-IT-Root-CAs.pem" -o /etc/pki/ca-trust/source/anchors/Current-IT-Root-CAs.pem + mkdir -p /etc/ipa + curl "${1}/chains/ipa-ca-chain-2015.crt" -o /etc/ipa/ipa.crt + update-ca-trust +fi diff --git a/docker/krb5.conf b/docker/krb5.conf new file mode 100644 index 0000000..0a89a28 --- /dev/null +++ b/docker/krb5.conf @@ -0,0 +1,31 @@ +# To opt out of the system crypto-policies configuration of krb5, remove the +# symlink at /etc/krb5.conf.d/crypto-policies which will not be recreated. +includedir /etc/krb5.conf.d/ + +[logging] + default = FILE:/var/log/krb5libs.log + kdc = FILE:/var/log/krb5kdc.log + admin_server = FILE:/var/log/kadmind.log + +[libdefaults] + dns_lookup_realm = false + ticket_lifetime = 24h + renew_lifetime = 7d + forwardable = true + rdns = false + pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt + spake_preauth_groups = edwards25519 + dns_canonicalize_hostname = fallback + qualify_shortname = "" +# default_realm = EXAMPLE.COM + default_ccache_name = KEYRING:persistent:%{uid} + +[realms] +# EXAMPLE.COM = { +# kdc = kerberos.example.com +# admin_server = kerberos.example.com +# } + +[domain_realm] +# .example.com = EXAMPLE.COM +# example.com = EXAMPLE.COM diff --git a/docker/krb5.conf.d/.gitignore b/docker/krb5.conf.d/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/docker/krb5.conf.d/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/package.json b/package.json index 7eb06e2..ba7ab76 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,6 @@ "private": true, "devDependencies": { "@faker-js/faker": "^9.2.0", - "@playwright/browser-chromium": "^1.48.2", - "@playwright/browser-firefox": "^1.48.2", "@playwright/test": "^1.48.2", "@stylistic/eslint-plugin": "^2.10.1", "@types/eslint__js": "^8.42.3", @@ -26,9 +24,9 @@ "undici": "^6.21.0" }, "scripts": { - "test": "playwright test --reporter=list", - "test:chrome": "playwright test --reporter=list --project=chrome", - "test:firefox": "playwright test --reporter=list --project=firefox", + "test": "playwright test", + "test:chromium": "playwright test --project=chromium", + "test:firefox": "playwright test --project=firefox", "dev": "playwright test --ui", "lint": "eslint . ", "lint:fix": "eslint . --fix", diff --git a/playwright.config.ts b/playwright.config.ts index 24b4ce9..9d697dc 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -36,7 +36,7 @@ export default defineConfig({ forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, - reporter: 'html', + reporter: process.env.CI ? [['dot'], ['junit', {outputFile: 'results.xml'}]] : 'list', use: { storageState: 'playwright/.auth/user.json', ignoreHTTPSErrors: true, diff --git a/playwright/helpers.ts b/playwright/helpers.ts index d66a3c9..2e1d168 100644 --- a/playwright/helpers.ts +++ b/playwright/helpers.ts @@ -1,9 +1,10 @@ import { Agent, setGlobalDispatcher } from 'undici'; import { GSS_MECH_OID_KRB5, initializeClient } from 'kerberos'; import { type BrowserContextOptions } from '@playwright/test'; -import { readFile, writeFile } from 'fs/promises'; +import { readFile, writeFile, mkdir } from 'fs/promises'; import dayjs_base from 'dayjs'; import utc_plugin from 'dayjs/plugin/utc'; +import { existsSync } from 'fs'; dayjs_base.extend(utc_plugin); @@ -20,6 +21,8 @@ interface JSONResponse { refresh: string; } +const storagePath = 'playwright/.auth/'; + export async function authenticate(): Promise<{ refresh: string; access: string }> { const client = await initializeClient(`HTTP@${process.env.OSIDB_URL}`, { mechOID: GSS_MECH_OID_KRB5, @@ -42,12 +45,15 @@ type Optional = Pick, K> & Omit; type Storage = Exclude; export async function loadStorage(): Promise { - const storage = JSON.parse(await readFile('playwright/.auth/user.json', 'utf8')) as Storage; + const storage = JSON.parse(await readFile(`${storagePath}/user.json`, 'utf8')) as Storage; return storage; } export async function saveStorage(storage: Optional): Promise { - await writeFile('playwright/.auth/user.json', JSON.stringify(storage, null, 2)); + if (!existsSync(storagePath)) { + await mkdir(storagePath, { recursive: true }); + } + await writeFile(`${storagePath}/user.json`, JSON.stringify(storage, null, 2)); } export const { utc: dayjs } = dayjs_base; diff --git a/tests/flaw.spec.ts b/tests/flaw.spec.ts index 2a73106..fbe2061 100644 --- a/tests/flaw.spec.ts +++ b/tests/flaw.spec.ts @@ -55,8 +55,8 @@ test.describe('flaw creation', () => { test.slow(); await flawCreatePage.createFlaw({ type, full: true }); - await expect.soft(page.getByText('Flaw created')).toBeVisible(); - await expect(page).toHaveURL(/flaws\/(?!new)\w+/); + await expect.soft(page.getByText('Flaw created')).toBeVisible({ timeout: 60_000 }); + await expect(page).toHaveURL(/flaws\/(?!new)\w+/, { timeout: 60_000 }); }); }); // TODO: Add tests for specific fields and special cases. @@ -88,7 +88,7 @@ test.describe('flaw edition', () => { await flawEditPage.submitButton.click(); await expect(page.getByText('Flaw saved')).toBeVisible(); - await expect(page.getByText(newTitle)).toBeVisible(); + await expect(page.getByText(newTitle, { exact: true })).toBeVisible(); }); test.describe('affects', () => { diff --git a/yarn.lock b/yarn.lock index bbca302..50eb753 100644 --- a/yarn.lock +++ b/yarn.lock @@ -114,20 +114,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@playwright/browser-chromium@^1.48.2": - version "1.48.2" - resolved "https://registry.yarnpkg.com/@playwright/browser-chromium/-/browser-chromium-1.48.2.tgz#7693eb46a4a5d5c7b1a5bf89b56b08b62c9963ab" - integrity sha512-TvYJ5PFaDPYNlKpvPSftBbPTnu75VdRKjoMjmkd7/P79rFIBD+v6K4wU8XR6PlAqqFdPcfLL5XXZnRwTRixbDQ== - dependencies: - playwright-core "1.48.2" - -"@playwright/browser-firefox@^1.48.2": - version "1.48.2" - resolved "https://registry.yarnpkg.com/@playwright/browser-firefox/-/browser-firefox-1.48.2.tgz#ebbb4ca4ee6f5200218a856c211184dfc0a164a3" - integrity sha512-Cf0ZvgOCmmyqNbFLC2KQyV6RdTxfmuUzASnVhA7unT9xV3zK0TGv5xJZH4ACRMMdYeZ/pSK3SWyewmjMEvSo3g== - dependencies: - playwright-core "1.48.2" - "@playwright/test@^1.48.2": version "1.48.2" resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.48.2.tgz#87dd40633f980872283404c8142a65744d3f13d6"