mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 21:11:53 +00:00
test(ui): add GCP provider support in ProvidersPage tests
- Introduced GCP provider data and credential interfaces to the ProvidersPage. - Implemented methods for filling GCP provider details and service account key credentials. - Added end-to-end tests for adding a GCP provider using service account key authentication. - Updated documentation to include new test case for GCP provider integration.
This commit is contained in:
@@ -25,6 +25,12 @@ export interface KubernetesProviderData {
|
||||
alias?: string;
|
||||
}
|
||||
|
||||
// GCP provider data
|
||||
export interface GCPProviderData {
|
||||
projectId: string;
|
||||
alias?: string;
|
||||
}
|
||||
|
||||
// AWS credential options
|
||||
export const AWS_CREDENTIAL_OPTIONS = {
|
||||
AWS_ROLE_ARN: "role",
|
||||
@@ -91,6 +97,20 @@ export interface KubernetesProviderCredential {
|
||||
kubeconfigContent:string;
|
||||
}
|
||||
|
||||
// GCP credential options
|
||||
export const GCP_CREDENTIAL_OPTIONS = {
|
||||
GCP_SERVICE_ACCOUNT: "service_account"
|
||||
} as const;
|
||||
|
||||
// GCP credential type
|
||||
type GCPCredentialType = (typeof GCP_CREDENTIAL_OPTIONS)[keyof typeof GCP_CREDENTIAL_OPTIONS];
|
||||
|
||||
// GCP provider credential
|
||||
export interface GCPProviderCredential {
|
||||
type: GCPCredentialType;
|
||||
serviceAccountKey:string;
|
||||
}
|
||||
|
||||
// Providers page
|
||||
export class ProvidersPage extends BasePage {
|
||||
|
||||
@@ -147,6 +167,11 @@ export class ProvidersPage extends BasePage {
|
||||
readonly kubernetesContextInput: Locator;
|
||||
readonly kubernetesKubeconfigContentInput: Locator;
|
||||
|
||||
// GCP provider form elements
|
||||
readonly gcpProjectIdInput: Locator;
|
||||
readonly gcpServiceAccountKeyInput: Locator;
|
||||
readonly gcpServiceAccountRadio: Locator;
|
||||
|
||||
// Delete button
|
||||
readonly deleteProviderConfirmationButton: Locator;
|
||||
|
||||
@@ -197,6 +222,10 @@ export class ProvidersPage extends BasePage {
|
||||
this.kubernetesContextInput = page.getByRole("textbox", { name: "Context" });
|
||||
this.kubernetesKubeconfigContentInput = page.getByRole("textbox", { name: "Kubeconfig Content" });
|
||||
|
||||
// GCP provider form inputs
|
||||
this.gcpProjectIdInput = page.getByRole("textbox", { name: "Project ID" });
|
||||
this.gcpServiceAccountKeyInput = page.getByRole("textbox", { name: "Service Account Key" });
|
||||
|
||||
// Alias input
|
||||
this.aliasInput = page.getByRole("textbox", { name: "Provider alias (optional)" });
|
||||
|
||||
@@ -231,6 +260,11 @@ export class ProvidersPage extends BasePage {
|
||||
name: /App Certificate Credentials/i,
|
||||
});
|
||||
|
||||
// Radios for selecting GCP credentials method
|
||||
this.gcpServiceAccountRadio = page.getByRole("radio", {
|
||||
name: /Service Account Key/i,
|
||||
});
|
||||
|
||||
// Inputs for IAM Role credentials
|
||||
this.roleArnInput = page.getByRole("textbox", { name: "Role ARN" });
|
||||
this.externalIdInput = page.getByRole("textbox", { name: "External ID" });
|
||||
@@ -287,6 +321,13 @@ export class ProvidersPage extends BasePage {
|
||||
await this.waitForPageLoad();
|
||||
}
|
||||
|
||||
async selectGCPProvider(): Promise<void> {
|
||||
// Select the GCP provider
|
||||
|
||||
await this.gcpProviderRadio.click({ force: true });
|
||||
await this.waitForPageLoad();
|
||||
}
|
||||
|
||||
|
||||
async fillAWSProviderDetails(data: AWSProviderData): Promise<void> {
|
||||
// Fill the AWS provider details
|
||||
@@ -327,6 +368,15 @@ export class ProvidersPage extends BasePage {
|
||||
}
|
||||
}
|
||||
|
||||
async fillGCPProviderDetails(data: GCPProviderData): Promise<void> {
|
||||
// Fill the GCP provider details
|
||||
|
||||
await this.gcpProjectIdInput.fill(data.projectId);
|
||||
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.
|
||||
@@ -464,6 +514,19 @@ export class ProvidersPage extends BasePage {
|
||||
await this.waitForPageLoad();
|
||||
}
|
||||
|
||||
async selectGCPCredentialsType(type: GCPCredentialType): Promise<void> {
|
||||
// Ensure we are on the add-credentials page where the selector exists
|
||||
|
||||
await expect(this.page).toHaveURL(/\/providers\/add-credentials/);
|
||||
if (type === GCP_CREDENTIAL_OPTIONS.GCP_SERVICE_ACCOUNT) {
|
||||
await this.gcpServiceAccountRadio.click({ force: true });
|
||||
} else {
|
||||
throw new Error(`Invalid GCP credential type: ${type}`);
|
||||
}
|
||||
// Wait for the page to load
|
||||
await this.waitForPageLoad();
|
||||
}
|
||||
|
||||
async fillRoleCredentials(credentials: AWSProviderCredential): Promise<void> {
|
||||
// Fill the role credentials form
|
||||
|
||||
@@ -545,6 +608,13 @@ export class ProvidersPage extends BasePage {
|
||||
}
|
||||
}
|
||||
|
||||
async fillGCPServiceAccountKeyCredentials(credentials: GCPProviderCredential): Promise<void> {
|
||||
// Fill the GCP credentials form
|
||||
|
||||
if (credentials.serviceAccountKey) {
|
||||
await this.gcpServiceAccountKeyInput.fill(credentials.serviceAccountKey);
|
||||
}
|
||||
}
|
||||
|
||||
async verifyPageLoaded(): Promise<void> {
|
||||
// Verify the providers page is loaded
|
||||
@@ -593,6 +663,13 @@ export class ProvidersPage extends BasePage {
|
||||
await expect(this.kubernetesContextInput).toBeVisible();
|
||||
}
|
||||
|
||||
async verifyGCPServiceAccountPageLoaded(): Promise<void> {
|
||||
// Verify the GCP service account page is loaded
|
||||
|
||||
await expect(this.page).toHaveTitle(/Prowler/);
|
||||
await expect(this.gcpServiceAccountKeyInput).toBeVisible();
|
||||
}
|
||||
|
||||
|
||||
async verifyLaunchScanPageLoaded(): Promise<void> {
|
||||
// Verify the launch scan page is loaded
|
||||
|
||||
@@ -323,3 +323,60 @@
|
||||
- Requires valid Kubernetes cluster with accessible kubeconfig
|
||||
- Kubeconfig must have sufficient permissions for security scanning
|
||||
- Test validates that kubeconfig content goes to the correct field (not the context field)
|
||||
|
||||
---
|
||||
|
||||
## Test Case: `PROVIDER-E2E-007` - Add GCP Provider with Service Account Key
|
||||
|
||||
**Priority:** `critical`
|
||||
|
||||
**Tags:**
|
||||
|
||||
- type → @e2e, @serial
|
||||
- feature → @providers
|
||||
- provider → @gcp
|
||||
|
||||
**Description/Objective:** Validates the complete flow of adding a new GCP provider using service account key authentication
|
||||
|
||||
**Preconditions:**
|
||||
|
||||
- Admin user authentication required (admin.auth.setup setup)
|
||||
- Environment variables configured: E2E_GCP_PROJECT_ID, E2E_GCP_BASE64_SERVICE_ACCOUNT_KEY
|
||||
- Remove any existing provider with the same Project ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Project ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
3. Select GCP provider type
|
||||
4. Fill provider details (project ID and alias)
|
||||
5. Select service account credentials type
|
||||
6. Fill GCP service account key credentials
|
||||
7. Launch initial scan
|
||||
8. Verify redirect to provider management page
|
||||
|
||||
### Expected Result:
|
||||
|
||||
- GCP provider successfully added with service account key
|
||||
- Initial scan launched successfully
|
||||
- User redirected to provider details page
|
||||
|
||||
### Key verification points:
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays GCP option
|
||||
- Provider details form accepts project ID and alias
|
||||
- Service account credentials page loads with service account key field
|
||||
- Service account key 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 GCP project ID and service account key
|
||||
- Service account key is provided as base64 encoded JSON content
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
- 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
|
||||
|
||||
@@ -14,6 +14,9 @@ import {
|
||||
KubernetesProviderData,
|
||||
KubernetesProviderCredential,
|
||||
KUBERNETES_CREDENTIAL_OPTIONS,
|
||||
GCPProviderData,
|
||||
GCPProviderCredential,
|
||||
GCP_CREDENTIAL_OPTIONS,
|
||||
} from "./providers-page";
|
||||
import { ScansPage } from "../scans/scans-page";
|
||||
import fs from "fs";
|
||||
@@ -541,4 +544,108 @@ test.describe("Add Provider", () => {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test.describe.serial("Add GCP Provider", () => {
|
||||
// Providers page object
|
||||
let providersPage: ProvidersPage;
|
||||
let scansPage: ScansPage;
|
||||
|
||||
// Test data from environment variables
|
||||
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",
|
||||
);
|
||||
}
|
||||
|
||||
// Setup before each test
|
||||
test.beforeEach(async ({ page }) => {
|
||||
providersPage = new ProvidersPage(page);
|
||||
// Clean up existing provider to ensure clean test state
|
||||
await providersPage.deleteProviderIfExists(projectId);
|
||||
});
|
||||
|
||||
// Use admin authentication for provider management
|
||||
test.use({ storageState: "playwright/.auth/admin_user.json" });
|
||||
|
||||
test(
|
||||
"should add a new GCP provider with service account key",
|
||||
{
|
||||
tag: [
|
||||
"@critical",
|
||||
"@e2e",
|
||||
"@providers",
|
||||
"@gcp",
|
||||
"@serial",
|
||||
"@PROVIDER-E2E-007",
|
||||
],
|
||||
},
|
||||
async ({ page }) => {
|
||||
// Validate required environment variables
|
||||
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");
|
||||
}
|
||||
|
||||
// Decode service account key from base64
|
||||
const serviceAccountKey = Buffer.from(serviceAccountKeyB64, 'base64').toString('utf8');
|
||||
|
||||
// Verify service account key is valid JSON
|
||||
if (!JSON.parse(serviceAccountKey)) {
|
||||
throw new Error("Invalid service account key format");
|
||||
}
|
||||
|
||||
// Prepare test data for GCP provider
|
||||
const gcpProviderData: GCPProviderData = {
|
||||
projectId: projectId,
|
||||
alias: "Test E2E GCP Account - Service Account Key",
|
||||
};
|
||||
|
||||
// Prepare static credentials
|
||||
const gcpCredentials: GCPProviderCredential = {
|
||||
type: GCP_CREDENTIAL_OPTIONS.GCP_SERVICE_ACCOUNT,
|
||||
serviceAccountKey: serviceAccountKey
|
||||
};
|
||||
|
||||
// Navigate to providers page
|
||||
await providersPage.goto();
|
||||
await providersPage.verifyPageLoaded();
|
||||
|
||||
// Start adding new provider
|
||||
await providersPage.clickAddProvider();
|
||||
await providersPage.verifyConnectAccountPageLoaded();
|
||||
|
||||
// Select M365 provider
|
||||
await providersPage.selectGCPProvider();
|
||||
|
||||
// Fill provider details
|
||||
await providersPage.fillGCPProviderDetails(gcpProviderData);
|
||||
await providersPage.clickNext();
|
||||
|
||||
// Select static credentials type
|
||||
await providersPage.selectGCPCredentialsType(
|
||||
GCP_CREDENTIAL_OPTIONS.GCP_SERVICE_ACCOUNT,
|
||||
);
|
||||
|
||||
// Verify GCP service account page is loaded
|
||||
await providersPage.verifyGCPServiceAccountPageLoaded();
|
||||
|
||||
// Fill static service account key details
|
||||
await providersPage.fillGCPServiceAccountKeyCredentials(gcpCredentials);
|
||||
await providersPage.clickNext();
|
||||
|
||||
// Launch scan
|
||||
await providersPage.verifyLaunchScanPageLoaded();
|
||||
await providersPage.clickNext();
|
||||
|
||||
// Wait for redirect to scan page
|
||||
scansPage = new ScansPage(page);
|
||||
await scansPage.verifyPageLoaded();
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user