Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
f7709cc
Add e2e tests for resource optimization plugin
hardengl Feb 5, 2026
9012e95
Extend Resource Optimization E2E tests for live cluster testing
hardengl Feb 6, 2026
fdd9a79
fix: ignore HTTPS certificate errors for live cluster testing
hardengl Feb 6, 2026
4133a1c
fix: update auth fixture and playwright config for live cluster testing
hardengl Feb 6, 2026
ff1a84e
fix: rewrite auth to use flight-path guest login pattern
hardengl Feb 6, 2026
6110480
feat(e2e): update ROS tests with source health check and Apply Recomm…
hardengl Feb 12, 2026
756a06f
fix(e2e): fix 3 test failures from local run
hardengl Feb 12, 2026
391c17c
fix(e2e): resolve strict mode violation on CSV/JSON export button loc…
hardengl Feb 26, 2026
3be706d
fix(e2e): make route paths configurable for dynamic plugin deployments
hardengl Mar 27, 2026
242a12c
fix(e2e): rewrite apply-recommendation test for secure proxy architec…
hardengl Mar 27, 2026
c9938c7
fix(e2e): improve test resilience for parallel execution and secure p…
hardengl Mar 27, 2026
c43902b
fix(e2e): use cost-authorized user for OpenShift cost management tests
hardengl Mar 27, 2026
ca05681
fix(ros-e2e): sidebar nav compatible with RHDH 1.8 and nested Cost ma…
hardengl Apr 6, 2026
d768bf8
Add backward compatibility for ROS 1.2.x E2E tests
hardengl Apr 7, 2026
151efba
Fix globalSetup TLS for self-signed certs in API probe
hardengl Apr 7, 2026
c5990d9
Switch globalSetup to browser-based sidebar detection
hardengl Apr 7, 2026
745dc1c
Use channel: 'chrome' in globalSetup to match container image
hardengl Apr 7, 2026
762b8f8
Skip container detail link test on legacy ROS 1.2.x
hardengl Apr 8, 2026
fa6ae4f
feat(e2e): add Extensions Marketplace plugin install tests
hardengl Apr 8, 2026
79c8213
fix(e2e): handle already-installed plugin in marketplace install test
hardengl Apr 8, 2026
f8b22ec
feat(e2e): add post-install sidebar verification to marketplace tests
hardengl Apr 9, 2026
699a114
fix(e2e): use guest login session for sidebar verification tests
hardengl Apr 9, 2026
e862ae2
fix: use Playwright bundled Chromium instead of system Chrome
May 9, 2026
e4ca9b7
feat(e2e): add FLPATH-4207 dynamic permission registration tests
hardengl May 20, 2026
ccb25bb
fix(e2e): fix FLPATH-4207 tests for live cluster auth patterns
hardengl May 20, 2026
d033579
feat(e2e): add granular cluster & project RBAC tests (3-tier model)
hardengl May 20, 2026
9b4e2d5
docs: add test coverage document for ROS/cost-management plugin
hardengl May 21, 2026
bc2560b
fix(e2e): make granular RBAC tests resilient to cluster name mismatches
hardengl May 21, 2026
5796c49
fix(e2e): skip granular data-filtering tests when RBAC_CLUSTER_ALIAS …
hardengl May 22, 2026
8fc5a34
fix(e2e): prevent apply-recommendation timeout on first iteration
hardengl Jun 10, 2026
6cd8908
fix(e2e): use 'cost management' search term for marketplace tests
hardengl Jun 12, 2026
7b0ec7f
fix(marketplace): complete the install flow with proper pluginConfig
hardengl Jun 12, 2026
88e4a30
fix(marketplace): robust install via React fiber + API fallback
hardengl Jun 12, 2026
e16f4a0
fix(marketplace): skip sidebar tests when pod restart pending
hardengl Jun 12, 2026
b61023e
fix(marketplace): detect restart banner as install success signal
hardengl Jun 15, 2026
1f8f011
fix(marketplace-test): check Installed tab before API fallback
hardengl Jun 16, 2026
4177b14
fix: increase timeout for multi-cluster permissions test
Jun 24, 2026
18063e9
fix: increase RBAC assertion timeouts for RHDH 1.10 compatibility (FL…
hardengl Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
182 changes: 182 additions & 0 deletions workspaces/cost-management/test-rbac-integration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#!/usr/bin/env bash
# Integration test for Cost Management plugin RBAC endpoints.
# Authenticates as real Keycloak users and hits the live backend API
# to verify RBAC enforcement on ocp-edge73.
#
# Usage: bash test-rbac-integration.sh
# Runs on: ocp-edge73 hypervisor (via SSH) or anywhere with route access
set -euo pipefail

###############################################################################
# Config
###############################################################################
RHDH_URL="https://backstage-backstage-rhdh-operator.apps.ocp-edge73-0.qe.lab.redhat.com"
KC_URL="https://keycloak-rhsso-operator.apps.ocp-edge73-0.qe.lab.redhat.com"
KC_REALM="basic"
KC_CLIENT_ID="rhdh"
KC_CLIENT_SECRET="rhdh"
USER_PASSWORD="test"

OPTIMIZATIONS_PATH="api/cost-management/proxy/recommendations/openshift"
OPENSHIFT_PATH="api/cost-management/proxy/reports/openshift/costs/"
APPLY_PATH="api/cost-management/apply-recommendation"

PASS=0
FAIL=0
TOTAL=0

###############################################################################
# Helpers
###############################################################################
red() { printf '\033[0;31m%s\033[0m' "$*"; }
green() { printf '\033[0;32m%s\033[0m' "$*"; }
bold() { printf '\033[1m%s\033[0m' "$*"; }

get_backstage_token() {
local user=$1
local kc_response kc_refresh bs_response bs_token

kc_response=$(curl -sk -X POST \
"${KC_URL}/auth/realms/${KC_REALM}/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=password&client_id=${KC_CLIENT_ID}&client_secret=${KC_CLIENT_SECRET}&username=${user}&password=${USER_PASSWORD}&scope=openid" 2>/dev/null)

kc_refresh=$(echo "$kc_response" | jq -r '.refresh_token // empty' 2>/dev/null)
if [[ -z "$kc_refresh" ]]; then
echo ""
return
fi

bs_response=$(curl -sk \
"${RHDH_URL}/api/auth/oidc/refresh?optional&scope=openid%20profile%20email&env=development" \
-H "x-requested-with: XMLHttpRequest" \
--cookie "oidc-refresh-token=${kc_refresh}" 2>/dev/null)

bs_token=$(echo "$bs_response" | jq -r '.backstageIdentity.token // empty' 2>/dev/null)
echo "$bs_token"
}

call_endpoint() {
local token=$1 method=$2 path=$3
shift 3
local extra_args=("$@")

curl -sk -o /dev/null -w "%{http_code}" \
-X "$method" \
"${RHDH_URL}/${path}" \
-H "Authorization: Bearer ${token}" \
-H "Content-Type: application/json" \
"${extra_args[@]}" 2>/dev/null
}

assert_status() {
local test_name=$1 expected=$2 actual=$3
TOTAL=$((TOTAL + 1))
if [[ "$actual" == "$expected" ]]; then
PASS=$((PASS + 1))
echo " $(green PASS) ${test_name} (HTTP ${actual})"
else
FAIL=$((FAIL + 1))
echo " $(red FAIL) ${test_name} (expected ${expected}, got ${actual})"
fi
}

# For apply-recommendation, authorized users may get non-200 from Orchestrator
# (workflow not deployed). We care about the RBAC gate: 403 = denied, !403 = passed RBAC.
assert_not_403() {
local test_name=$1 actual=$2
TOTAL=$((TOTAL + 1))
if [[ "$actual" != "403" ]]; then
PASS=$((PASS + 1))
echo " $(green PASS) ${test_name} (HTTP ${actual} — RBAC allowed, forwarded to Orchestrator)"
else
FAIL=$((FAIL + 1))
echo " $(red FAIL) ${test_name} (HTTP 403 — RBAC blocked, should have been allowed)"
fi
}

###############################################################################
# Test definitions: user → expected statuses
###############################################################################
# Format: "user optimizations openshift apply"
# apply = expected HTTP code for POST /apply-recommendation
# Use "-" to skip a test
declare -A USERS
USERS=(
[costmgmt-no-access]="403 403 403"
[costmgmt-workflow-only]="403 403 -"
[ro-read-all]="200 200 403"
[costmgmt-full-access]="200 200 200"
[ro-read-cluster]="403 403 -"
)

# Ordered list for consistent output
USER_ORDER=(
"costmgmt-no-access"
"costmgmt-workflow-only"
"ro-read-all"
"costmgmt-full-access"
"ro-read-cluster"
)

APPLY_BODY='{"workflowId":"cost-management-apply-recommendation","inputData":{"clusterName":"test-cluster","resourceType":"deployment","resourceNamespace":"test-ns","resourceName":"test-workload","containerName":"test-container","containerResources":{"requests":{"cpu":100,"memory":256},"limits":{"cpu":200,"memory":512}}}}'

###############################################################################
# Run
###############################################################################
echo ""
echo "$(bold '=== Cost Management RBAC Integration Tests ===')"
echo "RHDH: ${RHDH_URL}"
echo "Keycloak: ${KC_URL}/auth/realms/${KC_REALM}"
echo ""

for user in "${USER_ORDER[@]}"; do
read -r exp_opt exp_ocp exp_apply <<< "${USERS[$user]}"

echo "$(bold "--- ${user} ---")"

token=$(get_backstage_token "$user")
if [[ -z "$token" ]]; then
echo " $(red FAIL) Could not authenticate user '${user}' via Keycloak"
FAIL=$((FAIL + 1))
TOTAL=$((TOTAL + 1))
echo ""
continue
fi
echo " Authenticated OK (token ${#token} chars)"

# Optimizations API (ROS)
status=$(call_endpoint "$token" GET "$OPTIMIZATIONS_PATH")
assert_status "GET /proxy/recommendations/openshift" "$exp_opt" "$status"

# OpenShift costs API (Cost Management)
status=$(call_endpoint "$token" GET "$OPENSHIFT_PATH")
assert_status "GET /proxy/reports/openshift/costs/" "$exp_ocp" "$status"

# Apply Recommendation
if [[ "$exp_apply" != "-" ]]; then
status=$(call_endpoint "$token" POST "$APPLY_PATH" -d "$APPLY_BODY")
if [[ "$exp_apply" == "403" ]]; then
assert_status "POST /apply-recommendation (expect DENY)" "$exp_apply" "$status"
else
assert_not_403 "POST /apply-recommendation (expect ALLOW)" "$status"
fi
fi

echo ""
done

###############################################################################
# Summary
###############################################################################
echo "$(bold '=== Summary ===')"
echo "Total: ${TOTAL} $(green "Pass: ${PASS}") $(red "Fail: ${FAIL}")"
echo ""

if [[ $FAIL -gt 0 ]]; then
echo "$(red 'SOME TESTS FAILED')"
exit 1
else
echo "$(green 'ALL TESTS PASSED')"
exit 0
fi
Binary file added workspaces/dcm/.yarn/install-state.gz
Binary file not shown.
24 changes: 23 additions & 1 deletion workspaces/redhat-resource-optimization/app-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,26 @@ integrations:
# target: 'https://example.com'
# changeOrigin: true

proxy:
endpoints:
'/cost-management/v1':
target: https://console.redhat.com/api/cost-management/v1
allowedHeaders: ['Authorization']
# See: https://backstage.io/docs/releases/v1.28.0/#breaking-proxy-backend-plugin-protected-by-default
credentials: dangerously-allow-unauthenticated

# Resource Optimization plugin configuration
# Replace `${RHHCC_SA_CLIENT_ID}` and `${RHHCC_SA_CLIENT_SECRET}` with the service account credentials.
resourceOptimization:
clientId: ${RHHCC_SA_CLIENT_ID}
clientSecret: ${RHHCC_SA_CLIENT_SECRET}
optimizationWorkflowId: 'patch-k8s-resource'

# Orchestrator plugin configuration
orchestrator:
dataIndexService:
url: http://localhost:8080

# Reference documentation http://backstage.io/docs/features/techdocs/configuration
# Note: After experimenting with basic setup, use CI/CD to generate docs
# and an external cloud storage when deploying TechDocs for production use-case.
Expand All @@ -78,7 +98,9 @@ auth:
# see https://backstage.io/docs/auth/ to learn about auth providers
providers:
# See https://backstage.io/docs/auth/guest/provider
guest: {}
guest:
# Enable guest authentication for testing
allowGuestAccess: true

scaffolder:
{}
Expand Down
10 changes: 9 additions & 1 deletion workspaces/redhat-resource-optimization/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,14 @@
"prettier:check": "prettier --check .",
"prettier:fix": "prettier --write .",
"new": "backstage-cli new --scope @red-hat-developer-hub",
"postinstall": "cd ../../ && yarn install"
"postinstall": "cd ../../ && yarn install",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"test:e2e:headed": "playwright test --headed",
"test:e2e:debug": "playwright test --debug",
"test:e2e:chromium": "playwright test --project=chromium",
"test:e2e:firefox": "playwright test --project=firefox",
"test:e2e:webkit": "playwright test --project=webkit"
},
"workspaces": {
"packages": [
Expand All @@ -47,6 +54,7 @@
"@microsoft/api-extractor-model": "^7.29.2",
"@microsoft/tsdoc": "^0.16.0",
"@microsoft/tsdoc-config": "^0.18.0",
"@playwright/test": "1.55.1",
"@useoptic/optic": "^0.55.0",
"concurrently": "^9.0.0",
"knip": "^5.27.4",
Expand Down
Loading
Loading