test(ui): add GitHub provider support in ProvidersPage tests

- Introduced GitHub provider data and credential interfaces to the ProvidersPage.
- Implemented methods for filling GitHub provider details and credentials for both personal access token and GitHub App.
- Added end-to-end tests for adding a GitHub provider using personal access token and GitHub App authentication.
- Updated the UI E2E tests workflow to include necessary environment variables for GitHub integration.
- Enhanced documentation with new test cases for GitHub provider integration.
This commit is contained in:
StylusFrost
2025-10-27 20:38:21 +01:00
parent 2409049c88
commit faec92cbbc
4 changed files with 584 additions and 10 deletions
+6
View File
@@ -36,6 +36,12 @@ jobs:
E2E_M365_CERTIFICATE_CONTENT: ${{ secrets.E2E_M365_CERTIFICATE_CONTENT }}
E2E_KUBERNETES_CONTEXT: 'kind-kind'
E2E_KUBERNETES_KUBECONFIG_PATH: /home/runner/.kube/config
E2E_GITHUB_APP_ID: ${{ secrets.E2E_GITHUB_APP_ID }}
E2E_GITHUB_BASE64_APP_PRIVATE_KEY: ${{ secrets.E2E_GITHUB_BASE64_APP_PRIVATE_KEY }}
E2E_GITHUB_USERNAME: ${{ secrets.E2E_GITHUB_USERNAME }}
E2E_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.E2E_GITHUB_PERSONAL_ACCESS_TOKEN }}
E2E_GITHUB_ORGANIZATION: ${{ secrets.E2E_GITHUB_ORGANIZATION }}
E2E_GITHUB_ORGANIZATION_ACCESS_TOKEN: ${{ secrets.E2E_GITHUB_ORGANIZATION_ACCESS_TOKEN }}
E2E_NEW_USER_PASSWORD: ${{ secrets.E2E_NEW_USER_PASSWORD }}
steps:
+114 -1
View File
@@ -31,6 +31,12 @@ export interface GCPProviderData {
alias?: string;
}
// GitHub provider data
export interface GitHubProviderData {
username: string;
alias?: string;
}
// AWS credential options
export const AWS_CREDENTIAL_OPTIONS = {
AWS_ROLE_ARN: "role",
@@ -97,7 +103,7 @@ export interface KubernetesProviderCredential {
kubeconfigContent:string;
}
// GCP credential options
// GCP credential options
export const GCP_CREDENTIAL_OPTIONS = {
GCP_SERVICE_ACCOUNT: "service_account"
} as const;
@@ -111,6 +117,24 @@ export interface GCPProviderCredential {
serviceAccountKey:string;
}
// GitHub credential options
export const GITHUB_CREDENTIAL_OPTIONS = {
GITHUB_PERSONAL_ACCESS_TOKEN: "personal_access_token",
GITHUB_ORGANIZATION_ACCESS_TOKEN: "organization_access_token",
GITHUB_APP: "github_app"
} as const;
// GitHub credential type
type GitHubCredentialType = (typeof GITHUB_CREDENTIAL_OPTIONS)[keyof typeof GITHUB_CREDENTIAL_OPTIONS];
// GitHub provider personal access token credential
export interface GitHubProviderCredential {
type: GitHubCredentialType;
personalAccessToken?:string;
githubAppId?:string;
githubAppPrivateKey?:string;
}
// Providers page
export class ProvidersPage extends BasePage {
@@ -142,6 +166,10 @@ export class ProvidersPage extends BasePage {
readonly m365StaticCredentialsRadio: Locator;
readonly m365CertificateCredentialsRadio: Locator;
// GitHub credentials type selection
readonly githubPersonalAccessTokenRadio: Locator;
readonly githubAppCredentialsRadio: Locator;
// AWS role credentials form
readonly roleArnInput: Locator;
readonly externalIdInput: Locator;
@@ -172,6 +200,12 @@ export class ProvidersPage extends BasePage {
readonly gcpServiceAccountKeyInput: Locator;
readonly gcpServiceAccountRadio: Locator;
// GitHub provider form elements
readonly githubUsernameInput: Locator;
readonly githubAppIdInput: Locator;
readonly githubAppPrivateKeyInput: Locator;
readonly githubPersonalAccessTokenInput: Locator;
// Delete button
readonly deleteProviderConfirmationButton: Locator;
@@ -226,6 +260,13 @@ export class ProvidersPage extends BasePage {
this.gcpProjectIdInput = page.getByRole("textbox", { name: "Project ID" });
this.gcpServiceAccountKeyInput = page.getByRole("textbox", { name: "Service Account Key" });
// GitHub provider form inputs
this.githubUsernameInput = page.getByRole("textbox", { name: "Username" });
this.githubPersonalAccessTokenInput = page.getByRole("textbox", { name: "Personal Access Token" });
this.githubAppIdInput = page.getByRole("textbox", { name: "GitHub App ID" });
this.githubAppPrivateKeyInput = page.getByRole("textbox", { name: "GitHub App Private Key" });
// Alias input
this.aliasInput = page.getByRole("textbox", { name: "Provider alias (optional)" });
@@ -265,6 +306,14 @@ export class ProvidersPage extends BasePage {
name: /Service Account Key/i,
});
// Radios for selecting GitHub credentials method
this.githubPersonalAccessTokenRadio = page.getByRole("radio", {
name: /Personal Access Token/i,
});
this.githubAppCredentialsRadio = page.getByRole("radio", {
name: /GitHub App/i,
});
// Inputs for IAM Role credentials
this.roleArnInput = page.getByRole("textbox", { name: "Role ARN" });
this.externalIdInput = page.getByRole("textbox", { name: "External ID" });
@@ -328,6 +377,13 @@ export class ProvidersPage extends BasePage {
await this.waitForPageLoad();
}
async selectGitHubProvider(): Promise<void> {
// Select the GitHub provider
await this.githubProviderRadio.click({ force: true });
await this.waitForPageLoad();
}
async fillAWSProviderDetails(data: AWSProviderData): Promise<void> {
// Fill the AWS provider details
@@ -377,6 +433,15 @@ export class ProvidersPage extends BasePage {
}
}
async fillGitHubProviderDetails(data: GitHubProviderData): Promise<void> {
// Fill the GitHub provider details
await this.githubUsernameInput.fill(data.username);
if (data.alias) {
await this.aliasInput.fill(data.alias);
}
}
async clickNext(): Promise<void> {
// The wizard interface may use different labels for its primary action button on each step.
// This function determines which button to click depending on the current URL and page content.
@@ -527,6 +592,21 @@ export class ProvidersPage extends BasePage {
await this.waitForPageLoad();
}
async selectGitHubCredentialsType(type: GitHubCredentialType): Promise<void> {
// Ensure we are on the add-credentials page where the selector exists
await expect(this.page).toHaveURL(/\/providers\/add-credentials/);
if (type === GITHUB_CREDENTIAL_OPTIONS.GITHUB_PERSONAL_ACCESS_TOKEN) {
await this.githubPersonalAccessTokenRadio.click({ force: true });
} else if (type === GITHUB_CREDENTIAL_OPTIONS.GITHUB_APP) {
await this.githubAppCredentialsRadio.click({ force: true });
} else {
throw new Error(`Invalid GitHub credential type: ${type}`);
}
// Wait for the page to load
await this.waitForPageLoad();
}
async fillRoleCredentials(credentials: AWSProviderCredential): Promise<void> {
// Fill the role credentials form
@@ -616,6 +696,25 @@ export class ProvidersPage extends BasePage {
}
}
async fillGitHubPersonalAccessTokenCredentials(credentials: GitHubProviderCredential): Promise<void> {
// Fill the GitHub personal access token credentials form
if (credentials.personalAccessToken) {
await this.githubPersonalAccessTokenInput.fill(credentials.personalAccessToken);
}
}
async fillGitHubAppCredentials(credentials: GitHubProviderCredential): Promise<void> {
// Fill the GitHub app credentials form
if (credentials.githubAppId) {
await this.githubAppIdInput.fill(credentials.githubAppId);
}
if (credentials.githubAppPrivateKey) {
await this.githubAppPrivateKeyInput.fill(credentials.githubAppPrivateKey);
}
}
async verifyPageLoaded(): Promise<void> {
// Verify the providers page is loaded
@@ -670,6 +769,20 @@ export class ProvidersPage extends BasePage {
await expect(this.gcpServiceAccountKeyInput).toBeVisible();
}
async verifyGitHubPersonalAccessTokenPageLoaded(): Promise<void> {
// Verify the GitHub personal access token page is loaded
await expect(this.page).toHaveTitle(/Prowler/);
await expect(this.githubPersonalAccessTokenInput).toBeVisible();
}
async verifyGitHubAppPageLoaded(): Promise<void> {
// Verify the GitHub app page is loaded
await expect(this.page).toHaveTitle(/Prowler/);
await expect(this.githubAppIdInput).toBeVisible();
await expect(this.githubAppPrivateKeyInput).toBeVisible();
}
async verifyLaunchScanPageLoaded(): Promise<void> {
// Verify the launch scan page is loaded
+170
View File
@@ -380,3 +380,173 @@
- Requires valid GCP project with service account having appropriate permissions
- Service account must have sufficient permissions for security scanning
- Test validates that service account key goes to the correct field
- Test uses base64 encoded environment variables for GCP service account key
---
## Test Case: `PROVIDER-E2E-008` - Add GitHub Provider with Personal Access Token
**Priority:** `critical`
**Tags:**
- type → @e2e, @serial
- feature → @providers
- provider → @github
**Description/Objective:** Validates the complete flow of adding a new GitHub provider using personal access token authentication for a user account
**Preconditions:**
- Admin user authentication required (admin.auth.setup setup)
- Environment variables configured: E2E_GITHUB_USERNAME, E2E_GITHUB_PERSONAL_ACCESS_TOKEN
- Remove any existing provider with the same Username before starting the test
- This test must be run serially and never in parallel with other tests, as it requires the Username not to be already registered beforehand.
### Flow Steps:
1. Navigate to providers page
2. Click "Add Provider" button
3. Select GitHub provider type
4. Fill provider details (username and alias)
5. Select personal access token credentials type
6. Fill GitHub personal access token credentials
7. Launch initial scan
8. Verify redirect to provider management page
### Expected Result:
- GitHub provider successfully added with personal access token
- Initial scan launched successfully
- User redirected to provider details page
### Key verification points:
- Provider page loads correctly
- Connect account page displays GitHub option
- Provider details form accepts username and alias
- Personal access token credentials page loads with token field
- Personal access token is properly filled in the correct field
- Launch scan page appears
- Successful redirect to provider page after scan launch
### Notes:
- Test uses environment variables for GitHub username and personal access token
- Provider cleanup performed before each test to ensure clean state
- Requires valid GitHub account with personal access token
- Personal access token must have sufficient permissions for security scanning
- Test validates that personal access token goes to the correct field
---
## Test Case: `PROVIDER-E2E-009` - Add GitHub Provider with GitHub App
**Priority:** `critical`
**Tags:**
- type → @e2e, @serial
- feature → @providers
- provider → @github
**Description/Objective:** Validates the complete flow of adding a new GitHub provider using GitHub App authentication for a user account
**Preconditions:**
- Admin user authentication required (admin.auth.setup setup)
- Environment variables configured: E2E_GITHUB_USERNAME, E2E_GITHUB_APP_ID, E2E_GITHUB_BASE64_APP_PRIVATE_KEY
- Remove any existing provider with the same Username before starting the test
- This test must be run serially and never in parallel with other tests, as it requires the Username not to be already registered beforehand.
### Flow Steps:
1. Navigate to providers page
2. Click "Add Provider" button
3. Select GitHub provider type
4. Fill provider details (username and alias)
5. Select GitHub App credentials type
6. Fill GitHub App credentials (App ID and private key)
7. Launch initial scan
8. Verify redirect to provider management page
### Expected Result:
- GitHub provider successfully added with GitHub App credentials
- Initial scan launched successfully
- User redirected to provider details page
### Key verification points:
- Provider page loads correctly
- Connect account page displays GitHub option
- Provider details form accepts username and alias
- GitHub App credentials page loads with App ID and private key fields
- GitHub App credentials are properly filled in the correct fields
- Launch scan page appears
- Successful redirect to provider page after scan launch
### Notes:
- Test uses environment variables for GitHub username, App ID, and base64 encoded private key
- Private key is base64 encoded and must be decoded before use
- Provider cleanup performed before each test to ensure clean state
- Requires valid GitHub App with App ID and private key
- GitHub App must have sufficient permissions for security scanning
- Test validates that GitHub App credentials go to the correct fields
---
## Test Case: `PROVIDER-E2E-010` - Add GitHub Provider with Organization Personal Access Token
**Priority:** `critical`
**Tags:**
- type → @e2e, @serial
- feature → @providers
- provider → @github
**Description/Objective:** Validates the complete flow of adding a new GitHub provider using organization personal access token authentication
**Preconditions:**
- Admin user authentication required (admin.auth.setup setup)
- Environment variables configured: E2E_GITHUB_ORGANIZATION, E2E_GITHUB_ORGANIZATION_ACCESS_TOKEN
- Remove any existing provider with the same Organization name before starting the test
- This test must be run serially and never in parallel with other tests, as it requires the Organization name not to be already registered beforehand.
### Flow Steps:
1. Navigate to providers page
2. Click "Add Provider" button
3. Select GitHub provider type
4. Fill provider details (organization name and alias)
5. Select personal access token credentials type
6. Fill GitHub organization personal access token credentials
7. Launch initial scan
8. Verify redirect to provider management page
### Expected Result:
- GitHub provider successfully added with organization personal access token
- Initial scan launched successfully
- User redirected to provider details page
### Key verification points:
- Provider page loads correctly
- Connect account page displays GitHub option
- Provider details form accepts organization name and alias
- Personal access token credentials page loads with token field
- Organization personal access token is properly filled in the correct field
- Launch scan page appears
- Successful redirect to provider page after scan launch
### Notes:
- Test uses environment variables for GitHub organization name and organization access token
- Provider cleanup performed before each test to ensure clean state
- Requires valid GitHub organization with organization access token
- Organization access token must have sufficient permissions for security scanning
- Test validates that organization personal access token goes to the correct field
+294 -9
View File
@@ -17,6 +17,9 @@ import {
GCPProviderData,
GCPProviderCredential,
GCP_CREDENTIAL_OPTIONS,
GitHubProviderData,
GitHubProviderCredential,
GITHUB_CREDENTIAL_OPTIONS,
} from "./providers-page";
import { ScansPage } from "../scans/scans-page";
import fs from "fs";
@@ -554,10 +557,8 @@ test.describe("Add Provider", () => {
const projectId = process.env.E2E_GCP_PROJECT_ID;
// Validate required environment variables
if (!projectId ) {
throw new Error(
"E2E_GCP_PROJECT_ID environment variable is not set",
);
if (!projectId) {
throw new Error("E2E_GCP_PROJECT_ID environment variable is not set");
}
// Setup before each test
@@ -584,15 +585,21 @@ test.describe("Add Provider", () => {
},
async ({ page }) => {
// Validate required environment variables
const serviceAccountKeyB64 = process.env.E2E_GCP_BASE64_SERVICE_ACCOUNT_KEY;
const serviceAccountKeyB64 =
process.env.E2E_GCP_BASE64_SERVICE_ACCOUNT_KEY;
// Verify service account key is base64 encoded
if (!serviceAccountKeyB64) {
throw new Error("E2E_GCP_BASE64_SERVICE_ACCOUNT_KEY environment variable is not set");
throw new Error(
"E2E_GCP_BASE64_SERVICE_ACCOUNT_KEY environment variable is not set",
);
}
// Decode service account key from base64
const serviceAccountKey = Buffer.from(serviceAccountKeyB64, 'base64').toString('utf8');
const serviceAccountKey = Buffer.from(
serviceAccountKeyB64,
"base64",
).toString("utf8");
// Verify service account key is valid JSON
if (!JSON.parse(serviceAccountKey)) {
@@ -608,7 +615,7 @@ test.describe("Add Provider", () => {
// Prepare static credentials
const gcpCredentials: GCPProviderCredential = {
type: GCP_CREDENTIAL_OPTIONS.GCP_SERVICE_ACCOUNT,
serviceAccountKey: serviceAccountKey
serviceAccountKey: serviceAccountKey,
};
// Navigate to providers page
@@ -648,4 +655,282 @@ test.describe("Add Provider", () => {
},
);
});
test.describe.serial("Add GitHub Provider", () => {
// Providers page object
let providersPage: ProvidersPage;
let scansPage: ScansPage;
test.describe("Add GitHub provider with username", () => {
// Test data from environment variables
const username = process.env.E2E_GITHUB_USERNAME;
// Validate required environment variables
if (!username) {
throw new Error("E2E_GITHUB_USERNAME environment variable is not set");
}
// Setup before each test
test.beforeEach(async ({ page }) => {
providersPage = new ProvidersPage(page);
// Clean up existing provider to ensure clean test state
await providersPage.deleteProviderIfExists(username);
});
// Use admin authentication for provider management
test.use({ storageState: "playwright/.auth/admin_user.json" });
test(
"should add a new GitHub provider with personal access token",
{
tag: [
"@critical",
"@e2e",
"@providers",
"@github",
"@serial",
"@PROVIDER-E2E-008",
],
},
async ({ page }) => {
// Validate required environment variables
const personalAccessToken =
process.env.E2E_GITHUB_PERSONAL_ACCESS_TOKEN;
// Verify username and personal access token are set in environment variables
if (!personalAccessToken) {
throw new Error(
"E2E_GITHUB_PERSONAL_ACCESS_TOKEN environment variables are not set",
);
}
// Prepare test data for GitHub provider
const githubProviderData: GitHubProviderData = {
username: username,
alias: "Test E2E GitHub Account - Personal Access Token",
};
// Prepare personal access token credentials
const githubCredentials: GitHubProviderCredential = {
type: GITHUB_CREDENTIAL_OPTIONS.GITHUB_PERSONAL_ACCESS_TOKEN,
personalAccessToken: personalAccessToken,
};
// Navigate to providers page
await providersPage.goto();
await providersPage.verifyPageLoaded();
// Start adding new provider
await providersPage.clickAddProvider();
await providersPage.verifyConnectAccountPageLoaded();
// Select GitHub provider
await providersPage.selectGitHubProvider();
// Fill provider details
await providersPage.fillGitHubProviderDetails(githubProviderData);
await providersPage.clickNext();
// Select GitHub personal access token credentials type
await providersPage.selectGitHubCredentialsType(
GITHUB_CREDENTIAL_OPTIONS.GITHUB_PERSONAL_ACCESS_TOKEN,
);
// Verify GitHub personal access token page is loaded
await providersPage.verifyGitHubPersonalAccessTokenPageLoaded();
// Fill static personal access token details
await providersPage.fillGitHubPersonalAccessTokenCredentials(
githubCredentials,
);
await providersPage.clickNext();
// Launch scan
await providersPage.verifyLaunchScanPageLoaded();
await providersPage.clickNext();
// Wait for redirect to scan page
scansPage = new ScansPage(page);
await scansPage.verifyPageLoaded();
},
);
test(
"should add a new GitHub provider with github app",
{
tag: [
"@critical",
"@e2e",
"@providers",
"@github",
"@serial",
"@PROVIDER-E2E-009",
],
},
async ({ page }) => {
// Validate required environment variables
const githubAppId =
process.env.E2E_GITHUB_APP_ID;
const githubAppPrivateKeyB64 =
process.env.E2E_GITHUB_BASE64_APP_PRIVATE_KEY;
// Verify github app id and private key are set in environment variables
if (!githubAppId || !githubAppPrivateKeyB64) {
throw new Error(
"E2E_GITHUB_APP_ID and E2E_GITHUB_APP_PRIVATE_KEY environment variables are not set",
);
}
// Decode github app private key from base64
const githubAppPrivateKey = Buffer.from(
githubAppPrivateKeyB64,
"base64",
).toString("utf8");
// Prepare test data for GitHub provider
const githubProviderData: GitHubProviderData = {
username: username,
alias: "Test E2E GitHub Account - GitHub App",
};
// Prepare github app credentials
const githubCredentials: GitHubProviderCredential = {
type: GITHUB_CREDENTIAL_OPTIONS.GITHUB_APP,
githubAppId: githubAppId,
githubAppPrivateKey: githubAppPrivateKey,
};
// Navigate to providers page
await providersPage.goto();
await providersPage.verifyPageLoaded();
// Start adding new provider
await providersPage.clickAddProvider();
await providersPage.verifyConnectAccountPageLoaded();
// Select GitHub provider
await providersPage.selectGitHubProvider();
// Fill provider details
await providersPage.fillGitHubProviderDetails(githubProviderData);
await providersPage.clickNext();
// Select static github app credentials type
await providersPage.selectGitHubCredentialsType(
GITHUB_CREDENTIAL_OPTIONS.GITHUB_APP,
);
// Verify GitHub github app page is loaded
await providersPage.verifyGitHubAppPageLoaded();
// Fill static github app credentials details
await providersPage.fillGitHubAppCredentials(
githubCredentials,
);
await providersPage.clickNext();
// Launch scan
await providersPage.verifyLaunchScanPageLoaded();
await providersPage.clickNext();
// Wait for redirect to scan page
scansPage = new ScansPage(page);
await scansPage.verifyPageLoaded();
},
);
});
test.describe("Add GitHub provider with organization", () => {
// Test data from environment variables
const organization = process.env.E2E_GITHUB_ORGANIZATION;
// Validate required environment variables
if (!organization) {
throw new Error(
"E2E_GITHUB_ORGANIZATION environment variable is not set",
);
}
// Setup before each test
test.beforeEach(async ({ page }) => {
providersPage = new ProvidersPage(page);
// Clean up existing provider to ensure clean test state
await providersPage.deleteProviderIfExists(organization);
});
// Use admin authentication for provider management
test.use({ storageState: "playwright/.auth/admin_user.json" });
test(
"should add a new GitHub provider with organization personal access token",
{
tag: [
"@critical",
"@e2e",
"@providers",
"@github",
"@serial",
"@PROVIDER-E2E-010",
],
},
async ({ page }) => {
// Validate required environment variables
const organizationAccessToken =
process.env.E2E_GITHUB_ORGANIZATION_ACCESS_TOKEN;
// Verify username and personal access token are set in environment variables
if (!organizationAccessToken) {
throw new Error(
"E2E_GITHUB_ORGANIZATION_ACCESS_TOKEN environment variables are not set",
);
}
// Prepare test data for GitHub provider
const githubProviderData: GitHubProviderData = {
username: organization,
alias: "Test E2E GitHub Account - Organization Access Token",
};
// Prepare personal access token credentials
const githubCredentials: GitHubProviderCredential = {
type: GITHUB_CREDENTIAL_OPTIONS.GITHUB_PERSONAL_ACCESS_TOKEN,
personalAccessToken: organizationAccessToken,
};
// Navigate to providers page
await providersPage.goto();
await providersPage.verifyPageLoaded();
// Start adding new provider
await providersPage.clickAddProvider();
await providersPage.verifyConnectAccountPageLoaded();
// Select GitHub provider
await providersPage.selectGitHubProvider();
// Fill provider details
await providersPage.fillGitHubProviderDetails(githubProviderData);
await providersPage.clickNext();
// Select GitHub organization personal access token credentials type
await providersPage.selectGitHubCredentialsType(
GITHUB_CREDENTIAL_OPTIONS.GITHUB_PERSONAL_ACCESS_TOKEN,
);
// Verify GitHub personal access token page is loaded
await providersPage.verifyGitHubPersonalAccessTokenPageLoaded();
// Fill static personal access token details
await providersPage.fillGitHubPersonalAccessTokenCredentials(
githubCredentials,
);
await providersPage.clickNext();
// Launch scan
await providersPage.verifyLaunchScanPageLoaded();
await providersPage.clickNext();
// Wait for redirect to scan page
scansPage = new ScansPage(page);
await scansPage.verifyPageLoaded();
},
);
});
});
});