Stateless gateway API for ROSA HCP regional cluster management.
make build # Build the API binary
make test # Run unit tests
make lint # Run linters
make generate # Regenerate codeflowchart LR
CLI["AWS CLI"] --> APIGW["API Gateway"]
APIGW --> AuthMW
subgraph PlatformAPI["Platform API"]
AuthMW["Auth Middleware"] --> Handler["Handlers"]
Handler --> HCP["HCP Management"]
Handler --> AuthzMgmt["Authz Management\n(Policies, Groups,\nAttachments, Admins)"]
end
AuthMW -->|"account & group\nlookup"| DDB[("DynamoDB")]
AuthMW -->|policy evaluation| AVP["Amazon Verified\nPermissions (Cedar)"]
AuthzMgmt --> DDB
AuthzMgmt --> AVP
View the full API spec (Swagger UI)
| Flag | Default | Description |
|---|---|---|
--api-port |
8000 |
API server port |
--maestro-url |
http://maestro:8000 |
Maestro API URL |
--hyperfleet-url |
http://hyperfleet-api.hyperfleet-system:8000 |
Hyperfleet API base URL |
--dynamodb-table |
rosa-customer-accounts |
DynamoDB table |
--dynamodb-region |
us-east-1 |
AWS region |
make build
make test
make imageRun all unit tests (excludes e2e tests):
make testRun tests for a specific package:
make test-unit PKG=./pkg/authz/...Run authorization package tests only:
make test-authzGenerate coverage report:
make test-coverage
# Opens coverage.html in your browserE2E tests use Ginkgo and generate JUnit XML reports in ./test-results/junit.xml.
Set the following environment variables:
BASE_URL- API Gateway URL (e.g.,https://xxxxx.execute-api.us-east-2.amazonaws.com/prod)E2E_ACCOUNT_ID- AWS account ID for testing (optional, defaults to current AWS credentials)
The tests run natively on your platform (Linux, macOS, Windows).
Prerequisites: Install Ginkgo CLI
go install github.com/onsi/ginkgo/v2/ginkgo@latestRun tests:
export BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod"
export E2E_ACCOUNT_ID="123456789012" # Optional
make test-e2eResults are written to ./test-results/junit.xml.
This is useful for CI/CD pipelines or isolated test environments.
Note: Containers run Linux. You can build the container on macOS/Windows, but it runs Linux inside.
- Build the e2e container:
# Single platform build (default: linux/amd64)
# Works on macOS (including M1/M2), Linux, Windows
make image-e2e
# Multi-architecture build (linux/amd64, linux/arm64)
# Requires Docker Buildx
make image-e2e-multiarch
# Build and push multi-architecture image to registry
make image-e2e-push-multiarchYou can customize the target platforms:
make image-e2e-multiarch PLATFORMS=linux/amd64,linux/arm64,linux/ppc64leBuilding on macOS (including Apple Silicon):
# On macOS M1/M2, build for linux/arm64 (faster)
make image-e2e GOOS=linux GOARCH=arm64
# Or build for linux/amd64 (cross-compile)
make image-e2e GOOS=linux GOARCH=amd64- Run tests in the container:
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
E2E_ACCOUNT_ID="123456789012"With a specific AWS profile (shares your ~/.aws credentials):
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
AWS_PROFILE="my-aws-profile" \
AWS_REGION="us-east-2"Run specific tests with --focus:
# Run only AWS Credentials Check test
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
FOCUS="AWS Credentials"
# Run tests matching a pattern
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
FOCUS="management cluster"Skip specific tests:
# Skip authorization tests (default behavior)
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
SKIP="Authz"
# Run all tests (override default skip)
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
SKIP=""The container automatically:
- Mounts your
~/.awsdirectory (read-only) - includes bothcredentialsandconfigfiles - Passes the
AWS_PROFILEenvironment variable - Configures AWS SDK to load the profile
Using credentials from a custom location:
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
AWS_CREDENTIALS_PATH="$(PWD)/../my-credentials-dir"Note: The AWS SDK requires both credentials and config files for full profile support. If you only have a credentials file, make sure to:
- Set
AWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEYdirectly, OR - Ensure your credentials file contains all necessary settings
Or use Docker/Podman directly:
Standard approach (mounts entire ~/.aws directory):
docker run --rm \
-e E2E_BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
-e E2E_ACCOUNT_ID="123456789012" \
-e AWS_PROFILE="my-aws-profile" \
-e AWS_REGION="us-east-2" \
-e AWS_SDK_LOAD_CONFIG=1 \
-v $(pwd)/test-results:/app/test-results \
-v ~/.aws:/root/.aws:ro \
quay.io/openshift-online/rosa-regional-platform-api-e2e:latestWith a custom credentials directory:
docker run --rm \
-e E2E_BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
-e AWS_PROFILE="my-profile" \
-e AWS_REGION="us-east-2" \
-e AWS_SDK_LOAD_CONFIG=1 \
-v $(pwd)/test-results:/app/test-results \
-v /path/to/custom/aws-dir:/root/.aws:ro \
quay.io/openshift-online/rosa-regional-platform-api-e2e:latestThe JUnit XML results will be available in ./test-results/junit.xml after the tests complete.
Local development on macOS/Linux (fastest):
export BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod"
export AWS_PROFILE="my-profile"
make test-e2eTesting with a specific AWS profile in a container:
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
AWS_PROFILE="staging-profile"Debug AWS credentials in container:
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
AWS_PROFILE="rrp-chris-regional_cluster" \
FOCUS="AWS Credentials"Run specific test in container:
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
FOCUS="management cluster"CI/CD pipeline (uses IAM role or instance profile):
# AWS credentials provided by CI environment
make test-e2e-container BASE_URL="${API_URL}"Using Podman instead of Docker:
# Replace 'docker' with 'podman' in any command
podman run --rm \
-e E2E_BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
-e AWS_PROFILE="my-profile" \
-e AWS_SDK_LOAD_CONFIG=1 \
-v $(pwd)/test-results:/app/test-results \
-v ~/.aws:/root/.aws:ro \
quay.io/openshift-online/rosa-regional-platform-api-e2e:latestIf e2e tests fail with authentication errors, the AWS Credentials Check test helps diagnose the issue:
# Quick check - run just the credentials verification test (native)
make test-e2e-awscreds
# Or in a container with focus on AWS credentials check
make test-e2e-container \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
FOCUS="AWS Credentials"The test will show:
- ✓ Successfully validated credentials with your AWS account, ARN, and UserId
- ✗ Error message if credentials are missing or invalid
Example output:
✓ AWS Credentials verified successfully
Account: 123456789012
ARN: arn:aws:sts::123456789012:assumed-role/MyRole/session
UserId: AROAEXAMPLEID:session
Profile: rrp-chris-regional_cluster
Region: us-east-2Common issues:
- "no such file or directory": AWS credentials file not mounted correctly
- "Unable to locate credentials":
AWS_PROFILEdoesn't exist or credentials file is malformed - "ExpiredToken": Your AWS session token has expired (common with SSO)
- "AccessDenied": Credentials work but lack permissions for STS GetCallerIdentity
- "credential_process: exit status 127" or "uv: not found": Your AWS config uses
credential_processwith a tool not in the container
Workaround for credential_process issues:
If you get credential_process errors, use the static credentials target which automatically exports credentials from your profile:
# Automatically exports credentials from your profile and passes them to container
make test-e2e-container-static-creds \
BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
AWS_PROFILE="rrp-chris-regional_cluster"This target:
- Exports credentials from your profile using
aws configure export-credentials - Passes them as environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN)
- Avoids mounting credential files and running credential_process in the container
Or manually export credentials:
# Export your credentials directly (avoids credential_process)
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_SESSION_TOKEN="your-session-token" # If using temporary credentials
# Run tests with environment credentials
make test-e2e-container BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod"Or, get temporary credentials from your credential process locally and pass them:
# Get credentials from your local credential process
aws configure export-credentials --profile rrp-chris-regional_cluster --format env
# Then use the output to set env vars and run without mounting credentials
docker run --rm \
-e E2E_BASE_URL="https://xxxxx.execute-api.us-east-2.amazonaws.com/prod" \
-e AWS_ACCESS_KEY_ID="..." \
-e AWS_SECRET_ACCESS_KEY="..." \
-e AWS_SESSION_TOKEN="..." \
-e AWS_REGION="us-east-2" \
-v $(pwd)/test-results:/app/test-results \
quay.io/openshift-online/rosa-regional-platform-api-e2e:latestDebug credentials inside the container:
# Drop into an interactive shell to troubleshoot
make debug-e2e-container-creds AWS_PROFILE="rrp-chris-regional_cluster"
# Inside the container, try:
# ls -la /root/.aws/
# cat /root/.aws/config
# env | grep AWS
# aws sts get-caller-identity --profile rrp-chris-regional_clusterAuthorization tests require local DynamoDB and cedar-agent infrastructure.
Start the infrastructure:
make e2e-authz-infra-upRun authz e2e tests:
make test-e2e-authzStop the infrastructure:
make e2e-authz-infra-downOr run everything with automatic cleanup:
make test-e2e-authz-cleanTests compatibility by spinning up an ephemeral rosa-regional-platform environment with the platform-api image from the PR, then running the rosa-regional-platform test suite against it using the commit hash of the PR.
Trigger: /test rosa-regionality-compatibility-e2e (does not run automatically).
Configuration: Defined in openshift/release under ci-operator/config/openshift-online/rosa-regional-platform-api/.
test/
├── e2e/
│ ├── e2e_test.go # Main e2e test suite
│ ├── awscreds_check_test.go # AWS credentials verification tests
│ ├── authz_e2e_test.go # Authorization e2e tests
│ ├── api_client.go # Reusable API client with SigV4 auth
│ └── testdata_loader.go # Test data utilities
The e2e suite includes several test categories:
-
AWS Credentials Check (
awscreds_check_test.go)- Verifies AWS credentials are properly configured
- Uses STS GetCallerIdentity to validate credentials
- Reports AWS account, ARN, and profile information
- Useful for debugging credential mounting in containers
-
Platform API Tests (
e2e_test.go)- Tests API endpoints (
/live,/ready, etc.) - Management cluster operations
- ManifestWork creation and distribution
- Tests API endpoints (
-
Authorization Tests (
authz_e2e_test.go)- Tests Cedar-based authorization
- Requires local DynamoDB and cedar-agent
E2E tests use the shared APIClient for making authenticated requests to the API:
It("should successfully call an endpoint", func() {
response, err := apiClient.Get("/api/v0/ready", accountID)
Expect(err).To(BeNil())
Expect(response.StatusCode).To(Equal(http.StatusOK))
})For POST requests:
It("should create a resource", func() {
payload := map[string]interface{}{
"name": "test-resource",
"labels": map[string]string{
"key": "value",
},
}
response, err := apiClient.Post("/api/v0/resource", payload, accountID)
Expect(err).To(BeNil())
Expect(response.StatusCode).To(Equal(http.StatusCreated))
})awscurl -X POST https://z11111111.execute-api.us-east-2.amazonaws.com/prod/api/v0/management_clusters \
--service execute-api \
--region us-east-2 \
-H "Content-Type: application/json" \
-d '{"name": "management-01", "labels": {"cluster_type": "management", "cluster_id": "management-01"}}'awscurl https://z11111111.execute-api.us-east-2.amazonaws.com/prod/api/v0/resource_bundles \
--service execute-api \
--region us-east-2# see swagger for reference for the payload struct
awscurl -X POST https://z11111111.execute-api.us-east-2.amazonaws.com/prod/api/v0/work \
--service execute-api \
--region us-east-2 \
-d @payload.json