diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 0000000..8a16806 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,110 @@ +name: E2E + +on: + push: + branches: + - main + paths-ignore: + - 'dist/**' + schedule: + - cron: '0 5 * * 0' + +jobs: + e2e: + if: github.event_name == 'push' && github_actor == 'roxbot' + name: E2E + runs-on: ubuntu-latest + permissions: + id-token: write # Required for the central-login action which we will test. + contents: read + env: + USE_GKE_GCLOUD_AUTH_PLUGIN: "True" + steps: + - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + with: + repository: stackrox/stackrox + path: stackrox + fetch-depth: 0 # Required since we need to calculate the latest image tag with the existing tags. + + - name: Setup kubectl + uses: azure/setup-kubectl@v3 + + - name: Setup infractl + uses: stackrox/actions/infra/install-infractl@main + + - name: Setup GCloud auth + uses: "google-github-actions/auth@v1" + with: + credentials_json: "${{ secrets.GCP_SERVICE_ACCOUNT_STACKROX_CI }}" + + - name: Setup GCloud auth plugin + uses: "google-github-actions/setup-gcloud@v1" + with: + install_components: "gke-gcloud-auth-plugin" + + - name: Create GKE infra cluster + uses: stackrox/actions/infra/create-cluster@v1.0.9 + with: + token: ${{ secrets.INFRA_TOKEN }} + flavor: gke-default + name: central-login-${{ github.run_id }} + lifespan: 20m + wait: "true" + no-slack: "true" + + - name: Deploy Central to infra cluster + env: + CLUSTER_NAME: central-login-${{ github.run_id }} + INFRA_TOKEN: ${{ secrets.INFRA_TOKEN }} + ARTIFACTS_DIR: ${{ runner.temp }}/gke-artifacts + run: | + # Fetch the artifacts for the GKE cluster. + infractl artifacts --download-dir=${ARTIFACTS_DIR} ${CLUSTER_NAME} + + # Setup context for GKE cluster. + echo "KUBECONFIG=${ARTIFACTS_DIR}/kubeconfig" >> $GITHUB_ENV + export KUBECONFIG=${ARTIFACTS_DIR}/kubeconfig + + # Kill port-forwards from earlier runs. + pkill -f kubectl'.*port-forward.*' || true + pkill -9 -f kubectl'.*port-forward.*' || true + + # Deploy Central via deploy scripts. + cd stackrox + MONITORING_SUPPORT=false ./deploy/central.sh + kubectl set env -n stackrox deploy/central ROX_AUTH_MACHINE_TO_MACHINE=true + + # Kill port-forwards from the initial deploy. + pkill -f kubectl'.*port-forward.*' || true + pkill -9 -f kubectl'.*port-forward.*' || true + + ./deploy/k8s/central-deploy/central/scripts/port-forward.sh 8000 + + echo "ROX_PASSWORD=$(cat deploy/k8s/central-deploy/password)" >> $GITHUB_ENV + + - name: Wait for Central to be ready + run: | + cd stackrox + export USE_MIDSTREAM_IMAGES=false # Required for wait_for_api to be set. + source "tests/e2e/lib.sh" + wait_for_api + + - name: Add machine to machine configuration in Central + run: | + curl -u admin:${ROX_PASSWORD} \ + https://localhost:8000/v1/auth/m2m \ + -k -d '{"config": {"type": "GITHUB_ACTIONS", "tokenExpirationDuration": "5m", "mappings":[{"key":"sub","valueExpression":"repo:stackrox/central-login.*", "role":"Analyst"}]}}' + + - name: Run central-login action + uses: ./ + with: + endpoint: https://localhost:8000 + skip-tls-verify: true + + - name: Fetch roxctl and run roxctl central whoami + run: | + curl -k -u admin:${ROX_PASSWORD} https://localhost:8000/api/cli/download/roxctl-linux --output ./roxctl + chmod +x ./roxctl + echo $ROX_ENDPOINT + ./roxctl central whoami diff --git a/src/main.ts b/src/main.ts index 02ac25b..eaa19e8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -22,7 +22,8 @@ async function run(): Promise { // Additionally, also set the Central API endpoint as environment variable for other jobs to use. // This does not need to be marked as a secret. - core.exportVariable('ROX_ENDPOINT', parsedURL.toString()) + // The HTTPS scheme has to be stripped, as this is not expected to be set by roxctl for the endpoint. + core.exportVariable('ROX_ENDPOINT', getHostWithPort(parsedURL)) core.info( 'Successfully set the variable ROX_API_TOKEN and ROX_ENDPOINT to the access token and ' + @@ -68,4 +69,14 @@ async function obtainAccessToken( return response.data['accessToken'] } +function getHostWithPort(url: URL): string { + let host = url.host + // If the port is not given, assume HTTPs and port 443 (the port will be omitted if HTTPS is used as scheme _and_ + // the port is the default 443 port). + if (url.port === '') { + host = `${host}:443` + } + return host +} + run()